]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'fix/hda' into for-linus
authorTakashi Iwai <tiwai@suse.de>
Sat, 3 Oct 2009 16:31:33 +0000 (18:31 +0200)
committerTakashi Iwai <tiwai@suse.de>
Sat, 3 Oct 2009 16:31:33 +0000 (18:31 +0200)
2809 files changed:
.gitignore
CREDITS
Documentation/ABI/testing/sysfs-block
Documentation/DocBook/kernel-hacking.tmpl
Documentation/DocBook/mac80211.tmpl
Documentation/RCU/rculist_nulls.txt
Documentation/arm/memory.txt
Documentation/block/data-integrity.txt
Documentation/cgroups/cpusets.txt
Documentation/connector/cn_test.c
Documentation/connector/ucon.c
Documentation/driver-model/driver.txt
Documentation/dvb/get_dvb_firmware
Documentation/feature-removal-schedule.txt
Documentation/filesystems/9p.txt
Documentation/filesystems/afs.txt
Documentation/filesystems/proc.txt
Documentation/filesystems/sysfs.txt
Documentation/gcov.txt
Documentation/ioctl/ioctl-number.txt
Documentation/kernel-parameters.txt
Documentation/kmemleak.txt
Documentation/laptops/thinkpad-acpi.txt
Documentation/leds-lp3944.txt [new file with mode: 0644]
Documentation/lguest/lguest.c
Documentation/lockdep-design.txt
Documentation/networking/6pack.txt
Documentation/powerpc/booting-without-of.txt
Documentation/powerpc/dts-bindings/4xx/emac.txt [new file with mode: 0644]
Documentation/powerpc/dts-bindings/gpio/gpio.txt [new file with mode: 0644]
Documentation/powerpc/dts-bindings/gpio/led.txt
Documentation/powerpc/dts-bindings/gpio/mdio.txt [new file with mode: 0644]
Documentation/powerpc/dts-bindings/marvell.txt [new file with mode: 0644]
Documentation/powerpc/dts-bindings/phy.txt [new file with mode: 0644]
Documentation/powerpc/dts-bindings/spi-bus.txt [new file with mode: 0644]
Documentation/powerpc/dts-bindings/usb-ehci.txt [new file with mode: 0644]
Documentation/powerpc/dts-bindings/xilinx.txt [new file with mode: 0644]
Documentation/scheduler/sched-rt-group.txt
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/sound/alsa/Procfile.txt
Documentation/spi/spidev_test.c
Documentation/sysrq.txt
Documentation/video4linux/CARDLIST.em28xx
Documentation/video4linux/CARDLIST.saa7134
Documentation/video4linux/gspca.txt
Documentation/x86/00-INDEX
Documentation/x86/exception-tables.txt [moved from Documentation/exception.txt with 75% similarity]
MAINTAINERS
Makefile
REPORTING-BUGS
arch/alpha/include/asm/percpu.h
arch/alpha/include/asm/thread_info.h
arch/alpha/include/asm/tlb.h
arch/alpha/kernel/ptrace.c
arch/arm/Kconfig.debug
arch/arm/boot/compressed/misc.c
arch/arm/common/clkdev.c
arch/arm/configs/kb9202_defconfig
arch/arm/configs/kirkwood_defconfig
arch/arm/configs/mx27_defconfig
arch/arm/configs/mx3_defconfig
arch/arm/configs/omap3_evm_defconfig
arch/arm/configs/rx51_defconfig
arch/arm/configs/s3c2410_defconfig
arch/arm/configs/s3c6400_defconfig
arch/arm/configs/tct_hammer_defconfig
arch/arm/configs/u300_defconfig
arch/arm/include/asm/atomic.h
arch/arm/include/asm/page.h
arch/arm/include/asm/pgtable.h
arch/arm/include/asm/setup.h
arch/arm/include/asm/thread_info.h
arch/arm/include/asm/tlb.h
arch/arm/kernel/entry-common.S
arch/arm/kernel/irq.c
arch/arm/kernel/signal.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/mach-at91/board-sam9g20ek.c
arch/arm/mach-at91/board-sam9rlek.c
arch/arm/mach-at91/include/mach/at_hdmac.h [new file with mode: 0644]
arch/arm/mach-davinci/board-dm355-evm.c
arch/arm/mach-davinci/board-dm355-leopard.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/board-sffsdr.c
arch/arm/mach-ep93xx/dma-m2p.c
arch/arm/mach-ep93xx/include/mach/ts72xx.h
arch/arm/mach-ep93xx/ts72xx.c
arch/arm/mach-ixp4xx/include/mach/io.h
arch/arm/mach-kirkwood/mpp.h
arch/arm/mach-kirkwood/ts219-setup.c
arch/arm/mach-ks8695/include/mach/hardware.h
arch/arm/mach-ks8695/include/mach/timex.h
arch/arm/mach-ks8695/pci.c
arch/arm/mach-mx3/Kconfig
arch/arm/mach-mx3/Makefile
arch/arm/mach-mx3/armadillo5x0.c
arch/arm/mach-mx3/devices.c
arch/arm/mach-mx3/mx31moboard-devboard.c
arch/arm/mach-mx3/mx31moboard-marxbot.c
arch/arm/mach-mx3/mx31moboard.c
arch/arm/mach-mx3/pcm037.c
arch/arm/mach-mx3/pcm037.h [new file with mode: 0644]
arch/arm/mach-mx3/pcm037_eet.c [new file with mode: 0644]
arch/arm/mach-omap1/board-nokia770.c
arch/arm/mach-omap1/mailbox.c
arch/arm/mach-omap1/mcbsp.c
arch/arm/mach-omap2/board-2430sdp.c
arch/arm/mach-omap2/board-3430sdp.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/board-ldp.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-omap3pandora.c
arch/arm/mach-omap2/board-overo.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/board-rx51.c
arch/arm/mach-omap2/board-zoom2.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock24xx.c
arch/arm/mach-omap2/clock24xx.h
arch/arm/mach-omap2/clock34xx.c
arch/arm/mach-omap2/clock34xx.h
arch/arm/mach-omap2/cm.h
arch/arm/mach-omap2/gpmc-onenand.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/mailbox.c
arch/arm/mach-omap2/mcbsp.c
arch/arm/mach-omap2/mmc-twl4030.c
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/prcm.c
arch/arm/mach-omap2/sdrc.c
arch/arm/mach-omap2/serial.c
arch/arm/mach-omap2/sram34xx.S
arch/arm/mach-omap2/usb-musb.c
arch/arm/mach-pxa/em-x270.c
arch/arm/mach-pxa/include/mach/audio.h
arch/arm/mach-pxa/include/mach/mfp-pxa300.h
arch/arm/mach-pxa/palmld.c
arch/arm/mach-pxa/palmt5.c
arch/arm/mach-pxa/palmtx.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-pxa/treo680.c
arch/arm/mach-pxa/zylonite_pxa300.c
arch/arm/mach-pxa/zylonite_pxa320.c
arch/arm/mach-realview/core.c
arch/arm/mach-s3c2410/include/mach/gpio-core.h
arch/arm/mach-s3c2440/mach-mini2440.c
arch/arm/mach-s3c2442/mach-gta02.c
arch/arm/mach-u300/clock.c
arch/arm/mach-u300/core.c
arch/arm/mach-versatile/core.c
arch/arm/mm/init.c
arch/arm/mm/mmu.c
arch/arm/mm/proc-syms.c
arch/arm/plat-mxc/include/mach/iomux-mx3.h
arch/arm/plat-omap/cpu-omap.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/include/mach/clock.h
arch/arm/plat-omap/include/mach/cpu.h
arch/arm/plat-omap/include/mach/dma.h
arch/arm/plat-omap/include/mach/io.h
arch/arm/plat-omap/include/mach/mcbsp.h
arch/arm/plat-omap/include/mach/mux.h
arch/arm/plat-omap/include/mach/prcm.h
arch/arm/plat-omap/include/mach/sdrc.h
arch/arm/plat-omap/include/mach/serial.h
arch/arm/plat-omap/include/mach/sram.h
arch/arm/plat-omap/iommu.c
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/sram.c
arch/arm/plat-orion/include/plat/gpio.h
arch/arm/plat-pxa/gpio.c
arch/arm/plat-s3c/Makefile
arch/arm/plat-s3c/include/plat/audio-simtec.h [new file with mode: 0644]
arch/arm/plat-s3c/include/plat/devs.h
arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h
arch/arm/plat-s3c24xx/Makefile
arch/arm/plat-s3c24xx/clock-dclk.c
arch/arm/plat-s3c24xx/pwm.c
arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c
arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c
arch/arm/plat-s3c64xx/pm.c
arch/arm/plat-s3c64xx/s3c6400-clock.c
arch/arm/plat-stmp3xxx/pinmux.c
arch/avr32/boards/favr-32/setup.c
arch/avr32/include/asm/pgalloc.h
arch/avr32/include/asm/thread_info.h
arch/avr32/kernel/traps.c
arch/avr32/lib/memcpy.S
arch/blackfin/include/asm/context.S
arch/blackfin/include/asm/cpu.h
arch/blackfin/include/asm/hardirq.h
arch/blackfin/include/asm/processor.h
arch/blackfin/include/asm/thread_info.h
arch/blackfin/kernel/bfin_dma_5xx.c
arch/blackfin/kernel/bfin_gpio.c
arch/blackfin/kernel/cplb-nompu/cplbinit.c
arch/blackfin/kernel/process.c
arch/blackfin/kernel/ptrace.c
arch/blackfin/kernel/setup.c
arch/blackfin/kernel/sys_bfin.c
arch/blackfin/kernel/traps.c
arch/blackfin/lib/lshrdi3.c
arch/blackfin/mach-bf518/boards/ezbrd.c
arch/blackfin/mach-bf518/include/mach/anomaly.h
arch/blackfin/mach-bf518/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf527/boards/cm_bf527.c
arch/blackfin/mach-bf527/boards/ezbrd.c
arch/blackfin/mach-bf527/boards/ezkit.c
arch/blackfin/mach-bf527/include/mach/anomaly.h
arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf533/boards/stamp.c
arch/blackfin/mach-bf533/include/mach/anomaly.h
arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf537/boards/stamp.c
arch/blackfin/mach-bf537/include/mach/anomaly.h
arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf538/include/mach/anomaly.h
arch/blackfin/mach-bf538/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf548/boards/ezkit.c
arch/blackfin/mach-bf548/include/mach/anomaly.h
arch/blackfin/mach-bf561/include/mach/anomaly.h
arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h
arch/blackfin/mach-bf561/include/mach/mem_map.h
arch/blackfin/mach-common/entry.S
arch/blackfin/mach-common/smp.c
arch/cris/include/asm/pgalloc.h
arch/cris/include/asm/thread_info.h
arch/cris/kernel/sys_cris.c
arch/frv/Kconfig
arch/frv/include/asm/atomic.h
arch/frv/include/asm/perf_counter.h [new file with mode: 0644]
arch/frv/include/asm/pgalloc.h
arch/frv/include/asm/pgtable.h
arch/frv/include/asm/system.h
arch/frv/include/asm/thread_info.h
arch/frv/include/asm/unistd.h
arch/frv/kernel/entry.S
arch/frv/kernel/frv_ksyms.c
arch/frv/lib/Makefile
arch/frv/lib/atomic-ops.S
arch/frv/lib/atomic64-ops.S [new file with mode: 0644]
arch/frv/lib/perf_counter.c [new file with mode: 0644]
arch/h8300/include/asm/thread_info.h
arch/ia64/Makefile
arch/ia64/include/asm/bitops.h
arch/ia64/include/asm/fpu.h
arch/ia64/include/asm/pgalloc.h
arch/ia64/include/asm/pgtable.h
arch/ia64/include/asm/thread_info.h
arch/ia64/include/asm/tlb.h
arch/ia64/include/asm/xen/hypervisor.h
arch/ia64/kernel/dma-mapping.c
arch/ia64/kernel/esi.c
arch/ia64/kernel/ia64_ksyms.c
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/pci-dma.c
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/ptrace.c
arch/ia64/kernel/salinfo.c
arch/ia64/kernel/topology.c
arch/ia64/kvm/kvm_lib.c
arch/ia64/kvm/mmio.c
arch/ia64/kvm/process.c
arch/ia64/kvm/vcpu.c
arch/ia64/kvm/vcpu.h
arch/ia64/kvm/vtlb.c
arch/ia64/lib/ip_fast_csum.S
arch/ia64/pci/pci.c
arch/ia64/sn/kernel/io_common.c
arch/m32r/include/asm/pgalloc.h
arch/m32r/include/asm/thread_info.h
arch/m32r/kernel/ptrace.c
arch/m68k/amiga/config.c
arch/m68k/include/asm/motorola_pgalloc.h
arch/m68k/include/asm/pgtable_mm.h
arch/m68k/include/asm/sun3_pgalloc.h
arch/m68k/include/asm/thread_info_mm.h
arch/m68k/include/asm/thread_info_no.h
arch/m68k/include/asm/unistd.h
arch/m68k/kernel/entry.S
arch/m68knommu/kernel/process.c
arch/m68knommu/kernel/syscalltable.S
arch/m68knommu/kernel/traps.c
arch/microblaze/Kconfig
arch/microblaze/Makefile
arch/microblaze/configs/mmu_defconfig
arch/microblaze/configs/nommu_defconfig
arch/microblaze/include/asm/atomic.h
arch/microblaze/include/asm/bitops.h
arch/microblaze/include/asm/bug.h
arch/microblaze/include/asm/bugs.h
arch/microblaze/include/asm/checksum.h
arch/microblaze/include/asm/fb.h [new file with mode: 0644]
arch/microblaze/include/asm/hardirq.h
arch/microblaze/include/asm/io.h
arch/microblaze/include/asm/ioctls.h
arch/microblaze/include/asm/ipcbuf.h
arch/microblaze/include/asm/irq.h
arch/microblaze/include/asm/mman.h
arch/microblaze/include/asm/mmu.h
arch/microblaze/include/asm/mmu_context.h
arch/microblaze/include/asm/mmu_context_no.h [deleted file]
arch/microblaze/include/asm/module.h
arch/microblaze/include/asm/msgbuf.h
arch/microblaze/include/asm/param.h
arch/microblaze/include/asm/parport.h [new file with mode: 0644]
arch/microblaze/include/asm/pci.h
arch/microblaze/include/asm/pgalloc.h
arch/microblaze/include/asm/pgtable.h
arch/microblaze/include/asm/posix_types.h
arch/microblaze/include/asm/prom.h
arch/microblaze/include/asm/scatterlist.h
arch/microblaze/include/asm/sembuf.h
arch/microblaze/include/asm/serial.h
arch/microblaze/include/asm/shmbuf.h
arch/microblaze/include/asm/shmparam.h
arch/microblaze/include/asm/siginfo.h
arch/microblaze/include/asm/signal.h
arch/microblaze/include/asm/socket.h
arch/microblaze/include/asm/sockios.h
arch/microblaze/include/asm/stat.h
arch/microblaze/include/asm/swab.h
arch/microblaze/include/asm/syscalls.h
arch/microblaze/include/asm/system.h
arch/microblaze/include/asm/termbits.h
arch/microblaze/include/asm/termios.h
arch/microblaze/include/asm/thread_info.h
arch/microblaze/include/asm/timex.h
arch/microblaze/include/asm/tlb.h
arch/microblaze/include/asm/types.h
arch/microblaze/include/asm/uaccess.h
arch/microblaze/include/asm/ucontext.h
arch/microblaze/include/asm/unistd.h
arch/microblaze/include/asm/vga.h
arch/microblaze/kernel/Makefile
arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
arch/microblaze/kernel/cpu/cpuinfo-static.c
arch/microblaze/kernel/cpu/cpuinfo.c
arch/microblaze/kernel/entry-nommu.S
arch/microblaze/kernel/entry.S
arch/microblaze/kernel/head.S
arch/microblaze/kernel/hw_exception_handler.S
arch/microblaze/kernel/intc.c
arch/microblaze/kernel/irq.c
arch/microblaze/kernel/module.c
arch/microblaze/kernel/ptrace.c
arch/microblaze/kernel/setup.c
arch/microblaze/kernel/signal.c
arch/microblaze/kernel/sys_microblaze.c
arch/microblaze/kernel/syscall_table.S
arch/microblaze/kernel/timer.c
arch/microblaze/lib/Makefile
arch/microblaze/lib/checksum.c [deleted file]
arch/microblaze/mm/fault.c
arch/microblaze/mm/init.c
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/alchemy/mtx-1/platform.c
arch/mips/ar7/Makefile [new file with mode: 0644]
arch/mips/ar7/clock.c [new file with mode: 0644]
arch/mips/ar7/gpio.c [new file with mode: 0644]
arch/mips/ar7/irq.c [new file with mode: 0644]
arch/mips/ar7/memory.c [new file with mode: 0644]
arch/mips/ar7/platform.c [new file with mode: 0644]
arch/mips/ar7/prom.c [new file with mode: 0644]
arch/mips/ar7/setup.c [new file with mode: 0644]
arch/mips/ar7/time.c [new file with mode: 0644]
arch/mips/cavium-octeon/Makefile
arch/mips/cavium-octeon/dma-octeon.c
arch/mips/cavium-octeon/pci-common.c [deleted file]
arch/mips/cavium-octeon/smp.c
arch/mips/cobalt/buttons.c
arch/mips/cobalt/lcd.c
arch/mips/cobalt/led.c
arch/mips/cobalt/mtd.c
arch/mips/cobalt/rtc.c
arch/mips/cobalt/serial.c
arch/mips/cobalt/time.c
arch/mips/configs/ar7_defconfig [new file with mode: 0644]
arch/mips/dec/ecc-berr.c
arch/mips/dec/int-handler.S
arch/mips/dec/ioasic-irq.c
arch/mips/dec/kn01-berr.c
arch/mips/dec/kn02-irq.c
arch/mips/dec/kn02xa-berr.c
arch/mips/dec/prom/call_o32.S
arch/mips/dec/prom/console.c
arch/mips/dec/time.c
arch/mips/emma/common/Makefile
arch/mips/emma/common/prom.c
arch/mips/emma/markeins/Makefile
arch/mips/emma/markeins/irq.c
arch/mips/emma/markeins/led.c
arch/mips/emma/markeins/platform.c
arch/mips/emma/markeins/setup.c
arch/mips/fw/lib/call_o32.S
arch/mips/gt64120/wrppmc/serial.c
arch/mips/include/asm/amon.h [new file with mode: 0644]
arch/mips/include/asm/ds1287.h
arch/mips/include/asm/elf.h
arch/mips/include/asm/emma/emma2rh.h
arch/mips/include/asm/emma/markeins.h
arch/mips/include/asm/gcmpregs.h
arch/mips/include/asm/gic.h
arch/mips/include/asm/irq_gt641xx.h
arch/mips/include/asm/mach-ar7/ar7.h [new file with mode: 0644]
arch/mips/include/asm/mach-ar7/gpio.h [new file with mode: 0644]
arch/mips/include/asm/mach-ar7/irq.h [new file with mode: 0644]
arch/mips/include/asm/mach-ar7/prom.h [new file with mode: 0644]
arch/mips/include/asm/mach-ar7/spaces.h [new file with mode: 0644]
arch/mips/include/asm/mach-ar7/war.h [new file with mode: 0644]
arch/mips/include/asm/mach-cobalt/irq.h
arch/mips/include/asm/mach-cobalt/mach-gt64120.h
arch/mips/include/asm/octeon/pci-octeon.h [moved from arch/mips/cavium-octeon/pci-common.h with 52% similarity]
arch/mips/include/asm/page.h
arch/mips/include/asm/pgalloc.h
arch/mips/include/asm/pmc-sierra/msp71xx/war.h
arch/mips/include/asm/processor.h
arch/mips/include/asm/reg.h
arch/mips/include/asm/swab.h
arch/mips/include/asm/thread_info.h
arch/mips/include/asm/unistd.h
arch/mips/include/asm/vr41xx/capcella.h
arch/mips/include/asm/vr41xx/giu.h
arch/mips/include/asm/vr41xx/irq.h
arch/mips/include/asm/vr41xx/mpc30x.h
arch/mips/include/asm/vr41xx/pci.h
arch/mips/include/asm/vr41xx/siu.h
arch/mips/include/asm/vr41xx/tb0219.h
arch/mips/include/asm/vr41xx/tb0226.h
arch/mips/include/asm/vr41xx/vr41xx.h
arch/mips/jazz/jazzdma.c
arch/mips/kernel/binfmt_elfo32.c
arch/mips/kernel/cevt-ds1287.c
arch/mips/kernel/cevt-gt641xx.c
arch/mips/kernel/csrc-ioasic.c
arch/mips/kernel/head.S
arch/mips/kernel/irq-gic.c
arch/mips/kernel/irq-gt641xx.c
arch/mips/kernel/irq_txx9.c
arch/mips/kernel/module.c
arch/mips/kernel/proc.c
arch/mips/kernel/process.c
arch/mips/kernel/ptrace32.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/smp-cmp.c
arch/mips/kernel/smtc.c
arch/mips/kernel/stacktrace.c
arch/mips/kernel/sync-r4k.c
arch/mips/kernel/vpe.c
arch/mips/mipssim/sim_time.c
arch/mips/mm/c-octeon.c
arch/mips/mm/extable.c
arch/mips/mm/fault.c
arch/mips/mm/hugetlbpage.c
arch/mips/mti-malta/malta-init.c
arch/mips/mti-malta/malta-int.c
arch/mips/mti-malta/malta-reset.c
arch/mips/nxp/pnx8550/common/time.c
arch/mips/pci/Makefile
arch/mips/pci/fixup-capcella.c
arch/mips/pci/fixup-emma2rh.c
arch/mips/pci/fixup-mpc30x.c
arch/mips/pci/fixup-sb1250.c
arch/mips/pci/fixup-tb0219.c
arch/mips/pci/fixup-tb0226.c
arch/mips/pci/fixup-tb0287.c
arch/mips/pci/msi-octeon.c [moved from arch/mips/cavium-octeon/msi.c with 88% similarity]
arch/mips/pci/ops-emma2rh.c
arch/mips/pci/ops-vr41xx.c
arch/mips/pci/pci-emma2rh.c
arch/mips/pci/pci-octeon.c [moved from arch/mips/cavium-octeon/pci.c with 78% similarity]
arch/mips/pci/pci-tx4927.c
arch/mips/pci/pci-tx4938.c
arch/mips/pci/pci-tx4939.c
arch/mips/pci/pci-vr41xx.c
arch/mips/pci/pci-vr41xx.h
arch/mips/pci/pcie-octeon.c [moved from arch/mips/cavium-octeon/pcie.c with 97% similarity]
arch/mips/pmc-sierra/msp71xx/gpio.c
arch/mips/pmc-sierra/msp71xx/gpio_extended.c
arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c
arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
arch/mips/sibyte/swarm/swarm-i2c.c
arch/mips/txx9/generic/mem_tx4927.c
arch/mips/txx9/generic/setup.c
arch/mips/txx9/rbtx4939/setup.c
arch/mips/vr41xx/casio-e55/setup.c
arch/mips/vr41xx/common/bcu.c
arch/mips/vr41xx/common/cmu.c
arch/mips/vr41xx/common/giu.c
arch/mips/vr41xx/common/icu.c
arch/mips/vr41xx/common/init.c
arch/mips/vr41xx/common/irq.c
arch/mips/vr41xx/common/pmu.c
arch/mips/vr41xx/common/rtc.c
arch/mips/vr41xx/common/siu.c
arch/mips/vr41xx/common/type.c
arch/mips/vr41xx/ibm-workpad/setup.c
arch/mn10300/include/asm/pci.h
arch/mn10300/include/asm/pgalloc.h
arch/mn10300/include/asm/thread_info.h
arch/mn10300/include/asm/unistd.h
arch/mn10300/kernel/entry.S
arch/mn10300/kernel/ptrace.c
arch/mn10300/kernel/signal.c
arch/mn10300/kernel/sys_mn10300.c
arch/mn10300/kernel/traps.c
arch/mn10300/kernel/vmlinux.lds.S
arch/mn10300/mm/fault.c
arch/mn10300/mm/misalignment.c
arch/parisc/Kconfig
arch/parisc/include/asm/atomic.h
arch/parisc/include/asm/dma.h
arch/parisc/include/asm/perf_counter.h [new file with mode: 0644]
arch/parisc/include/asm/processor.h
arch/parisc/include/asm/system.h
arch/parisc/include/asm/thread_info.h
arch/parisc/include/asm/tlb.h
arch/parisc/include/asm/tlbflush.h
arch/parisc/include/asm/unistd.h
arch/parisc/kernel/cache.c
arch/parisc/kernel/entry.S
arch/parisc/kernel/inventory.c
arch/parisc/kernel/irq.c
arch/parisc/kernel/module.c
arch/parisc/kernel/pci-dma.c
arch/parisc/kernel/pci.c
arch/parisc/kernel/process.c
arch/parisc/kernel/processor.c
arch/parisc/kernel/setup.c
arch/parisc/kernel/sys_parisc32.c
arch/parisc/kernel/syscall_table.S
arch/parisc/kernel/time.c
arch/parisc/kernel/traps.c
arch/parisc/lib/checksum.c
arch/parisc/lib/memcpy.c
arch/parisc/math-emu/decode_exc.c
arch/parisc/mm/fault.c
arch/parisc/mm/init.c
arch/powerpc/Kconfig
arch/powerpc/boot/.gitignore
arch/powerpc/boot/dts/amigaone.dts
arch/powerpc/boot/dts/mpc8377_rdb.dts
arch/powerpc/boot/dts/mpc8378_rdb.dts
arch/powerpc/boot/dts/mpc8379_rdb.dts
arch/powerpc/boot/dts/mpc8569mds.dts
arch/powerpc/boot/dts/warp.dts
arch/powerpc/configs/44x/warp_defconfig
arch/powerpc/configs/83xx/asp8347_defconfig
arch/powerpc/configs/83xx/kmeter1_defconfig
arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
arch/powerpc/configs/83xx/mpc832x_mds_defconfig
arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
arch/powerpc/configs/83xx/mpc834x_itx_defconfig
arch/powerpc/configs/83xx/mpc834x_itxgp_defconfig
arch/powerpc/configs/83xx/mpc834x_mds_defconfig
arch/powerpc/configs/83xx/mpc836x_mds_defconfig
arch/powerpc/configs/83xx/mpc836x_rdk_defconfig
arch/powerpc/configs/83xx/mpc837x_mds_defconfig
arch/powerpc/configs/83xx/mpc837x_rdb_defconfig
arch/powerpc/configs/83xx/sbc834x_defconfig
arch/powerpc/configs/85xx/ksi8560_defconfig
arch/powerpc/configs/85xx/mpc8540_ads_defconfig
arch/powerpc/configs/85xx/mpc8560_ads_defconfig
arch/powerpc/configs/85xx/mpc85xx_cds_defconfig
arch/powerpc/configs/85xx/sbc8548_defconfig
arch/powerpc/configs/85xx/sbc8560_defconfig
arch/powerpc/configs/85xx/socrates_defconfig
arch/powerpc/configs/85xx/stx_gp3_defconfig
arch/powerpc/configs/85xx/tqm8540_defconfig
arch/powerpc/configs/85xx/tqm8541_defconfig
arch/powerpc/configs/85xx/tqm8548_defconfig
arch/powerpc/configs/85xx/tqm8555_defconfig
arch/powerpc/configs/85xx/tqm8560_defconfig
arch/powerpc/configs/85xx/xes_mpc85xx_defconfig
arch/powerpc/configs/86xx/gef_ppc9a_defconfig
arch/powerpc/configs/86xx/gef_sbc310_defconfig
arch/powerpc/configs/86xx/gef_sbc610_defconfig
arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig
arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
arch/powerpc/configs/86xx/sbc8641d_defconfig
arch/powerpc/configs/adder875_defconfig
arch/powerpc/configs/c2k_defconfig
arch/powerpc/configs/ep8248e_defconfig
arch/powerpc/configs/ep88xc_defconfig
arch/powerpc/configs/linkstation_defconfig
arch/powerpc/configs/mgcoge_defconfig
arch/powerpc/configs/mgsuvd_defconfig
arch/powerpc/configs/mpc7448_hpc2_defconfig
arch/powerpc/configs/mpc8272_ads_defconfig
arch/powerpc/configs/mpc83xx_defconfig
arch/powerpc/configs/mpc85xx_defconfig
arch/powerpc/configs/mpc85xx_smp_defconfig
arch/powerpc/configs/mpc866_ads_defconfig
arch/powerpc/configs/mpc86xx_defconfig
arch/powerpc/configs/mpc885_ads_defconfig
arch/powerpc/configs/pq2fads_defconfig
arch/powerpc/configs/prpmc2800_defconfig
arch/powerpc/configs/ps3_defconfig
arch/powerpc/configs/storcenter_defconfig
arch/powerpc/include/asm/cpm1.h
arch/powerpc/include/asm/delay.h
arch/powerpc/include/asm/dma-mapping.h
arch/powerpc/include/asm/highmem.h
arch/powerpc/include/asm/hw_irq.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/perf_counter.h
arch/powerpc/include/asm/pgalloc-32.h
arch/powerpc/include/asm/pgalloc-64.h
arch/powerpc/include/asm/pgalloc.h
arch/powerpc/include/asm/pte-hash64-64k.h
arch/powerpc/include/asm/rtas.h
arch/powerpc/include/asm/thread_info.h
arch/powerpc/kernel/dma.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/head_32.S
arch/powerpc/kernel/mpc7450-pmu.c
arch/powerpc/kernel/of_device.c
arch/powerpc/kernel/perf_counter.c
arch/powerpc/kernel/power4-pmu.c
arch/powerpc/kernel/power5+-pmu.c
arch/powerpc/kernel/power5-pmu.c
arch/powerpc/kernel/power6-pmu.c
arch/powerpc/kernel/power7-pmu.c
arch/powerpc/kernel/ppc970-pmu.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/ptrace32.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/udbg_16550.c
arch/powerpc/kernel/vector.S
arch/powerpc/mm/Makefile
arch/powerpc/mm/gup.c
arch/powerpc/mm/highmem.c [new file with mode: 0644]
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/mmu_context_nohash.c
arch/powerpc/mm/pgtable.c
arch/powerpc/mm/slb.c
arch/powerpc/mm/tlb_hash64.c
arch/powerpc/oprofile/cell/vma_map.c
arch/powerpc/platforms/44x/warp.c
arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/85xx/smp.c
arch/powerpc/platforms/85xx/socrates.c
arch/powerpc/platforms/85xx/xes_mpc85xx.c
arch/powerpc/platforms/cell/axon_msi.c
arch/powerpc/platforms/cell/smp.c
arch/powerpc/platforms/chrp/smp.c
arch/powerpc/platforms/pasemi/setup.c
arch/powerpc/platforms/powermac/cpufreq_64.c
arch/powerpc/platforms/powermac/pic.c
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/powermac/smp.c
arch/powerpc/platforms/ps3/system-bus.c
arch/powerpc/platforms/ps3/time.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/smp.c
arch/powerpc/platforms/pseries/xics.c
arch/powerpc/sysdev/fsl_rio.c
arch/powerpc/sysdev/ipic.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/ppc4xx_pci.c
arch/powerpc/sysdev/qe_lib/qe.c
arch/powerpc/sysdev/qe_lib/qe_ic.c
arch/powerpc/sysdev/uic.c
arch/powerpc/sysdev/xilinx_intc.c
arch/s390/Kconfig
arch/s390/include/asm/atomic.h
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/perf_counter.h
arch/s390/include/asm/thread_info.h
arch/s390/include/asm/tlb.h
arch/s390/kernel/dis.c
arch/s390/kernel/early.c
arch/s390/kernel/ipl.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/vdso64/clock_gettime.S
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/priv.c
arch/s390/kvm/sigp.c
arch/s390/lib/Makefile
arch/s390/lib/delay.c
arch/s390/lib/ucmpdi2.c [new file with mode: 0644]
arch/s390/mm/fault.c
arch/s390/power/swsusp.c
arch/s390/power/swsusp_asm64.S
arch/sh/Kconfig.debug
arch/sh/boards/board-ap325rxa.c
arch/sh/boards/mach-migor/setup.c
arch/sh/boards/mach-se/7206/io.c
arch/sh/boards/mach-se/7724/setup.c
arch/sh/configs/migor_defconfig
arch/sh/configs/se7724_defconfig
arch/sh/include/asm/perf_counter.h
arch/sh/include/asm/pgalloc.h
arch/sh/include/asm/syscall_32.h
arch/sh/include/asm/thread_info.h
arch/sh/include/asm/tlb.h
arch/sh/include/mach-se/mach/se7724.h
arch/sh/kernel/cpu/sh2/setup-sh7619.c
arch/sh/kernel/cpu/sh2a/setup-mxg.c
arch/sh/kernel/cpu/sh2a/setup-sh7201.c
arch/sh/kernel/cpu/sh2a/setup-sh7203.c
arch/sh/kernel/cpu/sh2a/setup-sh7206.c
arch/sh/kernel/cpu/sh3/setup-sh7705.c
arch/sh/kernel/cpu/sh3/setup-sh770x.c
arch/sh/kernel/cpu/sh3/setup-sh7710.c
arch/sh/kernel/cpu/sh3/setup-sh7720.c
arch/sh/kernel/cpu/sh4/setup-sh4-202.c
arch/sh/kernel/cpu/sh4/setup-sh7750.c
arch/sh/kernel/cpu/sh4/setup-sh7760.c
arch/sh/kernel/cpu/sh4a/setup-sh7343.c
arch/sh/kernel/cpu/sh4a/setup-sh7366.c
arch/sh/kernel/cpu/sh4a/setup-sh7722.c
arch/sh/kernel/cpu/sh4a/setup-sh7723.c
arch/sh/kernel/cpu/sh4a/setup-sh7724.c
arch/sh/kernel/cpu/sh4a/setup-sh7763.c
arch/sh/kernel/cpu/sh4a/setup-sh7770.c
arch/sh/kernel/cpu/sh4a/setup-sh7780.c
arch/sh/kernel/cpu/sh4a/setup-sh7785.c
arch/sh/kernel/cpu/sh4a/setup-sh7786.c
arch/sh/kernel/cpu/sh4a/setup-shx3.c
arch/sh/kernel/cpu/sh5/setup-sh5.c
arch/sh/kernel/cpu/shmobile/sleep.S
arch/sh/mm/fault_32.c
arch/sh/mm/tlb-sh3.c
arch/sh/mm/tlbflush_64.c
arch/sparc/boot/Makefile
arch/sparc/boot/piggyback_32.c
arch/sparc/boot/piggyback_64.c
arch/sparc/configs/sparc32_defconfig
arch/sparc/configs/sparc64_defconfig
arch/sparc/include/asm/pgalloc_32.h
arch/sparc/include/asm/pgtable_64.h
arch/sparc/include/asm/thread_info_32.h
arch/sparc/include/asm/thread_info_64.h
arch/sparc/include/asm/tlb_64.h
arch/sparc/kernel/irq_64.c
arch/sparc/kernel/ktlb.S
arch/sparc/kernel/nmi.c
arch/sparc/kernel/ptrace_32.c
arch/sparc/kernel/ptrace_64.c
arch/sparc/kernel/smp_64.c
arch/sparc/kernel/sun4d_smp.c
arch/sparc/kernel/sun4m_smp.c
arch/sparc/kernel/sys32.S
arch/sparc/kernel/systbls_64.S
arch/sparc/kernel/time_64.c
arch/sparc/kernel/traps_32.c
arch/sparc/kernel/vio.c
arch/sparc/mm/fault_32.c
arch/sparc/mm/fault_64.c
arch/sparc/mm/init_64.c
arch/sparc/mm/init_64.h
arch/sparc/prom/misc_64.c
arch/sparc/prom/printf.c
arch/um/drivers/slip_kern.c
arch/um/drivers/slirp_kern.c
arch/um/include/asm/dma-mapping.h
arch/um/include/asm/pgalloc.h
arch/um/include/asm/thread_info.h
arch/um/include/asm/tlb.h
arch/um/kernel/sysrq.c
arch/x86/Kconfig
arch/x86/boot/compressed/Makefile
arch/x86/boot/video-bios.c
arch/x86/boot/video-vesa.c
arch/x86/include/asm/atomic_32.h
arch/x86/include/asm/atomic_64.h
arch/x86/include/asm/boot.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/fixmap.h
arch/x86/include/asm/io_apic.h
arch/x86/include/asm/irqflags.h
arch/x86/include/asm/lguest.h
arch/x86/include/asm/lguest_hcall.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/nmi.h
arch/x86/include/asm/pci.h
arch/x86/include/asm/percpu.h
arch/x86/include/asm/perf_counter.h
arch/x86/include/asm/pgalloc.h
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/proto.h
arch/x86/include/asm/spinlock.h
arch/x86/include/asm/stacktrace.h
arch/x86/include/asm/thread_info.h
arch/x86/include/asm/uaccess.h
arch/x86/include/asm/uaccess_64.h
arch/x86/include/asm/uv/uv_bau.h
arch/x86/include/asm/uv/uv_hub.h
arch/x86/kernel/Makefile
arch/x86/kernel/amd_iommu.c
arch/x86/kernel/amd_iommu_init.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/es7000_32.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/ipi.c
arch/x86/kernel/apic/numaq_32.c
arch/x86/kernel/apic/probe_64.c
arch/x86/kernel/apic/x2apic_cluster.c
arch/x86/kernel/apic/x2apic_phys.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/cpu/Makefile
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/cpufreq/powernow-k8.c
arch/x86/kernel/cpu/cpufreq/powernow-k8.h
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/therm_throt.c
arch/x86/kernel/cpu/perf_counter.c
arch/x86/kernel/cpu/perfctr-watchdog.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/dumpstack_32.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/e820.c
arch/x86/kernel/efi.c
arch/x86/kernel/efi_64.c
arch/x86/kernel/head_32.S
arch/x86/kernel/irqinit.c
arch/x86/kernel/kvm.c
arch/x86/kernel/mfgpt_32.c
arch/x86/kernel/pci-dma.c
arch/x86/kernel/pci-gart_64.c
arch/x86/kernel/process.c
arch/x86/kernel/pvclock.c
arch/x86/kernel/reboot.c
arch/x86/kernel/setup.c
arch/x86/kernel/setup_percpu.c
arch/x86/kernel/tlb_uv.c
arch/x86/kernel/traps.c
arch/x86/kernel/tsc.c
arch/x86/kernel/vmi_32.c
arch/x86/kernel/vmlinux.lds.S
arch/x86/kvm/i8254.c
arch/x86/kvm/mmu.c
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/kvm/x86_emulate.c
arch/x86/lguest/boot.c
arch/x86/lguest/i386_head.S
arch/x86/lib/Makefile
arch/x86/lib/atomic64_32.c [new file with mode: 0644]
arch/x86/lib/clear_page_64.S
arch/x86/lib/copy_user_64.S
arch/x86/lib/delay.c
arch/x86/lib/msr.c
arch/x86/lib/usercopy_32.c
arch/x86/mm/fault.c
arch/x86/mm/highmem_32.c
arch/x86/mm/init.c
arch/x86/mm/init_64.c
arch/x86/mm/pageattr.c
arch/x86/mm/pat.c
arch/x86/mm/pgtable.c
arch/x86/mm/srat_64.c
arch/x86/mm/tlb.c
arch/x86/oprofile/nmi_int.c
arch/x86/pci/acpi.c
arch/x86/pci/amd_bus.c
arch/x86/pci/i386.c
arch/x86/power/Makefile
arch/x86/power/cpu.c
arch/x86/xen/Makefile
arch/x86/xen/enlighten.c
arch/xtensa/include/asm/thread_info.h
arch/xtensa/include/asm/tlb.h
arch/xtensa/kernel/traps.c
block/Kconfig
block/Makefile
block/blk-core.c
block/blk-integrity.c
block/blk-merge.c
block/blk-settings.c
block/blk-sysfs.c
block/bsg.c
block/cfq-iosched.c
block/cmd-filter.c [deleted file]
block/elevator.c
block/scsi_ioctl.c
crypto/algapi.c
crypto/async_tx/async_xor.c
drivers/acpi/acpi_memhotplug.c
drivers/acpi/acpica/acobject.h
drivers/acpi/acpica/dsopcode.c
drivers/acpi/acpica/exfldio.c
drivers/acpi/acpica/exstorob.c
drivers/acpi/osl.c
drivers/acpi/pci_root.c
drivers/acpi/processor_core.c
drivers/acpi/processor_idle.c
drivers/acpi/processor_thermal.c
drivers/acpi/processor_throttling.c
drivers/acpi/sleep.c
drivers/acpi/system.c
drivers/acpi/video.c
drivers/amba/bus.c
drivers/ata/ahci.c
drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/pata_at91.c
drivers/ata/pata_atiixp.c
drivers/ata/pata_octeon_cf.c
drivers/ata/pata_pcmcia.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/ata/sata_sil.c
drivers/base/devres.c
drivers/base/firmware_class.c
drivers/base/platform.c
drivers/base/power/main.c
drivers/base/sys.c
drivers/block/DAC960.c
drivers/block/Kconfig
drivers/block/Makefile
drivers/block/amiflop.c
drivers/block/aoe/aoe.h
drivers/block/aoe/aoeblk.c
drivers/block/aoe/aoedev.c
drivers/block/ataflop.c
drivers/block/cciss.c
drivers/block/cciss_cmd.h
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/mg_disk.c
drivers/block/osdblk.c [new file with mode: 0644]
drivers/block/pktcdvd.c
drivers/block/virtio_blk.c
drivers/block/xsysace.c
drivers/block/z2ram.c
drivers/bluetooth/hci_vhci.c
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/agp/intel-agp.c
drivers/char/agp/parisc-agp.c
drivers/char/amiserial.c
drivers/char/bsr.c
drivers/char/cyclades.c
drivers/char/epca.c
drivers/char/hvc_console.c
drivers/char/hw_random/intel-rng.c
drivers/char/isicom.c
drivers/char/istallion.c
drivers/char/moxa.c
drivers/char/mxser.c
drivers/char/n_hdlc.c
drivers/char/n_r3964.c
drivers/char/n_tty.c
drivers/char/nozomi.c
drivers/char/pcmcia/ipwireless/tty.c
drivers/char/pty.c
drivers/char/rio/rio_linux.c
drivers/char/riscom8.c
drivers/char/rocket.c
drivers/char/serial167.c
drivers/char/specialix.c
drivers/char/sx.c
drivers/char/synclink.c
drivers/char/synclink_gt.c
drivers/char/synclinkmp.c
drivers/char/sysrq.c
drivers/char/tb0219.c
drivers/char/tpm/tpm.c
drivers/char/tty_buffer.c
drivers/char/tty_ioctl.c
drivers/char/tty_ldisc.c
drivers/char/tty_port.c
drivers/char/vc_screen.c
drivers/char/vt.c
drivers/char/vt_ioctl.c
drivers/clocksource/sh_cmt.c
drivers/clocksource/sh_tmu.c
drivers/connector/cn_queue.c
drivers/connector/connector.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_conservative.c
drivers/cpufreq/cpufreq_ondemand.c
drivers/dma/Kconfig
drivers/dma/Makefile
drivers/dma/at_hdmac.c [new file with mode: 0644]
drivers/dma/at_hdmac_regs.h [new file with mode: 0644]
drivers/dma/dmatest.c
drivers/dma/fsldma.c
drivers/dma/fsldma.h
drivers/dma/mv_xor.c
drivers/edac/amd64_edac.c
drivers/edac/amd64_edac.h
drivers/edac/edac_core.h
drivers/edac/edac_mc_sysfs.c
drivers/edac/mpc85xx_edac.c
drivers/edac/mpc85xx_edac.h
drivers/edac/x38_edac.c
drivers/firewire/core-card.c
drivers/firewire/core-cdev.c
drivers/firewire/core-iso.c
drivers/firewire/core.h
drivers/firewire/ohci.c
drivers/firewire/sbp2.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/pl061.c
drivers/gpio/vr41xx_giu.c [moved from drivers/char/vr41xx_giu.c with 66% similarity]
drivers/gpu/drm/Kconfig
drivers/gpu/drm/Makefile
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/drm_stub.c
drivers/gpu/drm/drm_sysfs.c
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/dvo.h
drivers/gpu/drm/i915/dvo_ch7017.c
drivers/gpu/drm/i915/dvo_ch7xxx.c
drivers/gpu/drm/i915/dvo_ivch.c
drivers/gpu/drm/i915/dvo_sil164.c
drivers/gpu/drm/i915/dvo_tfp410.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_debug.c
drivers/gpu/drm/i915/i915_gem_debugfs.c
drivers/gpu/drm/i915/i915_gem_tiling.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_bios.h
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c [new file with mode: 0644]
drivers/gpu/drm/i915/intel_dp.h [new file with mode: 0644]
drivers/gpu/drm/i915/intel_dp_i2c.c [new file with mode: 0644]
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_dvo.c
drivers/gpu/drm/i915/intel_fb.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_modes.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sdvo_regs.h
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/radeon/Makefile
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r300_reg.h
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/r500_reg.h
drivers/gpu/drm/radeon/r520.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_cp.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_benchmark.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_cp.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_cursor.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_drv.h
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_fb.c
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_gem.c
drivers/gpu/drm/radeon/radeon_irq_kms.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_reg.h
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/radeon_share.h [new file with mode: 0644]
drivers/gpu/drm/radeon/radeon_state.c
drivers/gpu/drm/radeon/radeon_test.c [new file with mode: 0644]
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/radeon/rs400.c
drivers/gpu/drm/radeon/rs600.c
drivers/gpu/drm/radeon/rs690.c
drivers/gpu/drm/radeon/rs690r.h [new file with mode: 0644]
drivers/gpu/drm/radeon/rv515.c
drivers/gpu/drm/radeon/rv515r.h [new file with mode: 0644]
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/gpu/drm/ttm/ttm_bo_vm.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/via/via_irq.c
drivers/hid/hid-core.c
drivers/hid/usbhid/hid-core.c
drivers/hid/usbhid/hiddev.c
drivers/hwmon/abituguru3.c
drivers/hwmon/asus_atk0110.c
drivers/hwmon/max6650.c
drivers/hwmon/sht15.c
drivers/hwmon/smsc47m1.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-ibm_iic.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/i2c/busses/i2c-simtec.c
drivers/i2c/busses/i2c-stu300.c
drivers/i2c/chips/tsl2550.c
drivers/ide/cs5520.c
drivers/ide/ide-acpi.c
drivers/ide/ide-cd.c
drivers/ide/ide-cs.c
drivers/ide/ide-devsets.c
drivers/ide/ide-disk.c
drivers/ide/ide-dma.c
drivers/ide/ide-eh.c
drivers/ide/ide-floppy.c
drivers/ide/ide-io.c
drivers/ide/ide-ioctls.c
drivers/ide/ide-iops.c
drivers/ide/ide-pm.c
drivers/ide/ide-probe.c
drivers/ide/ide-tape.c
drivers/ieee1394/sbp2.c
drivers/ieee1394/sbp2.h
drivers/input/evdev.c
drivers/input/joydev.c
drivers/input/joystick/iforce/iforce-main.c
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/matrix_keypad.c [new file with mode: 0644]
drivers/input/misc/cobalt_btns.c
drivers/input/misc/pcspkr.c
drivers/input/misc/wistron_btns.c
drivers/input/mouse/gpio_mouse.c
drivers/input/serio/hp_sdc_mlc.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042.c
drivers/input/serio/serio.c
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/ucb1400_ts.c
drivers/isdn/gigaset/ev-layer.c
drivers/isdn/gigaset/interface.c
drivers/isdn/gigaset/isocdata.c
drivers/isdn/hisax/hfc_usb.c
drivers/isdn/i4l/isdn_tty.c
drivers/isdn/mISDN/l1oip_core.c
drivers/isdn/mISDN/stack.c
drivers/leds/Kconfig
drivers/leds/Makefile
drivers/leds/leds-alix2.c
drivers/leds/leds-bd2802.c
drivers/leds/leds-cobalt-raq.c
drivers/leds/leds-gpio.c
drivers/leds/leds-lp3944.c [new file with mode: 0644]
drivers/leds/leds-pca9532.c
drivers/leds/ledtrig-gpio.c
drivers/lguest/core.c
drivers/lguest/hypercalls.c
drivers/lguest/interrupts_and_traps.c
drivers/lguest/lg.h
drivers/lguest/lguest_device.c
drivers/lguest/lguest_user.c
drivers/lguest/page_tables.c
drivers/lguest/segments.c
drivers/lguest/x86/core.c
drivers/lguest/x86/switcher_32.S
drivers/macintosh/macio_asic.c
drivers/macintosh/via-maciisi.c
drivers/md/dm-crypt.c
drivers/md/dm-delay.c
drivers/md/dm-exception-store.c
drivers/md/dm-exception-store.h
drivers/md/dm-linear.c
drivers/md/dm-log-userspace-base.c
drivers/md/dm-log-userspace-transfer.c
drivers/md/dm-log-userspace-transfer.h
drivers/md/dm-mpath.c
drivers/md/dm-raid1.c
drivers/md/dm-snap-persistent.c
drivers/md/dm-snap.c
drivers/md/dm-stripe.c
drivers/md/dm-table.c
drivers/md/dm.c
drivers/md/dm.h
drivers/md/linear.c
drivers/md/md.c
drivers/md/md.h
drivers/md/multipath.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/media/common/tuners/qt1010.c
drivers/media/common/tuners/tuner-xc2028.c
drivers/media/common/tuners/tuner-xc2028.h
drivers/media/dvb/b2c2/flexcop-fe-tuner.c
drivers/media/dvb/bt8xx/dst_ca.c
drivers/media/dvb/dvb-core/dvbdev.h
drivers/media/dvb/dvb-usb/af9015.c
drivers/media/dvb/frontends/af9013.c
drivers/media/dvb/frontends/cx22700.c
drivers/media/dvb/frontends/cx22702.c
drivers/media/dvb/frontends/cx24110.c
drivers/media/dvb/frontends/dvb_dummy_fe.c
drivers/media/dvb/frontends/l64781.c
drivers/media/dvb/frontends/lgs8gl5.c
drivers/media/dvb/frontends/mt312.c
drivers/media/dvb/frontends/nxt6000.c
drivers/media/dvb/frontends/or51132.c
drivers/media/dvb/frontends/or51211.c
drivers/media/dvb/frontends/s5h1409.c
drivers/media/dvb/frontends/s5h1411.c
drivers/media/dvb/frontends/si21xx.c
drivers/media/dvb/frontends/sp8870.c
drivers/media/dvb/frontends/sp887x.c
drivers/media/dvb/frontends/stv0288.c
drivers/media/dvb/frontends/stv0297.c
drivers/media/dvb/frontends/stv0299.c
drivers/media/dvb/frontends/tda10021.c
drivers/media/dvb/frontends/tda10048.c
drivers/media/dvb/frontends/tda1004x.c
drivers/media/dvb/frontends/tda10086.c
drivers/media/dvb/frontends/tda8083.c
drivers/media/dvb/frontends/ves1820.c
drivers/media/dvb/frontends/ves1x93.c
drivers/media/dvb/frontends/zl10353.c
drivers/media/dvb/siano/Kconfig
drivers/media/dvb/siano/Makefile
drivers/media/dvb/siano/sms-cards.c
drivers/media/dvb/siano/smscoreapi.c
drivers/media/dvb/siano/smsdvb.c
drivers/media/dvb/siano/smssdio.c
drivers/media/dvb/ttpci/Kconfig
drivers/media/dvb/ttpci/av7110.c
drivers/media/radio/radio-mr800.c
drivers/media/radio/radio-si470x.c
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/bt8xx/bttv-cards.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bt8xx/bttv.h
drivers/media/video/bw-qcam.c
drivers/media/video/cx18/cx18-cards.c
drivers/media/video/cx18/cx18-controls.c
drivers/media/video/cx18/cx18-dvb.c
drivers/media/video/cx23885/cx23885-417.c
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx23885/cx23885-video.c
drivers/media/video/cx23885/cx23885.h
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/cx88/cx88-mpeg.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/dabusb.c
drivers/media/video/em28xx/Kconfig
drivers/media/video/em28xx/em28xx-cards.c
drivers/media/video/em28xx/em28xx-core.c
drivers/media/video/em28xx/em28xx-dvb.c
drivers/media/video/em28xx/em28xx-i2c.c
drivers/media/video/em28xx/em28xx-reg.h
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/em28xx/em28xx.h
drivers/media/video/gspca/Kconfig
drivers/media/video/gspca/Makefile
drivers/media/video/gspca/conex.c
drivers/media/video/gspca/gspca.c
drivers/media/video/gspca/gspca.h
drivers/media/video/gspca/m5602/m5602_s5k4aa.c
drivers/media/video/gspca/mars.c
drivers/media/video/gspca/sn9c20x.c [new file with mode: 0644]
drivers/media/video/gspca/sonixj.c
drivers/media/video/gspca/spca500.c
drivers/media/video/gspca/stk014.c
drivers/media/video/gspca/stv06xx/stv06xx.h
drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
drivers/media/video/gspca/sunplus.c
drivers/media/video/gspca/zc3xx.c
drivers/media/video/hdpvr/hdpvr-video.c
drivers/media/video/ivtv/ivtv-controls.c
drivers/media/video/mt9v011.c [new file with mode: 0644]
drivers/media/video/mt9v011.h [new file with mode: 0644]
drivers/media/video/mx1_camera.c
drivers/media/video/mx3_camera.c
drivers/media/video/pwc/pwc-if.c
drivers/media/video/pwc/pwc.h
drivers/media/video/pxa_camera.c
drivers/media/video/s2255drv.c
drivers/media/video/saa5246a.c
drivers/media/video/saa5249.c
drivers/media/video/saa7134/saa7134-cards.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/saa7134/saa7134-empress.c
drivers/media/video/saa7134/saa7134.h
drivers/media/video/se401.c
drivers/media/video/sh_mobile_ceu_camera.c
drivers/media/video/soc_camera.c
drivers/media/video/stk-webcam.c
drivers/media/video/stradis.c
drivers/media/video/stv680.c
drivers/media/video/usbvideo/vicam.c
drivers/media/video/usbvision/usbvision-video.c
drivers/media/video/uvc/uvc_driver.c
drivers/media/video/uvc/uvc_status.c
drivers/media/video/v4l2-dev.c
drivers/media/video/v4l2-ioctl.c
drivers/media/video/vivi.c
drivers/media/video/zoran/zoran_driver.c
drivers/media/video/zr364xx.c
drivers/mfd/dm355evm_msp.c
drivers/mfd/ezx-pcap.c
drivers/mfd/sm501.c
drivers/mfd/twl4030-irq.c
drivers/misc/cb710/sgbuf2.c
drivers/misc/eeprom/at25.c
drivers/misc/sgi-gru/grufile.c
drivers/misc/sgi-gru/grukservices.c
drivers/misc/sgi-xp/xpnet.c
drivers/mmc/host/cb710-mmc.c
drivers/mmc/host/imxmmc.c
drivers/mmc/host/mmc_spi.c
drivers/mmc/host/mvsdio.c
drivers/mmc/host/pxamci.c
drivers/mmc/host/sdhci-of.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mtd/cmdlinepart.c
drivers/mtd/devices/m25p80.c
drivers/mtd/inftlcore.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/Makefile
drivers/mtd/maps/integrator-flash.c
drivers/mtd/maps/sbc8240.c [deleted file]
drivers/mtd/mtd_blkdevs.c
drivers/mtd/mtdblock.c
drivers/mtd/mtdcore.c
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/omap2.c
drivers/mtd/nand/orion_nand.c
drivers/mtd/nftlcore.c
drivers/mtd/onenand/omap2.c
drivers/mtd/ubi/build.c
drivers/mtd/ubi/debug.c
drivers/mtd/ubi/debug.h
drivers/mtd/ubi/eba.c
drivers/mtd/ubi/gluebi.c
drivers/mtd/ubi/io.c
drivers/mtd/ubi/scan.c
drivers/mtd/ubi/scan.h
drivers/mtd/ubi/ubi-media.h
drivers/mtd/ubi/ubi.h
drivers/mtd/ubi/wl.c
drivers/net/3c515.c
drivers/net/3c59x.c
drivers/net/8139cp.c
drivers/net/8139too.c
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/a2065.c
drivers/net/arcnet/arcnet.c
drivers/net/arm/Kconfig
drivers/net/arm/Makefile
drivers/net/arm/at91_ether.c
drivers/net/arm/ixp4xx_eth.c
drivers/net/arm/w90p910_ether.c [new file with mode: 0644]
drivers/net/at1700.c
drivers/net/atl1c/atl1c.h
drivers/net/atl1c/atl1c_ethtool.c
drivers/net/atl1c/atl1c_main.c
drivers/net/atl1e/atl1e_ethtool.c
drivers/net/atlx/atl1.c
drivers/net/atlx/atl2.c
drivers/net/b44.c
drivers/net/benet/be.h
drivers/net/benet/be_ethtool.c
drivers/net/benet/be_hw.h
drivers/net/benet/be_main.c
drivers/net/bmac.c
drivers/net/bnx2.c
drivers/net/bnx2.h
drivers/net/bnx2x.h
drivers/net/bnx2x_link.c
drivers/net/bnx2x_main.c
drivers/net/bonding/bond_main.c
drivers/net/can/dev.c
drivers/net/can/sja1000/sja1000.c
drivers/net/cnic.c
drivers/net/cnic.h
drivers/net/cnic_if.h
drivers/net/cpmac.c
drivers/net/cs89x0.c
drivers/net/cxgb3/cxgb3_main.c
drivers/net/davinci_emac.c
drivers/net/dl2k.c
drivers/net/e100.c
drivers/net/e1000/e1000_main.c
drivers/net/e1000e/defines.h
drivers/net/e1000e/hw.h
drivers/net/e1000e/ich8lan.c
drivers/net/e1000e/lib.c
drivers/net/e1000e/netdev.c
drivers/net/e1000e/phy.c
drivers/net/eepro.c
drivers/net/eexpress.c
drivers/net/ehea/ehea.h
drivers/net/ehea/ehea_main.c
drivers/net/epic100.c
drivers/net/fealnx.c
drivers/net/fec.c
drivers/net/fec.h
drivers/net/fec_mpc52xx.c
drivers/net/forcedeth.c
drivers/net/fs_enet/fs_enet-main.c
drivers/net/fsl_pq_mdio.c
drivers/net/gianfar.c
drivers/net/gianfar_ethtool.c
drivers/net/hamachi.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/baycom_epp.c
drivers/net/hamradio/baycom_par.c
drivers/net/hamradio/baycom_ser_fdx.c
drivers/net/hamradio/baycom_ser_hdx.c
drivers/net/ibm_newemac/core.c
drivers/net/ibm_newemac/rgmii.c
drivers/net/igb/e1000_82575.c
drivers/net/igb/igb_main.c
drivers/net/igbvf/vf.c
drivers/net/irda/au1k_ir.c
drivers/net/irda/bfin_sir.c
drivers/net/irda/irtty-sir.c
drivers/net/irda/pxaficp_ir.c
drivers/net/irda/sa1100_ir.c
drivers/net/irda/w83977af_ir.c
drivers/net/isa-skeleton.c
drivers/net/ixgbe/ixgbe.h
drivers/net/ixgbe/ixgbe_82598.c
drivers/net/ixgbe/ixgbe_dcb_nl.c
drivers/net/ixgbe/ixgbe_ethtool.c
drivers/net/ixgbe/ixgbe_fcoe.c
drivers/net/ixgbe/ixgbe_main.c
drivers/net/ixgbe/ixgbe_phy.c
drivers/net/ixgbe/ixgbe_type.h
drivers/net/ixp2000/ixpdev.c
drivers/net/jazzsonic.c
drivers/net/ks8851.c [new file with mode: 0644]
drivers/net/ks8851.h [new file with mode: 0644]
drivers/net/macb.c
drivers/net/macsonic.c
drivers/net/mdio.c
drivers/net/mlx4/cmd.c
drivers/net/mlx4/en_ethtool.c
drivers/net/mlx4/en_rx.c
drivers/net/mlx4/en_tx.c
drivers/net/mlx4/main.c
drivers/net/natsemi.c
drivers/net/ne.c
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_ctx.c
drivers/net/netxen/netxen_nic_hdr.h
drivers/net/netxen/netxen_nic_hw.c
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/pci-skeleton.c
drivers/net/pcmcia/3c589_cs.c
drivers/net/pcmcia/ibmtr_cs.c
drivers/net/pcmcia/nmclan_cs.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/pcnet32.c
drivers/net/phy/mdio-gpio.c
drivers/net/phy/phy.c
drivers/net/phy/phy_device.c
drivers/net/plip.c
drivers/net/ppp_async.c
drivers/net/ppp_generic.c
drivers/net/ppp_synctty.c
drivers/net/pppoe.c
drivers/net/pppol2tp.c
drivers/net/ps3_gelic_net.c
drivers/net/ps3_gelic_wireless.c
drivers/net/qlge/qlge.h
drivers/net/qlge/qlge_ethtool.c
drivers/net/qlge/qlge_main.c
drivers/net/qlge/qlge_mpi.c
drivers/net/r6040.c
drivers/net/r8169.c
drivers/net/s6gmac.c
drivers/net/sc92031.c
drivers/net/sh_eth.c
drivers/net/skge.c
drivers/net/sky2.c
drivers/net/sky2.h
drivers/net/smc91x.c
drivers/net/smc91x.h
drivers/net/smsc911x.c
drivers/net/starfire.c
drivers/net/sundance.c
drivers/net/sunvnet.c
drivers/net/tokenring/ibmtr.c
drivers/net/tsi108_eth.c
drivers/net/tulip/de2104x.c
drivers/net/tulip/de4x5.c
drivers/net/tulip/tulip_core.c
drivers/net/tulip/winbond-840.c
drivers/net/tun.c
drivers/net/ucc_geth.c
drivers/net/usb/Kconfig
drivers/net/usb/Makefile
drivers/net/usb/cdc-phonet.c [new file with mode: 0644]
drivers/net/usb/cdc_eem.c
drivers/net/usb/dm9601.c
drivers/net/usb/kaweth.c
drivers/net/usb/net1080.c
drivers/net/usb/pegasus.c
drivers/net/usb/pegasus.h
drivers/net/usb/rndis_host.c
drivers/net/usb/smsc95xx.c
drivers/net/usb/usbnet.c
drivers/net/veth.c
drivers/net/via-rhine.c
drivers/net/via-velocity.c
drivers/net/virtio_net.c
drivers/net/wan/hd64570.c
drivers/net/wan/hd64572.c
drivers/net/wan/sbni.c
drivers/net/wireless/airo.c
drivers/net/wireless/ath/Kconfig
drivers/net/wireless/ath/ar9170/main.c
drivers/net/wireless/ath/ar9170/usb.c
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath9k/ani.c
drivers/net/wireless/ath/ath9k/eeprom.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/regd.c
drivers/net/wireless/b43/b43.h
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43/pcmcia.c
drivers/net/wireless/b43legacy/b43legacy.h
drivers/net/wireless/b43legacy/main.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/iwlwifi/iwl-3945.h
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-debugfs.c
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-sta.c
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/iwmc3200wifi/Kconfig
drivers/net/wireless/iwmc3200wifi/commands.c
drivers/net/wireless/iwmc3200wifi/netdev.c
drivers/net/wireless/libertas/11d.c
drivers/net/wireless/libertas/cmd.c
drivers/net/wireless/libertas/defs.h
drivers/net/wireless/libertas/hostcmd.h
drivers/net/wireless/libertas/scan.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mwl8k.c
drivers/net/wireless/orinoco/hw.c
drivers/net/wireless/orinoco/main.c
drivers/net/wireless/p54/p54common.c
drivers/net/wireless/p54/p54spi.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rtl818x/rtl8187_dev.c
drivers/net/wireless/rtl818x/rtl8187_leds.c
drivers/net/wireless/wavelan_cs.c
drivers/net/wireless/zd1211rw/zd_mac.c
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/net/yellowfin.c
drivers/net/zorro8390.c
drivers/of/of_mdio.c
drivers/oprofile/oprofile_stats.c
drivers/parisc/ccio-dma.c
drivers/parisc/dino.c
drivers/parisc/eisa.c
drivers/parisc/eisa_eeprom.c
drivers/parisc/eisa_enumerator.c
drivers/parisc/gsc.c
drivers/parisc/gsc.h
drivers/parisc/hppb.c
drivers/parisc/iosapic.c
drivers/parisc/lba_pci.c
drivers/parisc/pdc_stable.c
drivers/parisc/sba_iommu.c
drivers/parisc/superio.c
drivers/parport/parport_pc.c
drivers/pci/hotplug/cpci_hotplug_core.c
drivers/pci/hotplug/cpqphp_ctrl.c
drivers/pci/hotplug/cpqphp_sysfs.c
drivers/pci/hotplug/pci_hotplug_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/sgi_hotplug.c
drivers/pci/intel-iommu.c
drivers/pci/iov.c
drivers/pci/iova.c
drivers/pci/msi.c
drivers/pci/msi.h
drivers/pci/pci-driver.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aer/ecrc.c
drivers/pci/quirks.c
drivers/pci/setup-bus.c
drivers/pci/setup-res.c
drivers/pci/slot.c
drivers/pci/syscall.c
drivers/pcmcia/tcic.c
drivers/pcmcia/vrc4171_card.c
drivers/pcmcia/vrc4173_cardu.c
drivers/pcmcia/vrc4173_cardu.h
drivers/platform/x86/Kconfig
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/wmi.c
drivers/power/Kconfig
drivers/power/Makefile
drivers/power/ds2782_battery.c [new file with mode: 0644]
drivers/power/olpc_battery.c
drivers/power/wm97xx_battery.c
drivers/pps/pps.c
drivers/rtc/rtc-bfin.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-ds1374.c
drivers/rtc/rtc-vr41xx.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_erp.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_ioctl.c
drivers/s390/block/dcssblk.c
drivers/s390/block/xpram.c
drivers/s390/char/monreader.c
drivers/s390/char/sclp_rw.h
drivers/s390/char/vmwatchdog.c
drivers/s390/cio/device.c
drivers/s390/crypto/ap_bus.c
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_fc.c
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_scsi.c
drivers/s390/scsi/zfcp_sysfs.c
drivers/sbus/char/bbc_envctrl.c
drivers/scsi/atari_NCR5380.c
drivers/scsi/cxgb3i/Kbuild
drivers/scsi/cxgb3i/cxgb3i_iscsi.c
drivers/scsi/fnic/fnic_main.c
drivers/scsi/fnic/fnic_scsi.c
drivers/scsi/ibmvscsi/ibmvscsi.c
drivers/scsi/libfc/fc_exch.c
drivers/scsi/libiscsi.c
drivers/scsi/libsas/sas_expander.c
drivers/scsi/libsas/sas_port.c
drivers/scsi/mac53c94.c
drivers/scsi/mpt2sas/mpt2sas_base.c
drivers/scsi/mpt2sas/mpt2sas_base.h
drivers/scsi/mpt2sas/mpt2sas_config.c
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla4xxx/ql4_dbg.c
drivers/scsi/qla4xxx/ql4_def.h
drivers/scsi/qla4xxx/ql4_fw.h
drivers/scsi/qla4xxx/ql4_iocb.c
drivers/scsi/qla4xxx/ql4_isr.c
drivers/scsi/qla4xxx/ql4_mbx.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/qla4xxx/ql4_version.h
drivers/scsi/scsi_transport_fc.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/sd.c
drivers/scsi/sg.c
drivers/scsi/sun3_NCR5380.c
drivers/scsi/zalon.c
drivers/serial/8250_pci.c
drivers/serial/Kconfig
drivers/serial/atmel_serial.c
drivers/serial/bfin_sport_uart.c
drivers/serial/cpm_uart/cpm_uart_cpm2.c
drivers/serial/msm_serial.c
drivers/serial/s3c2400.c
drivers/serial/s3c2410.c
drivers/serial/s3c2412.c
drivers/serial/s3c2440.c
drivers/serial/s3c24a0.c
drivers/serial/s3c6400.c
drivers/serial/serial_ks8695.c
drivers/serial/sh-sci.c
drivers/serial/vr41xx_siu.c
drivers/spi/omap2_mcspi.c
drivers/spi/omap_uwire.c
drivers/spi/spi_bitbang.c
drivers/spi/spi_s3c24xx.c
drivers/spi/spidev.c
drivers/ssb/driver_mipscore.c
drivers/ssb/pcmcia.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/android/lowmemorykiller.c
drivers/staging/b3dfg/Kconfig
drivers/staging/comedi/drivers/jr3_pci.c
drivers/staging/comedi/drivers/s626.c
drivers/staging/go7007/s2250-loader.c
drivers/staging/heci/Kconfig
drivers/staging/meilhaus/TODO
drivers/staging/rspiusb/rspiusb.c
drivers/staging/rt2860/rt_linux.h
drivers/staging/rt2870/2870_main_dev.c
drivers/staging/rt2870/common/2870_rtmp_init.c
drivers/staging/rt2870/common/rtusb_io.c
drivers/staging/rt2870/rt2870.h
drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
drivers/staging/rtl8192su/Kconfig
drivers/staging/rtl8192su/ieee80211.h
drivers/staging/rtl8192su/ieee80211/ieee80211.h
drivers/staging/rtl8192su/ieee80211/ieee80211_module.c
drivers/staging/rtl8192su/ieee80211/ieee80211_softmac_wx.c
drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c
drivers/staging/rtl8192su/r8192U_core.c
drivers/staging/rtl8192su/r8192U_pm.c
drivers/staging/serqt_usb2/serqt_usb2.c
drivers/staging/stlc45xx/stlc45xx.c
drivers/staging/uc2322/Kconfig [deleted file]
drivers/staging/uc2322/Makefile [deleted file]
drivers/staging/uc2322/TODO [deleted file]
drivers/staging/uc2322/aten2011.c [deleted file]
drivers/staging/udlfb/udlfb.c
drivers/staging/usbip/usbip_common.c
drivers/staging/vt6655/device_main.c
drivers/telephony/ixj.c
drivers/telephony/phonedev.c
drivers/thermal/thermal_sys.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.h
drivers/usb/class/cdc-wdm.c
drivers/usb/class/usbtmc.c
drivers/usb/core/Kconfig
drivers/usb/core/config.c
drivers/usb/core/devices.c
drivers/usb/core/devio.c
drivers/usb/core/hcd.c
drivers/usb/core/hcd.h
drivers/usb/core/hub.c
drivers/usb/core/hub.h
drivers/usb/core/message.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/amd5536udc.c
drivers/usb/gadget/audio.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/langwell_udc.c
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/gadget/rndis.c
drivers/usb/gadget/s3c2410_udc.c
drivers/usb/host/Kconfig
drivers/usb/host/ehci-au1xxx.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-ixp4xx.c
drivers/usb/host/ehci-orion.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-ppc-of.c
drivers/usb/host/ehci-ps3.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci.h
drivers/usb/host/fhci-sched.c
drivers/usb/host/isp1760-if.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/r8a66597-hcd.c
drivers/usb/host/xhci-dbg.c
drivers/usb/host/xhci-hcd.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.h
drivers/usb/misc/Kconfig
drivers/usb/misc/iowarrior.c
drivers/usb/misc/rio500.c
drivers/usb/misc/usblcd.c
drivers/usb/mon/mon_bin.c
drivers/usb/musb/Kconfig
drivers/usb/musb/cppi_dma.h
drivers/usb/musb/davinci.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_gadget_ep0.c
drivers/usb/musb/musb_host.c
drivers/usb/musb/musb_regs.h
drivers/usb/otg/Kconfig
drivers/usb/otg/Makefile
drivers/usb/otg/langwell_otg.c [deleted file]
drivers/usb/otg/nop-usb-xceiv.c
drivers/usb/serial/console.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/generic.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/serial/sierra.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c
drivers/usb/storage/option_ms.c
drivers/usb/storage/transport.c
drivers/usb/storage/unusual_devs.h
drivers/video/Kconfig
drivers/video/amba-clcd.c
drivers/video/atafb.c
drivers/video/atmel_lcdfb.c
drivers/video/aty/atyfb.h
drivers/video/aty/atyfb_base.c
drivers/video/aty/mach64_accel.c
drivers/video/backlight/jornada720_bl.c
drivers/video/backlight/pwm_bl.c
drivers/video/backlight/tdo24m.c
drivers/video/cobalt_lcdfb.c
drivers/video/console/fbcon.c
drivers/video/console/fbcon_rotate.h
drivers/video/console/sticore.c
drivers/video/fbmem.c
drivers/video/fbmon.c
drivers/video/fsl-diu-fb.c
drivers/video/hitfb.c
drivers/video/i810/i810_main.c
drivers/video/matrox/matroxfb_DAC1064.c
drivers/video/matrox/matroxfb_Ti3026.c
drivers/video/matrox/matroxfb_base.c
drivers/video/matrox/matroxfb_crtc2.c
drivers/video/mx3fb.c
drivers/video/omap/omapfb_main.c
drivers/video/platinumfb.c
drivers/video/pxafb.c
drivers/video/s3c-fb.c
drivers/video/sh7760fb.c
drivers/video/sh_mobile_lcdcfb.c
drivers/video/sis/sis_main.c
drivers/video/sm501fb.c
drivers/video/stifb.c
drivers/video/via/hw.c
drivers/video/via/lcd.c
drivers/video/via/viafbdev.c
drivers/video/via/viafbdev.h
drivers/video/w100fb.c
drivers/video/xen-fbfront.c
drivers/virtio/virtio_pci.c
drivers/vlynq/Kconfig
drivers/vlynq/vlynq.c
drivers/w1/masters/omap_hdq.c
drivers/watchdog/ar7_wdt.c
drivers/watchdog/bcm47xx_wdt.c
drivers/watchdog/coh901327_wdt.c
drivers/watchdog/ep93xx_wdt.c
drivers/watchdog/ks8695_wdt.c
drivers/watchdog/sa1100_wdt.c
drivers/watchdog/w83627hf_wdt.c
drivers/watchdog/w83697ug_wdt.c
drivers/watchdog/wdrtas.c
drivers/xen/events.c
fs/9p/v9fs.c
fs/9p/v9fs.h
fs/9p/vfs_addr.c
fs/9p/vfs_inode.c
fs/9p/vfs_super.c
fs/Kconfig
fs/adfs/super.c
fs/afs/dir.c
fs/afs/file.c
fs/afs/flock.c
fs/afs/mntpt.c
fs/afs/super.c
fs/aio.c
fs/autofs4/dev-ioctl.c
fs/autofs4/expire.c
fs/bfs/dir.c
fs/bfs/file.c
fs/binfmt_elf.c
fs/binfmt_flat.c
fs/bio-integrity.c
fs/bio.c
fs/block_dev.c
fs/btrfs/async-thread.c
fs/btrfs/compression.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/free-space-cache.h
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/print-tree.c
fs/btrfs/relocation.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/btrfs/zlib.c
fs/buffer.c
fs/char_dev.c
fs/cifs/CHANGES
fs/cifs/README
fs/cifs/asn1.c
fs/cifs/cifs_debug.c
fs/cifs/cifs_dfs_ref.c
fs/cifs/cifs_spnego.c
fs/cifs/cifs_unicode.c
fs/cifs/cifsacl.c
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifsglob.h
fs/cifs/cifspdu.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/dns_resolve.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/link.c
fs/cifs/netmisc.c
fs/cifs/readdir.c
fs/cifs/sess.c
fs/cifs/xattr.c
fs/compat.c
fs/compat_ioctl.c
fs/dlm/lock.c
fs/dlm/lowcomms.c
fs/dlm/plock.c
fs/ecryptfs/keystore.c
fs/eventfd.c
fs/exec.c
fs/exofs/common.h
fs/exofs/dir.c
fs/exofs/exofs.h
fs/exofs/file.c
fs/exofs/inode.c
fs/exofs/namei.c
fs/exofs/osd.c
fs/exofs/super.c
fs/exofs/symlink.c
fs/ext2/ioctl.c
fs/ext2/namei.c
fs/ext3/Kconfig
fs/ext3/dir.c
fs/ext3/inode.c
fs/ext3/super.c
fs/ext4/ext4.h
fs/ext4/ext4_jbd2.c
fs/ext4/ext4_jbd2.h
fs/ext4/extents.c
fs/ext4/ialloc.c
fs/ext4/inode.c
fs/ext4/ioctl.c
fs/ext4/mballoc.c
fs/fat/dir.c
fs/fat/file.c
fs/fat/namei_msdos.c
fs/fat/namei_vfat.c
fs/fcntl.c
fs/freevxfs/vxfs_super.c
fs/fuse/dev.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/gfs2/aops.c
fs/gfs2/glock.c
fs/gfs2/glock.h
fs/gfs2/glops.c
fs/gfs2/incore.h
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/gfs2/super.h
fs/gfs2/sys.c
fs/gfs2/trace_gfs2.h
fs/hfs/super.c
fs/hfsplus/super.c
fs/hostfs/hostfs_kern.c
fs/hpfs/dir.c
fs/hpfs/file.c
fs/hpfs/hpfs_fn.h
fs/hpfs/inode.c
fs/hpfs/namei.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/isofs/inode.c
fs/jbd/journal.c
fs/jbd/transaction.c
fs/jbd2/journal.c
fs/jbd2/transaction.c
fs/jffs2/erase.c
fs/jffs2/file.c
fs/jffs2/scan.c
fs/jffs2/super.c
fs/jffs2/wbuf.c
fs/jfs/acl.c
fs/libfs.c
fs/lockd/clntproc.c
fs/lockd/svc4proc.c
fs/lockd/svcproc.c
fs/namei.c
fs/namespace.c
fs/nfs/client.c
fs/nfs/delegation.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/getroot.c
fs/nfs/inode.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/read.c
fs/nfs/write.c
fs/nfsd/nfsctl.c
fs/nfsd/nfssvc.c
fs/nfsd/vfs.c
fs/nilfs2/Kconfig [new file with mode: 0644]
fs/nilfs2/bmap.c
fs/nilfs2/btnode.c
fs/nilfs2/cpfile.c
fs/nilfs2/dat.c
fs/nilfs2/dir.c
fs/nilfs2/mdt.c
fs/nilfs2/segment.c
fs/nilfs2/super.c
fs/nilfs2/the_nilfs.h
fs/notify/Kconfig
fs/notify/dnotify/Kconfig
fs/notify/fsnotify.c
fs/notify/inotify/Kconfig
fs/notify/inotify/inotify_fsnotify.c
fs/notify/inotify/inotify_user.c
fs/notify/notification.c
fs/ocfs2/alloc.c
fs/ocfs2/aops.c
fs/ocfs2/dcache.c
fs/ocfs2/dcache.h
fs/ocfs2/dlm/dlmast.c
fs/ocfs2/dlm/dlmrecovery.c
fs/ocfs2/dlm/dlmunlock.c
fs/ocfs2/file.c
fs/ocfs2/ioctl.c
fs/ocfs2/journal.c
fs/ocfs2/journal.h
fs/ocfs2/ocfs2.h
fs/ocfs2/ocfs2_lockid.h
fs/ocfs2/quota.h
fs/ocfs2/quota_global.c
fs/ocfs2/quota_local.c
fs/ocfs2/stack_o2cb.c
fs/ocfs2/super.c
fs/ocfs2/xattr.c
fs/partitions/check.c
fs/pipe.c
fs/proc/base.c
fs/proc/task_mmu.c
fs/proc/task_nommu.c
fs/quota/dquot.c
fs/ramfs/file-nommu.c
fs/reiserfs/journal.c
fs/reiserfs/super.c
fs/reiserfs/xattr.c
fs/select.c
fs/squashfs/super.c
fs/sync.c
fs/sysfs/bin.c
fs/sysfs/dir.c
fs/ubifs/io.c
fs/ubifs/ioctl.c
fs/ubifs/recovery.c
fs/ubifs/replay.c
fs/ubifs/scan.c
fs/ubifs/super.c
fs/ubifs/ubifs.h
fs/udf/super.c
fs/xfs/linux-2.6/kmem.c
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_file.c
fs/xfs/linux-2.6/xfs_ioctl32.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/linux-2.6/xfs_sync.c
fs/xfs/linux-2.6/xfs_sync.h
fs/xfs/xfs_attr.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_btree.c
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_dir2.c
fs/xfs/xfs_fsops.c
fs/xfs/xfs_iget.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_log.c
fs/xfs/xfs_vnodeops.c
include/acpi/acpiosxf.h
include/acpi/processor.h
include/asm-generic/4level-fixup.h
include/asm-generic/percpu.h
include/asm-generic/pgtable-nopmd.h
include/asm-generic/pgtable-nopud.h
include/asm-generic/tlb.h
include/asm-generic/vmlinux.lds.h
include/crypto/algapi.h
include/crypto/internal/skcipher.h
include/drm/drm_edid.h
include/drm/drm_pciids.h
include/drm/radeon_drm.h
include/drm/ttm/ttm_bo_driver.h
include/drm/ttm/ttm_module.h
include/linux/aio.h
include/linux/backing-dev.h
include/linux/binfmts.h
include/linux/bio.h
include/linux/bitmap.h
include/linux/blkdev.h
include/linux/cb710.h
include/linux/cgroup.h
include/linux/clockchips.h
include/linux/clocksource.h
include/linux/console_struct.h
include/linux/cpumask.h
include/linux/crash_dump.h
include/linux/decompress/generic.h
include/linux/device-mapper.h
include/linux/device.h
include/linux/dm-log-userspace.h
include/linux/elfcore.h
include/linux/eventfd.h
include/linux/ext3_fs.h
include/linux/fb.h
include/linux/firewire.h
include/linux/flex_array.h [new file with mode: 0644]
include/linux/fs.h
include/linux/fsnotify_backend.h
include/linux/ftrace_event.h
include/linux/fuse.h
include/linux/gen_stats.h
include/linux/hardirq.h
include/linux/hrtimer.h
include/linux/hugetlb.h
include/linux/ide.h
include/linux/if_ether.h
include/linux/ima.h
include/linux/inetdevice.h
include/linux/init_task.h
include/linux/input/matrix_keypad.h [new file with mode: 0644]
include/linux/interrupt.h
include/linux/iocontext.h
include/linux/kernel.h
include/linux/kmemleak.h
include/linux/kvm_host.h
include/linux/leds-lp3944.h [new file with mode: 0644]
include/linux/leds.h
include/linux/lguest.h
include/linux/lguest_launcher.h
include/linux/libata.h
include/linux/linkage.h
include/linux/lmb.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/mnt_namespace.h
include/linux/mtd/mtd.h
include/linux/mtd/partitions.h
include/linux/netfilter/xt_conntrack.h
include/linux/netfilter/xt_osf.h
include/linux/nfs_fs.h
include/linux/nodemask.h
include/linux/of_mdio.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/percpu-defs.h
include/linux/perf_counter.h
include/linux/personality.h
include/linux/pps.h
include/linux/quotaops.h
include/linux/rfkill.h
include/linux/scatterlist.h
include/linux/sched.h
include/linux/security.h
include/linux/skbuff.h
include/linux/slub_def.h
include/linux/spi/spi.h
include/linux/spi/spidev.h
include/linux/spinlock.h
include/linux/sunrpc/xdr.h
include/linux/syscalls.h
include/linux/sysrq.h
include/linux/timer.h
include/linux/tty.h
include/linux/tty_ldisc.h
include/linux/ucb1400.h
include/linux/uio.h
include/linux/usb.h
include/linux/usb/langwell_otg.h [deleted file]
include/linux/usb/serial.h
include/linux/usb/usbnet.h
include/linux/videodev2.h
include/linux/virtio_blk.h
include/linux/virtio_config.h
include/linux/virtio_net.h
include/linux/virtio_ring.h
include/linux/wait.h
include/linux/workqueue.h
include/media/v4l2-chip-ident.h
include/net/act_api.h
include/net/bluetooth/rfcomm.h
include/net/cfg80211.h
include/net/gen_stats.h
include/net/netfilter/nf_conntrack.h
include/net/netfilter/xt_rateest.h
include/net/phonet/pn_dev.h
include/net/rose.h
include/net/sch_generic.h
include/net/sock.h
include/net/tcp.h
include/sound/ac97_codec.h
include/sound/asound.h
include/sound/core.h
include/sound/info.h
include/sound/memalloc.h
include/sound/pcm.h
include/sound/sh_fsi.h [new file with mode: 0644]
include/sound/soc-dai.h
include/sound/soc-dapm.h
include/sound/soc.h
include/sound/tlv.h
include/sound/uda1380.h [new file with mode: 0644]
include/sound/version.h
include/sound/wm8993.h [new file with mode: 0644]
include/sound/ymfpci.h
include/trace/events/block.h
include/trace/events/ext4.h
include/trace/events/irq.h
include/trace/events/jbd2.h
include/trace/events/kmem.h
include/trace/events/lockdep.h
include/trace/events/sched.h
include/trace/events/skb.h
include/trace/events/workqueue.h
include/trace/ftrace.h
init/Kconfig
init/main.c
ipc/mqueue.c
ipc/shm.c
kernel/Makefile
kernel/acct.c
kernel/cgroup.c
kernel/exit.c
kernel/fork.c
kernel/freezer.c
kernel/futex.c
kernel/futex_compat.c
kernel/hrtimer.c
kernel/irq/internals.h
kernel/irq/manage.c
kernel/irq/migration.c
kernel/irq/numa_migrate.c
kernel/kexec.c
kernel/kmod.c
kernel/kprobes.c
kernel/kthread.c
kernel/lockdep_proc.c
kernel/module.c
kernel/panic.c
kernel/perf_counter.c
kernel/posix-cpu-timers.c
kernel/posix-timers.c
kernel/power/user.c
kernel/profile.c
kernel/ptrace.c
kernel/rcutree.c
kernel/resource.c
kernel/rtmutex.c
kernel/sched.c
kernel/sched_cpupri.c
kernel/sched_fair.c
kernel/sched_rt.c
kernel/signal.c
kernel/smp.c
kernel/softirq.c
kernel/sysctl.c
kernel/time/clockevents.c
kernel/time/clocksource.c
kernel/time/tick-broadcast.c
kernel/time/timer_list.c
kernel/time/timer_stats.c
kernel/timer.c
kernel/trace/Kconfig
kernel/trace/blktrace.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_event_profile.c
kernel/trace/trace_event_types.h
kernel/trace/trace_events.c
kernel/trace/trace_events_filter.c
kernel/trace/trace_functions.c
kernel/trace/trace_functions_graph.c
kernel/trace/trace_output.c
kernel/trace/trace_printk.c
kernel/trace/trace_stack.c
kernel/trace/trace_stat.c
kernel/wait.c
lib/Kconfig.debug
lib/Makefile
lib/atomic64.c
lib/bitmap.c
lib/decompress_bunzip2.c
lib/decompress_inflate.c
lib/decompress_unlzma.c
lib/dma-debug.c
lib/dynamic_debug.c
lib/flex_array.c [new file with mode: 0644]
lib/lmb.c
lib/scatterlist.c
mm/Kconfig
mm/backing-dev.c
mm/bootmem.c
mm/dmapool.c
mm/filemap.c
mm/hugetlb.c
mm/kmemleak.c
mm/memcontrol.c
mm/memory.c
mm/mempolicy.c
mm/mempool.c
mm/mmap.c
mm/nommu.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/percpu.c
mm/rmap.c
mm/slab.c
mm/slob.c
mm/slub.c
mm/swapfile.c
mm/vmscan.c
net/9p/client.c
net/9p/error.c
net/9p/trans_fd.c
net/9p/trans_rdma.c
net/9p/trans_virtio.c
net/appletalk/ddp.c
net/atm/common.c
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/sock.c
net/bridge/br.c
net/bridge/br_if.c
net/can/bcm.c
net/can/raw.c
net/core/datagram.c
net/core/dev.c
net/core/gen_estimator.c
net/core/gen_stats.c
net/core/net_namespace.c
net/core/netpoll.c
net/core/sock.c
net/dccp/output.c
net/dccp/proto.c
net/decnet/af_decnet.c
net/dsa/mv88e6xxx.c
net/econet/af_econet.c
net/ieee802154/af_ieee802154.c
net/ieee802154/dgram.c
net/ieee802154/netlink.c
net/ieee802154/raw.c
net/ipv4/arp.c
net/ipv4/fib_trie.c
net/ipv4/ip_gre.c
net/ipv4/ip_input.c
net/ipv4/ip_output.c
net/ipv4/netfilter/nf_nat_helper.c
net/ipv4/tcp.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv4/xfrm4_policy.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/ip6_input.c
net/ipv6/ip6_output.c
net/ipv6/sit.c
net/ipv6/tcp_ipv6.c
net/ipv6/xfrm6_policy.c
net/ipx/af_ipx.c
net/irda/af_irda.c
net/irda/irnet/irnet.h
net/irda/irnet/irnet_ppp.c
net/irda/irttp.c
net/iucv/af_iucv.c
net/llc/af_llc.c
net/mac80211/Kconfig
net/mac80211/agg-tx.c
net/mac80211/key.c
net/mac80211/mesh.c
net/mac80211/mesh_hwmp.c
net/mac80211/mesh_pathtbl.c
net/mac80211/mlme.c
net/mac80211/pm.c
net/mac80211/rc80211_minstrel.c
net/mac80211/rx.c
net/mac80211/tx.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_expect.c
net/netfilter/nf_conntrack_extend.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/xt_RATEEST.c
net/netfilter/xt_conntrack.c
net/netfilter/xt_osf.c
net/netfilter/xt_quota.c
net/netlabel/netlabel_kapi.c
net/netrom/af_netrom.c
net/netrom/nr_route.c
net/phonet/pn_dev.c
net/phonet/pn_netlink.c
net/rfkill/core.c
net/rose/af_rose.c
net/rose/rose_route.c
net/rxrpc/af_rxrpc.c
net/sched/sch_api.c
net/sched/sch_atm.c
net/sched/sch_cbq.c
net/sched/sch_drr.c
net/sched/sch_hfsc.c
net/sched/sch_htb.c
net/sctp/output.c
net/sctp/protocol.c
net/sctp/socket.c
net/socket.c
net/sunrpc/clnt.c
net/sunrpc/sched.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/svc_xprt.c
net/unix/af_unix.c
net/wanrouter/wanmain.c
net/wireless/nl80211.c
net/wireless/reg.c
net/wireless/reg.h
net/wireless/scan.c
net/x25/af_x25.c
net/xfrm/xfrm_algo.c
net/xfrm/xfrm_hash.h
net/xfrm/xfrm_state.c
samples/trace_events/trace-events-sample.h
scripts/.gitignore
scripts/dtc/.gitignore [new file with mode: 0644]
scripts/get_maintainer.pl
scripts/kconfig/lxdialog/util.c
scripts/kconfig/mconf.c
scripts/kernel-doc
scripts/markup_oops.pl
scripts/package/builddeb
scripts/pnmtologo.c
scripts/recordmcount.pl
security/Kconfig
security/Makefile
security/capability.c
security/commoncap.c
security/integrity/ima/ima_crypto.c
security/integrity/ima/ima_main.c
security/integrity/ima/ima_queue.c
security/min_addr.c [new file with mode: 0644]
security/selinux/hooks.c
sound/Kconfig
sound/aoa/codecs/tas.c
sound/aoa/core/gpio-pmf.c
sound/arm/pxa2xx-ac97.c
sound/arm/pxa2xx-pcm-lib.c
sound/core/Kconfig
sound/core/Makefile
sound/core/control.c
sound/core/info.c
sound/core/init.c
sound/core/memalloc.c
sound/core/misc.c
sound/core/oss/mixer_oss.c
sound/core/oss/pcm_oss.c
sound/core/pcm.c
sound/core/pcm_lib.c
sound/core/pcm_memory.c
sound/core/pcm_native.c
sound/core/rawmidi.c
sound/core/seq/Makefile
sound/core/seq/oss/seq_oss_midi.c
sound/core/seq/seq_midi.c
sound/core/vmaster.c
sound/drivers/dummy.c
sound/isa/cmi8330.c
sound/isa/gus/gus_pcm.c
sound/mips/hal2.c
sound/mips/sgio2audio.c
sound/oss/aedsp16.c
sound/oss/kahlua.c
sound/oss/midibuf.c
sound/oss/mpu401.c
sound/oss/vwsnd.c
sound/pci/Kconfig
sound/pci/ali5451/ali5451.c
sound/pci/atiixp.c
sound/pci/atiixp_modem.c
sound/pci/au88x0/au8810.c
sound/pci/au88x0/au8820.c
sound/pci/au88x0/au8830.c
sound/pci/azt3328.c
sound/pci/azt3328.h
sound/pci/ca0106/ca0106_main.c
sound/pci/cmipci.c
sound/pci/cs4281.c
sound/pci/cs46xx/cs46xx.c
sound/pci/cs46xx/cs46xx_lib.h
sound/pci/ctxfi/ct20k2reg.h
sound/pci/ctxfi/ctamixer.c
sound/pci/ctxfi/ctatc.c
sound/pci/ctxfi/ctdaio.c
sound/pci/ctxfi/cthw20k1.c
sound/pci/ctxfi/cthw20k2.c
sound/pci/ctxfi/ctmixer.c
sound/pci/ctxfi/ctpcm.c
sound/pci/ctxfi/ctresource.c
sound/pci/ctxfi/ctsrc.c
sound/pci/ctxfi/ctvmem.c
sound/pci/echoaudio/echoaudio.c
sound/pci/echoaudio/mia.c
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1x.c
sound/pci/emu10k1/p16v.c
sound/pci/ens1370.c
sound/pci/es1938.c
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1712.h
sound/pci/ice1712/ice1724.c
sound/pci/ice1712/prodigy_hifi.c
sound/pci/intel8x0.c
sound/pci/intel8x0m.c
sound/pci/lx6464es/lx6464es.c
sound/pci/lx6464es/lx6464es.h
sound/pci/lx6464es/lx_core.c
sound/pci/mixart/mixart.c
sound/pci/nm256/nm256.c
sound/pci/oxygen/oxygen_io.c
sound/pci/oxygen/oxygen_lib.c
sound/pci/oxygen/oxygen_mixer.c
sound/pci/oxygen/oxygen_pcm.c
sound/pci/oxygen/virtuoso.c
sound/pci/riptide/riptide.c
sound/pci/rme32.c
sound/pci/rme96.c
sound/pci/rme9652/hdsp.c
sound/pci/sonicvibes.c
sound/pci/via82xx.c
sound/pci/via82xx_modem.c
sound/pci/vx222/vx222_ops.c
sound/pci/ymfpci/ymfpci.c
sound/pci/ymfpci/ymfpci_main.c
sound/ppc/keywest.c
sound/soc/Kconfig
sound/soc/Makefile
sound/soc/atmel/sam9g20_wm8731.c
sound/soc/au1x/psc-ac97.c
sound/soc/au1x/psc.h
sound/soc/blackfin/Kconfig
sound/soc/blackfin/Makefile
sound/soc/blackfin/bf5xx-ac97.c
sound/soc/blackfin/bf5xx-ac97.h
sound/soc/blackfin/bf5xx-ad1836.c [new file with mode: 0644]
sound/soc/blackfin/bf5xx-ad1938.c [new file with mode: 0644]
sound/soc/blackfin/bf5xx-ad73311.c
sound/soc/blackfin/bf5xx-i2s.c
sound/soc/blackfin/bf5xx-i2s.h
sound/soc/blackfin/bf5xx-sport.c
sound/soc/blackfin/bf5xx-ssm2602.c
sound/soc/blackfin/bf5xx-tdm-pcm.c [new file with mode: 0644]
sound/soc/blackfin/bf5xx-tdm-pcm.h [new file with mode: 0644]
sound/soc/blackfin/bf5xx-tdm.c [new file with mode: 0644]
sound/soc/blackfin/bf5xx-tdm.h [new file with mode: 0644]
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ad1836.c [new file with mode: 0644]
sound/soc/codecs/ad1836.h [new file with mode: 0644]
sound/soc/codecs/ad1938.c [new file with mode: 0644]
sound/soc/codecs/ad1938.h [new file with mode: 0644]
sound/soc/codecs/ak4535.c
sound/soc/codecs/ak4642.c [new file with mode: 0644]
sound/soc/codecs/ak4642.h [new file with mode: 0644]
sound/soc/codecs/cs4270.c
sound/soc/codecs/cx20442.c [new file with mode: 0644]
sound/soc/codecs/cx20442.h [new file with mode: 0644]
sound/soc/codecs/max9877.c [new file with mode: 0644]
sound/soc/codecs/max9877.h [new file with mode: 0644]
sound/soc/codecs/spdif_transciever.c
sound/soc/codecs/stac9766.c
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/tlv320aic3x.h
sound/soc/codecs/twl4030.c
sound/soc/codecs/twl4030.h
sound/soc/codecs/uda134x.c
sound/soc/codecs/uda1380.c
sound/soc/codecs/uda1380.h
sound/soc/codecs/wm8350.c
sound/soc/codecs/wm8400.c
sound/soc/codecs/wm8510.c
sound/soc/codecs/wm8523.c [new file with mode: 0644]
sound/soc/codecs/wm8523.h [new file with mode: 0644]
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8728.c
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8776.c [new file with mode: 0644]
sound/soc/codecs/wm8776.h [new file with mode: 0644]
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8903.c
sound/soc/codecs/wm8940.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8961.c [new file with mode: 0644]
sound/soc/codecs/wm8961.h [new file with mode: 0644]
sound/soc/codecs/wm8971.c
sound/soc/codecs/wm8974.c [new file with mode: 0644]
sound/soc/codecs/wm8974.h [new file with mode: 0644]
sound/soc/codecs/wm8988.c
sound/soc/codecs/wm8990.c
sound/soc/codecs/wm8993.c [new file with mode: 0644]
sound/soc/codecs/wm8993.h [new file with mode: 0644]
sound/soc/codecs/wm9081.c
sound/soc/codecs/wm9705.c
sound/soc/codecs/wm_hubs.c [new file with mode: 0644]
sound/soc/codecs/wm_hubs.h [new file with mode: 0644]
sound/soc/davinci/Kconfig
sound/soc/davinci/Makefile
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-i2s.c
sound/soc/davinci/davinci-mcasp.c [new file with mode: 0644]
sound/soc/davinci/davinci-mcasp.h [new file with mode: 0644]
sound/soc/davinci/davinci-pcm.c
sound/soc/davinci/davinci-pcm.h
sound/soc/fsl/Kconfig
sound/soc/fsl/efika-audio-fabric.c
sound/soc/fsl/mpc5200_dma.c
sound/soc/fsl/mpc5200_dma.h
sound/soc/fsl/mpc5200_psc_ac97.c
sound/soc/fsl/pcm030-audio-fabric.c
sound/soc/imx/Kconfig [new file with mode: 0644]
sound/soc/imx/Makefile [new file with mode: 0644]
sound/soc/imx/mx1_mx2-pcm.c [new file with mode: 0644]
sound/soc/imx/mx1_mx2-pcm.h [new file with mode: 0644]
sound/soc/imx/mx27vis_wm8974.c [new file with mode: 0644]
sound/soc/imx/mxc-ssi.c [new file with mode: 0644]
sound/soc/imx/mxc-ssi.h [new file with mode: 0644]
sound/soc/omap/Kconfig
sound/soc/omap/Makefile
sound/soc/omap/ams-delta.c [new file with mode: 0644]
sound/soc/omap/n810.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcbsp.h
sound/soc/omap/omap-pcm.c
sound/soc/omap/omap-pcm.h
sound/soc/omap/sdp3430.c
sound/soc/omap/zoom2.c [new file with mode: 0644]
sound/soc/pxa/Kconfig
sound/soc/pxa/magician.c
sound/soc/pxa/palm27x.c
sound/soc/pxa/pxa-ssp.c
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/pxa/pxa2xx-i2s.c
sound/soc/s3c24xx/Kconfig
sound/soc/s3c24xx/Makefile
sound/soc/s3c24xx/neo1973_gta02_wm8753.c [new file with mode: 0644]
sound/soc/s3c24xx/s3c-i2s-v2.c
sound/soc/s3c24xx/s3c2443-ac97.c
sound/soc/s3c24xx/s3c24xx-i2s.c
sound/soc/s3c24xx/s3c24xx-pcm.c
sound/soc/s3c24xx/s3c24xx_simtec.c [new file with mode: 0644]
sound/soc/s3c24xx/s3c24xx_simtec.h [new file with mode: 0644]
sound/soc/s3c24xx/s3c24xx_simtec_hermes.c [new file with mode: 0644]
sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c [new file with mode: 0644]
sound/soc/s6000/s6105-ipcam.c
sound/soc/sh/Kconfig
sound/soc/sh/Makefile
sound/soc/sh/fsi-ak4642.c [new file with mode: 0644]
sound/soc/sh/fsi.c [new file with mode: 0644]
sound/soc/soc-cache.c [new file with mode: 0644]
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-jack.c
sound/soc/txx9/txx9aclc.c
sound/sound_core.c
sound/usb/Kconfig
sound/usb/caiaq/audio.c
sound/usb/caiaq/device.c
sound/usb/caiaq/device.h
sound/usb/usbaudio.c
sound/usb/usbmidi.c
sound/usb/usbmixer.c
sound/usb/usx2y/us122l.c
sound/usb/usx2y/usbusx2y.c
sound/usb/usx2y/usbusx2yaudio.c
tools/perf/CREDITS [new file with mode: 0644]
tools/perf/Documentation/Makefile
tools/perf/Documentation/examples.txt [new file with mode: 0644]
tools/perf/Documentation/perf-record.txt
tools/perf/Documentation/perf-report.txt
tools/perf/Documentation/perf-stat.txt
tools/perf/Documentation/perf-top.txt
tools/perf/Makefile
tools/perf/builtin-annotate.c
tools/perf/builtin-help.c
tools/perf/builtin-list.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-stat.c
tools/perf/builtin-top.c
tools/perf/perf.c
tools/perf/perf.h
tools/perf/util/alias.c
tools/perf/util/cache.h
tools/perf/util/callchain.c [new file with mode: 0644]
tools/perf/util/callchain.h [new file with mode: 0644]
tools/perf/util/color.c
tools/perf/util/color.h
tools/perf/util/config.c
tools/perf/util/exec_cmd.c
tools/perf/util/header.c [new file with mode: 0644]
tools/perf/util/header.h [new file with mode: 0644]
tools/perf/util/help.c
tools/perf/util/help.h
tools/perf/util/include/asm/system.h [new file with mode: 0644]
tools/perf/util/include/linux/kernel.h [new file with mode: 0644]
tools/perf/util/include/linux/list.h [new file with mode: 0644]
tools/perf/util/include/linux/module.h [new file with mode: 0644]
tools/perf/util/include/linux/poison.h [new file with mode: 0644]
tools/perf/util/include/linux/prefetch.h [new file with mode: 0644]
tools/perf/util/include/linux/rbtree.h [new file with mode: 0644]
tools/perf/util/list.h [deleted file]
tools/perf/util/module.c [new file with mode: 0644]
tools/perf/util/module.h [new file with mode: 0644]
tools/perf/util/pager.c
tools/perf/util/parse-events.c
tools/perf/util/parse-events.h
tools/perf/util/parse-options.c
tools/perf/util/parse-options.h
tools/perf/util/quote.c
tools/perf/util/quote.h
tools/perf/util/rbtree.c [deleted file]
tools/perf/util/rbtree.h [deleted file]
tools/perf/util/run-command.c
tools/perf/util/run-command.h
tools/perf/util/strbuf.c
tools/perf/util/strbuf.h
tools/perf/util/string.h
tools/perf/util/strlist.c [new file with mode: 0644]
tools/perf/util/strlist.h [new file with mode: 0644]
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/types.h [moved from tools/perf/types.h with 100% similarity]
tools/perf/util/util.h
tools/perf/util/wrapper.c
virt/kvm/ioapic.c
virt/kvm/irq_comm.c
virt/kvm/kvm_main.c

index cecb3b040cc17d22acdb9268e130a459e771608a..b93fb7eff94286c7a15d475fa581dac32a89b0db 100644 (file)
@@ -27,6 +27,7 @@
 *.gz
 *.lzma
 *.patch
+*.gcno
 
 #
 # Top-level generic files
diff --git a/CREDITS b/CREDITS
index 2b88fb37ad503e12ed271aa26b1068b7c5d93aea..1a41bf4addd0689c9bd7243c80712ee409da9310 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1856,7 +1856,7 @@ E: rfkoenig@immd4.informatik.uni-erlangen.de
 D: The Linux Support Team Erlangen
 
 N: Andreas Koensgen
-E: ajk@iehk.rwth-aachen.de
+E: ajk@comnets.uni-bremen.de
 D: 6pack driver for AX.25
 
 N: Harald Koerfgen
@@ -2006,6 +2006,9 @@ E: paul@laufernet.com
 D: Soundblaster driver fixes, ISAPnP quirk
 S: California, USA
 
+N: Jonathan Layes
+D: ARPD support
+
 N: Tom Lees
 E: tom@lpsg.demon.co.uk
 W: http://www.lpsg.demon.co.uk/
@@ -3802,6 +3805,9 @@ S: van Bronckhorststraat 12
 S: 2612 XV Delft
 S: The Netherlands
 
+N: Thomas Woller
+D: CS461x Cirrus Logic sound driver
+
 N: David Woodhouse
 E: dwmw2@infradead.org
 D: JFFS2 file system, Memory Technology Device subsystem,
index cbbd3e0699453391a461bff35431df5f0ee0d53e..5f3bedaf8e35e90dfc92b2cebee16f6caa025986 100644 (file)
@@ -94,28 +94,37 @@ What:               /sys/block/<disk>/queue/physical_block_size
 Date:          May 2009
 Contact:       Martin K. Petersen <martin.petersen@oracle.com>
 Description:
-               This is the smallest unit the storage device can write
-               without resorting to read-modify-write operation.  It is
-               usually the same as the logical block size but may be
-               bigger.  One example is SATA drives with 4KB sectors
-               that expose a 512-byte logical block size to the
-               operating system.
+               This is the smallest unit a physical storage device can
+               write atomically.  It is usually the same as the logical
+               block size but may be bigger.  One example is SATA
+               drives with 4KB sectors that expose a 512-byte logical
+               block size to the operating system.  For stacked block
+               devices the physical_block_size variable contains the
+               maximum physical_block_size of the component devices.
 
 What:          /sys/block/<disk>/queue/minimum_io_size
 Date:          April 2009
 Contact:       Martin K. Petersen <martin.petersen@oracle.com>
 Description:
-               Storage devices may report a preferred minimum I/O size,
-               which is the smallest request the device can perform
-               without incurring a read-modify-write penalty.  For disk
-               drives this is often the physical block size.  For RAID
-               arrays it is often the stripe chunk size.
+               Storage devices may report a granularity or preferred
+               minimum I/O size which is the smallest request the
+               device can perform without incurring a performance
+               penalty.  For disk drives this is often the physical
+               block size.  For RAID arrays it is often the stripe
+               chunk size.  A properly aligned multiple of
+               minimum_io_size is the preferred request size for
+               workloads where a high number of I/O operations is
+               desired.
 
 What:          /sys/block/<disk>/queue/optimal_io_size
 Date:          April 2009
 Contact:       Martin K. Petersen <martin.petersen@oracle.com>
 Description:
                Storage devices may report an optimal I/O size, which is
-               the device's preferred unit of receiving I/O.  This is
-               rarely reported for disk drives.  For RAID devices it is
-               usually the stripe width or the internal block size.
+               the device's preferred unit for sustained I/O.  This is
+               rarely reported for disk drives.  For RAID arrays it is
+               usually the stripe width or the internal track size.  A
+               properly aligned multiple of optimal_io_size is the
+               preferred request size for workloads where sustained
+               throughput is desired.  If no optimal I/O size is
+               reported this file contains 0.
index a50d6cd58573b63be92acbc7f5ea06d0b884844f..992e67e6be7fbf34e3259bafaec97918505fbede 100644 (file)
@@ -449,8 +449,8 @@ printk(KERN_INFO "i = %u\n", i);
    </para>
 
    <programlisting>
-__u32 ipaddress;
-printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
+__be32 ipaddress;
+printk(KERN_INFO "my ip: %pI4\n", &amp;ipaddress);
    </programlisting>
 
    <para>
index e36986663570d6be1577365645c25b11e866c138..f3f37f141dbdb4a00ab621e07a9c1fa361a1f782 100644 (file)
@@ -184,8 +184,6 @@ usage should require reading the full document.
 !Finclude/net/mac80211.h ieee80211_ctstoself_get
 !Finclude/net/mac80211.h ieee80211_ctstoself_duration
 !Finclude/net/mac80211.h ieee80211_generic_frame_duration
-!Finclude/net/mac80211.h ieee80211_get_hdrlen_from_skb
-!Finclude/net/mac80211.h ieee80211_hdrlen
 !Finclude/net/mac80211.h ieee80211_wake_queue
 !Finclude/net/mac80211.h ieee80211_stop_queue
 !Finclude/net/mac80211.h ieee80211_wake_queues
index 93cb28d05dcd92da30dde47ec58205e2b0851022..18f9651ff23d411e96737ec070d4fc6bc29c50fe 100644 (file)
@@ -83,11 +83,12 @@ not detect it missed following items in original chain.
 obj = kmem_cache_alloc(...);
 lock_chain(); // typically a spin_lock()
 obj->key = key;
-atomic_inc(&obj->refcnt);
 /*
  * we need to make sure obj->key is updated before obj->next
+ * or obj->refcnt
  */
 smp_wmb();
+atomic_set(&obj->refcnt, 1);
 hlist_add_head_rcu(&obj->obj_node, list);
 unlock_chain(); // typically a spin_unlock()
 
@@ -159,6 +160,10 @@ out:
 obj = kmem_cache_alloc(cachep);
 lock_chain(); // typically a spin_lock()
 obj->key = key;
+/*
+ * changes to obj->key must be visible before refcnt one
+ */
+smp_wmb();
 atomic_set(&obj->refcnt, 1);
 /*
  * insert obj in RCU way (readers might be traversing chain)
index 43cb1004d35fb72da88424321ab108da124c52d0..9d58c7c5eddd082b9a22c087c7e0023e02fa4b02 100644 (file)
@@ -21,6 +21,8 @@ ffff8000      ffffffff        copy_user_page / clear_user_page use.
                                For SA11xx and Xscale, this is used to
                                setup a minicache mapping.
 
+ffff4000       ffffffff        cache aliasing on ARMv6 and later CPUs.
+
 ffff1000       ffff7fff        Reserved.
                                Platforms must not use this address range.
 
index e8ca040ba2cff4bb5b938939f75c1bb97f0610af..2d735b0ae383b625c87f37ed2603ec829adf6746 100644 (file)
@@ -50,7 +50,7 @@ encouraged them to allow separation of the data and integrity metadata
 scatter-gather lists.
 
 The controller will interleave the buffers on write and split them on
-read.  This means that the Linux can DMA the data buffers to and from
+read.  This means that Linux can DMA the data buffers to and from
 host memory without changes to the page cache.
 
 Also, the 16-bit CRC checksum mandated by both the SCSI and SATA specs
@@ -66,7 +66,7 @@ software RAID5).
 
 The IP checksum is weaker than the CRC in terms of detecting bit
 errors.  However, the strength is really in the separation of the data
-buffers and the integrity metadata.  These two distinct buffers much
+buffers and the integrity metadata.  These two distinct buffers must
 match up for an I/O to complete.
 
 The separation of the data and integrity metadata buffers as well as
index f9ca389dddf49a7f1bc80c7e724b4a2ffa7e1ba4..1d7e9784439adee55d9d7e983f90e2006b7ef954 100644 (file)
@@ -777,6 +777,18 @@ in cpuset directories:
 # /bin/echo 1-4 > cpus         -> set cpus list to cpus 1,2,3,4
 # /bin/echo 1,2,3,4 > cpus     -> set cpus list to cpus 1,2,3,4
 
+To add a CPU to a cpuset, write the new list of CPUs including the
+CPU to be added. To add 6 to the above cpuset:
+
+# /bin/echo 1-4,6 > cpus       -> set cpus list to cpus 1,2,3,4,6
+
+Similarly to remove a CPU from a cpuset, write the new list of CPUs
+without the CPU to be removed.
+
+To remove all the CPUs:
+
+# /bin/echo "" > cpus          -> clear cpus list
+
 2.3 Setting flags
 -----------------
 
index f688eba8770488e4ebf4fa147e5f6b643be10634..6a5be5d5c8e4895c9f30c8494066eca302ffa056 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     cn_test.c
  * 
- * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
  * All rights reserved.
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -194,5 +194,5 @@ module_init(cn_test_init);
 module_exit(cn_test_fini);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Connector's test module");
index d738cde2a8d51603e7faa207d7aea014ebb80d48..c5092ad0ce4b24912dc361a59dc596ed9ccda011 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     ucon.c
  *
- * Copyright (c) 2004+ Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * Copyright (c) 2004+ Evgeniy Polyakov <zbr@ioremap.net>
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 82132169d47a837fc55ea9d53555abc29b2c7b5d..60120fb3b9618181a9e58f855cdef3ecdc5d0649 100644 (file)
@@ -207,8 +207,8 @@ Attributes
 ~~~~~~~~~~
 struct driver_attribute {
         struct attribute        attr;
-        ssize_t (*show)(struct device_driver *, char * buf, size_t count, loff_t off);
-        ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off);
+        ssize_t (*show)(struct device_driver *driver, char *buf);
+        ssize_t (*store)(struct device_driver *, const char * buf, size_t count);
 };
 
 Device drivers can export attributes via their sysfs directories. 
index a52adfc9a57fe4d7b8cfbbecfa525df6d91906e1..3d1b0ab70c8ef3ed498eb00da7c68b5371d55ce6 100644 (file)
@@ -25,7 +25,7 @@ use IO::Handle;
                "tda10046lifeview", "av7110", "dec2000t", "dec2540t",
                "dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004",
                "or51211", "or51132_qam", "or51132_vsb", "bluebird",
-               "opera1", "cx231xx", "cx18", "cx23885", "pvrusb2" );
+               "opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718" );
 
 # Check args
 syntax() if (scalar(@ARGV) != 1);
@@ -381,6 +381,57 @@ sub cx18 {
     $allfiles;
 }
 
+sub mpc718 {
+    my $archive = 'Yuan MPC718 TV Tuner Card 2.13.10.1016.zip';
+    my $url = "ftp://ftp.work.acer-euro.com/desktop/aspire_idea510/vista/Drivers/$archive";
+    my $fwfile = "dvb-cx18-mpc718-mt352.fw";
+    my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
+
+    checkstandard();
+    wgetfile($archive, $url);
+    unzip($archive, $tmpdir);
+
+    my $sourcefile = "$tmpdir/Yuan MPC718 TV Tuner Card 2.13.10.1016/mpc718_32bit/yuanrap.sys";
+    my $found = 0;
+
+    open IN, '<', $sourcefile or die "Couldn't open $sourcefile to extract $fwfile data\n";
+    binmode IN;
+    open OUT, '>', $fwfile;
+    binmode OUT;
+    {
+       # Block scope because we change the line terminator variable $/
+       my $prevlen = 0;
+       my $currlen;
+
+       # Buried in the data segment are 3 runs of almost identical
+       # register-value pairs that end in 0x5d 0x01 which is a "TUNER GO"
+       # command for the MT352.
+       # Pull out the middle run (because it's easy) of register-value
+       # pairs to make the "firmware" file.
+
+       local $/ = "\x5d\x01"; # MT352 "TUNER GO"
+
+       while (<IN>) {
+           $currlen = length($_);
+           if ($prevlen == $currlen && $currlen <= 64) {
+               chop; chop; # Get rid of "TUNER GO"
+               s/^\0\0//;  # get rid of leading 00 00 if it's there
+               printf OUT "$_";
+               $found = 1;
+               last;
+           }
+           $prevlen = $currlen;
+       }
+    }
+    close OUT;
+    close IN;
+    if (!$found) {
+       unlink $fwfile;
+       die "Couldn't find valid register-value sequence in $sourcefile for $fwfile\n";
+    }
+    $fwfile;
+}
+
 sub cx23885 {
     my $url = "http://linuxtv.org/downloads/firmware/";
 
index f8cd450be9aa83a4a88cee408f79378ef575ce18..f0690bbbd73c3ddc647a383dd678dbd444de2b2d 100644 (file)
@@ -458,3 +458,37 @@ Why:       Remove the old legacy 32bit machine check code. This has been
        but the old version has been kept around for easier testing. Note this
        doesn't impact the old P5 and WinChip machine check handlers.
 Who:   Andi Kleen <andi@firstfloor.org>
+
+----------------------------
+
+What:  lock_policy_rwsem_* and unlock_policy_rwsem_* will not be
+       exported interface anymore.
+When:  2.6.33
+Why:   cpu_policy_rwsem has a new cleaner definition making it local to
+       cpufreq core and contained inside cpufreq.c. Other dependent
+       drivers should not use it in order to safely avoid lockdep issues.
+Who:   Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+
+----------------------------
+
+What:  sound-slot/service-* module aliases and related clutters in
+       sound/sound_core.c
+When:  August 2010
+Why:   OSS sound_core grabs all legacy minors (0-255) of SOUND_MAJOR
+       (14) and requests modules using custom sound-slot/service-*
+       module aliases.  The only benefit of doing this is allowing
+       use of custom module aliases which might as well be considered
+       a bug at this point.  This preemptive claiming prevents
+       alternative OSS implementations.
+
+       Till the feature is removed, the kernel will be requesting
+       both sound-slot/service-* and the standard char-major-* module
+       aliases and allow turning off the pre-claiming selectively via
+       CONFIG_SOUND_OSS_CORE_PRECLAIM and soundcore.preclaim_oss
+       kernel parameter.
+
+       After the transition phase is complete, both the custom module
+       aliases and switches to disable it will go away.  This removal
+       will also allow making ALSA OSS emulation independent of
+       sound_core.  The dependency will be broken then too.
+Who:   Tejun Heo <tj@kernel.org>
index bf8080640eba405d01aac5a101623e825b542d90..6208f55c44c352b3bcef39514fdd147684ac9064 100644 (file)
@@ -123,6 +123,9 @@ available from the same CVS repository.
 There are user and developer mailing lists available through the v9fs project
 on sourceforge (http://sourceforge.net/projects/v9fs).
 
+A stand-alone version of the module (which should build for any 2.6 kernel)
+is available via (http://github.com/ericvh/9p-sac/tree/master)
+
 News and other information is maintained on SWiK (http://swik.net/v9fs).
 
 Bug reports may be issued through the kernel.org bugzilla 
index 12ad6c7f4e50a8e33d395b3993341715b25db960..ffef91c4e0d690312fc8eb176121c76d1522fa43 100644 (file)
@@ -23,15 +23,13 @@ it does support include:
 
  (*) Security (currently only AFS kaserver and KerberosIV tickets).
 
- (*) File reading.
+ (*) File reading and writing.
 
  (*) Automounting.
 
-It does not yet support the following AFS features:
-
- (*) Write support.
+ (*) Local caching (via fscache).
 
- (*) Local caching.
+It does not yet support the following AFS features:
 
  (*) pioctl() system call.
 
@@ -56,7 +54,7 @@ They permit the debugging messages to be turned on dynamically by manipulating
 the masks in the following files:
 
        /sys/module/af_rxrpc/parameters/debug
-       /sys/module/afs/parameters/debug
+       /sys/module/kafs/parameters/debug
 
 
 =====
@@ -66,9 +64,9 @@ USAGE
 When inserting the driver modules the root cell must be specified along with a
 list of volume location server IP addresses:
 
-       insmod af_rxrpc.o
-       insmod rxkad.o
-       insmod kafs.o rootcell=cambridge.redhat.com:172.16.18.73:172.16.18.91
+       modprobe af_rxrpc
+       modprobe rxkad
+       modprobe kafs rootcell=cambridge.redhat.com:172.16.18.73:172.16.18.91
 
 The first module is the AF_RXRPC network protocol driver.  This provides the
 RxRPC remote operation protocol and may also be accessed from userspace.  See:
@@ -81,7 +79,7 @@ is the actual filesystem driver for the AFS filesystem.
 Once the module has been loaded, more modules can be added by the following
 procedure:
 
-       echo add grand.central.org 18.7.14.88:128.2.191.224 >/proc/fs/afs/cells
+       echo add grand.central.org 18.9.48.14:128.2.203.61:130.237.48.87 >/proc/fs/afs/cells
 
 Where the parameters to the "add" command are the name of a cell and a list of
 volume location servers within that cell, with the latter separated by colons.
@@ -101,7 +99,7 @@ The name of the volume can be suffixes with ".backup" or ".readonly" to
 specify connection to only volumes of those types.
 
 The name of the cell is optional, and if not given during a mount, then the
-named volume will be looked up in the cell specified during insmod.
+named volume will be looked up in the cell specified during modprobe.
 
 Additional cells can be added through /proc (see later section).
 
@@ -163,14 +161,14 @@ THE CELL DATABASE
 
 The filesystem maintains an internal database of all the cells it knows and the
 IP addresses of the volume location servers for those cells.  The cell to which
-the system belongs is added to the database when insmod is performed by the
+the system belongs is added to the database when modprobe is performed by the
 "rootcell=" argument or, if compiled in, using a "kafs.rootcell=" argument on
 the kernel command line.
 
 Further cells can be added by commands similar to the following:
 
        echo add CELLNAME VLADDR[:VLADDR][:VLADDR]... >/proc/fs/afs/cells
-       echo add grand.central.org 18.7.14.88:128.2.191.224 >/proc/fs/afs/cells
+       echo add grand.central.org 18.9.48.14:128.2.203.61:130.237.48.87 >/proc/fs/afs/cells
 
 No other cell database operations are available at this time.
 
@@ -233,7 +231,7 @@ insmod /tmp/kafs.o rootcell=cambridge.redhat.com:172.16.18.91
 mount -t afs \%root.afs. /afs
 mount -t afs \%cambridge.redhat.com:root.cell. /afs/cambridge.redhat.com/
 
-echo add grand.central.org 18.7.14.88:128.2.191.224 > /proc/fs/afs/cells
+echo add grand.central.org 18.9.48.14:128.2.203.61:130.237.48.87 > /proc/fs/afs/cells
 mount -t afs "#grand.central.org:root.cell." /afs/grand.central.org/
 mount -t afs "#grand.central.org:root.archive." /afs/grand.central.org/archive
 mount -t afs "#grand.central.org:root.contrib." /afs/grand.central.org/contrib
index fad18f9456e4f048f277bac165601f499c1e041e..ffead13f9443fd7d11b63e2cd3a6ffb15c0f1994 100644 (file)
@@ -1167,13 +1167,11 @@ CHAPTER 3: PER-PROCESS PARAMETERS
 3.1 /proc/<pid>/oom_adj - Adjust the oom-killer score
 ------------------------------------------------------
 
-This file can be used to adjust the score used to select which processes should
-be killed in an out-of-memory situation.  The oom_adj value is a characteristic
-of the task's mm, so all threads that share an mm with pid will have the same
-oom_adj value.  A high value will increase the likelihood of this process being
-killed by the oom-killer.  Valid values are in the range -16 to +15 as
-explained below and a special value of -17, which disables oom-killing
-altogether for threads sharing pid's mm.
+This file can be used to adjust the score used to select which processes
+should be killed in an  out-of-memory  situation.  Giving it a high score will
+increase the likelihood of this process being killed by the oom-killer.  Valid
+values are in the range -16 to +15, plus the special value -17, which disables
+oom-killing altogether for this process.
 
 The process to be killed in an out-of-memory situation is selected among all others
 based on its badness score. This value equals the original memory size of the process
@@ -1187,9 +1185,6 @@ the parent's score if they do not share the same memory. Thus forking servers
 are the prime candidates to be killed. Having only one 'hungry' child will make
 parent less preferable than the child.
 
-/proc/<pid>/oom_adj cannot be changed for kthreads since they are immune from
-oom-killing already.
-
 /proc/<pid>/oom_score shows process' current badness score.
 
 The following heuristics are then applied:
index 7e81e37c0b1ec0ccbea30a92ffbf70f495ffdbd0..b245d524d5682afe30a194821ab62e619092ff3c 100644 (file)
@@ -23,7 +23,8 @@ interface.
 Using sysfs
 ~~~~~~~~~~~
 
-sysfs is always compiled in. You can access it by doing:
+sysfs is always compiled in if CONFIG_SYSFS is defined. You can access
+it by doing:
 
     mount -t sysfs sysfs /sys 
 
index e716aadb3a337006865cfdfd8e53511adb20e787..40ec633527600be750ef15ec4f8706c8bcae0f01 100644 (file)
@@ -188,13 +188,18 @@ Solution: Exclude affected source files from profiling by specifying
           GCOV_PROFILE := n or GCOV_PROFILE_basename.o := n in the
           corresponding Makefile.
 
+Problem:  Files copied from sysfs appear empty or incomplete.
+Cause:    Due to the way seq_file works, some tools such as cp or tar
+          may not correctly copy files from sysfs.
+Solution: Use 'cat' to read .gcda files and 'cp -d' to copy links.
+          Alternatively use the mechanism shown in Appendix B.
+
 
 Appendix A: gather_on_build.sh
 ==============================
 
 Sample script to gather coverage meta files on the build machine
 (see 6a):
-
 #!/bin/bash
 
 KSRC=$1
@@ -226,7 +231,7 @@ Appendix B: gather_on_test.sh
 Sample script to gather coverage data files on the test machine
 (see 6b):
 
-#!/bin/bash
+#!/bin/bash -e
 
 DEST=$1
 GCDA=/sys/kernel/debug/gcov
@@ -236,11 +241,13 @@ if [ -z "$DEST" ] ; then
   exit 1
 fi
 
-find $GCDA -name '*.gcno' -o -name '*.gcda' | tar cfz $DEST -T -
+TEMPDIR=$(mktemp -d)
+echo Collecting data..
+find $GCDA -type d -exec mkdir -p $TEMPDIR/\{\} \;
+find $GCDA -name '*.gcda' -exec sh -c 'cat < $0 > '$TEMPDIR'/$0' {} \;
+find $GCDA -name '*.gcno' -exec sh -c 'cp -d $0 '$TEMPDIR'/$0' {} \;
+tar czf $DEST -C $TEMPDIR sys
+rm -rf $TEMPDIR
 
-if [ $? -eq 0 ] ; then
-  echo "$DEST successfully created, copy to build system and unpack with:"
-  echo "  tar xfz $DEST"
-else
-  echo "Could not create file $DEST"
-fi
+echo "$DEST successfully created, copy to build system and unpack with:"
+echo "  tar xfz $DEST"
index 7bb0d934b6d87ba2b2a26eb5dfa5dbda815d7264..dbea4f95fc8586224d85633f354e8945dc75bad3 100644 (file)
@@ -139,6 +139,7 @@ Code        Seq#    Include File            Comments
 'm'    all     linux/synclink.h        conflict!
 'm'    00-1F   net/irda/irmod.h        conflict!
 'n'    00-7F   linux/ncp_fs.h
+'n'    80-8F   linux/nilfs2_fs.h       NILFS2
 'n'    E0-FF   video/matrox.h          matroxfb
 'o'    00-1F   fs/ocfs2/ocfs2_fs.h     OCFS2
 'o'     00-03   include/mtd/ubi-user.h  conflict! (OCFS2 and UBI overlaps)
index d08759aa0903c8499c5b422a8161f5cdb900bdcc..7936b801fe6acc8e4dfe0f6f288a2e8ce9e81e08 100644 (file)
@@ -1115,6 +1115,10 @@ and is between 256 and 4096 characters. It is defined in the file
                        libata.dma=4      Compact Flash DMA only 
                        Combinations also work, so libata.dma=3 enables DMA
                        for disks and CDROMs, but not CFs.
+       
+       libata.ignore_hpa=      [LIBATA] Ignore HPA limit
+                       libata.ignore_hpa=0       keep BIOS limits (default)
+                       libata.ignore_hpa=1       ignore limits, using full disk
 
        libata.noacpi   [LIBATA] Disables use of ACPI in libata suspend/resume
                        when set.
@@ -1720,8 +1724,8 @@ and is between 256 and 4096 characters. It is defined in the file
        oprofile.cpu_type=      Force an oprofile cpu type
                        This might be useful if you have an older oprofile
                        userland or if you want common events.
-                       Format: { archperfmon }
-                       archperfmon: [X86] Force use of architectural
+                       Format: { arch_perfmon }
+                       arch_perfmon: [X86] Force use of architectural
                                perfmon on Intel CPUs instead of the
                                CPU specific event set.
 
@@ -1915,6 +1919,12 @@ and is between 256 and 4096 characters. It is defined in the file
                        Format: { 0 | 1 }
                        See arch/parisc/kernel/pdc_chassis.c
 
+       percpu_alloc=   [X86] Select which percpu first chunk allocator to use.
+                       Allowed values are one of "lpage", "embed" and "4k".
+                       See comments in arch/x86/kernel/setup_percpu.c for
+                       details on each allocator.  This parameter is primarily
+                       for debugging and performance comparison.
+
        pf.             [PARIDE]
                        See Documentation/blockdev/paride.txt.
 
@@ -2467,7 +2477,8 @@ and is between 256 and 4096 characters. It is defined in the file
 
        tp720=          [HW,PS2]
 
-       trace_buf_size=nn[KMG] [ftrace] will set tracing buffer size.
+       trace_buf_size=nn[KMG]
+                       [FTRACE] will set tracing buffer size.
 
        trix=           [HW,OSS] MediaTrix AudioTrix Pro
                        Format:
index 0112da3b9ab87f731006993c76e1a7fdc4eddcaa..89068030b01bbdb34392df6bf4fd8782d928ac57 100644 (file)
@@ -16,13 +16,17 @@ Usage
 -----
 
 CONFIG_DEBUG_KMEMLEAK in "Kernel hacking" has to be enabled. A kernel
-thread scans the memory every 10 minutes (by default) and prints any new
-unreferenced objects found. To trigger an intermediate scan and display
-all the possible memory leaks:
+thread scans the memory every 10 minutes (by default) and prints the
+number of new unreferenced objects found. To display the details of all
+the possible memory leaks:
 
   # mount -t debugfs nodev /sys/kernel/debug/
   # cat /sys/kernel/debug/kmemleak
 
+To trigger an intermediate memory scan:
+
+  # echo scan > /sys/kernel/debug/kmemleak
+
 Note that the orphan objects are listed in the order they were allocated
 and one object at the beginning of the list may cause other subsequent
 objects to be reported as orphan.
@@ -31,16 +35,21 @@ Memory scanning parameters can be modified at run-time by writing to the
 /sys/kernel/debug/kmemleak file. The following parameters are supported:
 
   off          - disable kmemleak (irreversible)
-  stack=on     - enable the task stacks scanning
+  stack=on     - enable the task stacks scanning (default)
   stack=off    - disable the tasks stacks scanning
-  scan=on      - start the automatic memory scanning thread
+  scan=on      - start the automatic memory scanning thread (default)
   scan=off     - stop the automatic memory scanning thread
-  scan=<secs>  - set the automatic memory scanning period in seconds (0
-                 to disable it)
+  scan=<secs>  - set the automatic memory scanning period in seconds
+                 (default 600, 0 to stop the automatic scanning)
+  scan         - trigger a memory scan
 
 Kmemleak can also be disabled at boot-time by passing "kmemleak=off" on
 the kernel command line.
 
+Memory may be allocated or freed before kmemleak is initialised and
+these actions are stored in an early log buffer. The size of this buffer
+is configured via the CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE option.
+
 Basic Algorithm
 ---------------
 
index f2296ecedb89d41e6afec1d3ea239256cb4fe768..e2ddcdeb61b6f5caffa1f80f901ebf5619f93dd7 100644 (file)
@@ -36,8 +36,6 @@ detailed description):
        - Bluetooth enable and disable
        - video output switching, expansion control
        - ThinkLight on and off
-       - limited docking and undocking
-       - UltraBay eject
        - CMOS/UCMS control
        - LED control
        - ACPI sounds
@@ -729,131 +727,6 @@ cannot be read or if it is unknown, thinkpad-acpi will report it as "off".
 It is impossible to know if the status returned through sysfs is valid.
 
 
-Docking / undocking -- /proc/acpi/ibm/dock
-------------------------------------------
-
-Docking and undocking (e.g. with the X4 UltraBase) requires some
-actions to be taken by the operating system to safely make or break
-the electrical connections with the dock.
-
-The docking feature of this driver generates the following ACPI events:
-
-       ibm/dock GDCK 00000003 00000001 -- eject request
-       ibm/dock GDCK 00000003 00000002 -- undocked
-       ibm/dock GDCK 00000000 00000003 -- docked
-
-NOTE: These events will only be generated if the laptop was docked
-when originally booted. This is due to the current lack of support for
-hot plugging of devices in the Linux ACPI framework. If the laptop was
-booted while not in the dock, the following message is shown in the
-logs:
-
-       Mar 17 01:42:34 aero kernel: thinkpad_acpi: dock device not present
-
-In this case, no dock-related events are generated but the dock and
-undock commands described below still work. They can be executed
-manually or triggered by Fn key combinations (see the example acpid
-configuration files included in the driver tarball package available
-on the web site).
-
-When the eject request button on the dock is pressed, the first event
-above is generated. The handler for this event should issue the
-following command:
-
-       echo undock > /proc/acpi/ibm/dock
-
-After the LED on the dock goes off, it is safe to eject the laptop.
-Note: if you pressed this key by mistake, go ahead and eject the
-laptop, then dock it back in. Otherwise, the dock may not function as
-expected.
-
-When the laptop is docked, the third event above is generated. The
-handler for this event should issue the following command to fully
-enable the dock:
-
-       echo dock > /proc/acpi/ibm/dock
-
-The contents of the /proc/acpi/ibm/dock file shows the current status
-of the dock, as provided by the ACPI framework.
-
-The docking support in this driver does not take care of enabling or
-disabling any other devices you may have attached to the dock. For
-example, a CD drive plugged into the UltraBase needs to be disabled or
-enabled separately. See the provided example acpid configuration files
-for how this can be accomplished.
-
-There is no support yet for PCI devices that may be attached to a
-docking station, e.g. in the ThinkPad Dock II. The driver currently
-does not recognize, enable or disable such devices. This means that
-the only docking stations currently supported are the X-series
-UltraBase docks and "dumb" port replicators like the Mini Dock (the
-latter don't need any ACPI support, actually).
-
-
-UltraBay eject -- /proc/acpi/ibm/bay
-------------------------------------
-
-Inserting or ejecting an UltraBay device requires some actions to be
-taken by the operating system to safely make or break the electrical
-connections with the device.
-
-This feature generates the following ACPI events:
-
-       ibm/bay MSTR 00000003 00000000 -- eject request
-       ibm/bay MSTR 00000001 00000000 -- eject lever inserted
-
-NOTE: These events will only be generated if the UltraBay was present
-when the laptop was originally booted (on the X series, the UltraBay
-is in the dock, so it may not be present if the laptop was undocked).
-This is due to the current lack of support for hot plugging of devices
-in the Linux ACPI framework. If the laptop was booted without the
-UltraBay, the following message is shown in the logs:
-
-       Mar 17 01:42:34 aero kernel: thinkpad_acpi: bay device not present
-
-In this case, no bay-related events are generated but the eject
-command described below still works. It can be executed manually or
-triggered by a hot key combination.
-
-Sliding the eject lever generates the first event shown above. The
-handler for this event should take whatever actions are necessary to
-shut down the device in the UltraBay (e.g. call idectl), then issue
-the following command:
-
-       echo eject > /proc/acpi/ibm/bay
-
-After the LED on the UltraBay goes off, it is safe to pull out the
-device.
-
-When the eject lever is inserted, the second event above is
-generated. The handler for this event should take whatever actions are
-necessary to enable the UltraBay device (e.g. call idectl).
-
-The contents of the /proc/acpi/ibm/bay file shows the current status
-of the UltraBay, as provided by the ACPI framework.
-
-EXPERIMENTAL warm eject support on the 600e/x, A22p and A3x (To use
-this feature, you need to supply the experimental=1 parameter when
-loading the module):
-
-These models do not have a button near the UltraBay device to request
-a hot eject but rather require the laptop to be put to sleep
-(suspend-to-ram) before the bay device is ejected or inserted).
-The sequence of steps to eject the device is as follows:
-
-       echo eject > /proc/acpi/ibm/bay
-       put the ThinkPad to sleep
-       remove the drive
-       resume from sleep
-       cat /proc/acpi/ibm/bay should show that the drive was removed
-
-On the A3x, both the UltraBay 2000 and UltraBay Plus devices are
-supported. Use "eject2" instead of "eject" for the second bay.
-
-Note: the UltraBay eject support on the 600e/x, A22p and A3x is
-EXPERIMENTAL and may not work as expected. USE WITH CAUTION!
-
-
 CMOS/UCMS control
 -----------------
 
diff --git a/Documentation/leds-lp3944.txt b/Documentation/leds-lp3944.txt
new file mode 100644 (file)
index 0000000..c6eda18
--- /dev/null
@@ -0,0 +1,50 @@
+Kernel driver lp3944
+====================
+
+  * National Semiconductor LP3944 Fun-light Chip
+    Prefix: 'lp3944'
+    Addresses scanned: None (see the Notes section below)
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LP/LP3944.html
+
+Authors:
+        Antonio Ospite <ospite@studenti.unina.it>
+
+
+Description
+-----------
+The LP3944 is a helper chip that can drive up to 8 leds, with two programmable
+DIM modes; it could even be used as a gpio expander but this driver assumes it
+is used as a led controller.
+
+The DIM modes are used to set _blink_ patterns for leds, the pattern is
+specified supplying two parameters:
+  - period: from 0s to 1.6s
+  - duty cycle: percentage of the period the led is on, from 0 to 100
+
+Setting a led in DIM0 or DIM1 mode makes it blink according to the pattern.
+See the datasheet for details.
+
+LP3944 can be found on Motorola A910 smartphone, where it drives the rgb
+leds, the camera flash light and the lcds power.
+
+
+Notes
+-----
+The chip is used mainly in embedded contexts, so this driver expects it is
+registered using the i2c_board_info mechanism.
+
+To register the chip at address 0x60 on adapter 0, set the platform data
+according to include/linux/leds-lp3944.h, set the i2c board info:
+
+       static struct i2c_board_info __initdata a910_i2c_board_info[] = {
+               {
+                       I2C_BOARD_INFO("lp3944", 0x60),
+                       .platform_data = &a910_lp3944_leds,
+               },
+       };
+
+and register it in the platform init function
+
+       i2c_register_board_info(0, a910_i2c_board_info,
+                       ARRAY_SIZE(a910_i2c_board_info));
index 9ebcd6ef361b565fc331bd09c202866f403fcf99..950cde6d6e58384083202b40af0921ef31e0e0ca 100644 (file)
@@ -1,7 +1,9 @@
-/*P:100 This is the Launcher code, a simple program which lays out the
- * "physical" memory for the new Guest by mapping the kernel image and
- * the virtual devices, then opens /dev/lguest to tell the kernel
- * about the Guest and control it. :*/
+/*P:100
+ * This is the Launcher code, a simple program which lays out the "physical"
+ * memory for the new Guest by mapping the kernel image and the virtual
+ * devices, then opens /dev/lguest to tell the kernel about the Guest and
+ * control it.
+:*/
 #define _LARGEFILE64_SOURCE
 #define _GNU_SOURCE
 #include <stdio.h>
 #include "linux/virtio_rng.h"
 #include "linux/virtio_ring.h"
 #include "asm/bootparam.h"
-/*L:110 We can ignore the 39 include files we need for this program, but I do
- * want to draw attention to the use of kernel-style types.
+/*L:110
+ * We can ignore the 42 include files we need for this program, but I do want
+ * to draw attention to the use of kernel-style types.
  *
  * As Linus said, "C is a Spartan language, and so should your naming be."  I
  * like these abbreviations, so we define them here.  Note that u64 is always
  * unsigned long long, which works on all Linux systems: this means that we can
- * use %llu in printf for any u64. */
+ * use %llu in printf for any u64.
+ */
 typedef unsigned long long u64;
 typedef uint32_t u32;
 typedef uint16_t u16;
@@ -69,8 +73,10 @@ typedef uint8_t u8;
 /* This will occupy 3 pages: it must be a power of 2. */
 #define VIRTQUEUE_NUM 256
 
-/*L:120 verbose is both a global flag and a macro.  The C preprocessor allows
- * this, and although I wouldn't recommend it, it works quite nicely here. */
+/*L:120
+ * verbose is both a global flag and a macro.  The C preprocessor allows
+ * this, and although I wouldn't recommend it, it works quite nicely here.
+ */
 static bool verbose;
 #define verbose(args...) \
        do { if (verbose) printf(args); } while(0)
@@ -87,8 +93,7 @@ static int lguest_fd;
 static unsigned int __thread cpu_id;
 
 /* This is our list of devices. */
-struct device_list
-{
+struct device_list {
        /* Counter to assign interrupt numbers. */
        unsigned int next_irq;
 
@@ -100,8 +105,7 @@ struct device_list
 
        /* A single linked list of devices. */
        struct device *dev;
-       /* And a pointer to the last device for easy append and also for
-        * configuration appending. */
+       /* And a pointer to the last device for easy append. */
        struct device *lastdev;
 };
 
@@ -109,8 +113,7 @@ struct device_list
 static struct device_list devices;
 
 /* The device structure describes a single device. */
-struct device
-{
+struct device {
        /* The linked-list pointer. */
        struct device *next;
 
@@ -135,8 +138,7 @@ struct device
 };
 
 /* The virtqueue structure describes a queue attached to a device. */
-struct virtqueue
-{
+struct virtqueue {
        struct virtqueue *next;
 
        /* Which device owns me. */
@@ -168,20 +170,24 @@ static char **main_args;
 /* The original tty settings to restore on exit. */
 static struct termios orig_term;
 
-/* We have to be careful with barriers: our devices are all run in separate
+/*
+ * We have to be careful with barriers: our devices are all run in separate
  * threads and so we need to make sure that changes visible to the Guest happen
- * in precise order. */
+ * in precise order.
+ */
 #define wmb() __asm__ __volatile__("" : : : "memory")
 #define mb() __asm__ __volatile__("" : : : "memory")
 
-/* Convert an iovec element to the given type.
+/*
+ * Convert an iovec element to the given type.
  *
  * This is a fairly ugly trick: we need to know the size of the type and
  * alignment requirement to check the pointer is kosher.  It's also nice to
  * have the name of the type in case we report failure.
  *
  * Typing those three things all the time is cumbersome and error prone, so we
- * have a macro which sets them all up and passes to the real function. */
+ * have a macro which sets them all up and passes to the real function.
+ */
 #define convert(iov, type) \
        ((type *)_convert((iov), sizeof(type), __alignof__(type), #type))
 
@@ -198,8 +204,10 @@ static void *_convert(struct iovec *iov, size_t size, size_t align,
 /* Wrapper for the last available index.  Makes it easier to change. */
 #define lg_last_avail(vq)      ((vq)->last_avail_idx)
 
-/* The virtio configuration space is defined to be little-endian.  x86 is
- * little-endian too, but it's nice to be explicit so we have these helpers. */
+/*
+ * The virtio configuration space is defined to be little-endian.  x86 is
+ * little-endian too, but it's nice to be explicit so we have these helpers.
+ */
 #define cpu_to_le16(v16) (v16)
 #define cpu_to_le32(v32) (v32)
 #define cpu_to_le64(v64) (v64)
@@ -241,11 +249,12 @@ static u8 *get_feature_bits(struct device *dev)
                + dev->num_vq * sizeof(struct lguest_vqconfig);
 }
 
-/*L:100 The Launcher code itself takes us out into userspace, that scary place
- * where pointers run wild and free!  Unfortunately, like most userspace
- * programs, it's quite boring (which is why everyone likes to hack on the
- * kernel!).  Perhaps if you make up an Lguest Drinking Game at this point, it
- * will get you through this section.  Or, maybe not.
+/*L:100
+ * The Launcher code itself takes us out into userspace, that scary place where
+ * pointers run wild and free!  Unfortunately, like most userspace programs,
+ * it's quite boring (which is why everyone likes to hack on the kernel!).
+ * Perhaps if you make up an Lguest Drinking Game at this point, it will get
+ * you through this section.  Or, maybe not.
  *
  * The Launcher sets up a big chunk of memory to be the Guest's "physical"
  * memory and stores it in "guest_base".  In other words, Guest physical ==
@@ -253,7 +262,8 @@ static u8 *get_feature_bits(struct device *dev)
  *
  * This can be tough to get your head around, but usually it just means that we
  * use these trivial conversion functions when the Guest gives us it's
- * "physical" addresses: */
+ * "physical" addresses:
+ */
 static void *from_guest_phys(unsigned long addr)
 {
        return guest_base + addr;
@@ -268,7 +278,8 @@ static unsigned long to_guest_phys(const void *addr)
  * Loading the Kernel.
  *
  * We start with couple of simple helper routines.  open_or_die() avoids
- * error-checking code cluttering the callers: */
+ * error-checking code cluttering the callers:
+ */
 static int open_or_die(const char *name, int flags)
 {
        int fd = open(name, flags);
@@ -283,12 +294,19 @@ static void *map_zeroed_pages(unsigned int num)
        int fd = open_or_die("/dev/zero", O_RDONLY);
        void *addr;
 
-       /* We use a private mapping (ie. if we write to the page, it will be
-        * copied). */
+       /*
+        * We use a private mapping (ie. if we write to the page, it will be
+        * copied).
+        */
        addr = mmap(NULL, getpagesize() * num,
                    PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0);
        if (addr == MAP_FAILED)
                err(1, "Mmaping %u pages of /dev/zero", num);
+
+       /*
+        * One neat mmap feature is that you can close the fd, and it
+        * stays mapped.
+        */
        close(fd);
 
        return addr;
@@ -305,20 +323,24 @@ static void *get_pages(unsigned int num)
        return addr;
 }
 
-/* This routine is used to load the kernel or initrd.  It tries mmap, but if
+/*
+ * This routine is used to load the kernel or initrd.  It tries mmap, but if
  * that fails (Plan 9's kernel file isn't nicely aligned on page boundaries),
- * it falls back to reading the memory in. */
+ * it falls back to reading the memory in.
+ */
 static void map_at(int fd, void *addr, unsigned long offset, unsigned long len)
 {
        ssize_t r;
 
-       /* We map writable even though for some segments are marked read-only.
+       /*
+        * We map writable even though for some segments are marked read-only.
         * The kernel really wants to be writable: it patches its own
         * instructions.
         *
         * MAP_PRIVATE means that the page won't be copied until a write is
         * done to it.  This allows us to share untouched memory between
-        * Guests. */
+        * Guests.
+        */
        if (mmap(addr, len, PROT_READ|PROT_WRITE|PROT_EXEC,
                 MAP_FIXED|MAP_PRIVATE, fd, offset) != MAP_FAILED)
                return;
@@ -329,7 +351,8 @@ static void map_at(int fd, void *addr, unsigned long offset, unsigned long len)
                err(1, "Reading offset %lu len %lu gave %zi", offset, len, r);
 }
 
-/* This routine takes an open vmlinux image, which is in ELF, and maps it into
+/*
+ * This routine takes an open vmlinux image, which is in ELF, and maps it into
  * the Guest memory.  ELF = Embedded Linking Format, which is the format used
  * by all modern binaries on Linux including the kernel.
  *
@@ -337,23 +360,28 @@ static void map_at(int fd, void *addr, unsigned long offset, unsigned long len)
  * address.  We use the physical address; the Guest will map itself to the
  * virtual address.
  *
- * We return the starting address. */
+ * We return the starting address.
+ */
 static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr)
 {
        Elf32_Phdr phdr[ehdr->e_phnum];
        unsigned int i;
 
-       /* Sanity checks on the main ELF header: an x86 executable with a
-        * reasonable number of correctly-sized program headers. */
+       /*
+        * Sanity checks on the main ELF header: an x86 executable with a
+        * reasonable number of correctly-sized program headers.
+        */
        if (ehdr->e_type != ET_EXEC
            || ehdr->e_machine != EM_386
            || ehdr->e_phentsize != sizeof(Elf32_Phdr)
            || ehdr->e_phnum < 1 || ehdr->e_phnum > 65536U/sizeof(Elf32_Phdr))
                errx(1, "Malformed elf header");
 
-       /* An ELF executable contains an ELF header and a number of "program"
+       /*
+        * An ELF executable contains an ELF header and a number of "program"
         * headers which indicate which parts ("segments") of the program to
-        * load where. */
+        * load where.
+        */
 
        /* We read in all the program headers at once: */
        if (lseek(elf_fd, ehdr->e_phoff, SEEK_SET) < 0)
@@ -361,8 +389,10 @@ static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr)
        if (read(elf_fd, phdr, sizeof(phdr)) != sizeof(phdr))
                err(1, "Reading program headers");
 
-       /* Try all the headers: there are usually only three.  A read-only one,
-        * a read-write one, and a "note" section which we don't load. */
+       /*
+        * Try all the headers: there are usually only three.  A read-only one,
+        * a read-write one, and a "note" section which we don't load.
+        */
        for (i = 0; i < ehdr->e_phnum; i++) {
                /* If this isn't a loadable segment, we ignore it */
                if (phdr[i].p_type != PT_LOAD)
@@ -380,13 +410,15 @@ static unsigned long map_elf(int elf_fd, const Elf32_Ehdr *ehdr)
        return ehdr->e_entry;
 }
 
-/*L:150 A bzImage, unlike an ELF file, is not meant to be loaded.  You're
- * supposed to jump into it and it will unpack itself.  We used to have to
- * perform some hairy magic because the unpacking code scared me.
+/*L:150
+ * A bzImage, unlike an ELF file, is not meant to be loaded.  You're supposed
+ * to jump into it and it will unpack itself.  We used to have to perform some
+ * hairy magic because the unpacking code scared me.
  *
  * Fortunately, Jeremy Fitzhardinge convinced me it wasn't that hard and wrote
  * a small patch to jump over the tricky bits in the Guest, so now we just read
- * the funky header so we know where in the file to load, and away we go! */
+ * the funky header so we know where in the file to load, and away we go!
+ */
 static unsigned long load_bzimage(int fd)
 {
        struct boot_params boot;
@@ -394,8 +426,10 @@ static unsigned long load_bzimage(int fd)
        /* Modern bzImages get loaded at 1M. */
        void *p = from_guest_phys(0x100000);
 
-       /* Go back to the start of the file and read the header.  It should be
-        * a Linux boot header (see Documentation/x86/i386/boot.txt) */
+       /*
+        * Go back to the start of the file and read the header.  It should be
+        * a Linux boot header (see Documentation/x86/i386/boot.txt)
+        */
        lseek(fd, 0, SEEK_SET);
        read(fd, &boot, sizeof(boot));
 
@@ -414,9 +448,11 @@ static unsigned long load_bzimage(int fd)
        return boot.hdr.code32_start;
 }
 
-/*L:140 Loading the kernel is easy when it's a "vmlinux", but most kernels
+/*L:140
+ * Loading the kernel is easy when it's a "vmlinux", but most kernels
  * come wrapped up in the self-decompressing "bzImage" format.  With a little
- * work, we can load those, too. */
+ * work, we can load those, too.
+ */
 static unsigned long load_kernel(int fd)
 {
        Elf32_Ehdr hdr;
@@ -433,24 +469,28 @@ static unsigned long load_kernel(int fd)
        return load_bzimage(fd);
 }
 
-/* This is a trivial little helper to align pages.  Andi Kleen hated it because
+/*
+ * This is a trivial little helper to align pages.  Andi Kleen hated it because
  * it calls getpagesize() twice: "it's dumb code."
  *
  * Kernel guys get really het up about optimization, even when it's not
- * necessary.  I leave this code as a reaction against that. */
+ * necessary.  I leave this code as a reaction against that.
+ */
 static inline unsigned long page_align(unsigned long addr)
 {
        /* Add upwards and truncate downwards. */
        return ((addr + getpagesize()-1) & ~(getpagesize()-1));
 }
 
-/*L:180 An "initial ram disk" is a disk image loaded into memory along with
- * the kernel which the kernel can use to boot from without needing any
- * drivers.  Most distributions now use this as standard: the initrd contains
- * the code to load the appropriate driver modules for the current machine.
+/*L:180
+ * An "initial ram disk" is a disk image loaded into memory along with the
+ * kernel which the kernel can use to boot from without needing any drivers.
+ * Most distributions now use this as standard: the initrd contains the code to
+ * load the appropriate driver modules for the current machine.
  *
  * Importantly, James Morris works for RedHat, and Fedora uses initrds for its
- * kernels.  He sent me this (and tells me when I break it). */
+ * kernels.  He sent me this (and tells me when I break it).
+ */
 static unsigned long load_initrd(const char *name, unsigned long mem)
 {
        int ifd;
@@ -462,12 +502,16 @@ static unsigned long load_initrd(const char *name, unsigned long mem)
        if (fstat(ifd, &st) < 0)
                err(1, "fstat() on initrd '%s'", name);
 
-       /* We map the initrd at the top of memory, but mmap wants it to be
-        * page-aligned, so we round the size up for that. */
+       /*
+        * We map the initrd at the top of memory, but mmap wants it to be
+        * page-aligned, so we round the size up for that.
+        */
        len = page_align(st.st_size);
        map_at(ifd, from_guest_phys(mem - len), 0, st.st_size);
-       /* Once a file is mapped, you can close the file descriptor.  It's a
-        * little odd, but quite useful. */
+       /*
+        * Once a file is mapped, you can close the file descriptor.  It's a
+        * little odd, but quite useful.
+        */
        close(ifd);
        verbose("mapped initrd %s size=%lu @ %p\n", name, len, (void*)mem-len);
 
@@ -476,8 +520,10 @@ static unsigned long load_initrd(const char *name, unsigned long mem)
 }
 /*:*/
 
-/* Simple routine to roll all the commandline arguments together with spaces
- * between them. */
+/*
+ * Simple routine to roll all the commandline arguments together with spaces
+ * between them.
+ */
 static void concat(char *dst, char *args[])
 {
        unsigned int i, len = 0;
@@ -494,10 +540,12 @@ static void concat(char *dst, char *args[])
        dst[len] = '\0';
 }
 
-/*L:185 This is where we actually tell the kernel to initialize the Guest.  We
+/*L:185
+ * This is where we actually tell the kernel to initialize the Guest.  We
  * saw the arguments it expects when we looked at initialize() in lguest_user.c:
  * the base of Guest "physical" memory, the top physical page to allow and the
- * entry point for the Guest. */
+ * entry point for the Guest.
+ */
 static void tell_kernel(unsigned long start)
 {
        unsigned long args[] = { LHREQ_INITIALIZE,
@@ -511,7 +559,7 @@ static void tell_kernel(unsigned long start)
 }
 /*:*/
 
-/*
+/*L:200
  * Device Handling.
  *
  * When the Guest gives us a buffer, it sends an array of addresses and sizes.
@@ -522,20 +570,26 @@ static void tell_kernel(unsigned long start)
 static void *_check_pointer(unsigned long addr, unsigned int size,
                            unsigned int line)
 {
-       /* We have to separately check addr and addr+size, because size could
-        * be huge and addr + size might wrap around. */
+       /*
+        * We have to separately check addr and addr+size, because size could
+        * be huge and addr + size might wrap around.
+        */
        if (addr >= guest_limit || addr + size >= guest_limit)
                errx(1, "%s:%i: Invalid address %#lx", __FILE__, line, addr);
-       /* We return a pointer for the caller's convenience, now we know it's
-        * safe to use. */
+       /*
+        * We return a pointer for the caller's convenience, now we know it's
+        * safe to use.
+        */
        return from_guest_phys(addr);
 }
 /* A macro which transparently hands the line number to the real function. */
 #define check_pointer(addr,size) _check_pointer(addr, size, __LINE__)
 
-/* Each buffer in the virtqueues is actually a chain of descriptors.  This
+/*
+ * Each buffer in the virtqueues is actually a chain of descriptors.  This
  * function returns the next descriptor in the chain, or vq->vring.num if we're
- * at the end. */
+ * at the end.
+ */
 static unsigned next_desc(struct vring_desc *desc,
                          unsigned int i, unsigned int max)
 {
@@ -556,7 +610,10 @@ static unsigned next_desc(struct vring_desc *desc,
        return next;
 }
 
-/* This actually sends the interrupt for this virtqueue */
+/*
+ * This actually sends the interrupt for this virtqueue, if we've used a
+ * buffer.
+ */
 static void trigger_irq(struct virtqueue *vq)
 {
        unsigned long buf[] = { LHREQ_IRQ, vq->config.irq };
@@ -576,12 +633,14 @@ static void trigger_irq(struct virtqueue *vq)
                err(1, "Triggering irq %i", vq->config.irq);
 }
 
-/* This looks in the virtqueue and for the first available buffer, and converts
+/*
+ * This looks in the virtqueue for the first available buffer, and converts
  * it to an iovec for convenient access.  Since descriptors consist of some
  * number of output then some number of input descriptors, it's actually two
  * iovecs, but we pack them into one and note how many of each there were.
  *
- * This function returns the descriptor number found. */
+ * This function waits if necessary, and returns the descriptor number found.
+ */
 static unsigned wait_for_vq_desc(struct virtqueue *vq,
                                 struct iovec iov[],
                                 unsigned int *out_num, unsigned int *in_num)
@@ -590,17 +649,23 @@ static unsigned wait_for_vq_desc(struct virtqueue *vq,
        struct vring_desc *desc;
        u16 last_avail = lg_last_avail(vq);
 
+       /* There's nothing available? */
        while (last_avail == vq->vring.avail->idx) {
                u64 event;
 
-               /* OK, tell Guest about progress up to now. */
+               /*
+                * Since we're about to sleep, now is a good time to tell the
+                * Guest about what we've used up to now.
+                */
                trigger_irq(vq);
 
                /* OK, now we need to know about added descriptors. */
                vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
 
-               /* They could have slipped one in as we were doing that: make
-                * sure it's written, then check again. */
+               /*
+                * They could have slipped one in as we were doing that: make
+                * sure it's written, then check again.
+                */
                mb();
                if (last_avail != vq->vring.avail->idx) {
                        vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
@@ -620,8 +685,10 @@ static unsigned wait_for_vq_desc(struct virtqueue *vq,
                errx(1, "Guest moved used index from %u to %u",
                     last_avail, vq->vring.avail->idx);
 
-       /* Grab the next descriptor number they're advertising, and increment
-        * the index we've seen. */
+       /*
+        * Grab the next descriptor number they're advertising, and increment
+        * the index we've seen.
+        */
        head = vq->vring.avail->ring[last_avail % vq->vring.num];
        lg_last_avail(vq)++;
 
@@ -636,8 +703,10 @@ static unsigned wait_for_vq_desc(struct virtqueue *vq,
        desc = vq->vring.desc;
        i = head;
 
-       /* If this is an indirect entry, then this buffer contains a descriptor
-        * table which we handle as if it's any normal descriptor chain. */
+       /*
+        * If this is an indirect entry, then this buffer contains a descriptor
+        * table which we handle as if it's any normal descriptor chain.
+        */
        if (desc[i].flags & VRING_DESC_F_INDIRECT) {
                if (desc[i].len % sizeof(struct vring_desc))
                        errx(1, "Invalid size for indirect buffer table");
@@ -656,8 +725,10 @@ static unsigned wait_for_vq_desc(struct virtqueue *vq,
                if (desc[i].flags & VRING_DESC_F_WRITE)
                        (*in_num)++;
                else {
-                       /* If it's an output descriptor, they're all supposed
-                        * to come before any input descriptors. */
+                       /*
+                        * If it's an output descriptor, they're all supposed
+                        * to come before any input descriptors.
+                        */
                        if (*in_num)
                                errx(1, "Descriptor has out after in");
                        (*out_num)++;
@@ -671,14 +742,19 @@ static unsigned wait_for_vq_desc(struct virtqueue *vq,
        return head;
 }
 
-/* After we've used one of their buffers, we tell them about it.  We'll then
- * want to send them an interrupt, using trigger_irq(). */
+/*
+ * After we've used one of their buffers, we tell the Guest about it.  Sometime
+ * later we'll want to send them an interrupt using trigger_irq(); note that
+ * wait_for_vq_desc() does that for us if it has to wait.
+ */
 static void add_used(struct virtqueue *vq, unsigned int head, int len)
 {
        struct vring_used_elem *used;
 
-       /* The virtqueue contains a ring of used buffers.  Get a pointer to the
-        * next entry in that used ring. */
+       /*
+        * The virtqueue contains a ring of used buffers.  Get a pointer to the
+        * next entry in that used ring.
+        */
        used = &vq->vring.used->ring[vq->vring.used->idx % vq->vring.num];
        used->id = head;
        used->len = len;
@@ -698,9 +774,9 @@ static void add_used_and_trigger(struct virtqueue *vq, unsigned head, int len)
 /*
  * The Console
  *
- * We associate some data with the console for our exit hack. */
-struct console_abort
-{
+ * We associate some data with the console for our exit hack.
+ */
+struct console_abort {
        /* How many times have they hit ^C? */
        int count;
        /* When did they start? */
@@ -715,30 +791,35 @@ static void console_input(struct virtqueue *vq)
        struct console_abort *abort = vq->dev->priv;
        struct iovec iov[vq->vring.num];
 
-       /* Make sure there's a descriptor waiting. */
+       /* Make sure there's a descriptor available. */
        head = wait_for_vq_desc(vq, iov, &out_num, &in_num);
        if (out_num)
                errx(1, "Output buffers in console in queue?");
 
-       /* Read it in. */
+       /* Read into it.  This is where we usually wait. */
        len = readv(STDIN_FILENO, iov, in_num);
        if (len <= 0) {
                /* Ran out of input? */
                warnx("Failed to get console input, ignoring console.");
-               /* For simplicity, dying threads kill the whole Launcher.  So
-                * just nap here. */
+               /*
+                * For simplicity, dying threads kill the whole Launcher.  So
+                * just nap here.
+                */
                for (;;)
                        pause();
        }
 
+       /* Tell the Guest we used a buffer. */
        add_used_and_trigger(vq, head, len);
 
-       /* Three ^C within one second?  Exit.
+       /*
+        * Three ^C within one second?  Exit.
         *
         * This is such a hack, but works surprisingly well.  Each ^C has to
         * be in a buffer by itself, so they can't be too fast.  But we check
         * that we get three within about a second, so they can't be too
-        * slow. */
+        * slow.
+        */
        if (len != 1 || ((char *)iov[0].iov_base)[0] != 3) {
                abort->count = 0;
                return;
@@ -763,15 +844,23 @@ static void console_output(struct virtqueue *vq)
        unsigned int head, out, in;
        struct iovec iov[vq->vring.num];
 
+       /* We usually wait in here, for the Guest to give us something. */
        head = wait_for_vq_desc(vq, iov, &out, &in);
        if (in)
                errx(1, "Input buffers in console output queue?");
+
+       /* writev can return a partial write, so we loop here. */
        while (!iov_empty(iov, out)) {
                int len = writev(STDOUT_FILENO, iov, out);
                if (len <= 0)
                        err(1, "Write to stdout gave %i", len);
                iov_consume(iov, out, len);
        }
+
+       /*
+        * We're finished with that buffer: if we're going to sleep,
+        * wait_for_vq_desc() will prod the Guest with an interrupt.
+        */
        add_used(vq, head, 0);
 }
 
@@ -791,15 +880,30 @@ static void net_output(struct virtqueue *vq)
        unsigned int head, out, in;
        struct iovec iov[vq->vring.num];
 
+       /* We usually wait in here for the Guest to give us a packet. */
        head = wait_for_vq_desc(vq, iov, &out, &in);
        if (in)
                errx(1, "Input buffers in net output queue?");
+       /*
+        * Send the whole thing through to /dev/net/tun.  It expects the exact
+        * same format: what a coincidence!
+        */
        if (writev(net_info->tunfd, iov, out) < 0)
                errx(1, "Write to tun failed?");
+
+       /*
+        * Done with that one; wait_for_vq_desc() will send the interrupt if
+        * all packets are processed.
+        */
        add_used(vq, head, 0);
 }
 
-/* Will reading from this file descriptor block? */
+/*
+ * Handling network input is a bit trickier, because I've tried to optimize it.
+ *
+ * First we have a helper routine which tells is if from this file descriptor
+ * (ie. the /dev/net/tun device) will block:
+ */
 static bool will_block(int fd)
 {
        fd_set fdset;
@@ -809,8 +913,11 @@ static bool will_block(int fd)
        return select(fd+1, &fdset, NULL, NULL, &zero) != 1;
 }
 
-/* This is where we handle packets coming in from the tun device to our
- * Guest. */
+/*
+ * This handles packets coming in from the tun device to our Guest.  Like all
+ * service routines, it gets called again as soon as it returns, so you don't
+ * see a while(1) loop here.
+ */
 static void net_input(struct virtqueue *vq)
 {
        int len;
@@ -818,21 +925,38 @@ static void net_input(struct virtqueue *vq)
        struct iovec iov[vq->vring.num];
        struct net_info *net_info = vq->dev->priv;
 
+       /*
+        * Get a descriptor to write an incoming packet into.  This will also
+        * send an interrupt if they're out of descriptors.
+        */
        head = wait_for_vq_desc(vq, iov, &out, &in);
        if (out)
                errx(1, "Output buffers in net input queue?");
 
-       /* Deliver interrupt now, since we're about to sleep. */
+       /*
+        * If it looks like we'll block reading from the tun device, send them
+        * an interrupt.
+        */
        if (vq->pending_used && will_block(net_info->tunfd))
                trigger_irq(vq);
 
+       /*
+        * Read in the packet.  This is where we normally wait (when there's no
+        * incoming network traffic).
+        */
        len = readv(net_info->tunfd, iov, in);
        if (len <= 0)
                err(1, "Failed to read from tun.");
+
+       /*
+        * Mark that packet buffer as used, but don't interrupt here.  We want
+        * to wait until we've done as much work as we can.
+        */
        add_used(vq, head, len);
 }
+/*:*/
 
-/* This is the helper to create threads. */
+/* This is the helper to create threads: run the service routine in a loop. */
 static int do_thread(void *_vq)
 {
        struct virtqueue *vq = _vq;
@@ -842,8 +966,10 @@ static int do_thread(void *_vq)
        return 0;
 }
 
-/* When a child dies, we kill our entire process group with SIGTERM.  This
- * also has the side effect that the shell restores the console for us! */
+/*
+ * When a child dies, we kill our entire process group with SIGTERM.  This
+ * also has the side effect that the shell restores the console for us!
+ */
 static void kill_launcher(int signal)
 {
        kill(0, SIGTERM);
@@ -878,11 +1004,15 @@ static void reset_device(struct device *dev)
        signal(SIGCHLD, (void *)kill_launcher);
 }
 
+/*L:216
+ * This actually creates the thread which services the virtqueue for a device.
+ */
 static void create_thread(struct virtqueue *vq)
 {
-       /* Create stack for thread and run it.  Since stack grows
-        * upwards, we point the stack pointer to the end of this
-        * region. */
+       /*
+        * Create stack for thread.  Since the stack grows upwards, we point
+        * the stack pointer to the end of this region.
+        */
        char *stack = malloc(32768);
        unsigned long args[] = { LHREQ_EVENTFD,
                                 vq->config.pfn*getpagesize(), 0 };
@@ -893,17 +1023,22 @@ static void create_thread(struct virtqueue *vq)
                err(1, "Creating eventfd");
        args[2] = vq->eventfd;
 
-       /* Attach an eventfd to this virtqueue: it will go off
-        * when the Guest does an LHCALL_NOTIFY for this vq. */
+       /*
+        * Attach an eventfd to this virtqueue: it will go off when the Guest
+        * does an LHCALL_NOTIFY for this vq.
+        */
        if (write(lguest_fd, &args, sizeof(args)) != 0)
                err(1, "Attaching eventfd");
 
-       /* CLONE_VM: because it has to access the Guest memory, and
-        * SIGCHLD so we get a signal if it dies. */
+       /*
+        * CLONE_VM: because it has to access the Guest memory, and SIGCHLD so
+        * we get a signal if it dies.
+        */
        vq->thread = clone(do_thread, stack + 32768, CLONE_VM | SIGCHLD, vq);
        if (vq->thread == (pid_t)-1)
                err(1, "Creating clone");
-       /* We close our local copy, now the child has it. */
+
+       /* We close our local copy now the child has it. */
        close(vq->eventfd);
 }
 
@@ -955,7 +1090,10 @@ static void update_device_status(struct device *dev)
        }
 }
 
-/* This is the generic routine we call when the Guest uses LHCALL_NOTIFY. */
+/*L:215
+ * This is the generic routine we call when the Guest uses LHCALL_NOTIFY.  In
+ * particular, it's used to notify us of device status changes during boot.
+ */
 static void handle_output(unsigned long addr)
 {
        struct device *i;
@@ -964,25 +1102,42 @@ static void handle_output(unsigned long addr)
        for (i = devices.dev; i; i = i->next) {
                struct virtqueue *vq;
 
-               /* Notifications to device descriptors update device status. */
+               /*
+                * Notifications to device descriptors mean they updated the
+                * device status.
+                */
                if (from_guest_phys(addr) == i->desc) {
                        update_device_status(i);
                        return;
                }
 
-               /* Devices *can* be used before status is set to DRIVER_OK. */
+               /*
+                * Devices *can* be used before status is set to DRIVER_OK.
+                * The original plan was that they would never do this: they
+                * would always finish setting up their status bits before
+                * actually touching the virtqueues.  In practice, we allowed
+                * them to, and they do (eg. the disk probes for partition
+                * tables as part of initialization).
+                *
+                * If we see this, we start the device: once it's running, we
+                * expect the device to catch all the notifications.
+                */
                for (vq = i->vq; vq; vq = vq->next) {
                        if (addr != vq->config.pfn*getpagesize())
                                continue;
                        if (i->running)
                                errx(1, "Notification on running %s", i->name);
+                       /* This just calls create_thread() for each virtqueue */
                        start_device(i);
                        return;
                }
        }
 
-       /* Early console write is done using notify on a nul-terminated string
-        * in Guest memory. */
+       /*
+        * Early console write is done using notify on a nul-terminated string
+        * in Guest memory.  It's also great for hacking debugging messages
+        * into a Guest.
+        */
        if (addr >= guest_limit)
                errx(1, "Bad NOTIFY %#lx", addr);
 
@@ -998,10 +1153,12 @@ static void handle_output(unsigned long addr)
  * routines to allocate and manage them.
  */
 
-/* The layout of the device page is a "struct lguest_device_desc" followed by a
+/*
+ * The layout of the device page is a "struct lguest_device_desc" followed by a
  * number of virtqueue descriptors, then two sets of feature bits, then an
  * array of configuration bytes.  This routine returns the configuration
- * pointer. */
+ * pointer.
+ */
 static u8 *device_config(const struct device *dev)
 {
        return (void *)(dev->desc + 1)
@@ -1009,9 +1166,11 @@ static u8 *device_config(const struct device *dev)
                + dev->feature_len * 2;
 }
 
-/* This routine allocates a new "struct lguest_device_desc" from descriptor
+/*
+ * This routine allocates a new "struct lguest_device_desc" from descriptor
  * table page just above the Guest's normal memory.  It returns a pointer to
- * that descriptor. */
+ * that descriptor.
+ */
 static struct lguest_device_desc *new_dev_desc(u16 type)
 {
        struct lguest_device_desc d = { .type = type };
@@ -1032,8 +1191,10 @@ static struct lguest_device_desc *new_dev_desc(u16 type)
        return memcpy(p, &d, sizeof(d));
 }
 
-/* Each device descriptor is followed by the description of its virtqueues.  We
- * specify how many descriptors the virtqueue is to have. */
+/*
+ * Each device descriptor is followed by the description of its virtqueues.  We
+ * specify how many descriptors the virtqueue is to have.
+ */
 static void add_virtqueue(struct device *dev, unsigned int num_descs,
                          void (*service)(struct virtqueue *))
 {
@@ -1050,6 +1211,11 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs,
        vq->next = NULL;
        vq->last_avail_idx = 0;
        vq->dev = dev;
+
+       /*
+        * This is the routine the service thread will run, and its Process ID
+        * once it's running.
+        */
        vq->service = service;
        vq->thread = (pid_t)-1;
 
@@ -1061,10 +1227,12 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs,
        /* Initialize the vring. */
        vring_init(&vq->vring, num_descs, p, LGUEST_VRING_ALIGN);
 
-       /* Append virtqueue to this device's descriptor.  We use
+       /*
+        * Append virtqueue to this device's descriptor.  We use
         * device_config() to get the end of the device's current virtqueues;
         * we check that we haven't added any config or feature information
-        * yet, otherwise we'd be overwriting them. */
+        * yet, otherwise we'd be overwriting them.
+        */
        assert(dev->desc->config_len == 0 && dev->desc->feature_len == 0);
        memcpy(device_config(dev), &vq->config, sizeof(vq->config));
        dev->num_vq++;
@@ -1072,14 +1240,18 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs,
 
        verbose("Virtqueue page %#lx\n", to_guest_phys(p));
 
-       /* Add to tail of list, so dev->vq is first vq, dev->vq->next is
-        * second.  */
+       /*
+        * Add to tail of list, so dev->vq is first vq, dev->vq->next is
+        * second.
+        */
        for (i = &dev->vq; *i; i = &(*i)->next);
        *i = vq;
 }
 
-/* The first half of the feature bitmask is for us to advertise features.  The
- * second half is for the Guest to accept features. */
+/*
+ * The first half of the feature bitmask is for us to advertise features.  The
+ * second half is for the Guest to accept features.
+ */
 static void add_feature(struct device *dev, unsigned bit)
 {
        u8 *features = get_feature_bits(dev);
@@ -1093,9 +1265,11 @@ static void add_feature(struct device *dev, unsigned bit)
        features[bit / CHAR_BIT] |= (1 << (bit % CHAR_BIT));
 }
 
-/* This routine sets the configuration fields for an existing device's
+/*
+ * This routine sets the configuration fields for an existing device's
  * descriptor.  It only works for the last device, but that's OK because that's
- * how we use it. */
+ * how we use it.
+ */
 static void set_config(struct device *dev, unsigned len, const void *conf)
 {
        /* Check we haven't overflowed our single page. */
@@ -1105,12 +1279,18 @@ static void set_config(struct device *dev, unsigned len, const void *conf)
        /* Copy in the config information, and store the length. */
        memcpy(device_config(dev), conf, len);
        dev->desc->config_len = len;
+
+       /* Size must fit in config_len field (8 bits)! */
+       assert(dev->desc->config_len == len);
 }
 
-/* This routine does all the creation and setup of a new device, including
- * calling new_dev_desc() to allocate the descriptor and device memory.
+/*
+ * This routine does all the creation and setup of a new device, including
+ * calling new_dev_desc() to allocate the descriptor and device memory.  We
+ * don't actually start the service threads until later.
  *
- * See what I mean about userspace being boring? */
+ * See what I mean about userspace being boring?
+ */
 static struct device *new_device(const char *name, u16 type)
 {
        struct device *dev = malloc(sizeof(*dev));
@@ -1123,10 +1303,12 @@ static struct device *new_device(const char *name, u16 type)
        dev->num_vq = 0;
        dev->running = false;
 
-       /* Append to device list.  Prepending to a single-linked list is
+       /*
+        * Append to device list.  Prepending to a single-linked list is
         * easier, but the user expects the devices to be arranged on the bus
         * in command-line order.  The first network device on the command line
-        * is eth0, the first block device /dev/vda, etc. */
+        * is eth0, the first block device /dev/vda, etc.
+        */
        if (devices.lastdev)
                devices.lastdev->next = dev;
        else
@@ -1136,8 +1318,10 @@ static struct device *new_device(const char *name, u16 type)
        return dev;
 }
 
-/* Our first setup routine is the console.  It's a fairly simple device, but
- * UNIX tty handling makes it uglier than it could be. */
+/*
+ * Our first setup routine is the console.  It's a fairly simple device, but
+ * UNIX tty handling makes it uglier than it could be.
+ */
 static void setup_console(void)
 {
        struct device *dev;
@@ -1145,8 +1329,10 @@ static void setup_console(void)
        /* If we can save the initial standard input settings... */
        if (tcgetattr(STDIN_FILENO, &orig_term) == 0) {
                struct termios term = orig_term;
-               /* Then we turn off echo, line buffering and ^C etc.  We want a
-                * raw input stream to the Guest. */
+               /*
+                * Then we turn off echo, line buffering and ^C etc: We want a
+                * raw input stream to the Guest.
+                */
                term.c_lflag &= ~(ISIG|ICANON|ECHO);
                tcsetattr(STDIN_FILENO, TCSANOW, &term);
        }
@@ -1157,10 +1343,12 @@ static void setup_console(void)
        dev->priv = malloc(sizeof(struct console_abort));
        ((struct console_abort *)dev->priv)->count = 0;
 
-       /* The console needs two virtqueues: the input then the output.  When
+       /*
+        * The console needs two virtqueues: the input then the output.  When
         * they put something the input queue, we make sure we're listening to
         * stdin.  When they put something in the output queue, we write it to
-        * stdout. */
+        * stdout.
+        */
        add_virtqueue(dev, VIRTQUEUE_NUM, console_input);
        add_virtqueue(dev, VIRTQUEUE_NUM, console_output);
 
@@ -1168,7 +1356,8 @@ static void setup_console(void)
 }
 /*:*/
 
-/*M:010 Inter-guest networking is an interesting area.  Simplest is to have a
+/*M:010
+ * Inter-guest networking is an interesting area.  Simplest is to have a
  * --sharenet=<name> option which opens or creates a named pipe.  This can be
  * used to send packets to another guest in a 1:1 manner.
  *
@@ -1182,7 +1371,8 @@ static void setup_console(void)
  * multiple inter-guest channels behind one interface, although it would
  * require some manner of hotplugging new virtio channels.
  *
- * Finally, we could implement a virtio network switch in the kernel. :*/
+ * Finally, we could implement a virtio network switch in the kernel.
+:*/
 
 static u32 str2ip(const char *ipaddr)
 {
@@ -1207,11 +1397,13 @@ static void str2mac(const char *macaddr, unsigned char mac[6])
        mac[5] = m[5];
 }
 
-/* This code is "adapted" from libbridge: it attaches the Host end of the
+/*
+ * This code is "adapted" from libbridge: it attaches the Host end of the
  * network device to the bridge device specified by the command line.
  *
  * This is yet another James Morris contribution (I'm an IP-level guy, so I
- * dislike bridging), and I just try not to break it. */
+ * dislike bridging), and I just try not to break it.
+ */
 static void add_to_bridge(int fd, const char *if_name, const char *br_name)
 {
        int ifidx;
@@ -1231,9 +1423,11 @@ static void add_to_bridge(int fd, const char *if_name, const char *br_name)
                err(1, "can't add %s to bridge %s", if_name, br_name);
 }
 
-/* This sets up the Host end of the network device with an IP address, brings
+/*
+ * This sets up the Host end of the network device with an IP address, brings
  * it up so packets will flow, the copies the MAC address into the hwaddr
- * pointer. */
+ * pointer.
+ */
 static void configure_device(int fd, const char *tapif, u32 ipaddr)
 {
        struct ifreq ifr;
@@ -1260,10 +1454,12 @@ static int get_tun_device(char tapif[IFNAMSIZ])
        /* Start with this zeroed.  Messy but sure. */
        memset(&ifr, 0, sizeof(ifr));
 
-       /* We open the /dev/net/tun device and tell it we want a tap device.  A
+       /*
+        * We open the /dev/net/tun device and tell it we want a tap device.  A
         * tap device is like a tun device, only somehow different.  To tell
         * the truth, I completely blundered my way through this code, but it
-        * works now! */
+        * works now!
+        */
        netfd = open_or_die("/dev/net/tun", O_RDWR);
        ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
        strcpy(ifr.ifr_name, "tap%d");
@@ -1274,18 +1470,22 @@ static int get_tun_device(char tapif[IFNAMSIZ])
                  TUN_F_CSUM|TUN_F_TSO4|TUN_F_TSO6|TUN_F_TSO_ECN) != 0)
                err(1, "Could not set features for tun device");
 
-       /* We don't need checksums calculated for packets coming in this
-        * device: trust us! */
+       /*
+        * We don't need checksums calculated for packets coming in this
+        * device: trust us!
+        */
        ioctl(netfd, TUNSETNOCSUM, 1);
 
        memcpy(tapif, ifr.ifr_name, IFNAMSIZ);
        return netfd;
 }
 
-/*L:195 Our network is a Host<->Guest network.  This can either use bridging or
+/*L:195
+ * Our network is a Host<->Guest network.  This can either use bridging or
  * routing, but the principle is the same: it uses the "tun" device to inject
  * packets into the Host as if they came in from a normal network card.  We
- * just shunt packets between the Guest and the tun device. */
+ * just shunt packets between the Guest and the tun device.
+ */
 static void setup_tun_net(char *arg)
 {
        struct device *dev;
@@ -1302,13 +1502,14 @@ static void setup_tun_net(char *arg)
        dev = new_device("net", VIRTIO_ID_NET);
        dev->priv = net_info;
 
-       /* Network devices need a receive and a send queue, just like
-        * console. */
+       /* Network devices need a recv and a send queue, just like console. */
        add_virtqueue(dev, VIRTQUEUE_NUM, net_input);
        add_virtqueue(dev, VIRTQUEUE_NUM, net_output);
 
-       /* We need a socket to perform the magic network ioctls to bring up the
-        * tap interface, connect to the bridge etc.  Any socket will do! */
+       /*
+        * We need a socket to perform the magic network ioctls to bring up the
+        * tap interface, connect to the bridge etc.  Any socket will do!
+        */
        ipfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
        if (ipfd < 0)
                err(1, "opening IP socket");
@@ -1362,39 +1563,31 @@ static void setup_tun_net(char *arg)
                verbose("device %u: tun %s: %s\n",
                        devices.device_num, tapif, arg);
 }
-
-/* Our block (disk) device should be really simple: the Guest asks for a block
- * number and we read or write that position in the file.  Unfortunately, that
- * was amazingly slow: the Guest waits until the read is finished before
- * running anything else, even if it could have been doing useful work.
- *
- * We could use async I/O, except it's reputed to suck so hard that characters
- * actually go missing from your code when you try to use it.
- *
- * So we farm the I/O out to thread, and communicate with it via a pipe. */
+/*:*/
 
 /* This hangs off device->priv. */
-struct vblk_info
-{
+struct vblk_info {
        /* The size of the file. */
        off64_t len;
 
        /* The file descriptor for the file. */
        int fd;
 
-       /* IO thread listens on this file descriptor [0]. */
-       int workpipe[2];
-
-       /* IO thread writes to this file descriptor to mark it done, then
-        * Launcher triggers interrupt to Guest. */
-       int done_fd;
 };
 
 /*L:210
  * The Disk
  *
- * Remember that the block device is handled by a separate I/O thread.  We head
- * straight into the core of that thread here:
+ * The disk only has one virtqueue, so it only has one thread.  It is really
+ * simple: the Guest asks for a block number and we read or write that position
+ * in the file.
+ *
+ * Before we serviced each virtqueue in a separate thread, that was unacceptably
+ * slow: the Guest waits until the read is finished before running anything
+ * else, even if it could have been doing useful work.
+ *
+ * We could have used async I/O, except it's reputed to suck so hard that
+ * characters actually go missing from your code when you try to use it.
  */
 static void blk_request(struct virtqueue *vq)
 {
@@ -1406,47 +1599,64 @@ static void blk_request(struct virtqueue *vq)
        struct iovec iov[vq->vring.num];
        off64_t off;
 
-       /* Get the next request. */
+       /*
+        * Get the next request, where we normally wait.  It triggers the
+        * interrupt to acknowledge previously serviced requests (if any).
+        */
        head = wait_for_vq_desc(vq, iov, &out_num, &in_num);
 
-       /* Every block request should contain at least one output buffer
+       /*
+        * Every block request should contain at least one output buffer
         * (detailing the location on disk and the type of request) and one
-        * input buffer (to hold the result). */
+        * input buffer (to hold the result).
+        */
        if (out_num == 0 || in_num == 0)
                errx(1, "Bad virtblk cmd %u out=%u in=%u",
                     head, out_num, in_num);
 
        out = convert(&iov[0], struct virtio_blk_outhdr);
        in = convert(&iov[out_num+in_num-1], u8);
+       /*
+        * For historical reasons, block operations are expressed in 512 byte
+        * "sectors".
+        */
        off = out->sector * 512;
 
-       /* The block device implements "barriers", where the Guest indicates
+       /*
+        * The block device implements "barriers", where the Guest indicates
         * that it wants all previous writes to occur before this write.  We
         * don't have a way of asking our kernel to do a barrier, so we just
-        * synchronize all the data in the file.  Pretty poor, no? */
+        * synchronize all the data in the file.  Pretty poor, no?
+        */
        if (out->type & VIRTIO_BLK_T_BARRIER)
                fdatasync(vblk->fd);
 
-       /* In general the virtio block driver is allowed to try SCSI commands.
-        * It'd be nice if we supported eject, for example, but we don't. */
+       /*
+        * In general the virtio block driver is allowed to try SCSI commands.
+        * It'd be nice if we supported eject, for example, but we don't.
+        */
        if (out->type & VIRTIO_BLK_T_SCSI_CMD) {
                fprintf(stderr, "Scsi commands unsupported\n");
                *in = VIRTIO_BLK_S_UNSUPP;
                wlen = sizeof(*in);
        } else if (out->type & VIRTIO_BLK_T_OUT) {
-               /* Write */
-
-               /* Move to the right location in the block file.  This can fail
-                * if they try to write past end. */
+               /*
+                * Write
+                *
+                * Move to the right location in the block file.  This can fail
+                * if they try to write past end.
+                */
                if (lseek64(vblk->fd, off, SEEK_SET) != off)
                        err(1, "Bad seek to sector %llu", out->sector);
 
                ret = writev(vblk->fd, iov+1, out_num-1);
                verbose("WRITE to sector %llu: %i\n", out->sector, ret);
 
-               /* Grr... Now we know how long the descriptor they sent was, we
+               /*
+                * Grr... Now we know how long the descriptor they sent was, we
                 * make sure they didn't try to write over the end of the block
-                * file (possibly extending it). */
+                * file (possibly extending it).
+                */
                if (ret > 0 && off + ret > vblk->len) {
                        /* Trim it back to the correct length */
                        ftruncate64(vblk->fd, vblk->len);
@@ -1456,10 +1666,12 @@ static void blk_request(struct virtqueue *vq)
                wlen = sizeof(*in);
                *in = (ret >= 0 ? VIRTIO_BLK_S_OK : VIRTIO_BLK_S_IOERR);
        } else {
-               /* Read */
-
-               /* Move to the right location in the block file.  This can fail
-                * if they try to read past end. */
+               /*
+                * Read
+                *
+                * Move to the right location in the block file.  This can fail
+                * if they try to read past end.
+                */
                if (lseek64(vblk->fd, off, SEEK_SET) != off)
                        err(1, "Bad seek to sector %llu", out->sector);
 
@@ -1474,13 +1686,16 @@ static void blk_request(struct virtqueue *vq)
                }
        }
 
-       /* OK, so we noted that it was pretty poor to use an fdatasync as a
+       /*
+        * OK, so we noted that it was pretty poor to use an fdatasync as a
         * barrier.  But Christoph Hellwig points out that we need a sync
         * *afterwards* as well: "Barriers specify no reordering to the front
-        * or the back."  And Jens Axboe confirmed it, so here we are: */
+        * or the back."  And Jens Axboe confirmed it, so here we are:
+        */
        if (out->type & VIRTIO_BLK_T_BARRIER)
                fdatasync(vblk->fd);
 
+       /* Finished that request. */
        add_used(vq, head, wlen);
 }
 
@@ -1491,7 +1706,7 @@ static void setup_block_file(const char *filename)
        struct vblk_info *vblk;
        struct virtio_blk_config conf;
 
-       /* The device responds to return from I/O thread. */
+       /* Creat the device. */
        dev = new_device("block", VIRTIO_ID_BLOCK);
 
        /* The device has one virtqueue, where the Guest places requests. */
@@ -1510,27 +1725,32 @@ static void setup_block_file(const char *filename)
        /* Tell Guest how many sectors this device has. */
        conf.capacity = cpu_to_le64(vblk->len / 512);
 
-       /* Tell Guest not to put in too many descriptors at once: two are used
-        * for the in and out elements. */
+       /*
+        * Tell Guest not to put in too many descriptors at once: two are used
+        * for the in and out elements.
+        */
        add_feature(dev, VIRTIO_BLK_F_SEG_MAX);
        conf.seg_max = cpu_to_le32(VIRTQUEUE_NUM - 2);
 
-       set_config(dev, sizeof(conf), &conf);
+       /* Don't try to put whole struct: we have 8 bit limit. */
+       set_config(dev, offsetof(struct virtio_blk_config, geometry), &conf);
 
        verbose("device %u: virtblock %llu sectors\n",
                ++devices.device_num, le64_to_cpu(conf.capacity));
 }
 
-struct rng_info {
-       int rfd;
-};
-
-/* Our random number generator device reads from /dev/random into the Guest's
+/*L:211
+ * Our random number generator device reads from /dev/random into the Guest's
  * input buffers.  The usual case is that the Guest doesn't want random numbers
  * and so has no buffers although /dev/random is still readable, whereas
  * console is the reverse.
  *
- * The same logic applies, however. */
+ * The same logic applies, however.
+ */
+struct rng_info {
+       int rfd;
+};
+
 static void rng_input(struct virtqueue *vq)
 {
        int len;
@@ -1543,9 +1763,10 @@ static void rng_input(struct virtqueue *vq)
        if (out_num)
                errx(1, "Output buffers in rng?");
 
-       /* This is why we convert to iovecs: the readv() call uses them, and so
-        * it reads straight into the Guest's buffer.  We loop to make sure we
-        * fill it. */
+       /*
+        * Just like the console write, we loop to cover the whole iovec.
+        * In this case, short reads actually happen quite a bit.
+        */
        while (!iov_empty(iov, in_num)) {
                len = readv(rng_info->rfd, iov, in_num);
                if (len <= 0)
@@ -1558,15 +1779,18 @@ static void rng_input(struct virtqueue *vq)
        add_used(vq, head, totlen);
 }
 
-/* And this creates a "hardware" random number device for the Guest. */
+/*L:199
+ * This creates a "hardware" random number device for the Guest.
+ */
 static void setup_rng(void)
 {
        struct device *dev;
        struct rng_info *rng_info = malloc(sizeof(*rng_info));
 
+       /* Our device's privat info simply contains the /dev/random fd. */
        rng_info->rfd = open_or_die("/dev/random", O_RDONLY);
 
-       /* The device responds to return from I/O thread. */
+       /* Create the new device. */
        dev = new_device("rng", VIRTIO_ID_RNG);
        dev->priv = rng_info;
 
@@ -1582,8 +1806,10 @@ static void __attribute__((noreturn)) restart_guest(void)
 {
        unsigned int i;
 
-       /* Since we don't track all open fds, we simply close everything beyond
-        * stderr. */
+       /*
+        * Since we don't track all open fds, we simply close everything beyond
+        * stderr.
+        */
        for (i = 3; i < FD_SETSIZE; i++)
                close(i);
 
@@ -1594,8 +1820,10 @@ static void __attribute__((noreturn)) restart_guest(void)
        err(1, "Could not exec %s", main_args[0]);
 }
 
-/*L:220 Finally we reach the core of the Launcher which runs the Guest, serves
- * its input and output, and finally, lays it to rest. */
+/*L:220
+ * Finally we reach the core of the Launcher which runs the Guest, serves
+ * its input and output, and finally, lays it to rest.
+ */
 static void __attribute__((noreturn)) run_guest(void)
 {
        for (;;) {
@@ -1630,7 +1858,7 @@ static void __attribute__((noreturn)) run_guest(void)
  *
  * Are you ready?  Take a deep breath and join me in the core of the Host, in
  * "make Host".
- :*/
+:*/
 
 static struct option opts[] = {
        { "verbose", 0, NULL, 'v' },
@@ -1651,8 +1879,7 @@ static void usage(void)
 /*L:105 The main routine is where the real work begins: */
 int main(int argc, char *argv[])
 {
-       /* Memory, top-level pagetable, code startpoint and size of the
-        * (optional) initrd. */
+       /* Memory, code startpoint and size of the (optional) initrd. */
        unsigned long mem = 0, start, initrd_size = 0;
        /* Two temporaries. */
        int i, c;
@@ -1664,24 +1891,32 @@ int main(int argc, char *argv[])
        /* Save the args: we "reboot" by execing ourselves again. */
        main_args = argv;
 
-       /* First we initialize the device list.  We keep a pointer to the last
+       /*
+        * First we initialize the device list.  We keep a pointer to the last
         * device, and the next interrupt number to use for devices (1:
-        * remember that 0 is used by the timer). */
+        * remember that 0 is used by the timer).
+        */
        devices.lastdev = NULL;
        devices.next_irq = 1;
 
+       /* We're CPU 0.  In fact, that's the only CPU possible right now. */
        cpu_id = 0;
-       /* We need to know how much memory so we can set up the device
+
+       /*
+        * We need to know how much memory so we can set up the device
         * descriptor and memory pages for the devices as we parse the command
         * line.  So we quickly look through the arguments to find the amount
-        * of memory now. */
+        * of memory now.
+        */
        for (i = 1; i < argc; i++) {
                if (argv[i][0] != '-') {
                        mem = atoi(argv[i]) * 1024 * 1024;
-                       /* We start by mapping anonymous pages over all of
+                       /*
+                        * We start by mapping anonymous pages over all of
                         * guest-physical memory range.  This fills it with 0,
                         * and ensures that the Guest won't be killed when it
-                        * tries to access it. */
+                        * tries to access it.
+                        */
                        guest_base = map_zeroed_pages(mem / getpagesize()
                                                      + DEVICE_PAGES);
                        guest_limit = mem;
@@ -1714,8 +1949,10 @@ int main(int argc, char *argv[])
                        usage();
                }
        }
-       /* After the other arguments we expect memory and kernel image name,
-        * followed by command line arguments for the kernel. */
+       /*
+        * After the other arguments we expect memory and kernel image name,
+        * followed by command line arguments for the kernel.
+        */
        if (optind + 2 > argc)
                usage();
 
@@ -1733,20 +1970,26 @@ int main(int argc, char *argv[])
        /* Map the initrd image if requested (at top of physical memory) */
        if (initrd_name) {
                initrd_size = load_initrd(initrd_name, mem);
-               /* These are the location in the Linux boot header where the
-                * start and size of the initrd are expected to be found. */
+               /*
+                * These are the location in the Linux boot header where the
+                * start and size of the initrd are expected to be found.
+                */
                boot->hdr.ramdisk_image = mem - initrd_size;
                boot->hdr.ramdisk_size = initrd_size;
                /* The bootloader type 0xFF means "unknown"; that's OK. */
                boot->hdr.type_of_loader = 0xFF;
        }
 
-       /* The Linux boot header contains an "E820" memory map: ours is a
-        * simple, single region. */
+       /*
+        * The Linux boot header contains an "E820" memory map: ours is a
+        * simple, single region.
+        */
        boot->e820_entries = 1;
        boot->e820_map[0] = ((struct e820entry) { 0, mem, E820_RAM });
-       /* The boot header contains a command line pointer: we put the command
-        * line after the boot header. */
+       /*
+        * The boot header contains a command line pointer: we put the command
+        * line after the boot header.
+        */
        boot->hdr.cmd_line_ptr = to_guest_phys(boot + 1);
        /* We use a simple helper to copy the arguments separated by spaces. */
        concat((char *)(boot + 1), argv+optind+2);
@@ -1760,11 +2003,13 @@ int main(int argc, char *argv[])
        /* Tell the entry path not to try to reload segment registers. */
        boot->hdr.loadflags |= KEEP_SEGMENTS;
 
-       /* We tell the kernel to initialize the Guest: this returns the open
-        * /dev/lguest file descriptor. */
+       /*
+        * We tell the kernel to initialize the Guest: this returns the open
+        * /dev/lguest file descriptor.
+        */
        tell_kernel(start);
 
-       /* Ensure that we terminate if a child dies. */
+       /* Ensure that we terminate if a device-servicing child dies. */
        signal(SIGCHLD, kill_launcher);
 
        /* If we exit via err(), this kills all the threads, restores tty. */
index e20d913d5914a29261d12f5fa4585164ed170c82..abf768c681e208c3fe5c4d7c5fc27f788c6c29c7 100644 (file)
@@ -30,9 +30,9 @@ State
 The validator tracks lock-class usage history into 4n + 1 separate state bits:
 
 - 'ever held in STATE context'
-- 'ever head as readlock in STATE context'
-- 'ever head with STATE enabled'
-- 'ever head as readlock with STATE enabled'
+- 'ever held as readlock in STATE context'
+- 'ever held with STATE enabled'
+- 'ever held as readlock with STATE enabled'
 
 Where STATE can be either one of (kernel/lockdep_states.h)
  - hardirq
index d0777a1200e1a3a3c224db65cac7fe0d866ea44f..8f339428fdf441d40bb653a226dc12fe9baea928 100644 (file)
@@ -1,7 +1,7 @@
 This is the 6pack-mini-HOWTO, written by
 
 Andreas Könsgen DG3KQ
-Internet: ajk@iehk.rwth-aachen.de
+Internet: ajk@comnets.uni-bremen.de
 AMPR-net: dg3kq@db0pra.ampr.org
 AX.25:    dg3kq@db0ach.#nrw.deu.eu
 
index 8d999d862d0e646ffb9c7949898d3987fc2004a4..79f533f38c6112d64bed9398c44d31cf3b552f6b 100644 (file)
@@ -1238,1122 +1238,7 @@ descriptions for the SOC devices for which new nodes have been
 defined; this list will expand as more and more SOC-containing
 platforms are moved over to use the flattened-device-tree model.
 
-   a) PHY nodes
-
-   Required properties:
-
-    - device_type : Should be "ethernet-phy"
-    - interrupts : <a b> where a is the interrupt number and b is a
-      field that represents an encoding of the sense and level
-      information for the interrupt.  This should be encoded based on
-      the information in section 2) depending on the type of interrupt
-      controller you have.
-    - interrupt-parent : the phandle for the interrupt controller that
-      services interrupts for this device.
-    - reg : The ID number for the phy, usually a small integer
-    - linux,phandle :  phandle for this node; likely referenced by an
-      ethernet controller node.
-
-
-   Example:
-
-       ethernet-phy@0 {
-               linux,phandle = <2452000>
-               interrupt-parent = <40000>;
-               interrupts = <35 1>;
-               reg = <0>;
-               device_type = "ethernet-phy";
-       };
-
-
-   b) Interrupt controllers
-
-   Some SOC devices contain interrupt controllers that are different
-   from the standard Open PIC specification.  The SOC device nodes for
-   these types of controllers should be specified just like a standard
-   OpenPIC controller.  Sense and level information should be encoded
-   as specified in section 2) of this chapter for each device that
-   specifies an interrupt.
-
-   Example :
-
-       pic@40000 {
-               linux,phandle = <40000>;
-               interrupt-controller;
-               #address-cells = <0>;
-               reg = <40000 40000>;
-               compatible = "chrp,open-pic";
-               device_type = "open-pic";
-       };
-
-    c) 4xx/Axon EMAC ethernet nodes
-
-    The EMAC ethernet controller in IBM and AMCC 4xx chips, and also
-    the Axon bridge.  To operate this needs to interact with a ths
-    special McMAL DMA controller, and sometimes an RGMII or ZMII
-    interface.  In addition to the nodes and properties described
-    below, the node for the OPB bus on which the EMAC sits must have a
-    correct clock-frequency property.
-
-      i) The EMAC node itself
-
-    Required properties:
-    - device_type       : "network"
-
-    - compatible        : compatible list, contains 2 entries, first is
-                         "ibm,emac-CHIP" where CHIP is the host ASIC (440gx,
-                         405gp, Axon) and second is either "ibm,emac" or
-                         "ibm,emac4".  For Axon, thus, we have: "ibm,emac-axon",
-                         "ibm,emac4"
-    - interrupts        : <interrupt mapping for EMAC IRQ and WOL IRQ>
-    - interrupt-parent  : optional, if needed for interrupt mapping
-    - reg               : <registers mapping>
-    - local-mac-address : 6 bytes, MAC address
-    - mal-device        : phandle of the associated McMAL node
-    - mal-tx-channel    : 1 cell, index of the tx channel on McMAL associated
-                         with this EMAC
-    - mal-rx-channel    : 1 cell, index of the rx channel on McMAL associated
-                         with this EMAC
-    - cell-index        : 1 cell, hardware index of the EMAC cell on a given
-                         ASIC (typically 0x0 and 0x1 for EMAC0 and EMAC1 on
-                         each Axon chip)
-    - max-frame-size    : 1 cell, maximum frame size supported in bytes
-    - rx-fifo-size      : 1 cell, Rx fifo size in bytes for 10 and 100 Mb/sec
-                         operations.
-                         For Axon, 2048
-    - tx-fifo-size      : 1 cell, Tx fifo size in bytes for 10 and 100 Mb/sec
-                         operations.
-                         For Axon, 2048.
-    - fifo-entry-size   : 1 cell, size of a fifo entry (used to calculate
-                         thresholds).
-                         For Axon, 0x00000010
-    - mal-burst-size    : 1 cell, MAL burst size (used to calculate thresholds)
-                         in bytes.
-                         For Axon, 0x00000100 (I think ...)
-    - phy-mode          : string, mode of operations of the PHY interface.
-                         Supported values are: "mii", "rmii", "smii", "rgmii",
-                         "tbi", "gmii", rtbi", "sgmii".
-                         For Axon on CAB, it is "rgmii"
-    - mdio-device       : 1 cell, required iff using shared MDIO registers
-                         (440EP).  phandle of the EMAC to use to drive the
-                         MDIO lines for the PHY used by this EMAC.
-    - zmii-device       : 1 cell, required iff connected to a ZMII.  phandle of
-                         the ZMII device node
-    - zmii-channel      : 1 cell, required iff connected to a ZMII.  Which ZMII
-                         channel or 0xffffffff if ZMII is only used for MDIO.
-    - rgmii-device      : 1 cell, required iff connected to an RGMII. phandle
-                         of the RGMII device node.
-                         For Axon: phandle of plb5/plb4/opb/rgmii
-    - rgmii-channel     : 1 cell, required iff connected to an RGMII.  Which
-                         RGMII channel is used by this EMAC.
-                         Fox Axon: present, whatever value is appropriate for each
-                         EMAC, that is the content of the current (bogus) "phy-port"
-                         property.
-
-    Optional properties:
-    - phy-address       : 1 cell, optional, MDIO address of the PHY. If absent,
-                         a search is performed.
-    - phy-map           : 1 cell, optional, bitmap of addresses to probe the PHY
-                         for, used if phy-address is absent. bit 0x00000001 is
-                         MDIO address 0.
-                         For Axon it can be absent, though my current driver
-                         doesn't handle phy-address yet so for now, keep
-                         0x00ffffff in it.
-    - rx-fifo-size-gige : 1 cell, Rx fifo size in bytes for 1000 Mb/sec
-                         operations (if absent the value is the same as
-                         rx-fifo-size).  For Axon, either absent or 2048.
-    - tx-fifo-size-gige : 1 cell, Tx fifo size in bytes for 1000 Mb/sec
-                         operations (if absent the value is the same as
-                         tx-fifo-size). For Axon, either absent or 2048.
-    - tah-device        : 1 cell, optional. If connected to a TAH engine for
-                         offload, phandle of the TAH device node.
-    - tah-channel       : 1 cell, optional. If appropriate, channel used on the
-                         TAH engine.
-
-    Example:
-
-       EMAC0: ethernet@40000800 {
-               device_type = "network";
-               compatible = "ibm,emac-440gp", "ibm,emac";
-               interrupt-parent = <&UIC1>;
-               interrupts = <1c 4 1d 4>;
-               reg = <40000800 70>;
-               local-mac-address = [00 04 AC E3 1B 1E];
-               mal-device = <&MAL0>;
-               mal-tx-channel = <0 1>;
-               mal-rx-channel = <0>;
-               cell-index = <0>;
-               max-frame-size = <5dc>;
-               rx-fifo-size = <1000>;
-               tx-fifo-size = <800>;
-               phy-mode = "rmii";
-               phy-map = <00000001>;
-               zmii-device = <&ZMII0>;
-               zmii-channel = <0>;
-       };
-
-      ii) McMAL node
-
-    Required properties:
-    - device_type        : "dma-controller"
-    - compatible         : compatible list, containing 2 entries, first is
-                          "ibm,mcmal-CHIP" where CHIP is the host ASIC (like
-                          emac) and the second is either "ibm,mcmal" or
-                          "ibm,mcmal2".
-                          For Axon, "ibm,mcmal-axon","ibm,mcmal2"
-    - interrupts         : <interrupt mapping for the MAL interrupts sources:
-                           5 sources: tx_eob, rx_eob, serr, txde, rxde>.
-                           For Axon: This is _different_ from the current
-                          firmware.  We use the "delayed" interrupts for txeob
-                          and rxeob. Thus we end up with mapping those 5 MPIC
-                          interrupts, all level positive sensitive: 10, 11, 32,
-                          33, 34 (in decimal)
-    - dcr-reg            : < DCR registers range >
-    - dcr-parent         : if needed for dcr-reg
-    - num-tx-chans       : 1 cell, number of Tx channels
-    - num-rx-chans       : 1 cell, number of Rx channels
-
-      iii) ZMII node
-
-    Required properties:
-    - compatible         : compatible list, containing 2 entries, first is
-                          "ibm,zmii-CHIP" where CHIP is the host ASIC (like
-                          EMAC) and the second is "ibm,zmii".
-                          For Axon, there is no ZMII node.
-    - reg                : <registers mapping>
-
-      iv) RGMII node
-
-    Required properties:
-    - compatible         : compatible list, containing 2 entries, first is
-                          "ibm,rgmii-CHIP" where CHIP is the host ASIC (like
-                          EMAC) and the second is "ibm,rgmii".
-                           For Axon, "ibm,rgmii-axon","ibm,rgmii"
-    - reg                : <registers mapping>
-    - revision           : as provided by the RGMII new version register if
-                          available.
-                          For Axon: 0x0000012a
-
-   d) Xilinx IP cores
-
-   The Xilinx EDK toolchain ships with a set of IP cores (devices) for use
-   in Xilinx Spartan and Virtex FPGAs.  The devices cover the whole range
-   of standard device types (network, serial, etc.) and miscellaneous
-   devices (gpio, LCD, spi, etc).  Also, since these devices are
-   implemented within the fpga fabric every instance of the device can be
-   synthesised with different options that change the behaviour.
-
-   Each IP-core has a set of parameters which the FPGA designer can use to
-   control how the core is synthesized.  Historically, the EDK tool would
-   extract the device parameters relevant to device drivers and copy them
-   into an 'xparameters.h' in the form of #define symbols.  This tells the
-   device drivers how the IP cores are configured, but it requres the kernel
-   to be recompiled every time the FPGA bitstream is resynthesized.
-
-   The new approach is to export the parameters into the device tree and
-   generate a new device tree each time the FPGA bitstream changes.  The
-   parameters which used to be exported as #defines will now become
-   properties of the device node.  In general, device nodes for IP-cores
-   will take the following form:
-
-       (name): (generic-name)@(base-address) {
-               compatible = "xlnx,(ip-core-name)-(HW_VER)"
-                            [, (list of compatible devices), ...];
-               reg = <(baseaddr) (size)>;
-               interrupt-parent = <&interrupt-controller-phandle>;
-               interrupts = < ... >;
-               xlnx,(parameter1) = "(string-value)";
-               xlnx,(parameter2) = <(int-value)>;
-       };
-
-       (generic-name):   an open firmware-style name that describes the
-                       generic class of device.  Preferably, this is one word, such
-                       as 'serial' or 'ethernet'.
-       (ip-core-name): the name of the ip block (given after the BEGIN
-                       directive in system.mhs).  Should be in lowercase
-                       and all underscores '_' converted to dashes '-'.
-       (name):         is derived from the "PARAMETER INSTANCE" value.
-       (parameter#):   C_* parameters from system.mhs.  The C_ prefix is
-                       dropped from the parameter name, the name is converted
-                       to lowercase and all underscore '_' characters are
-                       converted to dashes '-'.
-       (baseaddr):     the baseaddr parameter value (often named C_BASEADDR).
-       (HW_VER):       from the HW_VER parameter.
-       (size):         the address range size (often C_HIGHADDR - C_BASEADDR + 1).
-
-   Typically, the compatible list will include the exact IP core version
-   followed by an older IP core version which implements the same
-   interface or any other device with the same interface.
-
-   'reg', 'interrupt-parent' and 'interrupts' are all optional properties.
-
-   For example, the following block from system.mhs:
-
-       BEGIN opb_uartlite
-               PARAMETER INSTANCE = opb_uartlite_0
-               PARAMETER HW_VER = 1.00.b
-               PARAMETER C_BAUDRATE = 115200
-               PARAMETER C_DATA_BITS = 8
-               PARAMETER C_ODD_PARITY = 0
-               PARAMETER C_USE_PARITY = 0
-               PARAMETER C_CLK_FREQ = 50000000
-               PARAMETER C_BASEADDR = 0xEC100000
-               PARAMETER C_HIGHADDR = 0xEC10FFFF
-               BUS_INTERFACE SOPB = opb_7
-               PORT OPB_Clk = CLK_50MHz
-               PORT Interrupt = opb_uartlite_0_Interrupt
-               PORT RX = opb_uartlite_0_RX
-               PORT TX = opb_uartlite_0_TX
-               PORT OPB_Rst = sys_bus_reset_0
-       END
-
-   becomes the following device tree node:
-
-       opb_uartlite_0: serial@ec100000 {
-               device_type = "serial";
-               compatible = "xlnx,opb-uartlite-1.00.b";
-               reg = <ec100000 10000>;
-               interrupt-parent = <&opb_intc_0>;
-               interrupts = <1 0>; // got this from the opb_intc parameters
-               current-speed = <d#115200>;     // standard serial device prop
-               clock-frequency = <d#50000000>; // standard serial device prop
-               xlnx,data-bits = <8>;
-               xlnx,odd-parity = <0>;
-               xlnx,use-parity = <0>;
-       };
-
-   Some IP cores actually implement 2 or more logical devices.  In
-   this case, the device should still describe the whole IP core with
-   a single node and add a child node for each logical device.  The
-   ranges property can be used to translate from parent IP-core to the
-   registers of each device.  In addition, the parent node should be
-   compatible with the bus type 'xlnx,compound', and should contain
-   #address-cells and #size-cells, as with any other bus.  (Note: this
-   makes the assumption that both logical devices have the same bus
-   binding.  If this is not true, then separate nodes should be used
-   for each logical device).  The 'cell-index' property can be used to
-   enumerate logical devices within an IP core.  For example, the
-   following is the system.mhs entry for the dual ps2 controller found
-   on the ml403 reference design.
-
-       BEGIN opb_ps2_dual_ref
-               PARAMETER INSTANCE = opb_ps2_dual_ref_0
-               PARAMETER HW_VER = 1.00.a
-               PARAMETER C_BASEADDR = 0xA9000000
-               PARAMETER C_HIGHADDR = 0xA9001FFF
-               BUS_INTERFACE SOPB = opb_v20_0
-               PORT Sys_Intr1 = ps2_1_intr
-               PORT Sys_Intr2 = ps2_2_intr
-               PORT Clkin1 = ps2_clk_rx_1
-               PORT Clkin2 = ps2_clk_rx_2
-               PORT Clkpd1 = ps2_clk_tx_1
-               PORT Clkpd2 = ps2_clk_tx_2
-               PORT Rx1 = ps2_d_rx_1
-               PORT Rx2 = ps2_d_rx_2
-               PORT Txpd1 = ps2_d_tx_1
-               PORT Txpd2 = ps2_d_tx_2
-       END
-
-   It would result in the following device tree nodes:
-
-       opb_ps2_dual_ref_0: opb-ps2-dual-ref@a9000000 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "xlnx,compound";
-               ranges = <0 a9000000 2000>;
-               // If this device had extra parameters, then they would
-               // go here.
-               ps2@0 {
-                       compatible = "xlnx,opb-ps2-dual-ref-1.00.a";
-                       reg = <0 40>;
-                       interrupt-parent = <&opb_intc_0>;
-                       interrupts = <3 0>;
-                       cell-index = <0>;
-               };
-               ps2@1000 {
-                       compatible = "xlnx,opb-ps2-dual-ref-1.00.a";
-                       reg = <1000 40>;
-                       interrupt-parent = <&opb_intc_0>;
-                       interrupts = <3 0>;
-                       cell-index = <0>;
-               };
-       };
-
-   Also, the system.mhs file defines bus attachments from the processor
-   to the devices.  The device tree structure should reflect the bus
-   attachments.  Again an example; this system.mhs fragment:
-
-       BEGIN ppc405_virtex4
-               PARAMETER INSTANCE = ppc405_0
-               PARAMETER HW_VER = 1.01.a
-               BUS_INTERFACE DPLB = plb_v34_0
-               BUS_INTERFACE IPLB = plb_v34_0
-       END
-
-       BEGIN opb_intc
-               PARAMETER INSTANCE = opb_intc_0
-               PARAMETER HW_VER = 1.00.c
-               PARAMETER C_BASEADDR = 0xD1000FC0
-               PARAMETER C_HIGHADDR = 0xD1000FDF
-               BUS_INTERFACE SOPB = opb_v20_0
-       END
-
-       BEGIN opb_uart16550
-               PARAMETER INSTANCE = opb_uart16550_0
-               PARAMETER HW_VER = 1.00.d
-               PARAMETER C_BASEADDR = 0xa0000000
-               PARAMETER C_HIGHADDR = 0xa0001FFF
-               BUS_INTERFACE SOPB = opb_v20_0
-       END
-
-       BEGIN plb_v34
-               PARAMETER INSTANCE = plb_v34_0
-               PARAMETER HW_VER = 1.02.a
-       END
-
-       BEGIN plb_bram_if_cntlr
-               PARAMETER INSTANCE = plb_bram_if_cntlr_0
-               PARAMETER HW_VER = 1.00.b
-               PARAMETER C_BASEADDR = 0xFFFF0000
-               PARAMETER C_HIGHADDR = 0xFFFFFFFF
-               BUS_INTERFACE SPLB = plb_v34_0
-       END
-
-       BEGIN plb2opb_bridge
-               PARAMETER INSTANCE = plb2opb_bridge_0
-               PARAMETER HW_VER = 1.01.a
-               PARAMETER C_RNG0_BASEADDR = 0x20000000
-               PARAMETER C_RNG0_HIGHADDR = 0x3FFFFFFF
-               PARAMETER C_RNG1_BASEADDR = 0x60000000
-               PARAMETER C_RNG1_HIGHADDR = 0x7FFFFFFF
-               PARAMETER C_RNG2_BASEADDR = 0x80000000
-               PARAMETER C_RNG2_HIGHADDR = 0xBFFFFFFF
-               PARAMETER C_RNG3_BASEADDR = 0xC0000000
-               PARAMETER C_RNG3_HIGHADDR = 0xDFFFFFFF
-               BUS_INTERFACE SPLB = plb_v34_0
-               BUS_INTERFACE MOPB = opb_v20_0
-       END
-
-   Gives this device tree (some properties removed for clarity):
-
-       plb@0 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "xlnx,plb-v34-1.02.a";
-               device_type = "ibm,plb";
-               ranges; // 1:1 translation
-
-               plb_bram_if_cntrl_0: bram@ffff0000 {
-                       reg = <ffff0000 10000>;
-               }
-
-               opb@20000000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges = <20000000 20000000 20000000
-                                 60000000 60000000 20000000
-                                 80000000 80000000 40000000
-                                 c0000000 c0000000 20000000>;
-
-                       opb_uart16550_0: serial@a0000000 {
-                               reg = <a00000000 2000>;
-                       };
-
-                       opb_intc_0: interrupt-controller@d1000fc0 {
-                               reg = <d1000fc0 20>;
-                       };
-               };
-       };
-
-   That covers the general approach to binding xilinx IP cores into the
-   device tree.  The following are bindings for specific devices:
-
-      i) Xilinx ML300 Framebuffer
-
-      Simple framebuffer device from the ML300 reference design (also on the
-      ML403 reference design as well as others).
-
-      Optional properties:
-       - resolution = <xres yres> : pixel resolution of framebuffer.  Some
-                                    implementations use a different resolution.
-                                    Default is <d#640 d#480>
-       - virt-resolution = <xvirt yvirt> : Size of framebuffer in memory.
-                                           Default is <d#1024 d#480>.
-       - rotate-display (empty) : rotate display 180 degrees.
-
-      ii) Xilinx SystemACE
-
-      The Xilinx SystemACE device is used to program FPGAs from an FPGA
-      bitstream stored on a CF card.  It can also be used as a generic CF
-      interface device.
-
-      Optional properties:
-       - 8-bit (empty) : Set this property for SystemACE in 8 bit mode
-
-      iii) Xilinx EMAC and Xilinx TEMAC
-
-      Xilinx Ethernet devices.  In addition to general xilinx properties
-      listed above, nodes for these devices should include a phy-handle
-      property, and may include other common network device properties
-      like local-mac-address.
-
-      iv) Xilinx Uartlite
-
-      Xilinx uartlite devices are simple fixed speed serial ports.
-
-      Required properties:
-       - current-speed : Baud rate of uartlite
-
-      v) Xilinx hwicap
-
-               Xilinx hwicap devices provide access to the configuration logic
-               of the FPGA through the Internal Configuration Access Port
-               (ICAP).  The ICAP enables partial reconfiguration of the FPGA,
-               readback of the configuration information, and some control over
-               'warm boots' of the FPGA fabric.
-
-               Required properties:
-               - xlnx,family : The family of the FPGA, necessary since the
-                      capabilities of the underlying ICAP hardware
-                      differ between different families.  May be
-                      'virtex2p', 'virtex4', or 'virtex5'.
-
-      vi) Xilinx Uart 16550
-
-      Xilinx UART 16550 devices are very similar to the NS16550 but with
-      different register spacing and an offset from the base address.
-
-      Required properties:
-       - clock-frequency : Frequency of the clock input
-       - reg-offset : A value of 3 is required
-       - reg-shift : A value of 2 is required
-
-    e) USB EHCI controllers
-
-    Required properties:
-      - compatible : should be "usb-ehci".
-      - reg : should contain at least address and length of the standard EHCI
-        register set for the device. Optional platform-dependent registers
-        (debug-port or other) can be also specified here, but only after
-        definition of standard EHCI registers.
-      - interrupts : one EHCI interrupt should be described here.
-    If device registers are implemented in big endian mode, the device
-    node should have "big-endian-regs" property.
-    If controller implementation operates with big endian descriptors,
-    "big-endian-desc" property should be specified.
-    If both big endian registers and descriptors are used by the controller
-    implementation, "big-endian" property can be specified instead of having
-    both "big-endian-regs" and "big-endian-desc".
-
-     Example (Sequoia 440EPx):
-           ehci@e0000300 {
-                  compatible = "ibm,usb-ehci-440epx", "usb-ehci";
-                  interrupt-parent = <&UIC0>;
-                  interrupts = <1a 4>;
-                  reg = <0 e0000300 90 0 e0000390 70>;
-                  big-endian;
-          };
-
-   f) MDIO on GPIOs
-
-   Currently defined compatibles:
-   - virtual,gpio-mdio
-
-   MDC and MDIO lines connected to GPIO controllers are listed in the
-   gpios property as described in section VIII.1 in the following order:
-
-   MDC, MDIO.
-
-   Example:
-
-       mdio {
-               compatible = "virtual,mdio-gpio";
-               #address-cells = <1>;
-               #size-cells = <0>;
-               gpios = <&qe_pio_a 11
-                        &qe_pio_c 6>;
-       };
-
-    g) SPI (Serial Peripheral Interface) busses
-
-    SPI busses can be described with a node for the SPI master device
-    and a set of child nodes for each SPI slave on the bus.  For this
-    discussion, it is assumed that the system's SPI controller is in
-    SPI master mode.  This binding does not describe SPI controllers
-    in slave mode.
-
-    The SPI master node requires the following properties:
-    - #address-cells  - number of cells required to define a chip select
-                       address on the SPI bus.
-    - #size-cells     - should be zero.
-    - compatible      - name of SPI bus controller following generic names
-                       recommended practice.
-    No other properties are required in the SPI bus node.  It is assumed
-    that a driver for an SPI bus device will understand that it is an SPI bus.
-    However, the binding does not attempt to define the specific method for
-    assigning chip select numbers.  Since SPI chip select configuration is
-    flexible and non-standardized, it is left out of this binding with the
-    assumption that board specific platform code will be used to manage
-    chip selects.  Individual drivers can define additional properties to
-    support describing the chip select layout.
-
-    SPI slave nodes must be children of the SPI master node and can
-    contain the following properties.
-    - reg             - (required) chip select address of device.
-    - compatible      - (required) name of SPI device following generic names
-                       recommended practice
-    - spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz
-    - spi-cpol        - (optional) Empty property indicating device requires
-                       inverse clock polarity (CPOL) mode
-    - spi-cpha        - (optional) Empty property indicating device requires
-                       shifted clock phase (CPHA) mode
-    - spi-cs-high     - (optional) Empty property indicating device requires
-                       chip select active high
-
-    SPI example for an MPC5200 SPI bus:
-               spi@f00 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
-                       reg = <0xf00 0x20>;
-                       interrupts = <2 13 0 2 14 0>;
-                       interrupt-parent = <&mpc5200_pic>;
-
-                       ethernet-switch@0 {
-                               compatible = "micrel,ks8995m";
-                               spi-max-frequency = <1000000>;
-                               reg = <0>;
-                       };
-
-                       codec@1 {
-                               compatible = "ti,tlv320aic26";
-                               spi-max-frequency = <100000>;
-                               reg = <1>;
-                       };
-               };
-
-VII - Marvell Discovery mv64[345]6x System Controller chips
-===========================================================
-
-The Marvell mv64[345]60 series of system controller chips contain
-many of the peripherals needed to implement a complete computer
-system.  In this section, we define device tree nodes to describe
-the system controller chip itself and each of the peripherals
-which it contains.  Compatible string values for each node are
-prefixed with the string "marvell,", for Marvell Technology Group Ltd.
-
-1) The /system-controller node
-
-  This node is used to represent the system-controller and must be
-  present when the system uses a system controller chip. The top-level
-  system-controller node contains information that is global to all
-  devices within the system controller chip. The node name begins
-  with "system-controller" followed by the unit address, which is
-  the base address of the memory-mapped register set for the system
-  controller chip.
-
-  Required properties:
-
-    - ranges : Describes the translation of system controller addresses
-      for memory mapped registers.
-    - clock-frequency: Contains the main clock frequency for the system
-      controller chip.
-    - reg : This property defines the address and size of the
-      memory-mapped registers contained within the system controller
-      chip.  The address specified in the "reg" property should match
-      the unit address of the system-controller node.
-    - #address-cells : Address representation for system controller
-      devices.  This field represents the number of cells needed to
-      represent the address of the memory-mapped registers of devices
-      within the system controller chip.
-    - #size-cells : Size representation for for the memory-mapped
-      registers within the system controller chip.
-    - #interrupt-cells : Defines the width of cells used to represent
-      interrupts.
-
-  Optional properties:
-
-    - model : The specific model of the system controller chip.  Such
-      as, "mv64360", "mv64460", or "mv64560".
-    - compatible : A string identifying the compatibility identifiers
-      of the system controller chip.
-
-  The system-controller node contains child nodes for each system
-  controller device that the platform uses.  Nodes should not be created
-  for devices which exist on the system controller chip but are not used
-
-  Example Marvell Discovery mv64360 system-controller node:
-
-    system-controller@f1000000 { /* Marvell Discovery mv64360 */
-           #address-cells = <1>;
-           #size-cells = <1>;
-           model = "mv64360";                      /* Default */
-           compatible = "marvell,mv64360";
-           clock-frequency = <133333333>;
-           reg = <0xf1000000 0x10000>;
-           virtual-reg = <0xf1000000>;
-           ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */
-                   0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */
-                   0xa0000000 0xa0000000 0x4000000 /* User FLASH */
-                   0x00000000 0xf1000000 0x0010000 /* Bridge's regs */
-                   0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */
-
-           [ child node definitions... ]
-    }
-
-2) Child nodes of /system-controller
-
-   a) Marvell Discovery MDIO bus
-
-   The MDIO is a bus to which the PHY devices are connected.  For each
-   device that exists on this bus, a child node should be created.  See
-   the definition of the PHY node below for an example of how to define
-   a PHY.
-
-   Required properties:
-     - #address-cells : Should be <1>
-     - #size-cells : Should be <0>
-     - device_type : Should be "mdio"
-     - compatible : Should be "marvell,mv64360-mdio"
-
-   Example:
-
-     mdio {
-            #address-cells = <1>;
-            #size-cells = <0>;
-            device_type = "mdio";
-            compatible = "marvell,mv64360-mdio";
-
-            ethernet-phy@0 {
-                    ......
-            };
-     };
-
-
-   b) Marvell Discovery ethernet controller
-
-   The Discover ethernet controller is described with two levels
-   of nodes.  The first level describes an ethernet silicon block
-   and the second level describes up to 3 ethernet nodes within
-   that block.  The reason for the multiple levels is that the
-   registers for the node are interleaved within a single set
-   of registers.  The "ethernet-block" level describes the
-   shared register set, and the "ethernet" nodes describe ethernet
-   port-specific properties.
-
-   Ethernet block node
-
-   Required properties:
-     - #address-cells : <1>
-     - #size-cells : <0>
-     - compatible : "marvell,mv64360-eth-block"
-     - reg : Offset and length of the register set for this block
-
-   Example Discovery Ethernet block node:
-     ethernet-block@2000 {
-            #address-cells = <1>;
-            #size-cells = <0>;
-            compatible = "marvell,mv64360-eth-block";
-            reg = <0x2000 0x2000>;
-            ethernet@0 {
-                    .......
-            };
-     };
-
-   Ethernet port node
-
-   Required properties:
-     - device_type : Should be "network".
-     - compatible : Should be "marvell,mv64360-eth".
-     - reg : Should be <0>, <1>, or <2>, according to which registers
-       within the silicon block the device uses.
-     - interrupts : <a> where a is the interrupt number for the port.
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-     - phy : the phandle for the PHY connected to this ethernet
-       controller.
-     - local-mac-address : 6 bytes, MAC address
-
-   Example Discovery Ethernet port node:
-     ethernet@0 {
-            device_type = "network";
-            compatible = "marvell,mv64360-eth";
-            reg = <0>;
-            interrupts = <32>;
-            interrupt-parent = <&PIC>;
-            phy = <&PHY0>;
-            local-mac-address = [ 00 00 00 00 00 00 ];
-     };
-
-
-
-   c) Marvell Discovery PHY nodes
-
-   Required properties:
-     - device_type : Should be "ethernet-phy"
-     - interrupts : <a> where a is the interrupt number for this phy.
-     - interrupt-parent : the phandle for the interrupt controller that
-       services interrupts for this device.
-     - reg : The ID number for the phy, usually a small integer
-
-   Example Discovery PHY node:
-     ethernet-phy@1 {
-            device_type = "ethernet-phy";
-            compatible = "broadcom,bcm5421";
-            interrupts = <76>;      /* GPP 12 */
-            interrupt-parent = <&PIC>;
-            reg = <1>;
-     };
-
-
-   d) Marvell Discovery SDMA nodes
-
-   Represent DMA hardware associated with the MPSC (multiprotocol
-   serial controllers).
-
-   Required properties:
-     - compatible : "marvell,mv64360-sdma"
-     - reg : Offset and length of the register set for this device
-     - interrupts : <a> where a is the interrupt number for the DMA
-       device.
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery SDMA node:
-     sdma@4000 {
-            compatible = "marvell,mv64360-sdma";
-            reg = <0x4000 0xc18>;
-            virtual-reg = <0xf1004000>;
-            interrupts = <36>;
-            interrupt-parent = <&PIC>;
-     };
-
-
-   e) Marvell Discovery BRG nodes
-
-   Represent baud rate generator hardware associated with the MPSC
-   (multiprotocol serial controllers).
-
-   Required properties:
-     - compatible : "marvell,mv64360-brg"
-     - reg : Offset and length of the register set for this device
-     - clock-src : A value from 0 to 15 which selects the clock
-       source for the baud rate generator.  This value corresponds
-       to the CLKS value in the BRGx configuration register.  See
-       the mv64x60 User's Manual.
-     - clock-frequence : The frequency (in Hz) of the baud rate
-       generator's input clock.
-     - current-speed : The current speed setting (presumably by
-       firmware) of the baud rate generator.
-
-   Example Discovery BRG node:
-     brg@b200 {
-            compatible = "marvell,mv64360-brg";
-            reg = <0xb200 0x8>;
-            clock-src = <8>;
-            clock-frequency = <133333333>;
-            current-speed = <9600>;
-     };
-
-
-   f) Marvell Discovery CUNIT nodes
-
-   Represent the Serial Communications Unit device hardware.
-
-   Required properties:
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery CUNIT node:
-     cunit@f200 {
-            reg = <0xf200 0x200>;
-     };
-
-
-   g) Marvell Discovery MPSCROUTING nodes
-
-   Represent the Discovery's MPSC routing hardware
-
-   Required properties:
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery CUNIT node:
-     mpscrouting@b500 {
-            reg = <0xb400 0xc>;
-     };
-
-
-   h) Marvell Discovery MPSCINTR nodes
-
-   Represent the Discovery's MPSC DMA interrupt hardware registers
-   (SDMA cause and mask registers).
-
-   Required properties:
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery MPSCINTR node:
-     mpsintr@b800 {
-            reg = <0xb800 0x100>;
-     };
-
-
-   i) Marvell Discovery MPSC nodes
-
-   Represent the Discovery's MPSC (Multiprotocol Serial Controller)
-   serial port.
-
-   Required properties:
-     - device_type : "serial"
-     - compatible : "marvell,mv64360-mpsc"
-     - reg : Offset and length of the register set for this device
-     - sdma : the phandle for the SDMA node used by this port
-     - brg : the phandle for the BRG node used by this port
-     - cunit : the phandle for the CUNIT node used by this port
-     - mpscrouting : the phandle for the MPSCROUTING node used by this port
-     - mpscintr : the phandle for the MPSCINTR node used by this port
-     - cell-index : the hardware index of this cell in the MPSC core
-     - max_idle : value needed for MPSC CHR3 (Maximum Frame Length)
-       register
-     - interrupts : <a> where a is the interrupt number for the MPSC.
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery MPSCINTR node:
-     mpsc@8000 {
-            device_type = "serial";
-            compatible = "marvell,mv64360-mpsc";
-            reg = <0x8000 0x38>;
-            virtual-reg = <0xf1008000>;
-            sdma = <&SDMA0>;
-            brg = <&BRG0>;
-            cunit = <&CUNIT>;
-            mpscrouting = <&MPSCROUTING>;
-            mpscintr = <&MPSCINTR>;
-            cell-index = <0>;
-            max_idle = <40>;
-            interrupts = <40>;
-            interrupt-parent = <&PIC>;
-     };
-
-
-   j) Marvell Discovery Watch Dog Timer nodes
-
-   Represent the Discovery's watchdog timer hardware
-
-   Required properties:
-     - compatible : "marvell,mv64360-wdt"
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery Watch Dog Timer node:
-     wdt@b410 {
-            compatible = "marvell,mv64360-wdt";
-            reg = <0xb410 0x8>;
-     };
-
-
-   k) Marvell Discovery I2C nodes
-
-   Represent the Discovery's I2C hardware
-
-   Required properties:
-     - device_type : "i2c"
-     - compatible : "marvell,mv64360-i2c"
-     - reg : Offset and length of the register set for this device
-     - interrupts : <a> where a is the interrupt number for the I2C.
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery I2C node:
-            compatible = "marvell,mv64360-i2c";
-            reg = <0xc000 0x20>;
-            virtual-reg = <0xf100c000>;
-            interrupts = <37>;
-            interrupt-parent = <&PIC>;
-     };
-
-
-   l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes
-
-   Represent the Discovery's PIC hardware
-
-   Required properties:
-     - #interrupt-cells : <1>
-     - #address-cells : <0>
-     - compatible : "marvell,mv64360-pic"
-     - reg : Offset and length of the register set for this device
-     - interrupt-controller
-
-   Example Discovery PIC node:
-     pic {
-            #interrupt-cells = <1>;
-            #address-cells = <0>;
-            compatible = "marvell,mv64360-pic";
-            reg = <0x0 0x88>;
-            interrupt-controller;
-     };
-
-
-   m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes
-
-   Represent the Discovery's MPP hardware
-
-   Required properties:
-     - compatible : "marvell,mv64360-mpp"
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery MPP node:
-     mpp@f000 {
-            compatible = "marvell,mv64360-mpp";
-            reg = <0xf000 0x10>;
-     };
-
-
-   n) Marvell Discovery GPP (General Purpose Pins) nodes
-
-   Represent the Discovery's GPP hardware
-
-   Required properties:
-     - compatible : "marvell,mv64360-gpp"
-     - reg : Offset and length of the register set for this device
-
-   Example Discovery GPP node:
-     gpp@f000 {
-            compatible = "marvell,mv64360-gpp";
-            reg = <0xf100 0x20>;
-     };
-
-
-   o) Marvell Discovery PCI host bridge node
-
-   Represents the Discovery's PCI host bridge device.  The properties
-   for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE
-   1275-1994.  A typical value for the compatible property is
-   "marvell,mv64360-pci".
-
-   Example Discovery PCI host bridge node
-     pci@80000000 {
-            #address-cells = <3>;
-            #size-cells = <2>;
-            #interrupt-cells = <1>;
-            device_type = "pci";
-            compatible = "marvell,mv64360-pci";
-            reg = <0xcf8 0x8>;
-            ranges = <0x01000000 0x0        0x0
-                            0x88000000 0x0 0x01000000
-                      0x02000000 0x0 0x80000000
-                            0x80000000 0x0 0x08000000>;
-            bus-range = <0 255>;
-            clock-frequency = <66000000>;
-            interrupt-parent = <&PIC>;
-            interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
-            interrupt-map = <
-                    /* IDSEL 0x0a */
-                    0x5000 0 0 1 &PIC 80
-                    0x5000 0 0 2 &PIC 81
-                    0x5000 0 0 3 &PIC 91
-                    0x5000 0 0 4 &PIC 93
-
-                    /* IDSEL 0x0b */
-                    0x5800 0 0 1 &PIC 91
-                    0x5800 0 0 2 &PIC 93
-                    0x5800 0 0 3 &PIC 80
-                    0x5800 0 0 4 &PIC 81
-
-                    /* IDSEL 0x0c */
-                    0x6000 0 0 1 &PIC 91
-                    0x6000 0 0 2 &PIC 93
-                    0x6000 0 0 3 &PIC 80
-                    0x6000 0 0 4 &PIC 81
-
-                    /* IDSEL 0x0d */
-                    0x6800 0 0 1 &PIC 93
-                    0x6800 0 0 2 &PIC 80
-                    0x6800 0 0 3 &PIC 81
-                    0x6800 0 0 4 &PIC 91
-            >;
-     };
-
-
-   p) Marvell Discovery CPU Error nodes
-
-   Represent the Discovery's CPU error handler device.
-
-   Required properties:
-     - compatible : "marvell,mv64360-cpu-error"
-     - reg : Offset and length of the register set for this device
-     - interrupts : the interrupt number for this device
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery CPU Error node:
-     cpu-error@0070 {
-            compatible = "marvell,mv64360-cpu-error";
-            reg = <0x70 0x10 0x128 0x28>;
-            interrupts = <3>;
-            interrupt-parent = <&PIC>;
-     };
-
-
-   q) Marvell Discovery SRAM Controller nodes
-
-   Represent the Discovery's SRAM controller device.
-
-   Required properties:
-     - compatible : "marvell,mv64360-sram-ctrl"
-     - reg : Offset and length of the register set for this device
-     - interrupts : the interrupt number for this device
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery SRAM Controller node:
-     sram-ctrl@0380 {
-            compatible = "marvell,mv64360-sram-ctrl";
-            reg = <0x380 0x80>;
-            interrupts = <13>;
-            interrupt-parent = <&PIC>;
-     };
-
-
-   r) Marvell Discovery PCI Error Handler nodes
-
-   Represent the Discovery's PCI error handler device.
-
-   Required properties:
-     - compatible : "marvell,mv64360-pci-error"
-     - reg : Offset and length of the register set for this device
-     - interrupts : the interrupt number for this device
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery PCI Error Handler node:
-     pci-error@1d40 {
-            compatible = "marvell,mv64360-pci-error";
-            reg = <0x1d40 0x40 0xc28 0x4>;
-            interrupts = <12>;
-            interrupt-parent = <&PIC>;
-     };
-
-
-   s) Marvell Discovery Memory Controller nodes
-
-   Represent the Discovery's memory controller device.
-
-   Required properties:
-     - compatible : "marvell,mv64360-mem-ctrl"
-     - reg : Offset and length of the register set for this device
-     - interrupts : the interrupt number for this device
-     - interrupt-parent : the phandle for the interrupt controller
-       that services interrupts for this device.
-
-   Example Discovery Memory Controller node:
-     mem-ctrl@1400 {
-            compatible = "marvell,mv64360-mem-ctrl";
-            reg = <0x1400 0x60>;
-            interrupts = <17>;
-            interrupt-parent = <&PIC>;
-     };
-
-
-VIII - Specifying interrupt information for devices
+VII - Specifying interrupt information for devices
 ===================================================
 
 The device tree represents the busses and devices of a hardware
@@ -2439,56 +1324,7 @@ encodings listed below:
        2 =  high to low edge sensitive type enabled
        3 =  low to high edge sensitive type enabled
 
-IX - Specifying GPIO information for devices
-============================================
-
-1) gpios property
------------------
-
-Nodes that makes use of GPIOs should define them using `gpios' property,
-format of which is: <&gpio-controller1-phandle gpio1-specifier
-                    &gpio-controller2-phandle gpio2-specifier
-                    0 /* holes are permitted, means no GPIO 3 */
-                    &gpio-controller4-phandle gpio4-specifier
-                    ...>;
-
-Note that gpio-specifier length is controller dependent.
-
-gpio-specifier may encode: bank, pin position inside the bank,
-whether pin is open-drain and whether pin is logically inverted.
-
-Example of the node using GPIOs:
-
-       node {
-               gpios = <&qe_pio_e 18 0>;
-       };
-
-In this example gpio-specifier is "18 0" and encodes GPIO pin number,
-and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller.
-
-2) gpio-controller nodes
-------------------------
-
-Every GPIO controller node must have #gpio-cells property defined,
-this information will be used to translate gpio-specifiers.
-
-Example of two SOC GPIO banks defined as gpio-controller nodes:
-
-       qe_pio_a: gpio-controller@1400 {
-               #gpio-cells = <2>;
-               compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
-               reg = <0x1400 0x18>;
-               gpio-controller;
-       };
-
-       qe_pio_e: gpio-controller@1460 {
-               #gpio-cells = <2>;
-               compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
-               reg = <0x1460 0x18>;
-               gpio-controller;
-       };
-
-X - Specifying Device Power Management Information (sleep property)
+VIII - Specifying Device Power Management Information (sleep property)
 ===================================================================
 
 Devices on SOCs often have mechanisms for placing devices into low-power
diff --git a/Documentation/powerpc/dts-bindings/4xx/emac.txt b/Documentation/powerpc/dts-bindings/4xx/emac.txt
new file mode 100644 (file)
index 0000000..2161334
--- /dev/null
@@ -0,0 +1,148 @@
+    4xx/Axon EMAC ethernet nodes
+
+    The EMAC ethernet controller in IBM and AMCC 4xx chips, and also
+    the Axon bridge.  To operate this needs to interact with a ths
+    special McMAL DMA controller, and sometimes an RGMII or ZMII
+    interface.  In addition to the nodes and properties described
+    below, the node for the OPB bus on which the EMAC sits must have a
+    correct clock-frequency property.
+
+      i) The EMAC node itself
+
+    Required properties:
+    - device_type       : "network"
+
+    - compatible        : compatible list, contains 2 entries, first is
+                         "ibm,emac-CHIP" where CHIP is the host ASIC (440gx,
+                         405gp, Axon) and second is either "ibm,emac" or
+                         "ibm,emac4".  For Axon, thus, we have: "ibm,emac-axon",
+                         "ibm,emac4"
+    - interrupts        : <interrupt mapping for EMAC IRQ and WOL IRQ>
+    - interrupt-parent  : optional, if needed for interrupt mapping
+    - reg               : <registers mapping>
+    - local-mac-address : 6 bytes, MAC address
+    - mal-device        : phandle of the associated McMAL node
+    - mal-tx-channel    : 1 cell, index of the tx channel on McMAL associated
+                         with this EMAC
+    - mal-rx-channel    : 1 cell, index of the rx channel on McMAL associated
+                         with this EMAC
+    - cell-index        : 1 cell, hardware index of the EMAC cell on a given
+                         ASIC (typically 0x0 and 0x1 for EMAC0 and EMAC1 on
+                         each Axon chip)
+    - max-frame-size    : 1 cell, maximum frame size supported in bytes
+    - rx-fifo-size      : 1 cell, Rx fifo size in bytes for 10 and 100 Mb/sec
+                         operations.
+                         For Axon, 2048
+    - tx-fifo-size      : 1 cell, Tx fifo size in bytes for 10 and 100 Mb/sec
+                         operations.
+                         For Axon, 2048.
+    - fifo-entry-size   : 1 cell, size of a fifo entry (used to calculate
+                         thresholds).
+                         For Axon, 0x00000010
+    - mal-burst-size    : 1 cell, MAL burst size (used to calculate thresholds)
+                         in bytes.
+                         For Axon, 0x00000100 (I think ...)
+    - phy-mode          : string, mode of operations of the PHY interface.
+                         Supported values are: "mii", "rmii", "smii", "rgmii",
+                         "tbi", "gmii", rtbi", "sgmii".
+                         For Axon on CAB, it is "rgmii"
+    - mdio-device       : 1 cell, required iff using shared MDIO registers
+                         (440EP).  phandle of the EMAC to use to drive the
+                         MDIO lines for the PHY used by this EMAC.
+    - zmii-device       : 1 cell, required iff connected to a ZMII.  phandle of
+                         the ZMII device node
+    - zmii-channel      : 1 cell, required iff connected to a ZMII.  Which ZMII
+                         channel or 0xffffffff if ZMII is only used for MDIO.
+    - rgmii-device      : 1 cell, required iff connected to an RGMII. phandle
+                         of the RGMII device node.
+                         For Axon: phandle of plb5/plb4/opb/rgmii
+    - rgmii-channel     : 1 cell, required iff connected to an RGMII.  Which
+                         RGMII channel is used by this EMAC.
+                         Fox Axon: present, whatever value is appropriate for each
+                         EMAC, that is the content of the current (bogus) "phy-port"
+                         property.
+
+    Optional properties:
+    - phy-address       : 1 cell, optional, MDIO address of the PHY. If absent,
+                         a search is performed.
+    - phy-map           : 1 cell, optional, bitmap of addresses to probe the PHY
+                         for, used if phy-address is absent. bit 0x00000001 is
+                         MDIO address 0.
+                         For Axon it can be absent, though my current driver
+                         doesn't handle phy-address yet so for now, keep
+                         0x00ffffff in it.
+    - rx-fifo-size-gige : 1 cell, Rx fifo size in bytes for 1000 Mb/sec
+                         operations (if absent the value is the same as
+                         rx-fifo-size).  For Axon, either absent or 2048.
+    - tx-fifo-size-gige : 1 cell, Tx fifo size in bytes for 1000 Mb/sec
+                         operations (if absent the value is the same as
+                         tx-fifo-size). For Axon, either absent or 2048.
+    - tah-device        : 1 cell, optional. If connected to a TAH engine for
+                         offload, phandle of the TAH device node.
+    - tah-channel       : 1 cell, optional. If appropriate, channel used on the
+                         TAH engine.
+
+    Example:
+
+       EMAC0: ethernet@40000800 {
+               device_type = "network";
+               compatible = "ibm,emac-440gp", "ibm,emac";
+               interrupt-parent = <&UIC1>;
+               interrupts = <1c 4 1d 4>;
+               reg = <40000800 70>;
+               local-mac-address = [00 04 AC E3 1B 1E];
+               mal-device = <&MAL0>;
+               mal-tx-channel = <0 1>;
+               mal-rx-channel = <0>;
+               cell-index = <0>;
+               max-frame-size = <5dc>;
+               rx-fifo-size = <1000>;
+               tx-fifo-size = <800>;
+               phy-mode = "rmii";
+               phy-map = <00000001>;
+               zmii-device = <&ZMII0>;
+               zmii-channel = <0>;
+       };
+
+      ii) McMAL node
+
+    Required properties:
+    - device_type        : "dma-controller"
+    - compatible         : compatible list, containing 2 entries, first is
+                          "ibm,mcmal-CHIP" where CHIP is the host ASIC (like
+                          emac) and the second is either "ibm,mcmal" or
+                          "ibm,mcmal2".
+                          For Axon, "ibm,mcmal-axon","ibm,mcmal2"
+    - interrupts         : <interrupt mapping for the MAL interrupts sources:
+                           5 sources: tx_eob, rx_eob, serr, txde, rxde>.
+                           For Axon: This is _different_ from the current
+                          firmware.  We use the "delayed" interrupts for txeob
+                          and rxeob. Thus we end up with mapping those 5 MPIC
+                          interrupts, all level positive sensitive: 10, 11, 32,
+                          33, 34 (in decimal)
+    - dcr-reg            : < DCR registers range >
+    - dcr-parent         : if needed for dcr-reg
+    - num-tx-chans       : 1 cell, number of Tx channels
+    - num-rx-chans       : 1 cell, number of Rx channels
+
+      iii) ZMII node
+
+    Required properties:
+    - compatible         : compatible list, containing 2 entries, first is
+                          "ibm,zmii-CHIP" where CHIP is the host ASIC (like
+                          EMAC) and the second is "ibm,zmii".
+                          For Axon, there is no ZMII node.
+    - reg                : <registers mapping>
+
+      iv) RGMII node
+
+    Required properties:
+    - compatible         : compatible list, containing 2 entries, first is
+                          "ibm,rgmii-CHIP" where CHIP is the host ASIC (like
+                          EMAC) and the second is "ibm,rgmii".
+                           For Axon, "ibm,rgmii-axon","ibm,rgmii"
+    - reg                : <registers mapping>
+    - revision           : as provided by the RGMII new version register if
+                          available.
+                          For Axon: 0x0000012a
+
diff --git a/Documentation/powerpc/dts-bindings/gpio/gpio.txt b/Documentation/powerpc/dts-bindings/gpio/gpio.txt
new file mode 100644 (file)
index 0000000..edaa84d
--- /dev/null
@@ -0,0 +1,50 @@
+Specifying GPIO information for devices
+============================================
+
+1) gpios property
+-----------------
+
+Nodes that makes use of GPIOs should define them using `gpios' property,
+format of which is: <&gpio-controller1-phandle gpio1-specifier
+                    &gpio-controller2-phandle gpio2-specifier
+                    0 /* holes are permitted, means no GPIO 3 */
+                    &gpio-controller4-phandle gpio4-specifier
+                    ...>;
+
+Note that gpio-specifier length is controller dependent.
+
+gpio-specifier may encode: bank, pin position inside the bank,
+whether pin is open-drain and whether pin is logically inverted.
+
+Example of the node using GPIOs:
+
+       node {
+               gpios = <&qe_pio_e 18 0>;
+       };
+
+In this example gpio-specifier is "18 0" and encodes GPIO pin number,
+and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller.
+
+2) gpio-controller nodes
+------------------------
+
+Every GPIO controller node must have #gpio-cells property defined,
+this information will be used to translate gpio-specifiers.
+
+Example of two SOC GPIO banks defined as gpio-controller nodes:
+
+       qe_pio_a: gpio-controller@1400 {
+               #gpio-cells = <2>;
+               compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank";
+               reg = <0x1400 0x18>;
+               gpio-controller;
+       };
+
+       qe_pio_e: gpio-controller@1460 {
+               #gpio-cells = <2>;
+               compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
+               reg = <0x1460 0x18>;
+               gpio-controller;
+       };
+
+
index 4fe14deedc0a3e5aa3988288873c5e4f9a2ee01c..064db928c3c12cc3d6141664e57d25e7050520ed 100644 (file)
@@ -16,10 +16,17 @@ LED sub-node properties:
   string defining the trigger assigned to the LED.  Current triggers are:
     "backlight" - LED will act as a back-light, controlled by the framebuffer
                  system
-    "default-on" - LED will turn on
+    "default-on" - LED will turn on, but see "default-state" below
     "heartbeat" - LED "double" flashes at a load average based rate
     "ide-disk" - LED indicates disk activity
     "timer" - LED flashes at a fixed, configurable rate
+- default-state:  (optional) The initial state of the LED.  Valid
+  values are "on", "off", and "keep".  If the LED is already on or off
+  and the default-state property is set the to same value, then no
+  glitch should be produced where the LED momentarily turns off (or
+  on).  The "keep" setting will keep the LED at whatever its current
+  state is, without producing a glitch.  The default is off if this
+  property is not present.
 
 Examples:
 
@@ -30,14 +37,22 @@ leds {
                gpios = <&mcu_pio 0 1>; /* Active low */
                linux,default-trigger = "ide-disk";
        };
+
+       fault {
+               gpios = <&mcu_pio 1 0>;
+               /* Keep LED on if BIOS detected hardware fault */
+               default-state = "keep";
+       };
 };
 
 run-control {
        compatible = "gpio-leds";
        red {
                gpios = <&mpc8572 6 0>;
+               default-state = "off";
        };
        green {
                gpios = <&mpc8572 7 0>;
+               default-state = "on";
        };
 }
diff --git a/Documentation/powerpc/dts-bindings/gpio/mdio.txt b/Documentation/powerpc/dts-bindings/gpio/mdio.txt
new file mode 100644 (file)
index 0000000..bc95495
--- /dev/null
@@ -0,0 +1,19 @@
+MDIO on GPIOs
+
+Currently defined compatibles:
+- virtual,gpio-mdio
+
+MDC and MDIO lines connected to GPIO controllers are listed in the
+gpios property as described in section VIII.1 in the following order:
+
+MDC, MDIO.
+
+Example:
+
+mdio {
+       compatible = "virtual,mdio-gpio";
+       #address-cells = <1>;
+       #size-cells = <0>;
+       gpios = <&qe_pio_a 11
+                &qe_pio_c 6>;
+};
diff --git a/Documentation/powerpc/dts-bindings/marvell.txt b/Documentation/powerpc/dts-bindings/marvell.txt
new file mode 100644 (file)
index 0000000..3708a2f
--- /dev/null
@@ -0,0 +1,521 @@
+Marvell Discovery mv64[345]6x System Controller chips
+===========================================================
+
+The Marvell mv64[345]60 series of system controller chips contain
+many of the peripherals needed to implement a complete computer
+system.  In this section, we define device tree nodes to describe
+the system controller chip itself and each of the peripherals
+which it contains.  Compatible string values for each node are
+prefixed with the string "marvell,", for Marvell Technology Group Ltd.
+
+1) The /system-controller node
+
+  This node is used to represent the system-controller and must be
+  present when the system uses a system controller chip. The top-level
+  system-controller node contains information that is global to all
+  devices within the system controller chip. The node name begins
+  with "system-controller" followed by the unit address, which is
+  the base address of the memory-mapped register set for the system
+  controller chip.
+
+  Required properties:
+
+    - ranges : Describes the translation of system controller addresses
+      for memory mapped registers.
+    - clock-frequency: Contains the main clock frequency for the system
+      controller chip.
+    - reg : This property defines the address and size of the
+      memory-mapped registers contained within the system controller
+      chip.  The address specified in the "reg" property should match
+      the unit address of the system-controller node.
+    - #address-cells : Address representation for system controller
+      devices.  This field represents the number of cells needed to
+      represent the address of the memory-mapped registers of devices
+      within the system controller chip.
+    - #size-cells : Size representation for for the memory-mapped
+      registers within the system controller chip.
+    - #interrupt-cells : Defines the width of cells used to represent
+      interrupts.
+
+  Optional properties:
+
+    - model : The specific model of the system controller chip.  Such
+      as, "mv64360", "mv64460", or "mv64560".
+    - compatible : A string identifying the compatibility identifiers
+      of the system controller chip.
+
+  The system-controller node contains child nodes for each system
+  controller device that the platform uses.  Nodes should not be created
+  for devices which exist on the system controller chip but are not used
+
+  Example Marvell Discovery mv64360 system-controller node:
+
+    system-controller@f1000000 { /* Marvell Discovery mv64360 */
+           #address-cells = <1>;
+           #size-cells = <1>;
+           model = "mv64360";                      /* Default */
+           compatible = "marvell,mv64360";
+           clock-frequency = <133333333>;
+           reg = <0xf1000000 0x10000>;
+           virtual-reg = <0xf1000000>;
+           ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */
+                   0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */
+                   0xa0000000 0xa0000000 0x4000000 /* User FLASH */
+                   0x00000000 0xf1000000 0x0010000 /* Bridge's regs */
+                   0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */
+
+           [ child node definitions... ]
+    }
+
+2) Child nodes of /system-controller
+
+   a) Marvell Discovery MDIO bus
+
+   The MDIO is a bus to which the PHY devices are connected.  For each
+   device that exists on this bus, a child node should be created.  See
+   the definition of the PHY node below for an example of how to define
+   a PHY.
+
+   Required properties:
+     - #address-cells : Should be <1>
+     - #size-cells : Should be <0>
+     - device_type : Should be "mdio"
+     - compatible : Should be "marvell,mv64360-mdio"
+
+   Example:
+
+     mdio {
+            #address-cells = <1>;
+            #size-cells = <0>;
+            device_type = "mdio";
+            compatible = "marvell,mv64360-mdio";
+
+            ethernet-phy@0 {
+                    ......
+            };
+     };
+
+
+   b) Marvell Discovery ethernet controller
+
+   The Discover ethernet controller is described with two levels
+   of nodes.  The first level describes an ethernet silicon block
+   and the second level describes up to 3 ethernet nodes within
+   that block.  The reason for the multiple levels is that the
+   registers for the node are interleaved within a single set
+   of registers.  The "ethernet-block" level describes the
+   shared register set, and the "ethernet" nodes describe ethernet
+   port-specific properties.
+
+   Ethernet block node
+
+   Required properties:
+     - #address-cells : <1>
+     - #size-cells : <0>
+     - compatible : "marvell,mv64360-eth-block"
+     - reg : Offset and length of the register set for this block
+
+   Example Discovery Ethernet block node:
+     ethernet-block@2000 {
+            #address-cells = <1>;
+            #size-cells = <0>;
+            compatible = "marvell,mv64360-eth-block";
+            reg = <0x2000 0x2000>;
+            ethernet@0 {
+                    .......
+            };
+     };
+
+   Ethernet port node
+
+   Required properties:
+     - device_type : Should be "network".
+     - compatible : Should be "marvell,mv64360-eth".
+     - reg : Should be <0>, <1>, or <2>, according to which registers
+       within the silicon block the device uses.
+     - interrupts : <a> where a is the interrupt number for the port.
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+     - phy : the phandle for the PHY connected to this ethernet
+       controller.
+     - local-mac-address : 6 bytes, MAC address
+
+   Example Discovery Ethernet port node:
+     ethernet@0 {
+            device_type = "network";
+            compatible = "marvell,mv64360-eth";
+            reg = <0>;
+            interrupts = <32>;
+            interrupt-parent = <&PIC>;
+            phy = <&PHY0>;
+            local-mac-address = [ 00 00 00 00 00 00 ];
+     };
+
+
+
+   c) Marvell Discovery PHY nodes
+
+   Required properties:
+     - device_type : Should be "ethernet-phy"
+     - interrupts : <a> where a is the interrupt number for this phy.
+     - interrupt-parent : the phandle for the interrupt controller that
+       services interrupts for this device.
+     - reg : The ID number for the phy, usually a small integer
+
+   Example Discovery PHY node:
+     ethernet-phy@1 {
+            device_type = "ethernet-phy";
+            compatible = "broadcom,bcm5421";
+            interrupts = <76>;      /* GPP 12 */
+            interrupt-parent = <&PIC>;
+            reg = <1>;
+     };
+
+
+   d) Marvell Discovery SDMA nodes
+
+   Represent DMA hardware associated with the MPSC (multiprotocol
+   serial controllers).
+
+   Required properties:
+     - compatible : "marvell,mv64360-sdma"
+     - reg : Offset and length of the register set for this device
+     - interrupts : <a> where a is the interrupt number for the DMA
+       device.
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery SDMA node:
+     sdma@4000 {
+            compatible = "marvell,mv64360-sdma";
+            reg = <0x4000 0xc18>;
+            virtual-reg = <0xf1004000>;
+            interrupts = <36>;
+            interrupt-parent = <&PIC>;
+     };
+
+
+   e) Marvell Discovery BRG nodes
+
+   Represent baud rate generator hardware associated with the MPSC
+   (multiprotocol serial controllers).
+
+   Required properties:
+     - compatible : "marvell,mv64360-brg"
+     - reg : Offset and length of the register set for this device
+     - clock-src : A value from 0 to 15 which selects the clock
+       source for the baud rate generator.  This value corresponds
+       to the CLKS value in the BRGx configuration register.  See
+       the mv64x60 User's Manual.
+     - clock-frequence : The frequency (in Hz) of the baud rate
+       generator's input clock.
+     - current-speed : The current speed setting (presumably by
+       firmware) of the baud rate generator.
+
+   Example Discovery BRG node:
+     brg@b200 {
+            compatible = "marvell,mv64360-brg";
+            reg = <0xb200 0x8>;
+            clock-src = <8>;
+            clock-frequency = <133333333>;
+            current-speed = <9600>;
+     };
+
+
+   f) Marvell Discovery CUNIT nodes
+
+   Represent the Serial Communications Unit device hardware.
+
+   Required properties:
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery CUNIT node:
+     cunit@f200 {
+            reg = <0xf200 0x200>;
+     };
+
+
+   g) Marvell Discovery MPSCROUTING nodes
+
+   Represent the Discovery's MPSC routing hardware
+
+   Required properties:
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery CUNIT node:
+     mpscrouting@b500 {
+            reg = <0xb400 0xc>;
+     };
+
+
+   h) Marvell Discovery MPSCINTR nodes
+
+   Represent the Discovery's MPSC DMA interrupt hardware registers
+   (SDMA cause and mask registers).
+
+   Required properties:
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery MPSCINTR node:
+     mpsintr@b800 {
+            reg = <0xb800 0x100>;
+     };
+
+
+   i) Marvell Discovery MPSC nodes
+
+   Represent the Discovery's MPSC (Multiprotocol Serial Controller)
+   serial port.
+
+   Required properties:
+     - device_type : "serial"
+     - compatible : "marvell,mv64360-mpsc"
+     - reg : Offset and length of the register set for this device
+     - sdma : the phandle for the SDMA node used by this port
+     - brg : the phandle for the BRG node used by this port
+     - cunit : the phandle for the CUNIT node used by this port
+     - mpscrouting : the phandle for the MPSCROUTING node used by this port
+     - mpscintr : the phandle for the MPSCINTR node used by this port
+     - cell-index : the hardware index of this cell in the MPSC core
+     - max_idle : value needed for MPSC CHR3 (Maximum Frame Length)
+       register
+     - interrupts : <a> where a is the interrupt number for the MPSC.
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery MPSCINTR node:
+     mpsc@8000 {
+            device_type = "serial";
+            compatible = "marvell,mv64360-mpsc";
+            reg = <0x8000 0x38>;
+            virtual-reg = <0xf1008000>;
+            sdma = <&SDMA0>;
+            brg = <&BRG0>;
+            cunit = <&CUNIT>;
+            mpscrouting = <&MPSCROUTING>;
+            mpscintr = <&MPSCINTR>;
+            cell-index = <0>;
+            max_idle = <40>;
+            interrupts = <40>;
+            interrupt-parent = <&PIC>;
+     };
+
+
+   j) Marvell Discovery Watch Dog Timer nodes
+
+   Represent the Discovery's watchdog timer hardware
+
+   Required properties:
+     - compatible : "marvell,mv64360-wdt"
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery Watch Dog Timer node:
+     wdt@b410 {
+            compatible = "marvell,mv64360-wdt";
+            reg = <0xb410 0x8>;
+     };
+
+
+   k) Marvell Discovery I2C nodes
+
+   Represent the Discovery's I2C hardware
+
+   Required properties:
+     - device_type : "i2c"
+     - compatible : "marvell,mv64360-i2c"
+     - reg : Offset and length of the register set for this device
+     - interrupts : <a> where a is the interrupt number for the I2C.
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery I2C node:
+            compatible = "marvell,mv64360-i2c";
+            reg = <0xc000 0x20>;
+            virtual-reg = <0xf100c000>;
+            interrupts = <37>;
+            interrupt-parent = <&PIC>;
+     };
+
+
+   l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes
+
+   Represent the Discovery's PIC hardware
+
+   Required properties:
+     - #interrupt-cells : <1>
+     - #address-cells : <0>
+     - compatible : "marvell,mv64360-pic"
+     - reg : Offset and length of the register set for this device
+     - interrupt-controller
+
+   Example Discovery PIC node:
+     pic {
+            #interrupt-cells = <1>;
+            #address-cells = <0>;
+            compatible = "marvell,mv64360-pic";
+            reg = <0x0 0x88>;
+            interrupt-controller;
+     };
+
+
+   m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes
+
+   Represent the Discovery's MPP hardware
+
+   Required properties:
+     - compatible : "marvell,mv64360-mpp"
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery MPP node:
+     mpp@f000 {
+            compatible = "marvell,mv64360-mpp";
+            reg = <0xf000 0x10>;
+     };
+
+
+   n) Marvell Discovery GPP (General Purpose Pins) nodes
+
+   Represent the Discovery's GPP hardware
+
+   Required properties:
+     - compatible : "marvell,mv64360-gpp"
+     - reg : Offset and length of the register set for this device
+
+   Example Discovery GPP node:
+     gpp@f000 {
+            compatible = "marvell,mv64360-gpp";
+            reg = <0xf100 0x20>;
+     };
+
+
+   o) Marvell Discovery PCI host bridge node
+
+   Represents the Discovery's PCI host bridge device.  The properties
+   for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE
+   1275-1994.  A typical value for the compatible property is
+   "marvell,mv64360-pci".
+
+   Example Discovery PCI host bridge node
+     pci@80000000 {
+            #address-cells = <3>;
+            #size-cells = <2>;
+            #interrupt-cells = <1>;
+            device_type = "pci";
+            compatible = "marvell,mv64360-pci";
+            reg = <0xcf8 0x8>;
+            ranges = <0x01000000 0x0        0x0
+                            0x88000000 0x0 0x01000000
+                      0x02000000 0x0 0x80000000
+                            0x80000000 0x0 0x08000000>;
+            bus-range = <0 255>;
+            clock-frequency = <66000000>;
+            interrupt-parent = <&PIC>;
+            interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+            interrupt-map = <
+                    /* IDSEL 0x0a */
+                    0x5000 0 0 1 &PIC 80
+                    0x5000 0 0 2 &PIC 81
+                    0x5000 0 0 3 &PIC 91
+                    0x5000 0 0 4 &PIC 93
+
+                    /* IDSEL 0x0b */
+                    0x5800 0 0 1 &PIC 91
+                    0x5800 0 0 2 &PIC 93
+                    0x5800 0 0 3 &PIC 80
+                    0x5800 0 0 4 &PIC 81
+
+                    /* IDSEL 0x0c */
+                    0x6000 0 0 1 &PIC 91
+                    0x6000 0 0 2 &PIC 93
+                    0x6000 0 0 3 &PIC 80
+                    0x6000 0 0 4 &PIC 81
+
+                    /* IDSEL 0x0d */
+                    0x6800 0 0 1 &PIC 93
+                    0x6800 0 0 2 &PIC 80
+                    0x6800 0 0 3 &PIC 81
+                    0x6800 0 0 4 &PIC 91
+            >;
+     };
+
+
+   p) Marvell Discovery CPU Error nodes
+
+   Represent the Discovery's CPU error handler device.
+
+   Required properties:
+     - compatible : "marvell,mv64360-cpu-error"
+     - reg : Offset and length of the register set for this device
+     - interrupts : the interrupt number for this device
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery CPU Error node:
+     cpu-error@0070 {
+            compatible = "marvell,mv64360-cpu-error";
+            reg = <0x70 0x10 0x128 0x28>;
+            interrupts = <3>;
+            interrupt-parent = <&PIC>;
+     };
+
+
+   q) Marvell Discovery SRAM Controller nodes
+
+   Represent the Discovery's SRAM controller device.
+
+   Required properties:
+     - compatible : "marvell,mv64360-sram-ctrl"
+     - reg : Offset and length of the register set for this device
+     - interrupts : the interrupt number for this device
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery SRAM Controller node:
+     sram-ctrl@0380 {
+            compatible = "marvell,mv64360-sram-ctrl";
+            reg = <0x380 0x80>;
+            interrupts = <13>;
+            interrupt-parent = <&PIC>;
+     };
+
+
+   r) Marvell Discovery PCI Error Handler nodes
+
+   Represent the Discovery's PCI error handler device.
+
+   Required properties:
+     - compatible : "marvell,mv64360-pci-error"
+     - reg : Offset and length of the register set for this device
+     - interrupts : the interrupt number for this device
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery PCI Error Handler node:
+     pci-error@1d40 {
+            compatible = "marvell,mv64360-pci-error";
+            reg = <0x1d40 0x40 0xc28 0x4>;
+            interrupts = <12>;
+            interrupt-parent = <&PIC>;
+     };
+
+
+   s) Marvell Discovery Memory Controller nodes
+
+   Represent the Discovery's memory controller device.
+
+   Required properties:
+     - compatible : "marvell,mv64360-mem-ctrl"
+     - reg : Offset and length of the register set for this device
+     - interrupts : the interrupt number for this device
+     - interrupt-parent : the phandle for the interrupt controller
+       that services interrupts for this device.
+
+   Example Discovery Memory Controller node:
+     mem-ctrl@1400 {
+            compatible = "marvell,mv64360-mem-ctrl";
+            reg = <0x1400 0x60>;
+            interrupts = <17>;
+            interrupt-parent = <&PIC>;
+     };
+
+
diff --git a/Documentation/powerpc/dts-bindings/phy.txt b/Documentation/powerpc/dts-bindings/phy.txt
new file mode 100644 (file)
index 0000000..bb8c742
--- /dev/null
@@ -0,0 +1,25 @@
+PHY nodes
+
+Required properties:
+
+ - device_type : Should be "ethernet-phy"
+ - interrupts : <a b> where a is the interrupt number and b is a
+   field that represents an encoding of the sense and level
+   information for the interrupt.  This should be encoded based on
+   the information in section 2) depending on the type of interrupt
+   controller you have.
+ - interrupt-parent : the phandle for the interrupt controller that
+   services interrupts for this device.
+ - reg : The ID number for the phy, usually a small integer
+ - linux,phandle :  phandle for this node; likely referenced by an
+   ethernet controller node.
+
+Example:
+
+ethernet-phy@0 {
+       linux,phandle = <2452000>
+       interrupt-parent = <40000>;
+       interrupts = <35 1>;
+       reg = <0>;
+       device_type = "ethernet-phy";
+};
diff --git a/Documentation/powerpc/dts-bindings/spi-bus.txt b/Documentation/powerpc/dts-bindings/spi-bus.txt
new file mode 100644 (file)
index 0000000..e782add
--- /dev/null
@@ -0,0 +1,57 @@
+SPI (Serial Peripheral Interface) busses
+
+SPI busses can be described with a node for the SPI master device
+and a set of child nodes for each SPI slave on the bus.  For this
+discussion, it is assumed that the system's SPI controller is in
+SPI master mode.  This binding does not describe SPI controllers
+in slave mode.
+
+The SPI master node requires the following properties:
+- #address-cells  - number of cells required to define a chip select
+               address on the SPI bus.
+- #size-cells     - should be zero.
+- compatible      - name of SPI bus controller following generic names
+               recommended practice.
+No other properties are required in the SPI bus node.  It is assumed
+that a driver for an SPI bus device will understand that it is an SPI bus.
+However, the binding does not attempt to define the specific method for
+assigning chip select numbers.  Since SPI chip select configuration is
+flexible and non-standardized, it is left out of this binding with the
+assumption that board specific platform code will be used to manage
+chip selects.  Individual drivers can define additional properties to
+support describing the chip select layout.
+
+SPI slave nodes must be children of the SPI master node and can
+contain the following properties.
+- reg             - (required) chip select address of device.
+- compatible      - (required) name of SPI device following generic names
+               recommended practice
+- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz
+- spi-cpol        - (optional) Empty property indicating device requires
+               inverse clock polarity (CPOL) mode
+- spi-cpha        - (optional) Empty property indicating device requires
+               shifted clock phase (CPHA) mode
+- spi-cs-high     - (optional) Empty property indicating device requires
+               chip select active high
+
+SPI example for an MPC5200 SPI bus:
+       spi@f00 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
+               reg = <0xf00 0x20>;
+               interrupts = <2 13 0 2 14 0>;
+               interrupt-parent = <&mpc5200_pic>;
+
+               ethernet-switch@0 {
+                       compatible = "micrel,ks8995m";
+                       spi-max-frequency = <1000000>;
+                       reg = <0>;
+               };
+
+               codec@1 {
+                       compatible = "ti,tlv320aic26";
+                       spi-max-frequency = <100000>;
+                       reg = <1>;
+               };
+       };
diff --git a/Documentation/powerpc/dts-bindings/usb-ehci.txt b/Documentation/powerpc/dts-bindings/usb-ehci.txt
new file mode 100644 (file)
index 0000000..fa18612
--- /dev/null
@@ -0,0 +1,25 @@
+USB EHCI controllers
+
+Required properties:
+  - compatible : should be "usb-ehci".
+  - reg : should contain at least address and length of the standard EHCI
+    register set for the device. Optional platform-dependent registers
+    (debug-port or other) can be also specified here, but only after
+    definition of standard EHCI registers.
+  - interrupts : one EHCI interrupt should be described here.
+If device registers are implemented in big endian mode, the device
+node should have "big-endian-regs" property.
+If controller implementation operates with big endian descriptors,
+"big-endian-desc" property should be specified.
+If both big endian registers and descriptors are used by the controller
+implementation, "big-endian" property can be specified instead of having
+both "big-endian-regs" and "big-endian-desc".
+
+Example (Sequoia 440EPx):
+    ehci@e0000300 {
+          compatible = "ibm,usb-ehci-440epx", "usb-ehci";
+          interrupt-parent = <&UIC0>;
+          interrupts = <1a 4>;
+          reg = <0 e0000300 90 0 e0000390 70>;
+          big-endian;
+   };
diff --git a/Documentation/powerpc/dts-bindings/xilinx.txt b/Documentation/powerpc/dts-bindings/xilinx.txt
new file mode 100644 (file)
index 0000000..80339fe
--- /dev/null
@@ -0,0 +1,295 @@
+   d) Xilinx IP cores
+
+   The Xilinx EDK toolchain ships with a set of IP cores (devices) for use
+   in Xilinx Spartan and Virtex FPGAs.  The devices cover the whole range
+   of standard device types (network, serial, etc.) and miscellaneous
+   devices (gpio, LCD, spi, etc).  Also, since these devices are
+   implemented within the fpga fabric every instance of the device can be
+   synthesised with different options that change the behaviour.
+
+   Each IP-core has a set of parameters which the FPGA designer can use to
+   control how the core is synthesized.  Historically, the EDK tool would
+   extract the device parameters relevant to device drivers and copy them
+   into an 'xparameters.h' in the form of #define symbols.  This tells the
+   device drivers how the IP cores are configured, but it requres the kernel
+   to be recompiled every time the FPGA bitstream is resynthesized.
+
+   The new approach is to export the parameters into the device tree and
+   generate a new device tree each time the FPGA bitstream changes.  The
+   parameters which used to be exported as #defines will now become
+   properties of the device node.  In general, device nodes for IP-cores
+   will take the following form:
+
+       (name): (generic-name)@(base-address) {
+               compatible = "xlnx,(ip-core-name)-(HW_VER)"
+                            [, (list of compatible devices), ...];
+               reg = <(baseaddr) (size)>;
+               interrupt-parent = <&interrupt-controller-phandle>;
+               interrupts = < ... >;
+               xlnx,(parameter1) = "(string-value)";
+               xlnx,(parameter2) = <(int-value)>;
+       };
+
+       (generic-name):   an open firmware-style name that describes the
+                       generic class of device.  Preferably, this is one word, such
+                       as 'serial' or 'ethernet'.
+       (ip-core-name): the name of the ip block (given after the BEGIN
+                       directive in system.mhs).  Should be in lowercase
+                       and all underscores '_' converted to dashes '-'.
+       (name):         is derived from the "PARAMETER INSTANCE" value.
+       (parameter#):   C_* parameters from system.mhs.  The C_ prefix is
+                       dropped from the parameter name, the name is converted
+                       to lowercase and all underscore '_' characters are
+                       converted to dashes '-'.
+       (baseaddr):     the baseaddr parameter value (often named C_BASEADDR).
+       (HW_VER):       from the HW_VER parameter.
+       (size):         the address range size (often C_HIGHADDR - C_BASEADDR + 1).
+
+   Typically, the compatible list will include the exact IP core version
+   followed by an older IP core version which implements the same
+   interface or any other device with the same interface.
+
+   'reg', 'interrupt-parent' and 'interrupts' are all optional properties.
+
+   For example, the following block from system.mhs:
+
+       BEGIN opb_uartlite
+               PARAMETER INSTANCE = opb_uartlite_0
+               PARAMETER HW_VER = 1.00.b
+               PARAMETER C_BAUDRATE = 115200
+               PARAMETER C_DATA_BITS = 8
+               PARAMETER C_ODD_PARITY = 0
+               PARAMETER C_USE_PARITY = 0
+               PARAMETER C_CLK_FREQ = 50000000
+               PARAMETER C_BASEADDR = 0xEC100000
+               PARAMETER C_HIGHADDR = 0xEC10FFFF
+               BUS_INTERFACE SOPB = opb_7
+               PORT OPB_Clk = CLK_50MHz
+               PORT Interrupt = opb_uartlite_0_Interrupt
+               PORT RX = opb_uartlite_0_RX
+               PORT TX = opb_uartlite_0_TX
+               PORT OPB_Rst = sys_bus_reset_0
+       END
+
+   becomes the following device tree node:
+
+       opb_uartlite_0: serial@ec100000 {
+               device_type = "serial";
+               compatible = "xlnx,opb-uartlite-1.00.b";
+               reg = <ec100000 10000>;
+               interrupt-parent = <&opb_intc_0>;
+               interrupts = <1 0>; // got this from the opb_intc parameters
+               current-speed = <d#115200>;     // standard serial device prop
+               clock-frequency = <d#50000000>; // standard serial device prop
+               xlnx,data-bits = <8>;
+               xlnx,odd-parity = <0>;
+               xlnx,use-parity = <0>;
+       };
+
+   Some IP cores actually implement 2 or more logical devices.  In
+   this case, the device should still describe the whole IP core with
+   a single node and add a child node for each logical device.  The
+   ranges property can be used to translate from parent IP-core to the
+   registers of each device.  In addition, the parent node should be
+   compatible with the bus type 'xlnx,compound', and should contain
+   #address-cells and #size-cells, as with any other bus.  (Note: this
+   makes the assumption that both logical devices have the same bus
+   binding.  If this is not true, then separate nodes should be used
+   for each logical device).  The 'cell-index' property can be used to
+   enumerate logical devices within an IP core.  For example, the
+   following is the system.mhs entry for the dual ps2 controller found
+   on the ml403 reference design.
+
+       BEGIN opb_ps2_dual_ref
+               PARAMETER INSTANCE = opb_ps2_dual_ref_0
+               PARAMETER HW_VER = 1.00.a
+               PARAMETER C_BASEADDR = 0xA9000000
+               PARAMETER C_HIGHADDR = 0xA9001FFF
+               BUS_INTERFACE SOPB = opb_v20_0
+               PORT Sys_Intr1 = ps2_1_intr
+               PORT Sys_Intr2 = ps2_2_intr
+               PORT Clkin1 = ps2_clk_rx_1
+               PORT Clkin2 = ps2_clk_rx_2
+               PORT Clkpd1 = ps2_clk_tx_1
+               PORT Clkpd2 = ps2_clk_tx_2
+               PORT Rx1 = ps2_d_rx_1
+               PORT Rx2 = ps2_d_rx_2
+               PORT Txpd1 = ps2_d_tx_1
+               PORT Txpd2 = ps2_d_tx_2
+       END
+
+   It would result in the following device tree nodes:
+
+       opb_ps2_dual_ref_0: opb-ps2-dual-ref@a9000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "xlnx,compound";
+               ranges = <0 a9000000 2000>;
+               // If this device had extra parameters, then they would
+               // go here.
+               ps2@0 {
+                       compatible = "xlnx,opb-ps2-dual-ref-1.00.a";
+                       reg = <0 40>;
+                       interrupt-parent = <&opb_intc_0>;
+                       interrupts = <3 0>;
+                       cell-index = <0>;
+               };
+               ps2@1000 {
+                       compatible = "xlnx,opb-ps2-dual-ref-1.00.a";
+                       reg = <1000 40>;
+                       interrupt-parent = <&opb_intc_0>;
+                       interrupts = <3 0>;
+                       cell-index = <0>;
+               };
+       };
+
+   Also, the system.mhs file defines bus attachments from the processor
+   to the devices.  The device tree structure should reflect the bus
+   attachments.  Again an example; this system.mhs fragment:
+
+       BEGIN ppc405_virtex4
+               PARAMETER INSTANCE = ppc405_0
+               PARAMETER HW_VER = 1.01.a
+               BUS_INTERFACE DPLB = plb_v34_0
+               BUS_INTERFACE IPLB = plb_v34_0
+       END
+
+       BEGIN opb_intc
+               PARAMETER INSTANCE = opb_intc_0
+               PARAMETER HW_VER = 1.00.c
+               PARAMETER C_BASEADDR = 0xD1000FC0
+               PARAMETER C_HIGHADDR = 0xD1000FDF
+               BUS_INTERFACE SOPB = opb_v20_0
+       END
+
+       BEGIN opb_uart16550
+               PARAMETER INSTANCE = opb_uart16550_0
+               PARAMETER HW_VER = 1.00.d
+               PARAMETER C_BASEADDR = 0xa0000000
+               PARAMETER C_HIGHADDR = 0xa0001FFF
+               BUS_INTERFACE SOPB = opb_v20_0
+       END
+
+       BEGIN plb_v34
+               PARAMETER INSTANCE = plb_v34_0
+               PARAMETER HW_VER = 1.02.a
+       END
+
+       BEGIN plb_bram_if_cntlr
+               PARAMETER INSTANCE = plb_bram_if_cntlr_0
+               PARAMETER HW_VER = 1.00.b
+               PARAMETER C_BASEADDR = 0xFFFF0000
+               PARAMETER C_HIGHADDR = 0xFFFFFFFF
+               BUS_INTERFACE SPLB = plb_v34_0
+       END
+
+       BEGIN plb2opb_bridge
+               PARAMETER INSTANCE = plb2opb_bridge_0
+               PARAMETER HW_VER = 1.01.a
+               PARAMETER C_RNG0_BASEADDR = 0x20000000
+               PARAMETER C_RNG0_HIGHADDR = 0x3FFFFFFF
+               PARAMETER C_RNG1_BASEADDR = 0x60000000
+               PARAMETER C_RNG1_HIGHADDR = 0x7FFFFFFF
+               PARAMETER C_RNG2_BASEADDR = 0x80000000
+               PARAMETER C_RNG2_HIGHADDR = 0xBFFFFFFF
+               PARAMETER C_RNG3_BASEADDR = 0xC0000000
+               PARAMETER C_RNG3_HIGHADDR = 0xDFFFFFFF
+               BUS_INTERFACE SPLB = plb_v34_0
+               BUS_INTERFACE MOPB = opb_v20_0
+       END
+
+   Gives this device tree (some properties removed for clarity):
+
+       plb@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "xlnx,plb-v34-1.02.a";
+               device_type = "ibm,plb";
+               ranges; // 1:1 translation
+
+               plb_bram_if_cntrl_0: bram@ffff0000 {
+                       reg = <ffff0000 10000>;
+               }
+
+               opb@20000000 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <20000000 20000000 20000000
+                                 60000000 60000000 20000000
+                                 80000000 80000000 40000000
+                                 c0000000 c0000000 20000000>;
+
+                       opb_uart16550_0: serial@a0000000 {
+                               reg = <a00000000 2000>;
+                       };
+
+                       opb_intc_0: interrupt-controller@d1000fc0 {
+                               reg = <d1000fc0 20>;
+                       };
+               };
+       };
+
+   That covers the general approach to binding xilinx IP cores into the
+   device tree.  The following are bindings for specific devices:
+
+      i) Xilinx ML300 Framebuffer
+
+      Simple framebuffer device from the ML300 reference design (also on the
+      ML403 reference design as well as others).
+
+      Optional properties:
+       - resolution = <xres yres> : pixel resolution of framebuffer.  Some
+                                    implementations use a different resolution.
+                                    Default is <d#640 d#480>
+       - virt-resolution = <xvirt yvirt> : Size of framebuffer in memory.
+                                           Default is <d#1024 d#480>.
+       - rotate-display (empty) : rotate display 180 degrees.
+
+      ii) Xilinx SystemACE
+
+      The Xilinx SystemACE device is used to program FPGAs from an FPGA
+      bitstream stored on a CF card.  It can also be used as a generic CF
+      interface device.
+
+      Optional properties:
+       - 8-bit (empty) : Set this property for SystemACE in 8 bit mode
+
+      iii) Xilinx EMAC and Xilinx TEMAC
+
+      Xilinx Ethernet devices.  In addition to general xilinx properties
+      listed above, nodes for these devices should include a phy-handle
+      property, and may include other common network device properties
+      like local-mac-address.
+
+      iv) Xilinx Uartlite
+
+      Xilinx uartlite devices are simple fixed speed serial ports.
+
+      Required properties:
+       - current-speed : Baud rate of uartlite
+
+      v) Xilinx hwicap
+
+               Xilinx hwicap devices provide access to the configuration logic
+               of the FPGA through the Internal Configuration Access Port
+               (ICAP).  The ICAP enables partial reconfiguration of the FPGA,
+               readback of the configuration information, and some control over
+               'warm boots' of the FPGA fabric.
+
+               Required properties:
+               - xlnx,family : The family of the FPGA, necessary since the
+                      capabilities of the underlying ICAP hardware
+                      differ between different families.  May be
+                      'virtex2p', 'virtex4', or 'virtex5'.
+
+      vi) Xilinx Uart 16550
+
+      Xilinx UART 16550 devices are very similar to the NS16550 but with
+      different register spacing and an offset from the base address.
+
+      Required properties:
+       - clock-frequency : Frequency of the clock input
+       - reg-offset : A value of 3 is required
+       - reg-shift : A value of 2 is required
+
+
index 1df7f9cdab0576227671703c6fec1fc780ec596b..86eabe6c3419fd4f26aba47a090ecc1caff9a1fd 100644 (file)
@@ -73,7 +73,7 @@ The remaining CPU time will be used for user input and other tasks. Because
 realtime tasks have explicitly allocated the CPU time they need to perform
 their tasks, buffer underruns in the graphics or audio can be eliminated.
 
-NOTE: the above example is not fully implemented as of yet (2.6.25). We still
+NOTE: the above example is not fully implemented yet. We still
 lack an EDF scheduler to make non-uniform periods usable.
 
 
@@ -140,14 +140,15 @@ The other option is:
 
 .o CONFIG_CGROUP_SCHED (aka "Basis for grouping tasks" = "Control groups")
 
-This uses the /cgroup virtual file system and "/cgroup/<cgroup>/cpu.rt_runtime_us"
-to control the CPU time reserved for each control group instead.
+This uses the /cgroup virtual file system and
+"/cgroup/<cgroup>/cpu.rt_runtime_us" to control the CPU time reserved for each
+control group instead.
 
 For more information on working with control groups, you should read
 Documentation/cgroups/cgroups.txt as well.
 
-Group settings are checked against the following limits in order to keep the configuration
-schedulable:
+Group settings are checked against the following limits in order to keep the
+configuration schedulable:
 
    \Sum_{i} runtime_{i} / global_period <= global_runtime / global_period
 
@@ -189,7 +190,7 @@ Implementing SCHED_EDF might take a while to complete. Priority Inheritance is
 the biggest challenge as the current linux PI infrastructure is geared towards
 the limited static priority levels 0-99. With deadline scheduling you need to
 do deadline inheritance (since priority is inversely proportional to the
-deadline delta (deadline - now).
+deadline delta (deadline - now)).
 
 This means the whole PI machinery will have to be reworked - and that is one of
 the most complex pieces of code we have.
index f9d11140af913c95d317963d9b0c1bd672a881ef..1c8eb4518ce08e8a10303929692da407348a5c4c 100644 (file)
@@ -60,6 +60,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     slots      - Reserve the slot index for the given driver.
                  This option takes multiple strings.           
                  See "Module Autoloading Support" section for details.
+    debug      - Specifies the debug message level
+                 (0 = disable debug prints, 1 = normal debug messages,
+                  2 = verbose debug messages)
+                 This option appears only when CONFIG_SND_DEBUG=y.
+                 This option can be dynamically changed via sysfs
+                 /sys/modules/snd/parameters/debug file.
   
   Module snd-pcm-oss
   ------------------
@@ -513,6 +519,26 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     or input, but you may use this module for any application which
     requires a sound card (like RealPlayer).
 
+    pcm_devs       - Number of PCM devices assigned to each card
+                     (default = 1, up to 4)
+    pcm_substreams - Number of PCM substreams assigned to each PCM
+                     (default = 8, up to 16)
+    hrtimer        - Use hrtimer (=1, default) or system timer (=0)
+    fake_buffer    - Fake buffer allocations (default = 1)
+
+    When multiple PCM devices are created, snd-dummy gives different
+    behavior to each PCM device:
+      0 = interleaved with mmap support
+      1 = non-interleaved with mmap support
+      2 = interleaved without mmap 
+      3 = non-interleaved without mmap
+
+    As default, snd-dummy drivers doesn't allocate the real buffers
+    but either ignores read/write or mmap a single dummy page to all
+    buffer pages, in order to save the resouces.  If your apps need
+    the read/ written buffer data to be consistent, pass fake_buffer=0
+    option.
+
     The power-management is supported.
 
   Module snd-echo3g
index 381908d8ca4231dde74f5c138b200782036760c1..719a819f8cc2c0e597e27b2b8bcd7caa17638ea2 100644 (file)
@@ -101,6 +101,8 @@ card*/pcm*/xrun_debug
          bit 0 = Enable XRUN/jiffies debug messages
          bit 1 = Show stack trace at XRUN / jiffies check
          bit 2 = Enable additional jiffies check
+         bit 3 = Log hwptr update at each period interrupt
+         bit 4 = Log hwptr update at each snd_pcm_update_hw_ptr()
 
        When the bit 0 is set, the driver will show the messages to
        kernel log when an xrun is detected.  The debug message is
@@ -117,6 +119,9 @@ card*/pcm*/xrun_debug
        buggy) hardware that doesn't give smooth pointer updates.
        This feature is enabled via the bit 2.
 
+       Bits 3 and 4 are for logging the hwptr records.  Note that
+       these will give flood of kernel messages.
+
 card*/pcm*/sub*/info
        The general information of this PCM sub-stream.
 
index cf0e3ce0d52682171688c07974e90fce66036d5f..c1a5aad3c75a905d470725fc5795775227c4a4fd 100644 (file)
@@ -99,11 +99,13 @@ void parse_opts(int argc, char *argv[])
                        { "lsb",     0, 0, 'L' },
                        { "cs-high", 0, 0, 'C' },
                        { "3wire",   0, 0, '3' },
+                       { "no-cs",   0, 0, 'N' },
+                       { "ready",   0, 0, 'R' },
                        { NULL, 0, 0, 0 },
                };
                int c;
 
-               c = getopt_long(argc, argv, "D:s:d:b:lHOLC3", lopts, NULL);
+               c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);
 
                if (c == -1)
                        break;
@@ -139,6 +141,12 @@ void parse_opts(int argc, char *argv[])
                case '3':
                        mode |= SPI_3WIRE;
                        break;
+               case 'N':
+                       mode |= SPI_NO_CS;
+                       break;
+               case 'R':
+                       mode |= SPI_READY;
+                       break;
                default:
                        print_usage(argv[0]);
                        break;
index cf42b820ff9d5002fdf8a9cd280731a593544957..d56a017754239137bc875950a1461a76f8994003 100644 (file)
@@ -66,7 +66,8 @@ On all -  write a character to /proc/sysrq-trigger.  e.g.:
 'b'     - Will immediately reboot the system without syncing or unmounting
           your disks.
 
-'c'    - Will perform a kexec reboot in order to take a crashdump.
+'c'    - Will perform a system crash by a NULL pointer dereference.
+          A crashdump will be taken if configured.
 
 'd'    - Shows all locks that are held.
 
@@ -141,8 +142,8 @@ useful when you want to exit a program that will not let you switch consoles.
 re'B'oot is good when you're unable to shut down. But you should also 'S'ync
 and 'U'mount first.
 
-'C'rashdump can be used to manually trigger a crashdump when the system is hung.
-The kernel needs to have been built with CONFIG_KEXEC enabled.
+'C'rash can be used to manually trigger a crashdump when the system is hung.
+Note that this just triggers a crash if there is no dump mechanism available.
 
 'S'ync is great when your system is locked up, it allows you to sync your
 disks and will certainly lessen the chance of data loss and fscking. Note
index 873630e7e53eb5859b1cd722c0818865d895cd20..e352d754875cae415b0c27d766336c00942cd241 100644 (file)
@@ -1,5 +1,5 @@
   0 -> Unknown EM2800 video grabber             (em2800)        [eb1a:2800]
-  1 -> Unknown EM2750/28xx video grabber        (em2820/em2840) [eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883]
+  1 -> Unknown EM2750/28xx video grabber        (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2870,eb1a:2881,eb1a:2883]
   2 -> Terratec Cinergy 250 USB                 (em2820/em2840) [0ccd:0036]
   3 -> Pinnacle PCTV USB 2                      (em2820/em2840) [2304:0208]
   4 -> Hauppauge WinTV USB 2                    (em2820/em2840) [2040:4200,2040:4201]
@@ -20,7 +20,7 @@
  19 -> EM2860/SAA711X Reference Design          (em2860)
  20 -> AMD ATI TV Wonder HD 600                 (em2880)        [0438:b002]
  21 -> eMPIA Technology, Inc. GrabBeeX+ Video Encoder (em2800)        [eb1a:2801]
- 22 -> Unknown EM2750/EM2751 webcam grabber     (em2750)        [eb1a:2750,eb1a:2751]
+ 22 -> EM2710/EM2750/EM2751 webcam grabber      (em2750)        [eb1a:2750,eb1a:2751]
  23 -> Huaqi DLCW-130                           (em2750)
  24 -> D-Link DUB-T210 TV Tuner                 (em2820/em2840) [2001:f112]
  25 -> Gadmei UTV310                            (em2820/em2840)
@@ -66,3 +66,4 @@
  68 -> Terratec AV350                           (em2860)        [0ccd:0084]
  69 -> KWorld ATSC 315U HDTV TV Box             (em2882)        [eb1a:a313]
  70 -> Evga inDtube                             (em2882)
+ 71 -> Silvercrest Webcam 1.3mpix               (em2820/em2840)
index 15562427e8a9cb51b7f7611bb38a0bc7975bfa65..c913e5614195a9a359411ee163f8c2e081d24a2a 100644 (file)
 152 -> Asus Tiger Rev:1.00                      [1043:4857]
 153 -> Kworld Plus TV Analog Lite PCI           [17de:7128]
 154 -> Avermedia AVerTV GO 007 FM Plus          [1461:f31d]
-155 -> Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid  [0070:6706,0070:6708]
-156 -> Hauppauge WinTV-HVR1110r3 DVB-T/Hybrid   [0070:6707,0070:6709,0070:670a]
+155 -> Hauppauge WinTV-HVR1150 ATSC/QAM-Hybrid  [0070:6706,0070:6708]
+156 -> Hauppauge WinTV-HVR1120 DVB-T/Hybrid     [0070:6707,0070:6709,0070:670a]
 157 -> Avermedia AVerTV Studio 507UA            [1461:a11b]
 158 -> AVerMedia Cardbus TV/Radio (E501R)       [1461:b7e9]
 159 -> Beholder BeholdTV 505 RDS                [0000:505B]
index 2bcf78896e225a191cc58c23d8636ad92365ecd7..573f95b588079b6ae1ede70f479cf539e397e2eb 100644 (file)
@@ -44,7 +44,9 @@ zc3xx         0458:7007       Genius VideoCam V2
 zc3xx          0458:700c       Genius VideoCam V3
 zc3xx          0458:700f       Genius VideoCam Web V2
 sonixj         0458:7025       Genius Eye 311Q
+sn9c20x                0458:7029       Genius Look 320s
 sonixj         0458:702e       Genius Slim 310 NB
+sn9c20x                045e:00f4       LifeCam VX-6000 (SN9C20x + OV9650)
 sonixj         045e:00f5       MicroSoft VX3000
 sonixj         045e:00f7       MicroSoft VX1000
 ov519          045e:028c       Micro$oft xbox cam
@@ -282,6 +284,28 @@ sonixj             0c45:613a       Microdia Sonix PC Camera
 sonixj         0c45:613b       Surfer SN-206
 sonixj         0c45:613c       Sonix Pccam168
 sonixj         0c45:6143       Sonix Pccam168
+sn9c20x                0c45:6240       PC Camera (SN9C201 + MT9M001)
+sn9c20x                0c45:6242       PC Camera (SN9C201 + MT9M111)
+sn9c20x                0c45:6248       PC Camera (SN9C201 + OV9655)
+sn9c20x                0c45:624e       PC Camera (SN9C201 + SOI968)
+sn9c20x                0c45:624f       PC Camera (SN9C201 + OV9650)
+sn9c20x                0c45:6251       PC Camera (SN9C201 + OV9650)
+sn9c20x                0c45:6253       PC Camera (SN9C201 + OV9650)
+sn9c20x                0c45:6260       PC Camera (SN9C201 + OV7670)
+sn9c20x                0c45:6270       PC Camera (SN9C201 + MT9V011/MT9V111/MT9V112)
+sn9c20x                0c45:627b       PC Camera (SN9C201 + OV7660)
+sn9c20x                0c45:627c       PC Camera (SN9C201 + HV7131R)
+sn9c20x                0c45:627f       PC Camera (SN9C201 + OV9650)
+sn9c20x                0c45:6280       PC Camera (SN9C202 + MT9M001)
+sn9c20x                0c45:6282       PC Camera (SN9C202 + MT9M111)
+sn9c20x                0c45:6288       PC Camera (SN9C202 + OV9655)
+sn9c20x                0c45:628e       PC Camera (SN9C202 + SOI968)
+sn9c20x                0c45:628f       PC Camera (SN9C202 + OV9650)
+sn9c20x                0c45:62a0       PC Camera (SN9C202 + OV7670)
+sn9c20x                0c45:62b0       PC Camera (SN9C202 + MT9V011/MT9V111/MT9V112)
+sn9c20x                0c45:62b3       PC Camera (SN9C202 + OV9655)
+sn9c20x                0c45:62bb       PC Camera (SN9C202 + OV7660)
+sn9c20x                0c45:62bc       PC Camera (SN9C202 + HV7131R)
 sunplus                0d64:0303       Sunplus FashionCam DXG
 etoms          102c:6151       Qcam Sangha CIF
 etoms          102c:6251       Qcam xxxxxx VGA
@@ -290,6 +314,7 @@ spca561             10fd:7e50       FlyCam Usb 100
 zc3xx          10fd:8050       Typhoon Webshot II USB 300k
 ov534          1415:2000       Sony HD Eye for PS3 (SLEH 00201)
 pac207         145f:013a       Trust WB-1300N
+sn9c20x                145f:013d       Trust WB-3600R
 vc032x         15b8:6001       HP 2.0 Megapixel
 vc032x         15b8:6002       HP 2.0 Megapixel rz406aa
 spca501                1776:501c       Arowana 300K CMOS Camera
@@ -300,4 +325,11 @@ spca500            2899:012c       Toptro Industrial
 spca508                8086:0110       Intel Easy PC Camera
 spca500                8086:0630       Intel Pocket PC Camera
 spca506                99fa:8988       Grandtec V.cap
+sn9c20x                a168:0610       Dino-Lite Digital Microscope (SN9C201 + HV7131R)
+sn9c20x                a168:0611       Dino-Lite Digital Microscope (SN9C201 + HV7131R)
+sn9c20x                a168:0613       Dino-Lite Digital Microscope (SN9C201 + HV7131R)
+sn9c20x                a168:0618       Dino-Lite Digital Microscope (SN9C201 + HV7131R)
+sn9c20x                a168:0614       Dino-Lite Digital Microscope (SN9C201 + MT9M111)
+sn9c20x                a168:0615       Dino-Lite Digital Microscope (SN9C201 + MT9M111)
+sn9c20x                a168:0617       Dino-Lite Digital Microscope (SN9C201 + MT9M111)
 spca561                abcd:cdee       Petcam
index dbe3377754af5ab0d36c5665a3a118e02fc5621f..f37b46d348614be9fc5a0b54a8c303617e979d56 100644 (file)
@@ -2,3 +2,5 @@
        - this file
 mtrr.txt
        - how to use x86 Memory Type Range Registers to increase performance
+exception-tables.txt
+       - why and how Linux kernel uses exception tables on x86
similarity index 75%
rename from Documentation/exception.txt
rename to Documentation/x86/exception-tables.txt
index 2d5aded64247343e1cfa13ded99c3a1e0204517a..32901aa36f0a99f7c087aa7c510bbceb0ec14a89 100644 (file)
-     Kernel level exception handling in Linux 2.1.8
+     Kernel level exception handling in Linux
   Commentary by Joerg Pommnitz <joerg@raleigh.ibm.com>
 
-When a process runs in kernel mode, it often has to access user 
-mode memory whose address has been passed by an untrusted program. 
+When a process runs in kernel mode, it often has to access user
+mode memory whose address has been passed by an untrusted program.
 To protect itself the kernel has to verify this address.
 
-In older versions of Linux this was done with the 
-int verify_area(int type, const void * addr, unsigned long size) 
+In older versions of Linux this was done with the
+int verify_area(int type, const void * addr, unsigned long size)
 function (which has since been replaced by access_ok()).
 
-This function verified that the memory area starting at address 
+This function verified that the memory area starting at address
 'addr' and of size 'size' was accessible for the operation specified
-in type (read or write). To do this, verify_read had to look up the 
-virtual memory area (vma) that contained the address addr. In the 
-normal case (correctly working program), this test was successful. 
+in type (read or write). To do this, verify_read had to look up the
+virtual memory area (vma) that contained the address addr. In the
+normal case (correctly working program), this test was successful.
 It only failed for a few buggy programs. In some kernel profiling
 tests, this normally unneeded verification used up a considerable
 amount of time.
 
-To overcome this situation, Linus decided to let the virtual memory 
+To overcome this situation, Linus decided to let the virtual memory
 hardware present in every Linux-capable CPU handle this test.
 
 How does this work?
 
-Whenever the kernel tries to access an address that is currently not 
-accessible, the CPU generates a page fault exception and calls the 
-page fault handler 
+Whenever the kernel tries to access an address that is currently not
+accessible, the CPU generates a page fault exception and calls the
+page fault handler
 
 void do_page_fault(struct pt_regs *regs, unsigned long error_code)
 
-in arch/i386/mm/fault.c. The parameters on the stack are set up by 
-the low level assembly glue in arch/i386/kernel/entry.S. The parameter
-regs is a pointer to the saved registers on the stack, error_code 
+in arch/x86/mm/fault.c. The parameters on the stack are set up by
+the low level assembly glue in arch/x86/kernel/entry_32.S. The parameter
+regs is a pointer to the saved registers on the stack, error_code
 contains a reason code for the exception.
 
-do_page_fault first obtains the unaccessible address from the CPU 
-control register CR2. If the address is within the virtual address 
-space of the process, the fault probably occurred, because the page 
-was not swapped in, write protected or something similar. However, 
-we are interested in the other case: the address is not valid, there 
-is no vma that contains this address. In this case, the kernel jumps 
-to the bad_area label. 
-
-There it uses the address of the instruction that caused the exception 
-(i.e. regs->eip) to find an address where the execution can continue 
-(fixup). If this search is successful, the fault handler modifies the 
-return address (again regs->eip) and returns. The execution will 
+do_page_fault first obtains the unaccessible address from the CPU
+control register CR2. If the address is within the virtual address
+space of the process, the fault probably occurred, because the page
+was not swapped in, write protected or something similar. However,
+we are interested in the other case: the address is not valid, there
+is no vma that contains this address. In this case, the kernel jumps
+to the bad_area label.
+
+There it uses the address of the instruction that caused the exception
+(i.e. regs->eip) to find an address where the execution can continue
+(fixup). If this search is successful, the fault handler modifies the
+return address (again regs->eip) and returns. The execution will
 continue at the address in fixup.
 
 Where does fixup point to?
 
-Since we jump to the contents of fixup, fixup obviously points 
-to executable code. This code is hidden inside the user access macros. 
-I have picked the get_user macro defined in include/asm/uaccess.h as an
-example. The definition is somewhat hard to follow, so let's peek at 
+Since we jump to the contents of fixup, fixup obviously points
+to executable code. This code is hidden inside the user access macros.
+I have picked the get_user macro defined in arch/x86/include/asm/uaccess.h
+as an example. The definition is somewhat hard to follow, so let's peek at
 the code generated by the preprocessor and the compiler. I selected
-the get_user call in drivers/char/console.c for a detailed examination.
+the get_user call in drivers/char/sysrq.c for a detailed examination.
 
-The original code in console.c line 1405:
+The original code in sysrq.c line 587:
         get_user(c, buf);
 
 The preprocessor output (edited to become somewhat readable):
 
 (
-  {        
-    long __gu_err = - 14 , __gu_val = 0;        
-    const __typeof__(*( (  buf ) )) *__gu_addr = ((buf));        
-    if (((((0 + current_set[0])->tss.segment) == 0x18 )  || 
-       (((sizeof(*(buf))) <= 0xC0000000UL) && 
-       ((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf)))))))        
+  {
+    long __gu_err = - 14 , __gu_val = 0;
+    const __typeof__(*( (  buf ) )) *__gu_addr = ((buf));
+    if (((((0 + current_set[0])->tss.segment) == 0x18 )  ||
+       (((sizeof(*(buf))) <= 0xC0000000UL) &&
+       ((unsigned long)(__gu_addr ) <= 0xC0000000UL - (sizeof(*(buf)))))))
       do {
-        __gu_err  = 0;        
-        switch ((sizeof(*(buf)))) {        
-          case 1: 
-            __asm__ __volatile__(        
-              "1:      mov" "b" " %2,%" "b" "1\n"        
-              "2:\n"        
-              ".section .fixup,\"ax\"\n"        
-              "3:      movl %3,%0\n"        
-              "        xor" "b" " %" "b" "1,%" "b" "1\n"        
-              "        jmp 2b\n"        
-              ".section __ex_table,\"a\"\n"        
-              "        .align 4\n"        
-              "        .long 1b,3b\n"        
+        __gu_err  = 0;
+        switch ((sizeof(*(buf)))) {
+          case 1:
+            __asm__ __volatile__(
+              "1:      mov" "b" " %2,%" "b" "1\n"
+              "2:\n"
+              ".section .fixup,\"ax\"\n"
+              "3:      movl %3,%0\n"
+              "        xor" "b" " %" "b" "1,%" "b" "1\n"
+              "        jmp 2b\n"
+              ".section __ex_table,\"a\"\n"
+              "        .align 4\n"
+              "        .long 1b,3b\n"
               ".text"        : "=r"(__gu_err), "=q" (__gu_val): "m"((*(struct __large_struct *)
-                            (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  )) ; 
-              break;        
-          case 2: 
+                            (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  )) ;
+              break;
+          case 2:
             __asm__ __volatile__(
-              "1:      mov" "w" " %2,%" "w" "1\n"        
-              "2:\n"        
-              ".section .fixup,\"ax\"\n"        
-              "3:      movl %3,%0\n"        
-              "        xor" "w" " %" "w" "1,%" "w" "1\n"        
-              "        jmp 2b\n"        
-              ".section __ex_table,\"a\"\n"        
-              "        .align 4\n"        
-              "        .long 1b,3b\n"        
+              "1:      mov" "w" " %2,%" "w" "1\n"
+              "2:\n"
+              ".section .fixup,\"ax\"\n"
+              "3:      movl %3,%0\n"
+              "        xor" "w" " %" "w" "1,%" "w" "1\n"
+              "        jmp 2b\n"
+              ".section __ex_table,\"a\"\n"
+              "        .align 4\n"
+              "        .long 1b,3b\n"
               ".text"        : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
-                            (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  )); 
-              break;        
-          case 4: 
-            __asm__ __volatile__(        
-              "1:      mov" "l" " %2,%" "" "1\n"        
-              "2:\n"        
-              ".section .fixup,\"ax\"\n"        
-              "3:      movl %3,%0\n"        
-              "        xor" "l" " %" "" "1,%" "" "1\n"        
-              "        jmp 2b\n"        
-              ".section __ex_table,\"a\"\n"        
-              "        .align 4\n"        "        .long 1b,3b\n"        
+                            (   __gu_addr   )) ), "i"(- 14 ), "0"(  __gu_err  ));
+              break;
+          case 4:
+            __asm__ __volatile__(
+              "1:      mov" "l" " %2,%" "" "1\n"
+              "2:\n"
+              ".section .fixup,\"ax\"\n"
+              "3:      movl %3,%0\n"
+              "        xor" "l" " %" "" "1,%" "" "1\n"
+              "        jmp 2b\n"
+              ".section __ex_table,\"a\"\n"
+              "        .align 4\n"        "        .long 1b,3b\n"
               ".text"        : "=r"(__gu_err), "=r" (__gu_val) : "m"((*(struct __large_struct *)
-                            (   __gu_addr   )) ), "i"(- 14 ), "0"(__gu_err)); 
-              break;        
-          default: 
-            (__gu_val) = __get_user_bad();        
-        }        
-      } while (0) ;        
-    ((c)) = (__typeof__(*((buf))))__gu_val;        
+                            (   __gu_addr   )) ), "i"(- 14 ), "0"(__gu_err));
+              break;
+          default:
+            (__gu_val) = __get_user_bad();
+        }
+      } while (0) ;
+    ((c)) = (__typeof__(*((buf))))__gu_val;
     __gu_err;
   }
 );
@@ -127,12 +127,12 @@ see what code gcc generates:
 
  >         xorl %edx,%edx
  >         movl current_set,%eax
- >         cmpl $24,788(%eax)        
- >         je .L1424        
+ >         cmpl $24,788(%eax)
+ >         je .L1424
  >         cmpl $-1073741825,64(%esp)
- >         ja .L1423                
+ >         ja .L1423
  > .L1424:
- >         movl %edx,%eax                        
+ >         movl %edx,%eax
  >         movl 64(%esp),%ebx
  > #APP
  > 1:      movb (%ebx),%dl                /* this is the actual user access */
@@ -149,17 +149,17 @@ see what code gcc generates:
  > .L1423:
  >         movzbl %dl,%esi
 
-The optimizer does a good job and gives us something we can actually 
-understand. Can we? The actual user access is quite obvious. Thanks 
-to the unified address space we can just access the address in user 
+The optimizer does a good job and gives us something we can actually
+understand. Can we? The actual user access is quite obvious. Thanks
+to the unified address space we can just access the address in user
 memory. But what does the .section stuff do?????
 
 To understand this we have to look at the final kernel:
 
  > objdump --section-headers vmlinux
- > 
+ >
  > vmlinux:     file format elf32-i386
- > 
+ >
  > Sections:
  > Idx Name          Size      VMA       LMA       File off  Algn
  >   0 .text         00098f40  c0100000  c0100000  00001000  2**4
@@ -198,18 +198,18 @@ final kernel executable:
 
 The whole user memory access is reduced to 10 x86 machine instructions.
 The instructions bracketed in the .section directives are no longer
-in the normal execution path. They are located in a different section 
+in the normal execution path. They are located in a different section
 of the executable file:
 
  > objdump --disassemble --section=.fixup vmlinux
- > 
+ >
  > c0199ff5 <.fixup+10b5> movl   $0xfffffff2,%eax
  > c0199ffa <.fixup+10ba> xorb   %dl,%dl
  > c0199ffc <.fixup+10bc> jmp    c017e7a7 <do_con_write+e3>
 
 And finally:
  > objdump --full-contents --section=__ex_table vmlinux
- > 
+ >
  >  c01aa7c4 93c017c0 e09f19c0 97c017c0 99c017c0  ................
  >  c01aa7d4 f6c217c0 e99f19c0 a5e717c0 f59f19c0  ................
  >  c01aa7e4 080a18c0 01a019c0 0a0a18c0 04a019c0  ................
@@ -235,8 +235,8 @@ sections in the ELF object file. So the instructions
 ended up in the .fixup section of the object file and the addresses
         .long 1b,3b
 ended up in the __ex_table section of the object file. 1b and 3b
-are local labels. The local label 1b (1b stands for next label 1 
-backward) is the address of the instruction that might fault, i.e. 
+are local labels. The local label 1b (1b stands for next label 1
+backward) is the address of the instruction that might fault, i.e.
 in our case the address of the label 1 is c017e7a5:
 the original assembly code: > 1:      movb (%ebx),%dl
 and linked in vmlinux     : > c017e7a5 <do_con_write+e1> movb   (%ebx),%dl
@@ -254,7 +254,7 @@ The assembly code
 becomes the value pair
  >  c01aa7d4 c017c2f6 c0199fe9 c017e7a5 c0199ff5  ................
                                ^this is ^this is
-                               1b       3b 
+                               1b       3b
 c017e7a5,c0199ff5 in the exception table of the kernel.
 
 So, what actually happens if a fault from kernel mode with no suitable
@@ -266,9 +266,9 @@ vma occurs?
 3.) CPU calls do_page_fault
 4.) do page fault calls search_exception_table (regs->eip == c017e7a5);
 5.) search_exception_table looks up the address c017e7a5 in the
-    exception table (i.e. the contents of the ELF section __ex_table) 
+    exception table (i.e. the contents of the ELF section __ex_table)
     and returns the address of the associated fault handle code c0199ff5.
-6.) do_page_fault modifies its own return address to point to the fault 
+6.) do_page_fault modifies its own return address to point to the fault
     handle code and returns.
 7.) execution continues in the fault handling code.
 8.) 8a) EAX becomes -EFAULT (== -14)
index fa2a16def17afb765ad447f10b5dde634f83ded9..8dca9d89c6c1d1d04e65e58e881e902b0e450d09 100644 (file)
@@ -73,8 +73,8 @@ Note: For the hard of thinking, this list is meant to remain in alphabetical
 order. If you could add yourselves to it in alphabetical order that would be
 so much easier [Ed]
 
-P: Person
-M: Mail patches to
+P: Person (obsolete)
+M: Mail patches to: FullName <address@domain>
 L: Mailing list that is relevant to this area
 W: Web-page with status/info
 T: SCM tree type and location.  Type is one of: git, hg, quilt, stgit.
@@ -104,88 +104,74 @@ X: Files and directories that are NOT maintained, same rules as F:
    matches all files in and below net excluding net/ipv6/
 
 3C505 NETWORK DRIVER
-P:     Philip Blundell
-M:     philb@gnu.org
+M:     Philip Blundell <philb@gnu.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/3c505*
 
 3C59X NETWORK DRIVER
-P:     Steffen Klassert
-M:     klassert@mathematik.tu-chemnitz.de
+M:     Steffen Klassert <klassert@mathematik.tu-chemnitz.de>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     Documentation/networking/vortex.txt
 F:     drivers/net/3c59x.c
 
 3CR990 NETWORK DRIVER
-P:     David Dillow
-M:     dave@thedillows.org
+M:     David Dillow <dave@thedillows.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/typhoon*
 
 3W-9XXX SATA-RAID CONTROLLER DRIVER
-P:     Adam Radford
-M:     linuxraid@amcc.com
+M:     Adam Radford <linuxraid@amcc.com>
 L:     linux-scsi@vger.kernel.org
 W:     http://www.amcc.com
 S:     Supported
 F:     drivers/scsi/3w-9xxx*
 
 3W-XXXX ATA-RAID CONTROLLER DRIVER
-P:     Adam Radford
-M:     linuxraid@amcc.com
+M:     Adam Radford <linuxraid@amcc.com>
 L:     linux-scsi@vger.kernel.org
 W:     http://www.amcc.com
 S:     Supported
 F:     drivers/scsi/3w-xxxx*
 
 53C700 AND 53C700-66 SCSI DRIVER
-P:     James E.J. Bottomley
-M:     James.Bottomley@HansenPartnership.com
+M:     "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
 F:     drivers/scsi/53c700*
 
 6PACK NETWORK DRIVER FOR AX.25
-P:     Andreas Koensgen
-M:     ajk@iehk.rwth-aachen.de
+M:     Andreas Koensgen <ajk@comnets.uni-bremen.de>
 L:     linux-hams@vger.kernel.org
 S:     Maintained
 F:     drivers/net/hamradio/6pack.c
 
 8169 10/100/1000 GIGABIT ETHERNET DRIVER
-P:     Francois Romieu
-M:     romieu@fr.zoreil.com
+M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/r8169.c
 
 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
-P:     Alan Cox
-M:     alan@lxorguk.ukuu.org.uk
 L:     linux-serial@vger.kernel.org
 W:     http://serial.sourceforge.net
-S:     Odd Fixes
+S:     Orphan
 F:     drivers/serial/8250*
 F:     include/linux/serial_8250.h
 
 8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.]
-P:     Paul Gortmaker
-M:     p_gortmaker@yahoo.com
+M:     Paul Gortmaker <p_gortmaker@yahoo.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/*8390*
 F:     drivers/net/ax88796.c
 
 9P FILE SYSTEM
-P:     Eric Van Hensbergen
-M:     ericvh@gmail.com
-P:     Ron Minnich
-M:     rminnich@sandia.gov
-P:     Latchesar Ionkov
-M:     lucho@ionkov.net
+M:     Eric Van Hensbergen <ericvh@gmail.com>
+M:     Ron Minnich <rminnich@sandia.gov>
+M:     Latchesar Ionkov <lucho@ionkov.net>
 L:     v9fs-developer@lists.sourceforge.net
 W:     http://swik.net/v9fs
 T:     git git://git.kernel.org/pub/scm/linux/kernel/ericvh/v9fs.git
@@ -194,15 +180,13 @@ F:        Documentation/filesystems/9p.txt
 F:     fs/9p/
 
 A2232 SERIAL BOARD DRIVER
-P:     Enver Haase
-M:     A2232@gmx.net
+M:     Enver Haase <A2232@gmx.net>
 L:     linux-m68k@lists.linux-m68k.org
 S:     Maintained
 F:     drivers/char/ser_a2232*
 
 AACRAID SCSI RAID DRIVER
-P:     Adaptec OEM Raid Solutions
-M:     aacraid@adaptec.com
+M:     Adaptec OEM Raid Solutions <aacraid@adaptec.com>
 L:     linux-scsi@vger.kernel.org
 W:     http://www.adaptec.com/
 S:     Supported
@@ -210,44 +194,38 @@ F:        Documentation/scsi/aacraid.txt
 F:     drivers/scsi/aacraid/
 
 ABIT UGURU 1,2 HARDWARE MONITOR DRIVER
-P:     Hans de Goede
-M:     j.w.r.degoede@hhs.nl
+M:     Hans de Goede <j.w.r.degoede@hhs.nl>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     drivers/hwmon/abituguru.c
 
 ABIT UGURU 3 HARDWARE MONITOR DRIVER
-P:     Alistair John Strachan
-M:     alistair@devzero.co.uk
+M:     Alistair John Strachan <alistair@devzero.co.uk>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     drivers/hwmon/abituguru3.c
 
 ACENIC DRIVER
-P:     Jes Sorensen
-M:     jes@trained-monkey.org
+M:     Jes Sorensen <jes@trained-monkey.org>
 L:     linux-acenic@sunsite.dk
 S:     Maintained
 F:     drivers/net/acenic*
 
 ACER ASPIRE ONE TEMPERATURE AND FAN DRIVER
-P: Peter Feuerer
-M: peter@piie.net
-W: http://piie.net/?section=acerhdf
-S: Maintained
-F: drivers/platform/x86/acerhdf.c
+M:     Peter Feuerer <peter@piie.net>
+W:     http://piie.net/?section=acerhdf
+S:     Maintained
+F:     drivers/platform/x86/acerhdf.c
 
 ACER WMI LAPTOP EXTRAS
-P:     Carlos Corbacho
-M:     carlos@strangeworlds.co.uk
+M:     Carlos Corbacho <carlos@strangeworlds.co.uk>
 L:     aceracpi@googlegroups.com (subscribers-only)
 W:     http://code.google.com/p/aceracpi
 S:     Maintained
 F:     drivers/platform/x86/acer-wmi.c
 
 ACPI
-P:     Len Brown
-M:     lenb@kernel.org
+M:     Len Brown <lenb@kernel.org>
 L:     linux-acpi@vger.kernel.org
 W:     http://www.lesswatts.org/projects/acpi/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
@@ -257,8 +235,7 @@ F:  drivers/pnp/pnpacpi/
 F:     include/linux/acpi.h
 
 ACPI BATTERY DRIVERS
-P:     Alexey Starikovskiy
-M:     astarikovskiy@suse.de
+M:     Alexey Starikovskiy <astarikovskiy@suse.de>
 L:     linux-acpi@vger.kernel.org
 W:     http://www.lesswatts.org/projects/acpi/
 S:     Supported
@@ -266,80 +243,69 @@ F:        drivers/acpi/battery.c
 F:     drivers/acpi/*sbs*
 
 ACPI EC DRIVER
-P:     Alexey Starikovskiy
-M:     astarikovskiy@suse.de
+M:     Alexey Starikovskiy <astarikovskiy@suse.de>
 L:     linux-acpi@vger.kernel.org
 W:     http://www.lesswatts.org/projects/acpi/
 S:     Supported
 F:     drivers/acpi/ec.c
 
 ACPI FAN DRIVER
-P:     Zhang Rui
-M:     rui.zhang@intel.com
+M:     Zhang Rui <rui.zhang@intel.com>
 L:     linux-acpi@vger.kernel.org
 W:     http://www.lesswatts.org/projects/acpi/
 S:     Supported
 F:     drivers/acpi/fan.c
 
 ACPI PCI HOTPLUG DRIVER
-P:     Kristen Carlson Accardi
-M:     kristen.c.accardi@intel.com
+M:     Kristen Carlson Accardi <kristen.c.accardi@intel.com>
 L:     linux-pci@vger.kernel.org
 S:     Supported
 F:     drivers/pci/hotplug/acpi*
 
 ACPI THERMAL DRIVER
-P:     Zhang Rui
-M:     rui.zhang@intel.com
+M:     Zhang Rui <rui.zhang@intel.com>
 L:     linux-acpi@vger.kernel.org
 W:     http://www.lesswatts.org/projects/acpi/
 S:     Supported
 F:     drivers/acpi/*thermal*
 
 ACPI VIDEO DRIVER
-P:     Zhang Rui
-M:     rui.zhang@intel.com
+M:     Zhang Rui <rui.zhang@intel.com>
 L:     linux-acpi@vger.kernel.org
 W:     http://www.lesswatts.org/projects/acpi/
 S:     Supported
 F:     drivers/acpi/video.c
 
 ACPI WMI DRIVER
-P:     Carlos Corbacho
-M:     carlos@strangeworlds.co.uk
+M:     Carlos Corbacho <carlos@strangeworlds.co.uk>
 L:     linux-acpi@vger.kernel.org
 W:     http://www.lesswatts.org/projects/acpi/
 S:     Maintained
 F:     drivers/platform/x86/wmi.c
 
 AD1889 ALSA SOUND DRIVER
-P:     Kyle McMartin
-M:     kyle@mcmartin.ca
-P:     Thibaut Varene
-M:     T-Bone@parisc-linux.org
+M:     Kyle McMartin <kyle@mcmartin.ca>
+M:     Thibaut Varene <T-Bone@parisc-linux.org>
 W:     http://wiki.parisc-linux.org/AD1889
 L:     linux-parisc@vger.kernel.org
 S:     Maintained
 F:     sound/pci/ad1889.*
 
 ADM1025 HARDWARE MONITOR DRIVER
-P:     Jean Delvare
-M:     khali@linux-fr.org
+M:     Jean Delvare <khali@linux-fr.org>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/adm1025
 F:     drivers/hwmon/adm1025.c
 
 ADM1029 HARDWARE MONITOR DRIVER
-P:     Corentin Labbe
-M:     corentin.labbe@geomatys.fr
+M:     Corentin Labbe <corentin.labbe@geomatys.fr>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     drivers/hwmon/adm1029.c
 
 ADM8211 WIRELESS DRIVER
-P:     Michael Wu
-M:     flamingice@sourmilk.net
+M:     Michael Wu <flamingice@sourmilk.net>
 L:     linux-wireless@vger.kernel.org
 W:     http://linuxwireless.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git
@@ -347,35 +313,30 @@ S:        Maintained
 F:     drivers/net/wireless/adm8211.*
 
 ADT746X FAN DRIVER
-P:     Colin Leroy
-M:     colin@colino.net
+M:     Colin Leroy <colin@colino.net>
 S:     Maintained
 F:     drivers/macintosh/therm_adt746x.c
 
 ADVANSYS SCSI DRIVER
-P:     Matthew Wilcox
-M:     matthew@wil.cx
+M:     Matthew Wilcox <matthew@wil.cx>
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
 F:     Documentation/scsi/advansys.txt
 F:     drivers/scsi/advansys.c
 
 AEDSP16 DRIVER
-P:     Riccardo Facchetti
-M:     fizban@tin.it
+M:     Riccardo Facchetti <fizban@tin.it>
 S:     Maintained
 F:     sound/oss/aedsp16.c
 
 AFFS FILE SYSTEM
-P:     Roman Zippel
-M:     zippel@linux-m68k.org
+M:     Roman Zippel <zippel@linux-m68k.org>
 S:     Maintained
 F:     Documentation/filesystems/affs.txt
 F:     fs/affs/
 
 AFS FILESYSTEM & AF_RXRPC SOCKET DOMAIN
-P:     David Howells
-M:     dhowells@redhat.com
+M:     David Howells <dhowells@redhat.com>
 L:     linux-afs@lists.infradead.org
 S:     Supported
 F:     fs/afs/
@@ -383,40 +344,35 @@ F:        include/net/af_rxrpc.h
 F:     net/rxrpc/af_rxrpc.c
 
 AGPGART DRIVER
-P:     David Airlie
-M:     airlied@linux.ie
+M:     David Airlie <airlied@linux.ie>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git
 S:     Maintained
 F:     drivers/char/agp/
 F:     include/linux/agp*
 
 AHA152X SCSI DRIVER
-P:     Juergen E. Fischer
-M:     fischer@norbit.de
+M:     "Juergen E. Fischer" <fischer@norbit.de>
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
 F:     drivers/scsi/aha152x*
 F:     drivers/scsi/pcmcia/aha152x*
 
 AIC7XXX / AIC79XX SCSI DRIVER
-P:     Hannes Reinecke
-M:     hare@suse.de
+M:     Hannes Reinecke <hare@suse.de>
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
 F:     drivers/scsi/aic7xxx/
 F:     drivers/scsi/aic7xxx_old/
 
 AIO
-P:     Benjamin LaHaise
-M:     bcrl@kvack.org
+M:     Benjamin LaHaise <bcrl@kvack.org>
 L:     linux-aio@kvack.org
 S:     Supported
 F:     fs/aio.c
 F:     include/linux/*aio*.h
 
 ALCATEL SPEEDTOUCH USB DRIVER
-P:     Duncan Sands
-M:     duncan.sands@free.fr
+M:     Duncan Sands <duncan.sands@free.fr>
 L:     linux-usb@vger.kernel.org
 W:     http://www.linux-usb.org/SpeedTouch/
 S:     Maintained
@@ -424,32 +380,27 @@ F:        drivers/usb/atm/speedtch.c
 F:     drivers/usb/atm/usbatm.c
 
 ALCHEMY AU1XX0 MMC DRIVER
-P:     Manuel Lauss
-M:     manuel.lauss@gmail.com
+M:     Manuel Lauss <manuel.lauss@gmail.com>
 S:     Maintained
 F:     drivers/mmc/host/au1xmmc.c
 
 ALI1563 I2C DRIVER
-P:     Rudolf Marek
-M:     r.marek@assembler.cz
+M:     Rudolf Marek <r.marek@assembler.cz>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     Documentation/i2c/busses/i2c-ali1563
 F:     drivers/i2c/busses/i2c-ali1563.c
 
 ALPHA PORT
-P:     Richard Henderson
-M:     rth@twiddle.net
+M:     Richard Henderson <rth@twiddle.net>
 S:     Odd Fixes for 2.4; Maintained for 2.6.
-P:     Ivan Kokshaysky
-M:     ink@jurassic.park.msu.ru
+M:     Ivan Kokshaysky <ink@jurassic.park.msu.ru>
 S:     Maintained for 2.4; PCI support for 2.6.
 L:     linux-alpha@vger.kernel.org
 F:     arch/alpha/
 
 AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER
-P:     Thomas Dahlmann
-M:     dahlmann.thomas@arcor.de
+M:     Thomas Dahlmann <dahlmann.thomas@arcor.de>
 L:     linux-geode@lists.infradead.org (moderated for non-subscribers)
 S:     Supported
 F:     drivers/usb/gadget/amd5536udc.*
@@ -466,8 +417,7 @@ F:  drivers/video/geode/
 F:     arch/x86/include/asm/geode.h
 
 AMD IOMMU (AMD-VI)
-P:     Joerg Roedel
-M:     joerg.roedel@amd.com
+M:     Joerg Roedel <joerg.roedel@amd.com>
 L:     iommu@lists.linux-foundation.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu.git
 S:     Supported
@@ -475,40 +425,33 @@ F:        arch/x86/kernel/amd_iommu*.c
 F:     arch/x86/include/asm/amd_iommu*.h
 
 AMD MICROCODE UPDATE SUPPORT
-P:     Andreas Herrmann
-M:     andreas.herrmann3@amd.com
+M:     Andreas Herrmann <andreas.herrmann3@amd.com>
 L:     amd64-microcode@amd64.org
 S:     Supported
 F:     arch/x86/kernel/microcode_amd.c
 
 AMS (Apple Motion Sensor) DRIVER
-P:     Stelian Pop
-M:     stelian@popies.net
-P:     Michael Hanselmann
-M:     linux-kernel@hansmi.ch
+M:     Stelian Pop <stelian@popies.net>
+M:     Michael Hanselmann <linux-kernel@hansmi.ch>
 S:     Supported
 F:     drivers/hwmon/ams/
 
 AMSO1100 RNIC DRIVER
-P:     Tom Tucker
-M:     tom@opengridcomputing.com
-P:     Steve Wise
-M:     swise@opengridcomputing.com
+M:     Tom Tucker <tom@opengridcomputing.com>
+M:     Steve Wise <swise@opengridcomputing.com>
 L:     general@lists.openfabrics.org
 S:     Maintained
 F:     drivers/infiniband/hw/amso1100/
 
 AOA (Apple Onboard Audio) ALSA DRIVER
-P:     Johannes Berg
-M:     johannes@sipsolutions.net
+M:     Johannes Berg <johannes@sipsolutions.net>
 L:     linuxppc-dev@ozlabs.org
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Maintained
 F:     sound/aoa/
 
 APM DRIVER
-P:     Stephen Rothwell
-M:     sfr@canb.auug.org.au
+M:     Stephen Rothwell <sfr@canb.auug.org.au>
 L:     linux-laptop@vger.kernel.org
 W:     http://www.canb.auug.org.au/~sfr/
 S:     Supported
@@ -516,51 +459,44 @@ F:        arch/x86/kernel/apm_32.c
 F:     include/linux/apm_bios.h
 
 APPLE BCM5974 MULTITOUCH DRIVER
-P:     Henrik Rydberg
-M:     rydberg@euromail.se
+M:     Henrik Rydberg <rydberg@euromail.se>
 L:     linux-input@vger.kernel.org
 S:     Maintained
 F:     drivers/input/mouse/bcm5974.c
 
 APPLE SMC DRIVER
-P:     Nicolas Boichat
-M:     nicolas@boichat.ch
+M:     Nicolas Boichat <nicolas@boichat.ch>
 L:     mactel-linux-devel@lists.sourceforge.net
 S:     Maintained
 F:     drivers/hwmon/applesmc.c
 
 APPLETALK NETWORK LAYER
-P:     Arnaldo Carvalho de Melo
-M:     acme@ghostprotocols.net
+M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 S:     Maintained
 F:     drivers/net/appletalk/
 F:     net/appletalk/
 
 APPLETOUCH TOUCHPAD DRIVER
-P:     Johannes Berg
-M:     johannes@sipsolutions.net
+M:     Johannes Berg <johannes@sipsolutions.net>
 L:     linux-input@vger.kernel.org
 S:     Maintained
 F:     Documentation/input/appletouch.txt
 F:     drivers/input/mouse/appletouch.c
 
 ARC FRAMEBUFFER DRIVER
-P:     Jaya Kumar
-M:     jayalk@intworks.biz
+M:     Jaya Kumar <jayalk@intworks.biz>
 S:     Maintained
 F:     drivers/video/arcfb.c
 F:     drivers/video/fb_defio.c
 
 ARM MFM AND FLOPPY DRIVERS
-P:     Ian Molton
-M:     spyro@f2s.com
+M:     Ian Molton <spyro@f2s.com>
 S:     Maintained
 F:     arch/arm/lib/floppydma.S
 F:     arch/arm/include/asm/floppy.h
 
 ARM PORT
-P:     Russell King
-M:     linux@arm.linux.org.uk
+M:     Russell King <linux@arm.linux.org.uk>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 W:     http://www.arm.linux.org.uk/
 S:     Maintained
@@ -571,79 +507,67 @@ S:        Orphan
 F:     drivers/mmc/host/mmci.*
 
 ARM/ADI ROADRUNNER MACHINE SUPPORT
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 F:     arch/arm/mach-ixp23xx/
 F:     arch/arm/mach-ixp23xx/include/mach/
 
 ARM/ADS SPHERE MACHINE SUPPORT
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/AFEB9260 MACHINE SUPPORT
-P:     Sergey Lapin
-M:     slapin@ossfans.org
+M:     Sergey Lapin <slapin@ossfans.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/AJECO 1ARM MACHINE SUPPORT
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/ATMEL AT91RM9200 ARM ARCHITECTURE
-P:     Andrew Victor
-M:     linux@maxim.org.za
+M:     Andrew Victor <linux@maxim.org.za>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 W:     http://maxim.org.za/at91_26.html
 S:     Maintained
 
 ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/CIRRUS LOGIC EDB9315A MACHINE SUPPORT
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/CLKDEV SUPPORT
-P:     Russell King
-M:     linux@arm.linux.org.uk
+M:     Russell King <linux@arm.linux.org.uk>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 F:     arch/arm/common/clkdev.c
 F:     arch/arm/include/asm/clkdev.h
 
 ARM/COMPULAB CM-X270/EM-X270 and CM-X300 MACHINE SUPPORT
-P:     Mike Rapoport
-M:     mike@compulab.co.il
+M:     Mike Rapoport <mike@compulab.co.il>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/CORGI MACHINE SUPPORT
-P:     Richard Purdie
-M:     rpurdie@rpsys.net
+M:     Richard Purdie <rpurdie@rpsys.net>
 S:     Maintained
 
 ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE
-P:     Paulius Zaleckas
-M:     paulius.zaleckas@teltonika.lt
+M:     Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 T:     git git://gitorious.org/linux-gemini/mainline.git
 S:     Maintained
 F:     arch/arm/mach-gemini/
 
 ARM/EBSA110 MACHINE SUPPORT
-P:     Russell King
-M:     linux@arm.linux.org.uk
+M:     Russell King <linux@arm.linux.org.uk>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 W:     http://www.arm.linux.org.uk/
 S:     Maintained
@@ -651,12 +575,9 @@ F: arch/arm/mach-ebsa110/
 F:     drivers/net/arm/am79c961a.*
 
 ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6)
-P:     Daniel Ribeiro
-M:     drwyrm@gmail.com
-P:     Stefan Schmidt
-M:     stefan@openezx.org
-P:     Harald Welte
-M:     laforge@openezx.org
+M:     Daniel Ribeiro <drwyrm@gmail.com>
+M:     Stefan Schmidt <stefan@openezx.org>
+M:     Harald Welte <laforge@openezx.org>
 L:     openezx-devel@lists.openezx.org (subscribers-only)
 W:     http://www.openezx.org/
 S:     Maintained
@@ -664,15 +585,13 @@ T:        topgit git://git.openezx.org/openezx.git
 F:     arch/arm/mach-pxa/ezx.c
 
 ARM/FARADAY FA526 PORT
-P:     Paulius Zaleckas
-M:     paulius.zaleckas@teltonika.lt
+M:     Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 F:     arch/arm/mm/*-fa*
 
 ARM/FOOTBRIDGE ARCHITECTURE
-P:     Russell King
-M:     linux@arm.linux.org.uk
+M:     Russell King <linux@arm.linux.org.uk>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 W:     http://www.arm.linux.org.uk/
 S:     Maintained
@@ -680,175 +599,146 @@ F:      arch/arm/include/asm/hardware/dec21285.h
 F:     arch/arm/mach-footbridge/
 
 ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
-P:     Sascha Hauer
-M:     kernel@pengutronix.de
+M:     Sascha Hauer <kernel@pengutronix.de>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/GUMSTIX MACHINE SUPPORT
-P:     Steve Sakoman
-M:     sakoman@gmail.com
+M:     Steve Sakoman <sakoman@gmail.com>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/H4700 (HP IPAQ HX4700) MACHINE SUPPORT
-P:     Philipp Zabel
-M:     philipp.zabel@gmail.com
+M:     Philipp Zabel <philipp.zabel@gmail.com>
 S:     Maintained
 F:     arch/arm/mach-pxa/hx4700.c
 F:     arch/arm/mach-pxa/include/mach/hx4700.h
 
 ARM/HP JORNADA 7XX MACHINE SUPPORT
-P:     Kristoffer Ericson
-M:     kristoffer.ericson@gmail.com
+M:     Kristoffer Ericson <kristoffer.ericson@gmail.com>
 W:     www.jlime.com
 S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
+F:     arch/arm/mach-sa1100/jornada720.c
+F:     arch/arm/mach-sa1100/include/mach/jornada720.h
 
 ARM/INTEL IOP32X ARM ARCHITECTURE
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
-P:     Dan Williams
-M:     dan.j.williams@intel.com
+M:     Lennert Buytenhek <kernel@wantstofly.org>
+M:     Dan Williams <dan.j.williams@intel.com>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Supported
 
 ARM/INTEL IOP33X ARM ARCHITECTURE
-P:     Dan Williams
-M:     dan.j.williams@intel.com
+M:     Dan Williams <dan.j.williams@intel.com>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Supported
 
 ARM/INTEL IOP13XX ARM ARCHITECTURE
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
-P:     Dan Williams
-M:     dan.j.williams@intel.com
+M:     Lennert Buytenhek <kernel@wantstofly.org>
+M:     Dan Williams <dan.j.williams@intel.com>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Supported
 
 ARM/INTEL IQ81342EX MACHINE SUPPORT
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
-P:     Dan Williams
-M:     dan.j.williams@intel.com
+M:     Lennert Buytenhek <kernel@wantstofly.org>
+M:     Dan Williams <dan.j.williams@intel.com>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Supported
 
 ARM/INTEL IXP2000 ARM ARCHITECTURE
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/INTEL IXDP2850 MACHINE SUPPORT
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/INTEL IXP23XX ARM ARCHITECTURE
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/INTEL XSC3 (MANZANO) ARM CORE
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
-P:     Dan Williams
-M:     dan.j.williams@intel.com
+M:     Lennert Buytenhek <kernel@wantstofly.org>
+M:     Dan Williams <dan.j.williams@intel.com>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Supported
 
 ARM/IP FABRICS DOUBLE ESPRESSO MACHINE SUPPORT
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/LOGICPD PXA270 MACHINE SUPPORT
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/MAGICIAN MACHINE SUPPORT
-P:     Philipp Zabel
-M:     philipp.zabel@gmail.com
+M:     Philipp Zabel <philipp.zabel@gmail.com>
 S:     Maintained
 
 ARM/MIOA701 MACHINE SUPPORT
-P:     Robert Jarzmik
-M:     robert.jarzmik@free.fr
+M:     Robert Jarzmik <robert.jarzmik@free.fr>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 F:     arch/arm/mach-pxa/mioa701.c
 S:     Maintained
 
 ARM/NEC MOBILEPRO 900/c MACHINE SUPPORT
-P:     Michael Petchkovsky
-M:     mkpetch@internode.on.net
+M:     Michael Petchkovsky <mkpetch@internode.on.net>
 S:     Maintained
 
 ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT
-P:     Nelson Castillo
-M:     arhuaco@freaks-unidos.net
+M:     Nelson Castillo <arhuaco@freaks-unidos.net>
 L:     openmoko-kernel@lists.openmoko.org (subscribers-only)
 W:     http://wiki.openmoko.org/wiki/Neo_FreeRunner
 S:     Supported
 
 ARM/TOSA MACHINE SUPPORT
-P:     Dmitry Eremin-Solenikov
-M:     dbaryshkov@gmail.com
-P:     Dirk Opfer
-M:     dirk@opfer-online.de
+M:     Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+M:     Dirk Opfer <dirk@opfer-online.de>
 S:     Maintained
 
 ARM/PALMTX,PALMT5,PALMLD,PALMTE2 SUPPORT
-P:     Marek Vasut
-M:     marek.vasut@gmail.com
+M:     Marek Vasut <marek.vasut@gmail.com>
 W:     http://hackndev.com
 S:     Maintained
 
 ARM/PALM TREO 680 SUPPORT
-P:     Tomas Cech
-M:     sleep_walker@suse.cz
+M:     Tomas Cech <sleep_walker@suse.cz>
 W:     http://hackndev.com
 S:     Maintained
 
 ARM/PALMZ72 SUPPORT
-P:     Sergey Lapin
-M:     slapin@ossfans.org
+M:     Sergey Lapin <slapin@ossfans.org>
 W:     http://hackndev.com
 S:     Maintained
 
 ARM/PLEB SUPPORT
-P:     Peter Chubb
-M:     pleb@gelato.unsw.edu.au
+M:     Peter Chubb <pleb@gelato.unsw.edu.au>
 W:     http://www.disy.cse.unsw.edu.au/Hardware/PLEB
 S:     Maintained
 
 ARM/PT DIGITAL BOARD PORT
-P:     Stefan Eletzhofer
-M:     stefan.eletzhofer@eletztrick.de
+M:     Stefan Eletzhofer <stefan.eletzhofer@eletztrick.de>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 W:     http://www.arm.linux.org.uk/
 S:     Maintained
 
 ARM/RADISYS ENP2611 MACHINE SUPPORT
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/RISCPC ARCHITECTURE
-P:     Russell King
-M:     linux@arm.linux.org.uk
+M:     Russell King <linux@arm.linux.org.uk>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 W:     http://www.arm.linux.org.uk/
 S:     Maintained
@@ -862,63 +752,86 @@ F:        drivers/net/arm/ether*
 F:     drivers/scsi/arm/
 
 ARM/SHARK MACHINE SUPPORT
-P:     Alexander Schulz
-M:     alex@shark-linux.de
+M:     Alexander Schulz <alex@shark-linux.de>
 W:     http://www.shark-linux.de/shark.html
 S:     Maintained
 
+ARM/SAMSUNG ARM ARCHITECTURES
+M:     Ben Dooks <ben-linux@fluff.org>
+L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W:     http://www.fluff.org/ben/linux/
+S:     Maintained
+F:     arch/arm/plat-s3c/
+F:     arch/arm/plat-s3c24xx/
+
 ARM/S3C2410 ARM ARCHITECTURE
-P:     Ben Dooks
-M:     ben-linux@fluff.org
+M:     Ben Dooks <ben-linux@fluff.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 W:     http://www.fluff.org/ben/linux/
 S:     Maintained
+F:     arch/arm/mach-s3c2410/
 
 ARM/S3C2440 ARM ARCHITECTURE
-P:     Ben Dooks
-M:     ben-linux@fluff.org
+M:     Ben Dooks <ben-linux@fluff.org>
+L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W:     http://www.fluff.org/ben/linux/
+S:     Maintained
+F:     arch/arm/mach-s3c2440/
+
+ARM/S3C2442 ARM ARCHITECTURE
+M:     Ben Dooks <ben-linux@fluff.org>
+L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W:     http://www.fluff.org/ben/linux/
+S:     Maintained
+F:     arch/arm/mach-s3c2442/
+
+ARM/S3C2443 ARM ARCHITECTURE
+M:     Ben Dooks <ben-linux@fluff.org>
+L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W:     http://www.fluff.org/ben/linux/
+S:     Maintained
+F:     arch/arm/mach-s3c2443/
+
+ARM/S3C6400 ARM ARCHITECTURE
+M:     Ben Dooks <ben-linux@fluff.org>
+L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W:     http://www.fluff.org/ben/linux/
+S:     Maintained
+F:     arch/arm/mach-s3c6400/
+
+ARM/S3C6410 ARM ARCHITECTURE
+M:     Ben Dooks <ben-linux@fluff.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 W:     http://www.fluff.org/ben/linux/
 S:     Maintained
+F:     arch/arm/mach-s3c6410/
 
 ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/THECUS N2100 MACHINE SUPPORT
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 
 ARM/NUVOTON W90X900 ARM ARCHITECTURE
-P:     Wan ZongShun
-M:     mcuos.com@gmail.com
+M:     Wan ZongShun <mcuos.com@gmail.com>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 W:     http://www.mcuos.com
 S:     Maintained
 
 ARM/VFP SUPPORT
-P:     Russell King
-M:     linux@arm.linux.org.uk
+M:     Russell King <linux@arm.linux.org.uk>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 W:     http://www.arm.linux.org.uk/
 S:     Maintained
 F:     arch/arm/vfp/
 
-ARPD SUPPORT
-P:     Jonathan Layes
-L:     netdev@vger.kernel.org
-S:     Maintained
-F:     net/ipv4/arp.c
-
 ASUS ACPI EXTRAS DRIVER
-P:     Corentin Chary
-M:     corentincj@iksaif.net
-P:     Karol Kozimor
-M:     sziwan@users.sourceforge.net
+M:     Corentin Chary <corentincj@iksaif.net>
+M:     Karol Kozimor <sziwan@users.sourceforge.net>
 L:     acpi4asus-user@lists.sourceforge.net
 W:     http://acpi4asus.sf.net
 S:     Maintained
@@ -926,25 +839,21 @@ F:        arch/x86/kernel/acpi/boot.c
 F:     drivers/platform/x86/asus_acpi.c
 
 ASUS ASB100 HARDWARE MONITOR DRIVER
-P:     Mark M. Hoffman
-M:     mhoffman@lightlink.com
+M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     drivers/hwmon/asb100.c
 
 ASUS LAPTOP EXTRAS DRIVER
-P:     Corentin Chary
-M:     corentincj@iksaif.net
+M:     Corentin Chary <corentincj@iksaif.net>
 L:     acpi4asus-user@lists.sourceforge.net
 W:     http://acpi4asus.sf.net
 S:     Maintained
 F:     drivers/platform/x86/asus-laptop.c
 
 ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API
-P:     Dan Williams
-M:     dan.j.williams@intel.com
-P:     Maciej Sosnowski
-M:     maciej.sosnowski@intel.com
+M:     Dan Williams <dan.j.williams@intel.com>
+M:     Maciej Sosnowski <maciej.sosnowski@intel.com>
 W:     http://sourceforge.net/projects/xscaleiop
 S:     Supported
 F:     Documentation/crypto/async-tx-api.txt
@@ -954,64 +863,49 @@ F:        include/linux/dmaengine.h
 F:     include/linux/async_tx.h
 
 ATA OVER ETHERNET (AOE) DRIVER
-P:     Ed L. Cashin
-M:     ecashin@coraid.com
+M:     "Ed L. Cashin" <ecashin@coraid.com>
 W:     http://www.coraid.com/support/linux
 S:     Supported
 F:     Documentation/aoe/
 F:     drivers/block/aoe/
 
 ATHEROS ATH5K WIRELESS DRIVER
-P:     Jiri Slaby
-M:     jirislaby@gmail.com
-P:     Nick Kossifidis
-M:     mickflemm@gmail.com
-P:     Luis R. Rodriguez
-M:     lrodriguez@atheros.com
-P:     Bob Copeland
-M:     me@bobcopeland.com
+M:     Jiri Slaby <jirislaby@gmail.com>
+M:     Nick Kossifidis <mickflemm@gmail.com>
+M:     "Luis R. Rodriguez" <lrodriguez@atheros.com>
+M:     Bob Copeland <me@bobcopeland.com>
 L:     linux-wireless@vger.kernel.org
 L:     ath5k-devel@lists.ath5k.org
 S:     Maintained
 F:     drivers/net/wireless/ath/ath5k/
 
 ATHEROS ATH9K WIRELESS DRIVER
-P:     Luis R. Rodriguez
-M:     lrodriguez@atheros.com
-P:     Jouni Malinen
-M:     jmalinen@atheros.com
-P:     Sujith Manoharan
-M:     Sujith.Manoharan@atheros.com
-P:     Vasanthakumar Thiagarajan
-M:     vasanth@atheros.com
-P:     Senthil Balasubramanian
-M:     senthilkumar@atheros.com
+M:     "Luis R. Rodriguez" <lrodriguez@atheros.com>
+M:     Jouni Malinen <jmalinen@atheros.com>
+M:     Sujith Manoharan <Sujith.Manoharan@atheros.com>
+M:     Vasanthakumar Thiagarajan <vasanth@atheros.com>
+M:     Senthil Balasubramanian <senthilkumar@atheros.com>
 L:     linux-wireless@vger.kernel.org
 L:     ath9k-devel@lists.ath9k.org
 S:     Supported
 F:     drivers/net/wireless/ath/ath9k/
 
 ATHEROS AR9170 WIRELESS DRIVER
-P:     Christian Lamparter
-M:     chunkeey@web.de
+M:     Christian Lamparter <chunkeey@web.de>
 L:     linux-wireless@vger.kernel.org
 W:     http://wireless.kernel.org/en/users/Drivers/ar9170
 S:     Maintained
 F:     drivers/net/wireless/ath/ar9170/
 
 ATI_REMOTE2 DRIVER
-P:     Ville Syrjala
-M:     syrjala@sci.fi
+M:     Ville Syrjala <syrjala@sci.fi>
 S:     Maintained
 F:     drivers/input/misc/ati_remote2.c
 
 ATLX ETHERNET DRIVERS
-P:     Jay Cliburn
-M:     jcliburn@gmail.com
-P:     Chris Snook
-M:     csnook@redhat.com
-P:     Jie Yang
-M:     jie.yang@atheros.com
+M:     Jay Cliburn <jcliburn@gmail.com>
+M:     Chris Snook <chris.snook@gmail.com>
+M:     Jie Yang <jie.yang@atheros.com>
 L:     atl1-devel@lists.sourceforge.net
 W:     http://sourceforge.net/projects/atl1
 W:     http://atl1.sourceforge.net
@@ -1019,8 +913,7 @@ S: Maintained
 F:     drivers/net/atlx/
 
 ATM
-P:     Chas Williams
-M:     chas@cmf.nrl.navy.mil
+M:     Chas Williams <chas@cmf.nrl.navy.mil>
 L:     linux-atm-general@lists.sourceforge.net (subscribers-only)
 L:     netdev@vger.kernel.org
 W:     http://linux-atm.sourceforge.net
@@ -1029,8 +922,7 @@ F: drivers/atm/
 F:     include/linux/atm*
 
 ATMEL AT91 MCI DRIVER
-P:     Nicolas Ferre
-M:     nicolas.ferre@atmel.com
+M:     Nicolas Ferre <nicolas.ferre@atmel.com>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 W:     http://www.atmel.com/products/AT91/
 W:     http://www.at91.com/
@@ -1038,49 +930,42 @@ S:       Maintained
 F:     drivers/mmc/host/at91_mci.c
 
 ATMEL AT91 / AT32 MCI DRIVER
-P:     Nicolas Ferre
-M:     nicolas.ferre@atmel.com
+M:     Nicolas Ferre <nicolas.ferre@atmel.com>
 S:     Maintained
 F:     drivers/mmc/host/atmel-mci.c
 F:     drivers/mmc/host/atmel-mci-regs.h
 
 ATMEL AT91 / AT32 SERIAL DRIVER
-P:     Haavard Skinnemoen
-M:     hskinnemoen@atmel.com
+M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
 S:     Supported
 F:     drivers/serial/atmel_serial.c
 
 ATMEL LCDFB DRIVER
-P:     Nicolas Ferre
-M:     nicolas.ferre@atmel.com
+M:     Nicolas Ferre <nicolas.ferre@atmel.com>
 L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/video/atmel_lcdfb.c
 F:     include/video/atmel_lcdc.h
 
 ATMEL MACB ETHERNET DRIVER
-P:     Haavard Skinnemoen
-M:     hskinnemoen@atmel.com
+M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
 S:     Supported
 F:     drivers/net/macb.*
 
 ATMEL SPI DRIVER
-P:     Haavard Skinnemoen
-M:     hskinnemoen@atmel.com
+M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
 S:     Supported
 F:     drivers/spi/atmel_spi.*
 
 ATMEL USBA UDC DRIVER
-P:     Haavard Skinnemoen
-M:     hskinnemoen@atmel.com
+M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
 L:     kernel@avr32linux.org
 W:     http://avr32linux.org/twiki/bin/view/Main/AtmelUsbDeviceDriver
 S:     Supported
 F:     drivers/usb/gadget/atmel_usba_udc.*
 
 ATMEL WIRELESS DRIVER
-P:     Simon Kelley
-M:     simon@thekelleys.org.uk
+M:     Simon Kelley <simon@thekelleys.org.uk>
 L:     linux-wireless@vger.kernel.org
 W:     http://www.thekelleys.org.uk/atmel
 W:     http://atmelwlandriver.sourceforge.net/
@@ -1088,10 +973,8 @@ S:        Maintained
 F:     drivers/net/wireless/atmel*
 
 AUDIT SUBSYSTEM
-P:     Al Viro
-M:     viro@zeniv.linux.org.uk
-P:     Eric Paris
-M:     eparis@redhat.com
+M:     Al Viro <viro@zeniv.linux.org.uk>
+M:     Eric Paris <eparis@redhat.com>
 L:     linux-audit@redhat.com (subscribers-only)
 W:     http://people.redhat.com/sgrubb/audit/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current.git
@@ -1100,8 +983,7 @@ F: include/linux/audit.h
 F:     kernel/audit*
 
 AUXILIARY DISPLAY DRIVERS
-P:     Miguel Ojeda Sandonis
-M:     miguel.ojeda.sandonis@gmail.com
+M:     Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>
 W:     http://miguelojeda.es/auxdisplay.htm
 W:     http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
 S:     Maintained
@@ -1109,8 +991,7 @@ F: drivers/auxdisplay/
 F:     include/linux/cfag12864b.h
 
 AVR32 ARCHITECTURE
-P:     Haavard Skinnemoen
-M:     hskinnemoen@atmel.com
+M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
 W:     http://www.atmel.com/products/AVR32/
 W:     http://avr32linux.org/
 W:     http://avrfreaks.net/
@@ -1118,14 +999,12 @@ S:       Supported
 F:     arch/avr32/
 
 AVR32/AT32AP MACHINE SUPPORT
-P:     Haavard Skinnemoen
-M:     hskinnemoen@atmel.com
+M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
 S:     Supported
 F:     arch/avr32/mach-at32ap/
 
 AX.25 NETWORK LAYER
-P:     Ralf Baechle
-M:     ralf@linux-mips.org
+M:     Ralf Baechle <ralf@linux-mips.org>
 L:     linux-hams@vger.kernel.org
 W:     http://www.linux-ax25.org/
 S:     Maintained
@@ -1134,128 +1013,110 @@ F:    include/net/ax25.h
 F:     net/ax25/
 
 B43 WIRELESS DRIVER
-P:     Michael Buesch
-M:     mb@bu3sch.de
-P:     Stefano Brivio
-M:     stefano.brivio@polimi.it
+M:     Michael Buesch <mb@bu3sch.de>
+M:     Stefano Brivio <stefano.brivio@polimi.it>
 L:     linux-wireless@vger.kernel.org
 W:     http://linuxwireless.org/en/users/Drivers/b43
 S:     Maintained
 F:     drivers/net/wireless/b43/
 
 B43LEGACY WIRELESS DRIVER
-P:     Larry Finger
-M:     Larry.Finger@lwfinger.net
-P:     Stefano Brivio
-M:     stefano.brivio@polimi.it
+M:     Larry Finger <Larry.Finger@lwfinger.net>
+M:     Stefano Brivio <stefano.brivio@polimi.it>
 L:     linux-wireless@vger.kernel.org
 W:     http://linuxwireless.org/en/users/Drivers/b43
 S:     Maintained
 F:     drivers/net/wireless/b43legacy/
 
 BACKLIGHT CLASS/SUBSYSTEM
-P:     Richard Purdie
-M:     rpurdie@rpsys.net
+M:     Richard Purdie <rpurdie@rpsys.net>
 S:     Maintained
 F:     drivers/video/backlight/
 F:     include/linux/backlight.h
 
 BAYCOM/HDLCDRV DRIVERS FOR AX.25
-P:     Thomas Sailer
-M:     t.sailer@alumni.ethz.ch
+M:     Thomas Sailer <t.sailer@alumni.ethz.ch>
 L:     linux-hams@vger.kernel.org
 W:     http://www.baycom.org/~tom/ham/ham.html
 S:     Maintained
 F:     drivers/net/hamradio/baycom*
 
 BEFS FILE SYSTEM
-P:     Sergey S. Kostyliov
-M:     rathamahata@php4.ru
+M:     "Sergey S. Kostyliov" <rathamahata@php4.ru>
 S:     Maintained
 F:     Documentation/filesystems/befs.txt
 F:     fs/befs/
 
 BFS FILE SYSTEM
-P:     Tigran A. Aivazian
-M:     tigran@aivazian.fsnet.co.uk
+M:     "Tigran A. Aivazian" <tigran@aivazian.fsnet.co.uk>
 S:     Maintained
 F:     Documentation/filesystems/bfs.txt
 F:     fs/bfs/
 F:     include/linux/bfs_fs.h
 
 BLACKFIN ARCHITECTURE
-P:     Mike Frysinger
-M:     vapier@gentoo.org
+M:     Mike Frysinger <vapier@gentoo.org>
 L:     uclinux-dist-devel@blackfin.uclinux.org
 W:     http://blackfin.uclinux.org
 S:     Supported
 F:     arch/blackfin/
 
 BLACKFIN EMAC DRIVER
-P:     Michael Hennerich
-M:     michael.hennerich@analog.com
+M:     Michael Hennerich <michael.hennerich@analog.com>
 L:     uclinux-dist-devel@blackfin.uclinux.org
 W:     http://blackfin.uclinux.org
 S:     Supported
 F:     drivers/net/bfin_mac.*
 
 BLACKFIN RTC DRIVER
-P:     Mike Frysinger
-M:     vapier.adi@gmail.com
+M:     Mike Frysinger <vapier.adi@gmail.com>
 L:     uclinux-dist-devel@blackfin.uclinux.org
 W:     http://blackfin.uclinux.org
 S:     Supported
 F:     drivers/rtc/rtc-bfin.c
 
 BLACKFIN SERIAL DRIVER
-P:     Sonic Zhang
-M:     sonic.zhang@analog.com
+M:     Sonic Zhang <sonic.zhang@analog.com>
 L:     uclinux-dist-devel@blackfin.uclinux.org
 W:     http://blackfin.uclinux.org
 S:     Supported
 F:     drivers/serial/bfin_5xx.c
 
 BLACKFIN WATCHDOG DRIVER
-P:     Mike Frysinger
-M:     vapier.adi@gmail.com
+M:     Mike Frysinger <vapier.adi@gmail.com>
 L:     uclinux-dist-devel@blackfin.uclinux.org
 W:     http://blackfin.uclinux.org
 S:     Supported
 F:     drivers/watchdog/bfin_wdt.c
 
 BLACKFIN I2C TWI DRIVER
-P:     Sonic Zhang
-M:     sonic.zhang@analog.com
+M:     Sonic Zhang <sonic.zhang@analog.com>
 L:     uclinux-dist-devel@blackfin.uclinux.org
 W:     http://blackfin.uclinux.org/
 S:     Supported
 F:     drivers/i2c/busses/i2c-bfin-twi.c
 
 BLOCK LAYER
-P:     Jens Axboe
-M:     axboe@kernel.dk
+M:     Jens Axboe <axboe@kernel.dk>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
 S:     Maintained
 F:     block/
 
 BLOCK2MTD DRIVER
-P:     Joern Engel
-M:     joern@lazybastard.org
+M:     Joern Engel <joern@lazybastard.org>
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
 F:     drivers/mtd/devices/block2mtd.c
 
 BLUETOOTH DRIVERS
-P:     Marcel Holtmann
-M:     marcel@holtmann.org
+M:     Marcel Holtmann <marcel@holtmann.org>
 L:     linux-bluetooth@vger.kernel.org
 W:     http://www.bluez.org/
 S:     Maintained
 F:     drivers/bluetooth/
 
 BLUETOOTH SUBSYSTEM
-P:     Marcel Holtmann
-M:     marcel@holtmann.org
+M:     Marcel Holtmann <marcel@holtmann.org>
 L:     linux-bluetooth@vger.kernel.org
 W:     http://www.bluez.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git
@@ -1264,8 +1125,7 @@ F:        net/bluetooth/
 F:     include/net/bluetooth/
 
 BONDING DRIVER
-P:     Jay Vosburgh
-M:     fubar@us.ibm.com
+M:     Jay Vosburgh <fubar@us.ibm.com>
 L:     bonding-devel@lists.sourceforge.net
 W:     http://sourceforge.net/projects/bonding/
 S:     Supported
@@ -1273,54 +1133,46 @@ F:      drivers/net/bonding/
 F:     include/linux/if_bonding.h
 
 BROADCOM B44 10/100 ETHERNET DRIVER
-P:     Gary Zambrano
-M:     zambrano@broadcom.com
+M:     Gary Zambrano <zambrano@broadcom.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/b44.*
 
 BROADCOM BNX2 GIGABIT ETHERNET DRIVER
-P:     Michael Chan
-M:     mchan@broadcom.com
+M:     Michael Chan <mchan@broadcom.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/bnx2.*
 F:     drivers/net/bnx2_*
 
 BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
-P:     Eilon Greenstein
-M:     eilong@broadcom.com
+M:     Eilon Greenstein <eilong@broadcom.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/bnx2x*
 
 BROADCOM TG3 GIGABIT ETHERNET DRIVER
-P:     Matt Carlson
-M:     mcarlson@broadcom.com
-P:     Michael Chan
-M:     mchan@broadcom.com
+M:     Matt Carlson <mcarlson@broadcom.com>
+M:     Michael Chan <mchan@broadcom.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/tg3.*
 
 BSG (block layer generic sg v4 driver)
-P:     FUJITA Tomonori
-M:     fujita.tomonori@lab.ntt.co.jp
+M:     FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
 L:     linux-scsi@vger.kernel.org
 S:     Supported
 F:     block/bsg.c
 F:     include/linux/bsg.h
 
 BT8XXGPIO DRIVER
-P:     Michael Buesch
-M:     mb@bu3sch.de
+M:     Michael Buesch <mb@bu3sch.de>
 W:     http://bu3sch.de/btgpio.php
 S:     Maintained
 F:     drivers/gpio/bt8xxgpio.c
 
 BTRFS FILE SYSTEM
-P:     Chris Mason
-M:     chris.mason@oracle.com
+M:     Chris Mason <chris.mason@oracle.com>
 L:     linux-btrfs@vger.kernel.org
 W:     http://btrfs.wiki.kernel.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable.git
@@ -1329,8 +1181,7 @@ F:        Documentation/filesystems/btrfs.txt
 F:     fs/btrfs/
 
 BTTV VIDEO4LINUX DRIVER
-P:     Mauro Carvalho Chehab
-M:     mchehab@infradead.org
+M:     Mauro Carvalho Chehab <mchehab@infradead.org>
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
@@ -1339,16 +1190,14 @@ F:      Documentation/video4linux/bttv/
 F:     drivers/media/video/bt8xx/bttv*
 
 CACHEFILES: FS-CACHE BACKEND FOR CACHING ON MOUNTED FILESYSTEMS
-P:     David Howells
-M:     dhowells@redhat.com
+M:     David Howells <dhowells@redhat.com>
 L:     linux-cachefs@redhat.com
 S:     Supported
 F:     Documentation/filesystems/caching/cachefiles.txt
 F:     fs/cachefiles/
 
 CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER
-P:     Jonathan Corbet
-M:     corbet@lwn.net
+M:     Jonathan Corbet <corbet@lwn.net>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 S:     Maintained
@@ -1356,10 +1205,8 @@ F:       Documentation/video4linux/cafe_ccic
 F:     drivers/media/video/cafe_ccic*
 
 CALGARY x86-64 IOMMU
-P:     Muli Ben-Yehuda
-M:     muli@il.ibm.com
-P:     Jon D. Mason
-M:     jdmason@kudzu.us
+M:     Muli Ben-Yehuda <muli@il.ibm.com>
+M:     "Jon D. Mason" <jdmason@kudzu.us>
 L:     discuss@x86-64.org
 S:     Maintained
 F:     arch/x86/kernel/pci-calgary_64.c
@@ -1368,10 +1215,8 @@ F:       arch/x86/include/asm/calgary.h
 F:     arch/x86/include/asm/tce.h
 
 CAN NETWORK LAYER
-P:     Urs Thuermann
-M:     urs.thuermann@volkswagen.de
-P:     Oliver Hartkopp
-M:     oliver.hartkopp@volkswagen.de
+M:     Urs Thuermann <urs.thuermann@volkswagen.de>
+M:     Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
 L:     socketcan-core@lists.berlios.de (subscribers-only)
 W:     http://developer.berlios.de/projects/socketcan/
 S:     Maintained
@@ -1380,15 +1225,13 @@ F:      include/linux/can/
 F:     include/linux/can.h
 
 CAN NETWORK DRIVERS
-P:     Wolfgang Grandegger
-M:     wg@grandegger.com
+M:     Wolfgang Grandegger <wg@grandegger.com>
 L:     socketcan-core@lists.berlios.de (subscribers-only)
 W:     http://developer.berlios.de/projects/socketcan/
 S:     Maintained
 
 CELL BROADBAND ENGINE ARCHITECTURE
-P:     Arnd Bergmann
-M:     arnd@arndb.de
+M:     Arnd Bergmann <arnd@arndb.de>
 L:     linuxppc-dev@ozlabs.org
 L:     cbe-oss-dev@ozlabs.org
 W:     http://www.ibm.com/developerworks/power/cell/
@@ -1399,8 +1242,7 @@ F:        arch/powerpc/oprofile/*cell*
 F:     arch/powerpc/platforms/cell/
 
 CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
-P:     David Vrabel
-M:     david.vrabel@csr.com
+M:     David Vrabel <david.vrabel@csr.com>
 L:     linux-usb@vger.kernel.org
 S:     Supported
 F:     Documentation/usb/WUSB-Design-overview.txt
@@ -1409,8 +1251,7 @@ F:        drivers/usb/wusbcore/
 F:     include/linux/usb/wusb*
 
 CFAG12864B LCD DRIVER
-P:     Miguel Ojeda Sandonis
-M:     miguel.ojeda.sandonis@gmail.com
+M:     Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>
 W:     http://miguelojeda.es/auxdisplay.htm
 W:     http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
 S:     Maintained
@@ -1418,8 +1259,7 @@ F:        drivers/auxdisplay/cfag12864b.c
 F:     include/linux/cfag12864b.h
 
 CFAG12864BFB LCD FRAMEBUFFER DRIVER
-P:     Miguel Ojeda Sandonis
-M:     miguel.ojeda.sandonis@gmail.com
+M:     Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>
 W:     http://miguelojeda.es/auxdisplay.htm
 W:     http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
 S:     Maintained
@@ -1427,8 +1267,7 @@ F:        drivers/auxdisplay/cfag12864bfb.c
 F:     include/linux/cfag12864b.h
 
 CFG80211 and NL80211
-P:     Johannes Berg
-M:     johannes@sipsolutions.net
+M:     Johannes Berg <johannes@sipsolutions.net>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
 F:     include/linux/nl80211.h
@@ -1437,66 +1276,47 @@ F:      net/wireless/*
 X:     net/wireless/wext*
 
 CHECKPATCH
-P:     Andy Whitcroft
-M:     apw@canonical.com
+M:     Andy Whitcroft <apw@canonical.com>
 S:     Supported
 F:     scripts/checkpatch.pl
 
 CISCO 10G ETHERNET DRIVER
-P:     Scott Feldman
-M:     scofeldm@cisco.com
-P:     Joe Eykholt
-M:     jeykholt@cisco.com
+M:     Scott Feldman <scofeldm@cisco.com>
+M:     Joe Eykholt <jeykholt@cisco.com>
 S:     Supported
 F:     drivers/net/enic/
 
 CIRRUS LOGIC EP93XX ETHERNET DRIVER
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/arm/ep93xx_eth.c
 
 CIRRUS LOGIC EP93XX OHCI USB HOST DRIVER
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/host/ohci-ep93xx.c
 
 CIRRUS LOGIC CS4270 SOUND DRIVER
-P:     Timur Tabi
-M:     timur@freescale.com
+M:     Timur Tabi <timur@freescale.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Supported
 F:     sound/soc/codecs/cs4270*
 
-CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER
-P:     Cirrus Logic Corporation (kernel 2.2 driver)
-M:     Cirrus Logic Corporation, Thomas Woller <twoller@crystal.cirrus.com>
-P:     Nils Faerber (port to kernel 2.4)
-M:     Nils Faerber <nils@kernelconcepts.de>
-S:     Maintained
-F:     Documentation/input/cs461x.txt
-F:     sound/pci/cs46xx/
-
 CLK API
-P:     Russell King
-M:     linux@arm.linux.org.uk
+M:     Russell King <linux@arm.linux.org.uk>
 F:     include/linux/clk.h
 
 CISCO FCOE HBA DRIVER
-P:     Abhijeet Joglekar
-M:     abjoglek@cisco.com
-P:     Joe Eykholt
-M:     jeykholt@cisco.com
+M:     Abhijeet Joglekar <abjoglek@cisco.com>
+M:     Joe Eykholt <jeykholt@cisco.com>
 L:     linux-scsi@vger.kernel.org
 S:     Supported
 F:     drivers/scsi/fnic/
 
 CODA FILE SYSTEM
-P:     Jan Harkes
-M:     jaharkes@cs.cmu.edu
+M:     Jan Harkes <jaharkes@cs.cmu.edu>
 M:     coda@cs.cmu.edu
 L:     codalist@coda.cs.cmu.edu
 W:     http://www.coda.cs.cmu.edu/
@@ -1506,8 +1326,7 @@ F:        fs/coda/
 F:     include/linux/coda*.h
 
 COMMON INTERNET FILE SYSTEM (CIFS)
-P:     Steve French
-M:     sfrench@samba.org
+M:     Steve French <sfrench@samba.org>
 L:     linux-cifs-client@lists.samba.org
 L:     samba-technical@lists.samba.org
 W:     http://linux-cifs.samba.org/
@@ -1517,63 +1336,57 @@ F:      Documentation/filesystems/cifs.txt
 F:     fs/cifs/
 
 COMPACTPCI HOTPLUG CORE
-P:     Scott Murray
-M:     scottm@somanetworks.com
-M:     scott@spiteful.org
+M:     Scott Murray <scott@spiteful.org>
 L:     linux-pci@vger.kernel.org
-S:     Supported
+S:     Maintained
 F:     drivers/pci/hotplug/cpci_hotplug*
 
 COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER
-P:     Scott Murray
-M:     scottm@somanetworks.com
-M:     scott@spiteful.org
+M:     Scott Murray <scott@spiteful.org>
 L:     linux-pci@vger.kernel.org
-S:     Supported
+S:     Maintained
 F:     drivers/pci/hotplug/cpcihp_zt5550.*
 
 COMPACTPCI HOTPLUG GENERIC DRIVER
-P:     Scott Murray
-M:     scottm@somanetworks.com
-M:     scott@spiteful.org
+M:     Scott Murray <scott@spiteful.org>
 L:     linux-pci@vger.kernel.org
-S:     Supported
+S:     Maintained
 F:     drivers/pci/hotplug/cpcihp_generic.c
 
 COMPAL LAPTOP SUPPORT
-P:     Cezary Jackiewicz
-M:     cezary.jackiewicz@gmail.com
+M:     Cezary Jackiewicz <cezary.jackiewicz@gmail.com>
 S:     Maintained
 F:     drivers/platform/x86/compal-laptop.c
 
 COMPUTONE INTELLIPORT MULTIPORT CARD
-P:     Michael H. Warfield
-M:     mhw@wittsend.com
+M:     "Michael H. Warfield" <mhw@wittsend.com>
 W:     http://www.wittsend.com/computone.html
 S:     Maintained
 F:     Documentation/serial/computone.txt
 F:     drivers/char/ip2/
 
 CONEXANT ACCESSRUNNER USB DRIVER
-P:     Simon Arlott
-M:     cxacru@fire.lp0.eu
+M:     Simon Arlott <cxacru@fire.lp0.eu>
 L:     accessrunner-general@lists.sourceforge.net
 W:     http://accessrunner.sourceforge.net/
 S:     Maintained
 F:     drivers/usb/atm/cxacru.c
 
 CONFIGFS
-P:     Joel Becker
-M:     joel.becker@oracle.com
+M:     Joel Becker <joel.becker@oracle.com>
 S:     Supported
 F:     fs/configfs/
 F:     include/linux/configfs.h
 
+CONNECTOR
+M:     Evgeniy Polyakov <zbr@ioremap.net>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/connector/
+
 CONTROL GROUPS (CGROUPS)
-P:     Paul Menage
-M:     menage@google.com
-P:     Li Zefan
-M:     lizf@cn.fujitsu.com
+M:     Paul Menage <menage@google.com>
+M:     Li Zefan <lizf@cn.fujitsu.com>
 L:     containers@lists.linux-foundation.org
 S:     Maintained
 F:     include/linux/cgroup*
@@ -1581,30 +1394,26 @@ F:      kernel/cgroup*
 F:     mm/*cgroup*
 
 CORETEMP HARDWARE MONITORING DRIVER
-P:     Rudolf Marek
-M:     r.marek@assembler.cz
+M:     Rudolf Marek <r.marek@assembler.cz>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/coretemp
 F:     drivers/hwmon/coretemp.c
 
 COSA/SRP SYNC SERIAL DRIVER
-P:     Jan "Yenya" Kasprzak
-M:     kas@fi.muni.cz
+M:     Jan "Yenya" Kasprzak <kas@fi.muni.cz>
 W:     http://www.fi.muni.cz/~kas/cosa/
 S:     Maintained
 F:     drivers/net/wan/cosa*
 
 CPMAC ETHERNET DRIVER
-P:     Florian Fainelli
-M:     florian@openwrt.org
+M:     Florian Fainelli <florian@openwrt.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/cpmac.c
 
 CPU FREQUENCY DRIVERS
-P:     Dave Jones
-M:     davej@redhat.com
+M:     Dave Jones <davej@redhat.com>
 L:     cpufreq@vger.kernel.org
 W:     http://www.codemonkey.org.uk/projects/cpufreq/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq.git
@@ -1614,15 +1423,13 @@ F:      drivers/cpufreq/
 F:     include/linux/cpufreq.h
 
 CPUID/MSR DRIVER
-P:     H. Peter Anvin
-M:     hpa@zytor.com
+M:     "H. Peter Anvin" <hpa@zytor.com>
 S:     Maintained
 F:     arch/x86/kernel/cpuid.c
 F:     arch/x86/kernel/msr.c
 
 CPUSETS
-P:     Paul Menage
-M:     menage@google.com
+M:     Paul Menage <menage@google.com>
 W:     http://www.bullopensource.org/cpuset/
 W:     http://oss.sgi.com/projects/cpusets/
 S:     Supported
@@ -1637,20 +1444,16 @@ F:      Documentation/filesystems/cramfs.txt
 F:     fs/cramfs/
 
 CRIS PORT
-P:     Mikael Starvik
-M:     starvik@axis.com
-P:     Jesper Nilsson
-M:     jesper.nilsson@axis.com
+M:     Mikael Starvik <starvik@axis.com>
+M:     Jesper Nilsson <jesper.nilsson@axis.com>
 L:     linux-cris-kernel@axis.com
 W:     http://developer.axis.com
 S:     Maintained
 F:     arch/cris/
 
 CRYPTO API
-P:     Herbert Xu
-M:     herbert@gondor.apana.org.au
-P:     David S. Miller
-M:     davem@davemloft.net
+M:     Herbert Xu <herbert@gondor.apana.org.au>
+M:     "David S. Miller" <davem@davemloft.net>
 L:     linux-crypto@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git
 S:     Maintained
@@ -1661,58 +1464,50 @@ F:      drivers/crypto/
 F:     include/crypto/
 
 CRYPTOGRAPHIC RANDOM NUMBER GENERATOR
-P:     Neil Horman
-M:     nhorman@tuxdriver.com
+M:     Neil Horman <nhorman@tuxdriver.com>
 L:     linux-crypto@vger.kernel.org
 S:     Maintained
 
 CS5535 Audio ALSA driver
-P:     Jaya Kumar
-M:     jayakumar.alsa@gmail.com
+M:     Jaya Kumar <jayakumar.alsa@gmail.com>
 S:     Maintained
 F:     sound/pci/cs5535audio/
 
 CX18 VIDEO4LINUX DRIVER
-P:     Hans Verkuil
-M:     hverkuil@xs4all.nl
-P:     Andy Walls
-M:     awalls@radix.net
+M:     Hans Verkuil <hverkuil@xs4all.nl>
+M:     Andy Walls <awalls@radix.net>
 L:     ivtv-devel@ivtvdriver.org
-L:     ivtv-users@ivtvdriver.org
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 W:     http://linuxtv.org
+W:     http://www.ivtvdriver.org/index.php/Cx18
 S:     Maintained
 F:     Documentation/video4linux/cx18.txt
 F:     drivers/media/video/cx18/
 
 CXGB3 ETHERNET DRIVER (CXGB3)
-P:     Divy Le Ray
-M:     divy@chelsio.com
+M:     Divy Le Ray <divy@chelsio.com>
 L:     netdev@vger.kernel.org
 W:     http://www.chelsio.com
 S:     Supported
 F:     drivers/net/cxgb3/
 
 CXGB3 IWARP RNIC DRIVER (IW_CXGB3)
-P:     Steve Wise
-M:     swise@chelsio.com
+M:     Steve Wise <swise@chelsio.com>
 L:     general@lists.openfabrics.org
 W:     http://www.openfabrics.org
 S:     Supported
 F:     drivers/infiniband/hw/cxgb3/
 
 CYBERPRO FB DRIVER
-P:     Russell King
-M:     linux@arm.linux.org.uk
+M:     Russell King <linux@arm.linux.org.uk>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 W:     http://www.arm.linux.org.uk/
 S:     Maintained
 F:     drivers/video/cyber2000fb.*
 
 CYCLADES 2X SYNC CARD DRIVER
-P:     Arnaldo Carvalho de Melo
-M:     acme@ghostprotocols.net
+M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 W:     http://oops.ghostprotocols.net:81/blog
 S:     Maintained
 F:     drivers/net/wan/cycx*
@@ -1729,8 +1524,7 @@ S:        Orphan
 F:     drivers/net/wan/pc300*
 
 DAMA SLAVE for AX.25
-P:     Joerg Reuter
-M:     jreuter@yaina.de
+M:     Joerg Reuter <jreuter@yaina.de>
 W:     http://yaina.de/jreuter/
 W:     http://www.qsl.net/dl1bke/
 L:     linux-hams@vger.kernel.org
@@ -1744,29 +1538,23 @@ F:      net/ax25/ax25_timer.c
 F:     net/ax25/sysctl_net_ax25.c
 
 DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER
-P:     Tobias Ringstrom
-M:     tori@unhappy.mine.nu
+M:     Tobias Ringstrom <tori@unhappy.mine.nu>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     Documentation/networking/dmfe.txt
 F:     drivers/net/tulip/dmfe.c
 
 DC390/AM53C974 SCSI driver
-P:     Kurt Garloff
-M:     garloff@suse.de
+M:     Kurt Garloff <garloff@suse.de>
 W:     http://www.garloff.de/kurt/linux/dc390/
-P:     Guennadi Liakhovetski
-M:     g.liakhovetski@gmx.de
+M:     Guennadi Liakhovetski <g.liakhovetski@gmx.de>
 S:     Maintained
 F:     drivers/scsi/tmscsim.*
 
 DC395x SCSI driver
-P:     Oliver Neukum
-M:     oliver@neukum.name
-P:     Ali Akcaagac
-M:     aliakc@web.de
-P:     Jamie Lenehan
-M:     lenehan@twibble.org
+M:     Oliver Neukum <oliver@neukum.name>
+M:     Ali Akcaagac <aliakc@web.de>
+M:     Jamie Lenehan <lenehan@twibble.org>
 W:     http://twibble.org/dist/dc395x/
 L:     dc395x@twibble.org
 L:     http://lists.twibble.org/mailman/listinfo/dc395x/
@@ -1775,8 +1563,7 @@ F:        Documentation/scsi/dc395x.txt
 F:     drivers/scsi/dc395x.*
 
 DCCP PROTOCOL
-P:     Arnaldo Carvalho de Melo
-M:     acme@ghostprotocols.net
+M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 L:     dccp@vger.kernel.org
 W:     http://linux-net.osdl.org/index.php/DCCP
 S:     Maintained
@@ -1785,8 +1572,7 @@ F:        include/linux/tfrc.h
 F:     net/dccp/
 
 DECnet NETWORK LAYER
-P:     Christine Caulfield
-M:     christine.caulfield@googlemail.com
+M:     Christine Caulfield <christine.caulfield@googlemail.com>
 W:     http://linux-decnet.sourceforge.net
 L:     linux-decnet-user@lists.sourceforge.net
 S:     Maintained
@@ -1794,40 +1580,34 @@ F:      Documentation/networking/decnet.txt
 F:     net/decnet/
 
 DEFXX FDDI NETWORK DRIVER
-P:     Maciej W. Rozycki
-M:     macro@linux-mips.org
+M:     "Maciej W. Rozycki" <macro@linux-mips.org>
 S:     Maintained
 F:     drivers/net/defxx.*
 
 DELL LAPTOP DRIVER
-P:     Matthew Garrett
-M:     mjg59@srcf.ucam.org
+M:     Matthew Garrett <mjg59@srcf.ucam.org>
 S:     Maintained
 F:     drivers/platform/x86/dell-laptop.c
 
 DELL LAPTOP SMM DRIVER
-P:     Massimo Dal Zotto
-M:     dz@debian.org
+M:     Massimo Dal Zotto <dz@debian.org>
 W:     http://www.debian.org/~dz/i8k/
 S:     Maintained
 F:     drivers/char/i8k.c
 F:     include/linux/i8k.h
 
 DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas)
-P:     Doug Warzecha
-M:     Douglas_Warzecha@dell.com
+M:     Doug Warzecha <Douglas_Warzecha@dell.com>
 S:     Maintained
 F:     Documentation/dcdbas.txt
 F:     drivers/firmware/dcdbas.*
 
 DELL WMI EXTRAS DRIVER
-P:     Matthew Garrett
-M:     mjg59@srcf.ucam.org
+M:     Matthew Garrett <mjg59@srcf.ucam.org>
 S:     Maintained
 
 DEVICE NUMBER REGISTRY
-P:     Torben Mathiasen
-M:     device@lanana.org
+M:     Torben Mathiasen <device@lanana.org>
 W:     http://lanana.org/docs/device-list/index.html
 S:     Maintained
 
@@ -1842,8 +1622,7 @@ F:        include/linux/device-mapper.h
 F:     include/linux/dm-*.h
 
 DIGI INTL. EPCA DRIVER
-P:     Digi International, Inc
-M:     Eng.Linux@digi.com
+M:     "Digi International, Inc" <Eng.Linux@digi.com>
 L:     Eng.Linux@digi.com
 W:     http://www.digi.com
 S:     Orphan
@@ -1852,34 +1631,29 @@ F:      drivers/char/epca*
 F:     drivers/char/digi*
 
 DIRECTORY NOTIFICATION (DNOTIFY)
-P:     Eric Paris
-M:     eparis@parisplace.org
+M:     Eric Paris <eparis@parisplace.org>
 S:     Maintained
 F:     Documentation/filesystems/dnotify.txt
 F:     fs/notify/dnotify/
 F:     include/linux/dnotify.h
 
 DISK GEOMETRY AND PARTITION HANDLING
-P:     Andries Brouwer
-M:     aeb@cwi.nl
+M:     Andries Brouwer <aeb@cwi.nl>
 W:     http://www.win.tue.nl/~aeb/linux/Large-Disk.html
 W:     http://www.win.tue.nl/~aeb/linux/zip/zip-1.html
 W:     http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
 S:     Maintained
 
 DISKQUOTA
-P:     Jan Kara
-M:     jack@suse.cz
+M:     Jan Kara <jack@suse.cz>
 S:     Maintained
 F:     Documentation/filesystems/quota.txt
 F:     fs/quota/
 F:     include/linux/quota*.h
 
 DISTRIBUTED LOCK MANAGER (DLM)
-P:     Christine Caulfield
-M:     ccaulfie@redhat.com
-P:     David Teigland
-M:     teigland@redhat.com
+M:     Christine Caulfield <ccaulfie@redhat.com>
+M:     David Teigland <teigland@redhat.com>
 L:     cluster-devel@redhat.com
 W:     http://sources.redhat.com/cluster/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm.git
@@ -1887,52 +1661,44 @@ S:      Supported
 F:     fs/dlm/
 
 DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
-P:     Maciej Sosnowski
-M:     maciej.sosnowski@intel.com
-P:     Dan Williams
-M:     dan.j.williams@intel.com
+M:     Maciej Sosnowski <maciej.sosnowski@intel.com>
+M:     Dan Williams <dan.j.williams@intel.com>
 S:     Supported
 F:     drivers/dma/
 F:     include/linux/dma*
 
 DME1737 HARDWARE MONITOR DRIVER
-P:     Juerg Haefliger
-M:     juergh@gmail.com
+M:     Juerg Haefliger <juergh@gmail.com>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/dme1737
 F:     drivers/hwmon/dme1737.c
 
 DOCBOOK FOR DOCUMENTATION
-P:     Randy Dunlap
-M:     rdunlap@xenotime.net
+M:     Randy Dunlap <rdunlap@xenotime.net>
 S:     Maintained
 
 DOCKING STATION DRIVER
-P:     Shaohua Li
-M:     shaohua.li@intel.com
+M:     Shaohua Li <shaohua.li@intel.com>
 L:     linux-acpi@vger.kernel.org
 S:     Supported
 F:     drivers/acpi/dock.c
 
 DOCUMENTATION
-P:     Randy Dunlap
-M:     rdunlap@xenotime.net
+M:     Randy Dunlap <rdunlap@xenotime.net>
 L:     linux-doc@vger.kernel.org
 S:     Maintained
 F:     Documentation/
 
 DOUBLETALK DRIVER
-P:     James R. Van Zandt
-M:     jrv@vanzandt.mv.com
+M:     "James R. Van Zandt" <jrv@vanzandt.mv.com>
 L:     blinux-list@redhat.com
 S:     Maintained
 F:     drivers/char/dtlk.c
 F:     include/linux/dtlk.h
 
 DPT_I2O SCSI RAID DRIVER
-P:     Adaptec OEM Raid Solutions
-M:     aacraid@adaptec.com
+M:     Adaptec OEM Raid Solutions <aacraid@adaptec.com>
 L:     linux-scsi@vger.kernel.org
 W:     http://www.adaptec.com/
 S:     Maintained
@@ -1940,8 +1706,7 @@ F:        drivers/scsi/dpt*
 F:     drivers/scsi/dpt/
 
 DRIVER CORE, KOBJECTS, AND SYSFS
-P:     Greg Kroah-Hartman
-M:     gregkh@suse.de
+M:     Greg Kroah-Hartman <gregkh@suse.de>
 T:     quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
 S:     Supported
 F:     Documentation/kobject.txt
@@ -1951,52 +1716,45 @@ F:      include/linux/kobj*
 F:     lib/kobj*
 
 DRM DRIVERS
-P:     David Airlie
-M:     airlied@linux.ie
+M:     David Airlie <airlied@linux.ie>
 L:     dri-devel@lists.sourceforge.net
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git
 S:     Maintained
 F:     drivers/gpu/drm/
 
 DSCC4 DRIVER
-P:     Francois Romieu
-M:     romieu@fr.zoreil.com
+M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/wan/dscc4.c
 
 DZ DECSTATION DZ11 SERIAL DRIVER
-P:     Maciej W. Rozycki
-M:     macro@linux-mips.org
+M:     "Maciej W. Rozycki" <macro@linux-mips.org>
 S:     Maintained
 F:     drivers/serial/dz.*
 
 EATA-DMA SCSI DRIVER
-P:     Michael Neuffer
-M:     mike@i-Connect.Net
+M:     Michael Neuffer <mike@i-Connect.Net>
 L:     linux-eata@i-connect.net
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
 F:     drivers/scsi/eata*
 
 EATA ISA/EISA/PCI SCSI DRIVER
-P:     Dario Ballabio
-M:     ballabio_dario@emc.com
+M:     Dario Ballabio <ballabio_dario@emc.com>
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
 F:     drivers/scsi/eata.c
 
 EATA-PIO SCSI DRIVER
-P:     Michael Neuffer
-M:     mike@i-Connect.Net
+M:     Michael Neuffer <mike@i-Connect.Net>
 L:     linux-eata@i-connect.net
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
 F:     drivers/scsi/eata_pio.*
 
 EBTABLES
-P:     Bart De Schuymer
-M:     bart.de.schuymer@pandora.be
+M:     Bart De Schuymer <bart.de.schuymer@pandora.be>
 L:     ebtables-user@lists.sourceforge.net
 L:     ebtables-devel@lists.sourceforge.net
 W:     http://ebtables.sourceforge.net/
@@ -2005,10 +1763,8 @@ F:       include/linux/netfilter_bridge/ebt_*.h
 F:     net/bridge/netfilter/ebt*.c
 
 ECRYPT FILE SYSTEM
-P:     Tyler Hicks
-M:     tyhicks@linux.vnet.ibm.com
-P:     Dustin Kirkland
-M:     kirkland@canonical.com
+M:     Tyler Hicks <tyhicks@linux.vnet.ibm.com>
+M:     Dustin Kirkland <kirkland@canonical.com>
 L:     ecryptfs-devel@lists.launchpad.net
 W:     https://launchpad.net/ecryptfs
 S:     Supported
@@ -2016,8 +1772,7 @@ F:        Documentation/filesystems/ecryptfs.txt
 F:     fs/ecryptfs/
 
 EDAC-CORE
-P:     Doug Thompson
-M:     dougthompson@xmission.com
+M:     Doug Thompson <dougthompson@xmission.com>
 L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:     bluesmoke.sourceforge.net
 S:     Supported
@@ -2026,94 +1781,80 @@ F:      drivers/edac/edac_*
 F:     include/linux/edac.h
 
 EDAC-AMD64
-P:     Doug Thompson
-M:     dougthompson@xmission.com
-P:     Borislav Petkov
-M:     borislav.petkov@amd.com
+M:     Doug Thompson <dougthompson@xmission.com>
+M:     Borislav Petkov <borislav.petkov@amd.com>
 L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:     bluesmoke.sourceforge.net
 S:     Supported
 F:     drivers/edac/amd64_edac*
 
 EDAC-E752X
-P:     Mark Gross
-M:     mark.gross@intel.com
-P:     Doug Thompson
-M:     dougthompson@xmission.com
+M:     Mark Gross <mark.gross@intel.com>
+M:     Doug Thompson <dougthompson@xmission.com>
 L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/e752x_edac.c
 
 EDAC-E7XXX
-P:     Doug Thompson
-M:     dougthompson@xmission.com
+M:     Doug Thompson <dougthompson@xmission.com>
 L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/e7xxx_edac.c
 
 EDAC-I82443BXGX
-P:     Tim Small
-M:     tim@buttersideup.com
+M:     Tim Small <tim@buttersideup.com>
 L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i82443bxgx_edac.c
 
 EDAC-I3000
-P:     Jason Uhlenkott
-M:     juhlenko@akamai.com
+M:     Jason Uhlenkott <juhlenko@akamai.com>
 L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i3000_edac.c
 
 EDAC-I5000
-P:     Doug Thompson
-M:     dougthompson@xmission.com
+M:     Doug Thompson <dougthompson@xmission.com>
 L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i5000_edac.c
 
 EDAC-I5400
-P:     Mauro Carvalho Chehab
-M:     mchehab@redhat.com
+M:     Mauro Carvalho Chehab <mchehab@redhat.com>
 L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i5400_edac.c
 
 EDAC-I82975X
-P:     Ranganathan Desikan
-M:     rdesikan@jetzbroadband.com
-P:     Arvind R.
-M:     arvind@acarlab.com
+M:     Ranganathan Desikan <ravi@jetztechnologies.com>
+M:     "Arvind R." <arvind@jetztechnologies.com>
 L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/i82975x_edac.c
 
 EDAC-PASEMI
-P:     Egor Martovetsky
-M:     egor@pasemi.com
+M:     Egor Martovetsky <egor@pasemi.com>
 L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/pasemi_edac.c
 
 EDAC-R82600
-P:     Tim Small
-M:     tim@buttersideup.com
+M:     Tim Small <tim@buttersideup.com>
 L:     bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:     bluesmoke.sourceforge.net
 S:     Maintained
 F:     drivers/edac/r82600_edac.c
 
 EEEPC LAPTOP EXTRAS DRIVER
-P:     Corentin Chary
-M:     corentincj@iksaif.net
+M:     Corentin Chary <corentincj@iksaif.net>
 L:     acpi4asus-user@lists.sourceforge.net
 W:     http://acpi4asus.sf.net
 S:     Maintained
@@ -2125,66 +1866,54 @@ S:      Orphan
 F:     fs/efs/
 
 EHCA (IBM GX bus InfiniBand adapter) DRIVER
-P:     Hoang-Nam Nguyen
-M:     hnguyen@de.ibm.com
-P:     Christoph Raisch
-M:     raisch@de.ibm.com
+M:     Hoang-Nam Nguyen <hnguyen@de.ibm.com>
+M:     Christoph Raisch <raisch@de.ibm.com>
 L:     general@lists.openfabrics.org
 S:     Supported
 F:     drivers/infiniband/hw/ehca/
 
 EMBEDDED LINUX
-P:     Paul Gortmaker
-M:     paul.gortmaker@windriver.com
-P:     Matt Mackall
-M:     mpm@selenic.com
-P:     David Woodhouse
-M:     dwmw2@infradead.org
+M:     Paul Gortmaker <paul.gortmaker@windriver.com>
+M:     Matt Mackall <mpm@selenic.com>
+M:     David Woodhouse <dwmw2@infradead.org>
 L:     linux-embedded@vger.kernel.org
 S:     Maintained
 
 EMULEX LPFC FC SCSI DRIVER
-P:     James Smart
-M:     james.smart@emulex.com
+M:     James Smart <james.smart@emulex.com>
 L:     linux-scsi@vger.kernel.org
 W:     http://sourceforge.net/projects/lpfcxxxx
 S:     Supported
 F:     drivers/scsi/lpfc/
 
 ENE CB710 FLASH CARD READER DRIVER
-P:     Michał Mirosław
-M:     mirq-linux@rere.qmqm.pl
-L:     linux-kernel@vger.kernel.org
+M:     Michał Mirosław <mirq-linux@rere.qmqm.pl>
 S:     Maintained
 F:     drivers/misc/cb710/
 F:     drivers/mmc/host/cb710-mmc.*
 F:     include/linux/cb710.h
 
 EPSON 1355 FRAMEBUFFER DRIVER
-P:     Christopher Hoover
-M:     ch@murgatroid.com
-P:     Christopher Hoover
-M:     ch@hpl.hp.com
+M:     Christopher Hoover <ch@murgatroid.com>
+M:     Christopher Hoover <ch@hpl.hp.com>
 S:     Maintained
 F:     drivers/video/epson1355fb.c
 
 EPSON S1D13XXX FRAMEBUFFER DRIVER
-P:     Kristoffer Ericson
-M:     kristoffer.ericson@gmail.com
+M:     Kristoffer Ericson <kristoffer.ericson@gmail.com>
 S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
 F:     drivers/video/s1d13xxxfb.c
 F:     include/video/s1d13xxxfb.h
 
 ETHEREXPRESS-16 NETWORK DRIVER
-P:     Philip Blundell
-M:     philb@gnu.org
+M:     Philip Blundell <philb@gnu.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/eexpress.*
 
 ETHERNET BRIDGE
-P:     Stephen Hemminger
-M:     shemminger@linux-foundation.org
+M:     Stephen Hemminger <shemminger@linux-foundation.org>
 L:     bridge@lists.linux-foundation.org
 W:     http://www.linux-foundation.org/en/Net:Bridge
 S:     Maintained
@@ -2192,8 +1921,7 @@ F:        include/linux/netfilter_bridge/
 F:     net/bridge/
 
 ETHERTEAM 16I DRIVER
-P:     Mika Kuoppala
-M:     miku@iki.fi
+M:     Mika Kuoppala <miku@iki.fi>
 S:     Maintained
 F:     drivers/net/eth16i.c
 
@@ -2205,12 +1933,9 @@ F:       fs/ext2/
 F:     include/linux/ext2*
 
 EXT3 FILE SYSTEM
-P:     Stephen Tweedie
-M:     sct@redhat.com
-P:     Andrew Morton
-M:     akpm@linux-foundation.org
-P:     Andreas Dilger
-M:     adilger@sun.com
+M:     Stephen Tweedie <sct@redhat.com>
+M:     Andrew Morton <akpm@linux-foundation.org>
+M:     Andreas Dilger <adilger@sun.com>
 L:     linux-ext4@vger.kernel.org
 S:     Maintained
 F:     Documentation/filesystems/ext3.txt
@@ -2218,10 +1943,8 @@ F:       fs/ext3/
 F:     include/linux/ext3*
 
 EXT4 FILE SYSTEM
-P:     Theodore Ts'o
-M:     tytso@mit.edu
-P:     Andreas Dilger
-M:     adilger@sun.com
+M:     "Theodore Ts'o" <tytso@mit.edu>
+M:     Andreas Dilger <adilger@sun.com>
 L:     linux-ext4@vger.kernel.org
 W:     http://ext4.wiki.kernel.org
 S:     Maintained
@@ -2229,30 +1952,26 @@ F:      Documentation/filesystems/ext4.txt
 F:     fs/ext4/
 
 F71805F HARDWARE MONITORING DRIVER
-P:     Jean Delvare
-M:     khali@linux-fr.org
+M:     Jean Delvare <khali@linux-fr.org>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/f71805f
 F:     drivers/hwmon/f71805f.c
 
 FARSYNC SYNCHRONOUS DRIVER
-P:     Kevin Curtis
-M:     kevin.curtis@farsite.co.uk
+M:     Kevin Curtis <kevin.curtis@farsite.co.uk>
 W:     http://www.farsite.co.uk/
 S:     Supported
 F:     drivers/net/wan/farsync.*
 
 FAULT INJECTION SUPPORT
-P:     Akinobu Mita
-M:     akinobu.mita@gmail.com
+M:     Akinobu Mita <akinobu.mita@gmail.com>
 S:     Supported
 F:     Documentation/fault-injection/
 F:     lib/fault-inject.c
 
 FILE LOCKING (flock() and fcntl()/lockf())
-P:     Matthew Wilcox
-M:     matthew@wil.cx
+M:     Matthew Wilcox <matthew@wil.cx>
 L:     linux-fsdevel@vger.kernel.org
 S:     Maintained
 F:     include/linux/fcntl.h
@@ -2261,25 +1980,21 @@ F:      fs/fcntl.c
 F:     fs/locks.c
 
 FILESYSTEMS (VFS and infrastructure)
-P:     Alexander Viro
-M:     viro@zeniv.linux.org.uk
+M:     Alexander Viro <viro@zeniv.linux.org.uk>
 L:     linux-fsdevel@vger.kernel.org
 S:     Maintained
 F:     fs/*
 
 FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER
-P:     Riku Voipio
-M:     riku.vipio@iki.fi
+M:     Riku Voipio <riku.vipio@iki.fi>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     drivers/hwmon/f75375s.c
 F:     include/linux/f75375s.h
 
 FIREWIRE SUBSYSTEM
-P:     Kristian Hoegsberg
-M:     krh@redhat.com
-P:     Stefan Richter
-M:     stefanr@s5r6.in-berlin.de
+M:     Kristian Hoegsberg <krh@redhat.com>
+M:     Stefan Richter <stefanr@s5r6.in-berlin.de>
 L:     linux1394-devel@lists.sourceforge.net
 W:     http://www.linux1394.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
@@ -2294,15 +2009,13 @@ F:      drivers/base/firmware*.c
 F:     include/linux/firmware.h
 
 FPU EMULATOR
-P:     Bill Metzenthen
-M:     billm@melbpc.org.au
+M:     Bill Metzenthen <billm@melbpc.org.au>
 W:     http://floatingpoint.sourceforge.net/emulator/index.html
 S:     Maintained
 F:     arch/x86/math-emu/
 
 FRAME RELAY DLCI/FRAD (Sangoma drivers too)
-P:     Mike McLagan
-M:     mike.mclagan@linux.org
+M:     Mike McLagan <mike.mclagan@linux.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/wan/dlci.c
@@ -2317,25 +2030,21 @@ F:      drivers/video/fb*
 F:     include/linux/fb.h
 
 FREESCALE DMA DRIVER
-P:     Li Yang
-M:     leoli@freescale.com
-P:     Zhang Wei
-M:     zw@zh-kernel.org
+M:     Li Yang <leoli@freescale.com>
+M:     Zhang Wei <zw@zh-kernel.org>
 L:     linuxppc-dev@ozlabs.org
 S:     Maintained
 F:     drivers/dma/fsldma.*
 
 FREESCALE I2C CPM DRIVER
-P:     Jochen Friedrich
-M:     jochen@scram.de
+M:     Jochen Friedrich <jochen@scram.de>
 L:     linuxppc-dev@ozlabs.org
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     drivers/i2c/busses/i2c-cpm.c
 
 FREESCALE IMX / MXC FRAMEBUFFER DRIVER
-P:     Sascha Hauer
-M:     kernel@pengutronix.de
+M:     Sascha Hauer <kernel@pengutronix.de>
 L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
@@ -2343,10 +2052,8 @@ F:       arch/arm/plat-mxc/include/mach/imxfb.h
 F:     drivers/video/imxfb.c
 
 FREESCALE SOC FS_ENET DRIVER
-P:     Pantelis Antoniou
-M:     pantelis.antoniou@gmail.com
-P:     Vitaly Bordug
-M:     vbordug@ru.mvista.com
+M:     Pantelis Antoniou <pantelis.antoniou@gmail.com>
+M:     Vitaly Bordug <vbordug@ru.mvista.com>
 L:     linuxppc-dev@ozlabs.org
 L:     netdev@vger.kernel.org
 S:     Maintained
@@ -2354,39 +2061,34 @@ F:      drivers/net/fs_enet/
 F:     include/linux/fs_enet_pd.h
 
 FREESCALE QUICC ENGINE LIBRARY
-P:     Timur Tabi
-M:     timur@freescale.com
+M:     Timur Tabi <timur@freescale.com>
 L:     linuxppc-dev@ozlabs.org
 S:     Supported
 F:     arch/powerpc/sysdev/qe_lib/
 F:     arch/powerpc/include/asm/*qe.h
 
 FREESCALE HIGHSPEED USB DEVICE DRIVER
-P:     Li Yang
-M:     leoli@freescale.com
+M:     Li Yang <leoli@freescale.com>
 L:     linux-usb@vger.kernel.org
 L:     linuxppc-dev@ozlabs.org
 S:     Maintained
 F:     drivers/usb/gadget/fsl_usb2_udc.c
 
 FREESCALE QUICC ENGINE UCC ETHERNET DRIVER
-P:     Li Yang
-M:     leoli@freescale.com
+M:     Li Yang <leoli@freescale.com>
 L:     netdev@vger.kernel.org
 L:     linuxppc-dev@ozlabs.org
 S:     Maintained
 F:     drivers/net/ucc_geth*
 
 FREESCALE QUICC ENGINE UCC UART DRIVER
-P:     Timur Tabi
-M:     timur@freescale.com
+M:     Timur Tabi <timur@freescale.com>
 L:     linuxppc-dev@ozlabs.org
 S:     Supported
 F:     drivers/serial/ucc_uart.c
 
 FREESCALE SOC SOUND DRIVERS
-P:     Timur Tabi
-M:     timur@freescale.com
+M:     Timur Tabi <timur@freescale.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 L:     linuxppc-dev@ozlabs.org
 S:     Supported
@@ -2394,17 +2096,14 @@ F:      sound/soc/fsl/fsl*
 F:     sound/soc/fsl/mpc8610_hpcd.c
 
 FREEVXFS FILESYSTEM
-P:     Christoph Hellwig
-M:     hch@infradead.org
+M:     Christoph Hellwig <hch@infradead.org>
 W:     ftp://ftp.openlinux.org/pub/people/hch/vxfs
 S:     Maintained
 F:     fs/freevxfs/
 
 FREEZER
-P:     Pavel Machek
-M:     pavel@ucw.cz
-P:     Rafael J. Wysocki
-M:     rjw@sisk.pl
+M:     Pavel Machek <pavel@ucw.cz>
+M:     "Rafael J. Wysocki" <rjw@sisk.pl>
 L:     linux-pm@lists.linux-foundation.org
 S:     Supported
 F:     Documentation/power/freezing-of-tasks.txt
@@ -2412,8 +2111,7 @@ F:        include/linux/freezer.h
 F:     kernel/freezer.c
 
 FS-CACHE: LOCAL CACHING FOR NETWORK FILESYSTEMS
-P:     David Howells
-M:     dhowells@redhat.com
+M:     David Howells <dhowells@redhat.com>
 L:     linux-cachefs@redhat.com
 S:     Supported
 F:     Documentation/filesystems/caching/
@@ -2421,8 +2119,7 @@ F:        fs/fscache/
 F:     include/linux/fscache*.h
 
 FTRACE
-P:     Steven Rostedt
-M:     rostedt@goodmis.org
+M:     Steven Rostedt <rostedt@goodmis.org>
 S:     Maintained
 F:     Documentation/trace/ftrace.txt
 F:     arch/*/*/*/ftrace.h
@@ -2431,21 +2128,18 @@ F:      include/*/ftrace.h
 F:     kernel/trace/
 
 FUJITSU FR-V (FRV) PORT
-P:     David Howells
-M:     dhowells@redhat.com
+M:     David Howells <dhowells@redhat.com>
 S:     Maintained
 F:     arch/frv/
 
 FUJITSU LAPTOP EXTRAS
-P:     Jonathan Woithe
-M:     jwoithe@physics.adelaide.edu.au
+M:     Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
 L:     linux-acpi@vger.kernel.org
 S:     Maintained
 F:     drivers/platform/x86/fujitsu-laptop.c
 
 FUSE: FILESYSTEM IN USERSPACE
-P:     Miklos Szeredi
-M:     miklos@szeredi.hu
+M:     Miklos Szeredi <miklos@szeredi.hu>
 L:     fuse-devel@lists.sourceforge.net
 W:     http://fuse.sourceforge.net/
 S:     Maintained
@@ -2453,30 +2147,26 @@ F:      fs/fuse/
 F:     include/linux/fuse.h
 
 FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit)
-P:     Rik Faith
-M:     faith@cs.unc.edu
+M:     Rik Faith <faith@cs.unc.edu>
 L:     linux-scsi@vger.kernel.org
 S:     Odd Fixes (e.g., new signatures)
 F:     drivers/scsi/fdomain.*
 
 GDT SCSI DISK ARRAY CONTROLLER DRIVER
-P:     Achim Leubner
-M:     achim_leubner@adaptec.com
+M:     Achim Leubner <achim_leubner@adaptec.com>
 L:     linux-scsi@vger.kernel.org
 W:     http://www.icp-vortex.com/
 S:     Supported
 F:     drivers/scsi/gdt*
 
 GENERIC GPIO I2C DRIVER
-P:     Haavard Skinnemoen
-M:     hskinnemoen@atmel.com
+M:     Haavard Skinnemoen <hskinnemoen@atmel.com>
 S:     Supported
 F:     drivers/i2c/busses/i2c-gpio.c
 F:     include/linux/i2c-gpio.h
 
 GENERIC HDLC (WAN) DRIVERS
-P:     Krzysztof Halasa
-M:     khc@pm.waw.pl
+M:     Krzysztof Halasa <khc@pm.waw.pl>
 W:     http://www.kernel.org/pub/linux/utils/net/hdlc/
 S:     Maintained
 F:     drivers/net/wan/c101.c
@@ -2488,16 +2178,14 @@ F:      drivers/net/wan/pci200syn.c
 F:     drivers/net/wan/wanxl*
 
 GENERIC INCLUDE/ASM HEADER FILES
-P:     Arnd Bergmann
-M:     arnd@arndb.de
+M:     Arnd Bergmann <arnd@arndb.de>
 L:     linux-arch@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic.git
 S:     Maintained
 F:     include/asm-generic
 
 GFS2 FILE SYSTEM
-P:     Steven Whitehouse
-M:     swhiteho@redhat.com
+M:     Steven Whitehouse <swhiteho@redhat.com>
 L:     cluster-devel@redhat.com
 W:     http://sources.redhat.com/cluster/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes.git
@@ -2508,10 +2196,8 @@ F:       fs/gfs2/
 F:     include/linux/gfs2_ondisk.h
 
 GIGASET ISDN DRIVERS
-P:     Hansjoerg Lipp
-M:     hjlipp@web.de
-P:     Tilman Schmidt
-M:     tilman@imap.cc
+M:     Hansjoerg Lipp <hjlipp@web.de>
+M:     Tilman Schmidt <tilman@imap.cc>
 L:     gigaset307x-common@lists.sourceforge.net
 W:     http://gigaset307x.sourceforge.net/
 S:     Maintained
@@ -2520,8 +2206,7 @@ F:        drivers/isdn/gigaset/
 F:     include/linux/gigaset_dev.h
 
 HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
-P:     Frank Seidel
-M:     frank@f-seidel.de
+M:     Frank Seidel <frank@f-seidel.de>
 L:     lm-sensors@lm-sensors.org
 W:     http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
 S:     Maintained
@@ -2533,40 +2218,42 @@ S:      Odd Fixes
 F:     drivers/char/hvc_*
 
 GSPCA FINEPIX SUBDRIVER
-P:     Frank Zago
-M:     frank@zago.net
+M:     Frank Zago <frank@zago.net>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 S:     Maintained
 F:     drivers/media/video/gspca/finepix.c
 
 GSPCA M5602 SUBDRIVER
-P:     Erik Andren
-M:     erik.andren@gmail.com
+M:     Erik Andren <erik.andren@gmail.com>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 S:     Maintained
 F:     drivers/media/video/gspca/m5602/
 
 GSPCA PAC207 SONIXB SUBDRIVER
-P:     Hans de Goede
-M:     hdegoede@redhat.com
+M:     Hans de Goede <hdegoede@redhat.com>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 S:     Maintained
 F:     drivers/media/video/gspca/pac207.c
 
+GSPCA SN9C20X SUBDRIVER
+M:     Brian Johnson <brijohn@gmail.com>
+L:     linux-media@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
+S:     Maintained
+F:     drivers/media/video/gspca/sn9c20x.c
+
 GSPCA T613 SUBDRIVER
-P:     Leandro Costantino
-M:     lcostantino@gmail.com
+M:     Leandro Costantino <lcostantino@gmail.com>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 S:     Maintained
 F:     drivers/media/video/gspca/t613.c
 
 GSPCA USB WEBCAM DRIVER
-P:     Jean-Francois Moine
-M:     moinejf@free.fr
+M:     Jean-Francois Moine <moinejf@free.fr>
 W:     http://moinejf.free.fr
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
@@ -2586,31 +2273,27 @@ F:      drivers/char/hw_random/
 F:     include/linux/hw_random.h
 
 HARMONY SOUND DRIVER
-P:     Kyle McMartin
-M:     kyle@mcmartin.ca
+M:     Kyle McMartin <kyle@mcmartin.ca>
 L:     linux-parisc@vger.kernel.org
 S:     Maintained
 F:     sound/parisc/harmony.*
 
 HAYES ESP SERIAL DRIVER
-P:     Andrew J. Robinson
-M:     arobinso@nyx.net
+M:     "Andrew J. Robinson" <arobinso@nyx.net>
 W:     http://www.nyx.net/~arobinso
 S:     Maintained
 F:     Documentation/serial/hayes-esp.txt
 F:     drivers/char/esp.c
 
 HEWLETT-PACKARD SMART2 RAID DRIVER
-P:     Chirag Kantharia
-M:     chirag.kantharia@hp.com
+M:     Chirag Kantharia <chirag.kantharia@hp.com>
 L:     iss_storagedev@hp.com
 S:     Maintained
 F:     Documentation/blockdev/cpqarray.txt
 F:     drivers/block/cpqarray.*
 
 HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss)
-P:     Mike Miller
-M:     mike.miller@hp.com
+M:     Mike Miller <mike.miller@hp.com>
 L:     iss_storagedev@hp.com
 S:     Supported
 F:     Documentation/blockdev/cciss.txt
@@ -2618,25 +2301,21 @@ F:      drivers/block/cciss*
 F:     include/linux/cciss_ioctl.h
 
 HFS FILESYSTEM
-P:     Roman Zippel
-M:     zippel@linux-m68k.org
+M:     Roman Zippel <zippel@linux-m68k.org>
 S:     Maintained
 F:     Documentation/filesystems/hfs.txt
 F:     fs/hfs/
 
 HGA FRAMEBUFFER DRIVER
-P:     Ferenc Bakonyi
-M:     fero@drama.obuda.kando.hu
+M:     Ferenc Bakonyi <fero@drama.obuda.kando.hu>
 L:     linux-nvidia@lists.surfsouth.com
 W:     http://drama.obuda.kando.hu/~fero/cgi-bin/hgafb.shtml
 S:     Maintained
 F:     drivers/video/hgafb.c
 
 HIBERNATION (aka Software Suspend, aka swsusp)
-P:     Pavel Machek
-M:     pavel@ucw.cz
-P:     Rafael J. Wysocki
-M:     rjw@sisk.pl
+M:     Pavel Machek <pavel@ucw.cz>
+M:     "Rafael J. Wysocki" <rjw@sisk.pl>
 L:     linux-pm@lists.linux-foundation.org
 S:     Supported
 F:     arch/x86/power/
@@ -2648,8 +2327,7 @@ F:        include/linux/pm.h
 F:     arch/*/include/asm/suspend*.h
 
 HID CORE LAYER
-P:     Jiri Kosina
-M:     jkosina@suse.cz
+M:     Jiri Kosina <jkosina@suse.cz>
 L:     linux-input@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git
 S:     Maintained
@@ -2657,16 +2335,14 @@ F:      drivers/hid/
 F:     include/linux/hid*
 
 HIGH-RESOLUTION TIMERS, CLOCKEVENTS, DYNTICKS
-P:     Thomas Gleixner
-M:     tglx@linutronix.de
+M:     Thomas Gleixner <tglx@linutronix.de>
 S:     Maintained
 F:     Documentation/timers/
 F:     kernel/hrtimer.c
 F:     include/linux/hrtimer.h
 
 HIGH-SPEED SCC DRIVER FOR AX.25
-P:     Klaus Kudielka
-M:     klaus.kudielka@ieee.org
+M:     Klaus Kudielka <klaus.kudielka@ieee.org>
 L:     linux-hams@vger.kernel.org
 W:     http://www.nt.tuwien.ac.at/~kkudielk/Linux/
 S:     Maintained
@@ -2674,16 +2350,14 @@ F:      drivers/net/hamradio/dmascc.c
 F:     drivers/net/hamradio/scc.c
 
 HIGHPOINT ROCKETRAID 3xxx RAID DRIVER
-P:     HighPoint Linux Team
-M:     linux@highpoint-tech.com
+M:     HighPoint Linux Team <linux@highpoint-tech.com>
 W:     http://www.highpoint-tech.com
 S:     Supported
 F:     Documentation/scsi/hptiop.txt
 F:     drivers/scsi/hptiop.c
 
 HIPPI
-P:     Jes Sorensen
-M:     jes@trained-monkey.org
+M:     Jes Sorensen <jes@trained-monkey.org>
 L:     linux-hippi@sunsite.dk
 S:     Maintained
 F:     include/linux/hippidevice.h
@@ -2691,8 +2365,7 @@ F:        include/linux/if_hippi.h
 F:     net/802/hippi.c
 
 HOST AP DRIVER
-P:     Jouni Malinen
-M:     j@w1.fi
+M:     Jouni Malinen <j@w1.fi>
 L:     hostap@shmoo.com (subscribers-only)
 L:     linux-wireless@vger.kernel.org
 W:     http://hostap.epitest.fi/
@@ -2700,82 +2373,69 @@ S:      Maintained
 F:     drivers/net/wireless/hostap/
 
 HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER
-P:     Carlos Corbacho
-M:     carlos@strangeworlds.co.uk
+M:     Carlos Corbacho <carlos@strangeworlds.co.uk>
 S:     Odd Fixes
 F:     drivers/platform/x86/tc1100-wmi.c
 
 HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
-P:     Jaroslav Kysela
-M:     perex@perex.cz
+M:     Jaroslav Kysela <perex@perex.cz>
 S:     Maintained
 F:     drivers/net/hp100.*
 
 HPET:  High Precision Event Timers driver
-P:     Clemens Ladisch
-M:     clemens@ladisch.de
+M:     Clemens Ladisch <clemens@ladisch.de>
 S:     Maintained
 F:     Documentation/timers/hpet.txt
 F:     drivers/char/hpet.c
 F:     include/linux/hpet.h
 
 HPET:  i386
-P:     Venkatesh Pallipadi (Venki)
-M:     venkatesh.pallipadi@intel.com
+M:     "Venkatesh Pallipadi (Venki)" <venkatesh.pallipadi@intel.com>
 S:     Maintained
 F:     arch/x86/kernel/hpet.c
 F:     arch/x86/include/asm/hpet.h
 
 HPET:  x86_64
-P:     Vojtech Pavlik
-M:     vojtech@suse.cz
+M:     Vojtech Pavlik <vojtech@suse.cz>
 S:     Maintained
 
 HPET:  ACPI
-P:     Bob Picco
-M:     bob.picco@hp.com
+M:     Bob Picco <bob.picco@hp.com>
 S:     Maintained
 F:     drivers/char/hpet.c
 
 HPFS FILESYSTEM
-P:     Mikulas Patocka
-M:     mikulas@artax.karlin.mff.cuni.cz
+M:     Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz>
 W:     http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
 S:     Maintained
 F:     fs/hpfs/
 
 HSO 3G MODEM DRIVER
-P:     Jan Dumon
-M:     j.dumon@option.com
+M:     Jan Dumon <j.dumon@option.com>
 W:     http://www.pharscape.org
 S:     Maintained
 F:     drivers/net/usb/hso.c
 
 HTCPEN TOUCHSCREEN DRIVER
-P:     Pau Oliva Fora
-M:     pof@eslack.org
+M:     Pau Oliva Fora <pof@eslack.org>
 L:     linux-input@vger.kernel.org
 S:     Maintained
 F:     drivers/input/touchscreen/htcpen.c
 
 HUGETLB FILESYSTEM
-P:     William Irwin
-M:     wli@holomorphy.com
+M:     William Irwin <wli@holomorphy.com>
 S:     Maintained
 F:     fs/hugetlbfs/
 
 I2C/SMBUS STUB DRIVER
-P:     Mark M. Hoffman
-M:     mhoffman@lightlink.com
+M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     drivers/i2c/busses/i2c-stub.c
 
 I2C SUBSYSTEM
-P:     Jean Delvare (PC drivers, core)
-M:     khali@linux-fr.org
-P:     Ben Dooks (embedded platforms)
-M:     ben-linux@fluff.org
+M:     "Jean Delvare (PC drivers, core)" <khali@linux-fr.org>
+M:     "Ben Dooks (embedded platforms)" <ben-linux@fluff.org>
 L:     linux-i2c@vger.kernel.org
 W:     http://i2c.wiki.kernel.org/
 T:     quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/
@@ -2787,28 +2447,25 @@ F:      include/linux/i2c-dev.h
 F:     include/linux/i2c-id.h
 
 I2C-TINY-USB DRIVER
-P:     Till Harbaum
-M:     till@harbaum.org
+M:     Till Harbaum <till@harbaum.org>
 L:     linux-i2c@vger.kernel.org
 W:     http://www.harbaum.org/till/i2c_tiny_usb
 S:     Maintained
 F:     drivers/i2c/busses/i2c-tiny-usb.c
 
 i386 BOOT CODE
-P:     H. Peter Anvin
-M:     hpa@zytor.com
+M:     "H. Peter Anvin" <hpa@zytor.com>
 S:     Maintained
 F:     arch/x86/boot/
 
 i386 SETUP CODE / CPU ERRATA WORKAROUNDS
-P:     H. Peter Anvin
-M:     hpa@zytor.com
+M:     "H. Peter Anvin" <hpa@zytor.com>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/hpa/linux-2.6-x86setup.git
 S:     Maintained
 
 IA64 (Itanium) PLATFORM
-P:     Tony Luck
-M:     tony.luck@intel.com
+M:     Tony Luck <tony.luck@intel.com>
+M:     Fenghua Yu <fenghua.yu@intel.com>
 L:     linux-ia64@vger.kernel.org
 W:     http://www.ia64-linux.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6.git
@@ -2816,29 +2473,25 @@ S:      Maintained
 F:     arch/ia64/
 
 IBM MCA SCSI SUBSYSTEM DRIVER
-P:     Michael Lang
-M:     langa2@kph.uni-mainz.de
+M:     Michael Lang <langa2@kph.uni-mainz.de>
 W:     http://www.uni-mainz.de/~langm000/linux.html
 S:     Maintained
 F:     drivers/scsi/ibmmca.c
 
 IBM Power Linux RAID adapter
-P:     Brian King
-M:     brking@us.ibm.com
+M:     Brian King <brking@us.ibm.com>
 S:     Supported
 F:     drivers/scsi/ipr.*
 
 IBM ServeRAID RAID DRIVER
 P:     Jack Hammer
-P:     Dave Jeffery
-M:     ipslinux@adaptec.com
+M:     Dave Jeffery <ipslinux@adaptec.com>
 W:     http://www.developer.ibm.com/welcome/netfinity/serveraid.html
 S:     Supported
 F:     drivers/scsi/ips.*
 
 IDE SUBSYSTEM
-P:     David S. Miller
-M:     davem@davemloft.net
+M:     "David S. Miller" <davem@davemloft.net>
 L:     linux-ide@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide-2.6.git
 S:     Maintained
@@ -2847,25 +2500,21 @@ F:      drivers/ide/
 F:     include/linux/ide.h
 
 IDE/ATAPI DRIVERS
-P:     Borislav Petkov
-M:     petkovbb@gmail.com
+M:     Borislav Petkov <petkovbb@gmail.com>
 L:     linux-ide@vger.kernel.org
 S:     Maintained
 F:     Documentation/cdrom/ide-cd
 F:     drivers/ide/ide-cd*
 
 IDLE-I7300
-P:     Andy Henroid
-M:     andrew.d.henroid@intel.com
+M:     Andy Henroid <andrew.d.henroid@intel.com>
 L:     linux-pm@lists.linux-foundation.org
 S:     Supported
 F:     drivers/idle/i7300_idle.c
 
 IEEE 1394 SUBSYSTEM
-P:     Ben Collins
-M:     ben.collins@ubuntu.com
-P:     Stefan Richter
-M:     stefanr@s5r6.in-berlin.de
+M:     Ben Collins <ben.collins@ubuntu.com>
+M:     Stefan Richter <stefanr@s5r6.in-berlin.de>
 L:     linux1394-devel@lists.sourceforge.net
 W:     http://www.linux1394.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
@@ -2873,20 +2522,16 @@ S:      Maintained
 F:     drivers/ieee1394/
 
 IEEE 1394 RAW I/O DRIVER
-P:     Dan Dennedy
-M:     dan@dennedy.org
-P:     Stefan Richter
-M:     stefanr@s5r6.in-berlin.de
+M:     Dan Dennedy <dan@dennedy.org>
+M:     Stefan Richter <stefanr@s5r6.in-berlin.de>
 L:     linux1394-devel@lists.sourceforge.net
 S:     Maintained
 F:     drivers/ieee1394/raw1394*
 
 IEEE 802.15.4 SUBSYSTEM
-P:     Dmitry Eremin-Solenikov
-M:     dbaryshkov@gmail.com
-P:     Sergey Lapin
-M:     slapin@ossfans.org
-L:     linux-zigbee-devel@lists.sourceforge.net
+M:     Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+M:     Sergey Lapin <slapin@ossfans.org>
+L:     linux-zigbee-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:     http://apps.sourceforge.net/trac/linux-zigbee
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lowpan/lowpan.git
 S:     Maintained
@@ -2894,8 +2539,7 @@ F:        net/ieee802154/
 F:     drivers/ieee802154/
 
 INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
-P:     Mimi Zohar
-M:     zohar@us.ibm.com
+M:     Mimi Zohar <zohar@us.ibm.com>
 S:     Supported
 F:     security/integrity/ima/
 
@@ -2905,12 +2549,9 @@ S:       Orphan
 F:     drivers/video/imsttfb.c
 
 INFINIBAND SUBSYSTEM
-P:     Roland Dreier
-M:     rolandd@cisco.com
-P:     Sean Hefty
-M:     sean.hefty@intel.com
-P:     Hal Rosenstock
-M:     hal.rosenstock@gmail.com
+M:     Roland Dreier <rolandd@cisco.com>
+M:     Sean Hefty <sean.hefty@intel.com>
+M:     Hal Rosenstock <hal.rosenstock@gmail.com>
 L:     general@lists.openfabrics.org (moderated for non-subscribers)
 W:     http://www.openib.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git
@@ -2920,65 +2561,55 @@ F:      drivers/infiniband/
 F:     include/linux/if_infiniband.h
 
 INOTIFY
-P:     John McCutchan
-M:     john@johnmccutchan.com
-P:     Robert Love
-M:     rlove@rlove.org
-P:     Eric Paris
-M:     eparis@parisplace.org
+M:     John McCutchan <john@johnmccutchan.com>
+M:     Robert Love <rlove@rlove.org>
+M:     Eric Paris <eparis@parisplace.org>
 S:     Maintained
 F:     Documentation/filesystems/inotify.txt
 F:     fs/notify/inotify/
 F:     include/linux/inotify.h
 
 INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS
-P:     Dmitry Torokhov
-M:     dmitry.torokhov@gmail.com
-M:     dtor@mail.ru
+M:     Dmitry Torokhov <dmitry.torokhov@gmail.com>
+M:     Dmitry Torokhov <dtor@mail.ru>
 L:     linux-input@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git
 S:     Maintained
 F:     drivers/input/
 
 INTEL FRAMEBUFFER DRIVER (excluding 810 and 815)
-P:     Sylvain Meyer
-M:     sylvain.meyer@worldonline.fr
+M:     Sylvain Meyer <sylvain.meyer@worldonline.fr>
 L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
 S:     Maintained
 F:     Documentation/fb/intelfb.txt
 F:     drivers/video/intelfb/
 
 INTEL 810/815 FRAMEBUFFER DRIVER
-P:     Antonino Daplas
-M:     adaplas@gmail.com
+M:     Antonino Daplas <adaplas@gmail.com>
 L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/video/i810/
 
 INTEL MENLOW THERMAL DRIVER
-P:     Sujith Thomas
-M:     sujith.thomas@intel.com
+M:     Sujith Thomas <sujith.thomas@intel.com>
 L:     linux-acpi@vger.kernel.org
 W:     http://www.lesswatts.org/projects/acpi/
 S:     Supported
 F:     drivers/platform/x86/intel_menlow.c
 
 INTEL IA32 MICROCODE UPDATE SUPPORT
-P:     Tigran Aivazian
-M:     tigran@aivazian.fsnet.co.uk
+M:     Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
 S:     Maintained
 F:     arch/x86/kernel/microcode_core.c
 F:     arch/x86/kernel/microcode_intel.c
 
 INTEL I/OAT DMA DRIVER
-P:     Maciej Sosnowski
-M:     maciej.sosnowski@intel.com
+M:     Maciej Sosnowski <maciej.sosnowski@intel.com>
 S:     Supported
 F:     drivers/dma/ioat*
 
 INTEL IOMMU (VT-d)
-P:     David Woodhouse
-M:     dwmw2@infradead.org
+M:     David Woodhouse <dwmw2@infradead.org>
 L:     iommu@lists.linux-foundation.org
 T:     git git://git.infradead.org/iommu-2.6.git
 S:     Supported
@@ -2986,14 +2617,12 @@ F:      drivers/pci/intel-iommu.c
 F:     include/linux/intel-iommu.h
 
 INTEL IOP-ADMA DMA DRIVER
-P:     Dan Williams
-M:     dan.j.williams@intel.com
+M:     Dan Williams <dan.j.williams@intel.com>
 S:     Supported
 F:     drivers/dma/iop-adma.c
 
 INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT
-P:     Krzysztof Halasa
-M:     khc@pm.waw.pl
+M:     Krzysztof Halasa <khc@pm.waw.pl>
 S:     Maintained
 F:     arch/arm/mach-ixp4xx/include/mach/qmgr.h
 F:     arch/arm/mach-ixp4xx/include/mach/npe.h
@@ -3003,29 +2632,22 @@ F:      drivers/net/arm/ixp4xx_eth.c
 F:     drivers/net/wan/ixp4xx_hss.c
 
 INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT
-P:     Deepak Saxena
-M:     dsaxena@plexity.net
+M:     Deepak Saxena <dsaxena@plexity.net>
 S:     Maintained
 F:     drivers/char/hw_random/ixp4xx-rng.c
 
 INTEL IXP2000 ETHERNET DRIVER
-P:     Lennert Buytenhek
-M:     kernel@wantstofly.org
+M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ixp2000/
 
 INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/ixgb/ixgbe)
-P:     Jeff Kirsher
-M:     jeffrey.t.kirsher@intel.com
-P:     Jesse Brandeburg
-M:     jesse.brandeburg@intel.com
-P:     Bruce Allan
-M:     bruce.w.allan@intel.com
-P:     PJ Waskiewicz
-M:     peter.p.waskiewicz.jr@intel.com
-P:     John Ronciak
-M:     john.ronciak@intel.com
+M:     Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+M:     Jesse Brandeburg <jesse.brandeburg@intel.com>
+M:     Bruce Allan <bruce.w.allan@intel.com>
+M:     PJ Waskiewicz <peter.p.waskiewicz.jr@intel.com>
+M:     John Ronciak <john.ronciak@intel.com>
 L:     e1000-devel@lists.sourceforge.net
 W:     http://e1000.sourceforge.net/
 S:     Supported
@@ -3037,12 +2659,9 @@ F:       drivers/net/ixgb/
 F:     drivers/net/ixgbe/
 
 INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
-P:     Zhu Yi
-M:     yi.zhu@intel.com
-P:     James Ketrenos
-M:     jketreno@linux.intel.com
-P:     Reinette Chatre
-M:     reinette.chatre@intel.com
+M:     Zhu Yi <yi.zhu@intel.com>
+M:     James Ketrenos <jketreno@linux.intel.com>
+M:     Reinette Chatre <reinette.chatre@intel.com>
 L:     linux-wireless@vger.kernel.org
 L:     ipw2100-devel@lists.sourceforge.net
 W:     http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
@@ -3052,12 +2671,9 @@ F:       Documentation/networking/README.ipw2100
 F:     drivers/net/wireless/ipw2x00/ipw2100.*
 
 INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
-P:     Zhu Yi
-M:     yi.zhu@intel.com
-P:     James Ketrenos
-M:     jketreno@linux.intel.com
-P:     Reinette Chatre
-M:     reinette.chatre@intel.com
+M:     Zhu Yi <yi.zhu@intel.com>
+M:     James Ketrenos <jketreno@linux.intel.com>
+M:     Reinette Chatre <reinette.chatre@intel.com>
 L:     linux-wireless@vger.kernel.org
 L:     ipw2100-devel@lists.sourceforge.net
 W:     http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
@@ -3067,8 +2683,7 @@ F:        Documentation/networking/README.ipw2200
 F:     drivers/net/wireless/ipw2x00/ipw2200.*
 
 INTEL WIRELESS WIMAX CONNECTION 2400
-P:     Inaky Perez-Gonzalez
-M:     inaky.perez-gonzalez@intel.com
+M:     Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
 M:     linux-wimax@intel.com
 L:     wimax@linuxwimax.org
 S:     Supported
@@ -3078,10 +2693,8 @@ F:       drivers/net/wimax/i2400m/
 F:     include/linux/wimax/i2400m.h
 
 INTEL WIRELESS WIFI LINK (iwlwifi)
-P:     Zhu Yi
-M:     yi.zhu@intel.com
-P:     Reinette Chatre
-M:     reinette.chatre@intel.com
+M:     Zhu Yi <yi.zhu@intel.com>
+M:     Reinette Chatre <reinette.chatre@intel.com>
 L:     linux-wireless@vger.kernel.org
 L:     ipw3945-devel@lists.sourceforge.net
 W:     http://intellinuxwireless.org
@@ -3090,47 +2703,39 @@ S:      Supported
 F:     drivers/net/wireless/iwlwifi/
 
 IOC3 ETHERNET DRIVER
-P:     Ralf Baechle
-M:     ralf@linux-mips.org
+M:     Ralf Baechle <ralf@linux-mips.org>
 L:     linux-mips@linux-mips.org
 S:     Maintained
 F:     drivers/net/ioc3-eth.c
 
 IOC3 SERIAL DRIVER
-P:     Pat Gefre
-M:     pfg@sgi.com
+M:     Pat Gefre <pfg@sgi.com>
 L:     linux-mips@linux-mips.org
 S:     Maintained
 F:     drivers/serial/ioc3_serial.c
 
 IP MASQUERADING
-P:     Juanjo Ciarlante
-M:     jjciarla@raiz.uncu.edu.ar
+M:     Juanjo Ciarlante <jjciarla@raiz.uncu.edu.ar>
 S:     Maintained
 F:     net/ipv4/netfilter/ipt_MASQUERADE.c
 
 IP1000A 10/100/1000 GIGABIT ETHERNET DRIVER
-P:     Francois Romieu
-M:     romieu@fr.zoreil.com
-P:     Sorbica Shieh
-M:     sorbica@icplus.com.tw
-P:     Jesse Huang
-M:     jesse@icplus.com.tw
+M:     Francois Romieu <romieu@fr.zoreil.com>
+M:     Sorbica Shieh <sorbica@icplus.com.tw>
+M:     Jesse Huang <jesse@icplus.com.tw>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ipg.c
 
 IPATH DRIVER
-P:     Ralph Campbell
-M:     infinipath@qlogic.com
+M:     Ralph Campbell <infinipath@qlogic.com>
 L:     general@lists.openfabrics.org
 T:     git git://git.qlogic.com/ipath-linux-2.6
 S:     Supported
 F:     drivers/infiniband/hw/ipath/
 
 IPMI SUBSYSTEM
-P:     Corey Minyard
-M:     minyard@acm.org
+M:     Corey Minyard <minyard@acm.org>
 L:     openipmi-developer@lists.sourceforge.net
 W:     http://openipmi.sourceforge.net/
 S:     Supported
@@ -3139,20 +2744,16 @@ F:      drivers/char/ipmi/
 F:     include/linux/ipmi*
 
 IPS SCSI RAID DRIVER
-P:     Adaptec OEM Raid Solutions
-M:     aacraid@adaptec.com
+M:     Adaptec OEM Raid Solutions <aacraid@adaptec.com>
 L:     linux-scsi@vger.kernel.org
 W:     http://www.adaptec.com/
 S:     Maintained
 F:     drivers/scsi/ips*
 
 IPVS
-P:     Wensong Zhang
-M:     wensong@linux-vs.org
-P:     Simon Horman
-M:     horms@verge.net.au
-P:     Julian Anastasov
-M:     ja@ssi.bg
+M:     Wensong Zhang <wensong@linux-vs.org>
+M:     Simon Horman <horms@verge.net.au>
+M:     Julian Anastasov <ja@ssi.bg>
 L:     netdev@vger.kernel.org
 L:     lvs-devel@vger.kernel.org
 S:     Maintained
@@ -3160,17 +2761,14 @@ F:      Documentation/networking/ipvs-sysctl.txt
 F:     net/netfilter/ipvs/
 
 IPWIRELESS DRIVER
-P:     Jiri Kosina
-M:     jkosina@suse.cz
-P:     David Sterba
-M:     dsterba@suse.cz
+M:     Jiri Kosina <jkosina@suse.cz>
+M:     David Sterba <dsterba@suse.cz>
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/ipwireless_cs.git
 F:     drivers/char/pcmcia/ipwireless/
 
 IPX NETWORK LAYER
-P:     Arnaldo Carvalho de Melo
-M:     acme@ghostprotocols.net
+M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     include/linux/ipx.h
@@ -3178,8 +2776,7 @@ F:        include/net/ipx.h
 F:     net/ipx/
 
 IRDA SUBSYSTEM
-P:     Samuel Ortiz
-M:     samuel@sortiz.org
+M:     Samuel Ortiz <samuel@sortiz.org>
 L:     irda-users@lists.sourceforge.net (subscribers-only)
 W:     http://irda.sourceforge.net/
 S:     Maintained
@@ -3190,16 +2787,14 @@ F:      include/net/irda/
 F:     net/irda/
 
 ISAPNP
-P:     Jaroslav Kysela
-M:     perex@perex.cz
+M:     Jaroslav Kysela <perex@perex.cz>
 S:     Maintained
 F:     Documentation/isapnp.txt
 F:     drivers/pnp/isapnp/
 F:     include/linux/isapnp.h
 
 ISCSI
-P:     Mike Christie
-M:     michaelc@cs.wisc.edu
+M:     Mike Christie <michaelc@cs.wisc.edu>
 L:     open-iscsi@googlegroups.com
 W:     www.open-iscsi.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mnc/linux-2.6-iscsi.git
@@ -3208,8 +2803,7 @@ F:        drivers/scsi/*iscsi*
 F:     include/scsi/*iscsi*
 
 ISDN SUBSYSTEM
-P:     Karsten Keil
-M:     isdn@linux-pingi.de
+M:     Karsten Keil <isdn@linux-pingi.de>
 L:     isdn4linux@listserv.isdn4linux.de (subscribers-only)
 W:     http://www.isdn4linux.de
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kkeil/isdn-2.6.git
@@ -3220,18 +2814,15 @@ F:      include/linux/isdn.h
 F:     include/linux/isdn/
 
 ISDN SUBSYSTEM (Eicon active card driver)
-P:     Armin Schindler
-M:     mac@melware.de
+M:     Armin Schindler <mac@melware.de>
 L:     isdn4linux@listserv.isdn4linux.de (subscribers-only)
 W:     http://www.melware.de
 S:     Maintained
 F:     drivers/isdn/hardware/eicon/
 
 IVTV VIDEO4LINUX DRIVER
-P:     Hans Verkuil
-M:     hverkuil@xs4all.nl
+M:     Hans Verkuil <hverkuil@xs4all.nl>
 L:     ivtv-devel@ivtvdriver.org
-L:     ivtv-users@ivtvdriver.org
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 W:     http://www.ivtvdriver.org
@@ -3241,25 +2832,22 @@ F:      drivers/media/video/ivtv/
 F:     include/linux/ivtv*
 
 JFS FILESYSTEM
-P:     Dave Kleikamp
-M:     shaggy@austin.ibm.com
+M:     Dave Kleikamp <shaggy@linux.vnet.ibm.com>
 L:     jfs-discussion@lists.sourceforge.net
 W:     http://jfs.sourceforge.net/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git
-S:     Supported
+S:     Maintained
 F:     Documentation/filesystems/jfs.txt
 F:     fs/jfs/
 
 JME NETWORK DRIVER
-P:     Guo-Fu Tseng
-M:     cooldavid@cooldavid.org
+M:     Guo-Fu Tseng <cooldavid@cooldavid.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/jme.*
 
 JOURNALLING FLASH FILE SYSTEM V2 (JFFS2)
-P:     David Woodhouse
-M:     dwmw2@infradead.org
+M:     David Woodhouse <dwmw2@infradead.org>
 L:     linux-mtd@lists.infradead.org
 W:     http://www.linux-mtd.infradead.org/doc/jffs2.html
 S:     Maintained
@@ -3267,10 +2855,8 @@ F:       fs/jffs2/
 F:     include/linux/jffs2.h
 
 JOURNALLING LAYER FOR BLOCK DEVICES (JBD)
-P:     Stephen Tweedie
-M:     sct@redhat.com
-P:     Andrew Morton
-M:     akpm@linux-foundation.org
+M:     Stephen Tweedie <sct@redhat.com>
+M:     Andrew Morton <akpm@linux-foundation.org>
 L:     linux-ext4@vger.kernel.org
 S:     Maintained
 F:     fs/jbd*/
@@ -3278,48 +2864,41 @@ F:      include/linux/ext*jbd*.h
 F:     include/linux/jbd*.h
 
 K8TEMP HARDWARE MONITORING DRIVER
-P:     Rudolf Marek
-M:     r.marek@assembler.cz
+M:     Rudolf Marek <r.marek@assembler.cz>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/k8temp
 F:     drivers/hwmon/k8temp.c
 
 KCONFIG
-P:     Roman Zippel
-M:     zippel@linux-m68k.org
+M:     Roman Zippel <zippel@linux-m68k.org>
 L:     linux-kbuild@vger.kernel.org
 S:     Maintained
 F:     Documentation/kbuild/kconfig-language.txt
 F:     scripts/kconfig/
 
 KDUMP
-P:     Vivek Goyal
-M:     vgoyal@redhat.com
-P:     Haren Myneni
-M:     hbabu@us.ibm.com
+M:     Vivek Goyal <vgoyal@redhat.com>
+M:     Haren Myneni <hbabu@us.ibm.com>
 L:     kexec@lists.infradead.org
 W:     http://lse.sourceforge.net/kdump/
 S:     Maintained
 F:     Documentation/kdump/
 
 KERNEL AUTOMOUNTER (AUTOFS)
-P:     H. Peter Anvin
-M:     hpa@zytor.com
+M:     "H. Peter Anvin" <hpa@zytor.com>
 L:     autofs@linux.kernel.org
 S:     Odd Fixes
 F:     fs/autofs/
 
 KERNEL AUTOMOUNTER v4 (AUTOFS4)
-P:     Ian Kent
-M:     raven@themaw.net
+M:     Ian Kent <raven@themaw.net>
 L:     autofs@linux.kernel.org
 S:     Maintained
 F:     fs/autofs4/
 
 KERNEL BUILD
-P:     Sam Ravnborg
-M:     sam@ravnborg.org
+M:     Sam Ravnborg <sam@ravnborg.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-next.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-fixes.git
 L:     linux-kbuild@vger.kernel.org
@@ -3329,16 +2908,13 @@ F:      Makefile
 F:     scripts/Makefile.*
 
 KERNEL JANITORS
-P:     Several
 L:     kernel-janitors@vger.kernel.org
 W:     http://www.kerneljanitors.org/
-S:     Maintained
+S:     Odd fixes
 
 KERNEL NFSD, SUNRPC, AND LOCKD SERVERS
-P:     J. Bruce Fields
-M:     bfields@fieldses.org
-P:     Neil Brown
-M:     neilb@suse.de
+M:     "J. Bruce Fields" <bfields@fieldses.org>
+M:     Neil Brown <neilb@suse.de>
 L:     linux-nfs@vger.kernel.org
 W:     http://nfs.sourceforge.net/
 S:     Supported
@@ -3351,8 +2927,7 @@ F:        include/linux/lockd/
 F:     include/linux/sunrpc/
 
 KERNEL VIRTUAL MACHINE (KVM)
-P:     Avi Kivity
-M:     avi@redhat.com
+M:     Avi Kivity <avi@redhat.com>
 L:     kvm@vger.kernel.org
 W:     http://kvm.qumranet.com
 S:     Supported
@@ -3363,8 +2938,7 @@ F:        include/linux/kvm*
 F:     virt/kvm/
 
 KERNEL VIRTUAL MACHINE (KVM) FOR AMD-V
-P:     Joerg Roedel
-M:     joerg.roedel@amd.com
+M:     Joerg Roedel <joerg.roedel@amd.com>
 L:     kvm@vger.kernel.org
 W:     http://kvm.qumranet.com
 S:     Supported
@@ -3373,8 +2947,7 @@ F:        arch/x86/kvm/kvm_svm.h
 F:     arch/x86/kvm/svm.c
 
 KERNEL VIRTUAL MACHINE (KVM) FOR POWERPC
-P:     Hollis Blanchard
-M:     hollisb@us.ibm.com
+M:     Hollis Blanchard <hollisb@us.ibm.com>
 L:     kvm-ppc@vger.kernel.org
 W:     http://kvm.qumranet.com
 S:     Supported
@@ -3382,8 +2955,7 @@ F:        arch/powerpc/include/asm/kvm*
 F:     arch/powerpc/kvm/
 
 KERNEL VIRTUAL MACHINE For Itanium (KVM/IA64)
-P:     Xiantao Zhang
-M:     xiantao.zhang@intel.com
+M:     Xiantao Zhang <xiantao.zhang@intel.com>
 L:     kvm-ia64@vger.kernel.org
 W:     http://kvm.qumranet.com
 S:     Supported
@@ -3392,10 +2964,8 @@ F:       arch/ia64/include/asm/kvm*
 F:     arch/ia64/kvm/
 
 KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
-P:     Carsten Otte
-M:     cotte@de.ibm.com
-P:     Christian Borntraeger
-M:     borntraeger@de.ibm.com
+M:     Carsten Otte <cotte@de.ibm.com>
+M:     Christian Borntraeger <borntraeger@de.ibm.com>
 M:     linux390@de.ibm.com
 L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
@@ -3405,8 +2975,7 @@ F:        arch/s390/include/asm/kvm*
 F:     arch/s390/kvm/
 
 KEXEC
-P:     Eric Biederman
-M:     ebiederm@xmission.com
+M:     Eric Biederman <ebiederm@xmission.com>
 W:     http://ftp.kernel.org/pub/linux/kernel/people/horms/kexec-tools/
 L:     kexec@lists.infradead.org
 S:     Maintained
@@ -3414,8 +2983,7 @@ F:        include/linux/kexec.h
 F:     kernel/kexec.c
 
 KGDB
-P:     Jason Wessel
-M:     jason.wessel@windriver.com
+M:     Jason Wessel <jason.wessel@windriver.com>
 L:     kgdb-bugreport@lists.sourceforge.net
 S:     Maintained
 F:     Documentation/DocBook/kgdb.tmpl
@@ -3425,17 +2993,13 @@ F:      include/linux/kgdb.h
 F:     kernel/kgdb.c
 
 KMEMCHECK
-P:     Vegard Nossum
-M:     vegardno@ifi.uio.no
+M:     Vegard Nossum <vegardno@ifi.uio.no>
 P      Pekka Enberg
 M:     penberg@cs.helsinki.fi
-L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
 KMEMLEAK
-P:     Catalin Marinas
-M:     catalin.marinas@arm.com
-L:     linux-kernel@vger.kernel.org
+M:     Catalin Marinas <catalin.marinas@arm.com>
 S:     Maintained
 F:     Documentation/kmemleak.txt
 F:     include/linux/kmemleak.h
@@ -3443,30 +3007,24 @@ F:      mm/kmemleak.c
 F:     mm/kmemleak-test.c
 
 KMEMTRACE
-P:     Eduard - Gabriel Munteanu
-M:     eduard.munteanu@linux360.ro
+M:     Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro>
 S:     Maintained
 F:     Documentation/trace/kmemtrace.txt
 F:     include/linux/kmemtrace.h
 F:     kernel/trace/kmemtrace.c
 
 KPROBES
-P:     Ananth N Mavinakayanahalli
-M:     ananth@in.ibm.com
-P:     Anil S Keshavamurthy
-M:     anil.s.keshavamurthy@intel.com
-P:     David S. Miller
-M:     davem@davemloft.net
-P:     Masami Hiramatsu
-M:     mhiramat@redhat.com
+M:     Ananth N Mavinakayanahalli <ananth@in.ibm.com>
+M:     Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
+M:     "David S. Miller" <davem@davemloft.net>
+M:     Masami Hiramatsu <mhiramat@redhat.com>
 S:     Maintained
 F:     Documentation/kprobes.txt
 F:     include/linux/kprobes.h
 F:     kernel/kprobes.c
 
 KS0108 LCD CONTROLLER DRIVER
-P:     Miguel Ojeda Sandonis
-M:     miguel.ojeda.sandonis@gmail.com
+M:     Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>
 W:     http://miguelojeda.es/auxdisplay.htm
 W:     http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm
 S:     Maintained
@@ -3482,31 +3040,27 @@ F:      include/*/lapb.h
 F:     net/lapb/
 
 LASI 53c700 driver for PARISC
-P:     James E.J. Bottomley
-M:     James.Bottomley@HansenPartnership.com
+M:     "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
 F:     Documentation/scsi/53c700.txt
 F:     drivers/scsi/53c700*
 
 LED SUBSYSTEM
-P:     Richard Purdie
-M:     rpurdie@rpsys.net
+M:     Richard Purdie <rpurdie@rpsys.net>
 S:     Maintained
 F:     drivers/leds/
 F:     include/linux/leds.h
 
 LEGO USB Tower driver
-P:     Juergen Stuber
-M:     starblue@users.sourceforge.net
+M:     Juergen Stuber <starblue@users.sourceforge.net>
 L:     legousb-devel@lists.sourceforge.net
 W:     http://legousb.sourceforge.net/
 S:     Maintained
 F:     drivers/usb/misc/legousbtower.c
 
 LGUEST
-P:     Rusty Russell
-M:     rusty@rustcorp.com.au
+M:     Rusty Russell <rusty@rustcorp.com.au>
 L:     lguest@ozlabs.org
 W:     http://lguest.ozlabs.org/
 S:     Maintained
@@ -3517,119 +3071,100 @@ F:    include/linux/lguest*.h
 F:     arch/x86/include/asm/lguest*.h
 
 LINUX FOR IBM pSERIES (RS/6000)
-P:     Paul Mackerras
-M:     paulus@au.ibm.com
+M:     Paul Mackerras <paulus@au.ibm.com>
 W:     http://www.ibm.com/linux/ltc/projects/ppc
 S:     Supported
 
 LINUX FOR POWERPC (32-BIT AND 64-BIT)
-P:     Benjamin Herrenschmidt
-M:     benh@kernel.crashing.org
-P:     Paul Mackerras
-M:     paulus@samba.org
+M:     Benjamin Herrenschmidt <benh@kernel.crashing.org>
+M:     Paul Mackerras <paulus@samba.org>
 W:     http://www.penguinppc.org/
 L:     linuxppc-dev@ozlabs.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git
 S:     Supported
 
 LINUX FOR POWER MACINTOSH
-P:     Benjamin Herrenschmidt
-M:     benh@kernel.crashing.org
+M:     Benjamin Herrenschmidt <benh@kernel.crashing.org>
 W:     http://www.penguinppc.org/
 L:     linuxppc-dev@ozlabs.org
 S:     Maintained
 
 LINUX FOR POWERPC EMBEDDED MPC5XXX
-P:     Grant Likely
-M:     grant.likely@secretlab.ca
+M:     Grant Likely <grant.likely@secretlab.ca>
 L:     linuxppc-dev@ozlabs.org
 T:     git git://git.secretlab.ca/git/linux-2.6.git
 S:     Maintained
 
 LINUX FOR POWERPC EMBEDDED PPC4XX
-P:     Josh Boyer
-M:     jwboyer@linux.vnet.ibm.com
-P:     Matt Porter
-M:     mporter@kernel.crashing.org
+M:     Josh Boyer <jwboyer@linux.vnet.ibm.com>
+M:     Matt Porter <mporter@kernel.crashing.org>
 W:     http://www.penguinppc.org/
 L:     linuxppc-dev@ozlabs.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git
 S:     Maintained
 
 LINUX FOR POWERPC EMBEDDED XILINX VIRTEX
-P:     Grant Likely
-M:     grant.likely@secretlab.ca
+M:     Grant Likely <grant.likely@secretlab.ca>
 W:     http://wiki.secretlab.ca/index.php/Linux_on_Xilinx_Virtex
 L:     linuxppc-dev@ozlabs.org
 T:     git git://git.secretlab.ca/git/linux-2.6.git
 S:     Maintained
 
 LINUX FOR POWERPC EMBEDDED PPC8XX
-P:     Vitaly Bordug
-M:     vitb@kernel.crashing.org
-P:     Marcelo Tosatti
-M:     marcelo@kvack.org
+M:     Vitaly Bordug <vitb@kernel.crashing.org>
+M:     Marcelo Tosatti <marcelo@kvack.org>
 W:     http://www.penguinppc.org/
 L:     linuxppc-dev@ozlabs.org
 S:     Maintained
 
 LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX
-P:     Kumar Gala
-M:     galak@kernel.crashing.org
+M:     Kumar Gala <galak@kernel.crashing.org>
 W:     http://www.penguinppc.org/
 L:     linuxppc-dev@ozlabs.org
 S:     Maintained
 
 LINUX FOR POWERPC PA SEMI PWRFICIENT
-P:     Olof Johansson
-M:     olof@lixom.net
+M:     Olof Johansson <olof@lixom.net>
 W:     http://www.pasemi.com/
 L:     linuxppc-dev@ozlabs.org
 S:     Supported
 
 LINUX SECURITY MODULE (LSM) FRAMEWORK
-P:     Chris Wright
-M:     chrisw@sous-sol.org
+M:     Chris Wright <chrisw@sous-sol.org>
 L:     linux-security-module@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/chrisw/lsm-2.6.git
 S:     Supported
 
 LLC (802.2)
-P:     Arnaldo Carvalho de Melo
-M:     acme@ghostprotocols.net
+M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 S:     Maintained
 F:     include/linux/llc.h
 F:     include/net/llc*
 F:     net/llc/
 
 LIS3LV02D ACCELEROMETER DRIVER
-P:     Eric Piel
-M:     eric.piel@tremplin-utc.net
+M:     Eric Piel <eric.piel@tremplin-utc.net>
 S:     Maintained
 F:     Documentation/hwmon/lis3lv02d
 F:     drivers/hwmon/lis3lv02d.*
 
 LM83 HARDWARE MONITOR DRIVER
-P:     Jean Delvare
-M:     khali@linux-fr.org
+M:     Jean Delvare <khali@linux-fr.org>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/lm83
 F:     drivers/hwmon/lm83.c
 
 LM90 HARDWARE MONITOR DRIVER
-P:     Jean Delvare
-M:     khali@linux-fr.org
+M:     Jean Delvare <khali@linux-fr.org>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/lm90
 F:     drivers/hwmon/lm90.c
 
 LOCKDEP AND LOCKSTAT
-P:     Peter Zijlstra
-M:     peterz@infradead.org
-P:     Ingo Molnar
-M:     mingo@redhat.com
+M:     Peter Zijlstra <peterz@infradead.org>
+M:     Ingo Molnar <mingo@redhat.com>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/peterz/linux-2.6-lockdep.git
 S:     Maintained
 F:     Documentation/lockdep*.txt
@@ -3638,8 +3173,7 @@ F:        include/linux/lockdep.h
 F:     kernel/lockdep*
 
 LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks)
-P:     Richard Russon (FlatCap)
-M:     ldm@flatcap.org
+M:     "Richard Russon (FlatCap)" <ldm@flatcap.org>
 L:     linux-ntfs-dev@lists.sourceforge.net
 W:     http://www.linux-ntfs.org/content/view/19/37/
 S:     Maintained
@@ -3647,8 +3181,7 @@ F:        Documentation/ldm.txt
 F:     fs/partitions/ldm.*
 
 LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
-P:     Eric Moore
-M:     Eric.Moore@lsi.com
+M:     Eric Moore <Eric.Moore@lsi.com>
 M:     support@lsi.com
 L:     DL-MPTFusionLinux@lsi.com
 L:     linux-scsi@vger.kernel.org
@@ -3657,25 +3190,21 @@ S:      Supported
 F:     drivers/message/fusion/
 
 LSILOGIC/SYMBIOS/NCR 53C8XX and 53C1010 PCI-SCSI drivers
-P:     Matthew Wilcox
-M:     matthew@wil.cx
+M:     Matthew Wilcox <matthew@wil.cx>
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
 F:     drivers/scsi/sym53c8xx_2/
 
 LTP (Linux Test Project)
-P:     Subrata Modak
-M:     subrata@linux.vnet.ibm.com
-P:     Mike Frysinger
-M:     vapier@gentoo.org
+M:     Subrata Modak <subrata@linux.vnet.ibm.com>
+M:     Mike Frysinger <vapier@gentoo.org>
 L:     ltp-list@lists.sourceforge.net (subscribers-only)
 W:     http://ltp.sourceforge.net/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/galak/ltp.git
 S:     Maintained
 
 M32R ARCHITECTURE
-P:     Hirokazu Takata
-M:     takata@linux-m32r.org
+M:     Hirokazu Takata <takata@linux-m32r.org>
 L:     linux-m32r@ml.linux-m32r.org
 L:     linux-m32r-ja@ml.linux-m32r.org (in Japanese)
 W:     http://www.linux-m32r.org/
@@ -3683,10 +3212,8 @@ S:       Maintained
 F:     arch/m32r/
 
 M68K ARCHITECTURE
-P:     Geert Uytterhoeven
-M:     geert@linux-m68k.org
-P:     Roman Zippel
-M:     zippel@linux-m68k.org
+M:     Geert Uytterhoeven <geert@linux-m68k.org>
+M:     Roman Zippel <zippel@linux-m68k.org>
 L:     linux-m68k@lists.linux-m68k.org
 W:     http://www.linux-m68k.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git
@@ -3695,23 +3222,20 @@ F:      arch/m68k/
 F:     drivers/zorro/
 
 M68K ON APPLE MACINTOSH
-P:     Joshua Thompson
-M:     funaho@jurai.org
+M:     Joshua Thompson <funaho@jurai.org>
 W:     http://www.mac.linux-m68k.org/
 L:     linux-m68k@lists.linux-m68k.org
 S:     Maintained
 F:     arch/m68k/mac/
 
 M68K ON HP9000/300
-P:     Philip Blundell
-M:     philb@gnu.org
+M:     Philip Blundell <philb@gnu.org>
 W:     http://www.tazenda.demon.co.uk/phil/linux-hp
 S:     Maintained
 F:     arch/m68k/hp300/
 
 MAC80211
-P:     Johannes Berg
-M:     johannes@sipsolutions.net
+M:     Johannes Berg <johannes@sipsolutions.net>
 L:     linux-wireless@vger.kernel.org
 W:     http://linuxwireless.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git
@@ -3721,10 +3245,8 @@ F:       include/net/mac80211.h
 F:     net/mac80211/
 
 MAC80211 PID RATE CONTROL
-P:     Stefano Brivio
-M:     stefano.brivio@polimi.it
-P:     Mattias Nissler
-M:     mattias.nissler@gmx.de
+M:     Stefano Brivio <stefano.brivio@polimi.it>
+M:     Mattias Nissler <mattias.nissler@gmx.de>
 L:     linux-wireless@vger.kernel.org
 W:     http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/PID
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git
@@ -3732,67 +3254,57 @@ S:      Maintained
 F:     net/mac80211/rc80211_pid*
 
 MACVLAN DRIVER
-P:     Patrick McHardy
-M:     kaber@trash.net
+M:     Patrick McHardy <kaber@trash.net>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/macvlan.c
 F:     include/linux/if_macvlan.h
 
 MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
-P:     Michael Kerrisk
-M:     mtk.manpages@gmail.com
+M:     Michael Kerrisk <mtk.manpages@gmail.com>
 W:     http://www.kernel.org/doc/man-pages
 L:     linux-man@vger.kernel.org
 S:     Maintained
 
 MARVELL LIBERTAS WIRELESS DRIVER
-P:     Dan Williams
-M:     dcbw@redhat.com
+M:     Dan Williams <dcbw@redhat.com>
 L:     libertas-dev@lists.infradead.org
 S:     Maintained
 F:     drivers/net/wireless/libertas/
 
 MARVELL MV643XX ETHERNET DRIVER
-P:     Lennert Buytenhek
-M:     buytenh@marvell.com
+M:     Lennert Buytenhek <buytenh@marvell.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/mv643xx_eth.*
 F:     include/linux/mv643xx.h
 
 MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
-P:     Nicolas Pitre
-M:     nico@cam.org
+M:     Nicolas Pitre <nico@cam.org>
 S:     Maintained
 
 MARVELL YUKON / SYSKONNECT DRIVER
-P:     Mirko Lindner
-M:     mlindner@syskonnect.de
-P:     Ralph Roesler
-M:     rroesler@syskonnect.de
+M:     Mirko Lindner <mlindner@syskonnect.de>
+M:     Ralph Roesler <rroesler@syskonnect.de>
 W:     http://www.syskonnect.com
 S:     Supported
 
 MATROX FRAMEBUFFER DRIVER
-P:     Petr Vandrovec
-M:     vandrove@vc.cvut.cz
+M:     Petr Vandrovec <vandrove@vc.cvut.cz>
 L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/video/matrox/matroxfb_*
 F:     include/linux/matroxfb.h
 
 MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
-P:     Hans J. Koch
-M:     hjk@linutronix.de
+M:     "Hans J. Koch" <hjk@linutronix.de>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/max6650
 F:     drivers/hwmon/max6650.c
 
 MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
-P:     Mauro Carvalho Chehab
-M:     mchehab@infradead.org
+M:     Mauro Carvalho Chehab <mchehab@infradead.org>
 P:     LinuxTV.org Project
 L:     linux-media@vger.kernel.org
 W:     http://linuxtv.org
@@ -3806,8 +3318,7 @@ F:        include/linux/dvb/
 F:     include/linux/videodev*.h
 
 MEGARAID SCSI DRIVERS
-P:     Neela Syam Kolli
-M:     megaraidlinux@lsi.com
+M:     Neela Syam Kolli <megaraidlinux@lsi.com>
 L:     linux-scsi@vger.kernel.org
 W:     http://megaraid.lsilogic.com
 S:     Maintained
@@ -3823,19 +3334,15 @@ F:      include/linux/mm.h
 F:     mm/
 
 MEMORY RESOURCE CONTROLLER
-P:     Balbir Singh
-M:     balbir@linux.vnet.ibm.com
-P:     Pavel Emelyanov
-M:     xemul@openvz.org
-P:     KAMEZAWA Hiroyuki
-M:     kamezawa.hiroyu@jp.fujitsu.com
+M:     Balbir Singh <balbir@linux.vnet.ibm.com>
+M:     Pavel Emelyanov <xemul@openvz.org>
+M:     KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     mm/memcontrol.c
 
 MEMORY TECHNOLOGY DEVICES (MTD)
-P:     David Woodhouse
-M:     dwmw2@infradead.org
+M:     David Woodhouse <dwmw2@infradead.org>
 W:     http://www.linux-mtd.infradead.org/
 L:     linux-mtd@lists.infradead.org
 T:     git git://git.infradead.org/mtd-2.6.git
@@ -3845,8 +3352,7 @@ F:        include/linux/mtd/
 F:     include/mtd/
 
 MICROBLAZE ARCHITECTURE
-P:     Michal Simek
-M:     monstr@monstr.eu
+M:     Michal Simek <monstr@monstr.eu>
 L:     microblaze-uclinux@itee.uq.edu.au
 W:     http://www.monstr.eu/fdt/
 T:     git git://git.monstr.eu/linux-2.6-microblaze.git
@@ -3854,14 +3360,12 @@ S:      Supported
 F:     arch/microblaze/
 
 MICROTEK X6 SCANNER
-P:     Oliver Neukum
-M:     oliver@neukum.name
+M:     Oliver Neukum <oliver@neukum.name>
 S:     Maintained
 F:     drivers/usb/image/microtek.*
 
 MIPS
-P:     Ralf Baechle
-M:     ralf@linux-mips.org
+M:     Ralf Baechle <ralf@linux-mips.org>
 W:     http://www.linux-mips.org/
 L:     linux-mips@linux-mips.org
 T:     git git://git.linux-mips.org/pub/scm/linux.git
@@ -3870,8 +3374,7 @@ F:        Documentation/mips/
 F:     arch/mips/
 
 MISCELLANEOUS MCA-SUPPORT
-P:     James Bottomley
-M:     James.Bottomley@HansenPartnership.com
+M:     James Bottomley <James.Bottomley@HansenPartnership.com>
 S:     Maintained
 F:     Documentation/ia64/mca.txt
 F:     Documentation/mca.txt
@@ -3879,15 +3382,13 @@ F:      drivers/mca/
 F:     include/linux/mca*
 
 MODULE SUPPORT
-P:     Rusty Russell
-M:     rusty@rustcorp.com.au
+M:     Rusty Russell <rusty@rustcorp.com.au>
 S:     Maintained
 F:     include/linux/module.h
 F:     kernel/module.c
 
 MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER
-P:     Stelian Pop
-M:     stelian@popies.net
+M:     Stelian Pop <stelian@popies.net>
 W:     http://popies.net/meye/
 S:     Maintained
 F:     Documentation/video4linux/meye.txt
@@ -3895,135 +3396,112 @@ F:    drivers/media/video/meye.*
 F:     include/linux/meye.h
 
 MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER
-P:     Pavel Pisa
-M:     ppisa@pikron.com
+M:     Pavel Pisa <ppisa@pikron.com>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 F:     drivers/mmc/host/imxmmc.*
 
 MOUSE AND MISC DEVICES [GENERAL]
-P:     Alessandro Rubini
-M:     rubini@ipvvis.unipv.it
+M:     Alessandro Rubini <rubini@ipvvis.unipv.it>
 S:     Maintained
 F:     drivers/input/mouse/
 F:     include/linux/gpio_mouse.h
 
 MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
-P:     Jiri Slaby
-M:     jirislaby@gmail.com
+M:     Jiri Slaby <jirislaby@gmail.com>
 S:     Maintained
 F:     Documentation/serial/moxa-smartio
 F:     drivers/char/mxser.*
 
 MSI LAPTOP SUPPORT
-P:     Lennart Poettering
-M:     mzxreary@0pointer.de
+M:     Lennart Poettering <mzxreary@0pointer.de>
 W:     https://tango.0pointer.de/mailman/listinfo/s270-linux
 W:     http://0pointer.de/lennart/tchibo.html
 S:     Maintained
 F:     drivers/platform/x86/msi-laptop.c
 
 MULTIFUNCTION DEVICES (MFD)
-P:     Samuel Ortiz
-M:     sameo@linux.intel.com
+M:     Samuel Ortiz <sameo@linux.intel.com>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6.git
 S:     Supported
 F:     drivers/mfd/
 
 MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
-P:     Pierre Ossman
-M:     pierre@ossman.eu
-S:     Maintained
+S:     Orphan
+L:     linux-mmc@vger.kernel.org
 F:     drivers/mmc/
 F:     include/linux/mmc/
 
 MULTIMEDIA CARD (MMC) ETC. OVER SPI
-P:     David Brownell
-M:     dbrownell@users.sourceforge.net
+M:     David Brownell <dbrownell@users.sourceforge.net>
 S:     Odd Fixes
 F:     drivers/mmc/host/mmc_spi.c
 F:     include/linux/spi/mmc_spi.h
 
 MULTISOUND SOUND DRIVER
-P:     Andrew Veliath
-M:     andrewtv@usa.net
+M:     Andrew Veliath <andrewtv@usa.net>
 S:     Maintained
 F:     Documentation/sound/oss/MultiSound
 F:     sound/oss/msnd*
 
 MULTITECH MULTIPORT CARD (ISICOM)
-P:     Jiri Slaby
-M:     jirislaby@gmail.com
+M:     Jiri Slaby <jirislaby@gmail.com>
 S:     Maintained
 F:     drivers/char/isicom.c
 F:     include/linux/isicom.h
 
 MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
-P:     Felipe Balbi
-M:     felipe.balbi@nokia.com
+M:     Felipe Balbi <felipe.balbi@nokia.com>
 L:     linux-usb@vger.kernel.org
 T:     git git://gitorious.org/musb/mainline.git
 S:     Maintained
 F:     drivers/usb/musb/
 
 MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
-P:     Andrew Gallatin
-M:     gallatin@myri.com
-P:     Brice Goglin
-M:     brice@myri.com
+M:     Andrew Gallatin <gallatin@myri.com>
+M:     Brice Goglin <brice@myri.com>
 L:     netdev@vger.kernel.org
 W:     http://www.myri.com/scs/download-Myri10GE.html
 S:     Supported
 F:     drivers/net/myri10ge/
 
 NATSEMI ETHERNET DRIVER (DP8381x)
-P:     Tim Hockin
-M:     thockin@hockin.org
+M:     Tim Hockin <thockin@hockin.org>
 S:     Maintained
 F:     drivers/net/natsemi.c
 
 NCP FILESYSTEM
-P:     Petr Vandrovec
-M:     vandrove@vc.cvut.cz
+M:     Petr Vandrovec <vandrove@vc.cvut.cz>
 L:     linware@sh.cvut.cz
 S:     Maintained
 F:     fs/ncpfs/
 
 NCR DUAL 700 SCSI DRIVER (MICROCHANNEL)
-P:     James E.J. Bottomley
-M:     James.Bottomley@HansenPartnership.com
+M:     "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
 F:     drivers/scsi/NCR_D700.*
 
 NETEFFECT IWARP RNIC DRIVER (IW_NES)
-P:     Faisal Latif
-M:     faisal.latif@intel.com
-P:     Chien Tung
-M:     chien.tin.tung@intel.com
+M:     Faisal Latif <faisal.latif@intel.com>
+M:     Chien Tung <chien.tin.tung@intel.com>
 L:     general@lists.openfabrics.org
 W:     http://www.neteffect.com
 S:     Supported
 F:     drivers/infiniband/hw/nes/
 
 NETEM NETWORK EMULATOR
-P:     Stephen Hemminger
-M:     shemminger@linux-foundation.org
+M:     Stephen Hemminger <shemminger@linux-foundation.org>
 L:     netem@lists.linux-foundation.org
 S:     Maintained
 F:     net/sched/sch_netem.c
 
 NETERION (S2IO) 10GbE DRIVER (xframe/vxge)
-P:     Ramkrishna Vepa
-M:     ram.vepa@neterion.com
-P:     Rastapur Santosh
-M:     santosh.rastapur@neterion.com
-P:     Sivakumar Subramani
-M:     sivakumar.subramani@neterion.com
-P:     Sreenivasa Honnur
-M:     sreenivasa.honnur@neterion.com
-P:     Anil Murthy
-M:     anil.murthy@neterion.com
+M:     Ramkrishna Vepa <ram.vepa@neterion.com>
+M:     Rastapur Santosh <santosh.rastapur@neterion.com>
+M:     Sivakumar Subramani <sivakumar.subramani@neterion.com>
+M:     Sreenivasa Honnur <sreenivasa.honnur@neterion.com>
+M:     Anil Murthy <anil.murthy@neterion.com>
 L:     netdev@vger.kernel.org
 W:     http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous
 W:     http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous
@@ -4037,13 +3515,13 @@ P:      Marc Boucher
 P:     James Morris
 P:     Harald Welte
 P:     Jozsef Kadlecsik
-P:     Patrick McHardy
-M:     kaber@trash.net
+M:     Patrick McHardy <kaber@trash.net>
 L:     netfilter-devel@vger.kernel.org
 L:     netfilter@vger.kernel.org
 L:     coreteam@netfilter.org
 W:     http://www.netfilter.org/
 W:     http://www.iptables.org/
+T:     git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6.git
 S:     Supported
 F:     include/linux/netfilter*
 F:     include/linux/netfilter/
@@ -4053,8 +3531,7 @@ F:        net/*/netfilter/
 F:     net/netfilter/
 
 NETLABEL
-P:     Paul Moore
-M:     paul.moore@hp.com
+M:     Paul Moore <paul.moore@hp.com>
 W:     http://netlabel.sf.net
 L:     netdev@vger.kernel.org
 S:     Supported
@@ -4063,8 +3540,7 @@ F:        include/net/netlabel.h
 F:     net/netlabel/
 
 NETROM NETWORK LAYER
-P:     Ralf Baechle
-M:     ralf@linux-mips.org
+M:     Ralf Baechle <ralf@linux-mips.org>
 L:     linux-hams@vger.kernel.org
 W:     http://www.linux-ax25.org/
 S:     Maintained
@@ -4073,36 +3549,31 @@ F:      include/net/netrom.h
 F:     net/netrom/
 
 NETWORK BLOCK DEVICE (NBD)
-P:     Paul Clements
-M:     Paul.Clements@steeleye.com
+M:     Paul Clements <Paul.Clements@steeleye.com>
 S:     Maintained
 F:     Documentation/blockdev/nbd.txt
 F:     drivers/block/nbd.c
 F:     include/linux/nbd.h
 
 NETWORKING [GENERAL]
-P:     David S. Miller
-M:     davem@davemloft.net
+M:     "David S. Miller" <davem@davemloft.net>
 L:     netdev@vger.kernel.org
 W:     http://www.linuxfoundation.org/en/Net
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git
 S:     Maintained
 F:     net/
 F:     include/net/
+F:     include/linux/in.h
+F:     include/linux/net.h
+F:     include/linux/netdevice.h
 
 NETWORKING [IPv4/IPv6]
-P:     David S. Miller
-M:     davem@davemloft.net
-P:     Alexey Kuznetsov
-M:     kuznet@ms2.inr.ac.ru
-P:     Pekka Savola (ipv6)
-M:     pekkas@netcore.fi
-P:     James Morris
-M:     jmorris@namei.org
-P:     Hideaki YOSHIFUJI
-M:     yoshfuji@linux-ipv6.org
-P:     Patrick McHardy
-M:     kaber@trash.net
+M:     "David S. Miller" <davem@davemloft.net>
+M:     Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+M:     "Pekka Savola (ipv6)" <pekkas@netcore.fi>
+M:     James Morris <jmorris@namei.org>
+M:     Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
+M:     Patrick McHardy <kaber@trash.net>
 L:     netdev@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git
 S:     Maintained
@@ -4111,14 +3582,12 @@ F:      net/ipv6/
 F:     include/net/ip*
 
 NETWORKING [LABELED] (NetLabel, CIPSO, Labeled IPsec, SECMARK)
-P:     Paul Moore
-M:     paul.moore@hp.com
+M:     Paul Moore <paul.moore@hp.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 
 NETWORKING [WIRELESS]
-P:     John W. Linville
-M:     linville@tuxdriver.com
+M:     "John W. Linville" <linville@tuxdriver.com>
 L:     linux-wireless@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git
 S:     Maintained
@@ -4132,18 +3601,18 @@ W:      http://www.linuxfoundation.org/en/Net
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git
 S:     Odd Fixes
 F:     drivers/net/
+F:     include/linux/if_*
+F:     include/linux/*device.h
 
 NETXEN (1/10) GbE SUPPORT
-P:     Dhananjay Phadke
-M:     dhananjay@netxen.com
+M:     Dhananjay Phadke <dhananjay@netxen.com>
 L:     netdev@vger.kernel.org
 W:     http://www.netxen.com
 S:     Supported
 F:     drivers/net/netxen/
 
 NFS, SUNRPC, AND LOCKD CLIENTS
-P:     Trond Myklebust
-M:     Trond.Myklebust@netapp.com
+M:     Trond Myklebust <Trond.Myklebust@netapp.com>
 L:     linux-nfs@vger.kernel.org
 W:     http://client.linux-nfs.org
 T:     git git://git.linux-nfs.org/pub/linux/nfs-2.6.git
@@ -4157,17 +3626,14 @@ F:      include/linux/nfs*
 F:     include/linux/sunrpc/
 
 NI5010 NETWORK DRIVER
-P:     Jan-Pascal van Best
-M:     janpascal@vanbest.org
-P:     Andreas Mohr
-M:     andi@lisas.de
+M:     Jan-Pascal van Best <janpascal@vanbest.org>
+M:     Andreas Mohr <andi@lisas.de>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ni5010.*
 
 NILFS2 FILESYSTEM
-P:     KONISHI Ryusuke
-M:     konishi.ryusuke@lab.ntt.co.jp
+M:     KONISHI Ryusuke <konishi.ryusuke@lab.ntt.co.jp>
 L:     users@nilfs.org
 W:     http://www.nilfs.org/en/
 S:     Supported
@@ -4176,26 +3642,22 @@ F:      fs/nilfs2/
 F:     include/linux/nilfs2_fs.h
 
 NINJA SCSI-3 / NINJA SCSI-32Bi (16bit/CardBus) PCMCIA SCSI HOST ADAPTER DRIVER
-P:     YOKOTA Hiroshi
-M:     yokota@netlab.is.tsukuba.ac.jp
+M:     YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
 W:     http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/
 S:     Maintained
 F:     Documentation/scsi/NinjaSCSI.txt
 F:     drivers/scsi/pcmcia/nsp_*
 
 NINJA SCSI-32Bi/UDE PCI/CARDBUS SCSI HOST ADAPTER DRIVER
-P:     GOTO Masanori
-M:     gotom@debian.or.jp
-P:     YOKOTA Hiroshi
-M:     yokota@netlab.is.tsukuba.ac.jp
+M:     GOTO Masanori <gotom@debian.or.jp>
+M:     YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
 W:     http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/
 S:     Maintained
 F:     Documentation/scsi/NinjaSCSI.txt
 F:     drivers/scsi/nsp32*
 
 NTFS FILESYSTEM
-P:     Anton Altaparmakov
-M:     aia21@cantab.net
+M:     Anton Altaparmakov <aia21@cantab.net>
 L:     linux-ntfs-dev@lists.sourceforge.net
 W:     http://www.linux-ntfs.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/aia21/ntfs-2.6.git
@@ -4204,16 +3666,14 @@ F:      Documentation/filesystems/ntfs.txt
 F:     fs/ntfs/
 
 NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
-P:     Antonino Daplas
-M:     adaplas@gmail.com
+M:     Antonino Daplas <adaplas@gmail.com>
 L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/video/riva/
 F:     drivers/video/nvidia/
 
 OMAP SUPPORT
-P:     Tony Lindgren <tony@atomide.com>
-M:     tony@atomide.com
+M:     "Tony Lindgren <tony@atomide.com>" <tony@atomide.com>
 L:     linux-omap@vger.kernel.org
 W:     http://www.muru.com/linux/omap/
 W:     http://linux.omap.com/
@@ -4222,98 +3682,83 @@ S:      Maintained
 F:     arch/arm/*omap*
 
 OMAP CLOCK FRAMEWORK SUPPORT
-P:     Paul Walmsley
-M:     paul@pwsan.com
+M:     Paul Walmsley <paul@pwsan.com>
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     arch/arm/*omap*/*clock*
 
 OMAP POWER MANAGEMENT SUPPORT
-P:     Kevin Hilman
-M:     khilman@deeprootsystems.com
+M:     Kevin Hilman <khilman@deeprootsystems.com>
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     arch/arm/*omap*/*pm*
 
 OMAP AUDIO SUPPORT
-P:     Jarkko Nikula
-M:     jhnikula@gmail.com
+M:     Jarkko Nikula <jhnikula@gmail.com>
 L:     alsa-devel@alsa-project.org (subscribers-only)
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     sound/soc/omap/
 
 OMAP FRAMEBUFFER SUPPORT
-P:     Imre Deak
-M:     imre.deak@nokia.com
+M:     Imre Deak <imre.deak@nokia.com>
 L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     drivers/video/omap/
 
 OMAP MMC SUPPORT
-P:     Jarkko Lavinen
-M:     jarkko.lavinen@nokia.com
-L:     linux-kernel@vger.kernel.org
+M:     Jarkko Lavinen <jarkko.lavinen@nokia.com>
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     drivers/mmc/host/*omap*
 
 OMAP RANDOM NUMBER GENERATOR SUPPORT
-P:     Deepak Saxena
-M:     dsaxena@plexity.net
+M:     Deepak Saxena <dsaxena@plexity.net>
 S:     Maintained
 F:     drivers/char/hw_random/omap-rng.c
 
 OMAP USB SUPPORT
-P:     Felipe Balbi
-M:     felipe.balbi@nokia.com
-P:     David Brownell
-M:     dbrownell@users.sourceforge.net
+M:     Felipe Balbi <felipe.balbi@nokia.com>
+M:     David Brownell <dbrownell@users.sourceforge.net>
 L:     linux-usb@vger.kernel.org
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 
 OMFS FILESYSTEM
-P:     Bob Copeland
-M:     me@bobcopeland.com
+M:     Bob Copeland <me@bobcopeland.com>
 L:     linux-karma-devel@lists.sourceforge.net
 S:     Maintained
 F:     Documentation/filesystems/omfs.txt
 F:     fs/omfs/
 
 OMNIKEY CARDMAN 4000 DRIVER
-P:     Harald Welte
-M:     laforge@gnumonks.org
+M:     Harald Welte <laforge@gnumonks.org>
 S:     Maintained
 F:     drivers/char/pcmcia/cm4000_cs.c
 F:     include/linux/cm4000_cs.h
 
 OMNIKEY CARDMAN 4040 DRIVER
-P:     Harald Welte
-M:     laforge@gnumonks.org
+M:     Harald Welte <laforge@gnumonks.org>
 S:     Maintained
 F:     drivers/char/pcmcia/cm4040_cs.*
 
 OMNIVISION OV7670 SENSOR DRIVER
-P:     Jonathan Corbet
-M:     corbet@lwn.net
+M:     Jonathan Corbet <corbet@lwn.net>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 S:     Maintained
 F:     drivers/media/video/ov7670.c
 
 ONENAND FLASH DRIVER
-P:     Kyungmin Park
-M:     kyungmin.park@samsung.com
+M:     Kyungmin Park <kyungmin.park@samsung.com>
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
 F:     drivers/mtd/onenand/
 F:     include/linux/mtd/onenand*.h
 
 ONSTREAM SCSI TAPE DRIVER
-P:     Willem Riede
-M:     osst@riede.org
+M:     Willem Riede <osst@riede.org>
 L:     osst-users@lists.sourceforge.net
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
@@ -4321,16 +3766,14 @@ F:      drivers/scsi/osst*
 F:     drivers/scsi/st*
 
 OPENCORES I2C BUS DRIVER
-P:     Peter Korsgaard
-M:     jacmet@sunsite.dk
+M:     Peter Korsgaard <jacmet@sunsite.dk>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     Documentation/i2c/busses/i2c-ocores
 F:     drivers/i2c/busses/i2c-ocores.c
 
 OPROFILE
-P:     Robert Richter
-M:     robert.richter@amd.com
+M:     Robert Richter <robert.richter@amd.com>
 L:     oprofile-list@lists.sf.net
 S:     Maintained
 F:     arch/*/oprofile/
@@ -4338,10 +3781,8 @@ F:       drivers/oprofile/
 F:     include/linux/oprofile.h
 
 ORACLE CLUSTER FILESYSTEM 2 (OCFS2)
-P:     Mark Fasheh
-M:     mfasheh@suse.com
-P:     Joel Becker
-M:     joel.becker@oracle.com
+M:     Mark Fasheh <mfasheh@suse.com>
+M:     Joel Becker <joel.becker@oracle.com>
 L:     ocfs2-devel@oss.oracle.com (moderated for non-subscribers)
 W:     http://oss.oracle.com/projects/ocfs2/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2.git
@@ -4351,10 +3792,8 @@ F:       Documentation/filesystems/dlmfs.txt
 F:     fs/ocfs2/
 
 ORINOCO DRIVER
-P:     Pavel Roskin
-M:     proski@gnu.org
-P:     David Gibson
-M:     hermes@gibson.dropbear.id.au
+M:     Pavel Roskin <proski@gnu.org>
+M:     David Gibson <hermes@gibson.dropbear.id.au>
 L:     linux-wireless@vger.kernel.org
 L:     orinoco-users@lists.sourceforge.net
 L:     orinoco-devel@lists.sourceforge.net
@@ -4362,19 +3801,19 @@ W:      http://www.nongnu.org/orinoco/
 S:     Maintained
 F:     drivers/net/wireless/orinoco/
 
-OSD LIBRARY
-P:     Boaz Harrosh
-M:     bharrosh@panasas.com
-P:     Benny Halevy
-M:     bhalevy@panasas.com
+OSD LIBRARY and FILESYSTEM
+M:     Boaz Harrosh <bharrosh@panasas.com>
+M:     Benny Halevy <bhalevy@panasas.com>
 L:     osd-dev@open-osd.org
 W:     http://open-osd.org
 T:     git git://git.open-osd.org/open-osd.git
 S:     Maintained
+F:     drivers/scsi/osd/
+F:     include/scsi/osd_*
+F:     fs/exofs/
 
 P54 WIRELESS DRIVER
-P:     Michael Wu
-M:     flamingice@sourmilk.net
+M:     Michael Wu <flamingice@sourmilk.net>
 L:     linux-wireless@vger.kernel.org
 W:     http://prism54.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git
@@ -4382,30 +3821,25 @@ S:      Maintained
 F:     drivers/net/wireless/p54/
 
 PA SEMI ETHERNET DRIVER
-P:     Olof Johansson
-M:     olof@lixom.net
+M:     Olof Johansson <olof@lixom.net>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/pasemi_mac.*
 
 PA SEMI SMBUS DRIVER
-P:     Olof Johansson
-M:     olof@lixom.net
+M:     Olof Johansson <olof@lixom.net>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     drivers/i2c/busses/i2c-pasemi.c
 
 PANASONIC LAPTOP ACPI EXTRAS DRIVER
-P:     Harald Welte
-M:     laforge@gnumonks.org
+M:     Harald Welte <laforge@gnumonks.org>
 S:     Maintained
 F:     drivers/platform/x86/panasonic-laptop.c
 
 PANASONIC MN10300/AM33 PORT
-P:     David Howells
-M:     dhowells@redhat.com
-P:     Koichi Yasutake
-M:     yasutake.koichi@jp.panasonic.com
+M:     David Howells <dhowells@redhat.com>
+M:     Koichi Yasutake <yasutake.koichi@jp.panasonic.com>
 L:     linux-am33-list@redhat.com (moderated for non-subscribers)
 W:     ftp://ftp.redhat.com/pub/redhat/gnupro/AM33/
 S:     Maintained
@@ -4421,14 +3855,10 @@ F:      drivers/char/ppdev.c
 F:     include/linux/ppdev.h
 
 PARAVIRT_OPS INTERFACE
-P:     Jeremy Fitzhardinge
-M:     jeremy@xensource.com
-P:     Chris Wright
-M:     chrisw@sous-sol.org
-P:     Alok Kataria
-M:     akataria@vmware.com
-P:     Rusty Russell
-M:     rusty@rustcorp.com.au
+M:     Jeremy Fitzhardinge <jeremy@xensource.com>
+M:     Chris Wright <chrisw@sous-sol.org>
+M:     Alok Kataria <akataria@vmware.com>
+M:     Rusty Russell <rusty@rustcorp.com.au>
 L:     virtualization@lists.osdl.org
 S:     Supported
 F:     Documentation/ia64/paravirt_ops.txt
@@ -4436,8 +3866,7 @@ F:        arch/*/kernel/paravirt*
 F:     arch/*/include/asm/paravirt.h
 
 PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES
-P:     Tim Waugh
-M:     tim@cyberelk.net
+M:     Tim Waugh <tim@cyberelk.net>
 L:     linux-parport@lists.infradead.org (subscribers-only)
 W:     http://www.torque.net/linux-pp.html
 S:     Maintained
@@ -4445,10 +3874,8 @@ F:       Documentation/blockdev/paride.txt
 F:     drivers/block/paride/
 
 PARISC ARCHITECTURE
-P:     Kyle McMartin
-M:     kyle@mcmartin.ca
-P:     Helge Deller
-M:     deller@gmx.de
+M:     Kyle McMartin <kyle@mcmartin.ca>
+M:     Helge Deller <deller@gmx.de>
 L:     linux-parisc@vger.kernel.org
 W:     http://www.parisc-linux.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kyle/parisc-2.6.git
@@ -4457,37 +3884,32 @@ F:      arch/parisc/
 F:     drivers/parisc/
 
 PC87360 HARDWARE MONITORING DRIVER
-P:     Jim Cromie
-M:     jim.cromie@gmail.com
+M:     Jim Cromie <jim.cromie@gmail.com>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/pc87360
 F:     drivers/hwmon/pc87360.c
 
 PC8736x GPIO DRIVER
-P:     Jim Cromie
-M:     jim.cromie@gmail.com
+M:     Jim Cromie <jim.cromie@gmail.com>
 S:     Maintained
 F:     drivers/char/pc8736x_gpio.c
 
 PCA9532 LED DRIVER
-P:     Riku Voipio
-M:     riku.voipio@iki.fi
+M:     Riku Voipio <riku.voipio@iki.fi>
 S:     Maintained
 F:     drivers/leds/leds-pca9532.c
 F:     include/linux/leds-pca9532.h
 
 PCI ERROR RECOVERY
-P:     Linas Vepstas
-M:     linas@austin.ibm.com
+M:     Linas Vepstas <linas@austin.ibm.com>
 L:     linux-pci@vger.kernel.org
 S:     Supported
 F:     Documentation/PCI/pci-error-recovery.txt
 F:     Documentation/powerpc/eeh-pci-error-recovery.txt
 
 PCI SUBSYSTEM
-P:     Jesse Barnes
-M:     jbarnes@virtuousgeek.org
+M:     Jesse Barnes <jbarnes@virtuousgeek.org>
 L:     linux-pci@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git
 S:     Supported
@@ -4496,8 +3918,7 @@ F:        drivers/pci/
 F:     include/linux/pci*
 
 PCIE HOTPLUG DRIVER
-P:     Kristen Carlson Accardi
-M:     kristen.c.accardi@intel.com
+M:     Kristen Carlson Accardi <kristen.c.accardi@intel.com>
 L:     linux-pci@vger.kernel.org
 S:     Supported
 F:     drivers/pci/pcie/
@@ -4513,121 +3934,103 @@ F:    drivers/pcmcia/
 F:     include/pcmcia/
 
 PCNET32 NETWORK DRIVER
-P:     Don Fry
-M:     pcnet32@verizon.net
+M:     Don Fry <pcnet32@verizon.net>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/pcnet32.c
 
 PER-TASK DELAY ACCOUNTING
-P:     Balbir Singh
-M:     balbir@linux.vnet.ibm.com
+M:     Balbir Singh <balbir@linux.vnet.ibm.com>
 S:     Maintained
 F:     include/linux/delayacct.h
 F:     kernel/delayacct.c
 
 PERFORMANCE COUNTER SUBSYSTEM
-P:     Peter Zijlstra
-M:     a.p.zijlstra@chello.nl
-P:     Paul Mackerras
-M:     paulus@samba.org
-P:     Ingo Molnar
-M:     mingo@elte.hu
-L:     linux-kernel@vger.kernel.org
+M:     Peter Zijlstra <a.p.zijlstra@chello.nl>
+M:     Paul Mackerras <paulus@samba.org>
+M:     Ingo Molnar <mingo@elte.hu>
 S:     Supported
 
 PERSONALITY HANDLING
-P:     Christoph Hellwig
-M:     hch@infradead.org
+M:     Christoph Hellwig <hch@infradead.org>
 L:     linux-abi-devel@lists.sourceforge.net
 S:     Maintained
 F:     include/linux/personality.h
 
 PHRAM MTD DRIVER
-P:     Joern Engel
-M:     joern@lazybastard.org
+M:     Joern Engel <joern@lazybastard.org>
 L:     linux-mtd@lists.infradead.org
 S:     Maintained
 F:     drivers/mtd/devices/phram.c
 
 PKTCDVD DRIVER
-P:     Peter Osterlund
-M:     petero2@telia.com
+M:     Peter Osterlund <petero2@telia.com>
 S:     Maintained
 F:     drivers/block/pktcdvd.c
 F:     include/linux/pktcdvd.h
 
 POSIX CLOCKS and TIMERS
-P:     Thomas Gleixner
-M:     tglx@linutronix.de
+M:     Thomas Gleixner <tglx@linutronix.de>
 S:     Supported
 F:     fs/timerfd.c
 F:     include/linux/timer*
 F:     kernel/*timer*
 
 POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
-P:     Anton Vorontsov
-M:     cbou@mail.ru
-P:     David Woodhouse
-M:     dwmw2@infradead.org
+M:     Anton Vorontsov <cbou@mail.ru>
+M:     David Woodhouse <dwmw2@infradead.org>
 T:     git git://git.infradead.org/battery-2.6.git
 S:     Maintained
 F:     include/linux/power_supply.h
 F:     drivers/power/power_supply*
 
 PNP SUPPORT
-P:     Adam Belay
-M:     abelay@mit.edu
-P:     Bjorn Helgaas
-M:     bjorn.helgaas@hp.com
+M:     Adam Belay <abelay@mit.edu>
+M:     Bjorn Helgaas <bjorn.helgaas@hp.com>
 S:     Maintained
 F:     drivers/pnp/
 
 PNXxxxx I2C DRIVER
-P:     Vitaly Wool
-M:     vitalywool@gmail.com
+M:     Vitaly Wool <vitalywool@gmail.com>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     drivers/i2c/busses/i2c-pnx.c
 
 PPP PROTOCOL DRIVERS AND COMPRESSORS
-P:     Paul Mackerras
-M:     paulus@samba.org
+M:     Paul Mackerras <paulus@samba.org>
 L:     linux-ppp@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ppp_*
 
 PPP OVER ATM (RFC 2364)
-P:     Mitchell Blank Jr
-M:     mitch@sfgoth.com
+M:     Mitchell Blank Jr <mitch@sfgoth.com>
 S:     Maintained
 F:     net/atm/pppoatm.c
 F:     include/linux/atmppp.h
 
 PPP OVER ETHERNET
-P:     Michal Ostrowski
-M:     mostrows@earthlink.net
+M:     Michal Ostrowski <mostrows@earthlink.net>
 S:     Maintained
 F:     drivers/net/pppoe.c
 F:     drivers/net/pppox.c
 
 PPP OVER L2TP
-P:     James Chapman
-M:     jchapman@katalix.com
+M:     James Chapman <jchapman@katalix.com>
 S:     Maintained
 F:     drivers/net/pppol2tp.c
 F:     include/linux/if_pppol2tp.h
 
 PPS SUPPORT
-P:     Rodolfo Giometti
-M:     giometti@enneenne.com
+M:     Rodolfo Giometti <giometti@enneenne.com>
 W:     http://wiki.enneenne.com/index.php/LinuxPPS_support
 L:     linuxpps@ml.enneenne.com (subscribers-only)
 S:     Maintained
+F:     Documentation/pps/
+F:     drivers/pps/
+F:     include/linux/pps*.h
 
 PREEMPTIBLE KERNEL
-P:     Robert Love
-M:     rml@tech9.net
+M:     Robert Love <rml@tech9.net>
 L:     kpreempt-tech@lists.sourceforge.net
 W:     ftp://ftp.kernel.org/pub/linux/kernel/people/rml/preempt-kernel
 S:     Supported
@@ -4635,37 +4038,32 @@ F:      Documentation/preempt-locking.txt
 F:     include/linux/preempt.h
 
 PRISM54 WIRELESS DRIVER
-P:     Luis R. Rodriguez
-M:     mcgrof@gmail.com
+M:     "Luis R. Rodriguez" <mcgrof@gmail.com>
 L:     linux-wireless@vger.kernel.org
 W:     http://prism54.org
 S:     Maintained
 F:     drivers/net/wireless/prism54/
 
 PROMISE DC4030 CACHING DISK CONTROLLER DRIVER
-P:     Peter Denison
-M:     promise@pnd-pc.demon.co.uk
+M:     Peter Denison <promise@pnd-pc.demon.co.uk>
 W:     http://www.pnd-pc.demon.co.uk/promise/
 S:     Maintained
 
 PROMISE SATA TX2/TX4 CONTROLLER LIBATA DRIVER
-P:     Mikael Pettersson
-M:     mikpe@it.uu.se
+M:     Mikael Pettersson <mikpe@it.uu.se>
 L:     linux-ide@vger.kernel.org
 S:     Maintained
 F:     drivers/ata/sata_promise.*
 
 PS3 NETWORK SUPPORT
-P:     Geoff Levand
-M:     geoffrey.levand@am.sony.com
+M:     Geoff Levand <geoffrey.levand@am.sony.com>
 L:     netdev@vger.kernel.org
 L:     cbe-oss-dev@ozlabs.org
 S:     Supported
 F:     drivers/net/ps3_gelic_net.*
 
 PS3 PLATFORM SUPPORT
-P:     Geoff Levand
-M:     geoffrey.levand@am.sony.com
+M:     Geoff Levand <geoffrey.levand@am.sony.com>
 L:     linuxppc-dev@ozlabs.org
 L:     cbe-oss-dev@ozlabs.org
 S:     Supported
@@ -4680,16 +4078,13 @@ F:      drivers/usb/host/*ps3.c
 F:     sound/ppc/snd_ps3*
 
 PS3VRAM DRIVER
-P:     Jim Paris
-M:     jim@jtan.com
+M:     Jim Paris <jim@jtan.com>
 L:     cbe-oss-dev@ozlabs.org
 S:     Maintained
 
 PTRACE SUPPORT
-P:     Roland McGrath
-M:     roland@redhat.com
-P:     Oleg Nesterov
-M:     oleg@redhat.com
+M:     Roland McGrath <roland@redhat.com>
+M:     Oleg Nesterov <oleg@redhat.com>
 S:     Maintained
 F:     include/asm-generic/syscall.h
 F:     include/linux/ptrace.h
@@ -4698,8 +4093,7 @@ F:        include/linux/tracehook.h
 F:     kernel/ptrace.c
 
 PVRUSB2 VIDEO4LINUX DRIVER
-P:     Mike Isely
-M:     isely@pobox.com
+M:     Mike Isely <isely@pobox.com>
 L:     pvrusb2@isely.net       (subscribers-only)
 L:     linux-media@vger.kernel.org
 W:     http://www.isely.net/pvrusb2/
@@ -4709,10 +4103,8 @@ F:       Documentation/video4linux/README.pvrusb2
 F:     drivers/media/video/pvrusb2/
 
 PXA2xx/PXA3xx SUPPORT
-P:     Eric Miao
-M:     eric.y.miao@gmail.com
-P:     Russell King
-M:     linux@arm.linux.org.uk
+M:     Eric Miao <eric.y.miao@gmail.com>
+M:     Russell King <linux@arm.linux.org.uk>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
 F:     arch/arm/mach-pxa/
@@ -4724,17 +4116,14 @@ F:      sound/arm/pxa*
 F:     sound/soc/pxa
 
 PXA168 SUPPORT
-P:     Eric Miao
-M:     eric.y.miao@gmail.com
-P:     Jason Chagas
-M:     jason.chagas@marvell.com
+M:     Eric Miao <eric.y.miao@gmail.com>
+M:     Jason Chagas <jason.chagas@marvell.com>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git
 S:     Maintained
 
 PXA910 SUPPORT
-P:     Eric Miao
-M:     eric.y.miao@gmail.com
+M:     Eric Miao <eric.y.miao@gmail.com>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git
 S:     Maintained
@@ -4743,13 +4132,12 @@ PXA MMCI DRIVER
 S:     Orphan
 
 PXA RTC DRIVER
-P:     Robert Jarzmik
-M:     robert.jarzmik@free.fr
+M:     Robert Jarzmik <robert.jarzmik@free.fr>
 L:     rtc-linux@googlegroups.com
 S:     Maintained
 
 QLOGIC QLA2XXX FC-SCSI DRIVER
-P:     Andrew Vasquez
+M:     Andrew Vasquez <andrew.vasquez@qlogic.com>
 M:     linux-driver@qlogic.com
 L:     linux-scsi@vger.kernel.org
 S:     Supported
@@ -4757,7 +4145,7 @@ F:        Documentation/scsi/LICENSE.qla2xxx
 F:     drivers/scsi/qla2xxx/
 
 QLOGIC QLA3XXX NETWORK DRIVER
-P:     Ron Mercer
+M:     Ron Mercer <ron.mercer@qlogic.com>
 M:     linux-driver@qlogic.com
 L:     netdev@vger.kernel.org
 S:     Supported
@@ -4765,16 +4153,14 @@ F:      Documentation/networking/LICENSE.qla3xxx
 F:     drivers/net/qla3xxx.*
 
 QLOGIC QLGE 10Gb ETHERNET DRIVER
-P:     Ron Mercer
+M:     Ron Mercer <ron.mercer@qlogic.com>
 M:     linux-driver@qlogic.com
-M:     ron.mercer@qlogic.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/qlge/
 
 QNX4 FILESYSTEM
-P:     Anders Larsen
-M:     al@alarsen.net
+M:     Anders Larsen <al@alarsen.net>
 W:     http://www.alarsen.net/linux/qnx4fs/
 S:     Maintained
 F:     fs/qnx4/
@@ -4782,16 +4168,14 @@ F:      include/linux/qnx4_fs.h
 F:     include/linux/qnxtypes.h
 
 RADEON FRAMEBUFFER DISPLAY DRIVER
-P:     Benjamin Herrenschmidt
-M:     benh@kernel.crashing.org
+M:     Benjamin Herrenschmidt <benh@kernel.crashing.org>
 L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/video/aty/radeon*
 F:     include/linux/radeonfb.h
 
 RAGE128 FRAMEBUFFER DISPLAY DRIVER
-P:     Paul Mackerras
-M:     paulus@samba.org
+M:     Paul Mackerras <paulus@samba.org>
 L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/video/aty/aty128fb.c
@@ -4806,64 +4190,53 @@ T:      git git://git.kernel.org/pub/scm/linux/kernel/git/ivd/rt2x00.git
 F:     drivers/net/wireless/rt2x00/
 
 RAMDISK RAM BLOCK DEVICE DRIVER
-P:     Nick Piggin
-M:     npiggin@suse.de
+M:     Nick Piggin <npiggin@suse.de>
 S:     Maintained
 F:     Documentation/blockdev/ramdisk.txt
 F:     drivers/block/brd.c
 
 RANDOM NUMBER DRIVER
-P:     Matt Mackall
-M:     mpm@selenic.com
+M:     Matt Mackall <mpm@selenic.com>
 S:     Maintained
 F:     drivers/char/random.c
 
 RAPIDIO SUBSYSTEM
-P:     Matt Porter
-M:     mporter@kernel.crashing.org
+M:     Matt Porter <mporter@kernel.crashing.org>
 S:     Maintained
 F:     drivers/rapidio/
 
 RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
-P:     Corey Thomas
-M:     coreythomas@charter.net
+M:     Corey Thomas <coreythomas@charter.net>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
 F:     drivers/net/wireless/ray*
 
 RCUTORTURE MODULE
-P:     Josh Triplett
-M:     josh@freedesktop.org
-P:     Paul E. McKenney
-M:     paulmck@linux.vnet.ibm.com
+M:     Josh Triplett <josh@freedesktop.org>
+M:     "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
 S:     Maintained
 F:     Documentation/RCU/torture.txt
 F:     kernel/rcutorture.c
 
 RDC R-321X SoC
-P:     Florian Fainelli
-M:     florian@openwrt.org
+M:     Florian Fainelli <florian@openwrt.org>
 S:     Maintained
 
 RDC R6040 FAST ETHERNET DRIVER
-P:     Florian Fainelli
-M:     florian@openwrt.org
+M:     Florian Fainelli <florian@openwrt.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/r6040.c
 
 RDS - RELIABLE DATAGRAM SOCKETS
-P:     Andy Grover
-M:     andy.grover@oracle.com
+M:     Andy Grover <andy.grover@oracle.com>
 L:     rds-devel@oss.oracle.com (moderated for non-subscribers)
 S:     Supported
 F:     net/rds/
 
 READ-COPY UPDATE (RCU)
-P:     Dipankar Sarma
-M:     dipankar@in.ibm.com
-P:     Paul E. McKenney
-M:     paulmck@linux.vnet.ibm.com
+M:     Dipankar Sarma <dipankar@in.ibm.com>
+M:     "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
 W:     http://www.rdrop.com/users/paulmck/rclock/
 S:     Supported
 F:     Documentation/RCU/rcu.txt
@@ -4873,16 +4246,14 @@ F:      include/linux/srcu.h
 F:     kernel/rcupdate.c
 
 REAL TIME CLOCK DRIVER
-P:     Paul Gortmaker
-M:     p_gortmaker@yahoo.com
+M:     Paul Gortmaker <p_gortmaker@yahoo.com>
 S:     Maintained
 F:     Documentation/rtc.txt
 F:     drivers/rtc/
 F:     include/linux/rtc.h
 
 REAL TIME CLOCK (RTC) SUBSYSTEM
-P:     Alessandro Zummo
-M:     a.zummo@towertech.it
+M:     Alessandro Zummo <a.zummo@towertech.it>
 L:     rtc-linux@googlegroups.com
 S:     Maintained
 F:     Documentation/rtc.txt
@@ -4895,8 +4266,7 @@ S:        Supported
 F:     fs/reiserfs/
 
 RFKILL
-P:     Johannes Berg
-M:     johannes@sipsolutions.net
+M:     Johannes Berg <johannes@sipsolutions.net>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
 F      Documentation/rfkill.txt
@@ -4915,8 +4285,7 @@ F:        Documentation/serial/rocket.txt
 F:     drivers/char/rocket*
 
 ROSE NETWORK LAYER
-P:     Ralf Baechle
-M:     ralf@linux-mips.org
+M:     Ralf Baechle <ralf@linux-mips.org>
 L:     linux-hams@vger.kernel.org
 W:     http://www.linux-ax25.org/
 S:     Maintained
@@ -4925,8 +4294,7 @@ F:        include/net/rose.h
 F:     net/rose/
 
 RTL8180 WIRELESS DRIVER
-P:     John W. Linville
-M:     linville@tuxdriver.com
+M:     "John W. Linville" <linville@tuxdriver.com>
 L:     linux-wireless@vger.kernel.org
 W:     http://linuxwireless.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
@@ -4934,12 +4302,9 @@ S:       Maintained
 F:     drivers/net/wireless/rtl818*
 
 RTL8187 WIRELESS DRIVER
-P:     Herton Ronaldo Krzesinski
-M:     herton@mandriva.com.br
-P:     Hin-Tak Leung
-M:     htl10@users.sourceforge.net
-P:     Larry Finger
-M:     Larry.Finger@lwfinger.net
+M:     Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+M:     Hin-Tak Leung <htl10@users.sourceforge.net>
+M:     Larry Finger <Larry.Finger@lwfinger.net>
 L:     linux-wireless@vger.kernel.org
 W:     http://linuxwireless.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
@@ -4947,17 +4312,14 @@ S:      Maintained
 F:     drivers/net/wireless/rtl818x/rtl8187*
 
 S3 SAVAGE FRAMEBUFFER DRIVER
-P:     Antonino Daplas
-M:     adaplas@gmail.com
+M:     Antonino Daplas <adaplas@gmail.com>
 L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/video/savage/
 
 S390
-P:     Martin Schwidefsky
-M:     schwidefsky@de.ibm.com
-P:     Heiko Carstens
-M:     heiko.carstens@de.ibm.com
+M:     Martin Schwidefsky <schwidefsky@de.ibm.com>
+M:     Heiko Carstens <heiko.carstens@de.ibm.com>
 M:     linux390@de.ibm.com
 L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
@@ -4965,10 +4327,8 @@ S:       Supported
 F:     arch/s390/
 
 S390 NETWORK DRIVERS
-P:     Ursula Braun
-M:     ursula.braun@de.ibm.com
-P:     Frank Blaschka
-M:     blaschka@linux.vnet.ibm.com
+M:     Ursula Braun <ursula.braun@de.ibm.com>
+M:     Frank Blaschka <blaschka@linux.vnet.ibm.com>
 M:     linux390@de.ibm.com
 L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
@@ -4976,20 +4336,16 @@ S:      Supported
 F:     drivers/s390/net/
 
 S390 ZCRYPT DRIVER
-P:     Felix Beck
-M:     felix.beck@de.ibm.com
-P:     Ralph Wuerthner
-M:     ralph.wuerthner@de.ibm.com
+M:     Felix Beck <felix.beck@de.ibm.com>
+M:     Ralph Wuerthner <ralph.wuerthner@de.ibm.com>
 M:     linux390@de.ibm.com
 L:     linux-s390@vger.kernel.org
 S:     Supported
 F:     drivers/s390/crypto/
 
 S390 ZFCP DRIVER
-P:     Christof Schmitt
-M:     christof.schmitt@de.ibm.com
-P:     Martin Peschke
-M:     mp3@de.ibm.com
+M:     Christof Schmitt <christof.schmitt@de.ibm.com>
+M:     Martin Peschke <mp3@de.ibm.com>
 M:     linux390@de.ibm.com
 L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
@@ -4998,8 +4354,7 @@ F:        Documentation/s390/zfcpdump.txt
 F:     drivers/s390/scsi/zfcp_*
 
 S390 IUCV NETWORK LAYER
-P:     Ursula Braun
-M:     ursula.braun@de.ibm.com
+M:     Ursula Braun <ursula.braun@de.ibm.com>
 M:     linux390@de.ibm.com
 L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
@@ -5009,15 +4364,13 @@ F:      include/net/iucv/
 F:     net/iucv/
 
 S3C24XX SD/MMC Driver
-P:     Ben Dooks
-M:     ben-linux@fluff.org
+M:     Ben Dooks <ben-linux@fluff.org>
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Supported
 F:     drivers/mmc/host/s3cmci.*
 
 SAA7146 VIDEO4LINUX-2 DRIVER
-P:     Michael Hunold
-M:     michael@mihu.de
+M:     Michael Hunold <michael@mihu.de>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 W:     http://www.mihu.de/linux/saa7146
@@ -5027,31 +4380,26 @@ F:      drivers/media/video/*7146*
 F:     include/media/*7146*
 
 SC1200 WDT DRIVER
-P:     Zwane Mwaikambo
-M:     zwane@arm.linux.org.uk
+M:     Zwane Mwaikambo <zwane@arm.linux.org.uk>
 S:     Maintained
 F:     drivers/watchdog/sc1200wdt.c
 
 SCHEDULER
-P:     Ingo Molnar
-M:     mingo@elte.hu
-P:     Peter Zijlstra
-M:     peterz@infradead.org
+M:     Ingo Molnar <mingo@elte.hu>
+M:     Peter Zijlstra <peterz@infradead.org>
 S:     Maintained
 F:     kernel/sched*
 F:     include/linux/sched.h
 
 SCSI CDROM DRIVER
-P:     Jens Axboe
-M:     axboe@kernel.dk
+M:     Jens Axboe <axboe@kernel.dk>
 L:     linux-scsi@vger.kernel.org
 W:     http://www.kernel.dk
 S:     Maintained
 F:     drivers/scsi/sr*
 
 SCSI SG DRIVER
-P:     Doug Gilbert
-M:     dgilbert@interlog.com
+M:     Doug Gilbert <dgilbert@interlog.com>
 L:     linux-scsi@vger.kernel.org
 W:     http://www.torque.net/sg
 S:     Maintained
@@ -5059,8 +4407,7 @@ F:        drivers/scsi/sg.c
 F:     include/scsi/sg.h
 
 SCSI SUBSYSTEM
-P:     James E.J. Bottomley
-M:     James.Bottomley@HansenPartnership.com
+M:     "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
 L:     linux-scsi@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6.git
@@ -5070,18 +4417,15 @@ F:      drivers/scsi/
 F:     include/scsi/
 
 SCSI TAPE DRIVER
-P:     Kai Mäkisara
-M:     Kai.Makisara@kolumbus.fi
+M:     Kai Mäkisara <Kai.Makisara@kolumbus.fi>
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
 F:     Documentation/scsi/st.txt
 F:     drivers/scsi/st*
 
 SCTP PROTOCOL
-P:     Vlad Yasevich
-M:     vladislav.yasevich@hp.com
-P:     Sridhar Samudrala
-M:     sri@us.ibm.com
+M:     Vlad Yasevich <vladislav.yasevich@hp.com>
+M:     Sridhar Samudrala <sri@us.ibm.com>
 L:     linux-sctp@vger.kernel.org
 W:     http://lksctp.sourceforge.net
 S:     Supported
@@ -5091,8 +4435,7 @@ F:        include/net/sctp/
 F:     net/sctp/
 
 SCx200 CPU SUPPORT
-P:     Jim Cromie
-M:     jim.cromie@gmail.com
+M:     Jim Cromie <jim.cromie@gmail.com>
 S:     Odd Fixes
 F:     Documentation/i2c/busses/scx200_acb
 F:     arch/x86/kernel/scx200_32.c
@@ -5102,49 +4445,42 @@ F:      drivers/mtd/maps/scx200_docflash.c
 F:     include/linux/scx200.h
 
 SCx200 GPIO DRIVER
-P:     Jim Cromie
-M:     jim.cromie@gmail.com
+M:     Jim Cromie <jim.cromie@gmail.com>
 S:     Maintained
 F:     drivers/char/scx200_gpio.c
 F:     include/linux/scx200_gpio.h
 
 SCx200 HRT CLOCKSOURCE DRIVER
-P:     Jim Cromie
-M:     jim.cromie@gmail.com
+M:     Jim Cromie <jim.cromie@gmail.com>
 S:     Maintained
 F:     drivers/clocksource/scx200_hrt.c
 
 SDRICOH_CS MMC/SD HOST CONTROLLER INTERFACE DRIVER
-P:     Sascha Sommer
-M:     saschasommer@freenet.de
+M:     Sascha Sommer <saschasommer@freenet.de>
 L:     sdricohcs-devel@lists.sourceforge.net (subscribers-only)
 S:     Maintained
 F:     drivers/mmc/host/sdricoh_cs.c
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
-P:     Pierre Ossman
-M:     pierre@ossman.eu
+M:     Pierre Ossman <pierre@ossman.eu>
 L:     sdhci-devel@lists.ossman.eu
 S:     Maintained
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
-P:     Anton Vorontsov
-M:     avorontsov@ru.mvista.com
+M:     Anton Vorontsov <avorontsov@ru.mvista.com>
 L:     linuxppc-dev@ozlabs.org
 L:     sdhci-devel@lists.ossman.eu
 S:     Maintained
 F:     drivers/mmc/host/sdhci.*
 
 SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) SAMSUNG DRIVER
-P:     Ben Dooks
-M:     ben-linux@fluff.org
+M:     Ben Dooks <ben-linux@fluff.org>
 L:     sdhci-devel@lists.ossman.eu
 S:     Maintained
 F:     drivers/mmc/host/sdhci-s3c.c
 
 SECURITY SUBSYSTEM
-P:     James Morris
-M:     jmorris@namei.org
+M:     James Morris <jmorris@namei.org>
 L:     linux-security-module@vger.kernel.org (suggested Cc:)
 T:     git git://www.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git
 W:     http://security.wiki.kernel.org/
@@ -5152,17 +4488,13 @@ S:      Supported
 F:     security/
 
 SECURITY CONTACT
-P:     Security Officers
-M:     security@kernel.org
+M:     Security Officers <security@kernel.org>
 S:     Supported
 
 SELINUX SECURITY MODULE
-P:     Stephen Smalley
-M:     sds@tycho.nsa.gov
-P:     James Morris
-M:     jmorris@namei.org
-P:     Eric Paris
-M:     eparis@parisplace.org
+M:     Stephen Smalley <sds@tycho.nsa.gov>
+M:     James Morris <jmorris@namei.org>
+M:     Eric Paris <eparis@parisplace.org>
 L:     selinux@tycho.nsa.gov (subscribers-only, general discussion)
 W:     http://selinuxproject.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git
@@ -5171,15 +4503,13 @@ F:      include/linux/selinux*
 F:     security/selinux/
 
 SENSABLE PHANTOM
-P:     Jiri Slaby
-M:     jirislaby@gmail.com
+M:     Jiri Slaby <jirislaby@gmail.com>
 S:     Maintained
 F:     drivers/misc/phantom.c
 F:     include/linux/phantom.h
 
 SERIAL ATA (SATA) SUBSYSTEM
-P:     Jeff Garzik
-M:     jgarzik@pobox.com
+M:     Jeff Garzik <jgarzik@pobox.com>
 L:     linux-ide@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
 S:     Supported
@@ -5188,10 +4518,8 @@ F:       include/linux/ata.h
 F:     include/linux/libata.h
 
 SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER
-P:     Sathya Perla
-M:     sathyap@serverengines.com
-P:     Subbu Seetharaman
-M:     subbus@serverengines.com
+M:     Sathya Perla <sathyap@serverengines.com>
+M:     Subbu Seetharaman <subbus@serverengines.com>
 L:     netdev@vger.kernel.org
 W:     http://www.serverengines.com
 S:     Supported
@@ -5200,20 +4528,17 @@ F:      drivers/net/benet/
 SFC NETWORK DRIVER
 P:     Steve Hodgson
 P:     Ben Hutchings
-P:     Robert Stonehouse
-M:     linux-net-drivers@solarflare.com
+M:     Robert Stonehouse <linux-net-drivers@solarflare.com>
 S:     Supported
 F:     drivers/net/sfc/
 
 SGI GRU DRIVER
-P:     Jack Steiner
-M:     steiner@sgi.com
+M:     Jack Steiner <steiner@sgi.com>
 S:     Maintained
 F:     drivers/misc/sgi-gru/
 
 SGI SN-IA64 (Altix) SERIAL CONSOLE DRIVER
-P:     Pat Gefre
-M:     pfg@sgi.com
+M:     Pat Gefre <pfg@sgi.com>
 L:     linux-ia64@vger.kernel.org
 S:     Supported
 F:     Documentation/ia64/serial.txt
@@ -5221,22 +4546,19 @@ F:      drivers/serial/ioc?_serial.c
 F:     include/linux/ioc?.h
 
 SGI VISUAL WORKSTATION 320 AND 540
-P:     Andrey Panin
-M:     pazke@donpac.ru
+M:     Andrey Panin <pazke@donpac.ru>
 L:     linux-visws-devel@lists.sf.net
 W:     http://linux-visws.sf.net
 S:     Maintained for 2.6.
 F:     Documentation/sgi-visws.txt
 
 SGI XP/XPC/XPNET DRIVER
-P:     Robin Holt
-M:     holt@sgi.com
+M:     Robin Holt <holt@sgi.com>
 S:     Maintained
 F:     drivers/misc/sgi-xp/
 
 SHARP LH SUPPORT (LH7952X & LH7A40X)
-P:     Marc Singer
-M:     elf@buici.com
+M:     Marc Singer <elf@buici.com>
 W:     http://projects.buici.com/arm
 L:     linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
 S:     Maintained
@@ -5247,23 +4569,20 @@ F:      drivers/usb/gadget/lh7a40*
 F:     drivers/usb/host/ohci-lh7a40*
 
 SHPC HOTPLUG DRIVER
-P:     Kristen Carlson Accardi
-M:     kristen.c.accardi@intel.com
+M:     Kristen Carlson Accardi <kristen.c.accardi@intel.com>
 L:     linux-pci@vger.kernel.org
 S:     Supported
 F:     drivers/pci/hotplug/shpchp*
 
 SIMTEC EB110ATX (Chalice CATS)
 P:     Ben Dooks
-P:     Vincent Sanders
-M:     support@simtec.co.uk
+M:     Vincent Sanders <support@simtec.co.uk>
 W:     http://www.simtec.co.uk/products/EB110ATX/
 S:     Supported
 
 SIMTEC EB2410ITX (BAST)
 P:     Ben Dooks
-P:     Vincent Sanders
-M:     support@simtec.co.uk
+M:     Vincent Sanders <support@simtec.co.uk>
 W:     http://www.simtec.co.uk/products/EB2410ITX/
 S:     Supported
 F:     arch/arm/mach-s3c2410/
@@ -5271,31 +4590,27 @@ F:      drivers/*/*s3c2410*
 F:     drivers/*/*/*s3c2410*
 
 SIS 190 ETHERNET DRIVER
-P:     Francois Romieu
-M:     romieu@fr.zoreil.com
+M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/sis190.c
 
 SIS 900/7016 FAST ETHERNET DRIVER
-P:     Daniele Venzano
-M:     venza@brownhat.org
+M:     Daniele Venzano <venza@brownhat.org>
 W:     http://www.brownhat.org/sis900.html
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/sis900.*
 
 SIS 96X I2C/SMBUS DRIVER
-P:     Mark M. Hoffman
-M:     mhoffman@lightlink.com
+M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     Documentation/i2c/busses/i2c-sis96x
 F:     drivers/i2c/busses/i2c-sis96x.c
 
 SIS FRAMEBUFFER DRIVER
-P:     Thomas Winischhofer
-M:     thomas@winischhofer.net
+M:     Thomas Winischhofer <thomas@winischhofer.net>
 W:     http://www.winischhofer.net/linuxsisvga.shtml
 S:     Maintained
 F:     Documentation/fb/sisfb.txt
@@ -5303,70 +4618,59 @@ F:      drivers/video/sis/
 F:     include/video/sisfb.h
 
 SIS USB2VGA DRIVER
-P:     Thomas Winischhofer
-M:     thomas@winischhofer.net
+M:     Thomas Winischhofer <thomas@winischhofer.net>
 W:     http://www.winischhofer.at/linuxsisusbvga.shtml
 S:     Maintained
 F:     drivers/usb/misc/sisusbvga/
 
 SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
-P:     Stephen Hemminger
-M:     shemminger@linux-foundation.org
+M:     Stephen Hemminger <shemminger@linux-foundation.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/skge.*
 F:     drivers/net/sky2.*
 
 SLAB ALLOCATOR
-P:     Christoph Lameter
-M:     cl@linux-foundation.org
-P:     Pekka Enberg
-M:     penberg@cs.helsinki.fi
-P:     Matt Mackall
-M:     mpm@selenic.com
+M:     Christoph Lameter <cl@linux-foundation.org>
+M:     Pekka Enberg <penberg@cs.helsinki.fi>
+M:     Matt Mackall <mpm@selenic.com>
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     include/linux/sl?b*.h
 F:     mm/sl?b.c
 
 SMC91x ETHERNET DRIVER
-P:     Nicolas Pitre
-M:     nico@cam.org
+M:     Nicolas Pitre <nico@cam.org>
 S:     Maintained
 F:     drivers/net/smc91x.*
 
 SMSC47B397 HARDWARE MONITOR DRIVER
-P:     Mark M. Hoffman
-M:     mhoffman@lightlink.com
+M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/smsc47b397
 F:     drivers/hwmon/smsc47b397.c
 
 SMSC911x ETHERNET DRIVER
-P:     Steve Glendinning
-M:     steve.glendinning@smsc.com
+M:     Steve Glendinning <steve.glendinning@smsc.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     include/linux/smsc911x.h
 F:     drivers/net/smsc911x.*
 
 SMSC9420 PCI ETHERNET DRIVER
-P:     Steve Glendinning
-M:     steve.glendinning@smsc.com
+M:     Steve Glendinning <steve.glendinning@smsc.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/smsc9420.*
 
 SMX UIO Interface
-P:     Ben Nizette
-M:     bn@niasdigital.com
+M:     Ben Nizette <bn@niasdigital.com>
 S:     Maintained
 F:     drivers/uio/uio_smx.c
 
 SN-IA64 (Itanium) SUB-PLATFORM
-P:     Jes Sorensen
-M:     jes@sgi.com
+M:     Jes Sorensen <jes@sgi.com>
 L:     linux-altix@sgi.com
 L:     linux-ia64@vger.kernel.org
 W:     http://www.sgi.com/altix
@@ -5374,8 +4678,7 @@ S:        Maintained
 F:     arch/ia64/sn/
 
 SOC-CAMERA V4L2 SUBSYSTEM
-P:     Guennadi Liakhovetski
-M:     g.liakhovetski@gmx.de
+M:     Guennadi Liakhovetski <g.liakhovetski@gmx.de>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
 S:     Maintained
@@ -5383,37 +4686,32 @@ F:      include/media/v4l2*
 F:     drivers/media/video/v4l2*
 
 SOEKRIS NET48XX LED SUPPORT
-P:     Chris Boot
-M:     bootc@bootc.net
+M:     Chris Boot <bootc@bootc.net>
 S:     Maintained
 F:     drivers/leds/leds-net48xx.c
 
 SOFTWARE RAID (Multiple Disks) SUPPORT
-P:     Neil Brown
-M:     neilb@suse.de
+M:     Neil Brown <neilb@suse.de>
 L:     linux-raid@vger.kernel.org
 S:     Supported
 F:     drivers/md/
 F:     include/linux/raid/
 
 SONIC NETWORK DRIVER
-P:     Thomas Bogendoerfer
-M:     tsbogend@alpha.franken.de
+M:     Thomas Bogendoerfer <tsbogend@alpha.franken.de>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/sonic.*
 
 SONICS SILICON BACKPLANE DRIVER (SSB)
-P:     Michael Buesch
-M:     mb@bu3sch.de
+M:     Michael Buesch <mb@bu3sch.de>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/ssb/
 F:     include/linux/ssb/
 
 SONY VAIO CONTROL DEVICE DRIVER
-P:     Mattia Dongili
-M:     malattia@linux.it
+M:     Mattia Dongili <malattia@linux.it>
 L:     linux-acpi@vger.kernel.org
 W:     http://www.linux.it/~malattia/wiki/index.php/Sony_drivers
 S:     Maintained
@@ -5423,17 +4721,14 @@ F:      drivers/platform/x86/sony-laptop.c
 F:     include/linux/sony-laptop.h
 
 SONY MEMORYSTICK CARD SUPPORT
-P:     Alex Dubov
-M:     oakad@yahoo.com
+M:     Alex Dubov <oakad@yahoo.com>
 W:     http://tifmxx.berlios.de/
 S:     Maintained
 F:     drivers/memstick/host/tifm_ms.c
 
 SOUND
-P:     Jaroslav Kysela
-M:     perex@perex.cz
-P:     Takashi Iwai
-M:     tiwai@suse.de
+M:     Jaroslav Kysela <perex@perex.cz>
+M:     Takashi Iwai <tiwai@suse.de>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 W:     http://www.alsa-project.org/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
@@ -5444,10 +4739,8 @@ F:       include/sound/
 F:     sound/
 
 SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
-P:     Liam Girdwood
-M:     lrg@slimlogic.co.uk
-P:     Mark Brown
-M:     broonie@opensource.wolfsonmicro.com
+M:     Liam Girdwood <lrg@slimlogic.co.uk>
+M:     Mark Brown <broonie@opensource.wolfsonmicro.com>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound-2.6.git
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 W:     http://alsa-project.org/main/index.php/ASoC
@@ -5456,8 +4749,7 @@ F:        sound/soc/
 F:     include/sound/soc*
 
 SPARC + UltraSPARC (sparc/sparc64)
-P:     David S. Miller
-M:     davem@davemloft.net
+M:     "David S. Miller" <davem@davemloft.net>
 L:     sparclinux@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git
@@ -5465,15 +4757,13 @@ S:      Maintained
 F:     arch/sparc/
 
 SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
-P:     Roger Wolff
-M:     R.E.Wolff@BitWizard.nl
+M:     Roger Wolff <R.E.Wolff@BitWizard.nl>
 S:     Supported
 F:     Documentation/serial/specialix.txt
 F:     drivers/char/specialix*
 
 SPI SUBSYSTEM
-P:     David Brownell
-M:     dbrownell@users.sourceforge.net
+M:     David Brownell <dbrownell@users.sourceforge.net>
 L:     spi-devel-general@lists.sourceforge.net
 S:     Maintained
 F:     Documentation/spi/
@@ -5481,18 +4771,15 @@ F:      drivers/spi/
 F:     include/linux/spi/
 
 SPIDERNET NETWORK DRIVER for CELL
-P:     Ishizaki Kou
-M:     kou.ishizaki@toshiba.co.jp
-P:     Jens Osterkamp
-M:     jens@de.ibm.com
+M:     Ishizaki Kou <kou.ishizaki@toshiba.co.jp>
+M:     Jens Osterkamp <jens@de.ibm.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     Documentation/networking/spider_net.txt
 F:     drivers/net/spider_net*
 
 SPU FILE SYSTEM
-P:     Jeremy Kerr
-M:     jk@ozlabs.org
+M:     Jeremy Kerr <jk@ozlabs.org>
 L:     linuxppc-dev@ozlabs.org
 L:     cbe-oss-dev@ozlabs.org
 W:     http://www.ibm.com/developerworks/power/cell/
@@ -5501,8 +4788,7 @@ F:        Documentation/filesystems/spufs.txt
 F:     arch/powerpc/platforms/cell/spufs/
 
 SQUASHFS FILE SYSTEM
-P:     Phillip Lougher
-M:     phillip@lougher.demon.co.uk
+M:     Phillip Lougher <phillip@lougher.demon.co.uk>
 L:     squashfs-devel@lists.sourceforge.net (subscribers-only)
 W:     http://squashfs.org.uk
 S:     Maintained
@@ -5510,49 +4796,41 @@ F:      Documentation/filesystems/squashfs.txt
 F:     fs/squashfs/
 
 SRM (Alpha) environment access
-P:     Jan-Benedict Glaw
-M:     jbglaw@lug-owl.de
+M:     Jan-Benedict Glaw <jbglaw@lug-owl.de>
 S:     Maintained
 F:     arch/alpha/kernel/srm_env.c
 
 STABLE BRANCH
-P:     Greg Kroah-Hartman
-M:     greg@kroah.com
-P:     Chris Wright
-M:     chrisw@sous-sol.org
+M:     Greg Kroah-Hartman <greg@kroah.com>
+M:     Chris Wright <chrisw@sous-sol.org>
 L:     stable@kernel.org
 S:     Maintained
 
 STAGING SUBSYSTEM
-P:     Greg Kroah-Hartman
-M:     gregkh@suse.de
+M:     Greg Kroah-Hartman <gregkh@suse.de>
 T:     quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
 L:     devel@driverdev.osuosl.org
 S:     Maintained
 F:     drivers/staging/
 
 STARFIRE/DURALAN NETWORK DRIVER
-P:     Ion Badulescu
-M:     ionut@cs.columbia.edu
-S:     Maintained
+M:     Ion Badulescu <ionut@badula.org>
+S:     Odd Fixes
 F:     drivers/net/starfire*
 
 STARMODE RADIO IP (STRIP) PROTOCOL DRIVER
-W:     http://mosquitonet.Stanford.EDU/strip.html
 S:     Orphan
 F:     drivers/net/wireless/strip.c
 F:     include/linux/if_strip.h
 
 STRADIS MPEG-2 DECODER DRIVER
-P:     Nathan Laredo
-M:     laredo@gnu.org
+M:     Nathan Laredo <laredo@gnu.org>
 W:     http://www.stradis.com/
 S:     Maintained
 F:     drivers/media/video/stradis.c
 
 SUN3/3X
-P:     Sam Creasey
-M:     sammy@sammy.net
+M:     Sam Creasey <sammy@sammy.net>
 W:     http://sammy.net/sun3/
 S:     Maintained
 F:     arch/m68k/kernel/*sun3*
@@ -5560,8 +4838,7 @@ F:        arch/m68k/sun3*/
 F:     arch/m68k/include/asm/sun3*
 
 SUPERH
-P:     Paul Mundt
-M:     lethal@linux-sh.org
+M:     Paul Mundt <lethal@linux-sh.org>
 L:     linux-sh@vger.kernel.org
 W:     http://www.linux-sh.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git
@@ -5571,12 +4848,9 @@ F:       arch/sh/
 F:     drivers/sh/
 
 SUSPEND TO RAM
-P:     Len Brown
-M:     len.brown@intel.com
-P:     Pavel Machek
-M:     pavel@ucw.cz
-P:     Rafael J. Wysocki
-M:     rjw@sisk.pl
+M:     Len Brown <len.brown@intel.com>
+M:     Pavel Machek <pavel@ucw.cz>
+M:     "Rafael J. Wysocki" <rjw@sisk.pl>
 L:     linux-pm@lists.linux-foundation.org
 S:     Supported
 F:     Documentation/power/
@@ -5588,32 +4862,28 @@ F:      include/linux/freezer.h
 F:     include/linux/pm.h
 
 SVGA HANDLING
-P:     Martin Mares
-M:     mj@ucw.cz
+M:     Martin Mares <mj@ucw.cz>
 L:     linux-video@atrey.karlin.mff.cuni.cz
 S:     Maintained
 F:     Documentation/svga.txt
 F:     arch/x86/boot/video*
 
 SYSV FILESYSTEM
-P:     Christoph Hellwig
-M:     hch@infradead.org
+M:     Christoph Hellwig <hch@infradead.org>
 S:     Maintained
 F:     Documentation/filesystems/sysv-fs.txt
 F:     fs/sysv/
 F:     include/linux/sysv_fs.h
 
 TASKSTATS STATISTICS INTERFACE
-P:     Balbir Singh
-M:     balbir@linux.vnet.ibm.com
+M:     Balbir Singh <balbir@linux.vnet.ibm.com>
 S:     Maintained
 F:     Documentation/accounting/taskstats*
 F:     include/linux/taskstats*
 F:     kernel/taskstats.c
 
 TC CLASSIFIER
-P:     Jamal Hadi Salim
-M:     hadi@cyberus.ca
+M:     Jamal Hadi Salim <hadi@cyberus.ca>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     include/linux/pkt_cls.h
@@ -5621,38 +4891,31 @@ F:      include/net/pkt_cls.h
 F:     net/sched/
 
 TCP LOW PRIORITY MODULE
-P:     Wong Hoi Sing, Edison
-M:     hswong3i@gmail.com
-P:     Hung Hing Lun, Mike
-M:     hlhung3i@gmail.com
+M:     "Wong Hoi Sing, Edison" <hswong3i@gmail.com>
+M:     "Hung Hing Lun, Mike" <hlhung3i@gmail.com>
 W:     http://tcp-lp-mod.sourceforge.net/
 S:     Maintained
 F:     net/ipv4/tcp_lp.c
 
 TEHUTI ETHERNET DRIVER
-P:     Alexander Indenbaum
-M:     baum@tehutinetworks.net
-P:     Andy Gospodarek
-M:     andy@greyhouse.net
+M:     Alexander Indenbaum <baum@tehutinetworks.net>
+M:     Andy Gospodarek <andy@greyhouse.net>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/tehuti*
 
 Telecom Clock Driver for MCPL0010
-P:     Mark Gross
-M:     mark.gross@intel.com
+M:     Mark Gross <mark.gross@intel.com>
 S:     Supported
 F:     drivers/char/tlclk.c
 
 TENSILICA XTENSA PORT (xtensa)
-P:     Chris Zankel
-M:     chris@zankel.net
+M:     Chris Zankel <chris@zankel.net>
 S:     Maintained
 F:     arch/xtensa/
 
 THINKPAD ACPI EXTRAS DRIVER
-P:     Henrique de Moraes Holschuh
-M:     ibm-acpi@hmh.eng.br
+M:     Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
 L:     ibm-acpi-devel@lists.sourceforge.net
 W:     http://ibm-acpi.sourceforge.net
 W:     http://thinkwiki.org/wiki/Ibm-acpi
@@ -5661,20 +4924,22 @@ S:      Maintained
 F:     drivers/platform/x86/thinkpad_acpi.c
 
 TI FLASH MEDIA INTERFACE DRIVER
-P:     Alex Dubov
-M:     oakad@yahoo.com
+M:     Alex Dubov <oakad@yahoo.com>
 S:     Maintained
 F:     drivers/misc/tifm*
 F:     drivers/mmc/host/tifm_sd.c
 F:     include/linux/tifm.h
 
+TI TWL4030 SERIES SOC CODEC DRIVER
+M:     Peter Ujfalusi <peter.ujfalusi@nokia.com>
+L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
+S:     Maintained
+F:     sound/soc/codecs/twl4030*
+
 TIPC NETWORK LAYER
-P:     Per Liden
-M:     per.liden@ericsson.com
-P:     Jon Maloy
-M:     jon.maloy@ericsson.com
-P:     Allan Stephens
-M:     allan.stephens@windriver.com
+M:     Per Liden <per.liden@ericsson.com>
+M:     Jon Maloy <jon.maloy@ericsson.com>
+M:     Allan Stephens <allan.stephens@windriver.com>
 L:     tipc-discussion@lists.sourceforge.net
 W:     http://tipc.sourceforge.net/
 W:     http://tipc.cslab.ericsson.net/
@@ -5685,8 +4950,7 @@ F:        include/net/tipc/
 F:     net/tipc/
 
 TLAN NETWORK DRIVER
-P:     Samuel Chessman
-M:     chessman@tux.org
+M:     Samuel Chessman <chessman@tux.org>
 L:     tlan-devel@lists.sourceforge.net (subscribers-only)
 W:     http://sourceforge.net/projects/tlan/
 S:     Maintained
@@ -5694,10 +4958,8 @@ F:       Documentation/networking/tlan.txt
 F:     drivers/net/tlan.*
 
 TOMOYO SECURITY MODULE
-P:     Kentaro Takeda
-M:     takedakn@nttdata.co.jp
-P:     Tetsuo Handa
-M:     penguin-kernel@I-love.SAKURA.ne.jp
+M:     Kentaro Takeda <takedakn@nttdata.co.jp>
+M:     Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
 L:     tomoyo-users-en@lists.sourceforge.jp (subscribers-only, for developers and users in English)
 L:     tomoyo-dev@lists.sourceforge.jp (subscribers-only, for developers in Japanese)
 L:     tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese)
@@ -5711,8 +4973,7 @@ S:        Orphan
 F:     drivers/platform/x86/toshiba_acpi.c
 
 TOSHIBA SMM DRIVER
-P:     Jonathan Buzzard
-M:     jonathan@buzzard.org.uk
+M:     Jonathan Buzzard <jonathan@buzzard.org.uk>
 L:     tlinux-users@tce.toshiba-dme.co.jp
 W:     http://www.buzzard.org.uk/toshiba/
 S:     Maintained
@@ -5720,61 +4981,51 @@ F:      drivers/char/toshiba.c
 F:     include/linux/toshiba.h
 
 TMIO MMC DRIVER
-P:     Ian Molton
-M:     ian@mnementh.co.uk
+M:     Ian Molton <ian@mnementh.co.uk>
 S:     Maintained
 F:     drivers/mmc/host/tmio_mmc.*
 
 TMPFS (SHMEM FILESYSTEM)
-P:     Hugh Dickins
-M:     hugh.dickins@tiscali.co.uk
+M:     Hugh Dickins <hugh.dickins@tiscali.co.uk>
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     include/linux/shmem_fs.h
 F:     mm/shmem.c
 
 TPM DEVICE DRIVER
-P:     Debora Velarde
-M:     debora@linux.vnet.ibm.com
-P:     Rajiv Andrade
-M:     srajiv@linux.vnet.ibm.com
+M:     Debora Velarde <debora@linux.vnet.ibm.com>
+M:     Rajiv Andrade <srajiv@linux.vnet.ibm.com>
 W:     http://tpmdd.sourceforge.net
-P:     Marcel Selhorst
-M:     m.selhorst@sirrix.com
+M:     Marcel Selhorst <m.selhorst@sirrix.com>
 W:     http://www.sirrix.com
 L:     tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/char/tpm/
 
 TRIVIAL PATCHES
-P:     Jiri Kosina
-M:     trivial@kernel.org
+M:     Jiri Kosina <trivial@kernel.org>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git
 S:     Maintained
+
+TTY LAYER
+M:     Greg Kroah-Hartman <gregkh@suse.de>
+S:     Maintained
+T:     quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
 F:     drivers/char/tty_*
 F:     drivers/serial/serial_core.c
 F:     include/linux/serial_core.h
 F:     include/linux/serial.h
 F:     include/linux/tty.h
 
-TTY LAYER
-P:     Alan Cox
-M:     alan@lxorguk.ukuu.org.uk
-S:     Maintained
-T:     stgit http://zeniv.linux.org.uk/~alan/ttydev/
-
 TULIP NETWORK DRIVERS
-P:     Grant Grundler
-M:     grundler@parisc-linux.org
-P:     Kyle McMartin
-M:     kyle@mcmartin.ca
+M:     Grant Grundler <grundler@parisc-linux.org>
+M:     Kyle McMartin <kyle@mcmartin.ca>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/tulip/
 
 TUN/TAP driver
-P:     Maxim Krasnyansky
-M:     maxk@qualcomm.com
+M:     Maxim Krasnyansky <maxk@qualcomm.com>
 L:     vtun@office.satix.net
 W:     http://vtun.sourceforge.net/tun
 S:     Maintained
@@ -5782,24 +5033,20 @@ F:      Documentation/networking/tuntap.txt
 F:     arch/um/os-Linux/drivers/
 
 TURBOCHANNEL SUBSYSTEM
-P:     Maciej W. Rozycki
-M:     macro@linux-mips.org
+M:     "Maciej W. Rozycki" <macro@linux-mips.org>
 S:     Maintained
 F:     drivers/tc/
 F:     include/linux/tc.h
 
 U14-34F SCSI DRIVER
-P:     Dario Ballabio
-M:     ballabio_dario@emc.com
+M:     Dario Ballabio <ballabio_dario@emc.com>
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
 F:     drivers/scsi/u14-34f.c
 
 UBI FILE SYSTEM (UBIFS)
-P:     Artem Bityutskiy
-M:     dedekind@infradead.org
-P:     Adrian Hunter
-M:     ext-adrian.hunter@nokia.com
+M:     Artem Bityutskiy <dedekind@infradead.org>
+M:     Adrian Hunter <adrian.hunter@nokia.com>
 L:     linux-mtd@lists.infradead.org
 T:     git git://git.infradead.org/ubifs-2.6.git
 W:     http://www.linux-mtd.infradead.org/doc/ubifs.html
@@ -5808,37 +5055,32 @@ F:      Documentation/filesystems/ubifs.txt
 F:     fs/ubifs/
 
 UCLINUX (AND M68KNOMMU)
-P:     Greg Ungerer
-M:     gerg@uclinux.org
+M:     Greg Ungerer <gerg@uclinux.org>
 W:     http://www.uclinux.org/
 L:     uclinux-dev@uclinux.org  (subscribers-only)
 S:     Maintained
 F:     arch/m68knommu/
 
 UCLINUX FOR RENESAS H8/300 (H8300)
-P:     Yoshinori Sato
-M:     ysato@users.sourceforge.jp
+M:     Yoshinori Sato <ysato@users.sourceforge.jp>
 W:     http://uclinux-h8.sourceforge.jp/
 S:     Supported
 
 UDF FILESYSTEM
-P:     Jan Kara
-M:     jack@suse.cz
+M:     Jan Kara <jack@suse.cz>
 W:     http://linux-udf.sourceforge.net
 S:     Maintained
 F:     Documentation/filesystems/udf.txt
 F:     fs/udf/
 
 UFS FILESYSTEM
-P:     Evgeniy Dushistov
-M:     dushistov@mail.ru
+M:     Evgeniy Dushistov <dushistov@mail.ru>
 S:     Maintained
 F:     Documentation/filesystems/ufs.txt
 F:     fs/ufs/
 
 ULTRA-WIDEBAND (UWB) SUBSYSTEM:
-P:     David Vrabel
-M:     david.vrabel@csr.com
+M:     David Vrabel <david.vrabel@csr.com>
 L:     linux-usb@vger.kernel.org
 S:     Supported
 F:     drivers/uwb/*
@@ -5846,8 +5088,7 @@ F:        include/linux/uwb.h
 F:     include/linux/uwb/
 
 UNIFORM CDROM DRIVER
-P:     Jens Axboe
-M:     axboe@kernel.dk
+M:     Jens Axboe <axboe@kernel.dk>
 W:     http://www.kernel.dk
 S:     Maintained
 F:     Documentation/cdrom/
@@ -5855,8 +5096,7 @@ F:        drivers/cdrom/cdrom.c
 F:     include/linux/cdrom.h
 
 UNSORTED BLOCK IMAGES (UBI)
-P:     Artem Bityutskiy
-M:     dedekind@infradead.org
+M:     Artem Bityutskiy <dedekind@infradead.org>
 W:     http://www.linux-mtd.infradead.org/
 L:     linux-mtd@lists.infradead.org
 T:     git git://git.infradead.org/ubi-2.6.git
@@ -5866,23 +5106,20 @@ F:      include/linux/mtd/ubi.h
 F:     include/mtd/ubi-user.h
 
 USB ACM DRIVER
-P:     Oliver Neukum
-M:     oliver@neukum.name
+M:     Oliver Neukum <oliver@neukum.name>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     Documentation/usb/acm.txt
 F:     drivers/usb/class/cdc-acm.*
 
 USB BLOCK DRIVER (UB ub)
-P:     Pete Zaitcev
-M:     zaitcev@redhat.com
+M:     Pete Zaitcev <zaitcev@redhat.com>
 L:     linux-usb@vger.kernel.org
 S:     Supported
 F:     drivers/block/ub.c
 
 USB CDC ETHERNET DRIVER
-P:     Greg Kroah-Hartman
-M:     greg@kroah.com
+M:     Greg Kroah-Hartman <greg@kroah.com>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 W:     http://www.kroah.com/linux-usb/
@@ -5890,39 +5127,34 @@ F:      drivers/net/usb/cdc_*.c
 F:     include/linux/usb/cdc.h
 
 USB CYPRESS C67X00 DRIVER
-P:     Peter Korsgaard
-M:     jacmet@sunsite.dk
+M:     Peter Korsgaard <jacmet@sunsite.dk>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/c67x00/
 
 USB DAVICOM DM9601 DRIVER
-P:     Peter Korsgaard
-M:     jacmet@sunsite.dk
+M:     Peter Korsgaard <jacmet@sunsite.dk>
 L:     netdev@vger.kernel.org
 W:     http://www.linux-usb.org/usbnet
 S:     Maintained
 F:     drivers/net/usb/dm9601.c
 
 USB DIAMOND RIO500 DRIVER
-P:     Cesar Miquel
-M:     miquel@df.uba.ar
+M:     Cesar Miquel <miquel@df.uba.ar>
 L:     rio500-users@lists.sourceforge.net
 W:     http://rio500.sourceforge.net
 S:     Maintained
 F:     drivers/usb/misc/rio500*
 
 USB EHCI DRIVER
-P:     David Brownell
-M:     dbrownell@users.sourceforge.net
+M:     David Brownell <dbrownell@users.sourceforge.net>
 L:     linux-usb@vger.kernel.org
 S:     Odd Fixes
 F:     Documentation/usb/ehci.txt
 F:     drivers/usb/host/ehci*
 
 USB ET61X[12]51 DRIVER
-P:     Luca Risolia
-M:     luca.risolia@studio.unibo.it
+M:     Luca Risolia <luca.risolia@studio.unibo.it>
 L:     linux-usb@vger.kernel.org
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
@@ -5931,8 +5163,7 @@ S:        Maintained
 F:     drivers/media/video/et61x251/
 
 USB GADGET/PERIPHERAL SUBSYSTEM
-P:     David Brownell
-M:     dbrownell@users.sourceforge.net
+M:     David Brownell <dbrownell@users.sourceforge.net>
 L:     linux-usb@vger.kernel.org
 W:     http://www.linux-usb.org/gadget
 S:     Maintained
@@ -5940,8 +5171,7 @@ F:        drivers/usb/gadget/
 F:     include/linux/usb/gadget*
 
 USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...)
-P:     Jiri Kosina
-M:     jkosina@suse.cz
+M:     Jiri Kosina <jkosina@suse.cz>
 L:     linux-usb@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git
 S:     Maintained
@@ -5949,23 +5179,20 @@ F:      Documentation/usb/hiddev.txt
 F:     drivers/hid/usbhid/
 
 USB ISP116X DRIVER
-P:     Olav Kongas
-M:     ok@artecdesign.ee
+M:     Olav Kongas <ok@artecdesign.ee>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/host/isp116x*
 F:     include/linux/usb/isp116x.h
 
 USB KAWASAKI LSI DRIVER
-P:     Oliver Neukum
-M:     oliver@neukum.name
+M:     Oliver Neukum <oliver@neukum.name>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/serial/kl5kusb105.*
 
 USB MASS STORAGE DRIVER
-P:     Matthew Dharm
-M:     mdharm-usb@one-eyed-alien.net
+M:     Matthew Dharm <mdharm-usb@one-eyed-alien.net>
 L:     linux-usb@vger.kernel.org
 L:     usb-storage@lists.one-eyed-alien.net
 S:     Maintained
@@ -5973,31 +5200,27 @@ W:      http://www.one-eyed-alien.net/~mdharm/linux-usb/
 F:     drivers/usb/storage/
 
 USB OHCI DRIVER
-P:     David Brownell
-M:     dbrownell@users.sourceforge.net
+M:     David Brownell <dbrownell@users.sourceforge.net>
 L:     linux-usb@vger.kernel.org
 S:     Odd Fixes
 F:     Documentation/usb/ohci.txt
 F:     drivers/usb/host/ohci*
 
 USB OPTION-CARD DRIVER
-P:     Matthias Urlichs
-M:     smurf@smurf.noris.de
+M:     Matthias Urlichs <smurf@smurf.noris.de>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/serial/option.c
 
 USB OV511 DRIVER
-P:     Mark McClelland
-M:     mmcclell@bigfoot.com
+M:     Mark McClelland <mmcclell@bigfoot.com>
 L:     linux-usb@vger.kernel.org
 W:     http://alpha.dyndns.org/ov511/
 S:     Maintained
 F:     drivers/media/video/ov511.*
 
 USB PEGASUS DRIVER
-P:     Petko Manolov
-M:     petkan@users.sourceforge.net
+M:     Petko Manolov <petkan@users.sourceforge.net>
 L:     linux-usb@vger.kernel.org
 L:     netdev@vger.kernel.org
 W:     http://pegasus2.sourceforge.net/
@@ -6005,15 +5228,13 @@ S:      Maintained
 F:     drivers/net/usb/pegasus.*
 
 USB PRINTER DRIVER (usblp)
-P:     Pete Zaitcev
-M:     zaitcev@redhat.com
+M:     Pete Zaitcev <zaitcev@redhat.com>
 L:     linux-usb@vger.kernel.org
 S:     Supported
 F:     drivers/usb/class/usblp.c
 
 USB RTL8150 DRIVER
-P:     Petko Manolov
-M:     petkan@users.sourceforge.net
+M:     Petko Manolov <petkan@users.sourceforge.net>
 L:     linux-usb@vger.kernel.org
 L:     netdev@vger.kernel.org
 W:     http://pegasus2.sourceforge.net/
@@ -6021,8 +5242,7 @@ S:        Maintained
 F:     drivers/net/usb/rtl8150.c
 
 USB SE401 DRIVER
-P:     Jeroen Vreeken
-M:     pe1rxq@amsat.org
+M:     Jeroen Vreeken <pe1rxq@amsat.org>
 L:     linux-usb@vger.kernel.org
 W:     http://www.chello.nl/~j.vreeken/se401/
 S:     Maintained
@@ -6030,15 +5250,13 @@ F:      Documentation/video4linux/se401.txt
 F:     drivers/media/video/se401.*
 
 USB SERIAL BELKIN F5U103 DRIVER
-P:     William Greathouse
-M:     wgreathouse@smva.com
+M:     William Greathouse <wgreathouse@smva.com>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/serial/belkin_sa.*
 
 USB SERIAL CYPRESS M8 DRIVER
-P:     Lonnie Mendez
-M:     dignome@gmail.com
+M:     Lonnie Mendez <dignome@gmail.com>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 W:     http://geocities.com/i0xox0i
@@ -6046,23 +5264,20 @@ W:      http://firstlight.net/cvs
 F:     drivers/usb/serial/cypress_m8.*
 
 USB SERIAL CYBERJACK DRIVER
-P:     Matthias Bruestle and Harald Welte
-M:     support@reiner-sct.com
+M:     Matthias Bruestle and Harald Welte <support@reiner-sct.com>
 W:     http://www.reiner-sct.de/support/treiber_cyberjack.php
 S:     Maintained
 F:     drivers/usb/serial/cyberjack.c
 
 USB SERIAL DIGI ACCELEPORT DRIVER
-P:     Peter Berger and Al Borchers
-M:     pberger@brimson.com
-M:     alborchers@steinerpoint.com
+M:     Peter Berger <pberger@brimson.com>
+M:     Al Borchers <alborchers@steinerpoint.com>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/serial/digi_acceleport.c
 
 USB SERIAL DRIVER
-P:     Greg Kroah-Hartman
-M:     gregkh@suse.de
+M:     Greg Kroah-Hartman <gregkh@suse.de>
 L:     linux-usb@vger.kernel.org
 S:     Supported
 F:     Documentation/usb/usb-serial.txt
@@ -6071,38 +5286,33 @@ F:      drivers/usb/serial/usb-serial.c
 F:     include/linux/usb/serial.h
 
 USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER
-P:     Gary Brubaker
-M:     xavyer@ix.netcom.com
+M:     Gary Brubaker <xavyer@ix.netcom.com>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/serial/empeg.c
 
 USB SERIAL KEYSPAN DRIVER
-P:     Greg Kroah-Hartman
-M:     greg@kroah.com
+M:     Greg Kroah-Hartman <greg@kroah.com>
 L:     linux-usb@vger.kernel.org
 W:     http://www.kroah.com/linux/
 S:     Maintained
 F:     drivers/usb/serial/*keyspan*
 
 USB SERIAL WHITEHEAT DRIVER
-P:     Support Department
-M:     support@connecttech.com
+M:     Support Department <support@connecttech.com>
 L:     linux-usb@vger.kernel.org
 W:     http://www.connecttech.com
 S:     Supported
 F:     drivers/usb/serial/whiteheat*
 
 USB SMSC95XX ETHERNET DRIVER
-P:     Steve Glendinning
-M:     steve.glendinning@smsc.com
+M:     Steve Glendinning <steve.glendinning@smsc.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/usb/smsc95xx.*
 
 USB SN9C1xx DRIVER
-P:     Luca Risolia
-M:     luca.risolia@studio.unibo.it
+M:     Luca Risolia <luca.risolia@studio.unibo.it>
 L:     linux-usb@vger.kernel.org
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
@@ -6112,8 +5322,7 @@ F:        Documentation/video4linux/sn9c102.txt
 F:     drivers/media/video/sn9c102/
 
 USB SUBSYSTEM
-P:     Greg Kroah-Hartman
-M:     gregkh@suse.de
+M:     Greg Kroah-Hartman <gregkh@suse.de>
 L:     linux-usb@vger.kernel.org
 W:     http://www.linux-usb.org
 T:     quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
@@ -6125,15 +5334,13 @@ F:      include/linux/usb.h
 F:     include/linux/usb/
 
 USB UHCI DRIVER
-P:     Alan Stern
-M:     stern@rowland.harvard.edu
+M:     Alan Stern <stern@rowland.harvard.edu>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/host/uhci*
 
 USB "USBNET" DRIVER FRAMEWORK
-P:     David Brownell
-M:     dbrownell@users.sourceforge.net
+M:     David Brownell <dbrownell@users.sourceforge.net>
 L:     netdev@vger.kernel.org
 W:     http://www.linux-usb.org/usbnet
 S:     Maintained
@@ -6141,8 +5348,7 @@ F:        drivers/net/usb/usbnet.c
 F:     include/linux/usb/usbnet.h
 
 USB VIDEO CLASS
-P:     Laurent Pinchart
-M:     laurent.pinchart@skynet.be
+M:     Laurent Pinchart <laurent.pinchart@skynet.be>
 L:     linux-uvc-devel@lists.berlios.de (subscribers-only)
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
@@ -6151,8 +5357,7 @@ S:        Maintained
 F:     drivers/media/video/uvc/
 
 USB W996[87]CF DRIVER
-P:     Luca Risolia
-M:     luca.risolia@studio.unibo.it
+M:     Luca Risolia <luca.risolia@studio.unibo.it>
 L:     linux-usb@vger.kernel.org
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
@@ -6162,21 +5367,18 @@ F:      Documentation/video4linux/w9968cf.txt
 F:     drivers/media/video/w996*
 
 USB WIRELESS RNDIS DRIVER (rndis_wlan)
-P:     Jussi Kivilinna
-M:     jussi.kivilinna@mbnet.fi
+M:     Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
 F:     drivers/net/wireless/rndis_wlan.c
 
 USB XHCI DRIVER
-P:     Sarah Sharp
-M:     sarah.a.sharp@intel.com
+M:     Sarah Sharp <sarah.a.sharp@intel.com>
 L:     linux-usb@vger.kernel.org
 S:     Supported
 
 USB ZC0301 DRIVER
-P:     Luca Risolia
-M:     luca.risolia@studio.unibo.it
+M:     Luca Risolia <luca.risolia@studio.unibo.it>
 L:     linux-usb@vger.kernel.org
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
@@ -6186,16 +5388,14 @@ F:      Documentation/video4linux/zc0301.txt
 F:     drivers/media/video/zc0301/
 
 USB ZD1201 DRIVER
-P:     Jeroen Vreeken
-M:     pe1rxq@amsat.org
+M:     Jeroen Vreeken <pe1rxq@amsat.org>
 L:     linux-usb@vger.kernel.org
 W:     http://linux-lc100020.sourceforge.net
 S:     Maintained
 F:     drivers/net/wireless/zd1201.*
 
 USB ZR364XX DRIVER
-P:     Antoine Jacquet
-M:     royale@zerezo.com
+M:     Antoine Jacquet <royale@zerezo.com>
 L:     linux-usb@vger.kernel.org
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
@@ -6205,8 +5405,7 @@ F:        Documentation/video4linux/zr364xx.txt
 F:     drivers/media/video/zr364xx.c
 
 USER-MODE LINUX (UML)
-P:     Jeff Dike
-M:     jdike@addtoit.com
+M:     Jeff Dike <jdike@addtoit.com>
 L:     user-mode-linux-devel@lists.sourceforge.net
 L:     user-mode-linux-user@lists.sourceforge.net
 W:     http://user-mode-linux.sourceforge.net
@@ -6217,26 +5416,22 @@ F:      fs/hostfs/
 F:     fs/hppfs/
 
 USERSPACE I/O (UIO)
-P:     Hans J. Koch
-M:     hjk@linutronix.de
-P:     Greg Kroah-Hartman
-M:     gregkh@suse.de
+M:     "Hans J. Koch" <hjk@linutronix.de>
+M:     Greg Kroah-Hartman <gregkh@suse.de>
 S:     Maintained
 F:     Documentation/DocBook/uio-howto.tmpl
 F:     drivers/uio/
 F:     include/linux/uio*.h
 
 UTIL-LINUX-NG PACKAGE
-P:     Karel Zak
-M:     kzak@redhat.com
+M:     Karel Zak <kzak@redhat.com>
 L:     util-linux-ng@vger.kernel.org
 W:     http://kernel.org/~kzak/util-linux-ng/
 T:     git git://git.kernel.org/pub/scm/utils/util-linux-ng/util-linux-ng.git
 S:     Maintained
 
 UVESAFB DRIVER
-P:     Michal Januszewski
-M:     spock@gentoo.org
+M:     Michal Januszewski <spock@gentoo.org>
 L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:     http://dev.gentoo.org/~spock/projects/uvesafb/
 S:     Maintained
@@ -6244,53 +5439,44 @@ F:      Documentation/fb/uvesafb.txt
 F:     drivers/video/uvesafb.*
 
 VFAT/FAT/MSDOS FILESYSTEM
-P:     OGAWA Hirofumi
-M:     hirofumi@mail.parknet.co.jp
+M:     OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
 S:     Maintained
 F:     Documentation/filesystems/vfat.txt
 F:     fs/fat/
 
 VIA RHINE NETWORK DRIVER
-P:     Roger Luethi
-M:     rl@hellgate.ch
+M:     Roger Luethi <rl@hellgate.ch>
 S:     Maintained
 F:     drivers/net/via-rhine.c
 
 VIAPRO SMBUS DRIVER
-P:     Jean Delvare
-M:     khali@linux-fr.org
+M:     Jean Delvare <khali@linux-fr.org>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     Documentation/i2c/busses/i2c-viapro
 F:     drivers/i2c/busses/i2c-viapro.c
 
 VIA SD/MMC CARD CONTROLLER DRIVER
-P:     Joseph Chan
-M:     JosephChan@via.com.tw
-P:     Harald Welte
-M:     HaraldWelte@viatech.com
+M:     Joseph Chan <JosephChan@via.com.tw>
+M:     Harald Welte <HaraldWelte@viatech.com>
 S:     Maintained
 F:     drivers/mmc/host/via-sdmmc.c
 
 VIA UNICHROME(PRO)/CHROME9 FRAMEBUFFER DRIVER
-P:     Joseph Chan
-M:     JosephChan@via.com.tw
-P:     Scott Fang
-M:     ScottFang@viatech.com.cn
+M:     Joseph Chan <JosephChan@via.com.tw>
+M:     Scott Fang <ScottFang@viatech.com.cn>
 L:     linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/video/via/
 
 VIA VELOCITY NETWORK DRIVER
-P:     Francois Romieu
-M:     romieu@fr.zoreil.com
+M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/via-velocity.*
 
 VLAN (802.1Q)
-P:     Patrick McHardy
-M:     kaber@trash.net
+M:     Patrick McHardy <kaber@trash.net>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/macvlan.c
@@ -6298,18 +5484,15 @@ F:      include/linux/if_*vlan.h
 F:     net/8021q/
 
 VLYNQ BUS
-P:     Florian Fainelli
-M:     florian@openwrt.org
+M:     Florian Fainelli <florian@openwrt.org>
 L:     openwrt-devel@lists.openwrt.org
 S:     Maintained
 F:     drivers/vlynq/vlynq.c
 F:     include/linux/vlynq.h
 
 VOLTAGE AND CURRENT REGULATOR FRAMEWORK
-P:     Liam Girdwood
-M:     lrg@slimlogic.co.uk
-P:     Mark Brown
-M:     broonie@opensource.wolfsonmicro.com
+M:     Liam Girdwood <lrg@slimlogic.co.uk>
+M:     Mark Brown <broonie@opensource.wolfsonmicro.com>
 W:     http://opensource.wolfsonmicro.com/node/15
 W:     http://www.slimlogic.co.uk/?p=48
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6.git
@@ -6318,52 +5501,45 @@ F:      drivers/regulator/
 F:     include/linux/regulator/
 
 VT1211 HARDWARE MONITOR DRIVER
-P:     Juerg Haefliger
-M:     juergh@gmail.com
+M:     Juerg Haefliger <juergh@gmail.com>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/vt1211
 F:     drivers/hwmon/vt1211.c
 
 VT8231 HARDWARE MONITOR DRIVER
-P:     Roger Lucas
-M:     vt8231@hiddenengine.co.uk
+M:     Roger Lucas <vt8231@hiddenengine.co.uk>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     drivers/hwmon/vt8231.c
 
 W1 DALLAS'S 1-WIRE BUS
-P:     Evgeniy Polyakov
-M:     johnpol@2ka.mipt.ru
+M:     Evgeniy Polyakov <johnpol@2ka.mipt.ru>
 S:     Maintained
 F:     Documentation/w1/
 F:     drivers/w1/
 
 W83791D HARDWARE MONITORING DRIVER
-P:     Marc Hulsman
-M:     m.hulsman@tudelft.nl
+M:     Marc Hulsman <m.hulsman@tudelft.nl>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/w83791d
 F:     drivers/hwmon/w83791d.c
 
 W83793 HARDWARE MONITORING DRIVER
-P:     Rudolf Marek
-M:     r.marek@assembler.cz
+M:     Rudolf Marek <r.marek@assembler.cz>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/w83793
 F:     drivers/hwmon/w83793.c
 
 W83L51xD SD/MMC CARD INTERFACE DRIVER
-P:     Pierre Ossman
-M:     pierre@ossman.eu
+M:     Pierre Ossman <pierre@ossman.eu>
 S:     Maintained
 F:     drivers/mmc/host/wbsd.*
 
 WATCHDOG DEVICE DRIVERS
-P:     Wim Van Sebroeck
-M:     wim@iguana.be
+M:     Wim Van Sebroeck <wim@iguana.be>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog.git
 S:     Maintained
 F:     Documentation/watchdog/
@@ -6371,8 +5547,7 @@ F:        drivers/watchdog/
 F:     include/linux/watchdog.h
 
 WAVELAN NETWORK DRIVER & WIRELESS EXTENSIONS
-P:     Jean Tourrilhes
-M:     jt@hpl.hp.com
+M:     Jean Tourrilhes <jt@hpl.hp.com>
 L:     linux-wireless@vger.kernel.org
 W:     http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
 S:     Maintained
@@ -6380,46 +5555,39 @@ F:      Documentation/networking/wavelan.txt
 F:     drivers/net/wireless/wavelan*
 
 WD7000 SCSI DRIVER
-P:     Miroslav Zagorac
-M:     zaga@fly.cc.fer.hr
+M:     Miroslav Zagorac <zaga@fly.cc.fer.hr>
 L:     linux-scsi@vger.kernel.org
 S:     Maintained
 F:     drivers/scsi/wd7000.c
 
 WIMAX STACK
-P:     Inaky Perez-Gonzalez
-M:     inaky.perez-gonzalez@intel.com
+M:     Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
 M:     linux-wimax@intel.com
 L:     wimax@linuxwimax.org
 S:     Supported
 W:     http://linuxwimax.org
 
 WIMEDIA LLC PROTOCOL (WLP) SUBSYSTEM
-P:     David Vrabel
-M:     david.vrabel@csr.com
+M:     David Vrabel <david.vrabel@csr.com>
 S:     Maintained
 F:     include/linux/wlp.h
 F:     drivers/uwb/wlp/
 
 WISTRON LAPTOP BUTTON DRIVER
-P:     Miloslav Trmac
-M:     mitr@volny.cz
+M:     Miloslav Trmac <mitr@volny.cz>
 S:     Maintained
 F:     drivers/input/misc/wistron_btns.c
 
 WL3501 WIRELESS PCMCIA CARD DRIVER
-P:     Arnaldo Carvalho de Melo
-M:     acme@ghostprotocols.net
+M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 L:     linux-wireless@vger.kernel.org
 W:     http://oops.ghostprotocols.net:81/blog
 S:     Maintained
 F:     drivers/net/wireless/wl3501*
 
 WM97XX TOUCHSCREEN DRIVERS
-P:     Mark Brown
-M:     broonie@opensource.wolfsonmicro.com
-P:     Liam Girdwood
-M:     lrg@slimlogic.co.uk
+M:     Mark Brown <broonie@opensource.wolfsonmicro.com>
+M:     Liam Girdwood <lrg@slimlogic.co.uk>
 L:     linux-input@vger.kernel.org
 T:     git git://opensource.wolfsonmicro.com/linux-2.6-touch
 W:     http://opensource.wolfsonmicro.com/node/7
@@ -6428,8 +5596,7 @@ F:        drivers/input/touchscreen/*wm97*
 F:     include/linux/wm97xx.h
 
 X.25 NETWORK LAYER
-P:     Henner Eisen
-M:     eis@baty.hanse.de
+M:     Henner Eisen <eis@baty.hanse.de>
 L:     linux-x25@vger.kernel.org
 S:     Maintained
 F:     Documentation/networking/x25*
@@ -6437,12 +5604,9 @@ F:       include/net/x25*
 F:     net/x25/
 
 X86 ARCHITECTURE (32-BIT AND 64-BIT)
-P:     Thomas Gleixner
-M:     tglx@linutronix.de
-P:     Ingo Molnar
-M:     mingo@redhat.com
-P:     H. Peter Anvin
-M:     hpa@zytor.com
+M:     Thomas Gleixner <tglx@linutronix.de>
+M:     Ingo Molnar <mingo@redhat.com>
+M:     "H. Peter Anvin" <hpa@zytor.com>
 M:     x86@kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
 S:     Maintained
@@ -6450,10 +5614,8 @@ F:       Documentation/x86/
 F:     arch/x86/
 
 XEN HYPERVISOR INTERFACE
-P:     Jeremy Fitzhardinge
-M:     jeremy@xensource.com
-P:     Chris Wright
-M:     chrisw@sous-sol.org
+M:     Jeremy Fitzhardinge <jeremy@xensource.com>
+M:     Chris Wright <chrisw@sous-sol.org>
 L:     virtualization@lists.osdl.org
 L:     xen-devel@lists.xensource.com
 S:     Supported
@@ -6465,8 +5627,7 @@ F:        include/xen/
 
 XFS FILESYSTEM
 P:     Silicon Graphics Inc
-P:     Felix Blyakher
-M:     felixb@sgi.com
+M:     Felix Blyakher <felixb@sgi.com>
 M:     xfs-masters@oss.sgi.com
 L:     xfs@oss.sgi.com
 W:     http://oss.sgi.com/projects/xfs
@@ -6476,38 +5637,33 @@ F:      Documentation/filesystems/xfs.txt
 F:     fs/xfs/
 
 XILINX SYSTEMACE DRIVER
-P:     Grant Likely
-M:     grant.likely@secretlab.ca
+M:     Grant Likely <grant.likely@secretlab.ca>
 W:     http://www.secretlab.ca/
 S:     Maintained
 F:     drivers/block/xsysace.c
 
 XILINX UARTLITE SERIAL DRIVER
-P:     Peter Korsgaard
-M:     jacmet@sunsite.dk
+M:     Peter Korsgaard <jacmet@sunsite.dk>
 L:     linux-serial@vger.kernel.org
 S:     Maintained
 F:     drivers/serial/uartlite.c
 
 YAM DRIVER FOR AX.25
-P:     Jean-Paul Roubelat
-M:     jpr@f6fbb.org
+M:     Jean-Paul Roubelat <jpr@f6fbb.org>
 L:     linux-hams@vger.kernel.org
 S:     Maintained
 F:     drivers/net/hamradio/yam*
 F:     include/linux/yam.h
 
 YEALINK PHONE DRIVER
-P:     Henk Vergonet
-M:     Henk.Vergonet@gmail.com
+M:     Henk Vergonet <Henk.Vergonet@gmail.com>
 L:     usbb2k-api-dev@nongnu.org
 S:     Maintained
 F:     Documentation/input/yealink.txt
 F:     drivers/input/misc/yealink.*
 
 Z8530 DRIVER FOR AX.25
-P:     Joerg Reuter
-M:     jreuter@yaina.de
+M:     Joerg Reuter <jreuter@yaina.de>
 W:     http://yaina.de/jreuter/
 W:     http://www.qsl.net/dl1bke/
 L:     linux-hams@vger.kernel.org
@@ -6517,10 +5673,8 @@ F:       drivers/net/hamradio/*scc.c
 F:     drivers/net/hamradio/z8530.h
 
 ZD1211RW WIRELESS DRIVER
-P:     Daniel Drake
-M:     dsd@gentoo.org
-P:     Ulrich Kunitz
-M:     kune@deine-taler.de
+M:     Daniel Drake <dsd@gentoo.org>
+M:     Ulrich Kunitz <kune@deine-taler.de>
 W:     http://zd1211.ath.cx/wiki/DriverRewrite
 L:     linux-wireless@vger.kernel.org
 L:     zd1211-devs@lists.sourceforge.net (subscribers-only)
@@ -6536,14 +5690,12 @@ S:      Odd Fixes
 F:     drivers/media/video/zoran/
 
 ZS DECSTATION Z85C30 SERIAL DRIVER
-P:     Maciej W. Rozycki
-M:     macro@linux-mips.org
+M:     "Maciej W. Rozycki" <macro@linux-mips.org>
 S:     Maintained
 F:     drivers/serial/zs.*
 
 THE REST
-P:     Linus Torvalds
-M:     torvalds@linux-foundation.org
+M:     Linus Torvalds <torvalds@linux-foundation.org>
 L:     linux-kernel@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
 S:     Buried alive in reporters
index d1216fea0c922bf70de0203d3a51124a825c98c4..60de4ef312547da0264a363c87d0165626a6db8c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 31
-EXTRAVERSION = -rc1
+EXTRAVERSION =
 NAME = Man-Eating Seals of Antiquity
 
 # *DOCUMENTATION*
@@ -140,15 +140,13 @@ _all: modules
 endif
 
 srctree                := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR))
-TOPDIR         := $(srctree)
-# FIXME - TOPDIR is obsolete, use srctree/objtree
 objtree                := $(CURDIR)
 src            := $(srctree)
 obj            := $(objtree)
 
 VPATH          := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
 
-export srctree objtree VPATH TOPDIR
+export srctree objtree VPATH
 
 
 # SUBARCH tells the usermode build what the underlying arch is.  That is set
@@ -344,7 +342,9 @@ KBUILD_CPPFLAGS := -D__KERNEL__
 
 KBUILD_CFLAGS   := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
                   -fno-strict-aliasing -fno-common \
-                  -Werror-implicit-function-declaration
+                  -Werror-implicit-function-declaration \
+                  -Wno-format-security \
+                  -fno-delete-null-pointer-checks
 KBUILD_AFLAGS   := -D__ASSEMBLY__
 
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
@@ -566,7 +566,7 @@ KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
 KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,)
 
 # disable invalid "can't wrap" optimizations for signed / pointers
-KBUILD_CFLAGS  += $(call cc-option,-fwrapv)
+KBUILD_CFLAGS  += $(call cc-option,-fno-strict-overflow)
 
 # revert to pre-gcc-4.4 behaviour of .eh_frame
 KBUILD_CFLAGS  += $(call cc-option,-fno-dwarf2-cfi-asm)
index ab0c56630a8cb5924813a196b1b2be763f51d5b6..55a6074ccbb715d99b642fa510d3c993121f453d 100644 (file)
@@ -15,7 +15,10 @@ worry too much about getting the wrong person. If you are unsure send it
 to the person responsible for the code relevant to what you were doing.
 If it occurs repeatably try and describe how to recreate it. That is
 worth even more than the oops itself.  The list of maintainers and
-mailing lists is in the MAINTAINERS file in this directory.
+mailing lists is in the MAINTAINERS file in this directory.  If you
+know the file name that causes the problem you can use the following
+command in this directory to find some of the maintainers of that file:
+     perl scripts/get_maintainer.pl -f <filename>
 
       If it is a security bug, please copy the Security Contact listed
 in the MAINTAINERS file.  They can help coordinate bugfix and disclosure.
index 06c5c7a4afd3f6617440cdbcf669d70d591a0d44..b663f1f10b6a1011c7645580300951b977029acd 100644 (file)
@@ -30,7 +30,7 @@ extern unsigned long __per_cpu_offset[NR_CPUS];
 
 #ifndef MODULE
 #define SHIFT_PERCPU_PTR(var, offset) RELOC_HIDE(&per_cpu_var(var), (offset))
-#define PER_CPU_ATTRIBUTES
+#define PER_CPU_DEF_ATTRIBUTES
 #else
 /*
  * To calculate addresses of locally defined variables, GCC uses 32-bit
@@ -49,7 +49,7 @@ extern unsigned long __per_cpu_offset[NR_CPUS];
                : "=&r"(__ptr), "=&r"(tmp_gp));         \
        (typeof(&per_cpu_var(var)))(__ptr + (offset)); })
 
-#define PER_CPU_ATTRIBUTES     __used
+#define PER_CPU_DEF_ATTRIBUTES __used
 
 #endif /* MODULE */
 
@@ -71,7 +71,7 @@ extern unsigned long __per_cpu_offset[NR_CPUS];
 #define __get_cpu_var(var)             per_cpu_var(var)
 #define __raw_get_cpu_var(var)         per_cpu_var(var)
 
-#define PER_CPU_ATTRIBUTES
+#define PER_CPU_DEF_ATTRIBUTES
 
 #endif /* SMP */
 
index d069526bd7673f9ead6eb33e825782ea690e2fb0..60c83abfde7027832e0e7609ac7e032accb66386 100644 (file)
@@ -37,6 +37,7 @@ struct thread_info {
        .task           = &tsk,                 \
        .exec_domain    = &default_exec_domain, \
        .addr_limit     = KERNEL_DS,            \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .restart_block = {                      \
                .fn = do_no_restart_syscall,    \
        },                                      \
index c13636575fbab4fb14c17b75d53058b0f9181e1c..42866759f3fabd022c07c431a01bc9f45f6d91f4 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <asm-generic/tlb.h>
 
-#define __pte_free_tlb(tlb, pte)                       pte_free((tlb)->mm, pte)
-#define __pmd_free_tlb(tlb, pmd)                       pmd_free((tlb)->mm, pmd)
+#define __pte_free_tlb(tlb, pte, address)              pte_free((tlb)->mm, pte)
+#define __pmd_free_tlb(tlb, pmd, address)              pmd_free((tlb)->mm, pmd)
  
 #endif
index 1e9ad52c460ec293aa70f9cbc5bb3094adc08d74..e072041d19f8ba97f15ee6922ee5955e4db36930 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index a71fd941ade7cdd82610b62a1109a6dc04615907..a89e4734b8f0b6a966b7dd2bba0d1af32896b467 100644 (file)
@@ -99,14 +99,6 @@ config DEBUG_CLPS711X_UART2
          output to the second serial port on these devices.  Saying N will
          cause the debug messages to appear on the first serial port.
 
-config DEBUG_S3C_PORT
-       depends on DEBUG_LL && PLAT_S3C
-       bool "Kernel low-level debugging messages via S3C UART"
-       help
-         Say Y here if you want debug print routines to go to one of the
-         S3C internal UARTs. The chosen UART must have been configured
-         before it is used.
-
 config DEBUG_S3C_UART
        depends on PLAT_S3C
        int "S3C UART to use for low-level debug"
index 9e6e512f0117df5227142b06299747647f2db72d..17153b54613b4c5948db2f66b1cbf7a0716b2309 100644 (file)
@@ -29,7 +29,6 @@ unsigned int __machine_arch_type;
 
 static void putstr(const char *ptr);
 
-#include <linux/compiler.h>
 #include <mach/uncompress.h>
 
 #ifdef CONFIG_DEBUG_ICEDCC
index f37afd9422f3b1905884f525b58b19fcc4dd65f9..aae5bc01acc80d20d1f4cfe46c048d78455a67cb 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/err.h>
 #include <linux/string.h>
 #include <linux/mutex.h>
+#include <linux/clk.h>
 
 #include <asm/clkdev.h>
 #include <mach/clkdev.h>
index 8e74c66f239db6bec52dd8f88ffa1a8c44603b55..605a8462f17263cb2547d16dcdd1e73f37d3034a 100644 (file)
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-rc2
-# Sun Aug 14 19:26:59 2005
+# Linux kernel version: 2.6.30-rc8
+# Wed Jun  3 13:52:33 2009
 #
 CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_MMU=y
-CONFIG_UID16=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
-# Code maturity level options
+# General setup
 #
-# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
+CONFIG_EXPERIMENTAL=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 # CONFIG_SWAP is not set
-# CONFIG_SYSVIPC is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+CONFIG_AUDIT=y
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_HOTPLUG=y
-# CONFIG_KOBJECT_UEVENT is not set
-# CONFIG_IKCONFIG is not set
+CONFIG_ANON_INODES=y
 # CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+# CONFIG_STRIP_ASM_SYMS 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_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=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_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_TRACEPOINTS=y
+CONFIG_MARKERS=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
-# Loadable module support
+# IO Schedulers
 #
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_FREEZER is not set
 
 #
 # System Type
 #
-# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+CONFIG_ARCH_AT91=y
 # 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_GEMINI 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_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
 # CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_AAEC2000 is not set
-CONFIG_ARCH_AT91=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# Atmel AT91 System-on-Chip
+#
 CONFIG_ARCH_AT91RM9200=y
+# CONFIG_ARCH_AT91SAM9260 is not set
+# CONFIG_ARCH_AT91SAM9261 is not set
+# CONFIG_ARCH_AT91SAM9263 is not set
+# CONFIG_ARCH_AT91SAM9RL is not set
+# CONFIG_ARCH_AT91SAM9G20 is not set
+# CONFIG_ARCH_AT91CAP9 is not set
+# CONFIG_ARCH_AT91X40 is not set
+CONFIG_AT91_PMC_UNIT=y
 
 #
-# AT91RM9200 Implementations
+# AT91RM9200 Board Type
 #
+# CONFIG_MACH_ONEARM is not set
 # CONFIG_ARCH_AT91RM9200DK is not set
 # CONFIG_MACH_AT91RM9200EK is not set
 # CONFIG_MACH_CSB337 is not set
 # CONFIG_MACH_CSB637 is not set
 # CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_ATEB9200 is not set
 CONFIG_MACH_KB9200=y
+# CONFIG_MACH_PICOTUX2XX is not set
+# CONFIG_MACH_KAFA is not set
+# CONFIG_MACH_ECBAT91 is not set
+# CONFIG_MACH_YL9200 is not set
+
+#
+# AT91 Board Options
+#
+
+#
+# AT91 Feature Selections
+#
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+CONFIG_AT91_TIMER_HZ=128
+CONFIG_AT91_EARLY_DBGU=y
+# CONFIG_AT91_EARLY_USART0 is not set
+# CONFIG_AT91_EARLY_USART1 is not set
+# CONFIG_AT91_EARLY_USART2 is not set
+# CONFIG_AT91_EARLY_USART3 is not set
+# CONFIG_AT91_EARLY_USART4 is not set
+# CONFIG_AT91_EARLY_USART5 is not set
 
 #
 # Processor Type
 #
 CONFIG_CPU_32=y
 CONFIG_CPU_ARM920T=y
-CONFIG_CPU_32v4=y
+CONFIG_CPU_32v4T=y
 CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_PABRT_NOIFAR=y
 CONFIG_CPU_CACHE_V4WT=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_COPY_V4WB=y
 CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
 
 #
 # Processor Features
@@ -112,23 +249,48 @@ CONFIG_ARM_THUMB=y
 # CONFIG_CPU_ICACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_OUTER_CACHE is not set
 
 #
 # Bus support
 #
-CONFIG_ISA_DMA_API=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 # CONFIG_PCCARD is not set
 
 #
 # Kernel Features
 #
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=128
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_HAS_HOLES_MEMORYMODEL is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM 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_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
 # CONFIG_LEDS is not set
 CONFIG_ALIGNMENT_TRAP=y
 
@@ -137,8 +299,16 @@ CONFIG_ALIGNMENT_TRAP=y
 #
 CONFIG_ZBOOT_ROM_TEXT=0x10000000
 CONFIG_ZBOOT_ROM_BSS=0x20040000
-CONFIG_ZBOOT_ROM=y
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933"
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_CMDLINE="noinitrd root=/dev/mtdblock0 rootfstype=jffs2 mem=64M"
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
 
 #
 # Floating point emulation
@@ -149,74 +319,251 @@ CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933"
 #
 CONFIG_FPE_NWFPE=y
 # CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
 
 #
 # Userspace binary formats
 #
 CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
 CONFIG_BINFMT_MISC=y
-# CONFIG_ARTHUR is not set
 
 #
 # Power management options
 #
 # CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
 
 #
-# Device Drivers
+# Networking options
 #
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER 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 is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
-# Generic Driver Options
+# Network testing
 #
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-CONFIG_DEBUG_DRIVER=y
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
-# Memory Technology Devices (MTD)
+# Device Drivers
 #
-# CONFIG_MTD is not set
 
 #
-# Parallel port support
+# Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=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
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS 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
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_ATMEL=y
+# CONFIG_MTD_NAND_ATMEL_ECC_HW is not set
+CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y
+# CONFIG_MTD_NAND_ATMEL_ECC_NONE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+CONFIG_MTD_UBI_GLUEBI=y
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
 # CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=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_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_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_ATMEL_TCLIB=y
+CONFIG_ATMEL_TCB_CLKSRC=y
+CONFIG_ATMEL_TCB_CLKSRC_BLOCK=0
+CONFIG_ATMEL_SSC=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
 
 #
-# IO Schedulers
+# EEPROM support
 #
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -232,145 +579,87 @@ CONFIG_CHR_DEV_SG=y
 #
 # 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
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
-# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_SPI_ATTRS=m
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_DEBUG is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
 # CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-
-#
-# I2O device support
-#
-
-#
-# Networking support
-#
-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=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER 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
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE 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_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 CONFIG_ARM_AT91_ETHER=y
+# CONFIG_AX88796 is not set
 # CONFIG_SMC91X is not set
 # CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
 
 #
-# Ethernet (1000 Mbit)
-#
-
-#
-# Ethernet (10000 Mbit)
-#
-
-#
-# Token Ring devices
+# Wireless LAN
 #
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Enable WiMAX (Networking options) to see the WiMAX drivers
 #
-# CONFIG_NET_RADIO is not set
 
 #
-# Wan interfaces
+# 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_WAN is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
-
-#
-# ISDN subsystem
-#
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 # CONFIG_ISDN is not set
 
 #
 # Input device support
 #
 CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -380,7 +669,6 @@ CONFIG_INPUT_MOUSEDEV=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
 
@@ -390,23 +678,25 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
 
 #
 # Hardware I/O ports
 #
-CONFIG_SERIO=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
 
 #
 # Character devices
 #
 CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
@@ -419,215 +709,362 @@ CONFIG_HW_CONSOLE=y
 #
 CONFIG_SERIAL_ATMEL=y
 CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_SERIAL_ATMEL_PDC=y
+# CONFIG_SERIAL_ATMEL_TTYAT is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
 
 #
-# IPMI
+# Memory mapped GPIO expanders:
 #
-# CONFIG_IPMI_HANDLER is not set
 
 #
-# Watchdog Cards
+# I2C GPIO expanders:
 #
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-# CONFIG_AT91RM9200_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
 
 #
-# Ftape, the floppy tape device driver
+# PCI GPIO expanders:
 #
-# CONFIG_RAW_DRIVER is not set
 
 #
-# TPM devices
+# SPI GPIO expanders:
 #
-# CONFIG_AT91_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
 
 #
-# I2C support
+# Watchdog Device Drivers
 #
-# CONFIG_I2C is not set
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT91RM9200_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
 
 #
-# Misc devices
+# Sonics Silicon Backplane
 #
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
 
 #
 # Multimedia devices
 #
+
+#
+# Multimedia core support
+#
 # CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
 
 #
-# Digital Video Broadcasting Devices
+# Multimedia drivers
 #
-# CONFIG_DVB is not set
+# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
-# CONFIG_FB is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_MINI_4x6=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+# CONFIG_LOGO is not set
 # CONFIG_SOUND is not set
-
-#
-# USB support
-#
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 CONFIG_USB=y
-CONFIG_USB_DEBUG=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
 
 #
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
 
 #
 # USB Host Controller Drivers
 #
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
 
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_BLUETOOTH_TTY is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DEBUG=y
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_DPCM is not set
-
-#
-# USB Input Devices
-#
-# CONFIG_USB_HID is not set
 
 #
-# USB HID Boot Protocol drivers
+# also be needed; see USB_STORAGE Help for more info
 #
-# 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_XPAD is not set
-# CONFIG_USB_ATI_REMOTE is not set
+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_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_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+CONFIG_USB_LIBUSUAL=y
 
 #
 # USB Imaging devices
 #
+# CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
+# USB port drivers
 #
-# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_SERIAL is not set
 
 #
-# Video4Linux support is needed for USB Multimedia device support
+# USB Miscellaneous drivers
 #
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
 
 #
-# USB Network Adapters
+# OTG and related infrastructure
 #
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_USBNET is not set
-# CONFIG_USB_MON is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
 
 #
-# USB port drivers
+# MMC/SD/SDIO Card Drivers
 #
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
 
 #
-# USB Serial Converter support
+# MMC/SD/SDIO Host Controller Drivers
 #
-# CONFIG_USB_SERIAL is not set
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_AT91=y
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_NEW_LEDS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
 
 #
-# USB Miscellaneous drivers
+# RTC interfaces
 #
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 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_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
 
 #
-# USB DSL modem support
+# SPI RTC drivers
 #
 
 #
-# USB Gadget Support
+# Platform RTC drivers
 #
-# CONFIG_USB_GADGET is not set
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
 
 #
-# MMC/SD Card support
+# on-CPU RTC drivers
 #
-# CONFIG_MMC is not set
+CONFIG_RTC_DRV_AT91RM9200=y
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
 
 #
 # 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_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
 # CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS 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 is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
-# XFS support
+# Caches
 #
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=y
-CONFIG_AUTOFS4_FS=y
+# CONFIG_FSCACHE is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -639,7 +1076,7 @@ CONFIG_AUTOFS4_FS=y
 # DOS/FAT/NT Filesystems
 #
 CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
+# CONFIG_MSDOS_FS is not set
 CONFIG_VFAT_FS=y
 CONFIG_FAT_DEFAULT_CODEPAGE=437
 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
@@ -649,53 +1086,70 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # Pseudo filesystems
 #
 CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
-CONFIG_DEVPTS_FS_XATTR=y
-# CONFIG_DEVPTS_FS_SECURITY is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
+# CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# 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_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_UBIFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
-# CONFIG_NFSD is not set
+# CONFIG_NFS_V4 is not set
 CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
 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
 
 #
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
 CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_DEFAULT="iso8859-1"
 CONFIG_NLS_CODEPAGE_437=y
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
@@ -719,7 +1173,7 @@ CONFIG_NLS_CODEPAGE_437=y
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
-CONFIG_NLS_ASCII=y
+# 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
@@ -733,47 +1187,119 @@ CONFIG_NLS_ASCII=y
 # 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
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
 
 #
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_MAGIC_SYSRQ is not set
-CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
-# CONFIG_DEBUG_FS is not set
-CONFIG_FRAME_POINTER=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
-# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
 
 #
 # Security options
 #
 # CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_CRYPTO is not set
-
-#
-# Hardware crypto devices
-#
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
+CONFIG_AUDIT_GENERIC=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
index 0a1abb978d7efe4b8b475fc588eee5a1e4e54deb..af74cc2de8b6827448b4f40e51c9c5f9c3a4638b 100644 (file)
@@ -629,7 +629,7 @@ CONFIG_SCSI_LOWLEVEL=y
 CONFIG_ATA=y
 # CONFIG_ATA_NONSTANDARD is not set
 CONFIG_SATA_PMP=y
-# CONFIG_SATA_AHCI is not set
+CONFIG_SATA_AHCI=y
 # CONFIG_SATA_SIL24 is not set
 CONFIG_ATA_SFF=y
 # CONFIG_SATA_SVW is not set
index 083516cd0d7fc8dc6dbc984ccf80ce116cdc6f0b..75263a83741c89f70ba8f1d49fec338b4e2a070c 100644 (file)
@@ -1,15 +1,15 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc1
-# Wed Apr  8 10:18:06 2009
+# Linux kernel version: 2.6.31-rc4
+# Fri Jul 24 16:08:06 2009
 #
 CONFIG_ARM=y
+CONFIG_HAVE_PWM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_MMU=y
-# CONFIG_NO_IOPORT is not set
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -18,14 +18,13 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_ARCH_MTD_XIP=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -85,7 +84,12 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -99,6 +103,12 @@ CONFIG_KPROBES=y
 CONFIG_KRETPROBES=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
@@ -111,7 +121,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -138,13 +148,14 @@ CONFIG_FREEZER=y
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
 # CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
-# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_MXC=y
+# CONFIG_ARCH_STMP3XXX is not set
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_IOP13XX is not set
 # CONFIG_ARCH_IOP32X is not set
 # CONFIG_ARCH_IOP33X is not set
@@ -153,25 +164,25 @@ CONFIG_FREEZER=y
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
 # CONFIG_ARCH_KIRKWOOD is not set
-# CONFIG_ARCH_KS8695 is not set
-# CONFIG_ARCH_NS9XXX is not set
 # CONFIG_ARCH_LOKI is not set
 # CONFIG_ARCH_MV78XX0 is not set
-CONFIG_ARCH_MXC=y
 # CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
 # CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_MSM is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_MSM is not set
-# CONFIG_ARCH_W90X900 is not set
 
 #
 # Freescale MXC Implementations
@@ -188,6 +199,8 @@ CONFIG_MACH_MX27=y
 CONFIG_MACH_MX27ADS=y
 CONFIG_MACH_PCM038=y
 CONFIG_MACH_PCM970_BASEBOARD=y
+CONFIG_MACH_MX27_3DS=y
+CONFIG_MACH_MX27LITE=y
 CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_MXC_PWM=y
 
@@ -213,7 +226,6 @@ CONFIG_ARM_THUMB=y
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
 # CONFIG_CPU_CACHE_ROUND_ROBIN is not set
-# CONFIG_OUTER_CACHE is not set
 CONFIG_COMMON_CLKDEV=y
 
 #
@@ -238,7 +250,6 @@ CONFIG_PREEMPT=y
 CONFIG_HZ=100
 CONFIG_AEABI=y
 CONFIG_OABI_COMPAT=y
-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
 # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
 # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
 # CONFIG_HIGHMEM is not set
@@ -253,10 +264,11 @@ CONFIG_SPLIT_PTLOCK_CPUS=4096
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
 
 #
 # Boot options
@@ -361,6 +373,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -474,7 +487,16 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-# CONFIG_MTD_NAND is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+CONFIG_MTD_NAND_MXC=y
 # CONFIG_MTD_ONENAND is not set
 
 #
@@ -485,7 +507,15 @@ CONFIG_MTD_PHYSMAP=y
 #
 # UBI - Unsorted block images
 #
-# CONFIG_MTD_UBI is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
@@ -494,7 +524,21 @@ CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
-# CONFIG_MISC_DEVICES is not set
+# CONFIG_MG_DISK is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -508,7 +552,6 @@ CONFIG_HAVE_IDE=y
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -534,6 +577,8 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
 CONFIG_FEC=y
 # CONFIG_FEC2 is not set
 # CONFIG_NETDEV_1000 is not set
@@ -580,6 +625,11 @@ CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_TABLET is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 # CONFIG_TOUCHSCREEN_ADS7846 is not set
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
@@ -592,6 +642,7 @@ CONFIG_INPUT_TOUCHSCREEN=y
 # CONFIG_TOUCHSCREEN_TOUCHWIN is not set
 # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
 # CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -644,6 +695,7 @@ CONFIG_I2C_HELPER_AUTO=y
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_IMX=y
 # CONFIG_I2C_OCORES is not set
@@ -668,7 +720,6 @@ CONFIG_I2C_IMX=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -719,6 +770,7 @@ CONFIG_W1=y
 #
 # CONFIG_W1_MASTER_DS2482 is not set
 CONFIG_W1_MASTER_MXC=y
+# CONFIG_W1_MASTER_DS1WM is not set
 # CONFIG_W1_MASTER_GPIO is not set
 
 #
@@ -753,54 +805,16 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_TPS65010 is not set
 # CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
 # CONFIG_MFD_TC6393XB is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L2_COMMON=y
-CONFIG_VIDEO_ALLOW_V4L1=y
-CONFIG_VIDEO_V4L1_COMPAT=y
-# CONFIG_DVB_CORE is not set
-CONFIG_VIDEO_MEDIA=y
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=y
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=y
-CONFIG_MEDIA_TUNER_TDA8290=y
-CONFIG_MEDIA_TUNER_TDA9887=y
-CONFIG_MEDIA_TUNER_TEA5761=y
-CONFIG_MEDIA_TUNER_TEA5767=y
-CONFIG_MEDIA_TUNER_MT20XX=y
-CONFIG_MEDIA_TUNER_XC2028=y
-CONFIG_MEDIA_TUNER_XC5000=y
-CONFIG_MEDIA_TUNER_MC44S803=y
-CONFIG_VIDEO_V4L2=y
-CONFIG_VIDEO_V4L1=y
-CONFIG_VIDEO_CAPTURE_DRIVERS=y
-# CONFIG_VIDEO_ADV_DEBUG is not set
-# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-# CONFIG_VIDEO_VIVI is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_SAA5246A is not set
-# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_SOC_CAMERA is not set
-# CONFIG_RADIO_ADAPTERS is not set
-# CONFIG_DAB is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -917,6 +931,7 @@ CONFIG_RTC_DRV_PCF8563=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -962,12 +977,15 @@ CONFIG_RTC_DRV_PCF8563=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
@@ -1021,6 +1039,12 @@ CONFIG_JFFS2_ZLIB=y
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
@@ -1119,25 +1143,11 @@ CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_NOP_TRACER=y
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_IRQSOFF_TRACER is not set
-# CONFIG_PREEMPT_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
@@ -1151,16 +1161,104 @@ CONFIG_ARM_UNWIND=y
 # CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
-# CONFIG_CRYPTO is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
 CONFIG_BINARY_PRINTF=y
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_RATIONAL=y
 CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=y
 # CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
@@ -1168,6 +1266,8 @@ CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
index 20ada526f6de3873ed97c9db1de78466d00e21e5..a4f9a2a8149c8f228eec90f263f60e6c96858e97 100644 (file)
@@ -1,15 +1,15 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc1
-# Wed Apr  8 11:06:37 2009
+# Linux kernel version: 2.6.31-rc4
+# Tue Jul 28 14:11:34 2009
 #
 CONFIG_ARM=y
+CONFIG_HAVE_PWM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_MMU=y
-# CONFIG_NO_IOPORT is not set
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -18,14 +18,13 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_ARCH_MTD_XIP=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -86,7 +85,12 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -97,6 +101,11 @@ CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
@@ -109,7 +118,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -136,13 +145,14 @@ CONFIG_FREEZER=y
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_AT91 is not set
 # CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
-# CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_MXC=y
+# CONFIG_ARCH_STMP3XXX is not set
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_IOP13XX is not set
 # CONFIG_ARCH_IOP32X is not set
 # CONFIG_ARCH_IOP33X is not set
@@ -151,25 +161,25 @@ CONFIG_FREEZER=y
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_L7200 is not set
 # CONFIG_ARCH_KIRKWOOD is not set
-# CONFIG_ARCH_KS8695 is not set
-# CONFIG_ARCH_NS9XXX is not set
 # CONFIG_ARCH_LOKI is not set
 # CONFIG_ARCH_MV78XX0 is not set
-CONFIG_ARCH_MXC=y
 # CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
 # CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_MSM is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_S3C64XX is not set
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_MSM is not set
-# CONFIG_ARCH_W90X900 is not set
 
 #
 # Freescale MXC Implementations
@@ -178,6 +188,7 @@ CONFIG_ARCH_MXC=y
 # CONFIG_ARCH_MX2 is not set
 CONFIG_ARCH_MX3=y
 CONFIG_ARCH_MX31=y
+CONFIG_ARCH_MX35=y
 
 #
 # MX3 platforms:
@@ -185,12 +196,19 @@ CONFIG_ARCH_MX31=y
 CONFIG_MACH_MX31ADS=y
 CONFIG_MACH_MX31ADS_WM1133_EV1=y
 CONFIG_MACH_PCM037=y
+CONFIG_MACH_PCM037_EET=y
 CONFIG_MACH_MX31LITE=y
 CONFIG_MACH_MX31_3DS=y
 CONFIG_MACH_MX31MOBOARD=y
+CONFIG_MACH_MX31LILLY=y
 CONFIG_MACH_QONG=y
+CONFIG_MACH_PCM043=y
+CONFIG_MACH_ARMADILLO5X0=y
+CONFIG_MACH_MX35_3DS=y
 CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_MXC_PWM=y
+CONFIG_ARCH_HAS_RNGA=y
+CONFIG_ARCH_MXC_IOMUX_V3=y
 
 #
 # Processor Type
@@ -218,6 +236,7 @@ CONFIG_ARM_THUMB=y
 # CONFIG_CPU_BPREDICT_DISABLE is not set
 CONFIG_OUTER_CACHE=y
 CONFIG_CACHE_L2X0=y
+# CONFIG_ARM_ERRATA_411920 is not set
 CONFIG_COMMON_CLKDEV=y
 
 #
@@ -242,7 +261,6 @@ CONFIG_PREEMPT=y
 CONFIG_HZ=100
 CONFIG_AEABI=y
 CONFIG_OABI_COMPAT=y
-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
 # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
 # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
 # CONFIG_HIGHMEM is not set
@@ -257,10 +275,11 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
 
 #
 # Boot options
@@ -362,6 +381,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -465,7 +485,16 @@ CONFIG_MTD_PHYSMAP=y
 # CONFIG_MTD_DOC2000 is not set
 # CONFIG_MTD_DOC2001 is not set
 # CONFIG_MTD_DOC2001PLUS is not set
-# CONFIG_MTD_NAND is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+CONFIG_MTD_NAND_MXC=y
 # CONFIG_MTD_ONENAND is not set
 
 #
@@ -476,10 +505,30 @@ CONFIG_MTD_PHYSMAP=y
 #
 # UBI - Unsorted block images
 #
-# CONFIG_MTD_UBI is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
 # CONFIG_PARPORT is not set
 # CONFIG_BLK_DEV is not set
-# CONFIG_MISC_DEVICES is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -493,7 +542,6 @@ CONFIG_HAVE_IDE=y
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -528,7 +576,7 @@ CONFIG_MII=y
 # CONFIG_ETHOC is not set
 # CONFIG_SMC911X is not set
 CONFIG_SMSC911X=y
-# CONFIG_DNET is not set
+CONFIG_DNET=y
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -537,8 +585,10 @@ CONFIG_SMSC911X=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
-CONFIG_CS89x0=y
-CONFIG_CS89x0_NONISA_IRQ=y
+# CONFIG_CS89x0 is not set
+# CONFIG_KS8842 is not set
+CONFIG_FEC=y
+# CONFIG_FEC2 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 
@@ -609,6 +659,7 @@ CONFIG_I2C_HELPER_AUTO=y
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_IMX=y
 # CONFIG_I2C_OCORES is not set
@@ -633,7 +684,6 @@ CONFIG_I2C_IMX=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -669,6 +719,7 @@ CONFIG_W1=y
 #
 # CONFIG_W1_MASTER_DS2482 is not set
 CONFIG_W1_MASTER_MXC=y
+# CONFIG_W1_MASTER_DS1WM is not set
 # CONFIG_W1_MASTER_GPIO is not set
 
 #
@@ -703,6 +754,8 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_TPS65010 is not set
 # CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
 # CONFIG_MFD_TC6393XB is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
@@ -711,10 +764,8 @@ CONFIG_MFD_WM8350_CONFIG_MODE_0=y
 CONFIG_MFD_WM8352_CONFIG_MODE_0=y
 CONFIG_MFD_WM8350_I2C=y
 # CONFIG_MFD_PCF50633 is not set
-
-#
-# Multimedia devices
-#
+# CONFIG_AB3100_CORE is not set
+CONFIG_MEDIA_SUPPORT=y
 
 #
 # Multimedia core support
@@ -758,8 +809,10 @@ CONFIG_SOC_CAMERA_MT9T031=y
 CONFIG_SOC_CAMERA_MT9V022=y
 CONFIG_SOC_CAMERA_TW9910=y
 # CONFIG_SOC_CAMERA_PLATFORM is not set
-# CONFIG_SOC_CAMERA_OV772X is not set
+CONFIG_SOC_CAMERA_OV772X=y
+CONFIG_MX3_VIDEO=y
 CONFIG_VIDEO_MX3=y
+# CONFIG_VIDEO_SH_MOBILE_CEU is not set
 # CONFIG_RADIO_ADAPTERS is not set
 # CONFIG_DAB is not set
 
@@ -847,8 +900,11 @@ CONFIG_REGULATOR=y
 # CONFIG_REGULATOR_DEBUG is not set
 # CONFIG_REGULATOR_FIXED_VOLTAGE is not set
 # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
 # CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
 CONFIG_REGULATOR_WM8350=y
+# CONFIG_REGULATOR_LP3971 is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 
@@ -861,10 +917,12 @@ CONFIG_REGULATOR_WM8350=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -921,6 +979,12 @@ CONFIG_JFFS2_ZLIB=y
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
@@ -937,6 +1001,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -979,22 +1044,7 @@ CONFIG_FRAME_WARN=1024
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_IRQSOFF_TRACER is not set
-# CONFIG_PREEMPT_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 CONFIG_ARM_UNWIND=y
@@ -1094,9 +1144,9 @@ CONFIG_CRYPTO_DES=y
 #
 # Compression
 #
-# CONFIG_CRYPTO_DEFLATE is not set
+CONFIG_CRYPTO_DEFLATE=y
 # CONFIG_CRYPTO_ZLIB is not set
-# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_LZO=y
 
 #
 # Random Number Generation
@@ -1109,9 +1159,10 @@ CONFIG_CRYPTO_HW=y
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_RATIONAL=y
 CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=y
 # CONFIG_CRC_T10DIF is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
@@ -1119,6 +1170,8 @@ CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
index 28be17fbc1579f1f24a4c9d216fa735252861549..d5ff4776cd0a3500c1439308e54b3e57a20a6eff 100644 (file)
@@ -1107,7 +1107,7 @@ CONFIG_USB_ZERO=m
 CONFIG_USB_OTG_UTILS=y
 # CONFIG_USB_GPIO_VBUS is not set
 # CONFIG_ISP1301_OMAP is not set
-CONFIG_TWL4030_USB=y
+# CONFIG_TWL4030_USB is not set
 # CONFIG_NOP_USB_XCEIV is not set
 CONFIG_MMC=y
 # CONFIG_MMC_DEBUG is not set
index eb2cb31825c0b4a797258f652ef75d54f96233cb..f238df66efd4d3d2e80f1188b91171845e7ee502 100644 (file)
@@ -282,7 +282,7 @@ CONFIG_ALIGNMENT_TRAP=y
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="init=/sbin/preinit ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs rootflags=bulk_read,no_chk_data_crc rw console=ttyMTD,log console=tty0"
+CONFIG_CMDLINE="init=/sbin/preinit ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs rootflags=bulk_read,no_chk_data_crc rw console=ttyMTD,log console=tty0 console=ttyS2,115200n8"
 # CONFIG_XIP_KERNEL is not set
 # CONFIG_KEXEC is not set
 
@@ -1354,7 +1354,7 @@ CONFIG_USB_OTG_UTILS=y
 # CONFIG_USB_GPIO_VBUS is not set
 # CONFIG_ISP1301_OMAP is not set
 CONFIG_TWL4030_USB=y
-CONFIG_MMC=m
+CONFIG_MMC=y
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
 
@@ -1449,7 +1449,8 @@ CONFIG_RTC_DRV_TWL4030=m
 # on-CPU RTC drivers
 #
 # CONFIG_DMADEVICES is not set
-# CONFIG_REGULATOR is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_TWL4030=y
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 
index 2d58b8fe59bedb90791403301c2ffe4384e421f8..b49810461e41f7e90b57c9cb8de2ff833cbe2d49 100644 (file)
@@ -260,6 +260,7 @@ CONFIG_MACH_NEXCODER_2440=y
 CONFIG_SMDK2440_CPU2440=y
 CONFIG_MACH_AT2440EVB=y
 CONFIG_CPU_S3C2442=y
+CONFIG_MACH_MINI2440=y
 
 #
 # S3C2442 Machines
@@ -2298,7 +2299,6 @@ CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
-CONFIG_DEBUG_S3C_PORT=y
 CONFIG_DEBUG_S3C_UART=0
 
 #
index 2e8fa50e9a09a190d89c01d38b41e5733dcc2715..32860609e057764caa9c1b1f34331717c4dfb734 100644 (file)
@@ -816,7 +816,6 @@ CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
-CONFIG_DEBUG_S3C_PORT=y
 CONFIG_DEBUG_S3C_UART=0
 
 #
index 07dfb98df4f0798da3b02a9497c0a32b081ff3be..9d32faef05f6e1b183f5d5fc23f4728413aa2b88 100644 (file)
@@ -857,7 +857,6 @@ CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUG_LL=y
 # CONFIG_DEBUG_ICEDCC is not set
-# CONFIG_DEBUG_S3C_PORT is not set
 CONFIG_DEBUG_S3C_UART=0
 
 #
index 2d827e1211470f85c603bd5498dfd3f27511535d..7d61ae6e75daf7e9da06b214818ee0ad2ff22efa 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc6
-# Mon Jun  1 09:18:22 2009
+# Linux kernel version: 2.6.31-rc3
+# Thu Jul 16 23:36:10 2009
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -9,7 +9,6 @@ CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_MMU=y
-# CONFIG_NO_IOPORT is not set
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
@@ -18,13 +17,12 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_VECTORS_BASE=0xffff0000
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -68,7 +66,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -81,8 +78,13 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 # CONFIG_AIO is not set
+
+#
+# Performance Counters
+#
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -94,6 +96,10 @@ CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
@@ -106,7 +112,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+# CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -138,9 +144,9 @@ CONFIG_DEFAULT_IOSCHED="deadline"
 # CONFIG_ARCH_EP93XX is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_IOP13XX is not set
 # CONFIG_ARCH_IOP32X is not set
 # CONFIG_ARCH_IOP33X is not set
@@ -216,8 +222,8 @@ CONFIG_ARM_THUMB=y
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
 # CONFIG_CPU_CACHE_ROUND_ROBIN is not set
-# CONFIG_OUTER_CACHE is not set
 CONFIG_ARM_VIC=y
+CONFIG_ARM_VIC_NR=2
 CONFIG_COMMON_CLKDEV=y
 
 #
@@ -243,7 +249,6 @@ CONFIG_PREEMPT=y
 CONFIG_HZ=100
 CONFIG_AEABI=y
 CONFIG_OABI_COMPAT=y
-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
 # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
 # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
 # CONFIG_HIGHMEM is not set
@@ -258,17 +263,18 @@ CONFIG_SPLIT_PTLOCK_CPUS=4096
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
 
 #
 # Boot options
 #
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=/dev/mtdblock2 rw rootfstype=yaffs2 console=ttyAMA0,115200n8 ab3100.force=0,0x48 mtdparts=u300nand:128k@0x0(bootrecords)ro,8064k@128k(free)ro,253952k@8192k(platform) lpj=515072"
+CONFIG_CMDLINE="root=/dev/ram0 rw rootfstype=rootfs console=ttyAMA0,115200n8 lpj=515072"
 # CONFIG_XIP_KERNEL is not set
 # CONFIG_KEXEC is not set
 
@@ -359,6 +365,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -497,6 +504,7 @@ CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
@@ -533,12 +541,14 @@ CONFIG_INPUT_EVDEV=y
 #
 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_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8323 is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
-# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
@@ -597,9 +607,11 @@ CONFIG_I2C_HELPER_AUTO=y
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_SIMTEC is not set
+CONFIG_I2C_STU300=y
 
 #
 # External I2C/SMBus adapter drivers
@@ -620,7 +632,6 @@ CONFIG_I2C_HELPER_AUTO=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -635,6 +646,7 @@ CONFIG_SPI_MASTER=y
 #
 # CONFIG_SPI_BITBANG is not set
 # CONFIG_SPI_GPIO is not set
+CONFIG_SPI_PL022=y
 
 #
 # SPI Protocol Masters
@@ -647,6 +659,7 @@ CONFIG_POWER_SUPPLY=y
 # CONFIG_PDA_POWER is not set
 # CONFIG_BATTERY_DS2760 is not set
 # CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
@@ -657,6 +670,7 @@ CONFIG_WATCHDOG=y
 # Watchdog Device Drivers
 #
 # CONFIG_SOFT_WATCHDOG is not set
+CONFIG_COH901327_WATCHDOG=y
 CONFIG_SSB_POSSIBLE=y
 
 #
@@ -678,22 +692,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+CONFIG_AB3100_CORE=y
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -760,6 +761,11 @@ CONFIG_SND_JACK=y
 # CONFIG_SND_VERBOSE_PROCFS is not set
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 # CONFIG_SND_DRIVERS is not set
 # CONFIG_SND_ARM is not set
 # CONFIG_SND_SPI is not set
@@ -770,7 +776,7 @@ CONFIG_SND_SOC_I2C_AND_SPI=y
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
-# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_DEBUG=y
 # CONFIG_MMC_UNSAFE_RESUME is not set
 
 #
@@ -797,7 +803,7 @@ CONFIG_LEDS_CLASS=y
 #
 # CONFIG_LEDS_PCA9532 is not set
 # CONFIG_LEDS_GPIO is not set
-# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP3944 is not set
 # CONFIG_LEDS_PCA955X is not set
 # CONFIG_LEDS_DAC124S085 is not set
 # CONFIG_LEDS_BD2802 is not set
@@ -845,6 +851,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -887,7 +894,10 @@ CONFIG_REGULATOR=y
 # CONFIG_REGULATOR_DEBUG is not set
 # CONFIG_REGULATOR_FIXED_VOLTAGE is not set
 # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
 # CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_LP3971 is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 
@@ -900,16 +910,19 @@ CONFIG_REGULATOR=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=y
+# CONFIG_CUSE is not set
 
 #
 # Caches
@@ -1033,6 +1046,7 @@ CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_SLUB_DEBUG_ON is not set
 # CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
 # CONFIG_DEBUG_PREEMPT is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
@@ -1063,18 +1077,16 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_PAGE_POISONING is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
index 9e07fe50702913f6324b21faa9dbee4640334b20..9ed2377fe8e54b26fca9fc2ec6a9b6694fb17533 100644 (file)
@@ -159,8 +159,6 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
 
 #else /* ARM_ARCH_6 */
 
-#include <asm/system.h>
-
 #ifdef CONFIG_SMP
 #error SMP not supported on pre-ARMv6 CPUs
 #endif
index be962c1349c4aa17a65f4cd364fd6221f1ea83bc..9c746af1bf6e150ae19acebe961b0a0c116b5d45 100644 (file)
@@ -12,7 +12,7 @@
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT             12
-#define PAGE_SIZE              (1UL << PAGE_SHIFT)
+#define PAGE_SIZE              (_AC(1,UL) << PAGE_SHIFT)
 #define PAGE_MASK              (~(PAGE_SIZE-1))
 
 #ifndef __ASSEMBLY__
index 1cd2d6416bda447da0a64276ab2d302ff785cd19..c433c6c73112a70f379d954cdfb1ec07d19c86f3 100644 (file)
@@ -285,15 +285,6 @@ extern struct page *empty_zero_page;
 #define pte_young(pte)         (pte_val(pte) & L_PTE_YOUNG)
 #define pte_special(pte)       (0)
 
-/*
- * The following only works if pte_present() is not true.
- */
-#define pte_file(pte)          (pte_val(pte) & L_PTE_FILE)
-#define pte_to_pgoff(x)                (pte_val(x) >> 2)
-#define pgoff_to_pte(x)                __pte(((x) << 2) | L_PTE_FILE)
-
-#define PTE_FILE_MAX_BITS      30
-
 #define PTE_BIT_FUNC(fn,op) \
 static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
 
@@ -384,16 +375,50 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
-/* Encode and decode a swap entry.
+/*
+ * Encode and decode a swap entry.  Swap entries are stored in the Linux
+ * page tables as follows:
  *
- * We support up to 32GB of swap on 4k machines
+ *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+ *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *   <--------------- offset --------------------> <--- type --> 0 0
+ *
+ * This gives us up to 127 swap files and 32GB per swap file.  Note that
+ * the offset field is always non-zero.
  */
-#define __swp_type(x)          (((x).val >> 2) & 0x7f)
-#define __swp_offset(x)                ((x).val >> 9)
-#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 9) })
+#define __SWP_TYPE_SHIFT       2
+#define __SWP_TYPE_BITS                7
+#define __SWP_TYPE_MASK                ((1 << __SWP_TYPE_BITS) - 1)
+#define __SWP_OFFSET_SHIFT     (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
+
+#define __swp_type(x)          (((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK)
+#define __swp_offset(x)                ((x).val >> __SWP_OFFSET_SHIFT)
+#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) })
+
 #define __pte_to_swp_entry(pte)        ((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(swp)        ((pte_t) { (swp).val })
 
+/*
+ * It is an error for the kernel to have more swap files than we can
+ * encode in the PTEs.  This ensures that we know when MAX_SWAPFILES
+ * is increased beyond what we presently support.
+ */
+#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS)
+
+/*
+ * Encode and decode a file entry.  File entries are stored in the Linux
+ * page tables as follows:
+ *
+ *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+ *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *   <------------------------ offset -------------------------> 1 0
+ */
+#define pte_file(pte)          (pte_val(pte) & L_PTE_FILE)
+#define pte_to_pgoff(x)                (pte_val(x) >> 2)
+#define pgoff_to_pte(x)                __pte(((x) << 2) | L_PTE_FILE)
+
+#define PTE_FILE_MAX_BITS      30
+
 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
 /* FIXME: this is not correct */
 #define kern_addr_valid(addr)  (1)
index ee1304f22f944c3104d28d44c1b0eeb05957eb22..5ccce0a9b03cdfd6a054b4c43b429d3bbce922d9 100644 (file)
@@ -201,7 +201,8 @@ static struct tagtable __tagtable_##fn __tag = { tag, fn }
 struct membank {
        unsigned long start;
        unsigned long size;
-       int           node;
+       unsigned short node;
+       unsigned short highmem;
 };
 
 struct meminfo {
index 4f8848260ee2b85b4256b9762aeb7ce68e29ef38..73394e50cbca26e4198349de503fd18554f331d6 100644 (file)
@@ -73,7 +73,7 @@ struct thread_info {
        .task           = &tsk,                                         \
        .exec_domain    = &default_exec_domain,                         \
        .flags          = 0,                                            \
-       .preempt_count  = 1,                                            \
+       .preempt_count  = INIT_PREEMPT_COUNT,                           \
        .addr_limit     = KERNEL_DS,                                    \
        .cpu_domain     = domain_val(DOMAIN_USER, DOMAIN_MANAGER) |     \
                          domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) |   \
index 321c83e43a1e7a2cc9d8d770417004a5c206be9a..f41a6f57cd1223aef8d00f450bc1b68365623b19 100644 (file)
@@ -102,8 +102,8 @@ tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
 }
 
 #define tlb_remove_page(tlb,page)      free_page_and_swap_cache(page)
-#define pte_free_tlb(tlb, ptep)                pte_free((tlb)->mm, ptep)
-#define pmd_free_tlb(tlb, pmdp)                pmd_free((tlb)->mm, pmdp)
+#define pte_free_tlb(tlb, ptep, addr)  pte_free((tlb)->mm, ptep)
+#define pmd_free_tlb(tlb, pmdp, addr)  pmd_free((tlb)->mm, pmdp)
 
 #define tlb_migrate_finish(mm)         do { } while (0)
 
index 366e5097a41a4f535d1d24ddccab44f13580fb64..8c3de1a350b5dd85bdf06b79f1dab163cd305743 100644 (file)
@@ -148,7 +148,7 @@ trace:
        sub r0, r0, #MCOUNT_INSN_SIZE
        mov lr, pc
        mov pc, r2
-       mov lr, r1                              @ restore lr
+       ldr lr, [fp, #-4]                       @ restore lr
        ldmia sp!, {r0-r3, pc}
 
 #endif /* CONFIG_DYNAMIC_FTRACE */
index 096f600dc8d84e25603f9269cbfebeab634ac4d6..b7c3490eaa24adb04bc7e7b2f971f5980f245221 100644 (file)
@@ -98,17 +98,6 @@ unlock:
        return 0;
 }
 
-/* Handle bad interrupts */
-static struct irq_desc bad_irq_desc = {
-       .handle_irq = handle_bad_irq,
-       .lock = __SPIN_LOCK_UNLOCKED(bad_irq_desc.lock),
-};
-
-#ifdef CONFIG_CPUMASK_OFFSTACK
-/* We are not allocating bad_irq_desc.affinity or .pending_mask */
-#error "ARM architecture does not support CONFIG_CPUMASK_OFFSTACK."
-#endif
-
 /*
  * do_IRQ handles all hardware IRQ's.  Decoded IRQs should not
  * come via this function.  Instead, they should provide their
@@ -124,10 +113,13 @@ asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
         * Some hardware gives randomly wrong interrupts.  Rather
         * than crashing, do something sensible.
         */
-       if (irq >= NR_IRQS)
-               handle_bad_irq(irq, &bad_irq_desc);
-       else
+       if (unlikely(irq >= NR_IRQS)) {
+               if (printk_ratelimit())
+                       printk(KERN_WARNING "Bad IRQ%u\n", irq);
+               ack_bad_irq(irq);
+       } else {
                generic_handle_irq(irq);
+       }
 
        /* AT91 specific workaround */
        irq_finish(irq);
@@ -165,10 +157,6 @@ void __init init_IRQ(void)
        for (irq = 0; irq < NR_IRQS; irq++)
                irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;
 
-#ifdef CONFIG_SMP
-       cpumask_setall(bad_irq_desc.affinity);
-       bad_irq_desc.node = smp_processor_id();
-#endif
        init_arch_irq();
 }
 
index 93bb4247b7ed019e92a6b64806c86af2fe338c7f..f6bc5d442782374bb99618702722dde5d37e1dc2 100644 (file)
@@ -133,7 +133,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
 }
 
 #ifdef CONFIG_CRUNCH
-static int preserve_crunch_context(struct crunch_sigframe *frame)
+static int preserve_crunch_context(struct crunch_sigframe __user *frame)
 {
        char kbuf[sizeof(*frame) + 8];
        struct crunch_sigframe *kframe;
@@ -146,7 +146,7 @@ static int preserve_crunch_context(struct crunch_sigframe *frame)
        return __copy_to_user(frame, kframe, sizeof(*frame));
 }
 
-static int restore_crunch_context(struct crunch_sigframe *frame)
+static int restore_crunch_context(struct crunch_sigframe __user *frame)
 {
        char kbuf[sizeof(*frame) + 8];
        struct crunch_sigframe *kframe;
index 4340bf3d2c84a8feae21eea058283f143640a698..69371028a2025a7f7b2f52fb32cdabadeae728e7 100644 (file)
@@ -6,6 +6,7 @@
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
+#include <asm/page.h>
        
 OUTPUT_ARCH(arm)
 ENTRY(stext)
@@ -63,7 +64,7 @@ SECTIONS
                        usr/built-in.o(.init.ramfs)
                __initramfs_end = .;
 #endif
-               . = ALIGN(4096);
+               . = ALIGN(PAGE_SIZE);
                __per_cpu_load = .;
                __per_cpu_start = .;
                        *(.data.percpu.page_aligned)
@@ -73,7 +74,7 @@ SECTIONS
 #ifndef CONFIG_XIP_KERNEL
                __init_begin = _stext;
                INIT_DATA
-               . = ALIGN(4096);
+               . = ALIGN(PAGE_SIZE);
                __init_end = .;
 #endif
        }
@@ -118,7 +119,7 @@ SECTIONS
                *(.got)                 /* Global offset table          */
        }
 
-       RODATA
+       RO_DATA(PAGE_SIZE)
 
        _etext = .;                     /* End of text and rodata section */
 
@@ -158,17 +159,17 @@ SECTIONS
                *(.data.init_task)
 
 #ifdef CONFIG_XIP_KERNEL
-               . = ALIGN(4096);
+               . = ALIGN(PAGE_SIZE);
                __init_begin = .;
                INIT_DATA
-               . = ALIGN(4096);
+               . = ALIGN(PAGE_SIZE);
                __init_end = .;
 #endif
 
-               . = ALIGN(4096);
+               . = ALIGN(PAGE_SIZE);
                __nosave_begin = .;
                *(.data.nosave)
-               . = ALIGN(4096);
+               . = ALIGN(PAGE_SIZE);
                __nosave_end = .;
 
                /*
index cc270beadd5d67bea4389fd6eed8113177bb3135..a55398ed1211d932266ac4ebace286ffe53490df 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/at73c213.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
 #include <linux/clk.h>
 
 #include <mach/hardware.h>
@@ -218,6 +220,56 @@ static struct gpio_led ek_leds[] = {
        }
 };
 
+
+/*
+ * GPIO Buttons
+ */
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+static struct gpio_keys_button ek_buttons[] = {
+       {
+               .gpio           = AT91_PIN_PA30,
+               .code           = BTN_3,
+               .desc           = "Button 3",
+               .active_low     = 1,
+               .wakeup         = 1,
+       },
+       {
+               .gpio           = AT91_PIN_PA31,
+               .code           = BTN_4,
+               .desc           = "Button 4",
+               .active_low     = 1,
+               .wakeup         = 1,
+       }
+};
+
+static struct gpio_keys_platform_data ek_button_data = {
+       .buttons        = ek_buttons,
+       .nbuttons       = ARRAY_SIZE(ek_buttons),
+};
+
+static struct platform_device ek_button_device = {
+       .name           = "gpio-keys",
+       .id             = -1,
+       .num_resources  = 0,
+       .dev            = {
+               .platform_data  = &ek_button_data,
+       }
+};
+
+static void __init ek_add_device_buttons(void)
+{
+       at91_set_gpio_input(AT91_PIN_PA30, 1);  /* btn3 */
+       at91_set_deglitch(AT91_PIN_PA30, 1);
+       at91_set_gpio_input(AT91_PIN_PA31, 1);  /* btn4 */
+       at91_set_deglitch(AT91_PIN_PA31, 1);
+
+       platform_device_register(&ek_button_device);
+}
+#else
+static void __init ek_add_device_buttons(void) {}
+#endif
+
+
 static struct i2c_board_info __initdata ek_i2c_devices[] = {
        {
                I2C_BOARD_INFO("24c512", 0x50),
@@ -245,6 +297,8 @@ static void __init ek_board_init(void)
        at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
        /* LEDs */
        at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
+       /* Push Buttons */
+       ek_add_device_buttons();
        /* PCK0 provides MCLK to the WM8731 */
        at91_set_B_periph(AT91_PIN_PC1, 0);
        /* SSC (for WM8731) */
index 35e12a49d1a684372f736fe374abed15763cd6bd..f6b5672cabd6377e6fdb8cc9b9531c565c72042a 100644 (file)
@@ -186,19 +186,21 @@ static struct fb_monspecs at91fb_default_monspecs = {
 static void at91_lcdc_power_control(int on)
 {
        if (on)
-               at91_set_gpio_value(AT91_PIN_PA30, 0);  /* power up */
+               at91_set_gpio_value(AT91_PIN_PC1, 0);   /* power up */
        else
-               at91_set_gpio_value(AT91_PIN_PA30, 1);  /* power down */
+               at91_set_gpio_value(AT91_PIN_PC1, 1);   /* power down */
 }
 
 /* Driver datas */
 static struct atmel_lcdfb_info __initdata ek_lcdc_data = {
+       .lcdcon_is_backlight            = true,
        .default_bpp                    = 16,
        .default_dmacon                 = ATMEL_LCDC_DMAEN,
        .default_lcdcon2                = AT91SAM9RL_DEFAULT_LCDCON2,
        .default_monspecs               = &at91fb_default_monspecs,
        .atmel_lcdfb_power_control      = at91_lcdc_power_control,
        .guard_time                     = 1,
+       .lcd_wiring_mode                = ATMEL_LCDC_WIRING_RGB,
 };
 
 #else
diff --git a/arch/arm/mach-at91/include/mach/at_hdmac.h b/arch/arm/mach-at91/include/mach/at_hdmac.h
new file mode 100644 (file)
index 0000000..187cb58
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Header file for the Atmel AHB DMA Controller driver
+ *
+ * Copyright (C) 2008 Atmel 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.
+ */
+#ifndef AT_HDMAC_H
+#define AT_HDMAC_H
+
+#include <linux/dmaengine.h>
+
+/**
+ * struct at_dma_platform_data - Controller configuration parameters
+ * @nr_channels: Number of channels supported by hardware (max 8)
+ * @cap_mask: dma_capability flags supported by the platform
+ */
+struct at_dma_platform_data {
+       unsigned int    nr_channels;
+       dma_cap_mask_t  cap_mask;
+};
+
+/**
+ * enum at_dma_slave_width - DMA slave register access width.
+ * @AT_DMA_SLAVE_WIDTH_8BIT: Do 8-bit slave register accesses
+ * @AT_DMA_SLAVE_WIDTH_16BIT: Do 16-bit slave register accesses
+ * @AT_DMA_SLAVE_WIDTH_32BIT: Do 32-bit slave register accesses
+ */
+enum at_dma_slave_width {
+       AT_DMA_SLAVE_WIDTH_8BIT = 0,
+       AT_DMA_SLAVE_WIDTH_16BIT,
+       AT_DMA_SLAVE_WIDTH_32BIT,
+};
+
+/**
+ * struct at_dma_slave - Controller-specific information about a slave
+ * @dma_dev: required DMA master device
+ * @tx_reg: physical address of data register used for
+ *     memory-to-peripheral transfers
+ * @rx_reg: physical address of data register used for
+ *     peripheral-to-memory transfers
+ * @reg_width: peripheral register width
+ * @cfg: Platform-specific initializer for the CFG register
+ * @ctrla: Platform-specific initializer for the CTRLA register
+ */
+struct at_dma_slave {
+       struct device           *dma_dev;
+       dma_addr_t              tx_reg;
+       dma_addr_t              rx_reg;
+       enum at_dma_slave_width reg_width;
+       u32                     cfg;
+       u32                     ctrla;
+};
+
+
+/* Platform-configurable bits in CFG */
+#define        ATC_SRC_PER(h)          (0xFU & (h))    /* Channel src rq associated with periph handshaking ifc h */
+#define        ATC_DST_PER(h)          ((0xFU & (h)) <<  4)    /* Channel dst rq associated with periph handshaking ifc h */
+#define        ATC_SRC_REP             (0x1 <<  8)     /* Source Replay Mod */
+#define        ATC_SRC_H2SEL           (0x1 <<  9)     /* Source Handshaking Mod */
+#define                ATC_SRC_H2SEL_SW        (0x0 <<  9)
+#define                ATC_SRC_H2SEL_HW        (0x1 <<  9)
+#define        ATC_DST_REP             (0x1 << 12)     /* Destination Replay Mod */
+#define        ATC_DST_H2SEL           (0x1 << 13)     /* Destination Handshaking Mod */
+#define                ATC_DST_H2SEL_SW        (0x0 << 13)
+#define                ATC_DST_H2SEL_HW        (0x1 << 13)
+#define        ATC_SOD                 (0x1 << 16)     /* Stop On Done */
+#define        ATC_LOCK_IF             (0x1 << 20)     /* Interface Lock */
+#define        ATC_LOCK_B              (0x1 << 21)     /* AHB Bus Lock */
+#define        ATC_LOCK_IF_L           (0x1 << 22)     /* Master Interface Arbiter Lock */
+#define                ATC_LOCK_IF_L_CHUNK     (0x0 << 22)
+#define                ATC_LOCK_IF_L_BUFFER    (0x1 << 22)
+#define        ATC_AHB_PROT_MASK       (0x7 << 24)     /* AHB Protection */
+#define        ATC_FIFOCFG_MASK        (0x3 << 28)     /* FIFO Request Configuration */
+#define                ATC_FIFOCFG_LARGESTBURST        (0x0 << 28)
+#define                ATC_FIFOCFG_HALFFIFO            (0x1 << 28)
+#define                ATC_FIFOCFG_ENOUGHSPACE         (0x2 << 28)
+
+/* Platform-configurable bits in CTRLA */
+#define        ATC_SCSIZE_MASK         (0x7 << 16)     /* Source Chunk Transfer Size */
+#define                ATC_SCSIZE_1            (0x0 << 16)
+#define                ATC_SCSIZE_4            (0x1 << 16)
+#define                ATC_SCSIZE_8            (0x2 << 16)
+#define                ATC_SCSIZE_16           (0x3 << 16)
+#define                ATC_SCSIZE_32           (0x4 << 16)
+#define                ATC_SCSIZE_64           (0x5 << 16)
+#define                ATC_SCSIZE_128          (0x6 << 16)
+#define                ATC_SCSIZE_256          (0x7 << 16)
+#define        ATC_DCSIZE_MASK         (0x7 << 20)     /* Destination Chunk Transfer Size */
+#define                ATC_DCSIZE_1            (0x0 << 20)
+#define                ATC_DCSIZE_4            (0x1 << 20)
+#define                ATC_DCSIZE_8            (0x2 << 20)
+#define                ATC_DCSIZE_16           (0x3 << 20)
+#define                ATC_DCSIZE_32           (0x4 << 20)
+#define                ATC_DCSIZE_64           (0x5 << 20)
+#define                ATC_DCSIZE_128          (0x6 << 20)
+#define                ATC_DCSIZE_256          (0x7 << 20)
+
+#endif /* AT_HDMAC_H */
index 5ac2f565d860e934df9a52de72a4294c1b0f7fb3..d6ab64ccd496baedad9b2fb49e217bca0ebfdf40 100644 (file)
@@ -37,7 +37,6 @@
 #include <mach/serial.h>
 #include <mach/nand.h>
 #include <mach/mmc.h>
-#include <mach/common.h>
 
 #define DAVINCI_ASYNC_EMIF_CONTROL_BASE                0x01e10000
 #define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE       0x02000000
index 28c9008df4f45f1cd43879a83958d69845886485..84ad5d161a874133f88322e1b489fc10936c4b7b 100644 (file)
@@ -36,7 +36,6 @@
 #include <mach/serial.h>
 #include <mach/nand.h>
 #include <mach/mmc.h>
-#include <mach/common.h>
 
 #define DAVINCI_ASYNC_EMIF_CONTROL_BASE                0x01e10000
 #define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE       0x02000000
index d9d40450bdc5d8c018b03c18305d282d1160faab..56c8cd01de9ac2feff60be46879552d143196174 100644 (file)
@@ -45,7 +45,6 @@
 #include <mach/nand.h>
 #include <mach/mmc.h>
 #include <mach/emac.h>
-#include <mach/common.h>
 
 #define DM644X_EVM_PHY_MASK            (0x2)
 #define DM644X_EVM_MDIO_FREQUENCY      (2200000) /* PHY bus frequency */
index e17de6352624c2bd4b56e9fb643fb7eb01425c74..8657e72debc1d8ab4796cc952c67a8a18ac9593a 100644 (file)
@@ -47,7 +47,6 @@
 #include <mach/i2c.h>
 #include <mach/mmc.h>
 #include <mach/emac.h>
-#include <mach/common.h>
 
 #define DM646X_EVM_PHY_MASK            (0x2)
 #define DM646X_EVM_MDIO_FREQUENCY      (2200000) /* PHY bus frequency */
index 748a8e48541e4b9788add21e111aad9a766def54..7acdfd8ac0712dc577c0e56f5a0eec26b4919ae8 100644 (file)
@@ -52,7 +52,6 @@
 #include <mach/serial.h>
 #include <mach/psc.h>
 #include <mach/mux.h>
-#include <mach/common.h>
 
 #define SFFSDR_PHY_MASK                (0x2)
 #define SFFSDR_MDIO_FREQUENCY  (2200000) /* PHY bus frequency */
index a2df5bb7dff0d9cf799d8770e158dfc9885373e8..dbcac9c40a28883df558565be3c7e52c37426053 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/io.h>
 
 #include <mach/dma.h>
 #include <mach/hardware.h>
index 34ddec081c40dd817b6ca4741a020e0f3880cab4..411734422c1dd138c7743be759c8088533088436 100644 (file)
@@ -41,9 +41,6 @@
 #define TS72XX_OPTIONS2_TS9420_BOOT    0x02
 
 
-#define TS72XX_NOR_PHYS_BASE           0x60000000
-#define TS72XX_NOR2_PHYS_BASE          0x62000000
-
 #define TS72XX_NAND1_DATA_PHYS_BASE    0x60000000
 #define TS72XX_NAND2_DATA_PHYS_BASE    0x70000000
 #define TS72XX_NAND_DATA_VIRT_BASE     0xfebfc000
index 7ee024d3482984a339f854bc60df755a5ea4c781..aaf1371412afc7bf3281190b42abb14a3820bc0e 100644 (file)
@@ -112,13 +112,16 @@ static void __init ts72xx_map_io(void)
        }
 }
 
+/*************************************************************************
+ * NOR flash (TS-7200 only)
+ *************************************************************************/
 static struct physmap_flash_data ts72xx_flash_data = {
-       .width          = 1,
+       .width          = 2,
 };
 
 static struct resource ts72xx_flash_resource = {
-       .start          = TS72XX_NOR_PHYS_BASE,
-       .end            = TS72XX_NOR_PHYS_BASE + SZ_16M - 1,
+       .start          = EP93XX_CS6_PHYS_BASE,
+       .end            = EP93XX_CS6_PHYS_BASE + SZ_16M - 1,
        .flags          = IORESOURCE_MEM,
 };
 
@@ -132,6 +135,12 @@ static struct platform_device ts72xx_flash = {
        .resource       = &ts72xx_flash_resource,
 };
 
+static void __init ts72xx_register_flash(void)
+{
+       if (board_is_ts7200())
+               platform_device_register(&ts72xx_flash);
+}
+
 static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
 {
        __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
@@ -165,8 +174,7 @@ static struct ep93xx_eth_data ts72xx_eth_data = {
 static void __init ts72xx_init_machine(void)
 {
        ep93xx_init_devices();
-       if (board_is_ts7200())
-               platform_device_register(&ts72xx_flash);
+       ts72xx_register_flash();
        platform_device_register(&ts72xx_rtc_device);
 
        ep93xx_register_eth(&ts72xx_eth_data, 1);
index ce63048d45eb0ab7ad52556917ce5b28fe1c610c..8a947d42a6f1b83bf7ed4b4b74e96d3f13b9e8be 100644 (file)
@@ -17,7 +17,7 @@
 
 #include <mach/hardware.h>
 
-#define IO_SPACE_LIMIT 0xffff0000
+#define IO_SPACE_LIMIT 0x0000ffff
 
 extern int (*ixp4xx_pci_read)(u32 addr, u32 cmd, u32* data);
 extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data);
index e021a80c2cafa00df3cba91543a6e5dc55d05f7b..bc74278ed311c2bef402d6e16d808111669ed96e 100644 (file)
 
 #define MPP48_GPIO             MPP( 48, 0x0, 1, 1, 0,   0,   0,   1    )
 #define MPP48_TSMP12           MPP( 48, 0x1, 1, 1, 0,   0,   0,   1    )
-#define MPP48_TDM_DTX          MPP( 48. 0x2, 0, 1, 0,   0,   0,   1    )
+#define MPP48_TDM_DTX          MPP( 48, 0x2, 0, 1, 0,   0,   0,   1    )
 
 #define MPP49_GPIO             MPP( 49, 0x0, 1, 1, 0,   0,   0,   1    )
 #define MPP49_TSMP9            MPP( 49, 0x1, 1, 1, 0,   0,   0,   1    )
index 01aa213c0a6ffda67086c8c3aaac24dbfd4b5113..ec1a64f263d224285b9478f04a3c79cf85e173b7 100644 (file)
@@ -206,6 +206,15 @@ static void __init qnap_ts219_init(void)
 
 }
 
+static int __init ts219_pci_init(void)
+{
+   if (machine_is_ts219())
+           kirkwood_pcie_init();
+
+   return 0;
+}
+subsys_initcall(ts219_pci_init);
+
 MACHINE_START(TS219, "QNAP TS-119/TS-219")
        /* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
        .phys_io        = KIRKWOOD_REGS_PHYS_BASE,
index 1d640d075b7e58b68ab9b9aad62e6e9ed90adc08..e0f911d9e021711c7ff2489ac7951c114a1a74e3 100644 (file)
 
 #include <asm/sizes.h>
 
+/*
+ * Clocks are derived from MCLK, which is 25Mhz
+ */
+#define KS8695_CLOCK_RATE      25000000
+
 /*
  * Physical RAM address.
  */
index 4682e350369befa80f4163f772e6161a3446c873..10f716371bd350057e8b721690954ac1778bdebd 100644 (file)
@@ -14,7 +14,8 @@
 #ifndef __ASM_ARCH_TIMEX_H
 #define __ASM_ARCH_TIMEX_H
 
-/* timers are derived from MCLK, which is 25MHz */
-#define CLOCK_TICK_RATE 25000000
+#include <mach/hardware.h>
+
+#define CLOCK_TICK_RATE        KS8695_CLOCK_RATE
 
 #endif
index f5ebcc0fcab9f9c36eaaf5dcbcc6b350393fbb2a..78499667eb7b3241c3a5c1dfbbc69df4840a3991 100644 (file)
@@ -245,6 +245,9 @@ static int ks8695_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs
 
 static void __init ks8695_pci_preinit(void)
 {
+       /* make software reset to avoid freeze if PCI bus was messed up */
+       __raw_writel(0x80000000, KS8695_PCI_VA + KS8695_PBCS);
+
        /* stage 1 initialization, subid, subdevice = 0x0001 */
        __raw_writel(0x00010001, KS8695_PCI_VA + KS8695_CRCSID);
 
index 17a21a291e2f6eb7d9bdb7593e76f2c2ecac2cc4..851f2458bf65f0d7443d02941f898d3c17e6494c 100644 (file)
@@ -36,6 +36,14 @@ config MACH_PCM037
          Include support for Phytec pcm037 platform. This includes
          specific configurations for the board and its peripherals.
 
+config MACH_PCM037_EET
+       bool "Support pcm037 EET board extensions"
+       depends on MACH_PCM037
+       help
+         Add support for PCM037 EET baseboard extensions. If you are using the
+         OLED display with EET, use "video=mx3fb:CMEL-OLED" kernel
+         command-line parameter.
+
 config MACH_MX31LITE
        bool "Support MX31 LITEKIT (LogicPD)"
        select ARCH_MX31
index 0322696bd11a19ad0402852b8858efe3750c6303..6b9775471be684d52e2d5fc53bc018d7ff0d3bf9 100644 (file)
@@ -11,6 +11,7 @@ obj-$(CONFIG_MACH_MX31ADS)    += mx31ads.o
 obj-$(CONFIG_MACH_MX31LILLY)   += mx31lilly.o mx31lilly-db.o
 obj-$(CONFIG_MACH_MX31LITE)    += mx31lite.o
 obj-$(CONFIG_MACH_PCM037)      += pcm037.o
+obj-$(CONFIG_MACH_PCM037_EET)  += pcm037_eet.o
 obj-$(CONFIG_MACH_MX31_3DS)    += mx31pdk.o
 obj-$(CONFIG_MACH_MX31MOBOARD) += mx31moboard.o mx31moboard-devboard.o \
                                   mx31moboard-marxbot.o
index 541181090b370dffca050e92d4a11bae94c0eb29..ee331fd6b1bd9c6e5f72159de2249e7d38e2fb7d 100644 (file)
@@ -31,6 +31,8 @@
 #include <linux/smsc911x.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <mach/mmc.h>
 #include <mach/ipu.h>
 #include <mach/mx3fb.h>
+#include <mach/mxc_nand.h>
 
 #include "devices.h"
+#include "crm_regs.h"
 
 static int armadillo5x0_pins[] = {
        /* UART1 */
@@ -93,7 +97,56 @@ static int armadillo5x0_pins[] = {
        MX31_PIN_FPSHIFT__FPSHIFT,
        MX31_PIN_DRDY0__DRDY0,
        IOMUX_MODE(MX31_PIN_LCS1, IOMUX_CONFIG_GPIO), /*ADV7125_PSAVE*/
+};
 
+/*
+ * NAND Flash
+ */
+static struct mxc_nand_platform_data armadillo5x0_nand_flash_pdata = {
+       .width          = 1,
+       .hw_ecc         = 1,
+};
+
+/*
+ * MTD NOR Flash
+ */
+static struct mtd_partition armadillo5x0_nor_flash_partitions[] = {
+       {
+               .name           = "nor.bootloader",
+               .offset         = 0x00000000,
+               .size           = 4*32*1024,
+       }, {
+               .name           = "nor.kernel",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 16*128*1024,
+       }, {
+               .name           = "nor.userland",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 110*128*1024,
+       }, {
+               .name           = "nor.config",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 1*128*1024,
+       },
+};
+
+static struct physmap_flash_data armadillo5x0_nor_flash_pdata = {
+       .width          = 2,
+       .parts          = armadillo5x0_nor_flash_partitions,
+       .nr_parts       = ARRAY_SIZE(armadillo5x0_nor_flash_partitions),
+};
+
+static struct resource armadillo5x0_nor_flash_resource = {
+       .flags          = IORESOURCE_MEM,
+       .start          = CS0_BASE_ADDR,
+       .end            = CS0_BASE_ADDR + SZ_64M - 1,
+};
+
+static struct platform_device armadillo5x0_nor_flash = {
+       .name                   = "physmap-flash",
+       .id                     = -1,
+       .num_resources          = 1,
+       .resource               = &armadillo5x0_nor_flash_resource,
 };
 
 /*
@@ -272,6 +325,16 @@ static void __init armadillo5x0_init(void)
        /* Register FB */
        mxc_register_device(&mx3_ipu, &mx3_ipu_data);
        mxc_register_device(&mx3_fb, &mx3fb_pdata);
+
+       /* Register NOR Flash */
+       mxc_register_device(&armadillo5x0_nor_flash,
+                           &armadillo5x0_nor_flash_pdata);
+
+       /* Register NAND Flash */
+       mxc_register_device(&mxc_nand_device, &armadillo5x0_nand_flash_pdata);
+
+       /* set NAND page size to 2k if not configured via boot mode pins */
+       __raw_writel(__raw_readl(MXC_CCM_RCSR) | (1 << 30), MXC_CCM_RCSR);
 }
 
 static void __init armadillo5x0_timer_init(void)
index d927eddcad460432200db70adf10ae4a5263f55e..9e87e08fb121f50288d8e98682b1d5e6d4a4aafa 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/platform_device.h>
 #include <linux/serial.h>
 #include <linux/gpio.h>
-#include <linux/dma-mapping.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/common.h>
index 4704405165a16e75b90f40846453566a8a8a959a..b48581e7dedd83b83f968167610b633ca97781df 100644 (file)
@@ -63,7 +63,7 @@ static struct imxuart_platform_data uart_pdata = {
 
 static int devboard_sdhc2_get_ro(struct device *dev)
 {
-       return gpio_get_value(SDHC2_WP);
+       return !gpio_get_value(SDHC2_WP);
 }
 
 static int devboard_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
index 641c3d6153aee66566e552e1400375d6390d3dfb..901fb0166c0e893e5f3f37732de7ae56c5fc4a40 100644 (file)
@@ -67,7 +67,7 @@ static unsigned int marxbot_pins[] = {
 
 static int marxbot_sdhc2_get_ro(struct device *dev)
 {
-       return gpio_get_value(SDHC2_WP);
+       return !gpio_get_value(SDHC2_WP);
 }
 
 static int marxbot_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
index a17f2e4116097c2a792f8f38454fb901a96efbd7..2a2da4739ecfa7039f3e8f78396c99d9f806b68f 100644 (file)
@@ -94,7 +94,7 @@ static struct imxi2c_platform_data moboard_i2c1_pdata = {
 
 static int moboard_sdhc1_get_ro(struct device *dev)
 {
-       return gpio_get_value(SDHC1_WP);
+       return !gpio_get_value(SDHC1_WP);
 }
 
 static int moboard_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
index c6f61a1f06c8a2477bbc74e5111433abadbb0c6f..840cfda341d08c883489cc537d5ed851e93bd58d 100644 (file)
@@ -18,7 +18,7 @@
 
 #include <linux/types.h>
 #include <linux/init.h>
-
+#include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/plat-ram.h>
 #include <linux/irq.h>
 #include <linux/fsl_devices.h>
 
-#include <mach/hardware.h>
+#include <media/soc_camera.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
+#include <mach/board-pcm037.h>
 #include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/i2c.h>
 #include <mach/imx-uart.h>
 #include <mach/iomux-mx3.h>
 #include <mach/ipu.h>
-#include <mach/board-pcm037.h>
+#include <mach/mmc.h>
+#include <mach/mx3_camera.h>
 #include <mach/mx3fb.h>
 #include <mach/mxc_nand.h>
-#include <mach/mmc.h>
-#ifdef CONFIG_I2C_IMX
-#include <mach/i2c.h>
-#endif
 
 #include "devices.h"
+#include "pcm037.h"
+
+static enum pcm037_board_variant pcm037_instance = PCM037_PCM970;
+
+static int __init pcm037_variant_setup(char *str)
+{
+       if (!strcmp("eet", str))
+               pcm037_instance = PCM037_EET;
+       else if (strcmp("pcm970", str))
+               pr_warning("Unknown pcm037 baseboard variant %s\n", str);
+
+       return 1;
+}
+
+/* Supported values: "pcm970" (default) and "eet" */
+__setup("pcm037_variant=", pcm037_variant_setup);
+
+enum pcm037_board_variant pcm037_variant(void)
+{
+       return pcm037_instance;
+}
+
+/* UART1 with RTS/CTS handshake signals */
+static unsigned int pcm037_uart1_handshake_pins[] = {
+       MX31_PIN_CTS1__CTS1,
+       MX31_PIN_RTS1__RTS1,
+       MX31_PIN_TXD1__TXD1,
+       MX31_PIN_RXD1__RXD1,
+};
+
+/* UART1 without RTS/CTS handshake signals */
+static unsigned int pcm037_uart1_pins[] = {
+       MX31_PIN_TXD1__TXD1,
+       MX31_PIN_RXD1__RXD1,
+};
 
 static unsigned int pcm037_pins[] = {
        /* I2C */
        MX31_PIN_CSPI2_MOSI__SCL,
        MX31_PIN_CSPI2_MISO__SDA,
+       MX31_PIN_CSPI2_SS2__I2C3_SDA,
+       MX31_PIN_CSPI2_SCLK__I2C3_SCL,
        /* SDHC1 */
        MX31_PIN_SD1_DATA3__SD1_DATA3,
        MX31_PIN_SD1_DATA2__SD1_DATA2,
@@ -73,11 +111,6 @@ static unsigned int pcm037_pins[] = {
        MX31_PIN_CSPI1_SS0__SS0,
        MX31_PIN_CSPI1_SS1__SS1,
        MX31_PIN_CSPI1_SS2__SS2,
-       /* UART1 */
-       MX31_PIN_CTS1__CTS1,
-       MX31_PIN_RTS1__RTS1,
-       MX31_PIN_TXD1__TXD1,
-       MX31_PIN_RXD1__RXD1,
        /* UART2 */
        MX31_PIN_TXD2__TXD2,
        MX31_PIN_RXD2__RXD2,
@@ -120,6 +153,22 @@ static unsigned int pcm037_pins[] = {
        MX31_PIN_D3_SPL__D3_SPL,
        MX31_PIN_D3_CLS__D3_CLS,
        MX31_PIN_LCS0__GPI03_23,
+       /* CSI */
+       IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_GPIO),
+       MX31_PIN_CSI_D6__CSI_D6,
+       MX31_PIN_CSI_D7__CSI_D7,
+       MX31_PIN_CSI_D8__CSI_D8,
+       MX31_PIN_CSI_D9__CSI_D9,
+       MX31_PIN_CSI_D10__CSI_D10,
+       MX31_PIN_CSI_D11__CSI_D11,
+       MX31_PIN_CSI_D12__CSI_D12,
+       MX31_PIN_CSI_D13__CSI_D13,
+       MX31_PIN_CSI_D14__CSI_D14,
+       MX31_PIN_CSI_D15__CSI_D15,
+       MX31_PIN_CSI_HSYNC__CSI_HSYNC,
+       MX31_PIN_CSI_MCLK__CSI_MCLK,
+       MX31_PIN_CSI_PIXCLK__CSI_PIXCLK,
+       MX31_PIN_CSI_VSYNC__CSI_VSYNC,
 };
 
 static struct physmap_flash_data pcm037_flash_data = {
@@ -250,19 +299,43 @@ static struct mxc_nand_platform_data pcm037_nand_board_info = {
        .hw_ecc = 1,
 };
 
-#ifdef CONFIG_I2C_IMX
 static struct imxi2c_platform_data pcm037_i2c_1_data = {
        .bitrate = 100000,
 };
 
+static struct imxi2c_platform_data pcm037_i2c_2_data = {
+       .bitrate = 20000,
+};
+
 static struct at24_platform_data board_eeprom = {
        .byte_len = 4096,
        .page_size = 32,
        .flags = AT24_FLAG_ADDR16,
 };
 
+static int pcm037_camera_power(struct device *dev, int on)
+{
+       /* disable or enable the camera in X7 or X8 PCM970 connector */
+       gpio_set_value(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), !on);
+       return 0;
+}
+
+static struct i2c_board_info pcm037_i2c_2_devices[] = {
+       {
+               I2C_BOARD_INFO("mt9t031", 0x5d),
+       },
+};
+
+static struct soc_camera_link iclink = {
+       .bus_id         = 0,            /* Must match with the camera ID */
+       .power          = pcm037_camera_power,
+       .board_info     = &pcm037_i2c_2_devices[0],
+       .i2c_adapter_id = 2,
+       .module_name    = "mt9t031",
+};
+
 static struct i2c_board_info pcm037_i2c_devices[] = {
-       {
+       {
                I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
                .platform_data = &board_eeprom,
        }, {
@@ -270,7 +343,14 @@ static struct i2c_board_info pcm037_i2c_devices[] = {
                .type = "pcf8563",
        }
 };
-#endif
+
+static struct platform_device pcm037_camera = {
+       .name   = "soc-camera-pdrv",
+       .id     = 0,
+       .dev    = {
+               .platform_data = &iclink,
+       },
+};
 
 /* Not connected by default */
 #ifdef PCM970_SDHC_RW_SWITCH
@@ -334,9 +414,41 @@ static struct imxmmc_platform_data sdhc_pdata = {
        .exit = pcm970_sdhc1_exit,
 };
 
+struct mx3_camera_pdata camera_pdata = {
+       .dma_dev        = &mx3_ipu.dev,
+       .flags          = MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10,
+       .mclk_10khz     = 2000,
+};
+
+static int __init pcm037_camera_alloc_dma(const size_t buf_size)
+{
+       dma_addr_t dma_handle;
+       void *buf;
+       int dma;
+
+       if (buf_size < 2 * 1024 * 1024)
+               return -EINVAL;
+
+       buf = dma_alloc_coherent(NULL, buf_size, &dma_handle, GFP_KERNEL);
+       if (!buf) {
+               pr_err("%s: cannot allocate camera buffer-memory\n", __func__);
+               return -ENOMEM;
+       }
+
+       memset(buf, 0, buf_size);
+
+       dma = dma_declare_coherent_memory(&mx3_camera.dev,
+                                       dma_handle, dma_handle, buf_size,
+                                       DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
+
+       /* The way we call dma_declare_coherent_memory only a malloc can fail */
+       return dma & DMA_MEMORY_MAP ? 0 : -ENOMEM;
+}
+
 static struct platform_device *devices[] __initdata = {
        &pcm037_flash,
        &pcm037_sram_device,
+       &pcm037_camera,
 };
 
 static struct ipu_platform_data mx3_ipu_data = {
@@ -377,6 +489,22 @@ static const struct fb_videomode fb_modedb[] = {
                .sync           = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH,
                .vmode          = FB_VMODE_NONINTERLACED,
                .flag           = 0,
+       }, {
+               /* 240x320 @ 60 Hz */
+               .name           = "CMEL-OLED",
+               .refresh        = 60,
+               .xres           = 240,
+               .yres           = 320,
+               .pixclock       = 185925,
+               .left_margin    = 9,
+               .right_margin   = 16,
+               .upper_margin   = 7,
+               .lower_margin   = 9,
+               .hsync_len      = 1,
+               .vsync_len      = 1,
+               .sync           = FB_SYNC_OE_ACT_HIGH | FB_SYNC_CLK_INVERT,
+               .vmode          = FB_VMODE_NONINTERLACED,
+               .flag           = 0,
        },
 };
 
@@ -397,6 +525,14 @@ static void __init mxc_board_init(void)
        mxc_iomux_setup_multiple_pins(pcm037_pins, ARRAY_SIZE(pcm037_pins),
                        "pcm037");
 
+       if (pcm037_variant() == PCM037_EET)
+               mxc_iomux_setup_multiple_pins(pcm037_uart1_pins,
+                       ARRAY_SIZE(pcm037_uart1_pins), "pcm037_uart1");
+       else
+               mxc_iomux_setup_multiple_pins(pcm037_uart1_handshake_pins,
+                       ARRAY_SIZE(pcm037_uart1_handshake_pins),
+                       "pcm037_uart1");
+
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
        mxc_register_device(&mxc_uart_device0, &uart_pdata);
@@ -415,18 +551,30 @@ static void __init mxc_board_init(void)
        }
 
 
-#ifdef CONFIG_I2C_IMX
+       /* I2C adapters and devices */
        i2c_register_board_info(1, pcm037_i2c_devices,
                        ARRAY_SIZE(pcm037_i2c_devices));
 
        mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data);
-#endif
+       mxc_register_device(&mxc_i2c_device2, &pcm037_i2c_2_data);
+
        mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info);
        mxc_register_device(&mxcsdhc_device0, &sdhc_pdata);
        mxc_register_device(&mx3_ipu, &mx3_ipu_data);
        mxc_register_device(&mx3_fb, &mx3fb_pdata);
        if (!gpio_usbotg_hs_activate())
                mxc_register_device(&mxc_otg_udc_device, &usb_pdata);
+
+       /* CSI */
+       /* Camera power: default - off */
+       ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), "mt9t031-power");
+       if (!ret)
+               gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_CSI_D5), 1);
+       else
+               iclink.power = NULL;
+
+       if (!pcm037_camera_alloc_dma(4 * 1024 * 1024))
+               mxc_register_device(&mx3_camera, &camera_pdata);
 }
 
 static void __init pcm037_timer_init(void)
@@ -448,4 +596,3 @@ MACHINE_START(PCM037, "Phytec Phycore pcm037")
        .init_machine   = mxc_board_init,
        .timer          = &pcm037_timer,
 MACHINE_END
-
diff --git a/arch/arm/mach-mx3/pcm037.h b/arch/arm/mach-mx3/pcm037.h
new file mode 100644 (file)
index 0000000..d692972
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __PCM037_H__
+#define __PCM037_H__
+
+enum pcm037_board_variant {
+       PCM037_PCM970,
+       PCM037_EET,
+};
+
+extern enum pcm037_board_variant pcm037_variant(void);
+
+#endif
diff --git a/arch/arm/mach-mx3/pcm037_eet.c b/arch/arm/mach-mx3/pcm037_eet.c
new file mode 100644 (file)
index 0000000..8d38600
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2009
+ * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de>
+ *
+ * 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/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+
+#include <mach/common.h>
+#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
+#include <mach/spi.h>
+#endif
+#include <mach/iomux-mx3.h>
+
+#include <asm/mach-types.h>
+
+#include "pcm037.h"
+#include "devices.h"
+
+static unsigned int pcm037_eet_pins[] = {
+       /* Reserve and hardwire GPIO 57 high - S6E63D6 chipselect */
+       IOMUX_MODE(MX31_PIN_KEY_COL7, IOMUX_CONFIG_GPIO),
+       /* GPIO keys */
+       IOMUX_MODE(MX31_PIN_GPIO1_0,    IOMUX_CONFIG_GPIO), /* 0 */
+       IOMUX_MODE(MX31_PIN_GPIO1_1,    IOMUX_CONFIG_GPIO), /* 1 */
+       IOMUX_MODE(MX31_PIN_GPIO1_2,    IOMUX_CONFIG_GPIO), /* 2 */
+       IOMUX_MODE(MX31_PIN_GPIO1_3,    IOMUX_CONFIG_GPIO), /* 3 */
+       IOMUX_MODE(MX31_PIN_SVEN0,      IOMUX_CONFIG_GPIO), /* 32 */
+       IOMUX_MODE(MX31_PIN_STX0,       IOMUX_CONFIG_GPIO), /* 33 */
+       IOMUX_MODE(MX31_PIN_SRX0,       IOMUX_CONFIG_GPIO), /* 34 */
+       IOMUX_MODE(MX31_PIN_SIMPD0,     IOMUX_CONFIG_GPIO), /* 35 */
+       IOMUX_MODE(MX31_PIN_RTS1,       IOMUX_CONFIG_GPIO), /* 38 */
+       IOMUX_MODE(MX31_PIN_CTS1,       IOMUX_CONFIG_GPIO), /* 39 */
+       IOMUX_MODE(MX31_PIN_KEY_ROW4,   IOMUX_CONFIG_GPIO), /* 50 */
+       IOMUX_MODE(MX31_PIN_KEY_ROW5,   IOMUX_CONFIG_GPIO), /* 51 */
+       IOMUX_MODE(MX31_PIN_KEY_ROW6,   IOMUX_CONFIG_GPIO), /* 52 */
+       IOMUX_MODE(MX31_PIN_KEY_ROW7,   IOMUX_CONFIG_GPIO), /* 53 */
+
+       /* LEDs */
+       IOMUX_MODE(MX31_PIN_DTR_DTE1,   IOMUX_CONFIG_GPIO), /* 44 */
+       IOMUX_MODE(MX31_PIN_DSR_DTE1,   IOMUX_CONFIG_GPIO), /* 45 */
+       IOMUX_MODE(MX31_PIN_KEY_COL5,   IOMUX_CONFIG_GPIO), /* 55 */
+       IOMUX_MODE(MX31_PIN_KEY_COL6,   IOMUX_CONFIG_GPIO), /* 56 */
+};
+
+/* SPI */
+static struct spi_board_info pcm037_spi_dev[] = {
+       {
+               .modalias       = "dac124s085",
+               .max_speed_hz   = 400000,
+               .bus_num        = 0,
+               .chip_select    = 0,            /* Index in pcm037_spi1_cs[] */
+               .mode           = SPI_CPHA,
+       },
+};
+
+/* Platform Data for MXC CSPI */
+#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
+static int pcm037_spi1_cs[] = {MXC_SPI_CS(1), IOMUX_TO_GPIO(MX31_PIN_KEY_COL7)};
+
+struct spi_imx_master pcm037_spi1_master = {
+       .chipselect = pcm037_spi1_cs,
+       .num_chipselect = ARRAY_SIZE(pcm037_spi1_cs),
+};
+#endif
+
+/* GPIO-keys input device */
+static struct gpio_keys_button pcm037_gpio_keys[] = {
+       {
+               .type   = EV_KEY,
+               .code   = KEY_L,
+               .gpio   = 0,
+               .desc   = "Wheel Manual",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_A,
+               .gpio   = 1,
+               .desc   = "Wheel AF",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_V,
+               .gpio   = 2,
+               .desc   = "Wheel View",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_M,
+               .gpio   = 3,
+               .desc   = "Wheel Menu",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_UP,
+               .gpio   = 32,
+               .desc   = "Nav Pad Up",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_RIGHT,
+               .gpio   = 33,
+               .desc   = "Nav Pad Right",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_DOWN,
+               .gpio   = 34,
+               .desc   = "Nav Pad Down",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_LEFT,
+               .gpio   = 35,
+               .desc   = "Nav Pad Left",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_ENTER,
+               .gpio   = 38,
+               .desc   = "Nav Pad Ok",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = KEY_O,
+               .gpio   = 39,
+               .desc   = "Wheel Off",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = BTN_FORWARD,
+               .gpio   = 50,
+               .desc   = "Focus Forward",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = BTN_BACK,
+               .gpio   = 51,
+               .desc   = "Focus Backward",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = BTN_MIDDLE,
+               .gpio   = 52,
+               .desc   = "Release Half",
+               .wakeup = 0,
+       }, {
+               .type   = EV_KEY,
+               .code   = BTN_EXTRA,
+               .gpio   = 53,
+               .desc   = "Release Full",
+               .wakeup = 0,
+       },
+};
+
+static struct gpio_keys_platform_data pcm037_gpio_keys_platform_data = {
+       .buttons        = pcm037_gpio_keys,
+       .nbuttons       = ARRAY_SIZE(pcm037_gpio_keys),
+       .rep            = 0, /* No auto-repeat */
+};
+
+static struct platform_device pcm037_gpio_keys_device = {
+       .name   = "gpio-keys",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &pcm037_gpio_keys_platform_data,
+       },
+};
+
+static int eet_init_devices(void)
+{
+       if (!machine_is_pcm037() || pcm037_variant() != PCM037_EET)
+               return 0;
+
+       mxc_iomux_setup_multiple_pins(pcm037_eet_pins,
+                               ARRAY_SIZE(pcm037_eet_pins), "pcm037_eet");
+
+       /* SPI */
+       spi_register_board_info(pcm037_spi_dev, ARRAY_SIZE(pcm037_spi_dev));
+#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
+       mxc_register_device(&mxc_spi_device0, &pcm037_spi1_master);
+#endif
+
+       platform_device_register(&pcm037_gpio_keys_device);
+
+       return 0;
+}
+
+late_initcall(eet_init_devices);
index e70fc7c66bbb63d0b8b28d59d3e404ac9263a5f7..ed2a48a9ce74b51634514b0d2e4eee8ec1802c49 100644 (file)
@@ -36,7 +36,6 @@
 #include <mach/hwa742.h>
 #include <mach/lcd_mipid.h>
 #include <mach/mmc.h>
-#include <mach/usb.h>
 #include <mach/clock.h>
 
 #define ADS7846_PENDOWN_GPIO   15
@@ -205,9 +204,11 @@ static int nokia770_mmc_get_cover_state(struct device *dev, int slot)
 static struct omap_mmc_platform_data nokia770_mmc2_data = {
        .nr_slots                       = 1,
        .dma_mask                       = 0xffffffff,
+       .max_freq                       = 12000000,
        .slots[0]       = {
                .set_power              = nokia770_mmc_set_power,
                .get_cover_state        = nokia770_mmc_get_cover_state,
+               .ocr_mask               = MMC_VDD_32_33|MMC_VDD_33_34,
                .name                   = "mmcblk",
        },
 };
index 0af4d6c85b4763cad50a8af100b1a0045f47c90d..6810b4aeb02cd8d8e7d34de769772b3f8c81b3e4 100644 (file)
@@ -203,5 +203,5 @@ module_exit(omap1_mbox_exit);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("omap mailbox: omap1 architecture specific functions");
-MODULE_AUTHOR("Hiroshi DOYU" <Hiroshi.DOYU@nokia.com>);
+MODULE_AUTHOR("Hiroshi DOYU <Hiroshi.DOYU@nokia.com>");
 MODULE_ALIAS("platform:omap1-mailbox");
index a2d7814896bea8eb2f96e7eaf052a616e637a307..505d98cfe508c475539445b42a504fa5c8ad20c3 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <mach/irqs.h>
 #include <mach/dma.h>
-#include <mach/irqs.h>
 #include <mach/mux.h>
 #include <mach/cpu.h>
 #include <mach/mcbsp.h>
index 9c3fdcdf76c324306702d07974e912fb59246d09..8ec2a132904d3dd3f426d58ae991b691b92cb6a8 100644 (file)
@@ -141,7 +141,7 @@ static inline void board_smc91x_init(void)
 
 static void __init omap_2430sdp_init_irq(void)
 {
-       omap2_init_common_hw(NULL);
+       omap2_init_common_hw(NULL, NULL);
        omap_init_irq();
        omap_gpio_init();
 }
index 496a90e4ea7ac16d2983759a1b62dd007160c010..ac262cd74503d756f004503f1e92f570ea87ba5d 100644 (file)
@@ -169,7 +169,7 @@ static struct platform_device *sdp3430_devices[] __initdata = {
 
 static void __init omap_3430sdp_init_irq(void)
 {
-       omap2_init_common_hw(hyb18m512160af6_sdrc_params);
+       omap2_init_common_hw(hyb18m512160af6_sdrc_params, NULL);
        omap_init_irq();
        omap_gpio_init();
 }
index 57e477bd89c6d28cc095f06ce0bc3974c9b2da28..b0c7402248f7d37958f9e940988e868a5e9ee013 100644 (file)
@@ -59,7 +59,7 @@ static void __init gic_init_irq(void)
 
 static void __init omap_4430sdp_init_irq(void)
 {
-       omap2_init_common_hw(NULL);
+       omap2_init_common_hw(NULL, NULL);
 #ifdef CONFIG_OMAP_32K_TIMER
        omap2_gp_clockevent_set_gptimer(1);
 #endif
index 06dfba888b0ca408b9691e1623774f366e1569d3..dcfc20d03894c65cba921266c753f29228add833 100644 (file)
@@ -250,7 +250,7 @@ out:
 
 static void __init omap_apollon_init_irq(void)
 {
-       omap2_init_common_hw(NULL);
+       omap2_init_common_hw(NULL, NULL);
        omap_init_irq();
        omap_gpio_init();
        apollon_init_smc91x();
index 3492162a65c383907bb093702b0c9921ff1b8ac2..fd00aa03690cc8b690de63bd74e6dff6621bdb6d 100644 (file)
@@ -33,7 +33,7 @@
 
 static void __init omap_generic_init_irq(void)
 {
-       omap2_init_common_hw(NULL);
+       omap2_init_common_hw(NULL, NULL);
        omap_init_irq();
 }
 
index e7d017cdc43851b63c1c8a7c88feb0fe05039236..7b1d61d5bb2c43ec3fda06cfa50519242a8d7802 100644 (file)
@@ -270,7 +270,7 @@ static void __init h4_init_flash(void)
 
 static void __init omap_h4_init_irq(void)
 {
-       omap2_init_common_hw(NULL);
+       omap2_init_common_hw(NULL, NULL);
        omap_init_irq();
        omap_gpio_init();
        h4_init_flash();
index d8bc0a7dcb8df64463b3653de1f9a1626bc37619..ea383f88cb1b5b93a9b1f32801cb5fb8275caedb 100644 (file)
@@ -270,7 +270,7 @@ static inline void __init ldp_init_smsc911x(void)
 
 static void __init omap_ldp_init_irq(void)
 {
-       omap2_init_common_hw(NULL);
+       omap2_init_common_hw(NULL, NULL);
        omap_init_irq();
        omap_gpio_init();
        ldp_init_smsc911x();
index 991ac9c38032832dbed51e533f10b2ef7099ce81..e00ba128cece07f17c5958bd63cc3cfad4eab81e 100644 (file)
@@ -282,7 +282,8 @@ static int __init omap3_beagle_i2c_init(void)
 
 static void __init omap3_beagle_init_irq(void)
 {
-       omap2_init_common_hw(mt46h32m32lf6_sdrc_params);
+       omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
+                            mt46h32m32lf6_sdrc_params);
        omap_init_irq();
 #ifdef CONFIG_OMAP_32K_TIMER
        omap2_gp_clockevent_set_gptimer(12);
@@ -408,6 +409,10 @@ static void __init omap3_beagle_init(void)
 
        usb_musb_init();
        omap3beagle_flash_init();
+
+       /* Ensure SDRC pins are mux'd for self-refresh */
+       omap_cfg_reg(H16_34XX_SDRC_CKE0);
+       omap_cfg_reg(H17_34XX_SDRC_CKE1);
 }
 
 static void __init omap3_beagle_map_io(void)
index d3cc145814d01236bee62974f8d7630b7892ab4a..c4b144647dc574c4e31cb9adfc389106cbbe9cca 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/i2c/twl4030.h>
+#include <linux/usb/otg.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -279,7 +280,7 @@ struct spi_board_info omap3evm_spi_board_info[] = {
 
 static void __init omap3_evm_init_irq(void)
 {
-       omap2_init_common_hw(mt46h32m32lf6_sdrc_params);
+       omap2_init_common_hw(mt46h32m32lf6_sdrc_params, NULL);
        omap_init_irq();
        omap_gpio_init();
        omap3evm_init_smc911x();
@@ -307,6 +308,10 @@ static void __init omap3_evm_init(void)
                                ARRAY_SIZE(omap3evm_spi_board_info));
 
        omap_serial_init();
+#ifdef CONFIG_NOP_USB_XCEIV
+       /* OMAP3EVM uses ISP1504 phy and so register nop transceiver */
+       usb_nop_xceiv_register();
+#endif
        usb_musb_init();
        ads7846_dev_init();
 }
index e32aa23ce9629942d9d03befd1e3ee37a9b5c78f..864ee3d021f7b416c50e979b1204e2585cf1db47 100644 (file)
@@ -40,6 +40,7 @@
 #include <mach/mcspi.h>
 #include <mach/usb.h>
 #include <mach/keypad.h>
+#include <mach/mux.h>
 
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "mmc-twl4030.h"
@@ -310,7 +311,8 @@ static int __init omap3pandora_i2c_init(void)
 
 static void __init omap3pandora_init_irq(void)
 {
-       omap2_init_common_hw(mt46h32m32lf6_sdrc_params);
+       omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
+                            mt46h32m32lf6_sdrc_params);
        omap_init_irq();
        omap_gpio_init();
 }
@@ -397,6 +399,10 @@ static void __init omap3pandora_init(void)
        omap3pandora_ads7846_init();
        pandora_keys_gpio_init();
        usb_musb_init();
+
+       /* Ensure SDRC pins are mux'd for self-refresh */
+       omap_cfg_reg(H16_34XX_SDRC_CKE0);
+       omap_cfg_reg(H17_34XX_SDRC_CKE1);
 }
 
 static void __init omap3pandora_map_io(void)
index dff5528fbfb567fbdd661d1546c5a8cc83e09cd7..6bce23004aa4ba0f1051126663f27ccd43447b18 100644 (file)
@@ -44,6 +44,7 @@
 #include <mach/gpmc.h>
 #include <mach/hardware.h>
 #include <mach/nand.h>
+#include <mach/mux.h>
 #include <mach/usb.h>
 
 #include "sdram-micron-mt46h32m32lf-6.h"
@@ -51,6 +52,7 @@
 
 #define OVERO_GPIO_BT_XGATE    15
 #define OVERO_GPIO_W2W_NRESET  16
+#define OVERO_GPIO_PENDOWN     114
 #define OVERO_GPIO_BT_NRESET   164
 #define OVERO_GPIO_USBH_CPEN   168
 #define OVERO_GPIO_USBH_NRESET 183
@@ -146,7 +148,7 @@ static struct platform_device overo_smsc911x_device = {
        .name           = "smsc911x",
        .id             = -1,
        .num_resources  = ARRAY_SIZE(overo_smsc911x_resources),
-       .resource       = &overo_smsc911x_resources,
+       .resource       = overo_smsc911x_resources,
        .dev            = {
                .platform_data = &overo_smsc911x_config,
        },
@@ -360,7 +362,8 @@ static int __init overo_i2c_init(void)
 
 static void __init overo_init_irq(void)
 {
-       omap2_init_common_hw(mt46h32m32lf6_sdrc_params);
+       omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
+                            mt46h32m32lf6_sdrc_params);
        omap_init_irq();
        omap_gpio_init();
 }
@@ -395,6 +398,10 @@ static void __init overo_init(void)
        overo_ads7846_init();
        overo_init_smsc911x();
 
+       /* Ensure SDRC pins are mux'd for self-refresh */
+       omap_cfg_reg(H16_34XX_SDRC_CKE0);
+       omap_cfg_reg(H17_34XX_SDRC_CKE1);
+
        if ((gpio_request(OVERO_GPIO_W2W_NRESET,
                          "OVERO_GPIO_W2W_NRESET") == 0) &&
            (gpio_direction_output(OVERO_GPIO_W2W_NRESET, 1) == 0)) {
index da93b86234ed47d7ef1546d55e98072c0abc913d..56d931a425f7f74f93abd03465a214f2e7bf690d 100644 (file)
@@ -278,6 +278,10 @@ static struct twl4030_gpio_platform_data rx51_gpio_data = {
        .setup                  = rx51_twlgpio_setup,
 };
 
+static struct twl4030_usb_data rx51_usb_data = {
+       .usb_mode               = T2_USB_MODE_ULPI,
+};
+
 static struct twl4030_platform_data rx51_twldata = {
        .irq_base               = TWL4030_IRQ_BASE,
        .irq_end                = TWL4030_IRQ_END,
@@ -286,6 +290,7 @@ static struct twl4030_platform_data rx51_twldata = {
        .gpio                   = &rx51_gpio_data,
        .keypad                 = &rx51_kp_data,
        .madc                   = &rx51_madc_data,
+       .usb                    = &rx51_usb_data,
 
        .vaux1                  = &rx51_vaux1,
        .vaux2                  = &rx51_vaux2,
@@ -362,6 +367,7 @@ static struct omap_onenand_platform_data board_onenand_data = {
        .gpio_irq       = 65,
        .parts          = onenand_partitions,
        .nr_parts       = ARRAY_SIZE(onenand_partitions),
+       .flags          = ONENAND_SYNC_READWRITE,
 };
 
 static void __init board_onenand_init(void)
index 374ff63c3eb2d0cc4d55d8b49f85c9413b8df6d1..1c9e07fe82668ed5139d244f82bd9ceed088eacf 100644 (file)
@@ -61,7 +61,7 @@ static struct omap_board_config_kernel rx51_config[] = {
 
 static void __init rx51_init_irq(void)
 {
-       omap2_init_common_hw(NULL);
+       omap2_init_common_hw(NULL, NULL);
        omap_init_irq();
        omap_gpio_init();
 }
@@ -75,6 +75,10 @@ static void __init rx51_init(void)
        omap_serial_init();
        usb_musb_init();
        rx51_peripherals_init();
+
+       /* Ensure SDRC pins are mux'd for self-refresh */
+       omap_cfg_reg(H16_34XX_SDRC_CKE0);
+       omap_cfg_reg(H17_34XX_SDRC_CKE1);
 }
 
 static void __init rx51_map_io(void)
index bcc0f7632deaac0590bdc4313128826d19cb465a..427b7b8b1237e5bb035eea225eb7e7755790c08f 100644 (file)
@@ -25,7 +25,7 @@
 
 static void __init omap_zoom2_init_irq(void)
 {
-       omap2_init_common_hw(NULL);
+       omap2_init_common_hw(NULL, NULL);
        omap_init_irq();
        omap_gpio_init();
 }
index b0665f161c03845725a019f1f62ea64be8cf154d..456e2ad5f62136bb33187980f92b1323e1868462 100644 (file)
@@ -27,6 +27,7 @@
 #include <mach/clock.h>
 #include <mach/clockdomain.h>
 #include <mach/cpu.h>
+#include <mach/prcm.h>
 #include <asm/div64.h>
 
 #include <mach/sdrc.h>
@@ -38,8 +39,6 @@
 #include "cm-regbits-24xx.h"
 #include "cm-regbits-34xx.h"
 
-#define MAX_CLOCK_ENABLE_WAIT          100000
-
 /* DPLL rate rounding: minimum DPLL multiplier, divider values */
 #define DPLL_MIN_MULTIPLIER            1
 #define DPLL_MIN_DIVIDER               1
@@ -274,83 +273,97 @@ unsigned long omap2_fixed_divisor_recalc(struct clk *clk)
 }
 
 /**
- * omap2_wait_clock_ready - wait for clock to enable
- * @reg: physical address of clock IDLEST register
- * @mask: value to mask against to determine if the clock is active
- * @name: name of the clock (for printk)
+ * omap2_clk_dflt_find_companion - find companion clock to @clk
+ * @clk: struct clk * to find the companion clock of
+ * @other_reg: void __iomem ** to return the companion clock CM_*CLKEN va in
+ * @other_bit: u8 ** to return the companion clock bit shift in
+ *
+ * Note: We don't need special code here for INVERT_ENABLE for the
+ * time being since INVERT_ENABLE only applies to clocks enabled by
+ * CM_CLKEN_PLL
  *
- * Returns 1 if the clock enabled in time, or 0 if it failed to enable
- * in roughly MAX_CLOCK_ENABLE_WAIT microseconds.
+ * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes it's
+ * just a matter of XORing the bits.
+ *
+ * Some clocks don't have companion clocks.  For example, modules with
+ * only an interface clock (such as MAILBOXES) don't have a companion
+ * clock.  Right now, this code relies on the hardware exporting a bit
+ * in the correct companion register that indicates that the
+ * nonexistent 'companion clock' is active.  Future patches will
+ * associate this type of code with per-module data structures to
+ * avoid this issue, and remove the casts.  No return value.
  */
-int omap2_wait_clock_ready(void __iomem *reg, u32 mask, const char *name)
+void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
+                                  u8 *other_bit)
 {
-       int i = 0;
-       int ena = 0;
+       u32 r;
 
        /*
-        * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
-        * 34xx reverses this, just to keep us on our toes
+        * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes
+        * it's just a matter of XORing the bits.
         */
-       if (cpu_mask & (RATE_IN_242X | RATE_IN_243X))
-               ena = mask;
-       else if (cpu_mask & RATE_IN_343X)
-               ena = 0;
-
-       /* Wait for lock */
-       while (((__raw_readl(reg) & mask) != ena) &&
-              (i++ < MAX_CLOCK_ENABLE_WAIT)) {
-               udelay(1);
-       }
-
-       if (i <= MAX_CLOCK_ENABLE_WAIT)
-               pr_debug("Clock %s stable after %d loops\n", name, i);
-       else
-               printk(KERN_ERR "Clock %s didn't enable in %d tries\n",
-                      name, MAX_CLOCK_ENABLE_WAIT);
-
-
-       return (i < MAX_CLOCK_ENABLE_WAIT) ? 1 : 0;
-};
+       r = ((__force u32)clk->enable_reg ^ (CM_FCLKEN ^ CM_ICLKEN));
 
+       *other_reg = (__force void __iomem *)r;
+       *other_bit = clk->enable_bit;
+}
 
-/*
- * Note: We don't need special code here for INVERT_ENABLE
- * for the time being since INVERT_ENABLE only applies to clocks enabled by
- * CM_CLKEN_PLL
+/**
+ * omap2_clk_dflt_find_idlest - find CM_IDLEST reg va, bit shift for @clk
+ * @clk: struct clk * to find IDLEST info for
+ * @idlest_reg: void __iomem ** to return the CM_IDLEST va in
+ * @idlest_bit: u8 ** to return the CM_IDLEST bit shift in
+ *
+ * Return the CM_IDLEST register address and bit shift corresponding
+ * to the module that "owns" this clock.  This default code assumes
+ * that the CM_IDLEST bit shift is the CM_*CLKEN bit shift, and that
+ * the IDLEST register address ID corresponds to the CM_*CLKEN
+ * register address ID (e.g., that CM_FCLKEN2 corresponds to
+ * CM_IDLEST2).  This is not true for all modules.  No return value.
  */
-static void omap2_clk_wait_ready(struct clk *clk)
+void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
+                               u8 *idlest_bit)
 {
-       void __iomem *reg, *other_reg, *st_reg;
-       u32 bit;
+       u32 r;
 
-       /*
-        * REVISIT: This code is pretty ugly.  It would be nice to generalize
-        * it and pull it into struct clk itself somehow.
-        */
-       reg = clk->enable_reg;
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       *idlest_bit = clk->enable_bit;
+}
 
-       /*
-        * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes
-        * it's just a matter of XORing the bits.
-        */
-       other_reg = (void __iomem *)((u32)reg ^ (CM_FCLKEN ^ CM_ICLKEN));
+/**
+ * omap2_module_wait_ready - wait for an OMAP module to leave IDLE
+ * @clk: struct clk * belonging to the module
+ *
+ * If the necessary clocks for the OMAP hardware IP block that
+ * corresponds to clock @clk are enabled, then wait for the module to
+ * indicate readiness (i.e., to leave IDLE).  This code does not
+ * belong in the clock code and will be moved in the medium term to
+ * module-dependent code.  No return value.
+ */
+static void omap2_module_wait_ready(struct clk *clk)
+{
+       void __iomem *companion_reg, *idlest_reg;
+       u8 other_bit, idlest_bit;
+
+       /* Not all modules have multiple clocks that their IDLEST depends on */
+       if (clk->ops->find_companion) {
+               clk->ops->find_companion(clk, &companion_reg, &other_bit);
+               if (!(__raw_readl(companion_reg) & (1 << other_bit)))
+                       return;
+       }
 
-       /* Check if both functional and interface clocks
-        * are running. */
-       bit = 1 << clk->enable_bit;
-       if (!(__raw_readl(other_reg) & bit))
-               return;
-       st_reg = (void __iomem *)(((u32)other_reg & ~0xf0) | 0x20); /* CM_IDLEST* */
+       clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit);
 
-       omap2_wait_clock_ready(st_reg, bit, clk->name);
+       omap2_cm_wait_idlest(idlest_reg, (1 << idlest_bit), clk->name);
 }
 
-static int omap2_dflt_clk_enable(struct clk *clk)
+int omap2_dflt_clk_enable(struct clk *clk)
 {
        u32 v;
 
        if (unlikely(clk->enable_reg == NULL)) {
-               printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
+               pr_err("clock.c: Enable for %s without enable code\n",
                       clk->name);
                return 0; /* REVISIT: -EINVAL */
        }
@@ -363,26 +376,13 @@ static int omap2_dflt_clk_enable(struct clk *clk)
        __raw_writel(v, clk->enable_reg);
        v = __raw_readl(clk->enable_reg); /* OCP barrier */
 
-       return 0;
-}
+       if (clk->ops->find_idlest)
+               omap2_module_wait_ready(clk);
 
-static int omap2_dflt_clk_enable_wait(struct clk *clk)
-{
-       int ret;
-
-       if (!clk->enable_reg) {
-               printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
-                      clk->name);
-               return 0; /* REVISIT: -EINVAL */
-       }
-
-       ret = omap2_dflt_clk_enable(clk);
-       if (ret == 0)
-               omap2_clk_wait_ready(clk);
-       return ret;
+       return 0;
 }
 
-static void omap2_dflt_clk_disable(struct clk *clk)
+void omap2_dflt_clk_disable(struct clk *clk)
 {
        u32 v;
 
@@ -406,8 +406,10 @@ static void omap2_dflt_clk_disable(struct clk *clk)
 }
 
 const struct clkops clkops_omap2_dflt_wait = {
-       .enable         = omap2_dflt_clk_enable_wait,
+       .enable         = omap2_dflt_clk_enable,
        .disable        = omap2_dflt_clk_disable,
+       .find_companion = omap2_clk_dflt_find_companion,
+       .find_idlest    = omap2_clk_dflt_find_idlest,
 };
 
 const struct clkops clkops_omap2_dflt = {
index 2679ddfa64248307abad3f45c256423a6936a0a5..9ae7540f8af2c078e35ea661d759683414ad2664 100644 (file)
@@ -65,6 +65,12 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
 u32 omap2_get_dpll_rate(struct clk *clk);
 int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name);
 void omap2_clk_prepare_for_reboot(void);
+int omap2_dflt_clk_enable(struct clk *clk);
+void omap2_dflt_clk_disable(struct clk *clk);
+void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
+                                  u8 *other_bit);
+void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
+                               u8 *idlest_bit);
 
 extern const struct clkops clkops_omap2_dflt_wait;
 extern const struct clkops clkops_omap2_dflt;
index 44de0271fc2f23a434e888176e9f34e6f0eba3dc..bc5d3ac6661191e3eeb68ef2c2d0723688d337fd 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <mach/clock.h>
 #include <mach/sram.h>
+#include <mach/prcm.h>
 #include <asm/div64.h>
 #include <asm/clkdev.h>
 
 static const struct clkops clkops_oscck;
 static const struct clkops clkops_fixed;
 
+static void omap2430_clk_i2chs_find_idlest(struct clk *clk,
+                                          void __iomem **idlest_reg,
+                                          u8 *idlest_bit);
+
+/* 2430 I2CHS has non-standard IDLEST register */
+static const struct clkops clkops_omap2430_i2chs_wait = {
+       .enable         = omap2_dflt_clk_enable,
+       .disable        = omap2_dflt_clk_disable,
+       .find_idlest    = omap2430_clk_i2chs_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
 #include "clock24xx.h"
 
 struct omap_clk {
@@ -239,6 +252,26 @@ static void __iomem *prcm_clksrc_ctrl;
  * Omap24xx specific clock functions
  *-------------------------------------------------------------------------*/
 
+/**
+ * omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ *
+ * OMAP2430 I2CHS CM_IDLEST bits are in CM_IDLEST1_CORE, but the
+ * CM_*CLKEN bits are in CM_{I,F}CLKEN2_CORE.  This custom function
+ * passes back the correct CM_IDLEST register address for I2CHS
+ * modules.  No return value.
+ */
+static void omap2430_clk_i2chs_find_idlest(struct clk *clk,
+                                          void __iomem **idlest_reg,
+                                          u8 *idlest_bit)
+{
+       *idlest_reg = OMAP_CM_REGADDR(CORE_MOD, CM_IDLEST);
+       *idlest_bit = clk->enable_bit;
+}
+
+
 /**
  * omap2xxx_clk_get_core_rate - return the CORE_CLK rate
  * @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck")
@@ -325,8 +358,8 @@ static int omap2_clk_fixed_enable(struct clk *clk)
        else if (clk == &apll54_ck)
                cval = OMAP24XX_ST_54M_APLL;
 
-       omap2_wait_clock_ready(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), cval,
-                           clk->name);
+       omap2_cm_wait_idlest(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), cval,
+                            clk->name);
 
        /*
         * REVISIT: Should we return an error code if omap2_wait_clock_ready()
index 458f00cdcbea3a354658f2b2fe7b23c25cf3ec55..d19cf7a7d8db36ef7045edb601b65361709c4ddd 100644 (file)
@@ -2337,7 +2337,7 @@ static struct clk i2c2_fck = {
 
 static struct clk i2chs2_fck = {
        .name           = "i2c_fck",
-       .ops            = &clkops_omap2_dflt_wait,
+       .ops            = &clkops_omap2430_i2chs_wait,
        .id             = 2,
        .parent         = &func_96m_ck,
        .clkdm_name     = "core_l4_clkdm",
@@ -2370,7 +2370,7 @@ static struct clk i2c1_fck = {
 
 static struct clk i2chs1_fck = {
        .name           = "i2c_fck",
-       .ops            = &clkops_omap2_dflt_wait,
+       .ops            = &clkops_omap2430_i2chs_wait,
        .id             = 1,
        .parent         = &func_96m_ck,
        .clkdm_name     = "core_l4_clkdm",
index 045da923e75bd0cde5bd275e0daed86a4592ac9e..cd7819cc0c9eb091226adf584c3608a86cb31508 100644 (file)
@@ -2,7 +2,7 @@
  * OMAP3-specific clock framework functions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2008 Nokia Corporation
+ * Copyright (C) 2007-2009 Nokia Corporation
  *
  * Written by Paul Walmsley
  * Testing and integration fixes by Jouni Högander
 
 static const struct clkops clkops_noncore_dpll_ops;
 
+static void omap3430es2_clk_ssi_find_idlest(struct clk *clk,
+                                           void __iomem **idlest_reg,
+                                           u8 *idlest_bit);
+static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
+                                           void __iomem **idlest_reg,
+                                           u8 *idlest_bit);
+static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
+                                                   void __iomem **idlest_reg,
+                                                   u8 *idlest_bit);
+
+static const struct clkops clkops_omap3430es2_ssi_wait = {
+       .enable         = omap2_dflt_clk_enable,
+       .disable        = omap2_dflt_clk_disable,
+       .find_idlest    = omap3430es2_clk_ssi_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
+static const struct clkops clkops_omap3430es2_hsotgusb_wait = {
+       .enable         = omap2_dflt_clk_enable,
+       .disable        = omap2_dflt_clk_disable,
+       .find_idlest    = omap3430es2_clk_hsotgusb_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
+static const struct clkops clkops_omap3430es2_dss_usbhost_wait = {
+       .enable         = omap2_dflt_clk_enable,
+       .disable        = omap2_dflt_clk_disable,
+       .find_idlest    = omap3430es2_clk_dss_usbhost_find_idlest,
+       .find_companion = omap2_clk_dflt_find_companion,
+};
+
 #include "clock34xx.h"
 
 struct omap_clk {
@@ -157,10 +188,13 @@ static struct omap_clk omap34xx_clks[] = {
        CLK(NULL,       "fshostusb_fck", &fshostusb_fck, CK_3430ES1),
        CLK(NULL,       "core_12m_fck", &core_12m_fck,  CK_343X),
        CLK("omap_hdq.0", "fck",        &hdq_fck,       CK_343X),
-       CLK(NULL,       "ssi_ssr_fck",  &ssi_ssr_fck,   CK_343X),
-       CLK(NULL,       "ssi_sst_fck",  &ssi_sst_fck,   CK_343X),
+       CLK(NULL,       "ssi_ssr_fck",  &ssi_ssr_fck_3430es1,   CK_3430ES1),
+       CLK(NULL,       "ssi_ssr_fck",  &ssi_ssr_fck_3430es2,   CK_3430ES2),
+       CLK(NULL,       "ssi_sst_fck",  &ssi_sst_fck_3430es1,   CK_3430ES1),
+       CLK(NULL,       "ssi_sst_fck",  &ssi_sst_fck_3430es2,   CK_3430ES2),
        CLK(NULL,       "core_l3_ick",  &core_l3_ick,   CK_343X),
-       CLK("musb_hdrc",        "ick",  &hsotgusb_ick,  CK_343X),
+       CLK("musb_hdrc",        "ick",  &hsotgusb_ick_3430es1,  CK_3430ES1),
+       CLK("musb_hdrc",        "ick",  &hsotgusb_ick_3430es2,  CK_3430ES2),
        CLK(NULL,       "sdrc_ick",     &sdrc_ick,      CK_343X),
        CLK(NULL,       "gpmc_fck",     &gpmc_fck,      CK_343X),
        CLK(NULL,       "security_l3_ick", &security_l3_ick, CK_343X),
@@ -193,18 +227,21 @@ static struct omap_clk omap34xx_clks[] = {
        CLK(NULL,       "mailboxes_ick", &mailboxes_ick, CK_343X),
        CLK(NULL,       "omapctrl_ick", &omapctrl_ick,  CK_343X),
        CLK(NULL,       "ssi_l4_ick",   &ssi_l4_ick,    CK_343X),
-       CLK(NULL,       "ssi_ick",      &ssi_ick,       CK_343X),
+       CLK(NULL,       "ssi_ick",      &ssi_ick_3430es1,       CK_3430ES1),
+       CLK(NULL,       "ssi_ick",      &ssi_ick_3430es2,       CK_3430ES2),
        CLK(NULL,       "usb_l4_ick",   &usb_l4_ick,    CK_3430ES1),
        CLK(NULL,       "security_l4_ick2", &security_l4_ick2, CK_343X),
        CLK(NULL,       "aes1_ick",     &aes1_ick,      CK_343X),
        CLK("omap_rng", "ick",          &rng_ick,       CK_343X),
        CLK(NULL,       "sha11_ick",    &sha11_ick,     CK_343X),
        CLK(NULL,       "des1_ick",     &des1_ick,      CK_343X),
-       CLK("omapfb",   "dss1_fck",     &dss1_alwon_fck, CK_343X),
+       CLK("omapfb",   "dss1_fck",     &dss1_alwon_fck_3430es1, CK_3430ES1),
+       CLK("omapfb",   "dss1_fck",     &dss1_alwon_fck_3430es2, CK_3430ES2),
        CLK("omapfb",   "tv_fck",       &dss_tv_fck,    CK_343X),
        CLK("omapfb",   "video_fck",    &dss_96m_fck,   CK_343X),
        CLK("omapfb",   "dss2_fck",     &dss2_alwon_fck, CK_343X),
-       CLK("omapfb",   "ick",          &dss_ick,       CK_343X),
+       CLK("omapfb",   "ick",          &dss_ick_3430es1,       CK_3430ES1),
+       CLK("omapfb",   "ick",          &dss_ick_3430es2,       CK_3430ES2),
        CLK(NULL,       "cam_mclk",     &cam_mclk,      CK_343X),
        CLK(NULL,       "cam_ick",      &cam_ick,       CK_343X),
        CLK(NULL,       "csi2_96m_fck", &csi2_96m_fck,  CK_343X),
@@ -300,6 +337,73 @@ static struct omap_clk omap34xx_clks[] = {
  */
 #define SDRC_MPURATE_LOOPS             96
 
+/**
+ * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ *
+ * The OMAP3430ES2 SSI target CM_IDLEST bit is at a different shift
+ * from the CM_{I,F}CLKEN bit.  Pass back the correct info via
+ * @idlest_reg and @idlest_bit.  No return value.
+ */
+static void omap3430es2_clk_ssi_find_idlest(struct clk *clk,
+                                           void __iomem **idlest_reg,
+                                           u8 *idlest_bit)
+{
+       u32 r;
+
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
+}
+
+/**
+ * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ *
+ * Some OMAP modules on OMAP3 ES2+ chips have both initiator and
+ * target IDLEST bits.  For our purposes, we are concerned with the
+ * target IDLEST bits, which exist at a different bit position than
+ * the *CLKEN bit position for these modules (DSS and USBHOST) (The
+ * default find_idlest code assumes that they are at the same
+ * position.)  No return value.
+ */
+static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
+                                                   void __iomem **idlest_reg,
+                                                   u8 *idlest_bit)
+{
+       u32 r;
+
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       /* USBHOST_IDLE has same shift */
+       *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
+}
+
+/**
+ * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
+ * @clk: struct clk * being enabled
+ * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
+ * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
+ *
+ * The OMAP3430ES2 HSOTGUSB target CM_IDLEST bit is at a different
+ * shift from the CM_{I,F}CLKEN bit.  Pass back the correct info via
+ * @idlest_reg and @idlest_bit.  No return value.
+ */
+static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
+                                                void __iomem **idlest_reg,
+                                                u8 *idlest_bit)
+{
+       u32 r;
+
+       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
+       *idlest_reg = (__force void __iomem *)r;
+       *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
+}
+
 /**
  * omap3_dpll_recalc - recalculate DPLL rate
  * @clk: DPLL struct clk
@@ -725,7 +829,9 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
        u32 unlock_dll = 0;
        u32 c;
        unsigned long validrate, sdrcrate, mpurate;
-       struct omap_sdrc_params *sp;
+       struct omap_sdrc_params *sdrc_cs0;
+       struct omap_sdrc_params *sdrc_cs1;
+       int ret;
 
        if (!clk || !rate)
                return -EINVAL;
@@ -743,8 +849,8 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
        else
                sdrcrate >>= ((clk->rate / rate) >> 1);
 
-       sp = omap2_sdrc_get_params(sdrcrate);
-       if (!sp)
+       ret = omap2_sdrc_get_params(sdrcrate, &sdrc_cs0, &sdrc_cs1);
+       if (ret)
                return -EINVAL;
 
        if (sdrcrate < MIN_SDRC_DLL_LOCK_FREQ) {
@@ -765,12 +871,29 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
 
        pr_debug("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate,
                 validrate);
-       pr_debug("clock: SDRC timing params used: %08x %08x %08x\n",
-                sp->rfr_ctrl, sp->actim_ctrla, sp->actim_ctrlb);
-
-       omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla,
-                                 sp->actim_ctrlb, new_div, unlock_dll, c,
-                                 sp->mr, rate > clk->rate);
+       pr_debug("clock: SDRC CS0 timing params used:"
+                " RFR %08x CTRLA %08x CTRLB %08x MR %08x\n",
+                sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
+                sdrc_cs0->actim_ctrlb, sdrc_cs0->mr);
+       if (sdrc_cs1)
+               pr_debug("clock: SDRC CS1 timing params used: "
+                " RFR %08x CTRLA %08x CTRLB %08x MR %08x\n",
+                sdrc_cs1->rfr_ctrl, sdrc_cs1->actim_ctrla,
+                sdrc_cs1->actim_ctrlb, sdrc_cs1->mr);
+
+       if (sdrc_cs1)
+               omap3_configure_core_dpll(
+                                 new_div, unlock_dll, c, rate > clk->rate,
+                                 sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
+                                 sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
+                                 sdrc_cs1->rfr_ctrl, sdrc_cs1->actim_ctrla,
+                                 sdrc_cs1->actim_ctrlb, sdrc_cs1->mr);
+       else
+               omap3_configure_core_dpll(
+                                 new_div, unlock_dll, c, rate > clk->rate,
+                                 sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
+                                 sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
+                                 0, 0, 0, 0);
 
        return 0;
 }
index e433aec4efdd2c65587556702df13001c9aaffe6..57cc2725b923bd31fc97eb9a5a2c85780ba83bc6 100644 (file)
@@ -1568,7 +1568,7 @@ static const struct clksel ssi_ssr_clksel[] = {
        { .parent = NULL }
 };
 
-static struct clk ssi_ssr_fck = {
+static struct clk ssi_ssr_fck_3430es1 = {
        .name           = "ssi_ssr_fck",
        .ops            = &clkops_omap2_dflt,
        .init           = &omap2_init_clksel_parent,
@@ -1581,10 +1581,31 @@ static struct clk ssi_ssr_fck = {
        .recalc         = &omap2_clksel_recalc,
 };
 
-static struct clk ssi_sst_fck = {
+static struct clk ssi_ssr_fck_3430es2 = {
+       .name           = "ssi_ssr_fck",
+       .ops            = &clkops_omap3430es2_ssi_wait,
+       .init           = &omap2_init_clksel_parent,
+       .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+       .enable_bit     = OMAP3430_EN_SSI_SHIFT,
+       .clksel_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
+       .clksel_mask    = OMAP3430_CLKSEL_SSI_MASK,
+       .clksel         = ssi_ssr_clksel,
+       .clkdm_name     = "core_l4_clkdm",
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk ssi_sst_fck_3430es1 = {
        .name           = "ssi_sst_fck",
        .ops            = &clkops_null,
-       .parent         = &ssi_ssr_fck,
+       .parent         = &ssi_ssr_fck_3430es1,
+       .fixed_div      = 2,
+       .recalc         = &omap2_fixed_divisor_recalc,
+};
+
+static struct clk ssi_sst_fck_3430es2 = {
+       .name           = "ssi_sst_fck",
+       .ops            = &clkops_null,
+       .parent         = &ssi_ssr_fck_3430es2,
        .fixed_div      = 2,
        .recalc         = &omap2_fixed_divisor_recalc,
 };
@@ -1606,9 +1627,19 @@ static struct clk core_l3_ick = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk hsotgusb_ick = {
+static struct clk hsotgusb_ick_3430es1 = {
        .name           = "hsotgusb_ick",
-       .ops            = &clkops_omap2_dflt_wait,
+       .ops            = &clkops_omap2_dflt,
+       .parent         = &core_l3_ick,
+       .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+       .enable_bit     = OMAP3430_EN_HSOTGUSB_SHIFT,
+       .clkdm_name     = "core_l3_clkdm",
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk hsotgusb_ick_3430es2 = {
+       .name           = "hsotgusb_ick",
+       .ops            = &clkops_omap3430es2_hsotgusb_wait,
        .parent         = &core_l3_ick,
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
        .enable_bit     = OMAP3430_EN_HSOTGUSB_SHIFT,
@@ -1947,7 +1978,7 @@ static struct clk ssi_l4_ick = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk ssi_ick = {
+static struct clk ssi_ick_3430es1 = {
        .name           = "ssi_ick",
        .ops            = &clkops_omap2_dflt,
        .parent         = &ssi_l4_ick,
@@ -1957,6 +1988,16 @@ static struct clk ssi_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk ssi_ick_3430es2 = {
+       .name           = "ssi_ick",
+       .ops            = &clkops_omap3430es2_ssi_wait,
+       .parent         = &ssi_l4_ick,
+       .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
+       .enable_bit     = OMAP3430_EN_SSI_SHIFT,
+       .clkdm_name     = "core_l4_clkdm",
+       .recalc         = &followparent_recalc,
+};
+
 /* REVISIT: Technically the TRM claims that this is CORE_CLK based,
  * but l4_ick makes more sense to me */
 
@@ -2024,7 +2065,7 @@ static struct clk des1_ick = {
 };
 
 /* DSS */
-static struct clk dss1_alwon_fck = {
+static struct clk dss1_alwon_fck_3430es1 = {
        .name           = "dss1_alwon_fck",
        .ops            = &clkops_omap2_dflt,
        .parent         = &dpll4_m4x2_ck,
@@ -2034,6 +2075,16 @@ static struct clk dss1_alwon_fck = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk dss1_alwon_fck_3430es2 = {
+       .name           = "dss1_alwon_fck",
+       .ops            = &clkops_omap3430es2_dss_usbhost_wait,
+       .parent         = &dpll4_m4x2_ck,
+       .enable_reg     = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
+       .enable_bit     = OMAP3430_EN_DSS1_SHIFT,
+       .clkdm_name     = "dss_clkdm",
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk dss_tv_fck = {
        .name           = "dss_tv_fck",
        .ops            = &clkops_omap2_dflt,
@@ -2067,7 +2118,7 @@ static struct clk dss2_alwon_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk dss_ick = {
+static struct clk dss_ick_3430es1 = {
        /* Handles both L3 and L4 clocks */
        .name           = "dss_ick",
        .ops            = &clkops_omap2_dflt,
@@ -2079,6 +2130,18 @@ static struct clk dss_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk dss_ick_3430es2 = {
+       /* Handles both L3 and L4 clocks */
+       .name           = "dss_ick",
+       .ops            = &clkops_omap3430es2_dss_usbhost_wait,
+       .parent         = &l4_ick,
+       .init           = &omap2_init_clk_clkdm,
+       .enable_reg     = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
+       .enable_bit     = OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
+       .clkdm_name     = "dss_clkdm",
+       .recalc         = &followparent_recalc,
+};
+
 /* CAM */
 
 static struct clk cam_mclk = {
@@ -2118,7 +2181,7 @@ static struct clk csi2_96m_fck = {
 
 static struct clk usbhost_120m_fck = {
        .name           = "usbhost_120m_fck",
-       .ops            = &clkops_omap2_dflt_wait,
+       .ops            = &clkops_omap2_dflt,
        .parent         = &dpll5_m2_ck,
        .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
@@ -2129,7 +2192,7 @@ static struct clk usbhost_120m_fck = {
 
 static struct clk usbhost_48m_fck = {
        .name           = "usbhost_48m_fck",
-       .ops            = &clkops_omap2_dflt_wait,
+       .ops            = &clkops_omap3430es2_dss_usbhost_wait,
        .parent         = &omap_48m_fck,
        .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
@@ -2141,7 +2204,7 @@ static struct clk usbhost_48m_fck = {
 static struct clk usbhost_ick = {
        /* Handles both L3 and L4 clocks */
        .name           = "usbhost_ick",
-       .ops            = &clkops_omap2_dflt_wait,
+       .ops            = &clkops_omap3430es2_dss_usbhost_wait,
        .parent         = &l4_ick,
        .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
index 1d3c93bf86d32a69c9d9d5a258bce6a51078c6fb..f3c91a1ca391f8acf011c54e827f41ec2324c30b 100644 (file)
@@ -29,9 +29,9 @@
  * These registers appear once per CM module.
  */
 
-#define OMAP3430_CM_REVISION           OMAP_CM_REGADDR(OCP_MOD, 0x0000)
-#define OMAP3430_CM_SYSCONFIG          OMAP_CM_REGADDR(OCP_MOD, 0x0010)
-#define OMAP3430_CM_POLCTRL            OMAP_CM_REGADDR(OCP_MOD, 0x009c)
+#define OMAP3430_CM_REVISION           OMAP34XX_CM_REGADDR(OCP_MOD, 0x0000)
+#define OMAP3430_CM_SYSCONFIG          OMAP34XX_CM_REGADDR(OCP_MOD, 0x0010)
+#define OMAP3430_CM_POLCTRL            OMAP34XX_CM_REGADDR(OCP_MOD, 0x009c)
 
 #define OMAP3_CM_CLKOUT_CTRL_OFFSET    0x0070
 #define OMAP3430_CM_CLKOUT_CTRL                OMAP_CM_REGADDR(OMAP3430_CCR_MOD, 0x0070)
index 2fd22f9c5f0e785e694075efbccca830f52b397e..54fec53a48e7a8e4d5cabe7fade86e184f72df92 100644 (file)
@@ -31,6 +31,8 @@ static struct platform_device gpmc_onenand_device = {
 static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
 {
        struct gpmc_timings t;
+       u32 reg;
+       int err;
 
        const int t_cer = 15;
        const int t_avdp = 12;
@@ -43,6 +45,11 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
        const int t_wpl = 40;
        const int t_wph = 30;
 
+       /* Ensure sync read and sync write are disabled */
+       reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
+       reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE;
+       writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
+
        memset(&t, 0, sizeof(t));
        t.sync_clk = 0;
        t.cs_on = 0;
@@ -74,7 +81,16 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
                          GPMC_CONFIG1_DEVICESIZE_16 |
                          GPMC_CONFIG1_MUXADDDATA);
 
-       return gpmc_cs_set_timings(cs, &t);
+       err = gpmc_cs_set_timings(cs, &t);
+       if (err)
+               return err;
+
+       /* Ensure sync read and sync write are disabled */
+       reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
+       reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE;
+       writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
+
+       return 0;
 }
 
 static void set_onenand_cfg(void __iomem *onenand_base, int latency,
@@ -124,7 +140,8 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
        } else if (cfg->flags & ONENAND_SYNC_READWRITE) {
                sync_read = 1;
                sync_write = 1;
-       }
+       } else
+               return omap2_onenand_set_async_mode(cs, onenand_base);
 
        if (!freq) {
                /* Very first call freq is not known */
index 458990e20c60db3a7f97d5b74ee33cee71496c78..a98201cc265cc08f5189b04fac3cb178212e0038 100644 (file)
@@ -48,6 +48,28 @@ int omap_chip_is(struct omap_chip_id oci)
 }
 EXPORT_SYMBOL(omap_chip_is);
 
+int omap_type(void)
+{
+       u32 val = 0;
+
+       if (cpu_is_omap24xx())
+               val = omap_ctrl_readl(OMAP24XX_CONTROL_STATUS);
+       else if (cpu_is_omap34xx())
+               val = omap_ctrl_readl(OMAP343X_CONTROL_STATUS);
+       else {
+               pr_err("Cannot detect omap type!\n");
+               goto out;
+       }
+
+       val &= OMAP2_DEVICETYPE_MASK;
+       val >>= 8;
+
+out:
+       return val;
+}
+EXPORT_SYMBOL(omap_type);
+
+
 /*----------------------------------------------------------------------------*/
 
 #define OMAP_TAP_IDCODE                0x0204
index 3a86b0f660314c28234c31fe7bd1e731d1a6b95e..e9b9bcb19b4e3b12680926435e9b0deee261e42c 100644 (file)
@@ -276,14 +276,15 @@ static int __init _omap2_init_reprogram_sdrc(void)
        return v;
 }
 
-void __init omap2_init_common_hw(struct omap_sdrc_params *sp)
+void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
+                                struct omap_sdrc_params *sdrc_cs1)
 {
        omap2_mux_init();
 #ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once the clkdev is ready */
        pwrdm_init(powerdomains_omap);
        clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
        omap2_clk_init();
-       omap2_sdrc_init(sp);
+       omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
        _omap2_init_reprogram_sdrc();
 #endif
        gpmc_init();
index fd5b8a5925cc5abaa3193066a26f9f35af1e53e4..6f71f3730c97789d461880912de06abc5861fa58 100644 (file)
@@ -282,12 +282,12 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        /* DSP or IVA2 IRQ */
-       mbox_dsp_info.irq = platform_get_irq(pdev, 0);
-       if (mbox_dsp_info.irq < 0) {
+       ret = platform_get_irq(pdev, 0);
+       if (ret < 0) {
                dev_err(&pdev->dev, "invalid irq resource\n");
-               ret = -ENODEV;
                goto err_dsp;
        }
+       mbox_dsp_info.irq = ret;
 
        ret = omap_mbox_register(&pdev->dev, &mbox_dsp_info);
        if (ret)
index a5c0f0435cd6725423ededd8b47247d000773916..0447d26d454b5ae3655daa66b3163e8b7a19c5fc 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <mach/irqs.h>
 #include <mach/dma.h>
-#include <mach/irqs.h>
 #include <mach/mux.h>
 #include <mach/cpu.h>
 #include <mach/mcbsp.h>
@@ -129,6 +128,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
+               .buffer_size    = 0x6F,
        },
        {
                .phys_base      = OMAP34XX_MCBSP2_BASE,
@@ -137,6 +137,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
+               .buffer_size    = 0x3FF,
        },
        {
                .phys_base      = OMAP34XX_MCBSP3_BASE,
@@ -145,6 +146,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP3_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP3_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
+               .buffer_size    = 0x6F,
        },
        {
                .phys_base      = OMAP34XX_MCBSP4_BASE,
@@ -153,6 +155,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP4_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP4_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
+               .buffer_size    = 0x6F,
        },
        {
                .phys_base      = OMAP34XX_MCBSP5_BASE,
@@ -161,6 +164,7 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .rx_irq         = INT_24XX_MCBSP5_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP5_IRQ_TX,
                .ops            = &omap2_mcbsp_ops,
+               .buffer_size    = 0x6F,
        },
 };
 #define OMAP34XX_MCBSP_PDATA_SZ                ARRAY_SIZE(omap34xx_mcbsp_pdata)
index 9756a878fd90263c5ddd4fcfd7a1d6dc60228c77..3c04c2f1b23ff2faae92630600f7c20a4ed2b57b 100644 (file)
@@ -119,6 +119,7 @@ static int twl_mmc_late_init(struct device *dev)
                                if (i != 0)
                                        break;
                                ret = PTR_ERR(reg);
+                               hsmmc[i].vcc = NULL;
                                goto err;
                        }
                        hsmmc[i].vcc = reg;
@@ -165,8 +166,13 @@ done:
 static void twl_mmc_cleanup(struct device *dev)
 {
        struct omap_mmc_platform_data *mmc = dev->platform_data;
+       int i;
 
        gpio_free(mmc->slots[0].switch_pin);
+       for(i = 0; i < ARRAY_SIZE(hsmmc); i++) {
+               regulator_put(hsmmc[i].vcc);
+               regulator_put(hsmmc[i].vcc_aux);
+       }
 }
 
 #ifdef CONFIG_PM
@@ -263,8 +269,19 @@ static int twl_mmc1_set_power(struct device *dev, int slot, int power_on,
 static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int vdd)
 {
        int ret = 0;
-       struct twl_mmc_controller *c = &hsmmc[1];
+       struct twl_mmc_controller *c = NULL;
        struct omap_mmc_platform_data *mmc = dev->platform_data;
+       int i;
+
+       for (i = 1; i < ARRAY_SIZE(hsmmc); i++) {
+               if (mmc == hsmmc[i].mmc) {
+                       c = &hsmmc[i];
+                       break;
+               }
+       }
+
+       if (c == NULL)
+               return -ENODEV;
 
        /* If we don't see a Vcc regulator, assume it's a fixed
         * voltage always-on regulator.
index 026c4fc883a7f21816a7b7433cd96e62092a8bc4..43d6b92b65f293ab2a329a49e2aafab58e3a9015 100644 (file)
@@ -486,6 +486,12 @@ MUX_CFG_34XX("H19_34XX_GPIO164_OUT", 0x19c,
                OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_OUTPUT)
 MUX_CFG_34XX("J25_34XX_GPIO170", 0x1c6,
                OMAP34XX_MUX_MODE4 | OMAP34XX_PIN_INPUT)
+
+/* OMAP3 SDRC CKE signals to SDR/DDR ram chips */
+MUX_CFG_34XX("H16_34XX_SDRC_CKE0", 0x262,
+               OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
+MUX_CFG_34XX("H17_34XX_SDRC_CKE1", 0x264,
+               OMAP34XX_MUX_MODE0 | OMAP34XX_PIN_OUTPUT)
 };
 
 #define OMAP34XX_PINS_SZ       ARRAY_SIZE(omap34xx_pins)
index f7b3baf766789a157dafb06b7d7d99621cf98357..21201cd4117b5d55a4380422d253687372657bad 100644 (file)
@@ -11,9 +11,6 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_PM_H
 #define __ARCH_ARM_MACH_OMAP2_PM_H
 
-extern int omap2_pm_init(void);
-extern int omap3_pm_init(void);
-
 #ifdef CONFIG_PM_DEBUG
 extern void omap2_pm_dump(int mode, int resume, unsigned int us);
 extern int omap2_pm_debug;
index db1025562fb066b8714fa4594a14162875530c05..528dbdc26e2363536335c88446b8c17ebbef234b 100644 (file)
@@ -470,7 +470,7 @@ static void __init prcm_setup_regs(void)
                          WKUP_MOD, PM_WKEN);
 }
 
-int __init omap2_pm_init(void)
+static int __init omap2_pm_init(void)
 {
        u32 l;
 
index 841d4c5ed8be10efa543d4ddb37e5d24acaaab32..488d595d8e4b337a29a589a950a5d3f73aca15a4 100644 (file)
@@ -39,7 +39,9 @@
 struct power_state {
        struct powerdomain *pwrdm;
        u32 next_state;
+#ifdef CONFIG_SUSPEND
        u32 saved_state;
+#endif
        struct list_head node;
 };
 
@@ -293,6 +295,9 @@ out:
        local_irq_enable();
 }
 
+#ifdef CONFIG_SUSPEND
+static suspend_state_t suspend_state;
+
 static int omap3_pm_prepare(void)
 {
        disable_hlt();
@@ -321,7 +326,6 @@ static int omap3_pm_suspend(void)
 restore:
        /* Restore next_pwrsts */
        list_for_each_entry(pwrst, &pwrst_list, node) {
-               set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
                state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
                if (state > pwrst->next_state) {
                        printk(KERN_INFO "Powerdomain (%s) didn't enter "
@@ -329,6 +333,7 @@ restore:
                               pwrst->pwrdm->name, pwrst->next_state);
                        ret = -1;
                }
+               set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
        }
        if (ret)
                printk(KERN_ERR "Could not enter target state in pm_suspend\n");
@@ -339,11 +344,11 @@ restore:
        return ret;
 }
 
-static int omap3_pm_enter(suspend_state_t state)
+static int omap3_pm_enter(suspend_state_t unused)
 {
        int ret = 0;
 
-       switch (state) {
+       switch (suspend_state) {
        case PM_SUSPEND_STANDBY:
        case PM_SUSPEND_MEM:
                ret = omap3_pm_suspend();
@@ -360,12 +365,30 @@ static void omap3_pm_finish(void)
        enable_hlt();
 }
 
+/* Hooks to enable / disable UART interrupts during suspend */
+static int omap3_pm_begin(suspend_state_t state)
+{
+       suspend_state = state;
+       omap_uart_enable_irqs(0);
+       return 0;
+}
+
+static void omap3_pm_end(void)
+{
+       suspend_state = PM_SUSPEND_ON;
+       omap_uart_enable_irqs(1);
+       return;
+}
+
 static struct platform_suspend_ops omap_pm_ops = {
+       .begin          = omap3_pm_begin,
+       .end            = omap3_pm_end,
        .prepare        = omap3_pm_prepare,
        .enter          = omap3_pm_enter,
        .finish         = omap3_pm_finish,
        .valid          = suspend_valid_only_mem,
 };
+#endif /* CONFIG_SUSPEND */
 
 
 /**
@@ -613,6 +636,24 @@ static void __init prcm_setup_regs(void)
        /* Clear any pending PRCM interrupts */
        prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
 
+       /* Don't attach IVA interrupts */
+       prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
+       prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
+       prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
+       prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
+
+       /* Clear any pending 'reset' flags */
+       prm_write_mod_reg(0xffffffff, MPU_MOD, RM_RSTST);
+       prm_write_mod_reg(0xffffffff, CORE_MOD, RM_RSTST);
+       prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, RM_RSTST);
+       prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, RM_RSTST);
+       prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, RM_RSTST);
+       prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, RM_RSTST);
+       prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, RM_RSTST);
+
+       /* Clear any pending PRCM interrupts */
+       prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
+
        omap3_iva_idle();
        omap3_d2d_idle();
 }
@@ -652,7 +693,7 @@ static int __init clkdms_setup(struct clockdomain *clkdm)
        return 0;
 }
 
-int __init omap3_pm_init(void)
+static int __init omap3_pm_init(void)
 {
        struct power_state *pwrst, *tmp;
        int ret;
@@ -692,7 +733,9 @@ int __init omap3_pm_init(void)
        _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend,
                                         omap34xx_cpu_suspend_sz);
 
+#ifdef CONFIG_SUSPEND
        suspend_set_ops(&omap_pm_ops);
+#endif /* CONFIG_SUSPEND */
 
        pm_idle = omap3_pm_idle;
 
index f945156d55859cbf97e0f70f9f917c7d2630107f..ced555a4cd1a1d50fb3094c892bfdfd07112caae 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/delay.h>
 
 #include <mach/common.h>
 #include <mach/prcm.h>
@@ -28,6 +29,8 @@
 static void __iomem *prm_base;
 static void __iomem *cm_base;
 
+#define MAX_MODULE_ENABLE_WAIT         100000
+
 u32 omap_prcm_get_reset_sources(void)
 {
        /* XXX This presumably needs modification for 34XX */
@@ -120,6 +123,46 @@ u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
 }
 EXPORT_SYMBOL(cm_rmw_mod_reg_bits);
 
+/**
+ * omap2_cm_wait_idlest - wait for IDLEST bit to indicate module readiness
+ * @reg: physical address of module IDLEST register
+ * @mask: value to mask against to determine if the module is active
+ * @name: name of the clock (for printk)
+ *
+ * Returns 1 if the module indicated readiness in time, or 0 if it
+ * failed to enable in roughly MAX_MODULE_ENABLE_WAIT microseconds.
+ */
+int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, const char *name)
+{
+       int i = 0;
+       int ena = 0;
+
+       /*
+        * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
+        * 34xx reverses this, just to keep us on our toes
+        */
+       if (cpu_is_omap24xx())
+               ena = mask;
+       else if (cpu_is_omap34xx())
+               ena = 0;
+       else
+               BUG();
+
+       /* Wait for lock */
+       while (((__raw_readl(reg) & mask) != ena) &&
+              (i++ < MAX_MODULE_ENABLE_WAIT))
+               udelay(1);
+
+       if (i < MAX_MODULE_ENABLE_WAIT)
+               pr_debug("cm: Module associated with clock %s ready after %d "
+                        "loops\n", name, i);
+       else
+               pr_err("cm: Module associated with clock %s didn't enable in "
+                      "%d tries\n", name, MAX_MODULE_ENABLE_WAIT);
+
+       return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
+};
+
 void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
 {
        prm_base = omap2_globals->prm;
index 2045441e8385987967eb02b7f6045c503dc94b1d..9e3bd4fa781082fb4832ad26d96518edabb548fe 100644 (file)
@@ -32,7 +32,7 @@
 #include <mach/sdrc.h>
 #include "sdrc.h"
 
-static struct omap_sdrc_params *sdrc_init_params;
+static struct omap_sdrc_params *sdrc_init_params_cs0, *sdrc_init_params_cs1;
 
 void __iomem *omap2_sdrc_base;
 void __iomem *omap2_sms_base;
@@ -45,33 +45,49 @@ void __iomem *omap2_sms_base;
 /**
  * omap2_sdrc_get_params - return SDRC register values for a given clock rate
  * @r: SDRC clock rate (in Hz)
+ * @sdrc_cs0: chip select 0 ram timings **
+ * @sdrc_cs1: chip select 1 ram timings **
  *
  * Return pre-calculated values for the SDRC_ACTIM_CTRLA,
- * SDRC_ACTIM_CTRLB, SDRC_RFR_CTRL, and SDRC_MR registers, for a given
- * SDRC clock rate 'r'.  These parameters control various timing
- * delays in the SDRAM controller that are expressed in terms of the
- * number of SDRC clock cycles to wait; hence the clock rate
- * dependency. Note that sdrc_init_params must be sorted rate
- * descending.  Also assumes that both chip-selects use the same
- * timing parameters.  Returns a struct omap_sdrc_params * upon
- * success, or NULL upon failure.
+ *  SDRC_ACTIM_CTRLB, SDRC_RFR_CTRL and SDRC_MR registers in sdrc_cs[01]
+ *  structs,for a given SDRC clock rate 'r'.
+ * These parameters control various timing delays in the SDRAM controller
+ *  that are expressed in terms of the number of SDRC clock cycles to
+ *  wait; hence the clock rate dependency.
+ *
+ * Supports 2 different timing parameters for both chip selects.
+ *
+ * Note 1: the sdrc_init_params_cs[01] must be sorted rate descending.
+ * Note 2: If sdrc_init_params_cs_1 is not NULL it must be of same size
+ *  as sdrc_init_params_cs_0.
+ *
+ * Fills in the struct omap_sdrc_params * for each chip select.
+ * Returns 0 upon success or -1 upon failure.
  */
-struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r)
+int omap2_sdrc_get_params(unsigned long r,
+                         struct omap_sdrc_params **sdrc_cs0,
+                         struct omap_sdrc_params **sdrc_cs1)
 {
-       struct omap_sdrc_params *sp;
+       struct omap_sdrc_params *sp0, *sp1;
 
-       if (!sdrc_init_params)
-               return NULL;
+       if (!sdrc_init_params_cs0)
+               return -1;
 
-       sp = sdrc_init_params;
+       sp0 = sdrc_init_params_cs0;
+       sp1 = sdrc_init_params_cs1;
 
-       while (sp->rate && sp->rate != r)
-               sp++;
+       while (sp0->rate && sp0->rate != r) {
+               sp0++;
+               if (sdrc_init_params_cs1)
+                       sp1++;
+       }
 
-       if (!sp->rate)
-               return NULL;
+       if (!sp0->rate)
+               return -1;
 
-       return sp;
+       *sdrc_cs0 = sp0;
+       *sdrc_cs1 = sp1;
+       return 0;
 }
 
 
@@ -83,13 +99,15 @@ void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
 
 /**
  * omap2_sdrc_init - initialize SMS, SDRC devices on boot
- * @sp: pointer to a null-terminated list of struct omap_sdrc_params
+ * @sdrc_cs[01]: pointers to a null-terminated list of struct omap_sdrc_params
+ *  Support for 2 chip selects timings
  *
  * Turn on smart idle modes for SDRAM scheduler and controller.
  * Program a known-good configuration for the SDRC to deal with buggy
  * bootloaders.
  */
-void __init omap2_sdrc_init(struct omap_sdrc_params *sp)
+void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
+                           struct omap_sdrc_params *sdrc_cs1)
 {
        u32 l;
 
@@ -103,11 +121,15 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sp)
        l |= (0x2 << 3);
        sdrc_write_reg(l, SDRC_SYSCONFIG);
 
-       sdrc_init_params = sp;
+       sdrc_init_params_cs0 = sdrc_cs0;
+       sdrc_init_params_cs1 = sdrc_cs1;
 
        /* XXX Enable SRFRONIDLEREQ here also? */
+       /*
+        * PWDENA should not be set due to 34xx erratum 1.150 - PWDENA
+        * can cause random memory corruption
+        */
        l = (1 << SDRC_POWER_EXTCLKDIS_SHIFT) |
-               (1 << SDRC_POWER_PWDENA_SHIFT) |
                (1 << SDRC_POWER_PAGEPOLICY_SHIFT);
        sdrc_write_reg(l, SDRC_POWER);
 }
index b094c15bfe471d6ccc47073d891bd4459b432c1a..a7421a50410bc16a23126439071c73f51b35474e 100644 (file)
@@ -54,6 +54,7 @@ struct omap_uart_state {
 
        struct plat_serial8250_port *p;
        struct list_head node;
+       struct platform_device pdev;
 
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
        int context_valid;
@@ -68,10 +69,9 @@ struct omap_uart_state {
 #endif
 };
 
-static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS];
 static LIST_HEAD(uart_list);
 
-static struct plat_serial8250_port serial_platform_data[] = {
+static struct plat_serial8250_port serial_platform_data0[] = {
        {
                .membase        = IO_ADDRESS(OMAP_UART1_BASE),
                .mapbase        = OMAP_UART1_BASE,
@@ -81,6 +81,12 @@ static struct plat_serial8250_port serial_platform_data[] = {
                .regshift       = 2,
                .uartclk        = OMAP24XX_BASE_BAUD * 16,
        }, {
+               .flags          = 0
+       }
+};
+
+static struct plat_serial8250_port serial_platform_data1[] = {
+       {
                .membase        = IO_ADDRESS(OMAP_UART2_BASE),
                .mapbase        = OMAP_UART2_BASE,
                .irq            = 73,
@@ -89,6 +95,12 @@ static struct plat_serial8250_port serial_platform_data[] = {
                .regshift       = 2,
                .uartclk        = OMAP24XX_BASE_BAUD * 16,
        }, {
+               .flags          = 0
+       }
+};
+
+static struct plat_serial8250_port serial_platform_data2[] = {
+       {
                .membase        = IO_ADDRESS(OMAP_UART3_BASE),
                .mapbase        = OMAP_UART3_BASE,
                .irq            = 74,
@@ -217,6 +229,40 @@ static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
        clk_disable(uart->fck);
 }
 
+static void omap_uart_enable_wakeup(struct omap_uart_state *uart)
+{
+       /* Set wake-enable bit */
+       if (uart->wk_en && uart->wk_mask) {
+               u32 v = __raw_readl(uart->wk_en);
+               v |= uart->wk_mask;
+               __raw_writel(v, uart->wk_en);
+       }
+
+       /* Ensure IOPAD wake-enables are set */
+       if (cpu_is_omap34xx() && uart->padconf) {
+               u16 v = omap_ctrl_readw(uart->padconf);
+               v |= OMAP3_PADCONF_WAKEUPENABLE0;
+               omap_ctrl_writew(v, uart->padconf);
+       }
+}
+
+static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
+{
+       /* Clear wake-enable bit */
+       if (uart->wk_en && uart->wk_mask) {
+               u32 v = __raw_readl(uart->wk_en);
+               v &= ~uart->wk_mask;
+               __raw_writel(v, uart->wk_en);
+       }
+
+       /* Ensure IOPAD wake-enables are cleared */
+       if (cpu_is_omap34xx() && uart->padconf) {
+               u16 v = omap_ctrl_readw(uart->padconf);
+               v &= ~OMAP3_PADCONF_WAKEUPENABLE0;
+               omap_ctrl_writew(v, uart->padconf);
+       }
+}
+
 static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
                                          int enable)
 {
@@ -246,6 +292,11 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
 
 static void omap_uart_allow_sleep(struct omap_uart_state *uart)
 {
+       if (device_may_wakeup(&uart->pdev.dev))
+               omap_uart_enable_wakeup(uart);
+       else
+               omap_uart_disable_wakeup(uart);
+
        if (!uart->clocked)
                return;
 
@@ -292,7 +343,6 @@ void omap_uart_resume_idle(int num)
                        /* Check for normal UART wakeup */
                        if (__raw_readl(uart->wk_st) & uart->wk_mask)
                                omap_uart_block_sleep(uart);
-
                        return;
                }
        }
@@ -346,16 +396,13 @@ static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
        return IRQ_NONE;
 }
 
-static u32 sleep_timeout = DEFAULT_TIMEOUT;
-
 static void omap_uart_idle_init(struct omap_uart_state *uart)
 {
-       u32 v;
        struct plat_serial8250_port *p = uart->p;
        int ret;
 
        uart->can_sleep = 0;
-       uart->timeout = sleep_timeout;
+       uart->timeout = DEFAULT_TIMEOUT;
        setup_timer(&uart->timer, omap_uart_idle_timer,
                    (unsigned long) uart);
        mod_timer(&uart->timer, jiffies + uart->timeout);
@@ -413,76 +460,101 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
                uart->padconf = 0;
        }
 
-       /* Set wake-enable bit */
-       if (uart->wk_en && uart->wk_mask) {
-               v = __raw_readl(uart->wk_en);
-               v |= uart->wk_mask;
-               __raw_writel(v, uart->wk_en);
-       }
-
-       /* Ensure IOPAD wake-enables are set */
-       if (cpu_is_omap34xx() && uart->padconf) {
-               u16 v;
-
-               v = omap_ctrl_readw(uart->padconf);
-               v |= OMAP3_PADCONF_WAKEUPENABLE0;
-               omap_ctrl_writew(v, uart->padconf);
-       }
-
        p->flags |= UPF_SHARE_IRQ;
        ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED,
                          "serial idle", (void *)uart);
        WARN_ON(ret);
 }
 
-static ssize_t sleep_timeout_show(struct kobject *kobj,
-                                 struct kobj_attribute *attr,
+void omap_uart_enable_irqs(int enable)
+{
+       int ret;
+       struct omap_uart_state *uart;
+
+       list_for_each_entry(uart, &uart_list, node) {
+               if (enable)
+                       ret = request_irq(uart->p->irq, omap_uart_interrupt,
+                               IRQF_SHARED, "serial idle", (void *)uart);
+               else
+                       free_irq(uart->p->irq, (void *)uart);
+       }
+}
+
+static ssize_t sleep_timeout_show(struct device *dev,
+                                 struct device_attribute *attr,
                                  char *buf)
 {
-       return sprintf(buf, "%u\n", sleep_timeout / HZ);
+       struct platform_device *pdev = container_of(dev,
+                                       struct platform_device, dev);
+       struct omap_uart_state *uart = container_of(pdev,
+                                       struct omap_uart_state, pdev);
+
+       return sprintf(buf, "%u\n", uart->timeout / HZ);
 }
 
-static ssize_t sleep_timeout_store(struct kobject *kobj,
-                                  struct kobj_attribute *attr,
+static ssize_t sleep_timeout_store(struct device *dev,
+                                  struct device_attribute *attr,
                                   const char *buf, size_t n)
 {
-       struct omap_uart_state *uart;
+       struct platform_device *pdev = container_of(dev,
+                                       struct platform_device, dev);
+       struct omap_uart_state *uart = container_of(pdev,
+                                       struct omap_uart_state, pdev);
        unsigned int value;
 
        if (sscanf(buf, "%u", &value) != 1) {
                printk(KERN_ERR "sleep_timeout_store: Invalid value\n");
                return -EINVAL;
        }
-       sleep_timeout = value * HZ;
-       list_for_each_entry(uart, &uart_list, node) {
-               uart->timeout = sleep_timeout;
-               if (uart->timeout)
-                       mod_timer(&uart->timer, jiffies + uart->timeout);
-               else
-                       /* A zero value means disable timeout feature */
-                       omap_uart_block_sleep(uart);
-       }
+
+       uart->timeout = value * HZ;
+       if (uart->timeout)
+               mod_timer(&uart->timer, jiffies + uart->timeout);
+       else
+               /* A zero value means disable timeout feature */
+               omap_uart_block_sleep(uart);
+
        return n;
 }
 
-static struct kobj_attribute sleep_timeout_attr =
-       __ATTR(sleep_timeout, 0644, sleep_timeout_show, sleep_timeout_store);
-
+DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show, sleep_timeout_store);
+#define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr))
 #else
 static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
+#define DEV_CREATE_FILE(dev, attr)
 #endif /* CONFIG_PM */
 
-static struct platform_device serial_device = {
-       .name                   = "serial8250",
-       .id                     = PLAT8250_DEV_PLATFORM,
-       .dev                    = {
-               .platform_data  = serial_platform_data,
+static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS] = {
+       {
+               .pdev = {
+                       .name                   = "serial8250",
+                       .id                     = PLAT8250_DEV_PLATFORM,
+                       .dev                    = {
+                               .platform_data  = serial_platform_data0,
+                       },
+               },
+       }, {
+               .pdev = {
+                       .name                   = "serial8250",
+                       .id                     = PLAT8250_DEV_PLATFORM1,
+                       .dev                    = {
+                               .platform_data  = serial_platform_data1,
+                       },
+               },
+       }, {
+               .pdev = {
+                       .name                   = "serial8250",
+                       .id                     = PLAT8250_DEV_PLATFORM2,
+                       .dev                    = {
+                               .platform_data  = serial_platform_data2,
+                       },
+               },
        },
 };
 
 void __init omap_serial_init(void)
 {
-       int i, err;
+       int i;
        const struct omap_uart_config *info;
        char name[16];
 
@@ -496,14 +568,12 @@ void __init omap_serial_init(void)
 
        if (info == NULL)
                return;
-       if (cpu_is_omap44xx()) {
-               for (i = 0; i < OMAP_MAX_NR_PORTS; i++)
-                       serial_platform_data[i].irq += 32;
-       }
 
        for (i = 0; i < OMAP_MAX_NR_PORTS; i++) {
-               struct plat_serial8250_port *p = serial_platform_data + i;
                struct omap_uart_state *uart = &omap_uart[i];
+               struct platform_device *pdev = &uart->pdev;
+               struct device *dev = &pdev->dev;
+               struct plat_serial8250_port *p = dev->platform_data;
 
                if (!(info->enabled_uarts & (1 << i))) {
                        p->membase = NULL;
@@ -531,20 +601,21 @@ void __init omap_serial_init(void)
                uart->num = i;
                p->private_data = uart;
                uart->p = p;
-               list_add(&uart->node, &uart_list);
+               list_add_tail(&uart->node, &uart_list);
+
+               if (cpu_is_omap44xx())
+                       p->irq += 32;
 
                omap_uart_enable_clocks(uart);
                omap_uart_reset(uart);
                omap_uart_idle_init(uart);
-       }
-
-       err = platform_device_register(&serial_device);
-
-#ifdef CONFIG_PM
-       if (!err)
-               err = sysfs_create_file(&serial_device.dev.kobj,
-                                       &sleep_timeout_attr.attr);
-#endif
 
+               if (WARN_ON(platform_device_register(pdev)))
+                       continue;
+               if ((cpu_is_omap34xx() && uart->padconf) ||
+                   (uart->wk_en && uart->wk_mask)) {
+                       device_init_wakeup(dev, true);
+                       DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
+               }
+       }
 }
-
index f41f8d96ddba55df420943a6ed8b6561db842342..82aa4a3d160ce917b8b85ce0959b3a5d093968ed 100644 (file)
@@ -36,7 +36,7 @@
 
        .text
 
-/* r4 parameters */
+/* r1 parameters */
 #define SDRC_NO_UNLOCK_DLL             0x0
 #define SDRC_UNLOCK_DLL                        0x1
 
@@ -58,7 +58,6 @@
 
 /* SDRC_POWER bit settings */
 #define SRFRONIDLEREQ_MASK             0x40
-#define PWDENA_MASK                    0x4
 
 /* CM_IDLEST1_CORE bit settings */
 #define ST_SDRC_MASK                   0x2
 
 /*
  * omap3_sram_configure_core_dpll - change DPLL3 M2 divider
- * r0 = new SDRC_RFR_CTRL register contents
- * r1 = new SDRC_ACTIM_CTRLA register contents
- * r2 = new SDRC_ACTIM_CTRLB register contents
- * r3 = new M2 divider setting (only 1 and 2 supported right now)
- * r4 = unlock SDRC DLL? (1 = yes, 0 = no).  Only unlock DLL for
+ *
+ * Params passed in registers:
+ *  r0 = new M2 divider setting (only 1 and 2 supported right now)
+ *  r1 = unlock SDRC DLL? (1 = yes, 0 = no).  Only unlock DLL for
  *      SDRC rates < 83MHz
- * r5 = number of MPU cycles to wait for SDRC to stabilize after
+ *  r2 = number of MPU cycles to wait for SDRC to stabilize after
  *      reprogramming the SDRC when switching to a slower MPU speed
- * r6 = new SDRC_MR_0 register value
- * r7 = increasing SDRC rate? (1 = yes, 0 = no)
+ *  r3 = increasing SDRC rate? (1 = yes, 0 = no)
+ *
+ * Params passed via the stack. The needed params will be copied in SRAM
+ *  before use by the code in SRAM (SDRAM is not accessible during SDRC
+ *  reconfiguration):
+ *  new SDRC_RFR_CTRL_0 register contents
+ *  new SDRC_ACTIM_CTRL_A_0 register contents
+ *  new SDRC_ACTIM_CTRL_B_0 register contents
+ *  new SDRC_MR_0 register value
+ *  new SDRC_RFR_CTRL_1 register contents
+ *  new SDRC_ACTIM_CTRL_A_1 register contents
+ *  new SDRC_ACTIM_CTRL_B_1 register contents
+ *  new SDRC_MR_1 register value
  *
+ * If the param SDRC_RFR_CTRL_1 is 0, the parameters
+ *  are not programmed into the SDRC CS1 registers
  */
 ENTRY(omap3_sram_configure_core_dpll)
        stmfd   sp!, {r1-r12, lr}       @ store regs to stack
-       ldr     r4, [sp, #52]           @ pull extra args off the stack
-       ldr     r5, [sp, #56]           @ load extra args from the stack
-       ldr     r6, [sp, #60]           @ load extra args from the stack
-       ldr     r7, [sp, #64]           @ load extra args from the stack
+
+                                       @ pull the extra args off the stack
+                                       @  and store them in SRAM
+       ldr     r4, [sp, #52]
+       str     r4, omap_sdrc_rfr_ctrl_0_val
+       ldr     r4, [sp, #56]
+       str     r4, omap_sdrc_actim_ctrl_a_0_val
+       ldr     r4, [sp, #60]
+       str     r4, omap_sdrc_actim_ctrl_b_0_val
+       ldr     r4, [sp, #64]
+       str     r4, omap_sdrc_mr_0_val
+       ldr     r4, [sp, #68]
+       str     r4, omap_sdrc_rfr_ctrl_1_val
+       cmp     r4, #0                  @ if SDRC_RFR_CTRL_1 is 0,
+       beq     skip_cs1_params         @  do not use cs1 params
+       ldr     r4, [sp, #72]
+       str     r4, omap_sdrc_actim_ctrl_a_1_val
+       ldr     r4, [sp, #76]
+       str     r4, omap_sdrc_actim_ctrl_b_1_val
+       ldr     r4, [sp, #80]
+       str     r4, omap_sdrc_mr_1_val
+skip_cs1_params:
        dsb                             @ flush buffered writes to interconnect
-       cmp     r7, #1                  @ if increasing SDRC clk rate,
+
+       cmp     r3, #1                  @ if increasing SDRC clk rate,
        bleq    configure_sdrc          @ program the SDRC regs early (for RFR)
-       cmp     r4, #SDRC_UNLOCK_DLL    @ set the intended DLL state
+       cmp     r1, #SDRC_UNLOCK_DLL    @ set the intended DLL state
        bleq    unlock_dll
        blne    lock_dll
        bl      sdram_in_selfrefresh    @ put SDRAM in self refresh, idle SDRC
        bl      configure_core_dpll     @ change the DPLL3 M2 divider
+       mov     r12, r2
+       bl      wait_clk_stable         @ wait for SDRC to stabilize
        bl      enable_sdrc             @ take SDRC out of idle
-       cmp     r4, #SDRC_UNLOCK_DLL    @ wait for DLL status to change
+       cmp     r1, #SDRC_UNLOCK_DLL    @ wait for DLL status to change
        bleq    wait_dll_unlock
        blne    wait_dll_lock
-       cmp     r7, #1                  @ if increasing SDRC clk rate,
+       cmp     r3, #1                  @ if increasing SDRC clk rate,
        beq     return_to_sdram         @ return to SDRAM code, otherwise,
        bl      configure_sdrc          @ reprogram SDRC regs now
-       mov     r12, r5
-       bl      wait_clk_stable         @ wait for SDRC to stabilize
 return_to_sdram:
        isb                             @ prevent speculative exec past here
        mov     r0, #0                  @ return value
@@ -113,7 +143,7 @@ return_to_sdram:
 unlock_dll:
        ldr     r11, omap3_sdrc_dlla_ctrl
        ldr     r12, [r11]
-       and     r12, r12, #FIXEDDELAY_MASK
+       bic     r12, r12, #FIXEDDELAY_MASK
        orr     r12, r12, #FIXEDDELAY_DEFAULT
        orr     r12, r12, #DLLIDLE_MASK
        str     r12, [r11]              @ (no OCP barrier needed)
@@ -129,7 +159,6 @@ sdram_in_selfrefresh:
        ldr     r12, [r11]              @ read the contents of SDRC_POWER
        mov     r9, r12                 @ keep a copy of SDRC_POWER bits
        orr     r12, r12, #SRFRONIDLEREQ_MASK   @ enable self refresh on idle
-       bic     r12, r12, #PWDENA_MASK  @ clear PWDENA
        str     r12, [r11]              @ write back to SDRC_POWER register
        ldr     r12, [r11]              @ posted-write barrier for SDRC
 idle_sdrc:
@@ -149,7 +178,7 @@ configure_core_dpll:
        ldr     r12, [r11]
        ldr     r10, core_m2_mask_val   @ modify m2 for core dpll
        and     r12, r12, r10
-       orr     r12, r12, r3, lsl #CORE_DPLL_CLKOUT_DIV_SHIFT
+       orr     r12, r12, r0, lsl #CORE_DPLL_CLKOUT_DIV_SHIFT
        str     r12, [r11]
        ldr     r12, [r11]              @ posted-write barrier for CM
        bx      lr
@@ -187,15 +216,34 @@ wait_dll_unlock:
        bne     wait_dll_unlock
        bx      lr
 configure_sdrc:
-       ldr     r11, omap3_sdrc_rfr_ctrl
-       str     r0, [r11]
-       ldr     r11, omap3_sdrc_actim_ctrla
-       str     r1, [r11]
-       ldr     r11, omap3_sdrc_actim_ctrlb
-       str     r2, [r11]
+       ldr     r12, omap_sdrc_rfr_ctrl_0_val   @ fetch value from SRAM
+       ldr     r11, omap3_sdrc_rfr_ctrl_0      @ fetch addr from SRAM
+       str     r12, [r11]                      @ store
+       ldr     r12, omap_sdrc_actim_ctrl_a_0_val
+       ldr     r11, omap3_sdrc_actim_ctrl_a_0
+       str     r12, [r11]
+       ldr     r12, omap_sdrc_actim_ctrl_b_0_val
+       ldr     r11, omap3_sdrc_actim_ctrl_b_0
+       str     r12, [r11]
+       ldr     r12, omap_sdrc_mr_0_val
        ldr     r11, omap3_sdrc_mr_0
-       str     r6, [r11]
-       ldr     r6, [r11]               @ posted-write barrier for SDRC
+       str     r12, [r11]
+       ldr     r12, omap_sdrc_rfr_ctrl_1_val
+       cmp     r12, #0                 @ if SDRC_RFR_CTRL_1 is 0,
+       beq     skip_cs1_prog           @  do not program cs1 params
+       ldr     r11, omap3_sdrc_rfr_ctrl_1
+       str     r12, [r11]
+       ldr     r12, omap_sdrc_actim_ctrl_a_1_val
+       ldr     r11, omap3_sdrc_actim_ctrl_a_1
+       str     r12, [r11]
+       ldr     r12, omap_sdrc_actim_ctrl_b_1_val
+       ldr     r11, omap3_sdrc_actim_ctrl_b_1
+       str     r12, [r11]
+       ldr     r12, omap_sdrc_mr_1_val
+       ldr     r11, omap3_sdrc_mr_1
+       str     r12, [r11]
+skip_cs1_prog:
+       ldr     r12, [r11]              @ posted-write barrier for SDRC
        bx      lr
 
 omap3_sdrc_power:
@@ -206,14 +254,40 @@ omap3_cm_idlest1_core:
        .word OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST)
 omap3_cm_iclken1_core:
        .word OMAP34XX_CM_REGADDR(CORE_MOD, CM_ICLKEN1)
-omap3_sdrc_rfr_ctrl:
+
+omap3_sdrc_rfr_ctrl_0:
        .word OMAP34XX_SDRC_REGADDR(SDRC_RFR_CTRL_0)
-omap3_sdrc_actim_ctrla:
+omap3_sdrc_rfr_ctrl_1:
+       .word OMAP34XX_SDRC_REGADDR(SDRC_RFR_CTRL_1)
+omap3_sdrc_actim_ctrl_a_0:
        .word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_A_0)
-omap3_sdrc_actim_ctrlb:
+omap3_sdrc_actim_ctrl_a_1:
+       .word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_A_1)
+omap3_sdrc_actim_ctrl_b_0:
        .word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_B_0)
+omap3_sdrc_actim_ctrl_b_1:
+       .word OMAP34XX_SDRC_REGADDR(SDRC_ACTIM_CTRL_B_1)
 omap3_sdrc_mr_0:
        .word OMAP34XX_SDRC_REGADDR(SDRC_MR_0)
+omap3_sdrc_mr_1:
+       .word OMAP34XX_SDRC_REGADDR(SDRC_MR_1)
+omap_sdrc_rfr_ctrl_0_val:
+       .word 0xDEADBEEF
+omap_sdrc_rfr_ctrl_1_val:
+       .word 0xDEADBEEF
+omap_sdrc_actim_ctrl_a_0_val:
+       .word 0xDEADBEEF
+omap_sdrc_actim_ctrl_a_1_val:
+       .word 0xDEADBEEF
+omap_sdrc_actim_ctrl_b_0_val:
+       .word 0xDEADBEEF
+omap_sdrc_actim_ctrl_b_1_val:
+       .word 0xDEADBEEF
+omap_sdrc_mr_0_val:
+       .word 0xDEADBEEF
+omap_sdrc_mr_1_val:
+       .word 0xDEADBEEF
+
 omap3_sdrc_dlla_status:
        .word OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS)
 omap3_sdrc_dlla_ctrl:
@@ -223,3 +297,4 @@ core_m2_mask_val:
 
 ENTRY(omap3_sram_configure_core_dpll_sz)
        .word   . - omap3_sram_configure_core_dpll
+
index d85296dc896c2090136652997a2d401c5e60e576..739e59e8025cc7b109707ac7f4b302afbb82fb14 100644 (file)
@@ -155,20 +155,6 @@ static struct platform_device musb_device = {
        .resource       = musb_resources,
 };
 
-#ifdef CONFIG_NOP_USB_XCEIV
-static u64 nop_xceiv_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device nop_xceiv_device = {
-       .name           = "nop_usb_xceiv",
-       .id             = -1,
-       .dev = {
-               .dma_mask               = &nop_xceiv_dmamask,
-               .coherent_dma_mask      = DMA_BIT_MASK(32),
-               .platform_data          = NULL,
-       },
-};
-#endif
-
 void __init usb_musb_init(void)
 {
        if (cpu_is_omap243x())
@@ -183,13 +169,6 @@ void __init usb_musb_init(void)
         */
        musb_plat.clock = "ick";
 
-#ifdef CONFIG_NOP_USB_XCEIV
-       if (platform_device_register(&nop_xceiv_device) < 0) {
-               printk(KERN_ERR "Unable to register NOP-XCEIV device\n");
-               return;
-       }
-#endif
-
        if (platform_device_register(&musb_device) < 0) {
                printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
                return;
index 63b10d9bb1d3a374908206d78fb5cc2426a408e5..9cd09465a0e8bbb9474e22d24160de5ef50500a5 100644 (file)
@@ -1141,12 +1141,16 @@ struct power_supply_info em_x270_psy_info = {
 
 static void em_x270_battery_low(void)
 {
+#if defined(CONFIG_APM_EMULATION)
        apm_queue_event(APM_LOW_BATTERY);
+#endif
 }
 
 static void em_x270_battery_critical(void)
 {
+#if defined(CONFIG_APM_EMULATION)
        apm_queue_event(APM_CRITICAL_SUSPEND);
+#endif
 }
 
 struct da9030_battery_info em_x270_batterty_info = {
index 16eb02552d5def1fff4d61bef51ac84ffa6f333b..a3449e35a6f554eb781d6203c294e648528edce9 100644 (file)
@@ -3,10 +3,12 @@
 
 #include <sound/core.h>
 #include <sound/pcm.h>
+#include <sound/ac97_codec.h>
 
 /*
  * @reset_gpio: AC97 reset gpio (normally gpio113 or gpio95)
  *              a -1 value means no gpio will be used for reset
+ * @codec_pdata: AC97 codec platform_data
 
  * reset_gpio should only be specified for pxa27x CPUs where a silicon
  * bug prevents correct operation of the reset line. If not specified,
@@ -20,6 +22,7 @@ typedef struct {
        void (*resume)(void *);
        void *priv;
        int reset_gpio;
+       void *codec_pdata[AC97_BUS_MAX_DEVICES];
 } pxa2xx_audio_ops_t;
 
 extern void pxa_set_ac97_info(pxa2xx_audio_ops_t *ops);
index ae8441192ef07a2d0c3ab7f07fafdbf2f974859b..7139e0dc26d16062304bd72beca1f339e61899e7 100644 (file)
 #define GPIO37_ULPI_DATA_OUT_7 MFP_CFG(GPIO37, AF3)
 #define GPIO33_ULPI_OTG_INTR   MFP_CFG(GPIO33, AF1)
 
-#define ULPI_DIR       MFP_CFG_DRV(ULPI_DIR, MFP_AF0, MFP_DS01X)
-#define ULPI_NXT       MFP_CFG_DRV(ULPI_NXT, MFP_AF0, MFP_DS01X)
-#define ULPI_STP       MFP_CFG_DRV(ULPI_STP, MFP_AF0, MFP_DS01X)
+#define ULPI_DIR       MFP_CFG_DRV(ULPI_DIR, AF0, DS01X)
+#define ULPI_NXT       MFP_CFG_DRV(ULPI_NXT, AF0, DS01X)
+#define ULPI_STP       MFP_CFG_DRV(ULPI_STP, AF0, DS01X)
 #endif /* CONFIG_CPU_PXA310 */
 
 #endif /* __ASM_ARCH_MFP_PXA300_H */
index ed70f281dd090812f71dac139aaa795660b7b0dd..169fcc18154e68389f32fe35d03a5f95b44f48e1 100644 (file)
@@ -128,6 +128,10 @@ static unsigned long palmld_pin_config[] __initdata = {
        GPIO38_GPIO,    /* wifi ready */
        GPIO81_GPIO,    /* wifi reset */
 
+       /* FFUART */
+       GPIO34_FFUART_RXD,
+       GPIO39_FFUART_TXD,
+
        /* HDD */
        GPIO98_GPIO,    /* HDD reset */
        GPIO115_GPIO,   /* HDD power */
index aae64a12a734e2ce82d2e91cca54d27d0b1cd345..33f726ff55e5ec30784400847746129826bea3be 100644 (file)
@@ -111,6 +111,10 @@ static unsigned long palmt5_pin_config[] __initdata = {
        /* PWM */
        GPIO16_PWM0_OUT,
 
+       /* FFUART */
+       GPIO34_FFUART_RXD,
+       GPIO39_FFUART_TXD,
+
        /* MISC */
        GPIO10_GPIO,    /* hotsync button */
        GPIO90_GPIO,    /* power detect */
index 6c15d84bde53a4853d1ac8e8aa8c119e47ca421e..83d020879581f5438fc1165885fae3140ec11d68 100644 (file)
@@ -127,6 +127,10 @@ static unsigned long palmtx_pin_config[] __initdata = {
        GPIO76_LCD_PCLK,
        GPIO77_LCD_BIAS,
 
+       /* FFUART */
+       GPIO34_FFUART_RXD,
+       GPIO39_FFUART_TXD,
+
        /* MISC. */
        GPIO10_GPIO,    /* hotsync button */
        GPIO12_GPIO,    /* power detect */
index 6f678d93bf4eb2f0da4b1a142c39945d127503be..09b7b1a10cadf9beb86fb51affa9bbea4ed26c11 100644 (file)
@@ -250,7 +250,7 @@ static DEFINE_PXA3_CKEN(pxa3xx_mmc2, MMC2, 19500000, 0);
 static struct clk_lookup pxa3xx_clkregs[] = {
        INIT_CLKREG(&clk_pxa3xx_pout, NULL, "CLK_POUT"),
        /* Power I2C clock is always on */
-       INIT_CLKREG(&clk_dummy, "pxa2xx-i2c.1", NULL),
+       INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL),
        INIT_CLKREG(&clk_pxa3xx_lcd, "pxa2xx-fb", NULL),
        INIT_CLKREG(&clk_pxa3xx_camera, NULL, "CAMCLK"),
        INIT_CLKREG(&clk_pxa3xx_ac97, NULL, "AC97CLK"),
index a06f19edebb3a201da7e33645c0e7297af97e13c..753ec4df17b9447f412fbf6edded190e74f4c098 100644 (file)
@@ -409,7 +409,7 @@ err1:
 
 static void treo680_irda_shutdown(struct device *dev)
 {
-       gpio_free(GPIO_NR_TREO680_AMP_EN);
+       gpio_free(GPIO_NR_TREO680_IR_EN);
 }
 
 static struct pxaficp_platform_data treo680_ficp_info = {
index cefd1c0a854aa920df0fdd5704dee5550a07123f..84095440a87870477e78da5cfe0349fb69993efd 100644 (file)
@@ -197,10 +197,12 @@ static void __init zylonite_detect_lcd_panel(void)
        for (i = 0; i < NUM_LCD_DETECT_PINS; i++) {
                id = id << 1;
                gpio = mfp_to_gpio(lcd_detect_pins[i]);
+               gpio_request(gpio, "LCD_ID_PINS");
                gpio_direction_input(gpio);
 
                if (gpio_get_value(gpio))
                        id = id | 0x1;
+               gpio_free(gpio);
        }
 
        /* lcd id, flush out bit 1 */
index cc5a22833605e27e99980c866781e9d0fd60b300..60d08f23f5e4ed3933e2ad9855efb8b5b9ad7332 100644 (file)
@@ -176,10 +176,12 @@ static void __init zylonite_detect_lcd_panel(void)
        for (i = 0; i < NUM_LCD_DETECT_PINS; i++) {
                id = id << 1;
                gpio = mfp_to_gpio(lcd_detect_pins[i]);
+               gpio_request(gpio, "LCD_ID_PINS");
                gpio_direction_input(gpio);
 
                if (gpio_get_value(gpio))
                        id = id | 0x1;
+               gpio_free(gpio);
        }
 
        /* lcd id, flush out bit 1 */
index 9ea9c05093cd47afed1d6798d5a2eeb9d9333f43..facbd49eec67e30bb1d3dbfedf2364fe964a1cdc 100644 (file)
@@ -208,8 +208,7 @@ struct platform_device realview_i2c_device = {
 
 static struct i2c_board_info realview_i2c_board_info[] = {
        {
-               I2C_BOARD_INFO("rtc-ds1307", 0xd0 >> 1),
-               .type = "ds1338",
+               I2C_BOARD_INFO("ds1338", 0xd0 >> 1),
        },
 };
 
index 8fe192081d3a7f7720189ab81f397fa2a12b8b0b..f8b879a7973c6fd457e2b1829068a4894dd27922 100644 (file)
@@ -28,7 +28,7 @@ static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)
                return NULL;
 
        chip = &s3c24xx_gpios[pin/32];
-       return (S3C2410_GPIO_OFFSET(pin) > chip->chip.ngpio) ? chip : NULL;
+       return (S3C2410_GPIO_OFFSET(pin) < chip->chip.ngpio) ? chip : NULL;
 }
 
 #endif /* __ASM_ARCH_GPIO_CORE_H */
index 6a5bc3021bdb6218a5ffb31a0229b797f3994797..ec71a69657867edcbc7ffb79a2eda78d36f73bf3 100644 (file)
@@ -48,8 +48,6 @@
 #include <plat/mci.h>
 #include <plat/udc.h>
 
-#include <plat/regs-serial.h>
-
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
@@ -275,6 +273,7 @@ static struct s3c2410_nand_set mini2440_nand_sets[] __initdata = {
                .nr_chips       = 1,
                .nr_partitions  = ARRAY_SIZE(mini2440_default_nand_part),
                .partitions     = mini2440_default_nand_part,
+               .flash_bbt      = 1, /* we use u-boot to create a BBT */
        },
 };
 
index e23b581aa0e169dff61e4b58c4c8c73370277f5e..0fb385bd9cd9c44eaa164cfe14d6721063eab8d3 100644 (file)
@@ -433,8 +433,7 @@ static struct s3c2410_nand_set gta02_nand_sets[] = {
                 */
                .name           = "neo1973-nand",
                .nr_chips       = 1,
-               .use_bbt        = 1,
-               .force_soft_ecc = 1,
+               .flash_bbt      = 1,
        },
 };
 
index 5cd04d6751b30166c1d3a1146725ddfa3a840e34..111f7ea32b384bd6e492d1cb1c0cf9635632c035 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/timer.h>
 #include <linux/io.h>
+#include <linux/seq_file.h>
 
 #include <asm/clkdev.h>
 #include <mach/hardware.h>
@@ -702,6 +703,7 @@ static struct clk amba_clk = {
        .rate       = 52000000, /* this varies! */
        .hw_ctrld   = true,
        .reset      = false,
+       .lock       = __SPIN_LOCK_UNLOCKED(amba_clk.lock),
 };
 
 /*
@@ -720,6 +722,7 @@ static struct clk cpu_clk = {
        .set_rate   = clk_set_rate_cpuclk,
        .get_rate   = clk_get_rate_cpuclk,
        .round_rate = clk_round_rate_cpuclk,
+       .lock       = __SPIN_LOCK_UNLOCKED(cpu_clk.lock),
 };
 
 static struct clk nandif_clk = {
@@ -732,6 +735,7 @@ static struct clk nandif_clk = {
        .clk_val    = U300_SYSCON_SBCER_NANDIF_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(nandif_clk.lock),
 };
 
 static struct clk semi_clk = {
@@ -744,6 +748,7 @@ static struct clk semi_clk = {
        .clk_val    = U300_SYSCON_SBCER_SEMI_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(semi_clk.lock),
 };
 
 #ifdef CONFIG_MACH_U300_BS335
@@ -758,6 +763,7 @@ static struct clk isp_clk = {
        .clk_val    = U300_SYSCON_SBCER_ISP_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(isp_clk.lock),
 };
 
 static struct clk cds_clk = {
@@ -771,6 +777,7 @@ static struct clk cds_clk = {
        .clk_val    = U300_SYSCON_SBCER_CDS_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(cds_clk.lock),
 };
 #endif
 
@@ -785,6 +792,7 @@ static struct clk dma_clk = {
        .clk_val    = U300_SYSCON_SBCER_DMAC_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(dma_clk.lock),
 };
 
 static struct clk aaif_clk = {
@@ -798,6 +806,7 @@ static struct clk aaif_clk = {
        .clk_val    = U300_SYSCON_SBCER_AAIF_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(aaif_clk.lock),
 };
 
 static struct clk apex_clk = {
@@ -811,6 +820,7 @@ static struct clk apex_clk = {
        .clk_val    = U300_SYSCON_SBCER_APEX_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(apex_clk.lock),
 };
 
 static struct clk video_enc_clk = {
@@ -825,6 +835,7 @@ static struct clk video_enc_clk = {
        .clk_val    = U300_SYSCON_SBCER_VIDEO_ENC_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(video_enc_clk.lock),
 };
 
 static struct clk xgam_clk = {
@@ -839,6 +850,7 @@ static struct clk xgam_clk = {
        .get_rate   = clk_get_rate_xgamclk,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(xgam_clk.lock),
 };
 
 /* This clock is used to activate the video encoder */
@@ -854,6 +866,7 @@ static struct clk ahb_clk = {
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
        .get_rate   = clk_get_rate_ahb_clk,
+       .lock       = __SPIN_LOCK_UNLOCKED(ahb_clk.lock),
 };
 
 
@@ -871,6 +884,7 @@ static struct clk ahb_subsys_clk = {
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
        .get_rate   = clk_get_rate_ahb_clk,
+       .lock       = __SPIN_LOCK_UNLOCKED(ahb_subsys_clk.lock),
 };
 
 static struct clk intcon_clk = {
@@ -882,6 +896,8 @@ static struct clk intcon_clk = {
        .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RRR,
        .res_mask   = U300_SYSCON_RRR_INTCON_RESET_EN,
        /* INTCON can be reset but not clock-gated */
+       .lock       = __SPIN_LOCK_UNLOCKED(intcon_clk.lock),
+
 };
 
 static struct clk mspro_clk = {
@@ -895,6 +911,7 @@ static struct clk mspro_clk = {
        .clk_val    = U300_SYSCON_SBCER_MSPRO_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(mspro_clk.lock),
 };
 
 static struct clk emif_clk = {
@@ -909,6 +926,7 @@ static struct clk emif_clk = {
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
        .get_rate   = clk_get_rate_emif_clk,
+       .lock       = __SPIN_LOCK_UNLOCKED(emif_clk.lock),
 };
 
 
@@ -926,6 +944,7 @@ static struct clk fast_clk = {
        .clk_val    = U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(fast_clk.lock),
 };
 
 static struct clk mmcsd_clk = {
@@ -942,6 +961,7 @@ static struct clk mmcsd_clk = {
        .round_rate = clk_round_rate_mclk,
        .disable    = syscon_clk_disable,
        .enable     = syscon_clk_enable,
+       .lock       = __SPIN_LOCK_UNLOCKED(mmcsd_clk.lock),
 };
 
 static struct clk i2s0_clk = {
@@ -956,6 +976,7 @@ static struct clk i2s0_clk = {
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
        .get_rate   = clk_get_rate_i2s_i2c_spi,
+       .lock       = __SPIN_LOCK_UNLOCKED(i2s0_clk.lock),
 };
 
 static struct clk i2s1_clk = {
@@ -970,6 +991,7 @@ static struct clk i2s1_clk = {
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
        .get_rate   = clk_get_rate_i2s_i2c_spi,
+       .lock       = __SPIN_LOCK_UNLOCKED(i2s1_clk.lock),
 };
 
 static struct clk i2c0_clk = {
@@ -984,6 +1006,7 @@ static struct clk i2c0_clk = {
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
        .get_rate   = clk_get_rate_i2s_i2c_spi,
+       .lock       = __SPIN_LOCK_UNLOCKED(i2c0_clk.lock),
 };
 
 static struct clk i2c1_clk = {
@@ -998,6 +1021,7 @@ static struct clk i2c1_clk = {
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
        .get_rate   = clk_get_rate_i2s_i2c_spi,
+       .lock       = __SPIN_LOCK_UNLOCKED(i2c1_clk.lock),
 };
 
 static struct clk spi_clk = {
@@ -1012,6 +1036,7 @@ static struct clk spi_clk = {
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
        .get_rate   = clk_get_rate_i2s_i2c_spi,
+       .lock       = __SPIN_LOCK_UNLOCKED(spi_clk.lock),
 };
 
 #ifdef CONFIG_MACH_U300_BS335
@@ -1026,6 +1051,7 @@ static struct clk uart1_clk = {
        .clk_val    = U300_SYSCON_SBCER_UART1_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(uart1_clk.lock),
 };
 #endif
 
@@ -1044,6 +1070,7 @@ static struct clk slow_clk = {
        .clk_val    = U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(slow_clk.lock),
 };
 
 /* TODO: implement SYSCON clock? */
@@ -1055,6 +1082,7 @@ static struct clk wdog_clk = {
        .rate       = 32768,
        .reset      = false,
        /* This is always on, cannot be enabled/disabled or reset */
+       .lock       = __SPIN_LOCK_UNLOCKED(wdog_clk.lock),
 };
 
 /* This one is hardwired to PLL13 */
@@ -1069,6 +1097,7 @@ static struct clk uart_clk = {
        .clk_val    = U300_SYSCON_SBCER_UART_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(uart_clk.lock),
 };
 
 static struct clk keypad_clk = {
@@ -1082,6 +1111,7 @@ static struct clk keypad_clk = {
        .clk_val    = U300_SYSCON_SBCER_KEYPAD_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(keypad_clk.lock),
 };
 
 static struct clk gpio_clk = {
@@ -1095,6 +1125,7 @@ static struct clk gpio_clk = {
        .clk_val    = U300_SYSCON_SBCER_GPIO_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(gpio_clk.lock),
 };
 
 static struct clk rtc_clk = {
@@ -1106,6 +1137,7 @@ static struct clk rtc_clk = {
        .res_reg    = U300_SYSCON_VBASE + U300_SYSCON_RSR,
        .res_mask   = U300_SYSCON_RSR_RTC_RESET_EN,
        /* This clock is always on, cannot be enabled/disabled */
+       .lock       = __SPIN_LOCK_UNLOCKED(rtc_clk.lock),
 };
 
 static struct clk bustr_clk = {
@@ -1119,6 +1151,7 @@ static struct clk bustr_clk = {
        .clk_val    = U300_SYSCON_SBCER_BTR_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(bustr_clk.lock),
 };
 
 static struct clk evhist_clk = {
@@ -1132,6 +1165,7 @@ static struct clk evhist_clk = {
        .clk_val    = U300_SYSCON_SBCER_EH_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(evhist_clk.lock),
 };
 
 static struct clk timer_clk = {
@@ -1145,6 +1179,7 @@ static struct clk timer_clk = {
        .clk_val    = U300_SYSCON_SBCER_ACC_TMR_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(timer_clk.lock),
 };
 
 static struct clk app_timer_clk = {
@@ -1158,6 +1193,7 @@ static struct clk app_timer_clk = {
        .clk_val    = U300_SYSCON_SBCER_APP_TMR_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(app_timer_clk.lock),
 };
 
 #ifdef CONFIG_MACH_U300_BS335
@@ -1172,6 +1208,7 @@ static struct clk ppm_clk = {
        .clk_val    = U300_SYSCON_SBCER_PPM_CLK_EN,
        .enable     = syscon_clk_enable,
        .disable    = syscon_clk_disable,
+       .lock       = __SPIN_LOCK_UNLOCKED(ppm_clk.lock),
 };
 #endif
 
@@ -1187,53 +1224,53 @@ static struct clk ppm_clk = {
  */
 static struct clk_lookup lookups[] = {
        /* Connected directly to the AMBA bus */
-       DEF_LOOKUP("amba", &amba_clk),
-       DEF_LOOKUP("cpu", &cpu_clk),
-       DEF_LOOKUP("nandif", &nandif_clk),
-       DEF_LOOKUP("semi", &semi_clk),
+       DEF_LOOKUP("amba",      &amba_clk),
+       DEF_LOOKUP("cpu",       &cpu_clk),
+       DEF_LOOKUP("fsmc",      &nandif_clk),
+       DEF_LOOKUP("semi",      &semi_clk),
 #ifdef CONFIG_MACH_U300_BS335
-       DEF_LOOKUP("isp", &isp_clk),
-       DEF_LOOKUP("cds", &cds_clk),
+       DEF_LOOKUP("isp",       &isp_clk),
+       DEF_LOOKUP("cds",       &cds_clk),
 #endif
-       DEF_LOOKUP("dma", &dma_clk),
-       DEF_LOOKUP("aaif", &aaif_clk),
-       DEF_LOOKUP("apex", &apex_clk),
+       DEF_LOOKUP("dma",       &dma_clk),
+       DEF_LOOKUP("msl",       &aaif_clk),
+       DEF_LOOKUP("apex",      &apex_clk),
        DEF_LOOKUP("video_enc", &video_enc_clk),
-       DEF_LOOKUP("xgam", &xgam_clk),
-       DEF_LOOKUP("ahb", &ahb_clk),
+       DEF_LOOKUP("xgam",      &xgam_clk),
+       DEF_LOOKUP("ahb",       &ahb_clk),
        /* AHB bridge clocks */
-       DEF_LOOKUP("ahb", &ahb_subsys_clk),
-       DEF_LOOKUP("intcon", &intcon_clk),
-       DEF_LOOKUP("mspro", &mspro_clk),
-       DEF_LOOKUP("pl172", &emif_clk),
+       DEF_LOOKUP("ahb_subsys", &ahb_subsys_clk),
+       DEF_LOOKUP("intcon",    &intcon_clk),
+       DEF_LOOKUP("mspro",     &mspro_clk),
+       DEF_LOOKUP("pl172",     &emif_clk),
        /* FAST bridge clocks */
-       DEF_LOOKUP("fast", &fast_clk),
-       DEF_LOOKUP("mmci", &mmcsd_clk),
+       DEF_LOOKUP("fast",      &fast_clk),
+       DEF_LOOKUP("mmci",      &mmcsd_clk),
        /*
         * The .0 and .1 identifiers on these comes from the platform device
         * .id field and are assigned when the platform devices are registered.
         */
-       DEF_LOOKUP("i2s.0", &i2s0_clk),
-       DEF_LOOKUP("i2s.1", &i2s1_clk),
-       DEF_LOOKUP("stddci2c.0", &i2c0_clk),
-       DEF_LOOKUP("stddci2c.1", &i2c1_clk),
-       DEF_LOOKUP("pl022", &spi_clk),
+       DEF_LOOKUP("i2s.0",     &i2s0_clk),
+       DEF_LOOKUP("i2s.1",     &i2s1_clk),
+       DEF_LOOKUP("stu300.0",  &i2c0_clk),
+       DEF_LOOKUP("stu300.1",  &i2c1_clk),
+       DEF_LOOKUP("pl022",     &spi_clk),
 #ifdef CONFIG_MACH_U300_BS335
-       DEF_LOOKUP("uart1", &uart1_clk),
+       DEF_LOOKUP("uart1",     &uart1_clk),
 #endif
        /* SLOW bridge clocks */
-       DEF_LOOKUP("slow", &slow_clk),
-       DEF_LOOKUP("wdog", &wdog_clk),
-       DEF_LOOKUP("uart0", &uart_clk),
-       DEF_LOOKUP("apptimer", &app_timer_clk),
-       DEF_LOOKUP("keypad", &keypad_clk),
+       DEF_LOOKUP("slow",      &slow_clk),
+       DEF_LOOKUP("coh901327_wdog",      &wdog_clk),
+       DEF_LOOKUP("uart0",     &uart_clk),
+       DEF_LOOKUP("apptimer",  &app_timer_clk),
+       DEF_LOOKUP("coh901461-keypad",    &keypad_clk),
        DEF_LOOKUP("u300-gpio", &gpio_clk),
-       DEF_LOOKUP("rtc0", &rtc_clk),
-       DEF_LOOKUP("bustr", &bustr_clk),
-       DEF_LOOKUP("evhist", &evhist_clk),
-       DEF_LOOKUP("timer", &timer_clk),
+       DEF_LOOKUP("rtc-coh901331",      &rtc_clk),
+       DEF_LOOKUP("bustr",     &bustr_clk),
+       DEF_LOOKUP("evhist",    &evhist_clk),
+       DEF_LOOKUP("timer",     &timer_clk),
 #ifdef CONFIG_MACH_U300_BS335
-       DEF_LOOKUP("ppm", &ppm_clk),
+       DEF_LOOKUP("ppm",       &ppm_clk),
 #endif
 };
 
@@ -1427,16 +1464,20 @@ static const struct file_operations u300_clocks_operations = {
        .release        = single_release,
 };
 
-static void init_clk_read_procfs(void)
+static int __init init_clk_read_debugfs(void)
 {
        /* Expose a simple debugfs interface to view all clocks */
        (void) debugfs_create_file("u300_clocks", S_IFREG | S_IRUGO,
-                                  NULL, NULL, &u300_clocks_operations);
-}
-#else
-static inline void init_clk_read_procfs(void)
-{
+                                  NULL, NULL,
+                                  &u300_clocks_operations);
+       return 0;
 }
+/*
+ * This needs to come in after the core_initcall() for the
+ * overall clocks, because debugfs is not available until
+ * the subsystems come up.
+ */
+module_init(init_clk_read_debugfs);
 #endif
 
 static int __init u300_clock_init(void)
@@ -1462,8 +1503,6 @@ static int __init u300_clock_init(void)
 
        clk_register();
 
-       init_clk_read_procfs();
-
        /*
         * Some of these may be on when we boot the system so make sure they
         * are turned OFF.
index 89b3ccf35e1bbf74740c2c856f03ad908b694fe9..2e9b8ccd8ec2e6d8cccc347231cc00293de22619 100644 (file)
@@ -455,8 +455,8 @@ void __init u300_init_irq(void)
        for (i = 0; i < NR_IRQS; i++)
                set_bit(i, (unsigned long *) &mask[0]);
        u300_enable_intcon_clock();
-       vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], 0);
-       vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], 0);
+       vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], mask[0]);
+       vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], mask[1]);
 }
 
 
@@ -510,7 +510,7 @@ static struct db_chip db_chips[] __initdata = {
        }
 };
 
-static void u300_init_check_chip(void)
+static void __init u300_init_check_chip(void)
 {
 
        u16 val;
index 69214fc8bd19576093accb6904549ecc2e12fa0c..31093af7d05211ba940d80d6700291257db1bb6c 100644 (file)
@@ -342,8 +342,7 @@ static struct platform_device versatile_i2c_device = {
 
 static struct i2c_board_info versatile_i2c_board_info[] = {
        {
-               I2C_BOARD_INFO("rtc-ds1307", 0xd0 >> 1),
-               .type = "ds1338",
+               I2C_BOARD_INFO("ds1338", 0xd0 >> 1),
        },
 };
 
index 8277802ec85926abe0e3bd7ad6dd10fb83e987d4..3a7279c1ce5e7eb5ed857f6d7bf442920c12860c 100644 (file)
@@ -120,6 +120,32 @@ void show_mem(void)
        printk("%d pages swap cached\n", cached);
 }
 
+static void __init find_node_limits(int node, struct meminfo *mi,
+       unsigned long *min, unsigned long *max_low, unsigned long *max_high)
+{
+       int i;
+
+       *min = -1UL;
+       *max_low = *max_high = 0;
+
+       for_each_nodebank(i, mi, node) {
+               struct membank *bank = &mi->bank[i];
+               unsigned long start, end;
+
+               start = bank_pfn_start(bank);
+               end = bank_pfn_end(bank);
+
+               if (*min > start)
+                       *min = start;
+               if (*max_high < end)
+                       *max_high = end;
+               if (bank->highmem)
+                       continue;
+               if (*max_low < end)
+                       *max_low = end;
+       }
+}
+
 /*
  * FIXME: We really want to avoid allocating the bootmap bitmap
  * over the top of the initrd.  Hopefully, this is located towards
@@ -210,40 +236,24 @@ static inline void map_memory_bank(struct membank *bank)
 #endif
 }
 
-static unsigned long __init bootmem_init_node(int node, struct meminfo *mi)
+static void __init bootmem_init_node(int node, struct meminfo *mi,
+       unsigned long start_pfn, unsigned long end_pfn)
 {
-       unsigned long start_pfn, end_pfn, boot_pfn;
+       unsigned long boot_pfn;
        unsigned int boot_pages;
        pg_data_t *pgdat;
        int i;
 
-       start_pfn = -1UL;
-       end_pfn = 0;
-
        /*
-        * Calculate the pfn range, and map the memory banks for this node.
+        * Map the memory banks for this node.
         */
        for_each_nodebank(i, mi, node) {
                struct membank *bank = &mi->bank[i];
-               unsigned long start, end;
 
-               start = bank_pfn_start(bank);
-               end = bank_pfn_end(bank);
-
-               if (start_pfn > start)
-                       start_pfn = start;
-               if (end_pfn < end)
-                       end_pfn = end;
-
-               map_memory_bank(bank);
+               if (!bank->highmem)
+                       map_memory_bank(bank);
        }
 
-       /*
-        * If there is no memory in this node, ignore it.
-        */
-       if (end_pfn == 0)
-               return end_pfn;
-
        /*
         * Allocate the bootmem bitmap page.
         */
@@ -260,7 +270,8 @@ static unsigned long __init bootmem_init_node(int node, struct meminfo *mi)
 
        for_each_nodebank(i, mi, node) {
                struct membank *bank = &mi->bank[i];
-               free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank));
+               if (!bank->highmem)
+                       free_bootmem_node(pgdat, bank_phys_start(bank), bank_phys_size(bank));
                memory_present(node, bank_pfn_start(bank), bank_pfn_end(bank));
        }
 
@@ -269,8 +280,6 @@ static unsigned long __init bootmem_init_node(int node, struct meminfo *mi)
         */
        reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT,
                             boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
-
-       return end_pfn;
 }
 
 static void __init bootmem_reserve_initrd(int node)
@@ -297,33 +306,39 @@ static void __init bootmem_reserve_initrd(int node)
 static void __init bootmem_free_node(int node, struct meminfo *mi)
 {
        unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
-       unsigned long start_pfn, end_pfn;
-       pg_data_t *pgdat = NODE_DATA(node);
+       unsigned long min, max_low, max_high;
        int i;
 
-       start_pfn = pgdat->bdata->node_min_pfn;
-       end_pfn = pgdat->bdata->node_low_pfn;
+       find_node_limits(node, mi, &min, &max_low, &max_high);
 
        /*
         * initialise the zones within this node.
         */
        memset(zone_size, 0, sizeof(zone_size));
-       memset(zhole_size, 0, sizeof(zhole_size));
 
        /*
         * The size of this node has already been determined.  If we need
         * to do anything fancy with the allocation of this memory to the
         * zones, now is the time to do it.
         */
-       zone_size[0] = end_pfn - start_pfn;
+       zone_size[0] = max_low - min;
+#ifdef CONFIG_HIGHMEM
+       zone_size[ZONE_HIGHMEM] = max_high - max_low;
+#endif
 
        /*
         * For each bank in this node, calculate the size of the holes.
         *  holes = node_size - sum(bank_sizes_in_node)
         */
-       zhole_size[0] = zone_size[0];
-       for_each_nodebank(i, mi, node)
-               zhole_size[0] -= bank_pfn_size(&mi->bank[i]);
+       memcpy(zhole_size, zone_size, sizeof(zhole_size));
+       for_each_nodebank(i, mi, node) {
+               int idx = 0;
+#ifdef CONFIG_HIGHMEM
+               if (mi->bank[i].highmem)
+                       idx = ZONE_HIGHMEM;
+#endif
+               zhole_size[idx] -= bank_pfn_size(&mi->bank[i]);
+       }
 
        /*
         * Adjust the sizes according to any special requirements for
@@ -331,13 +346,13 @@ static void __init bootmem_free_node(int node, struct meminfo *mi)
         */
        arch_adjust_zones(node, zone_size, zhole_size);
 
-       free_area_init_node(node, zone_size, start_pfn, zhole_size);
+       free_area_init_node(node, zone_size, min, zhole_size);
 }
 
 void __init bootmem_init(void)
 {
        struct meminfo *mi = &meminfo;
-       unsigned long memend_pfn = 0;
+       unsigned long min, max_low, max_high;
        int node, initrd_node;
 
        /*
@@ -345,11 +360,29 @@ void __init bootmem_init(void)
         */
        initrd_node = check_initrd(mi);
 
+       max_low = max_high = 0;
+
        /*
         * Run through each node initialising the bootmem allocator.
         */
        for_each_node(node) {
-               unsigned long end_pfn = bootmem_init_node(node, mi);
+               unsigned long node_low, node_high;
+
+               find_node_limits(node, mi, &min, &node_low, &node_high);
+
+               if (node_low > max_low)
+                       max_low = node_low;
+               if (node_high > max_high)
+                       max_high = node_high;
+
+               /*
+                * If there is no memory in this node, ignore it.
+                * (We can't have nodes which have no lowmem)
+                */
+               if (node_low == 0)
+                       continue;
+
+               bootmem_init_node(node, mi, min, node_low);
 
                /*
                 * Reserve any special node zero regions.
@@ -362,12 +395,6 @@ void __init bootmem_init(void)
                 */
                if (node == initrd_node)
                        bootmem_reserve_initrd(node);
-
-               /*
-                * Remember the highest memory PFN.
-                */
-               if (end_pfn > memend_pfn)
-                       memend_pfn = end_pfn;
        }
 
        /*
@@ -383,7 +410,7 @@ void __init bootmem_init(void)
        for_each_node(node)
                bootmem_free_node(node, mi);
 
-       high_memory = __va((memend_pfn << PAGE_SHIFT) - 1) + 1;
+       high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
 
        /*
         * This doesn't seem to be used by the Linux memory manager any
@@ -393,7 +420,8 @@ void __init bootmem_init(void)
         * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
         * the system, not the maximum PFN.
         */
-       max_pfn = max_low_pfn = memend_pfn - PHYS_PFN_OFFSET;
+       max_low_pfn = max_low - PHYS_PFN_OFFSET;
+       max_pfn = max_high - PHYS_PFN_OFFSET;
 }
 
 static inline int free_area(unsigned long pfn, unsigned long end, char *s)
index 4722582b17b82f526feef2d2f439bef26a98e946..4426ee67ceca5d3d74c9b0dbe0f39c5b7e2b8538 100644 (file)
@@ -687,13 +687,19 @@ __early_param("vmalloc=", early_vmalloc);
 
 static void __init sanity_check_meminfo(void)
 {
-       int i, j;
+       int i, j, highmem = 0;
 
        for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
                struct membank *bank = &meminfo.bank[j];
                *bank = meminfo.bank[i];
 
 #ifdef CONFIG_HIGHMEM
+               if (__va(bank->start) > VMALLOC_MIN ||
+                   __va(bank->start) < (void *)PAGE_OFFSET)
+                       highmem = 1;
+
+               bank->highmem = highmem;
+
                /*
                 * Split those memory banks which are partially overlapping
                 * the vmalloc area greatly simplifying things later.
@@ -714,6 +720,7 @@ static void __init sanity_check_meminfo(void)
                                i++;
                                bank[1].size -= VMALLOC_MIN - __va(bank->start);
                                bank[1].start = __pa(VMALLOC_MIN - 1) + 1;
+                               bank[1].highmem = highmem = 1;
                                j++;
                        }
                        bank->size = VMALLOC_MIN - __va(bank->start);
index 195e48edd8c2ce951cb8ac5b3272e962785d6bae..ac5c80062b704b791d0d9af9be34e7484f8d4311 100644 (file)
@@ -27,6 +27,7 @@ EXPORT_SYMBOL(__cpuc_flush_kern_all);
 EXPORT_SYMBOL(__cpuc_flush_user_all);
 EXPORT_SYMBOL(__cpuc_flush_user_range);
 EXPORT_SYMBOL(__cpuc_coherent_kern_range);
+EXPORT_SYMBOL(__cpuc_flush_dcache_page);
 EXPORT_SYMBOL(dmac_inv_range);  /* because of flush_ioremap_region() */
 #else
 EXPORT_SYMBOL(cpu_cache);
index 27f8d1b2bc6ba611bc0759b1900f81a39182c9d9..2eb182f73876acfc1c33965d2e82e3f20a23360f 100644 (file)
@@ -602,6 +602,8 @@ enum iomux_pins {
 #define MX31_PIN_I2C_DAT__SDA          IOMUX_MODE(MX31_PIN_I2C_DAT, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_DCD_DTE1__I2C2_SDA    IOMUX_MODE(MX31_PIN_DCD_DTE1, IOMUX_CONFIG_ALT2)
 #define MX31_PIN_RI_DTE1__I2C2_SCL     IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_ALT2)
+#define MX31_PIN_CSPI2_SS2__I2C3_SDA   IOMUX_MODE(MX31_PIN_CSPI2_SS2, IOMUX_CONFIG_ALT1)
+#define MX31_PIN_CSPI2_SCLK__I2C3_SCL  IOMUX_MODE(MX31_PIN_CSPI2_SCLK, IOMUX_CONFIG_ALT1)
 #define MX31_PIN_CSI_D4__CSI_D4                IOMUX_MODE(MX31_PIN_CSI_D4, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_CSI_D5__CSI_D5                IOMUX_MODE(MX31_PIN_CSI_D5, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_CSI_D6__CSI_D6                IOMUX_MODE(MX31_PIN_CSI_D6, IOMUX_CONFIG_FUNC)
index 843e8af640660bcd24b62aaef2de2c121ca3633b..1868c0d8f9b5c9a6db2fbdc263a1fa4570c4e656 100644 (file)
@@ -78,10 +78,10 @@ static int omap_target(struct cpufreq_policy *policy,
 
        /* Ensure desired rate is within allowed range.  Some govenors
         * (ondemand) will just pass target_freq=0 to get the minimum. */
-       if (target_freq < policy->cpuinfo.min_freq)
-               target_freq = policy->cpuinfo.min_freq;
-       if (target_freq > policy->cpuinfo.max_freq)
-               target_freq = policy->cpuinfo.max_freq;
+       if (target_freq < policy->min)
+               target_freq = policy->min;
+       if (target_freq > policy->max)
+               target_freq = policy->max;
 
        freqs.old = omap_getspeed(0);
        freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
index def14ec265b369f7929ea5bd841f4e97a6ac5b38..9b00f4cbc903c52d4cd0e0135af664d5a0a0a904 100644 (file)
@@ -946,7 +946,9 @@ void omap_start_dma(int lch)
 
                        cur_lch = next_lch;
                } while (next_lch != -1);
-       } else if (cpu_class_is_omap2()) {
+       } else if (cpu_is_omap242x() ||
+               (cpu_is_omap243x() &&  omap_type() <= OMAP2430_REV_ES1_0)) {
+
                /* Errata: Need to write lch even if not using chaining */
                dma_write(lch, CLNK_CTRL(lch));
        }
@@ -1125,6 +1127,11 @@ int omap_dma_running(void)
 void omap_dma_link_lch(int lch_head, int lch_queue)
 {
        if (omap_dma_in_1510_mode()) {
+               if (lch_head == lch_queue) {
+                       dma_write(dma_read(CCR(lch_head)) | (3 << 8),
+                                                               CCR(lch_head));
+                       return;
+               }
                printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
                BUG();
                return;
@@ -1147,6 +1154,11 @@ EXPORT_SYMBOL(omap_dma_link_lch);
 void omap_dma_unlink_lch(int lch_head, int lch_queue)
 {
        if (omap_dma_in_1510_mode()) {
+               if (lch_head == lch_queue) {
+                       dma_write(dma_read(CCR(lch_head)) & ~(3 << 8),
+                                                               CCR(lch_head));
+                       return;
+               }
                printk(KERN_ERR "DMA linking is not supported in 1510 mode\n");
                BUG();
                return;
@@ -2457,6 +2469,19 @@ static int __init omap_init_dma(void)
                setup_irq(irq, &omap24xx_dma_irq);
        }
 
+       /* Enable smartidle idlemodes and autoidle */
+       if (cpu_is_omap34xx()) {
+               u32 v = dma_read(OCP_SYSCONFIG);
+               v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK |
+                               DMA_SYSCONFIG_SIDLEMODE_MASK |
+                               DMA_SYSCONFIG_AUTOIDLE);
+               v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
+                       DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
+                       DMA_SYSCONFIG_AUTOIDLE);
+               dma_write(v , OCP_SYSCONFIG);
+       }
+
+
        /* FIXME: Update LCD DMA to work on 24xx */
        if (cpu_class_is_omap1()) {
                r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0,
index 7fd89ba8d3b5939684ab6999a12fc19c5430b31e..9298bc0ab171ff6150bfb1f36f07285b4f956575 100644 (file)
@@ -476,14 +476,12 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable)
        __raw_writel(l, reg);
 }
 
-static int __omap_get_gpio_datain(int gpio)
+static int _get_gpio_datain(struct gpio_bank *bank, int gpio)
 {
-       struct gpio_bank *bank;
        void __iomem *reg;
 
        if (check_gpio(gpio) < 0)
                return -EINVAL;
-       bank = get_gpio_bank(gpio);
        reg = bank->base;
        switch (bank->method) {
 #ifdef CONFIG_ARCH_OMAP1
@@ -524,6 +522,53 @@ static int __omap_get_gpio_datain(int gpio)
                        & (1 << get_gpio_index(gpio))) != 0;
 }
 
+static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
+{
+       void __iomem *reg;
+
+       if (check_gpio(gpio) < 0)
+               return -EINVAL;
+       reg = bank->base;
+
+       switch (bank->method) {
+#ifdef CONFIG_ARCH_OMAP1
+       case METHOD_MPUIO:
+               reg += OMAP_MPUIO_OUTPUT;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP15XX
+       case METHOD_GPIO_1510:
+               reg += OMAP1510_GPIO_DATA_OUTPUT;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP16XX
+       case METHOD_GPIO_1610:
+               reg += OMAP1610_GPIO_DATAOUT;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP730
+       case METHOD_GPIO_730:
+               reg += OMAP730_GPIO_DATA_OUTPUT;
+               break;
+#endif
+#ifdef CONFIG_ARCH_OMAP850
+       case METHOD_GPIO_850:
+               reg += OMAP850_GPIO_DATA_OUTPUT;
+               break;
+#endif
+#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \
+               defined(CONFIG_ARCH_OMAP4)
+       case METHOD_GPIO_24XX:
+               reg += OMAP24XX_GPIO_DATAOUT;
+               break;
+#endif
+       default:
+               return -EINVAL;
+       }
+
+       return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0;
+}
+
 #define MOD_REG_BIT(reg, bit_mask, set)        \
 do {   \
        int l = __raw_readl(base + reg); \
@@ -1189,6 +1234,7 @@ static void gpio_mask_irq(unsigned int irq)
        struct gpio_bank *bank = get_irq_chip_data(irq);
 
        _set_gpio_irqenable(bank, gpio, 0);
+       _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE);
 }
 
 static void gpio_unmask_irq(unsigned int irq)
@@ -1196,6 +1242,11 @@ static void gpio_unmask_irq(unsigned int irq)
        unsigned int gpio = irq - IH_GPIO_BASE;
        struct gpio_bank *bank = get_irq_chip_data(irq);
        unsigned int irq_mask = 1 << get_gpio_index(gpio);
+       struct irq_desc *desc = irq_to_desc(irq);
+       u32 trigger = desc->status & IRQ_TYPE_SENSE_MASK;
+
+       if (trigger)
+               _set_gpio_triggering(bank, get_gpio_index(gpio), trigger);
 
        /* For level-triggered GPIOs, the clearing must be done after
         * the HW source is cleared, thus after the handler has run */
@@ -1350,9 +1401,49 @@ static int gpio_input(struct gpio_chip *chip, unsigned offset)
        return 0;
 }
 
+static int gpio_is_input(struct gpio_bank *bank, int mask)
+{
+       void __iomem *reg = bank->base;
+
+       switch (bank->method) {
+       case METHOD_MPUIO:
+               reg += OMAP_MPUIO_IO_CNTL;
+               break;
+       case METHOD_GPIO_1510:
+               reg += OMAP1510_GPIO_DIR_CONTROL;
+               break;
+       case METHOD_GPIO_1610:
+               reg += OMAP1610_GPIO_DIRECTION;
+               break;
+       case METHOD_GPIO_730:
+               reg += OMAP730_GPIO_DIR_CONTROL;
+               break;
+       case METHOD_GPIO_850:
+               reg += OMAP850_GPIO_DIR_CONTROL;
+               break;
+       case METHOD_GPIO_24XX:
+               reg += OMAP24XX_GPIO_OE;
+               break;
+       }
+       return __raw_readl(reg) & mask;
+}
+
 static int gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-       return __omap_get_gpio_datain(chip->base + offset);
+       struct gpio_bank *bank;
+       void __iomem *reg;
+       int gpio;
+       u32 mask;
+
+       gpio = chip->base + offset;
+       bank = get_gpio_bank(gpio);
+       reg = bank->base;
+       mask = 1 << get_gpio_index(gpio);
+
+       if (gpio_is_input(bank, mask))
+               return _get_gpio_datain(bank, gpio);
+       else
+               return _get_gpio_dataout(bank, gpio);
 }
 
 static int gpio_output(struct gpio_chip *chip, unsigned offset, int value)
@@ -1585,6 +1676,7 @@ static int __init _omap_gpio_init(void)
                        __raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_IRQENABLE1);
                        __raw_writel(0xffffffff, bank->base + OMAP24XX_GPIO_IRQSTATUS1);
                        __raw_writew(0x0015, bank->base + OMAP24XX_GPIO_SYSCONFIG);
+                       __raw_writel(0x00000000, bank->base + OMAP24XX_GPIO_DEBOUNCE_EN);
 
                        /* Initialize interface clock ungated, module enabled */
                        __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL);
@@ -1885,34 +1977,6 @@ arch_initcall(omap_gpio_sysinit);
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 
-static int gpio_is_input(struct gpio_bank *bank, int mask)
-{
-       void __iomem *reg = bank->base;
-
-       switch (bank->method) {
-       case METHOD_MPUIO:
-               reg += OMAP_MPUIO_IO_CNTL;
-               break;
-       case METHOD_GPIO_1510:
-               reg += OMAP1510_GPIO_DIR_CONTROL;
-               break;
-       case METHOD_GPIO_1610:
-               reg += OMAP1610_GPIO_DIRECTION;
-               break;
-       case METHOD_GPIO_730:
-               reg += OMAP730_GPIO_DIR_CONTROL;
-               break;
-       case METHOD_GPIO_850:
-               reg += OMAP850_GPIO_DIR_CONTROL;
-               break;
-       case METHOD_GPIO_24XX:
-               reg += OMAP24XX_GPIO_OE;
-               break;
-       }
-       return __raw_readl(reg) & mask;
-}
-
-
 static int dbg_gpio_show(struct seq_file *s, void *unused)
 {
        unsigned        i, j, gpio;
index f9f65e1ba3f13abe11d7c06d514b6581e6697016..4b8b0d65cbf20c10dfcc0b0795ed16b3bf054de9 100644 (file)
@@ -20,6 +20,8 @@ struct clockdomain;
 struct clkops {
        int                     (*enable)(struct clk *);
        void                    (*disable)(struct clk *);
+       void                    (*find_idlest)(struct clk *, void __iomem **, u8 *);
+       void                    (*find_companion)(struct clk *, void __iomem **, u8 *);
 };
 
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
index fc60c4ebcc28af1d0d1fa80d583b7f35cf00feaf..11e73d9e8928458adc5656add696d835cf330d7a 100644 (file)
 #ifndef __ASM_ARCH_OMAP_CPU_H
 #define __ASM_ARCH_OMAP_CPU_H
 
+/*
+ * Omap device type i.e. EMU/HS/TST/GP/BAD
+ */
+#define OMAP2_DEVICE_TYPE_TEST         0
+#define OMAP2_DEVICE_TYPE_EMU          1
+#define OMAP2_DEVICE_TYPE_SEC          2
+#define OMAP2_DEVICE_TYPE_GP           3
+#define OMAP2_DEVICE_TYPE_BAD          4
+
+int omap_type(void);
+
 struct omap_chip_id {
        u8 oc;
        u8 type;
@@ -367,9 +378,6 @@ IS_OMAP_TYPE(3430, 0x3430)
 #define cpu_class_is_omap2()   (cpu_is_omap24xx() || cpu_is_omap34xx() || \
                                cpu_is_omap44xx())
 
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
-                       defined(CONFIG_ARCH_OMAP4)
-
 /* Various silicon revisions for omap2 */
 #define OMAP242X_CLASS         0x24200024
 #define OMAP2420_REV_ES1_0     0x24200024
@@ -424,17 +432,4 @@ IS_OMAP_TYPE(3430, 0x3430)
 
 
 int omap_chip_is(struct omap_chip_id oci);
-int omap_type(void);
-
-/*
- * Macro to detect device type i.e. EMU/HS/TST/GP/BAD
- */
-#define OMAP2_DEVICE_TYPE_TEST         0
-#define OMAP2_DEVICE_TYPE_EMU          1
-#define OMAP2_DEVICE_TYPE_SEC          2
-#define OMAP2_DEVICE_TYPE_GP           3
-#define OMAP2_DEVICE_TYPE_BAD          4
-
 void omap2_check_revision(void);
-
-#endif    /* defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) */
index 8c1eae88737e9e6a0ca24d85a5b51c63050c156a..7b939cc01962034fd8003964be7bcc33d4e1a535 100644 (file)
 #define DMA_THREAD_FIFO_25             (0x02 << 14)
 #define DMA_THREAD_FIFO_50             (0x03 << 14)
 
+/* DMA4_OCP_SYSCONFIG bits */
+#define DMA_SYSCONFIG_MIDLEMODE_MASK           (3 << 12)
+#define DMA_SYSCONFIG_CLOCKACTIVITY_MASK       (3 << 8)
+#define DMA_SYSCONFIG_EMUFREE                  (1 << 5)
+#define DMA_SYSCONFIG_SIDLEMODE_MASK           (3 << 3)
+#define DMA_SYSCONFIG_SOFTRESET                        (1 << 2)
+#define DMA_SYSCONFIG_AUTOIDLE                 (1 << 0)
+
+#define DMA_SYSCONFIG_MIDLEMODE(n)             ((n) << 12)
+#define DMA_SYSCONFIG_SIDLEMODE(n)             ((n) << 3)
+
+#define DMA_IDLEMODE_SMARTIDLE                 0x2
+#define DMA_IDLEMODE_NO_IDLE                   0x1
+#define DMA_IDLEMODE_FORCE_IDLE                        0x0
+
 /* Chaining modes*/
 #ifndef CONFIG_ARCH_OMAP1
 #define OMAP_DMA_STATIC_CHAIN          0x1
index 3b28147205691a05df715d71a31d5e33fef858eb..21fb0efdda86a02f17931888bd16c1927295bb7d 100644 (file)
 #define OMAP2_IO_ADDRESS(pa)   IOMEM(__OMAP2_IO_ADDRESS(pa))
 
 #ifdef __ASSEMBLER__
-#define IOMEM(x)               x
+#define IOMEM(x)               (x)
 #else
 #define IOMEM(x)               ((void __force __iomem *)(x))
 
@@ -228,7 +228,8 @@ extern void omap1_map_common_io(void);
 extern void omap1_init_common_hw(void);
 
 extern void omap2_map_common_io(void);
-extern void omap2_init_common_hw(struct omap_sdrc_params *sp);
+extern void omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
+                                struct omap_sdrc_params *sdrc_cs1);
 
 #define __arch_ioremap(p,s,t)  omap_ioremap(p,s,t)
 #define __arch_iounmap(v)      omap_iounmap(v)
index bb154ea76769509a7937c4ba472e8d04c5bf41d3..63a3f254af7b80376c474f58cfaf680a8cf498fb 100644 (file)
 #define OMAP_MCBSP_REG_XCERG   0x74
 #define OMAP_MCBSP_REG_XCERH   0x78
 #define OMAP_MCBSP_REG_SYSCON  0x8C
+#define OMAP_MCBSP_REG_THRSH2  0x90
+#define OMAP_MCBSP_REG_THRSH1  0x94
+#define OMAP_MCBSP_REG_IRQST   0xA0
+#define OMAP_MCBSP_REG_IRQEN   0xA4
+#define OMAP_MCBSP_REG_WAKEUPEN        0xA8
 #define OMAP_MCBSP_REG_XCCR    0xAC
 #define OMAP_MCBSP_REG_RCCR    0xB0
 
 #define RDISABLE               0x0001
 
 /********************** McBSP SYSCONFIG bit definitions ********************/
+#define CLOCKACTIVITY(value)   ((value)<<8)
+#define SIDLEMODE(value)       ((value)<<3)
+#define ENAWAKEUP              0x0004
 #define SOFTRST                        0x0002
 
+/********************** McBSP DMA operating modes **************************/
+#define MCBSP_DMA_MODE_ELEMENT         0
+#define MCBSP_DMA_MODE_THRESHOLD       1
+#define MCBSP_DMA_MODE_FRAME           2
+
+/********************** McBSP WAKEUPEN bit definitions *********************/
+#define XEMPTYEOFEN            0x4000
+#define XRDYEN                 0x0400
+#define XEOFEN                 0x0200
+#define XFSXEN                 0x0100
+#define XSYNCERREN             0x0080
+#define RRDYEN                 0x0008
+#define REOFEN                 0x0004
+#define RFSREN                 0x0002
+#define RSYNCERREN             0x0001
+
 /* we don't do multichannel for now */
 struct omap_mcbsp_reg_cfg {
        u16 spcr2;
@@ -344,6 +368,9 @@ struct omap_mcbsp_platform_data {
        u8 dma_rx_sync, dma_tx_sync;
        u16 rx_irq, tx_irq;
        struct omap_mcbsp_ops *ops;
+#ifdef CONFIG_ARCH_OMAP34XX
+       u16 buffer_size;
+#endif
 };
 
 struct omap_mcbsp {
@@ -377,6 +404,11 @@ struct omap_mcbsp {
        struct omap_mcbsp_platform_data *pdata;
        struct clk *iclk;
        struct clk *fclk;
+#ifdef CONFIG_ARCH_OMAP34XX
+       int dma_op_mode;
+       u16 max_tx_thres;
+       u16 max_rx_thres;
+#endif
 };
 extern struct omap_mcbsp **mcbsp_ptr;
 extern int omap_mcbsp_count;
@@ -385,10 +417,25 @@ int omap_mcbsp_init(void);
 void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
                                        int size);
 void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config);
+#ifdef CONFIG_ARCH_OMAP34XX
+void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold);
+void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold);
+u16 omap_mcbsp_get_max_tx_threshold(unsigned int id);
+u16 omap_mcbsp_get_max_rx_threshold(unsigned int id);
+int omap_mcbsp_get_dma_op_mode(unsigned int id);
+#else
+static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
+{ }
+static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
+{ }
+static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; }
+static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; }
+static inline int omap_mcbsp_get_dma_op_mode(unsigned int id) { return 0; }
+#endif
 int omap_mcbsp_request(unsigned int id);
 void omap_mcbsp_free(unsigned int id);
-void omap_mcbsp_start(unsigned int id);
-void omap_mcbsp_stop(unsigned int id);
+void omap_mcbsp_start(unsigned int id, int tx, int rx);
+void omap_mcbsp_stop(unsigned int id, int tx, int rx);
 void omap_mcbsp_xmit_word(unsigned int id, u32 word);
 u32 omap_mcbsp_recv_word(unsigned int id);
 
index 85a621705766eef343511478f57b3a7a9ffce671..80281c458baf26b74dee1bbcc0f516772272fd2a 100644 (file)
@@ -853,6 +853,10 @@ enum omap34xx_index {
        AE5_34XX_GPIO143,
        H19_34XX_GPIO164_OUT,
        J25_34XX_GPIO170,
+
+       /* OMAP3 SDRC CKE signals to SDR/DDR ram chips */
+       H16_34XX_SDRC_CKE0,
+       H17_34XX_SDRC_CKE1,
 };
 
 struct omap_mux_cfg {
index 24ac3c7159126eda9a7e88d00158fdc14713f704..cda2a70397b4acb3655d10364a669dda094e16d5 100644 (file)
@@ -25,6 +25,7 @@
 
 u32 omap_prcm_get_reset_sources(void);
 void omap_prcm_arch_reset(char mode);
+int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, const char *name);
 
 #endif
 
index adc73522491fe03e75d7617ce94401d6c92c001b..0be18e4ff182b2902275de08d45eb44104bcd4a6 100644 (file)
 #define SDRC_ACTIM_CTRL_A_0    0x09c
 #define SDRC_ACTIM_CTRL_B_0    0x0a0
 #define SDRC_RFR_CTRL_0                0x0a4
+#define SDRC_MR_1              0x0B4
+#define SDRC_ACTIM_CTRL_A_1    0x0C4
+#define SDRC_ACTIM_CTRL_B_1    0x0C8
+#define SDRC_RFR_CTRL_1                0x0D4
 
 /*
  * These values represent the number of memory clock cycles between
@@ -102,8 +106,11 @@ struct omap_sdrc_params {
        u32 mr;
 };
 
-void __init omap2_sdrc_init(struct omap_sdrc_params *sp);
-struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r);
+void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
+                           struct omap_sdrc_params *sdrc_cs1);
+int omap2_sdrc_get_params(unsigned long r,
+                         struct omap_sdrc_params **sdrc_cs0,
+                         struct omap_sdrc_params **sdrc_cs1);
 
 #ifdef CONFIG_ARCH_OMAP2
 
index 13abd02d15279163291772ff129a71012d8a257e..def0529c75eb8ccc764657ee1bec2aa237ed9b62 100644 (file)
@@ -59,6 +59,7 @@ extern void omap_uart_check_wakeup(void);
 extern void omap_uart_prepare_suspend(void);
 extern void omap_uart_prepare_idle(int num);
 extern void omap_uart_resume_idle(int num);
+extern void omap_uart_enable_irqs(int enable);
 #endif
 
 #endif
index 4d53cc59d7a3b5acb34b4f4bb0a870f3d2ad6f3e..8974e3fc2691ea6d023462203a366c2b123735b1 100644 (file)
@@ -21,11 +21,12 @@ extern void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
                                      u32 mem_type);
 extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);
 
-extern u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl,
-                                    u32 sdrc_actim_ctrla,
-                                    u32 sdrc_actim_ctrlb, u32 m2,
-                                    u32 unlock_dll, u32 f, u32 sdrc_mr,
-                                    u32 inc);
+extern u32 omap3_configure_core_dpll(
+                       u32 m2, u32 unlock_dll, u32 f, u32 inc,
+                       u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
+                       u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
+                       u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
+                       u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
 
 /* Do not use these */
 extern void omap1_sram_reprogram_clock(u32 ckctl, u32 dpllctl);
@@ -59,12 +60,12 @@ extern void omap243x_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
                                                u32 mem_type);
 extern unsigned long omap243x_sram_reprogram_sdrc_sz;
 
-
-extern u32 omap3_sram_configure_core_dpll(u32 sdrc_rfr_ctrl,
-                                         u32 sdrc_actim_ctrla,
-                                         u32 sdrc_actim_ctrlb, u32 m2,
-                                         u32 unlock_dll, u32 f, u32 sdrc_mr,
-                                         u32 inc);
+extern u32 omap3_sram_configure_core_dpll(
+                       u32 m2, u32 unlock_dll, u32 f, u32 inc,
+                       u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
+                       u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
+                       u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
+                       u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
 extern unsigned long omap3_sram_configure_core_dpll_sz;
 
 #endif
index 4cf449fa2cb54a8013cd8df951ab00af2c439905..4a03013990135c6c4faa2ee134a55c16feb26470 100644 (file)
@@ -298,7 +298,7 @@ void flush_iotlb_page(struct iommu *obj, u32 da)
                if ((start <= da) && (da < start + bytes)) {
                        dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n",
                                __func__, start, da, bytes);
-
+                       iotlb_load_cr(obj, &cr);
                        iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
                }
        }
index efa0e0111f38815f4416634bc31427d786e8fced..8dc7927906f19fd8fde5a364c6133f6dc1eb47d7 100644 (file)
@@ -198,6 +198,170 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)
 }
 EXPORT_SYMBOL(omap_mcbsp_config);
 
+#ifdef CONFIG_ARCH_OMAP34XX
+/*
+ * omap_mcbsp_set_tx_threshold configures how to deal
+ * with transmit threshold. the threshold value and handler can be
+ * configure in here.
+ */
+void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold)
+{
+       struct omap_mcbsp *mcbsp;
+       void __iomem *io_base;
+
+       if (!cpu_is_omap34xx())
+               return;
+
+       if (!omap_mcbsp_check_valid_id(id)) {
+               printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+               return;
+       }
+       mcbsp = id_to_mcbsp_ptr(id);
+       io_base = mcbsp->io_base;
+
+       OMAP_MCBSP_WRITE(io_base, THRSH2, threshold);
+}
+EXPORT_SYMBOL(omap_mcbsp_set_tx_threshold);
+
+/*
+ * omap_mcbsp_set_rx_threshold configures how to deal
+ * with receive threshold. the threshold value and handler can be
+ * configure in here.
+ */
+void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold)
+{
+       struct omap_mcbsp *mcbsp;
+       void __iomem *io_base;
+
+       if (!cpu_is_omap34xx())
+               return;
+
+       if (!omap_mcbsp_check_valid_id(id)) {
+               printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+               return;
+       }
+       mcbsp = id_to_mcbsp_ptr(id);
+       io_base = mcbsp->io_base;
+
+       OMAP_MCBSP_WRITE(io_base, THRSH1, threshold);
+}
+EXPORT_SYMBOL(omap_mcbsp_set_rx_threshold);
+
+/*
+ * omap_mcbsp_get_max_tx_thres just return the current configured
+ * maximum threshold for transmission
+ */
+u16 omap_mcbsp_get_max_tx_threshold(unsigned int id)
+{
+       struct omap_mcbsp *mcbsp;
+
+       if (!omap_mcbsp_check_valid_id(id)) {
+               printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+               return -ENODEV;
+       }
+       mcbsp = id_to_mcbsp_ptr(id);
+
+       return mcbsp->max_tx_thres;
+}
+EXPORT_SYMBOL(omap_mcbsp_get_max_tx_threshold);
+
+/*
+ * omap_mcbsp_get_max_rx_thres just return the current configured
+ * maximum threshold for reception
+ */
+u16 omap_mcbsp_get_max_rx_threshold(unsigned int id)
+{
+       struct omap_mcbsp *mcbsp;
+
+       if (!omap_mcbsp_check_valid_id(id)) {
+               printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+               return -ENODEV;
+       }
+       mcbsp = id_to_mcbsp_ptr(id);
+
+       return mcbsp->max_rx_thres;
+}
+EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold);
+
+/*
+ * omap_mcbsp_get_dma_op_mode just return the current configured
+ * operating mode for the mcbsp channel
+ */
+int omap_mcbsp_get_dma_op_mode(unsigned int id)
+{
+       struct omap_mcbsp *mcbsp;
+       int dma_op_mode;
+
+       if (!omap_mcbsp_check_valid_id(id)) {
+               printk(KERN_ERR "%s: Invalid id (%u)\n", __func__, id + 1);
+               return -ENODEV;
+       }
+       mcbsp = id_to_mcbsp_ptr(id);
+
+       spin_lock_irq(&mcbsp->lock);
+       dma_op_mode = mcbsp->dma_op_mode;
+       spin_unlock_irq(&mcbsp->lock);
+
+       return dma_op_mode;
+}
+EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode);
+
+static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp)
+{
+       /*
+        * Enable wakup behavior, smart idle and all wakeups
+        * REVISIT: some wakeups may be unnecessary
+        */
+       if (cpu_is_omap34xx()) {
+               u16 syscon;
+
+               syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON);
+               syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03));
+
+               spin_lock_irq(&mcbsp->lock);
+               if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) {
+                       syscon |= (ENAWAKEUP | SIDLEMODE(0x02) |
+                                       CLOCKACTIVITY(0x02));
+                       OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN,
+                                       XRDYEN | RRDYEN);
+               } else {
+                       syscon |= SIDLEMODE(0x01);
+               }
+               spin_unlock_irq(&mcbsp->lock);
+
+               OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon);
+       }
+}
+
+static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp)
+{
+       /*
+        * Disable wakup behavior, smart idle and all wakeups
+        */
+       if (cpu_is_omap34xx()) {
+               u16 syscon;
+
+               syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON);
+               syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03));
+               /*
+                * HW bug workaround - If no_idle mode is taken, we need to
+                * go to smart_idle before going to always_idle, or the
+                * device will not hit retention anymore.
+                */
+               syscon |= SIDLEMODE(0x02);
+               OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon);
+
+               syscon &= ~(SIDLEMODE(0x03));
+               OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon);
+
+               OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, 0);
+       }
+}
+#else
+static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) {}
+static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) {}
+#endif
+
 /*
  * We can choose between IRQ based or polled IO.
  * This needs to be called before omap_mcbsp_request().
@@ -257,6 +421,9 @@ int omap_mcbsp_request(unsigned int id)
        clk_enable(mcbsp->iclk);
        clk_enable(mcbsp->fclk);
 
+       /* Do procedure specific to omap34xx arch, if applicable */
+       omap34xx_mcbsp_request(mcbsp);
+
        /*
         * Make sure that transmitter, receiver and sample-rate generator are
         * not running before activating IRQs.
@@ -305,6 +472,9 @@ void omap_mcbsp_free(unsigned int id)
        if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free)
                mcbsp->pdata->ops->free(id);
 
+       /* Do procedure specific to omap34xx arch, if applicable */
+       omap34xx_mcbsp_free(mcbsp);
+
        clk_disable(mcbsp->fclk);
        clk_disable(mcbsp->iclk);
 
@@ -328,14 +498,15 @@ void omap_mcbsp_free(unsigned int id)
 EXPORT_SYMBOL(omap_mcbsp_free);
 
 /*
- * Here we start the McBSP, by enabling the sample
- * generator, both transmitter and receivers,
- * and the frame sync.
+ * Here we start the McBSP, by enabling transmitter, receiver or both.
+ * If no transmitter or receiver is active prior calling, then sample-rate
+ * generator and frame sync are started.
  */
-void omap_mcbsp_start(unsigned int id)
+void omap_mcbsp_start(unsigned int id, int tx, int rx)
 {
        struct omap_mcbsp *mcbsp;
        void __iomem *io_base;
+       int idle;
        u16 w;
 
        if (!omap_mcbsp_check_valid_id(id)) {
@@ -348,32 +519,58 @@ void omap_mcbsp_start(unsigned int id)
        mcbsp->rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7;
        mcbsp->tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7;
 
-       /* Start the sample generator */
-       w = OMAP_MCBSP_READ(io_base, SPCR2);
-       OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6));
+       idle = !((OMAP_MCBSP_READ(io_base, SPCR2) |
+                 OMAP_MCBSP_READ(io_base, SPCR1)) & 1);
+
+       if (idle) {
+               /* Start the sample generator */
+               w = OMAP_MCBSP_READ(io_base, SPCR2);
+               OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6));
+       }
 
        /* Enable transmitter and receiver */
+       tx &= 1;
        w = OMAP_MCBSP_READ(io_base, SPCR2);
-       OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1);
+       OMAP_MCBSP_WRITE(io_base, SPCR2, w | tx);
 
+       rx &= 1;
        w = OMAP_MCBSP_READ(io_base, SPCR1);
-       OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1);
+       OMAP_MCBSP_WRITE(io_base, SPCR1, w | rx);
 
-       udelay(100);
+       /*
+        * Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec
+        * REVISIT: 100us may give enough time for two CLKSRG, however
+        * due to some unknown PM related, clock gating etc. reason it
+        * is now at 500us.
+        */
+       udelay(500);
 
-       /* Start frame sync */
-       w = OMAP_MCBSP_READ(io_base, SPCR2);
-       OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7));
+       if (idle) {
+               /* Start frame sync */
+               w = OMAP_MCBSP_READ(io_base, SPCR2);
+               OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7));
+       }
+
+       if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+               /* Release the transmitter and receiver */
+               w = OMAP_MCBSP_READ(io_base, XCCR);
+               w &= ~(tx ? XDISABLE : 0);
+               OMAP_MCBSP_WRITE(io_base, XCCR, w);
+               w = OMAP_MCBSP_READ(io_base, RCCR);
+               w &= ~(rx ? RDISABLE : 0);
+               OMAP_MCBSP_WRITE(io_base, RCCR, w);
+       }
 
        /* Dump McBSP Regs */
        omap_mcbsp_dump_reg(id);
 }
 EXPORT_SYMBOL(omap_mcbsp_start);
 
-void omap_mcbsp_stop(unsigned int id)
+void omap_mcbsp_stop(unsigned int id, int tx, int rx)
 {
        struct omap_mcbsp *mcbsp;
        void __iomem *io_base;
+       int idle;
        u16 w;
 
        if (!omap_mcbsp_check_valid_id(id)) {
@@ -385,16 +582,33 @@ void omap_mcbsp_stop(unsigned int id)
        io_base = mcbsp->io_base;
 
        /* Reset transmitter */
+       tx &= 1;
+       if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+               w = OMAP_MCBSP_READ(io_base, XCCR);
+               w |= (tx ? XDISABLE : 0);
+               OMAP_MCBSP_WRITE(io_base, XCCR, w);
+       }
        w = OMAP_MCBSP_READ(io_base, SPCR2);
-       OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1));
+       OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~tx);
 
        /* Reset receiver */
+       rx &= 1;
+       if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+               w = OMAP_MCBSP_READ(io_base, RCCR);
+               w |= (tx ? RDISABLE : 0);
+               OMAP_MCBSP_WRITE(io_base, RCCR, w);
+       }
        w = OMAP_MCBSP_READ(io_base, SPCR1);
-       OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1));
+       OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~rx);
 
-       /* Reset the sample rate generator */
-       w = OMAP_MCBSP_READ(io_base, SPCR2);
-       OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6));
+       idle = !((OMAP_MCBSP_READ(io_base, SPCR2) |
+                 OMAP_MCBSP_READ(io_base, SPCR1)) & 1);
+
+       if (idle) {
+               /* Reset the sample rate generator */
+               w = OMAP_MCBSP_READ(io_base, SPCR2);
+               OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6));
+       }
 }
 EXPORT_SYMBOL(omap_mcbsp_stop);
 
@@ -883,6 +1097,149 @@ void omap_mcbsp_set_spi_mode(unsigned int id,
 }
 EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
 
+#ifdef CONFIG_ARCH_OMAP34XX
+#define max_thres(m)                   (mcbsp->pdata->buffer_size)
+#define valid_threshold(m, val)                ((val) <= max_thres(m))
+#define THRESHOLD_PROP_BUILDER(prop)                                   \
+static ssize_t prop##_show(struct device *dev,                         \
+                       struct device_attribute *attr, char *buf)       \
+{                                                                      \
+       struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);                \
+                                                                       \
+       return sprintf(buf, "%u\n", mcbsp->prop);                       \
+}                                                                      \
+                                                                       \
+static ssize_t prop##_store(struct device *dev,                                \
+                               struct device_attribute *attr,          \
+                               const char *buf, size_t size)           \
+{                                                                      \
+       struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);                \
+       unsigned long val;                                              \
+       int status;                                                     \
+                                                                       \
+       status = strict_strtoul(buf, 0, &val);                          \
+       if (status)                                                     \
+               return status;                                          \
+                                                                       \
+       if (!valid_threshold(mcbsp, val))                               \
+               return -EDOM;                                           \
+                                                                       \
+       mcbsp->prop = val;                                              \
+       return size;                                                    \
+}                                                                      \
+                                                                       \
+static DEVICE_ATTR(prop, 0644, prop##_show, prop##_store);
+
+THRESHOLD_PROP_BUILDER(max_tx_thres);
+THRESHOLD_PROP_BUILDER(max_rx_thres);
+
+static const char *dma_op_modes[] = {
+       "element", "threshold", "frame",
+};
+
+static ssize_t dma_op_mode_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+       int dma_op_mode, i = 0;
+       ssize_t len = 0;
+       const char * const *s;
+
+       spin_lock_irq(&mcbsp->lock);
+       dma_op_mode = mcbsp->dma_op_mode;
+       spin_unlock_irq(&mcbsp->lock);
+
+       for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) {
+               if (dma_op_mode == i)
+                       len += sprintf(buf + len, "[%s] ", *s);
+               else
+                       len += sprintf(buf + len, "%s ", *s);
+       }
+       len += sprintf(buf + len, "\n");
+
+       return len;
+}
+
+static ssize_t dma_op_mode_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t size)
+{
+       struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+       const char * const *s;
+       int i = 0;
+
+       for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++)
+               if (sysfs_streq(buf, *s))
+                       break;
+
+       if (i == ARRAY_SIZE(dma_op_modes))
+               return -EINVAL;
+
+       spin_lock_irq(&mcbsp->lock);
+       if (!mcbsp->free) {
+               size = -EBUSY;
+               goto unlock;
+       }
+       mcbsp->dma_op_mode = i;
+
+unlock:
+       spin_unlock_irq(&mcbsp->lock);
+
+       return size;
+}
+
+static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store);
+
+static const struct attribute *additional_attrs[] = {
+       &dev_attr_max_tx_thres.attr,
+       &dev_attr_max_rx_thres.attr,
+       &dev_attr_dma_op_mode.attr,
+       NULL,
+};
+
+static const struct attribute_group additional_attr_group = {
+       .attrs = (struct attribute **)additional_attrs,
+};
+
+static inline int __devinit omap_additional_add(struct device *dev)
+{
+       return sysfs_create_group(&dev->kobj, &additional_attr_group);
+}
+
+static inline void __devexit omap_additional_remove(struct device *dev)
+{
+       sysfs_remove_group(&dev->kobj, &additional_attr_group);
+}
+
+static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp)
+{
+       mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
+       if (cpu_is_omap34xx()) {
+               mcbsp->max_tx_thres = max_thres(mcbsp);
+               mcbsp->max_rx_thres = max_thres(mcbsp);
+               /*
+                * REVISIT: Set dmap_op_mode to THRESHOLD as default
+                * for mcbsp2 instances.
+                */
+               if (omap_additional_add(mcbsp->dev))
+                       dev_warn(mcbsp->dev,
+                               "Unable to create additional controls\n");
+       } else {
+               mcbsp->max_tx_thres = -EINVAL;
+               mcbsp->max_rx_thres = -EINVAL;
+       }
+}
+
+static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp)
+{
+       if (cpu_is_omap34xx())
+               omap_additional_remove(mcbsp->dev);
+}
+#else
+static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {}
+static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) {}
+#endif /* CONFIG_ARCH_OMAP34XX */
+
 /*
  * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
  * 730 has only 2 McBSP, and both of them are MPU peripherals.
@@ -953,6 +1310,10 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
        mcbsp->dev = &pdev->dev;
        mcbsp_ptr[id] = mcbsp;
        platform_set_drvdata(pdev, mcbsp);
+
+       /* Initialize mcbsp properties for OMAP34XX if needed / applicable */
+       omap34xx_device_init(mcbsp);
+
        return 0;
 
 err_fclk:
@@ -976,6 +1337,8 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev)
                                mcbsp->pdata->ops->free)
                        mcbsp->pdata->ops->free(mcbsp->id);
 
+               omap34xx_device_exit(mcbsp);
+
                clk_disable(mcbsp->fclk);
                clk_disable(mcbsp->iclk);
                clk_put(mcbsp->fclk);
index 65006df3f1b750832b3832c3fb1ac62aa84b6a94..5eae7876979ce9a398b8fb93a73b69e961474287 100644 (file)
@@ -44,9 +44,9 @@
 #define OMAP2_SRAM_VA          0xe3000000
 #define OMAP2_SRAM_PUB_VA      (OMAP2_SRAM_VA + 0x800)
 #define OMAP3_SRAM_PA           0x40200000
-#define OMAP3_SRAM_VA           0xd7000000
+#define OMAP3_SRAM_VA           0xe3000000
 #define OMAP3_SRAM_PUB_PA       0x40208000
-#define OMAP3_SRAM_PUB_VA       0xd7008000
+#define OMAP3_SRAM_PUB_VA       (OMAP3_SRAM_VA + 0x8000)
 #define OMAP4_SRAM_PA          0x40200000              /*0x402f0000*/
 #define OMAP4_SRAM_VA          0xd7000000              /*0xd70f0000*/
 
@@ -133,7 +133,12 @@ void __init omap_detect_sram(void)
                        if (cpu_is_omap34xx()) {
                                omap_sram_base = OMAP3_SRAM_PUB_VA;
                                omap_sram_start = OMAP3_SRAM_PUB_PA;
-                               omap_sram_size = 0x8000; /* 32K */
+                               if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) ||
+                                   (omap_type() == OMAP2_DEVICE_TYPE_SEC)) {
+                                       omap_sram_size = 0x7000; /* 28K */
+                               } else {
+                                       omap_sram_size = 0x8000; /* 32K */
+                               }
                        } else {
                                omap_sram_base = OMAP2_SRAM_PUB_VA;
                                omap_sram_start = OMAP2_SRAM_PUB_PA;
@@ -368,20 +373,26 @@ static inline int omap243x_sram_init(void)
 
 #ifdef CONFIG_ARCH_OMAP3
 
-static u32 (*_omap3_sram_configure_core_dpll)(u32 sdrc_rfr_ctrl,
-                                             u32 sdrc_actim_ctrla,
-                                             u32 sdrc_actim_ctrlb,
-                                             u32 m2, u32 unlock_dll,
-                                             u32 f, u32 sdrc_mr, u32 inc);
-u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl, u32 sdrc_actim_ctrla,
-                             u32 sdrc_actim_ctrlb, u32 m2, u32 unlock_dll,
-                             u32 f, u32 sdrc_mr, u32 inc)
+static u32 (*_omap3_sram_configure_core_dpll)(
+                       u32 m2, u32 unlock_dll, u32 f, u32 inc,
+                       u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
+                       u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
+                       u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
+                       u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1);
+
+u32 omap3_configure_core_dpll(u32 m2, u32 unlock_dll, u32 f, u32 inc,
+                       u32 sdrc_rfr_ctrl_0, u32 sdrc_actim_ctrl_a_0,
+                       u32 sdrc_actim_ctrl_b_0, u32 sdrc_mr_0,
+                       u32 sdrc_rfr_ctrl_1, u32 sdrc_actim_ctrl_a_1,
+                       u32 sdrc_actim_ctrl_b_1, u32 sdrc_mr_1)
 {
        BUG_ON(!_omap3_sram_configure_core_dpll);
-       return _omap3_sram_configure_core_dpll(sdrc_rfr_ctrl,
-                                              sdrc_actim_ctrla,
-                                              sdrc_actim_ctrlb, m2,
-                                              unlock_dll, f, sdrc_mr, inc);
+       return _omap3_sram_configure_core_dpll(
+                       m2, unlock_dll, f, inc,
+                       sdrc_rfr_ctrl_0, sdrc_actim_ctrl_a_0,
+                       sdrc_actim_ctrl_b_0, sdrc_mr_0,
+                       sdrc_rfr_ctrl_1, sdrc_actim_ctrl_a_1,
+                       sdrc_actim_ctrl_b_1, sdrc_mr_1);
 }
 
 /* REVISIT: Should this be same as omap34xx_sram_init() after off-idle? */
index 9646a94ed3d06aa1937f8d9889d11248777ebec3..07c430fdc9ef6489328337c05cee85fecb49524c 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef __PLAT_GPIO_H
 #define __PLAT_GPIO_H
 
+#include <linux/init.h>
+
 /*
  * GENERIC_GPIO primitives.
  */
index abc79d44acaacd472a3f1996c5c060487cbeba08..98548c6903a08aadff48196e2c4f6148968fc83d 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sysdev.h>
-#include <linux/bootmem.h>
+#include <linux/slab.h>
 
 #include <mach/gpio.h>
 
@@ -112,17 +112,12 @@ static int __init pxa_init_gpio_chip(int gpio_end)
        int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
        struct pxa_gpio_chip *chips;
 
-       /* this is early, we have to use bootmem allocator, and we really
-        * want this to be allocated dynamically for different 'gpio_end'
-        */
-       chips = alloc_bootmem_low(nbanks * sizeof(struct pxa_gpio_chip));
+       chips = kzalloc(nbanks * sizeof(struct pxa_gpio_chip), GFP_KERNEL);
        if (chips == NULL) {
                pr_err("%s: failed to allocate GPIO chips\n", __func__);
                return -ENOMEM;
        }
 
-       memset(chips, 0, nbanks * sizeof(struct pxa_gpio_chip));
-
        for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
                struct gpio_chip *c = &chips[i].chip;
 
index 74bb7cb5da49571766c568ec3ad5ad90a4d434a4..0761766b183325cc3f5f0a7565445bc3ff94705a 100644 (file)
@@ -34,7 +34,7 @@ obj-$(CONFIG_S3C_DEV_HSMMC)   += dev-hsmmc.o
 obj-$(CONFIG_S3C_DEV_HSMMC1)   += dev-hsmmc1.o
 obj-y                          += dev-i2c0.o
 obj-$(CONFIG_S3C_DEV_I2C1)     += dev-i2c1.o
-obj-$(CONFIG_SND_S3C24XX_SOC)  += dev-audio.o
+obj-$(CONFIG_SND_S3C64XX_SOC_I2S)      += dev-audio.o
 obj-$(CONFIG_S3C_DEV_FB)       += dev-fb.o
 obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o
 obj-$(CONFIG_S3C_DEV_USB_HSOTG)        += dev-usb-hsotg.o
diff --git a/arch/arm/plat-s3c/include/plat/audio-simtec.h b/arch/arm/plat-s3c/include/plat/audio-simtec.h
new file mode 100644 (file)
index 0000000..0f440b9
--- /dev/null
@@ -0,0 +1,37 @@
+/* arch/arm/plat-s3c/include/plat/audio-simtec.h
+ *
+ * Copyright 2008 Simtec Electronics
+ *     http://armlinux.simtec.co.uk/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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.
+ *
+ * Simtec Audio support.
+*/
+
+/**
+ * struct s3c24xx_audio_simtec_pdata - platform data for simtec audio
+ * @use_mpllin: Select codec clock from MPLLin
+ * @output_cdclk: Need to output CDCLK to the codec
+ * @have_mic: Set if we have a MIC socket
+ * @have_lout: Set if we have a LineOut socket
+ * @amp_gpio: GPIO pin to enable the AMP
+ * @amp_gain: Option GPIO to control AMP gain
+ */
+struct s3c24xx_audio_simtec_pdata {
+       unsigned int    use_mpllin:1;
+       unsigned int    output_cdclk:1;
+
+       unsigned int    have_mic:1;
+       unsigned int    have_lout:1;
+
+       int             amp_gpio;
+       int             amp_gain[2];
+
+       void    (*startup)(void);
+};
+
+extern int simtec_audio_add(const char *codec_name,
+                           struct s3c24xx_audio_simtec_pdata *pdata);
index b5b9c4d46e9a3b7e04745062d3086eb6d1947337..2e170827e0b078cd62db84541a7c23ebbf274672 100644 (file)
@@ -37,6 +37,7 @@ extern struct platform_device s3c_device_i2c1;
 extern struct platform_device s3c_device_rtc;
 extern struct platform_device s3c_device_adc;
 extern struct platform_device s3c_device_sdi;
+extern struct platform_device s3c_device_iis;
 extern struct platform_device s3c_device_hwmon;
 extern struct platform_device s3c_device_hsmmc0;
 extern struct platform_device s3c_device_hsmmc1;
index 0fad7571030eb9f911529e85f4d1d17c729ad704..07659dad1748a95ebcba9ad72f3d76f1905ea113 100644 (file)
 #define S3C2412_IISCON_RXDMA_ACTIVE    (1 << 1)
 #define S3C2412_IISCON_IIS_ACTIVE      (1 << 0)
 
+#define S3C64XX_IISMOD_BLC_16BIT       (0 << 13)
+#define S3C64XX_IISMOD_BLC_8BIT                (1 << 13)
+#define S3C64XX_IISMOD_BLC_24BIT       (2 << 13)
+#define S3C64XX_IISMOD_BLC_MASK                (3 << 13)
+
 #define S3C64XX_IISMOD_IMS_PCLK                (0 << 10)
 #define S3C64XX_IISMOD_IMS_SYSMUX      (1 << 10)
 
index 636cb12711df8e98de68cce12d0196d10529da94..579a165c282708276c3511eb8f6734b3f3cc588a 100644 (file)
@@ -29,7 +29,7 @@ obj-$(CONFIG_PM_SIMTEC)               += pm-simtec.o
 obj-$(CONFIG_PM)               += pm.o
 obj-$(CONFIG_PM)               += irq-pm.o
 obj-$(CONFIG_PM)               += sleep.o
-obj-$(CONFIG_HAVE_PWM)         += pwm.o
+obj-$(CONFIG_S3C24XX_PWM)      += pwm.o
 obj-$(CONFIG_S3C2410_CLOCK)    += s3c2410-clock.o
 obj-$(CONFIG_S3C2410_DMA)      += dma.o
 obj-$(CONFIG_S3C24XX_ADC)      += adc.o
index 5b75a797b5ab9f53cb54f9cf8bcf0cc839f51439..0afb217a775e1eec0ff34563dc2eaaf497490448 100644 (file)
@@ -129,7 +129,7 @@ static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent)
 
        /* calculate the MISCCR setting for the clock */
 
-       if (parent == &clk_xtal)
+       if (parent == &clk_mpll)
                source = S3C2410_MISCCR_CLK0_MPLL;
        else if (parent == &clk_upll)
                source = S3C2410_MISCCR_CLK0_UPLL;
index 0120b760315ba3a881fdf1829739b015829479a4..82a6d4de02a381ddfff417cf66b8c0425d107502 100644 (file)
@@ -246,6 +246,10 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
 
        tcmp = duty_ns / tin_ns;
        tcmp = tcnt - tcmp;
+       /* the pwm hw only checks the compare register after a decrement,
+          so the pin never toggles if tcmp = tcnt */
+       if (tcmp == tcnt)
+               tcmp--;
 
        pwm_dbg(pwm, "tin_ns=%lu, tcmp=%ld/%lu\n", tin_ns, tcmp, tcnt);
 
index 9edf7894eedd663fd5a2ad652515ce08c437f09d..da7a61728c18eacbe8acbbd5e4f8c36cf66ecc23 100644 (file)
@@ -12,8 +12,7 @@
 */
 
 #include <linux/kernel.h>
-
-#include <mach/hardware.h>
+#include <linux/gpio.h>
 
 #include <mach/spi.h>
 #include <mach/regs-gpio.h>
index f34d0fc69ad81228add93dcd4db889aa4c44230c..86b9edc674133e4b85fcbe628fdf36ef4a0efa76 100644 (file)
@@ -12,8 +12,7 @@
 */
 
 #include <linux/kernel.h>
-
-#include <mach/hardware.h>
+#include <linux/gpio.h>
 
 #include <mach/spi.h>
 #include <mach/regs-gpio.h>
index 07a6516a4f3cdfa97d26aaf71c1821ba19fca761..47632fc7eb66184cbd10ca6ef71232b195ff7f59 100644 (file)
@@ -117,8 +117,6 @@ void s3c_pm_save_core(void)
  * this.
  */
 
-#include <plat/regs-gpio.h>
-
 static void s3c64xx_cpu_suspend(void)
 {
        unsigned long tmp;
index 1debc1f9f987bd09cc96d0d2574493bd5adb9e73..febac1950d8ea658c5ba1321d56a000f01509972 100644 (file)
@@ -153,7 +153,7 @@ static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
        u32 div;
 
        if (parent < rate)
-               return rate;
+               return parent;
 
        div = (parent / rate) - 1;
        if (div > armclk_mask)
@@ -175,7 +175,7 @@ static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
        div = clk_get_rate(clk->parent) / rate;
 
        val = __raw_readl(S3C_CLK_DIV0);
-       val &= armclk_mask;
+       val &= ~armclk_mask;
        val |= (div - 1);
        __raw_writel(val, S3C_CLK_DIV0);
 
index d41200382208c6fc8918b178e991a2151ae42dd8..6d6b1a468eda765eb8425461398a5008db5f7e2e 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/sysdev.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
-#include <linux/sysdev.h>
 #include <linux/irq.h>
 
 #include <mach/hardware.h>
index 46c9b0a224cfb01812684d74f2f6b06fb8cfcb1c..75f19f47fb2fb92a8fea40b10ddd303d0f837ca8 100644 (file)
@@ -72,6 +72,10 @@ static struct ads7846_platform_data ads7843_data = {
        .debounce_max           = 20,
        .debounce_rep           = 4,
        .debounce_tol           = 5,
+
+       .keep_vref_on           = true,
+       .settle_delay_usecs     = 500,
+       .penirq_recheck_delay_usecs = 100,
 };
 
 static struct spi_board_info __initdata spi1_board_info[] = {
index 64082132394312a4c861abdc6b110f58517a7a40..92ecd8446ef80b6fe06c62bce45fe93a40f344bb 100644 (file)
@@ -83,7 +83,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
        quicklist_free_page(QUICK_PT, NULL, pte);
 }
 
-#define __pte_free_tlb(tlb,pte)                                \
+#define __pte_free_tlb(tlb,pte,addr)                   \
 do {                                                   \
        pgtable_page_dtor(pte);                         \
        tlb_remove_page((tlb), pte);                    \
index 4442f8d2d4239a09470e04583aa9f168583246d9..fc42de5ca209ac5e9de0cfca9c1f35561f740be2 100644 (file)
@@ -40,7 +40,7 @@ struct thread_info {
        .exec_domain    = &default_exec_domain,                         \
        .flags          = 0,                                            \
        .cpu            = 0,                                            \
-       .preempt_count  = 1,                                            \
+       .preempt_count  = INIT_PREEMPT_COUNT,                           \
        .restart_block  = {                                             \
                .fn     = do_no_restart_syscall                         \
        }                                                               \
index 6e3d491184eab1d079b83a6cdaf33139f1365c1f..b91b2044af9c9660210bb9efd5f11ab60a08dcbc 100644 (file)
@@ -32,22 +32,25 @@ void NORET_TYPE die(const char *str, struct pt_regs *regs, long err)
        spin_lock_irq(&die_lock);
        bust_spinlocks(1);
 
-       printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n" KERN_EMERG,
+       printk(KERN_ALERT "Oops: %s, sig: %ld [#%d]\n",
               str, err, ++die_counter);
+
+       printk(KERN_EMERG);
+
 #ifdef CONFIG_PREEMPT
-       printk("PREEMPT ");
+       printk(KERN_CONT "PREEMPT ");
 #endif
 #ifdef CONFIG_FRAME_POINTER
-       printk("FRAME_POINTER ");
+       printk(KERN_CONT "FRAME_POINTER ");
 #endif
        if (current_cpu_data.features & AVR32_FEATURE_OCD) {
                unsigned long did = ocd_read(DID);
-               printk("chip: 0x%03lx:0x%04lx rev %lu\n",
+               printk(KERN_CONT "chip: 0x%03lx:0x%04lx rev %lu\n",
                       (did >> 1) & 0x7ff,
                       (did >> 12) & 0x7fff,
                       (did >> 28) & 0xf);
        } else {
-               printk("cpu: arch %u r%u / core %u r%u\n",
+               printk(KERN_CONT "cpu: arch %u r%u / core %u r%u\n",
                       current_cpu_data.arch_type,
                       current_cpu_data.arch_revision,
                       current_cpu_data.cpu_type,
index 0abb26142b64689ae717f97be7f173a95e92861f..c2ca49d705af704da614ef7ff2dee9b4d253f975 100644 (file)
@@ -24,8 +24,8 @@ memcpy:
        brne    1f
 
        /* At this point, "from" is word-aligned */
-2:     sub     r10, 4
-       mov     r9, r12
+2:     mov     r9, r12
+5:     sub     r10, 4
        brlt    4f
 
 3:     ld.w    r8, r11++
@@ -49,6 +49,7 @@ memcpy:
 
        /* Handle unaligned "from" pointer */
 1:     sub     r10, 4
+       movlt   r9, r12
        brlt    4b
        add     r10, r9
        lsl     r9, 2
@@ -59,4 +60,13 @@ memcpy:
        st.b    r12++, r8
        ld.ub   r8, r11++
        st.b    r12++, r8
-       rjmp    2b
+       mov     r8, r12
+       add     pc, pc, r9
+       sub     r8, 1
+       nop
+       sub     r8, 1
+       nop
+       sub     r8, 1
+       nop
+       mov     r9, r8
+       rjmp    5b
index 16561ab18b38b602a9426a9f0c6c0b8bcb8aac93..f8a664f022b1ad1022bf7c9aa842e369124e4808 100644 (file)
        [--sp] = RETN;
        [--sp] = RETE;
        [--sp] = SEQSTAT;
-#ifdef CONFIG_KGDB
-       r1.l = lo(IPEND);
-       r1.h = hi(IPEND);
+#ifdef CONFIG_DEBUG_KERNEL
+       p1.l = lo(IPEND);
+       p1.h = hi(IPEND);
+       r1 = [p1];
        [--sp] = r1;
 #else
        [--sp] = r0;    /* Skip IPEND as well. */
index 565b8136855ed16d5237376cc7186878dcc46855..fadfa82f93b2d11c3ffa3cbfa9324a10c4b94261 100644 (file)
@@ -32,7 +32,6 @@ struct blackfin_cpudata {
        struct task_struct *idle;
        unsigned int imemctl;
        unsigned int dmemctl;
-       unsigned long loops_per_jiffy;
        unsigned long dcache_invld_count;
        unsigned long icache_invld_count;
 };
index cbd52f86bb9f752ce8f33dff091546e815a3ed38..0b78b873df5103fca28d39673703a4aac45e3e04 100644 (file)
@@ -6,6 +6,9 @@
 extern void ack_bad_irq(unsigned int irq);
 #define ack_bad_irq ack_bad_irq
 
+/* Define until common code gets sane defaults */
+#define HARDIRQ_BITS 9
+
 #include <asm-generic/hardirq.h>
 
 #endif
index d0be99be8308d3a9324dacae900939f384e6f1e0..a36ad8dac0681914dd067af2a6c1609d39e475c5 100644 (file)
@@ -105,23 +105,16 @@ static inline uint32_t __pure bfin_revid(void)
        /* Always use CHIPID, to work around ANOMALY_05000234 */
        uint32_t revid = (bfin_read_CHIPID() & CHIPID_VERSION) >> 28;
 
-#ifdef CONFIG_BF52x
-       /* ANOMALY_05000357
+#ifdef _BOOTROM_GET_DXE_ADDRESS_TWI
+       /*
+        * ANOMALY_05000364
         * Incorrect Revision Number in DSPID Register
         */
-       if (revid == 0)
-               switch (bfin_read16(_BOOTROM_GET_DXE_ADDRESS_TWI)) {
-               case 0x0010:
-                       revid = 0;
-                       break;
-               case 0x2796:
-                       revid = 1;
-                       break;
-               default:
-                       revid = 0xFFFF;
-                       break;
-               }
+       if (ANOMALY_05000364 &&
+           bfin_read16(_BOOTROM_GET_DXE_ADDRESS_TWI) == 0x2796)
+               revid = 1;
 #endif
+
        return revid;
 }
 
index 2920087516f2a08175b54ed3086844434db937c9..2bbfdd950afc49c4623d876125b0a71dd7de4903 100644 (file)
@@ -77,7 +77,7 @@ struct thread_info {
        .exec_domain    = &default_exec_domain, \
        .flags          = 0,                    \
        .cpu            = 0,                    \
-       .preempt_count  = 1,                    \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .restart_block  = {                     \
                .fn = do_no_restart_syscall,    \
        },                                      \
index e0bf8cc06907abd67040c37127f0091792c39a8a..9f9b82816652d6bddc4c67199699d9ba22647e1f 100644 (file)
@@ -253,32 +253,31 @@ void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size)
        BUG_ON(src % 4);
        BUG_ON(size % 4);
 
-       /* Force a sync in case a previous config reset on this channel
-        * occurred.  This is needed so subsequent writes to DMA registers
-        * are not spuriously lost/corrupted.
-        */
-       __builtin_bfin_ssync();
-
        src_ch = 0;
        /* Find an avalible memDMA channel */
        while (1) {
-               if (!src_ch || src_ch == (struct dma_register *)MDMA_S1_NEXT_DESC_PTR) {
-                       dst_ch = (struct dma_register *)MDMA_D0_NEXT_DESC_PTR;
-                       src_ch = (struct dma_register *)MDMA_S0_NEXT_DESC_PTR;
-               } else {
+               if (src_ch == (struct dma_register *)MDMA_S0_NEXT_DESC_PTR) {
                        dst_ch = (struct dma_register *)MDMA_D1_NEXT_DESC_PTR;
                        src_ch = (struct dma_register *)MDMA_S1_NEXT_DESC_PTR;
+               } else {
+                       dst_ch = (struct dma_register *)MDMA_D0_NEXT_DESC_PTR;
+                       src_ch = (struct dma_register *)MDMA_S0_NEXT_DESC_PTR;
                }
 
-               if (!bfin_read16(&src_ch->cfg)) {
+               if (!bfin_read16(&src_ch->cfg))
+                       break;
+               else if (bfin_read16(&dst_ch->irq_status) & DMA_DONE) {
+                       bfin_write16(&src_ch->cfg, 0);
                        break;
-               } else {
-                       if (bfin_read16(&src_ch->irq_status) & DMA_DONE)
-                               bfin_write16(&src_ch->cfg, 0);
                }
-
        }
 
+       /* Force a sync in case a previous config reset on this channel
+        * occurred.  This is needed so subsequent writes to DMA registers
+        * are not spuriously lost/corrupted.
+        */
+       __builtin_bfin_ssync();
+
        /* Destination */
        bfin_write32(&dst_ch->start_addr, dst);
        bfin_write16(&dst_ch->x_count, size >> 2);
index beffa00a93c3a6e2d98f236e82f1653e232c40e8..6b94462713710b612f3fb82e351b92d5e5bdb46a 100644 (file)
@@ -686,14 +686,12 @@ void bfin_gpio_pm_hibernate_restore(void)
                *port_fer[bank] = gpio_bank_saved[bank].fer;
 #endif
                gpio_array[bank]->inen  = gpio_bank_saved[bank].inen;
+               gpio_array[bank]->data_set = gpio_bank_saved[bank].data
+                                               & gpio_bank_saved[bank].dir;
                gpio_array[bank]->dir   = gpio_bank_saved[bank].dir;
                gpio_array[bank]->polar = gpio_bank_saved[bank].polar;
                gpio_array[bank]->edge  = gpio_bank_saved[bank].edge;
                gpio_array[bank]->both  = gpio_bank_saved[bank].both;
-
-               gpio_array[bank]->data_set = gpio_bank_saved[bank].data
-                                               | gpio_bank_saved[bank].dir;
-
                gpio_array[bank]->maska = gpio_bank_saved[bank].maska;
        }
        AWA_DUMMY_READ(maska);
index d6c067782e638987ba406164f6df65adeb0b15db..685f160a5a369789671f948e2132d36fb5c2e29b 100644 (file)
@@ -72,13 +72,24 @@ void __init generate_cplb_tables_cpu(unsigned int cpu)
        }
 
        /* Cover L1 memory.  One 4M area for code and data each is enough.  */
-       if (L1_DATA_A_LENGTH || L1_DATA_B_LENGTH) {
-               d_tbl[i_d].addr = L1_DATA_A_START;
-               d_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
+       if (cpu == 0) {
+               if (L1_DATA_A_LENGTH || L1_DATA_B_LENGTH) {
+                       d_tbl[i_d].addr = L1_DATA_A_START;
+                       d_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
+               }
+               i_tbl[i_i].addr = L1_CODE_START;
+               i_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
        }
-       i_tbl[i_i].addr = L1_CODE_START;
-       i_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
-
+#ifdef CONFIG_SMP
+       else {
+               if (L1_DATA_A_LENGTH || L1_DATA_B_LENGTH) {
+                       d_tbl[i_d].addr = COREB_L1_DATA_A_START;
+                       d_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB;
+               }
+               i_tbl[i_i].addr = COREB_L1_CODE_START;
+               i_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB;
+       }
+#endif
        first_switched_dcplb = i_d;
        first_switched_icplb = i_i;
 
index 79cad0ac5892eacdcb153e046eb3ee6115c5c69d..9da36bab7ccb10194a3cde2c40628f4e52aeeccb 100644 (file)
@@ -361,7 +361,7 @@ static inline
 int in_mem_const(unsigned long addr, unsigned long size,
                  unsigned long const_addr, unsigned long const_size)
 {
-       return in_mem_const_off(addr, 0, size, const_addr, const_size);
+       return in_mem_const_off(addr, size, 0, const_addr, const_size);
 }
 #define IN_ASYNC(bnum, bctlnum) \
 ({ \
@@ -390,13 +390,13 @@ int bfin_mem_access_type(unsigned long addr, unsigned long size)
        if (in_mem_const(addr, size, L1_DATA_B_START, L1_DATA_B_LENGTH))
                return cpu == 0 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA;
 #ifdef COREB_L1_CODE_START
-       if (in_mem_const(addr, size, COREB_L1_CODE_START, L1_CODE_LENGTH))
+       if (in_mem_const(addr, size, COREB_L1_CODE_START, COREB_L1_CODE_LENGTH))
                return cpu == 1 ? BFIN_MEM_ACCESS_ITEST : BFIN_MEM_ACCESS_IDMA;
        if (in_mem_const(addr, size, COREB_L1_SCRATCH_START, L1_SCRATCH_LENGTH))
                return cpu == 1 ? BFIN_MEM_ACCESS_CORE_ONLY : -EFAULT;
-       if (in_mem_const(addr, size, COREB_L1_DATA_A_START, L1_DATA_A_LENGTH))
+       if (in_mem_const(addr, size, COREB_L1_DATA_A_START, COREB_L1_DATA_A_LENGTH))
                return cpu == 1 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA;
-       if (in_mem_const(addr, size, COREB_L1_DATA_B_START, L1_DATA_B_LENGTH))
+       if (in_mem_const(addr, size, COREB_L1_DATA_B_START, COREB_L1_DATA_B_LENGTH))
                return cpu == 1 ? BFIN_MEM_ACCESS_CORE : BFIN_MEM_ACCESS_IDMA;
 #endif
        if (in_mem_const(addr, size, L2_START, L2_LENGTH))
@@ -472,13 +472,13 @@ int _access_ok(unsigned long addr, unsigned long size)
        if (in_mem_const_off(addr, size, _ebss_b_l1 - _sdata_b_l1, L1_DATA_B_START, L1_DATA_B_LENGTH))
                return 1;
 #ifdef COREB_L1_CODE_START
-       if (in_mem_const(addr, size, COREB_L1_CODE_START, L1_CODE_LENGTH))
+       if (in_mem_const(addr, size, COREB_L1_CODE_START, COREB_L1_CODE_LENGTH))
                return 1;
        if (in_mem_const(addr, size, COREB_L1_SCRATCH_START, L1_SCRATCH_LENGTH))
                return 1;
-       if (in_mem_const(addr, size, COREB_L1_DATA_A_START, L1_DATA_A_LENGTH))
+       if (in_mem_const(addr, size, COREB_L1_DATA_A_START, COREB_L1_DATA_A_LENGTH))
                return 1;
-       if (in_mem_const(addr, size, COREB_L1_DATA_B_START, L1_DATA_B_LENGTH))
+       if (in_mem_const(addr, size, COREB_L1_DATA_B_START, COREB_L1_DATA_B_LENGTH))
                return 1;
 #endif
        if (in_mem_const_off(addr, size, _ebss_l2 - _stext_l2, L2_START, L2_LENGTH))
index d76618db50df8c4e3f4c06cb44d09906e5b41147..6a387eec6b65e5baa3bcfb247e037748bea6f587 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index 298f023bcc09b91bbb34eb59262dbf60069b59e3..6225edae488edeb713db588487fe709d839572eb 100644 (file)
@@ -168,7 +168,6 @@ void __cpuinit bfin_setup_cpudata(unsigned int cpu)
        struct blackfin_cpudata *cpudata = &per_cpu(cpu_data, cpu);
 
        cpudata->idle = current;
-       cpudata->loops_per_jiffy = loops_per_jiffy;
        cpudata->imemctl = bfin_read_IMEM_CONTROL();
        cpudata->dmemctl = bfin_read_DMEM_CONTROL();
 }
@@ -408,13 +407,14 @@ static void __init print_memory_map(char *who)
                        bfin_memmap.map[i].addr + bfin_memmap.map[i].size);
                switch (bfin_memmap.map[i].type) {
                case BFIN_MEMMAP_RAM:
-                               printk("(usable)\n");
-                               break;
+                       printk(KERN_CONT "(usable)\n");
+                       break;
                case BFIN_MEMMAP_RESERVED:
-                               printk("(reserved)\n");
-                               break;
-               default:        printk("type %lu\n", bfin_memmap.map[i].type);
-                               break;
+                       printk(KERN_CONT "(reserved)\n");
+                       break;
+               default:
+                       printk(KERN_CONT "type %lu\n", bfin_memmap.map[i].type);
+                       break;
                }
        }
 }
@@ -567,17 +567,23 @@ static __init void memory_setup(void)
 #  endif                               /* ANOMALY_05000263 */
 # endif                                /* CONFIG_ROMFS_FS */
 
-       memory_end -= mtd_size;
-
-       if (mtd_size == 0) {
-               console_init();
-               panic("Don't boot kernel without rootfs attached.");
+       /* Since the default MTD_UCLINUX has no magic number, we just blindly
+        * read 8 past the end of the kernel's image, and look at it.
+        * When no image is attached, mtd_size is set to a random number
+        * Do some basic sanity checks before operating on things
+        */
+       if (mtd_size == 0 || memory_end <= mtd_size) {
+               pr_emerg("Could not find valid ram mtd attached.\n");
+       } else {
+               memory_end -= mtd_size;
+
+               /* Relocate MTD image to the top of memory after the uncached memory area */
+               uclinux_ram_map.phys = memory_mtd_start = memory_end;
+               uclinux_ram_map.size = mtd_size;
+               pr_info("Found mtd parition at 0x%p, (len=0x%lx), moving to 0x%p\n",
+                       _end, mtd_size, (void *)memory_mtd_start);
+               dma_memcpy((void *)uclinux_ram_map.phys, _end, uclinux_ram_map.size);
        }
-
-       /* Relocate MTD image to the top of memory after the uncached memory area */
-       uclinux_ram_map.phys = memory_mtd_start = memory_end;
-       uclinux_ram_map.size = mtd_size;
-       dma_memcpy((void *)uclinux_ram_map.phys, _end, uclinux_ram_map.size);
 #endif                         /* CONFIG_MTD_UCLINUX */
 
 #if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
@@ -614,19 +620,19 @@ static __init void memory_setup(void)
        printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", _ramend >> 20);
 
        printk(KERN_INFO "Memory map:\n"
-               KERN_INFO "  fixedcode = 0x%p-0x%p\n"
-               KERN_INFO "  text      = 0x%p-0x%p\n"
-               KERN_INFO "  rodata    = 0x%p-0x%p\n"
-               KERN_INFO "  bss       = 0x%p-0x%p\n"
-               KERN_INFO "  data      = 0x%p-0x%p\n"
-               KERN_INFO "    stack   = 0x%p-0x%p\n"
-               KERN_INFO "  init      = 0x%p-0x%p\n"
-               KERN_INFO "  available = 0x%p-0x%p\n"
+              "  fixedcode = 0x%p-0x%p\n"
+              "  text      = 0x%p-0x%p\n"
+              "  rodata    = 0x%p-0x%p\n"
+              "  bss       = 0x%p-0x%p\n"
+              "  data      = 0x%p-0x%p\n"
+              "    stack   = 0x%p-0x%p\n"
+              "  init      = 0x%p-0x%p\n"
+              "  available = 0x%p-0x%p\n"
 #ifdef CONFIG_MTD_UCLINUX
-               KERN_INFO "  rootfs    = 0x%p-0x%p\n"
+              "  rootfs    = 0x%p-0x%p\n"
 #endif
 #if DMA_UNCACHED_REGION > 0
-               KERN_INFO "  DMA Zone  = 0x%p-0x%p\n"
+              "  DMA Zone  = 0x%p-0x%p\n"
 #endif
                , (void *)FIXED_CODE_START, (void *)FIXED_CODE_END,
                _stext, _etext,
@@ -859,20 +865,13 @@ void __init setup_arch(char **cmdline_p)
 #endif
        printk(KERN_INFO "Hardware Trace ");
        if (bfin_read_TBUFCTL() & 0x1)
-               printk("Active ");
+               printk(KERN_CONT "Active ");
        else
-               printk("Off ");
+               printk(KERN_CONT "Off ");
        if (bfin_read_TBUFCTL() & 0x2)
-               printk("and Enabled\n");
+               printk(KERN_CONT "and Enabled\n");
        else
-       printk("and Disabled\n");
-
-#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
-       /* we need to initialize the Flashrom device here since we might
-        * do things with flash early on in the boot
-        */
-       flash_probe();
-#endif
+               printk(KERN_CONT "and Disabled\n");
 
        printk(KERN_INFO "Boot Mode: %i\n", bfin_read_SYSCR() & 0xF);
 
@@ -937,10 +936,6 @@ void __init setup_arch(char **cmdline_p)
                               CPU, bfin_revid());
        }
 
-       /* We can't run on BF548-0.1 due to ANOMALY 05000448 */
-       if (bfin_cpuid() == 0x27de && bfin_revid() == 1)
-               panic("You can't run on this processor due to 05000448");
-
        printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n");
 
        printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n",
@@ -1163,9 +1158,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                sclk/1000000, sclk%1000000);
        seq_printf(m, "bogomips\t: %lu.%02lu\n"
                "Calibration\t: %lu loops\n",
-               (cpudata->loops_per_jiffy * HZ) / 500000,
-               ((cpudata->loops_per_jiffy * HZ) / 5000) % 100,
-               (cpudata->loops_per_jiffy * HZ));
+               (loops_per_jiffy * HZ) / 500000,
+               ((loops_per_jiffy * HZ) / 5000) % 100,
+               (loops_per_jiffy * HZ));
 
        /* Check Cache configutation */
        switch (cpudata->dmemctl & (1 << DMC0_P | 1 << DMC1_P)) {
index a8f1329c15a48befeb62f31a7b80603b263dda2d..3da60fb13ce46d8a45b5194e152985608c0cbaeb 100644 (file)
@@ -29,7 +29,6 @@
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
index 8eeb457ce5d5fc6cc6541a174be1c6989113328a..bf2b2d1f8ae5f35ecd64b68abbbc324f444fa421 100644 (file)
@@ -212,7 +212,7 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
        console_verbose();
        oops_in_progress = 1;
 #ifdef CONFIG_DEBUG_VERBOSE
-       printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n");
+       printk(KERN_EMERG "Double Fault\n");
 #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT
        if (((long)fp->seqstat &  SEQSTAT_EXCAUSE) == VEC_UNCOV) {
                unsigned int cpu = smp_processor_id();
@@ -570,11 +570,12 @@ asmlinkage void trap_c(struct pt_regs *fp)
        if (kernel_mode_regs(fp) || (current && !current->mm)) {
                console_verbose();
                oops_in_progress = 1;
-               if (strerror)
-                       verbose_printk(strerror);
        }
 
        if (sig != SIGTRAP) {
+               if (strerror)
+                       verbose_printk(strerror);
+
                dump_bfin_process(fp);
                dump_bfin_mem(fp);
                show_regs(fp);
@@ -583,15 +584,14 @@ asmlinkage void trap_c(struct pt_regs *fp)
 #ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE
                if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M)
                        verbose_printk(KERN_NOTICE "No trace since you do not have "
-                               "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n"
-                               KERN_NOTICE "\n");
+                              "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n\n");
                else
 #endif
                        dump_bfin_trace_buffer();
 
                if (oops_in_progress) {
                        /* Dump the current kernel stack */
-                       verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n");
+                       verbose_printk(KERN_NOTICE "Kernel Stack\n");
                        show_stack(current, NULL);
                        print_modules();
 #ifndef CONFIG_ACCESS_CHECK
@@ -620,7 +620,9 @@ asmlinkage void trap_c(struct pt_regs *fp)
                force_sig_info(sig, &info, current);
        }
 
-       if (ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8))
+       if ((ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8)) ||
+           (ANOMALY_05000281 && trapnr == VEC_HWERR) ||
+           (ANOMALY_05000189 && (trapnr == VEC_CPLB_I_VL || trapnr == VEC_CPLB_VL)))
                fp->pc = SAFE_USER_INSTRUCTION;
 
  traps_done:
@@ -906,7 +908,7 @@ void show_stack(struct task_struct *task, unsigned long *stack)
 
                        ret_addr = 0;
                        if (!j && i % 8 == 0)
-                               printk("\n" KERN_NOTICE "%p:",addr);
+                               printk(KERN_NOTICE "%p:",addr);
 
                        /* if it is an odd address, or zero, just skip it */
                        if (*addr & 0x1 || !*addr)
@@ -996,9 +998,9 @@ void dump_bfin_process(struct pt_regs *fp)
 
                printk(KERN_NOTICE "CPU = %d\n", current_thread_info()->cpu);
                if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START)
-                       verbose_printk(KERN_NOTICE  "TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
-                               KERN_NOTICE " BSS = 0x%p-0x%p  USER-STACK = 0x%p\n"
-                               KERN_NOTICE "\n",
+                       verbose_printk(KERN_NOTICE
+                               "TEXT = 0x%p-0x%p        DATA = 0x%p-0x%p\n"
+                               " BSS = 0x%p-0x%p  USER-STACK = 0x%p\n\n",
                                (void *)current->mm->start_code,
                                (void *)current->mm->end_code,
                                (void *)current->mm->start_data,
@@ -1009,8 +1011,8 @@ void dump_bfin_process(struct pt_regs *fp)
                else
                        verbose_printk(KERN_NOTICE "invalid mm\n");
        } else
-               verbose_printk(KERN_NOTICE "\n" KERN_NOTICE
-                    "No Valid process in current context\n");
+               verbose_printk(KERN_NOTICE
+                              "No Valid process in current context\n");
 #endif
 }
 
@@ -1028,7 +1030,7 @@ void dump_bfin_mem(struct pt_regs *fp)
             addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10;
             addr++) {
                if (!((unsigned long)addr & 0xF))
-                       verbose_printk("\n" KERN_NOTICE "0x%p: ", addr);
+                       verbose_printk(KERN_NOTICE "0x%p: ", addr);
 
                if (!get_instruction(&val, addr)) {
                                val = 0;
@@ -1056,9 +1058,9 @@ void dump_bfin_mem(struct pt_regs *fp)
            oops_in_progress)){
                verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n");
 #ifndef CONFIG_DEBUG_HWERR
-               verbose_printk(KERN_NOTICE "The remaining message may be meaningless\n"
-                       KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a"
-                        " better idea where it came from\n");
+               verbose_printk(KERN_NOTICE
+"The remaining message may be meaningless\n"
+"You should enable CONFIG_DEBUG_HWERR to get a better idea where it came from\n");
 #else
                /* If we are handling only one peripheral interrupt
                 * and current mm and pid are valid, and the last error
@@ -1114,9 +1116,10 @@ void show_regs(struct pt_regs *fp)
 
        verbose_printk(KERN_NOTICE "%s", linux_banner);
 
-       verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted());
+       verbose_printk(KERN_NOTICE "\nSEQUENCER STATUS:\t\t%s\n",
+                      print_tainted());
        verbose_printk(KERN_NOTICE " SEQSTAT: %08lx  IPEND: %04lx  SYSCFG: %04lx\n",
-               (long)fp->seqstat, fp->ipend, fp->syscfg);
+                      (long)fp->seqstat, fp->ipend, fp->syscfg);
        if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) {
                verbose_printk(KERN_NOTICE "  HWERRCAUSE: 0x%lx\n",
                        (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14);
@@ -1184,7 +1187,7 @@ unlock:
                verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
        }
 
-       verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n");
+       verbose_printk(KERN_NOTICE "PROCESSOR STATE:\n");
        verbose_printk(KERN_NOTICE " R0 : %08lx    R1 : %08lx    R2 : %08lx    R3 : %08lx\n",
                fp->r0, fp->r1, fp->r2, fp->r3);
        verbose_printk(KERN_NOTICE " R4 : %08lx    R5 : %08lx    R6 : %08lx    R7 : %08lx\n",
index 84b9c5592220eac8648306a57295047b21456671..e57bf6fbdf3f4040bee13652a35c984b8cc45d85 100644 (file)
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#define BITS_PER_UNIT 8
-
-typedef int SItype __attribute__ ((mode(SI)));
-typedef unsigned int USItype __attribute__ ((mode(SI)));
-typedef int DItype __attribute__ ((mode(DI)));
-typedef int word_type __attribute__ ((mode(__word__)));
-
-struct DIstruct {
-       SItype high, low;
-};
-
-typedef union {
-       struct DIstruct s;
-       DItype ll;
-} DIunion;
+#include "gcclib.h"
 
 #ifdef CONFIG_ARITHMETIC_OPS_L1
 DItype __lshrdi3(DItype u, word_type b)__attribute__((l1_text));
index d9791106be9f71b16187201736815a09bcfa8445..809be268e42d4fcdf20ea802bb35bb1d87677559 100644 (file)
@@ -534,7 +534,7 @@ static struct platform_device i2c_bfin_twi_device = {
 #endif
 
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
-#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
        },
index 426e064062a0322ed4a21fe29096869fdcf71cce..753ed810e1c61f8bc0b63d6a117c82504f3fbd9e 100644 (file)
@@ -82,6 +82,7 @@
 #define ANOMALY_05000179 (0)
 #define ANOMALY_05000182 (0)
 #define ANOMALY_05000183 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
 #define ANOMALY_05000202 (0)
 #define ANOMALY_05000215 (0)
 #define ANOMALY_05000357 (0)
 #define ANOMALY_05000362 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000371 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (0)
index 0fb2ce5d840e14ae73ba9058d19e4da9f3bd0733..dbade93395eb2b996e1467702504436a6c97c958 100644 (file)
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
index f4867ce0c618b89f64c9d634739f65bf8934de89..b09484f538f41abdf1ebf69ebd48acb7fe61f9c4 100644 (file)
@@ -793,7 +793,7 @@ static struct platform_device i2c_bfin_twi_device = {
 #endif
 
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
-#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
                .type = "pcf8574_lcd",
index b2f30f06b73e2290b40bc518d292c0a135ed6f14..2ad68cd10ae674af6b7d693afb98f7cbcdc79320 100644 (file)
@@ -591,7 +591,7 @@ static struct platform_device i2c_bfin_twi_device = {
 #endif
 
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
-#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
        },
index 799a1d1fa89044f87eae1691350199fae081f851..75e563d3f9d4f0f49aa87921a11781e8fbcbd01b 100644 (file)
@@ -858,7 +858,7 @@ static struct platform_device i2c_bfin_twi_device = {
 #endif
 
 static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
-#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
        },
index 0d63f7406168cd154684dd352c9b741f8f7ec8b0..c438ca89d8c9047c71669ffd652d67a92f135eb1 100644 (file)
 #define ANOMALY_05000443 (1)
 /* The WURESET Bit in the SYSCR Register is not Functional */
 #define ANOMALY_05000445 (1)
+/* USB DMA Short Packet Data Corruption */
+#define ANOMALY_05000450 (1)
 /* BCODE_QUICKBOOT, BCODE_ALLBOOT, and BCODE_FULLBOOT Settings in SYSCR Register Not Functional */
 #define ANOMALY_05000451 (1)
 /* Incorrect Default Hysteresis Setting for RESET, NMI, and BMODE Signals */
 #define ANOMALY_05000179 (0)
 #define ANOMALY_05000182 (0)
 #define ANOMALY_05000183 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
 #define ANOMALY_05000202 (0)
 #define ANOMALY_05000215 (0)
 #define ANOMALY_05000412 (0)
 #define ANOMALY_05000447 (0)
 #define ANOMALY_05000448 (0)
-#define ANOMALY_05000450 (0)
 
 #endif
index a625659dd67f4470d0ff310e833362ddd6ff3ebe..ebd6cebc1fbc40bd500b6df924b05fd81b1b53f7 100644 (file)
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
index a68ade8a3ca2a876c721c030efa84dfa01087d0d..3d743ccaff6ab8d4b543b091f72833b8c8f73a21 100644 (file)
@@ -453,7 +453,7 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
                .irq = 39,
        },
 #endif
-#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
        },
index 70a0ad69c6106f94c95a4b835cb917d4c086880c..cd83db2fb1a17fdc99e3cba7a7423005430afc80 100644 (file)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000353 (1)
 #define ANOMALY_05000362 (1)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
 #define ANOMALY_05000389 (0)
index a3789d7ccf8c233c4fc182be215ba7585742c7c8..4062e24e759bbc83eb51dedf8386fb7dcc9792bd 100644 (file)
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
index c1f76dd2c4ed50aac0fb806098e776854782b8b7..bd656907b8c01588983d0f4e3c1cf267679d0c5c 100644 (file)
@@ -1313,10 +1313,10 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = {
 #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
        {
                I2C_BOARD_INFO("ad7142_joystick", 0x2C),
-               .irq = IRQ_PF5,
+               .irq = IRQ_PG5,
        },
 #endif
-#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
        },
index 57c128cc3b6480a57762e5269bbccfb9365a6718..e66aa131f517d66ec5fe17588bf71d5f8c1cb7ef 100644 (file)
 #define ANOMALY_05000179 (0)
 #define ANOMALY_05000182 (0)
 #define ANOMALY_05000183 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
 #define ANOMALY_05000202 (0)
 #define ANOMALY_05000215 (0)
 #define ANOMALY_05000353 (1)
 #define ANOMALY_05000362 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
 #define ANOMALY_05000389 (0)
index b86662fb9de76fad4cf16b0ee3a46e5d81db4d32..e95d54f9af6c008075cb9529b47e066ac376cc4d 100644 (file)
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
index c97acdf85cd3020b70a362b17ceb53e16464813f..451cf8a82a42b0e1edbb3525232cf485587158af 100644 (file)
 #define ANOMALY_05000158 (0)
 #define ANOMALY_05000171 (0)
 #define ANOMALY_05000182 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
 #define ANOMALY_05000202 (0)
 #define ANOMALY_05000215 (0)
 #define ANOMALY_05000353 (1)
 #define ANOMALY_05000362 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
 #define ANOMALY_05000389 (0)
index c536551eb4b8ff64dd35194d9270e32014aa8704..999f239fe1a6376373efe75f5424398d48308ee1 100644 (file)
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
index 81f5b95cc3612d1592765274056c090627c6dfff..dc0dd9b2bcef46383369795cda3a3a19264e2fe4 100644 (file)
@@ -864,7 +864,7 @@ static struct i2c_board_info __initdata bfin_i2c_board_info0[] = {
 
 #if !defined(CONFIG_BF542)     /* The BF542 only has 1 TWI */
 static struct i2c_board_info __initdata bfin_i2c_board_info1[] = {
-#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
+#if defined(CONFIG_BFIN_TWI_LCD) || defined(CONFIG_BFIN_TWI_LCD_MODULE)
        {
                I2C_BOARD_INFO("pcf8574_lcd", 0x22),
        },
index 18a4cd24f6732492bfeb9ed2bbb5ededb30f38fb..cd040fe0bc5c10e47b38f6fbd1882d5f3dbdad34 100644 (file)
 #define ANOMALY_05000179 (0)
 #define ANOMALY_05000182 (0)
 #define ANOMALY_05000183 (0)
+#define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
 #define ANOMALY_05000202 (0)
 #define ANOMALY_05000215 (0)
 #define ANOMALY_05000323 (0)
 #define ANOMALY_05000362 (1)
 #define ANOMALY_05000363 (0)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000400 (0)
 #define ANOMALY_05000412 (0)
index 94b8e277f09d1d1773291fc6065c4be73e0b285a..a5312b2d267e25117d53a6875f0ffcc0c75c4e9c 100644 (file)
 #define ANOMALY_05000273 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000353 (1)
+#define ANOMALY_05000364 (0)
 #define ANOMALY_05000380 (0)
 #define ANOMALY_05000386 (1)
 #define ANOMALY_05000389 (0)
index a1b50878553fbfc462e63a869a5ab7be1c190722..fd5e8878b8c419f73f99b84d89a5db7b96748173 100644 (file)
@@ -53,7 +53,7 @@
 #define UART_SET_DLAB(uart)     do { UART_PUT_LCR(uart, UART_GET_LCR(uart) | DLAB); SSYNC(); } while (0)
 #define UART_CLEAR_DLAB(uart)   do { UART_PUT_LCR(uart, UART_GET_LCR(uart) & ~DLAB); SSYNC(); } while (0)
 
-#define UART_GET_CTS(x) (!gpio_get_value(x->cts_pin))
+#define UART_GET_CTS(x) gpio_get_value(x->cts_pin)
 #define UART_DISABLE_RTS(x) gpio_set_value(x->rts_pin, 1)
 #define UART_ENABLE_RTS(x) gpio_set_value(x->rts_pin, 0)
 #define UART_ENABLE_INTS(x, v) UART_PUT_IER(x, v)
index a63e15c86d90438dec954ce6b6d883682e13374a..5b96ea549a049bb00a902e779da827e338d6d9da 100644 (file)
@@ -37,7 +37,6 @@
 
 /* Memory Map for ADSP-BF561 processors */
 
-#ifdef CONFIG_BF561
 #define COREA_L1_CODE_START       0xFFA00000
 #define COREA_L1_DATA_A_START     0xFF800000
 #define COREA_L1_DATA_B_START     0xFF900000
 #define BFIN_DCACHESIZE        (0*1024)
 #define BFIN_DSUPBANKS 0
 #endif /*CONFIG_BFIN_DCACHE*/
+
+/*
+ * If we are in SMP mode, then the cache settings of Core B will match
+ * the settings of Core A.  If we aren't, then we assume Core B is not
+ * using any cache.  This allows the rest of the kernel to work with
+ * the core in either mode as we are only loading user code into it and
+ * it is the user's problem to make sure they aren't doing something
+ * stupid there.
+ *
+ * Note that we treat the L1 code region as a contiguous blob to make
+ * the rest of the kernel simpler.  Easier to check one region than a
+ * bunch of small ones.  Again, possible misbehavior here is the fault
+ * of the user -- don't try to use memory that doesn't exist.
+ */
+#ifdef CONFIG_SMP
+# define COREB_L1_CODE_LENGTH     L1_CODE_LENGTH
+# define COREB_L1_DATA_A_LENGTH   L1_DATA_A_LENGTH
+# define COREB_L1_DATA_B_LENGTH   L1_DATA_B_LENGTH
+#else
+# define COREB_L1_CODE_LENGTH     0x14000
+# define COREB_L1_DATA_A_LENGTH   0x8000
+# define COREB_L1_DATA_B_LENGTH   0x8000
 #endif
 
 /* Level 2 Memory */
index 5a4e7c7fd92c4e0976ce58f1bf977b6911390775..fb1795d5be2af2e9765f31c1c40fafd90257580e 100644 (file)
@@ -218,7 +218,7 @@ ENTRY(_ex_single_step)
        /* Single stepping only a single instruction, so clear the trace
         * bit here.  */
        r7 = syscfg;
-       bitclr (r7, 0);
+       bitclr (r7, SYSCFG_SSSTEP_P);
        syscfg = R7;
        jump _ex_trap_c;
 
@@ -251,7 +251,7 @@ ENTRY(_ex_single_step)
        if !cc jump _bfin_return_from_exception;
 
        r7 = syscfg;
-       bitclr (r7, 0);
+       bitclr (r7, SYSCFG_SSSTEP_P);   /* Turn off single step */
        syscfg = R7;
 
        /* Fall through to _bfin_return_from_exception.  */
@@ -342,9 +342,11 @@ ENTRY(_ex_trap_c)
        r6 = retx;
        [p5 + PDA_RETX] = r6;
 #endif
+       /* Save the state of single stepping */
        r6 = SYSCFG;
        [p5 + PDA_SYSCFG] = r6;
-       BITCLR(r6, 0);
+       /* Clear it while we handle the exception in IRQ5 mode */
+       BITCLR(r6, SYSCFG_SSSTEP_P);
        SYSCFG = r6;
 
        /* Disable all interrupts, but make sure level 5 is enabled so
@@ -367,7 +369,7 @@ ENDPROC(_ex_trap_c)
  * exception. This is a unrecoverable event, so crash.
  * Note: this cannot be ENTRY() as we jump here with "if cc jump" ...
  */
-_double_fault:
+ENTRY(_double_fault)
        /* Turn caches & protection off, to ensure we don't get any more
         * double exceptions
         */
@@ -872,7 +874,7 @@ ENTRY(_ret_from_exception)
        raise 15;               /* raise evt15 to do signal or reschedule */
 4:
        r0 = syscfg;
-       bitclr(r0, 0);
+       bitclr(r0, SYSCFG_SSSTEP_P);            /* Turn off single step */
        syscfg = r0;
 5:
        rts;
index 61840059dfac30feb314fcf373f4ef51dea943cd..349ee3f5466a8dd089902e335e765e1492563509 100644 (file)
@@ -211,6 +211,8 @@ int smp_call_function(void (*func)(void *info), void *info, int wait)
                return 0;
 
        msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+       if (!msg)
+               return -ENOMEM;
        INIT_LIST_HEAD(&msg->list);
        msg->call_struct.func = func;
        msg->call_struct.info = info;
@@ -252,6 +254,8 @@ int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
        cpu_set(cpu, callmap);
 
        msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+       if (!msg)
+               return -ENOMEM;
        INIT_LIST_HEAD(&msg->list);
        msg->call_struct.func = func;
        msg->call_struct.info = info;
@@ -287,6 +291,8 @@ void smp_send_reschedule(int cpu)
                return;
 
        msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+       if (!msg)
+               return;
        memset(msg, 0, sizeof(msg));
        INIT_LIST_HEAD(&msg->list);
        msg->type = BFIN_IPI_RESCHEDULE;
@@ -314,6 +320,8 @@ void smp_send_stop(void)
                return;
 
        msg = kmalloc(sizeof(*msg), GFP_ATOMIC);
+       if (!msg)
+               return;
        memset(msg, 0, sizeof(msg));
        INIT_LIST_HEAD(&msg->list);
        msg->type = BFIN_IPI_CPU_STOP;
@@ -450,7 +458,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
        unsigned int cpu;
 
        for_each_online_cpu(cpu)
-               bogosum += per_cpu(cpu_data, cpu).loops_per_jiffy;
+               bogosum += loops_per_jiffy;
 
        printk(KERN_INFO "SMP: Total of %d processors activated "
               "(%lu.%02lu BogoMIPS).\n",
index a1ba761d0573637ffb79ff4f9d6624d644dad9ce..6da975db112fdabff1125ed0f3ecb38df892caae 100644 (file)
@@ -47,7 +47,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
        __free_page(pte);
 }
 
-#define __pte_free_tlb(tlb,pte)                                \
+#define __pte_free_tlb(tlb,pte,address)                        \
 do {                                                   \
        pgtable_page_dtor(pte);                         \
        tlb_remove_page((tlb), pte);                    \
index bc5b2935ca53a782c66acf4c371e87e46de39077..c3aade36c330400cb7dceb69051a422bb16ed34a 100644 (file)
@@ -50,8 +50,6 @@ struct thread_info {
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #ifndef __ASSEMBLY__
 #define INIT_THREAD_INFO(tsk)                          \
@@ -60,7 +58,7 @@ struct thread_info {
        .exec_domain    = &default_exec_domain,         \
        .flags          = 0,                            \
        .cpu            = 0,                            \
-       .preempt_count  = 1,                            \
+       .preempt_count  = INIT_PREEMPT_COUNT,           \
        .addr_limit     = KERNEL_DS,                    \
        .restart_block = {                              \
                       .fn = do_no_restart_syscall,     \
index a79fbd87021b02cf03663f7a06d680a58a24ceac..2ad962c7e88ebaddcbc11ed7a3a88f3e2e900385 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
index 8a5bd7a9c6f533b452b21de81127c476b1826765..b86e19c9b5b0a137c297f5a1a55e1be49b7d250b 100644 (file)
@@ -7,6 +7,7 @@ config FRV
        default y
        select HAVE_IDE
        select HAVE_ARCH_TRACEHOOK
+       select HAVE_PERF_COUNTERS
 
 config ZONE_DMA
        bool
index 0409d981fd39501820618036f8667957ef7f205d..00a57af79afc6b7d6d45fd1046dd96abdf35184b 100644 (file)
@@ -121,10 +121,72 @@ static inline void atomic_dec(atomic_t *v)
 #define atomic_dec_and_test(v)         (atomic_sub_return(1, (v)) == 0)
 #define atomic_inc_and_test(v)         (atomic_add_return(1, (v)) == 0)
 
+/*
+ * 64-bit atomic ops
+ */
+typedef struct {
+       volatile long long counter;
+} atomic64_t;
+
+#define ATOMIC64_INIT(i)       { (i) }
+
+static inline long long atomic64_read(atomic64_t *v)
+{
+       long long counter;
+
+       asm("ldd%I1 %M1,%0"
+           : "=e"(counter)
+           : "m"(v->counter));
+       return counter;
+}
+
+static inline void atomic64_set(atomic64_t *v, long long i)
+{
+       asm volatile("std%I0 %1,%M0"
+                    : "=m"(v->counter)
+                    : "e"(i));
+}
+
+extern long long atomic64_inc_return(atomic64_t *v);
+extern long long atomic64_dec_return(atomic64_t *v);
+extern long long atomic64_add_return(long long i, atomic64_t *v);
+extern long long atomic64_sub_return(long long i, atomic64_t *v);
+
+static inline long long atomic64_add_negative(long long i, atomic64_t *v)
+{
+       return atomic64_add_return(i, v) < 0;
+}
+
+static inline void atomic64_add(long long i, atomic64_t *v)
+{
+       atomic64_add_return(i, v);
+}
+
+static inline void atomic64_sub(long long i, atomic64_t *v)
+{
+       atomic64_sub_return(i, v);
+}
+
+static inline void atomic64_inc(atomic64_t *v)
+{
+       atomic64_inc_return(v);
+}
+
+static inline void atomic64_dec(atomic64_t *v)
+{
+       atomic64_dec_return(v);
+}
+
+#define atomic64_sub_and_test(i,v)     (atomic64_sub_return((i), (v)) == 0)
+#define atomic64_dec_and_test(v)       (atomic64_dec_return((v)) == 0)
+#define atomic64_inc_and_test(v)       (atomic64_inc_return((v)) == 0)
+
 /*****************************************************************************/
 /*
  * exchange value with memory
  */
+extern uint64_t __xchg_64(uint64_t i, volatile void *v);
+
 #ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
 
 #define xchg(ptr, x)                                                           \
@@ -174,8 +236,10 @@ extern uint32_t __xchg_32(uint32_t i, volatile void *v);
 
 #define tas(ptr) (xchg((ptr), 1))
 
-#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+#define atomic_cmpxchg(v, old, new)    (cmpxchg(&(v)->counter, old, new))
+#define atomic_xchg(v, new)            (xchg(&(v)->counter, new))
+#define atomic64_cmpxchg(v, old, new)  (__cmpxchg_64(old, new, &(v)->counter))
+#define atomic64_xchg(v, new)          (__xchg_64(new, &(v)->counter))
 
 static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 {
diff --git a/arch/frv/include/asm/perf_counter.h b/arch/frv/include/asm/perf_counter.h
new file mode 100644 (file)
index 0000000..ccf726e
--- /dev/null
@@ -0,0 +1,17 @@
+/* FRV performance counter support
+ *
+ * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _ASM_PERF_COUNTER_H
+#define _ASM_PERF_COUNTER_H
+
+#define PERF_COUNTER_INDEX_OFFSET      0
+
+#endif /* _ASM_PERF_COUNTER_H */
index 971e6addb0095a4175d86b68715937e918d2f474..416d19a632f228a30f1133df32fc1629fa359731 100644 (file)
@@ -49,7 +49,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
        __free_page(pte);
 }
 
-#define __pte_free_tlb(tlb,pte)                                \
+#define __pte_free_tlb(tlb,pte,address)                        \
 do {                                                   \
        pgtable_page_dtor(pte);                         \
        tlb_remove_page((tlb),(pte));                   \
@@ -62,7 +62,7 @@ do {                                                  \
  */
 #define pmd_alloc_one(mm, addr)                ({ BUG(); ((pmd_t *) 2); })
 #define pmd_free(mm, x)                        do { } while (0)
-#define __pmd_free_tlb(tlb,x)          do { } while (0)
+#define __pmd_free_tlb(tlb,x,a)                do { } while (0)
 
 #endif /* CONFIG_MMU */
 
index 33233011b1c1147ff46d2aaac3522150d72630c7..22c60692b5513c7c6f66d49947a16e574ba31835 100644 (file)
@@ -225,7 +225,7 @@ static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address)
  */
 #define pud_alloc_one(mm, address)             NULL
 #define pud_free(mm, x)                                do { } while (0)
-#define __pud_free_tlb(tlb, x                do { } while (0)
+#define __pud_free_tlb(tlb, x, address)                do { } while (0)
 
 /*
  * The "pud_xxx()" functions here are trivial for a folded two-level
index 7742ec000cc474d018c6378705395ce9e0b43688..efd22d9077ac3be05e0ce45b4d9cd5fa0f1a83ce 100644 (file)
@@ -208,6 +208,8 @@ extern void free_initmem(void);
  * - if (*ptr == test) then orig = *ptr; *ptr = test;
  * - if (*ptr != test) then orig = *ptr;
  */
+extern uint64_t __cmpxchg_64(uint64_t test, uint64_t new, volatile uint64_t *v);
+
 #ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS
 
 #define cmpxchg(ptr, test, new)                                                        \
index e8a5ed7be0212791674996fd16afeb4f38a6b751..e608e056bb5301582b44b13d2bba9d9ccabfc23a 100644 (file)
@@ -56,8 +56,6 @@ struct thread_info {
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #ifndef __ASSEMBLY__
 
@@ -67,7 +65,7 @@ struct thread_info {
        .exec_domain    = &default_exec_domain, \
        .flags          = 0,                    \
        .cpu            = 0,                    \
-       .preempt_count  = 1,                    \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .addr_limit     = KERNEL_DS,            \
        .restart_block = {                      \
                .fn = do_no_restart_syscall,    \
index 96d78d5d2c41969b0b497846faff20a954f552bb..4a8fb427ce0a274a62aeffb989bbb195549d4ee8 100644 (file)
 #define __NR_inotify_init1     332
 #define __NR_preadv            333
 #define __NR_pwritev           334
+#define __NR_rt_tgsigqueueinfo 335
+#define __NR_perf_counter_open 336
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 335
+#define NR_syscalls 337
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 /* #define __ARCH_WANT_OLD_READDIR */
index 356e0e327a8923f87d366776f06e5b916852bf56..fde1e446b440e7a5027ec597437365350d18fda5 100644 (file)
@@ -1524,5 +1524,7 @@ sys_call_table:
        .long sys_inotify_init1
        .long sys_preadv
        .long sys_pwritev
+       .long sys_rt_tgsigqueueinfo     /* 335 */
+       .long sys_perf_counter_open
 
 syscall_table_size = (. - sys_call_table)
index 0316b3c50efff8814d0ba2b44156ddec40c886c4..a89803b58b9a970c47c0784ca1be398478de6142 100644 (file)
@@ -67,6 +67,10 @@ EXPORT_SYMBOL(atomic_sub_return);
 EXPORT_SYMBOL(__xchg_32);
 EXPORT_SYMBOL(__cmpxchg_32);
 #endif
+EXPORT_SYMBOL(atomic64_add_return);
+EXPORT_SYMBOL(atomic64_sub_return);
+EXPORT_SYMBOL(__xchg_64);
+EXPORT_SYMBOL(__cmpxchg_64);
 
 EXPORT_SYMBOL(__debug_bug_printk);
 EXPORT_SYMBOL(__delay_loops_MHz);
index 08be305c9f446c436a51aa6930d7cb8d2ebb24f6..0a377210c89b3117dec4145769b39998721a3f8a 100644 (file)
@@ -4,5 +4,5 @@
 
 lib-y := \
        __ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o __ucmpdi2.o \
-       checksum.o memcpy.o memset.o atomic-ops.o \
-       outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o
+       checksum.o memcpy.o memset.o atomic-ops.o atomic64-ops.o \
+       outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o perf_counter.o
index ee0ac905fb08ac271139ecd12de58e9fc9b61366..5e9e6ab5dd0e89ef2977743b847aa274da6f0890 100644 (file)
@@ -163,11 +163,10 @@ __cmpxchg_32:
        ld.p            @(gr11,gr0),gr8
        orcr            cc7,cc7,cc3
        subcc           gr8,gr9,gr7,icc0
-       bne             icc0,#0,1f
+       bnelr           icc0,#0
        cst.p           gr10,@(gr11,gr0)        ,cc3,#1
        corcc           gr29,gr29,gr0           ,cc3,#1
        beq             icc3,#0,0b
-1:
        bralr
 
        .size           __cmpxchg_32, .-__cmpxchg_32
diff --git a/arch/frv/lib/atomic64-ops.S b/arch/frv/lib/atomic64-ops.S
new file mode 100644 (file)
index 0000000..b6194ee
--- /dev/null
@@ -0,0 +1,162 @@
+/* kernel atomic64 operations
+ *
+ * For an explanation of how atomic ops work in this arch, see:
+ *   Documentation/frv/atomic-ops.txt
+ *
+ * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/spr-regs.h>
+
+       .text
+       .balign 4
+
+
+###############################################################################
+#
+# long long atomic64_inc_return(atomic64_t *v)
+#
+###############################################################################
+       .globl          atomic64_inc_return
+        .type          atomic64_inc_return,@function
+atomic64_inc_return:
+       or.p            gr8,gr8,gr10
+0:
+       orcc            gr0,gr0,gr0,icc3                /* set ICC3.Z */
+       ckeq            icc3,cc7
+       ldd.p           @(gr10,gr0),gr8                 /* LDD.P/ORCR must be atomic */
+       orcr            cc7,cc7,cc3                     /* set CC3 to true */
+       addicc          gr9,#1,gr9,icc0
+       addxi           gr8,#0,gr8,icc0
+       cstd.p          gr8,@(gr10,gr0)         ,cc3,#1
+       corcc           gr29,gr29,gr0           ,cc3,#1 /* clear ICC3.Z if store happens */
+       beq             icc3,#0,0b
+       bralr
+
+       .size           atomic64_inc_return, .-atomic64_inc_return
+
+###############################################################################
+#
+# long long atomic64_dec_return(atomic64_t *v)
+#
+###############################################################################
+       .globl          atomic64_dec_return
+        .type          atomic64_dec_return,@function
+atomic64_dec_return:
+       or.p            gr8,gr8,gr10
+0:
+       orcc            gr0,gr0,gr0,icc3                /* set ICC3.Z */
+       ckeq            icc3,cc7
+       ldd.p           @(gr10,gr0),gr8                 /* LDD.P/ORCR must be atomic */
+       orcr            cc7,cc7,cc3                     /* set CC3 to true */
+       subicc          gr9,#1,gr9,icc0
+       subxi           gr8,#0,gr8,icc0
+       cstd.p          gr8,@(gr10,gr0)         ,cc3,#1
+       corcc           gr29,gr29,gr0           ,cc3,#1 /* clear ICC3.Z if store happens */
+       beq             icc3,#0,0b
+       bralr
+
+       .size           atomic64_dec_return, .-atomic64_dec_return
+
+###############################################################################
+#
+# long long atomic64_add_return(long long i, atomic64_t *v)
+#
+###############################################################################
+       .globl          atomic64_add_return
+        .type          atomic64_add_return,@function
+atomic64_add_return:
+       or.p            gr8,gr8,gr4
+       or              gr9,gr9,gr5
+0:
+       orcc            gr0,gr0,gr0,icc3                /* set ICC3.Z */
+       ckeq            icc3,cc7
+       ldd.p           @(gr10,gr0),gr8                 /* LDD.P/ORCR must be atomic */
+       orcr            cc7,cc7,cc3                     /* set CC3 to true */
+       addcc           gr9,gr5,gr9,icc0
+       addx            gr8,gr4,gr8,icc0
+       cstd.p          gr8,@(gr10,gr0)         ,cc3,#1
+       corcc           gr29,gr29,gr0           ,cc3,#1 /* clear ICC3.Z if store happens */
+       beq             icc3,#0,0b
+       bralr
+
+       .size           atomic64_add_return, .-atomic64_add_return
+
+###############################################################################
+#
+# long long atomic64_sub_return(long long i, atomic64_t *v)
+#
+###############################################################################
+       .globl          atomic64_sub_return
+        .type          atomic64_sub_return,@function
+atomic64_sub_return:
+       or.p            gr8,gr8,gr4
+       or              gr9,gr9,gr5
+0:
+       orcc            gr0,gr0,gr0,icc3                /* set ICC3.Z */
+       ckeq            icc3,cc7
+       ldd.p           @(gr10,gr0),gr8                 /* LDD.P/ORCR must be atomic */
+       orcr            cc7,cc7,cc3                     /* set CC3 to true */
+       subcc           gr9,gr5,gr9,icc0
+       subx            gr8,gr4,gr8,icc0
+       cstd.p          gr8,@(gr10,gr0)         ,cc3,#1
+       corcc           gr29,gr29,gr0           ,cc3,#1 /* clear ICC3.Z if store happens */
+       beq             icc3,#0,0b
+       bralr
+
+       .size           atomic64_sub_return, .-atomic64_sub_return
+
+###############################################################################
+#
+# uint64_t __xchg_64(uint64_t i, uint64_t *v)
+#
+###############################################################################
+       .globl          __xchg_64
+        .type          __xchg_64,@function
+__xchg_64:
+       or.p            gr8,gr8,gr4
+       or              gr9,gr9,gr5
+0:
+       orcc            gr0,gr0,gr0,icc3                /* set ICC3.Z */
+       ckeq            icc3,cc7
+       ldd.p           @(gr10,gr0),gr8                 /* LDD.P/ORCR must be atomic */
+       orcr            cc7,cc7,cc3                     /* set CC3 to true */
+       cstd.p          gr4,@(gr10,gr0)         ,cc3,#1
+       corcc           gr29,gr29,gr0           ,cc3,#1 /* clear ICC3.Z if store happens */
+       beq             icc3,#0,0b
+       bralr
+
+       .size           __xchg_64, .-__xchg_64
+
+###############################################################################
+#
+# uint64_t __cmpxchg_64(uint64_t test, uint64_t new, uint64_t *v)
+#
+###############################################################################
+       .globl          __cmpxchg_64
+        .type          __cmpxchg_64,@function
+__cmpxchg_64:
+       or.p            gr8,gr8,gr4
+       or              gr9,gr9,gr5
+0:
+       orcc            gr0,gr0,gr0,icc3                /* set ICC3.Z */
+       ckeq            icc3,cc7
+       ldd.p           @(gr12,gr0),gr8                 /* LDD.P/ORCR must be atomic */
+       orcr            cc7,cc7,cc3
+       subcc           gr8,gr4,gr0,icc0
+       subcc.p         gr9,gr5,gr0,icc1
+       bnelr           icc0,#0
+       bnelr           icc1,#0
+       cstd.p          gr10,@(gr12,gr0)        ,cc3,#1
+       corcc           gr29,gr29,gr0           ,cc3,#1 /* clear ICC3.Z if store happens */
+       beq             icc3,#0,0b
+       bralr
+
+       .size           __cmpxchg_64, .-__cmpxchg_64
+
diff --git a/arch/frv/lib/perf_counter.c b/arch/frv/lib/perf_counter.c
new file mode 100644 (file)
index 0000000..2000fee
--- /dev/null
@@ -0,0 +1,19 @@
+/* Performance counter handling
+ *
+ * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <linux/perf_counter.h>
+
+/*
+ * mark the performance counter as pending
+ */
+void set_perf_counter_pending(void)
+{
+}
index 700014d2155fd8d82a4aeadb54c4b3ad682855bb..8bbc8b0ee45db3ad2ddb97f6c6c9be4b5550315f 100644 (file)
@@ -36,7 +36,7 @@ struct thread_info {
        .exec_domain =  &default_exec_domain,   \
        .flags =        0,                      \
        .cpu =          0,                      \
-       .preempt_count = 1,                     \
+       .preempt_count = INIT_PREEMPT_COUNT,    \
        .restart_block  = {                     \
                .fn = do_no_restart_syscall,    \
        },                                      \
index 58a7e46affda28b44daf8199244ab3eca354fa8a..e7cbaa02cd0b432fa99c43d0c8de742b2c11d485 100644 (file)
@@ -41,11 +41,6 @@ $(error Sorry, you need a newer version of the assember, one that is built from
                ftp://ftp.hpl.hp.com/pub/linux-ia64/gas-030124.tar.gz)
 endif
 
-ifeq ($(call cc-version),0304)
-       cflags-$(CONFIG_ITANIUM)        += -mtune=merced
-       cflags-$(CONFIG_MCKINLEY)       += -mtune=mckinley
-endif
-
 KBUILD_CFLAGS += $(cflags-y)
 head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o
 
index e2ca800373351d26b1042394275ebe10f6c8d23e..57a2787bc9fb62e6d5cadc62a2bc394e78cca707 100644 (file)
@@ -286,7 +286,7 @@ __test_and_clear_bit(int nr, volatile void * addr)
 {
        __u32 *p = (__u32 *) addr + (nr >> 5);
        __u32 m = 1 << (nr & 31);
-       int oldbitset = *p & m;
+       int oldbitset = (*p & m) != 0;
 
        *p &= ~m;
        return oldbitset;
index 0c26157cffa55fe0ea1c348fd0a542b11e6c46c3..b6395ad1500a00f7d2a133b3633bed96fd91be2f 100644 (file)
@@ -6,6 +6,8 @@
  *     David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
+#include <linux/types.h>
+
 /* floating point status register: */
 #define FPSR_TRAP_VD   (1 << 0)        /* invalid op trap disabled */
 #define FPSR_TRAP_DD   (1 << 1)        /* denormal trap disabled */
index b9ac1a6fc21694a55e2771e471ab8cc90ab997cf..96a8d927db2851c9c17d8b48f6b47da66f9dd572 100644 (file)
@@ -48,7 +48,7 @@ static inline void pud_free(struct mm_struct *mm, pud_t *pud)
 {
        quicklist_free(0, NULL, pud);
 }
-#define __pud_free_tlb(tlb, pud      pud_free((tlb)->mm, pud)
+#define __pud_free_tlb(tlb, pud, address)      pud_free((tlb)->mm, pud)
 #endif /* CONFIG_PGTABLE_4 */
 
 static inline void
@@ -67,7 +67,7 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
        quicklist_free(0, NULL, pmd);
 }
 
-#define __pmd_free_tlb(tlb, pmd      pmd_free((tlb)->mm, pmd)
+#define __pmd_free_tlb(tlb, pmd, address)      pmd_free((tlb)->mm, pmd)
 
 static inline void
 pmd_populate(struct mm_struct *mm, pmd_t * pmd_entry, pgtable_t pte)
@@ -117,6 +117,6 @@ static inline void check_pgt_cache(void)
        quicklist_trim(0, NULL, 25, 16);
 }
 
-#define __pte_free_tlb(tlb, pte      pte_free((tlb)->mm, pte)
+#define __pte_free_tlb(tlb, pte, address)      pte_free((tlb)->mm, pte)
 
 #endif                         /* _ASM_IA64_PGALLOC_H */
index 0a9cc73d35c78fac88f4733511021849a0b2a248..8840a690d1e7aa346b82fc68672186631c2e0828 100644 (file)
 #include <linux/bitops.h>
 #include <asm/cacheflush.h>
 #include <asm/mmu_context.h>
-#include <asm/processor.h>
 
 /*
  * Next come the mappings that determine how mmap() protection bits
index ae6922626bf49bbecae323b08e58478bcaeb4e07..8ce2e388e37c550573bfc2ca28033a43b7d74d50 100644 (file)
@@ -48,7 +48,7 @@ struct thread_info {
        .flags          = 0,                    \
        .cpu            = 0,                    \
        .addr_limit     = KERNEL_DS,            \
-       .preempt_count  = 0,                    \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .restart_block = {                      \
                .fn = do_no_restart_syscall,    \
        },                                      \
index 20d8a39680c212af2e455327fb5782680af8c772..85d965cb19a0835ace573551d667053fcc8fa260 100644 (file)
@@ -236,22 +236,22 @@ do {                                                      \
        __tlb_remove_tlb_entry(tlb, ptep, addr);        \
 } while (0)
 
-#define pte_free_tlb(tlb, ptep)                                \
+#define pte_free_tlb(tlb, ptep, address)               \
 do {                                                   \
        tlb->need_flush = 1;                            \
-       __pte_free_tlb(tlb, ptep);                      \
+       __pte_free_tlb(tlb, ptep, address);             \
 } while (0)
 
-#define pmd_free_tlb(tlb, ptep)                                \
+#define pmd_free_tlb(tlb, ptep, address)               \
 do {                                                   \
        tlb->need_flush = 1;                            \
-       __pmd_free_tlb(tlb, ptep);                      \
+       __pmd_free_tlb(tlb, ptep, address);             \
 } while (0)
 
-#define pud_free_tlb(tlb, pudp)                                \
+#define pud_free_tlb(tlb, pudp, address)               \
 do {                                                   \
        tlb->need_flush = 1;                            \
-       __pud_free_tlb(tlb, pudp);                      \
+       __pud_free_tlb(tlb, pudp, address);             \
 } while (0)
 
 #endif /* _ASM_IA64_TLB_H */
index e425227a418e9b15a40a0dce0d8f09be3061ec90..88afb54501e48feba6c24d6f25c7f5967b308c89 100644 (file)
@@ -33,6 +33,7 @@
 #ifndef _ASM_IA64_XEN_HYPERVISOR_H
 #define _ASM_IA64_XEN_HYPERVISOR_H
 
+#include <linux/err.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/version.h>     /* to compile feature.c */
 #include <xen/features.h>              /* to comiple xen-netfront.c */
index 086a2aeb0404e6a889d6b10cfe766eca20a568c3..f2c1600da097f00a6c6c388ded1a9e5523dd39d9 100644 (file)
@@ -6,6 +6,16 @@ int iommu_detected __read_mostly;
 struct dma_map_ops *dma_ops;
 EXPORT_SYMBOL(dma_ops);
 
+#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
+
+static int __init dma_init(void)
+{
+       dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+
+       return 0;
+}
+fs_initcall(dma_init);
+
 struct dma_map_ops *dma_get_ops(struct device *dev)
 {
        return dma_ops;
index ebf4e988e78ca7abd8e0397668dfeb5bc1ee47ae..d5764a3d74af2b73176444212e21f7747b35f679 100644 (file)
@@ -65,7 +65,7 @@ static int __init esi_init (void)
        }
 
        if (!esi)
-               return -ENODEV;;
+               return -ENODEV;
 
        systab = __va(esi);
 
index 2d311864e359d93036ae8e4b31d0e39f5ee56c4d..8ebccb589e1c28a5797186633a840bfc80933d1c 100644 (file)
@@ -21,6 +21,7 @@ EXPORT_SYMBOL(csum_ipv6_magic);
 
 #include <asm/page.h>
 EXPORT_SYMBOL(clear_page);
+EXPORT_SYMBOL(copy_page);
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
 #include <linux/bootmem.h>
@@ -60,9 +61,6 @@ EXPORT_SYMBOL(__udivdi3);
 EXPORT_SYMBOL(__moddi3);
 EXPORT_SYMBOL(__umoddi3);
 
-#include <asm/page.h>
-EXPORT_SYMBOL(copy_page);
-
 #if defined(CONFIG_MD_RAID456) || defined(CONFIG_MD_RAID456_MODULE)
 extern void xor_ia64_2(void);
 extern void xor_ia64_3(void);
index c48b03f2b61dd30aaf22da1fcec101d59fd0b426..dab4d393908c6323279ea61e1443f0e31961834f 100644 (file)
@@ -1072,6 +1072,10 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
        }
 
        addr = ioremap(phys_addr, 0);
+       if (addr == NULL) {
+               spin_unlock_irqrestore(&iosapic_lock, flags);
+               return -ENOMEM;
+       }
        ver = iosapic_version(addr);
        if ((err = iosapic_check_gsi_range(gsi_base, ver))) {
                iounmap(addr);
index 05695962fe4405bd8a028b33c8665158af14a2c3..f6b1ff0aea76f95b094c01be87a7b4c98393a3f2 100644 (file)
@@ -69,11 +69,6 @@ iommu_dma_init(void)
 
 int iommu_dma_supported(struct device *dev, u64 mask)
 {
-       struct dma_map_ops *ops = platform_dma_get_ops(dev);
-
-       if (ops->dma_supported)
-               return ops->dma_supported(dev, mask);
-
        /* Copied from i386. Doesn't make much sense, because it will
           only work for pci_alloc_coherent.
           The caller just has to use GFP_DMA in this case. */
index abce2468a40baeefd47bd8d39f5b61e9218b8f9e..f1782705b1f72caaf2cae0ae96ab869b84a8e0f3 100644 (file)
@@ -5603,7 +5603,7 @@ pfm_interrupt_handler(int irq, void *arg)
  * /proc/perfmon interface, for debug only
  */
 
-#define PFM_PROC_SHOW_HEADER   ((void *)nr_cpu_ids+1)
+#define PFM_PROC_SHOW_HEADER   ((void *)(long)nr_cpu_ids+1)
 
 static void *
 pfm_proc_start(struct seq_file *m, loff_t *pos)
index 92c9689b7d9764a80fc72b8a06f2c45b10443387..9daa87fdb0182e63cde61e6c78df1ff6dea41340 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
-#include <linux/smp_lock.h>
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/audit.h>
index 7053c55b7649337c19f5495c205a0d1584f33caa..e6676fca482876db425b281d476ad06ca64dc873 100644 (file)
@@ -192,7 +192,7 @@ struct salinfo_platform_oemdata_parms {
 static void
 salinfo_work_to_do(struct salinfo_data *data)
 {
-       down_trylock(&data->mutex);
+       (void)(down_trylock(&data->mutex) ?: 0);
        up(&data->mutex);
 }
 
index bc80dff1df7ae8a421f78d34ddab8f7ddc8cb034..8f060352e1297acf0d91db5b512b6ac12d022a36 100644 (file)
@@ -372,6 +372,10 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
        retval = kobject_init_and_add(&all_cpu_cache_info[cpu].kobj,
                                      &cache_ktype_percpu_entry, &sys_dev->kobj,
                                      "%s", "cache");
+       if (unlikely(retval < 0)) {
+               cpu_cache_sysfs_exit(cpu);
+               return retval;
+       }
 
        for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++) {
                this_object = LEAF_KOBJECT_PTR(cpu,i);
@@ -385,7 +389,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev)
                        }
                        kobject_put(&all_cpu_cache_info[cpu].kobj);
                        cpu_cache_sysfs_exit(cpu);
-                       break;
+                       return retval;
                }
                kobject_uevent(&(this_object->kobj), KOBJ_ADD);
        }
index a85cb611ecd7c8f4782b54724021026188640b96..f1268b8e6f9e69b7818aed279859268aa02d62f1 100644 (file)
  *
  */
 #undef CONFIG_MODULES
+#include <linux/module.h>
+#undef CONFIG_KALLSYMS
+#undef EXPORT_SYMBOL
+#undef EXPORT_SYMBOL_GPL
+#define EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_GPL(sym)
 #include "../../../lib/vsprintf.c"
 #include "../../../lib/ctype.c"
index 21f63fffc379ad8a7faf227e1867789ec13c502d..9bf55afd08d0603902ae63877499a91488a6d221 100644 (file)
@@ -247,7 +247,8 @@ void emulate_io_inst(struct kvm_vcpu *vcpu, u64 padr, u64 ma)
                vcpu_get_fpreg(vcpu, inst.M9.f2, &v);
                /* Write high word. FIXME: this is a kludge!  */
                v.u.bits[1] &= 0x3ffff;
-               mmio_access(vcpu, padr + 8, &v.u.bits[1], 8, ma, IOREQ_WRITE);
+               mmio_access(vcpu, padr + 8, (u64 *)&v.u.bits[1], 8,
+                           ma, IOREQ_WRITE);
                data = v.u.bits[0];
                size = 3;
        } else if (inst.M10.major == 7 && inst.M10.x6 == 0x3B) {
@@ -265,7 +266,8 @@ void emulate_io_inst(struct kvm_vcpu *vcpu, u64 padr, u64 ma)
 
                /* Write high word.FIXME: this is a kludge!  */
                v.u.bits[1] &= 0x3ffff;
-               mmio_access(vcpu, padr + 8, &v.u.bits[1], 8, ma, IOREQ_WRITE);
+               mmio_access(vcpu, padr + 8, (u64 *)&v.u.bits[1],
+                           8, ma, IOREQ_WRITE);
                data = v.u.bits[0];
                size = 3;
        } else if (inst.M10.major == 7 && inst.M10.x6 == 0x31) {
index a8f84da04b49b8baa8daed4f49bdc2e178e240be..bb862fb224f2968df93206e37589612556988f6b 100644 (file)
@@ -130,7 +130,7 @@ static void collect_interruption(struct kvm_vcpu *vcpu)
        if (vdcr & IA64_DCR_PP) {
                vpsr |= IA64_PSR_PP;
        } else {
-               vpsr &= ~IA64_PSR_PP;;
+               vpsr &= ~IA64_PSR_PP;
        }
 
        vcpu_set_psr(vcpu, vpsr);
@@ -594,11 +594,11 @@ static void set_pal_call_data(struct kvm_vcpu *vcpu)
                p->u.pal_data.gr30 = vcpu_get_gr(vcpu, 30);
                break;
        case PAL_BRAND_INFO:
-               p->u.pal_data.gr29 = gr29;;
+               p->u.pal_data.gr29 = gr29;
                p->u.pal_data.gr30 = kvm_trans_pal_call_args(vcpu, gr30);
                break;
        default:
-               p->u.pal_data.gr29 = gr29;;
+               p->u.pal_data.gr29 = gr29;
                p->u.pal_data.gr30 = vcpu_get_gr(vcpu, 30);
        }
        p->u.pal_data.gr28 = gr28;
index a2c6c15e4761871ffe98f5bba8b52b6b70691056..cc406d064a091a58e3d87441bb41adfea500c4e0 100644 (file)
@@ -406,7 +406,7 @@ void getreg(unsigned long regnum, unsigned long *val,
         * Now look at registers in [0-31] range and init correct UNAT
         */
        addr = (unsigned long)regs;
-       unat = &regs->eml_unat;;
+       unat = &regs->eml_unat;
 
        addr += gr_info[regnum];
 
@@ -461,7 +461,7 @@ void setreg(unsigned long regnum, unsigned long val,
 u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg)
 {
        struct kvm_pt_regs *regs = vcpu_regs(vcpu);
-       u64 val;
+       unsigned long val;
 
        if (!reg)
                return 0;
@@ -469,7 +469,7 @@ u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg)
        return val;
 }
 
-void vcpu_set_gr(struct kvm_vcpu *vcpu, u64 reg, u64 value, int nat)
+void vcpu_set_gr(struct kvm_vcpu *vcpu, unsigned long reg, u64 value, int nat)
 {
        struct kvm_pt_regs *regs = vcpu_regs(vcpu);
        long sof = (regs->cr_ifs) & 0x7f;
@@ -1072,7 +1072,7 @@ void kvm_ttag(struct kvm_vcpu *vcpu, INST64 inst)
        vcpu_set_gr(vcpu, inst.M46.r1, tag, 0);
 }
 
-int vcpu_tpa(struct kvm_vcpu *vcpu, u64 vadr, u64 *padr)
+int vcpu_tpa(struct kvm_vcpu *vcpu, u64 vadr, unsigned long *padr)
 {
        struct thash_data *data;
        union ia64_isr visr, pt_isr;
index 042af92ced8304c03e29ee48112ac1b5fee87e7e..360724d3ae699d38681da70c1b750c6318f87a81 100644 (file)
@@ -686,14 +686,15 @@ static inline int highest_inservice_irq(struct kvm_vcpu *vcpu)
        return highest_bits((int *)&(VMX(vcpu, insvc[0])));
 }
 
-extern void vcpu_get_fpreg(struct kvm_vcpu *vcpu, u64 reg,
+extern void vcpu_get_fpreg(struct kvm_vcpu *vcpu, unsigned long reg,
                                        struct ia64_fpreg *val);
-extern void vcpu_set_fpreg(struct kvm_vcpu *vcpu, u64 reg,
+extern void vcpu_set_fpreg(struct kvm_vcpu *vcpu, unsigned long reg,
                                        struct ia64_fpreg *val);
-extern u64 vcpu_get_gr(struct kvm_vcpu *vcpu, u64 reg);
-extern void vcpu_set_gr(struct kvm_vcpu *vcpu, u64 reg, u64 val, int nat);
-extern u64 vcpu_get_psr(struct kvm_vcpu *vcpu);
-extern void vcpu_set_psr(struct kvm_vcpu *vcpu, u64 val);
+extern u64 vcpu_get_gr(struct kvm_vcpu *vcpu, unsigned long reg);
+extern void vcpu_set_gr(struct kvm_vcpu *vcpu, unsigned long reg,
+                       u64 val, int nat);
+extern unsigned long vcpu_get_psr(struct kvm_vcpu *vcpu);
+extern void vcpu_set_psr(struct kvm_vcpu *vcpu, unsigned long val);
 extern u64 vcpu_thash(struct kvm_vcpu *vcpu, u64 vadr);
 extern void vcpu_bsw0(struct kvm_vcpu *vcpu);
 extern void thash_vhpt_insert(struct kvm_vcpu *v, u64 pte,
index 4290a429bf7c9b48f0cd9ff049d60626e23af689..20b3852f7a6ec50d765fe3911fa0b6e6a0ef4859 100644 (file)
@@ -135,7 +135,7 @@ struct thash_data *__vtr_lookup(struct kvm_vcpu *vcpu, u64 va, int type)
        u64 rid;
 
        rid = vcpu_get_rr(vcpu, va);
-       rid = rid & RR_RID_MASK;;
+       rid = rid & RR_RID_MASK;
        if (type == D_TLB) {
                if (vcpu_quick_region_check(vcpu->arch.dtr_regions, va)) {
                        for (trp = (struct thash_data *)&vcpu->arch.dtrs, i = 0;
@@ -518,7 +518,7 @@ struct thash_data *vtlb_lookup(struct kvm_vcpu *v, u64 va, int is_data)
 
        struct thash_cb *hcb = &v->arch.vtlb;
 
-       cch = __vtr_lookup(v, va, is_data);;
+       cch = __vtr_lookup(v, va, is_data);
        if (cch)
                return cch;
 
index 1f86aeb2c9485bb70054280b103fa8280bbad3dc..620d9dc5220f377c9cd2da899a81795054a27ad0 100644 (file)
@@ -96,20 +96,22 @@ END(ip_fast_csum)
 GLOBAL_ENTRY(csum_ipv6_magic)
        ld4     r20=[in0],4
        ld4     r21=[in1],4
-       dep     r15=in3,in2,32,16
+       zxt4    in2=in2
        ;;
        ld4     r22=[in0],4
        ld4     r23=[in1],4
-       mux1    r15=r15,@rev
+       dep     r15=in3,in2,32,16
        ;;
        ld4     r24=[in0],4
        ld4     r25=[in1],4
-       shr.u   r15=r15,16
+       mux1    r15=r15,@rev
        add     r16=r20,r21
        add     r17=r22,r23
+       zxt4    in4=in4
        ;;
        ld4     r26=[in0],4
        ld4     r27=[in1],4
+       shr.u   r15=r15,16
        add     r18=r24,r25
        add     r8=r16,r17
        ;;
index 729298f4b23438dfbd299d6019d59889448e19a5..7de76dd352fe4e6350ee0a8bf6d366fe05c66f35 100644 (file)
@@ -537,7 +537,7 @@ pcibios_align_resource (void *data, struct resource *res,
 /*
  * PCI BIOS setup, always defaults to SAL interface
  */
-char * __devinit
+char * __init
 pcibios_setup (char *str)
 {
        return str;
index 76645cf6ac5d1ded06cd4ae24eb7399ecf83075d..25831c47c579bcf3f3059c5bd914dc22e17f6c98 100644 (file)
@@ -435,7 +435,8 @@ void sn_generate_path(struct pci_bus *pci_bus, char *address)
        bricktype = MODULE_GET_BTYPE(moduleid);
        if ((bricktype == L1_BRICKTYPE_191010) ||
            (bricktype == L1_BRICKTYPE_1932))
-                       sprintf(address, "%s^%d", address, geo_slot(geoid));
+                       sprintf(address + strlen(address), "^%d",
+                                               geo_slot(geoid));
 }
 
 void __devinit
index f11a2b909cdbf8ab3bc1a11195b0160173c2a58b..0fc7361989797d9a8c6fb6cc2a823367f75236e0 100644 (file)
@@ -58,7 +58,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
        __free_page(pte);
 }
 
-#define __pte_free_tlb(tlb, pte)       pte_free((tlb)->mm, (pte))
+#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, (pte))
 
 /*
  * allocating and freeing a pmd is trivial: the 1-entry pmd is
@@ -68,7 +68,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
 
 #define pmd_alloc_one(mm, addr)                ({ BUG(); ((pmd_t *)2); })
 #define pmd_free(mm, x)                        do { } while (0)
-#define __pmd_free_tlb(tlb, x)         do { } while (0)
+#define __pmd_free_tlb(tlb, x, addr)   do { } while (0)
 #define pgd_populate(mm, pmd, pte)     BUG()
 
 #define check_pgt_cache()      do { } while (0)
index 8589d462df27e366863974619b5cf293e0b9213c..07bb5bd00e2a0660dc3be6c0c0c4514da8ade81b 100644 (file)
@@ -57,8 +57,6 @@ struct thread_info {
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #ifndef __ASSEMBLY__
 
@@ -68,7 +66,7 @@ struct thread_info {
        .exec_domain    = &default_exec_domain, \
        .flags          = 0,                    \
        .cpu            = 0,                    \
-       .preempt_count  = 1,                    \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .addr_limit     = KERNEL_DS,            \
        .restart_block = {                      \
                .fn = do_no_restart_syscall,    \
index bf0abe9e1f73e9bc9f30b1162df1577f75f51907..98b8feb12ed899e6dba32d0532b981057d4f5a6e 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/mm.h>
 #include <linux/err.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index 6e562751ad51b5653181165d8b4ffc54f6cb1b8b..6c74751c7b821bbc5eedfeeba20a2bc9673149bb 100644 (file)
@@ -574,10 +574,11 @@ static int a2000_hwclk(int op, struct rtc_time *t)
 
        tod_2000.cntrl1 = TOD2000_CNTRL1_HOLD;
 
-       while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--) {
+       while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt) {
                tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
                udelay(70);
                tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
+               --cnt;
        }
 
        if (!cnt)
@@ -649,10 +650,11 @@ static int amiga_set_clock_mmss(unsigned long nowtime)
 
                tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
 
-               while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--) {
+               while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt) {
                        tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
                        udelay(70);
                        tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
+                       --cnt;
                }
 
                if (!cnt)
index d08bf6261df88889f0e39091f8356580920208bb..2f02f264e6944dd7fd11d8d4ffe0e10244fe1f60 100644 (file)
@@ -36,12 +36,10 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addres
                return NULL;
 
        pte = kmap(page);
-       if (pte) {
-               __flush_page_to_ram(pte);
-               flush_tlb_kernel_page(pte);
-               nocache_page(pte);
-       }
-       kunmap(pte);
+       __flush_page_to_ram(pte);
+       flush_tlb_kernel_page(pte);
+       nocache_page(pte);
+       kunmap(page);
        pgtable_page_ctor(page);
        return page;
 }
@@ -54,7 +52,8 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t page)
        __free_page(page);
 }
 
-static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page)
+static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page,
+                                 unsigned long address)
 {
        pgtable_page_dtor(page);
        cache_page(kmap(page));
@@ -73,7 +72,8 @@ static inline int pmd_free(struct mm_struct *mm, pmd_t *pmd)
        return free_pointer_table(pmd);
 }
 
-static inline int __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+static inline int __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
+                                unsigned long address)
 {
        return free_pointer_table(pmd);
 }
index 0b604f0f192d5916b74aee3026c70a7351834671..fe60e1abaee8900523cb827ea8d9ca1a410dcde8 100644 (file)
@@ -135,8 +135,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
 #endif
 
 #ifndef __ASSEMBLY__
-#include <asm-generic/pgtable.h>
-
 /*
  * Macro to mark a page protection value as "uncacheable".
  */
@@ -154,6 +152,7 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
            ? (__pgprot((pgprot_val(prot) & _CACHEMASK040) | _PAGE_NOCACHE_S))  \
            : (prot)))
 
+#include <asm-generic/pgtable.h>
 #endif /* !__ASSEMBLY__ */
 
 /*
index d4c83f14381652402d35f4b3cb5fb5967f97a6de..48d80d5a666f80b64d5b62e318197b1752e29733 100644 (file)
@@ -32,7 +32,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t page)
         __free_page(page);
 }
 
-#define __pte_free_tlb(tlb,pte)                                \
+#define __pte_free_tlb(tlb,pte,addr)                   \
 do {                                                   \
        pgtable_page_dtor(pte);                         \
        tlb_remove_page((tlb), pte);                    \
@@ -80,7 +80,7 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, pgtable_t page
  * inside the pgd, so has no extra memory associated with it.
  */
 #define pmd_free(mm, x)                        do { } while (0)
-#define __pmd_free_tlb(tlb, x)         do { } while (0)
+#define __pmd_free_tlb(tlb, x, addr)   do { } while (0)
 
 static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 {
index af0fda46e94bc969978a9572221ac2843f23bae2..6ea5c33b3c564ed2d1558840f9642241fcc2e2e8 100644 (file)
@@ -19,6 +19,7 @@ struct thread_info {
 {                                              \
        .task           = &tsk,                 \
        .exec_domain    = &default_exec_domain, \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .restart_block = {                      \
                .fn = do_no_restart_syscall,    \
        },                                      \
index 82529f424ea3d567d0c1a9a2991b9591f7dacd85..c2bde5e24b0b9063d3c984e55dc168a6d9329158 100644 (file)
@@ -49,6 +49,7 @@ struct thread_info {
        .exec_domain    = &default_exec_domain, \
        .flags          = 0,                    \
        .cpu            = 0,                    \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .restart_block  = {                     \
                .fn = do_no_restart_syscall,    \
        },                                      \
index aa29a8640f74819eba8ab1a07ef0ecec1826ee95..946d8691f2b007af1d35ace8b9fbd4864ce7b5ba 100644 (file)
 #define __NR_inotify_init1     328
 #define __NR_preadv            329
 #define __NR_pwritev           330
+#define __NR_rt_tgsigqueueinfo 331
+#define __NR_perf_counter_open 332
 
 #ifdef __KERNEL__
 
-#define NR_syscalls            331
+#define NR_syscalls            333
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index 8744f60c07a99618394bd31255b7ce5cf2e12eca..c3735cd6207e585e38a788ae84190db375ccc798 100644 (file)
@@ -755,4 +755,6 @@ sys_call_table:
        .long sys_inotify_init1
        .long sys_preadv
        .long sys_pwritev               /* 330 */
+       .long sys_rt_tgsigqueueinfo
+       .long sys_perf_counter_open
 
index 1e96c6eb631258f75946f9ab84f4ab26f1ab3890..8f8f4abab2ff16419afc8abb35fffdf4c4f63276 100644 (file)
@@ -290,7 +290,7 @@ void dump(struct pt_regs *fp)
        unsigned char   *tp;
        int             i;
 
-       printk(KERN_EMERG "\n" KERN_EMERG "CURRENT PROCESS:\n" KERN_EMERG "\n");
+       printk(KERN_EMERG "\nCURRENT PROCESS:\n\n");
        printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid);
 
        if (current->mm) {
@@ -301,8 +301,7 @@ void dump(struct pt_regs *fp)
                        (int) current->mm->end_data,
                        (int) current->mm->end_data,
                        (int) current->mm->brk);
-               printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n"
-                       KERN_EMERG "\n",
+               printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n\n",
                        (int) current->mm->start_stack,
                        (int)(((unsigned long) current) + THREAD_SIZE));
        }
@@ -313,35 +312,35 @@ void dump(struct pt_regs *fp)
                fp->d0, fp->d1, fp->d2, fp->d3);
        printk(KERN_EMERG "d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
                fp->d4, fp->d5, fp->a0, fp->a1);
-       printk(KERN_EMERG "\n" KERN_EMERG "USP: %08x   TRAPFRAME: %08x\n",
+       printk(KERN_EMERG "\nUSP: %08x   TRAPFRAME: %08x\n",
                (unsigned int) rdusp(), (unsigned int) fp);
 
-       printk(KERN_EMERG "\n" KERN_EMERG "CODE:");
+       printk(KERN_EMERG "\nCODE:");
        tp = ((unsigned char *) fp->pc) - 0x20;
        for (sp = (unsigned long *) tp, i = 0; (i < 0x40);  i += 4) {
                if ((i % 0x10) == 0)
-                       printk("\n" KERN_EMERG "%08x: ", (int) (tp + i));
+                       printk(KERN_EMERG "%08x: ", (int) (tp + i));
                printk("%08x ", (int) *sp++);
        }
-       printk("\n" KERN_EMERG "\n");
+       printk(KERN_EMERG "\n");
 
        printk(KERN_EMERG "KERNEL STACK:");
        tp = ((unsigned char *) fp) - 0x40;
        for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) {
                if ((i % 0x10) == 0)
-                       printk("\n" KERN_EMERG "%08x: ", (int) (tp + i));
+                       printk(KERN_EMERG "%08x: ", (int) (tp + i));
                printk("%08x ", (int) *sp++);
        }
-       printk("\n" KERN_EMERG "\n");
+       printk(KERN_EMERG "\n");
 
        printk(KERN_EMERG "USER STACK:");
        tp = (unsigned char *) (rdusp() - 0x10);
        for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) {
                if ((i % 0x10) == 0)
-                       printk("\n" KERN_EMERG "%08x: ", (int) (tp + i));
+                       printk(KERN_EMERG "%08x: ", (int) (tp + i));
                printk("%08x ", (int) *sp++);
        }
-       printk("\n" KERN_EMERG "\n");
+       printk(KERN_EMERG "\n");
 }
 
 /*
index c0b8782832fd11f578963c54159d9e06f7f4c3e4..0ae123e089853db14487cc323a6811c6e2c2f703 100644 (file)
@@ -349,6 +349,8 @@ ENTRY(sys_call_table)
        .long sys_inotify_init1
        .long sys_preadv
        .long sys_pwritev               /* 330 */
+       .long sys_rt_tgsigqueueinfo
+       .long sys_perf_counter_open
 
        .rept NR_syscalls-(.-sys_call_table)/4
                .long sys_ni_syscall
index 51d325343ab58baaa3f5abe3396dbea067ae41c2..3739c8f657d75f12d94c92e2e1665a6f927c2e7d 100644 (file)
@@ -111,7 +111,7 @@ static void print_this_address(unsigned long addr, int i)
        if (i % 5)
                printk(KERN_CONT " [%08lx] ", addr);
        else
-               printk(KERN_CONT "\n" KERN_EMERG " [%08lx] ", addr);
+               printk(KERN_EMERG " [%08lx] ", addr);
        i++;
 #endif
 }
@@ -137,8 +137,8 @@ static void __show_stack(struct task_struct *task, unsigned long *stack)
                if (stack + 1 + i > endstack)
                        break;
                if (i % 8 == 0)
-                       printk("\n" KERN_EMERG "       ");
-               printk(" %08lx", *(stack + i));
+                       printk(KERN_EMERG "       ");
+               printk(KERN_CONT " %08lx", *(stack + i));
        }
        printk("\n");
        i = 0;
index b50b845fdd506d6f6e914038794a854769301bfc..2db722d80d4d19133e8508c046c029a5c2c06cc1 100644 (file)
@@ -53,6 +53,9 @@ config GENERIC_HARDIRQS_NO__DO_IRQ
 config GENERIC_GPIO
        def_bool y
 
+config GENERIC_CSUM
+       def_bool y
+
 config PCI
        def_bool n
 
index d0bcf80a113659d2b3da42e9cd0e7c4c58f701a9..8439598d4655bb8192c79f696b60ac2d1ea05a2d 100644 (file)
@@ -6,14 +6,16 @@ endif
 
 # What CPU vesion are we building for, and crack it open
 # as major.minor.rev
-CPU_VER=$(subst ",,$(CONFIG_XILINX_MICROBLAZE0_HW_VER) )
-CPU_MAJOR=$(shell echo $(CPU_VER) | cut -d '.' -f 1)
-CPU_MINOR=$(shell echo $(CPU_VER) | cut -d '.' -f 2)
-CPU_REV=$(shell echo $(CPU_VER) | cut -d '.' -f 3)
+CPU_VER   := $(shell echo $(CONFIG_XILINX_MICROBLAZE0_HW_VER))
+CPU_MAJOR := $(shell echo $(CPU_VER) | cut -d '.' -f 1)
+CPU_MINOR := $(shell echo $(CPU_VER) | cut -d '.' -f 2)
+CPU_REV   := $(shell echo $(CPU_VER) | cut -d '.' -f 3)
 
 export CPU_VER CPU_MAJOR CPU_MINOR CPU_REV
 
 # Use cpu-related CONFIG_ vars to set compile options.
+# The various CONFIG_XILINX cpu features options are integers 0/1/2...
+# rather than bools y/n
 
 # Work out HW multipler support.  This is icky.
 # 1. Spartan2 has no HW multiplers.
@@ -34,30 +36,29 @@ CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR) += -mxl-pattern-compare
 
 CPUFLAGS-1 += $(call cc-option,-mcpu=v$(CPU_VER))
 
-# The various CONFIG_XILINX cpu features options are integers 0/1/2...
-# rather than bools y/n
-
 # r31 holds current when in kernel mode
-CFLAGS_KERNEL += -ffixed-r31 $(CPUFLAGS-1) $(CPUFLAGS-2)
+KBUILD_KERNEL += -ffixed-r31 $(CPUFLAGS-1) $(CPUFLAGS-2)
 
 LDFLAGS                :=
 LDFLAGS_vmlinux        :=
-LDFLAGS_BLOB := --format binary --oformat elf32-microblaze
 
-LIBGCC := $(shell $(CC) $(CFLAGS_KERNEL) -print-libgcc-file-name)
+LIBGCC := $(shell $(CC) $(KBUILD_KERNEL) -print-libgcc-file-name)
 
-head-y         := arch/microblaze/kernel/head.o
-libs-y         += arch/microblaze/lib/ $(LIBGCC)
-core-y         += arch/microblaze/kernel/ arch/microblaze/mm/ \
-                  arch/microblaze/platform/
+head-y := arch/microblaze/kernel/head.o
+libs-y += arch/microblaze/lib/
+libs-y += $(LIBGCC)
+core-y += arch/microblaze/kernel/
+core-y += arch/microblaze/mm/
+core-y += arch/microblaze/platform/
 
-boot := arch/$(ARCH)/boot
+boot := arch/microblaze/boot
 
 # defines filename extension depending memory management type
 ifeq ($(CONFIG_MMU),)
-MMUEXT         := -nommu
+MMU := -nommu
 endif
-export MMUEXT
+
+export MMU
 
 all: linux.bin
 
index bd0b85ec38f5f822ca24f0d4a26afbdc8b8a30a9..09c32962b66f76f4fa24fd9eb76be75a56428b47 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc6
-# Fri May 22 10:02:33 2009
+# Linux kernel version: 2.6.31-rc6
+# Tue Aug 18 11:00:02 2009
 #
 CONFIG_MICROBLAZE=y
 # CONFIG_SWAP is not set
@@ -18,7 +18,11 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_CSUM=y
+# CONFIG_PCI is not set
+CONFIG_NO_DMA=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -59,8 +63,8 @@ CONFIG_INITRAMFS_ROOT_GID=0
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
-CONFIG_INITRAMFS_COMPRESSION_NONE=y
-# CONFIG_INITRAMFS_COMPRESSION_GZIP is not set
+# CONFIG_INITRAMFS_COMPRESSION_NONE is not set
+CONFIG_INITRAMFS_COMPRESSION_GZIP=y
 # CONFIG_INITRAMFS_COMPRESSION_BZIP2 is not set
 # CONFIG_INITRAMFS_COMPRESSION_LZMA is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -71,7 +75,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -84,13 +87,22 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 # CONFIG_SHMEM is not set
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -102,7 +114,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -194,9 +206,9 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 
 #
 # Exectuable file formats
@@ -262,6 +274,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -325,7 +338,6 @@ CONFIG_MISC_DEVICES=y
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -344,7 +356,7 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
-# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_NETDEV_10000=y
 
@@ -410,6 +422,11 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -418,12 +435,6 @@ CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
-CONFIG_SSB_POSSIBLE=y
-
-#
-# Sonics Silicon Backplane
-#
-# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -433,22 +444,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -469,9 +465,12 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_RTC_CLASS is not set
-# CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -485,12 +484,15 @@ CONFIG_EXT2_FS=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
@@ -678,6 +680,7 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_SYSCTL_SYSCALL_CHECK is not set
 # CONFIG_PAGE_POISONING is not set
 # CONFIG_SAMPLES is not set
+# CONFIG_KMEMCHECK is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_HEART_BEAT=y
 CONFIG_DEBUG_BOOTMEM=y
@@ -793,6 +796,5 @@ CONFIG_ZLIB_INFLATE=y
 CONFIG_DECOMPRESS_GZIP=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
-CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
index 4ef6af0a8f3192e2e6a869690f68ca7f0afcf4c0..8b638615a972ceff7e7b2883f8ada7407a8cf89f 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc5
-# Mon May 11 09:01:02 2009
+# Linux kernel version: 2.6.31-rc6
+# Tue Aug 18 10:35:30 2009
 #
 CONFIG_MICROBLAZE=y
 # CONFIG_SWAP is not set
@@ -17,9 +17,12 @@ CONFIG_GENERIC_TIME=y
 # CONFIG_GENERIC_TIME_VSYSCALL is not set
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_CSUM=y
 # CONFIG_PCI is not set
-# CONFIG_NO_DMA is not set
+CONFIG_NO_DMA=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -64,7 +67,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -76,13 +78,23 @@ CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
 # CONFIG_MARKERS is not set
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -95,7 +107,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -156,8 +168,16 @@ CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttyUL0,115200"
 # CONFIG_CMDLINE_FORCE is not set
 CONFIG_OF=y
-CONFIG_OF_DEVICE=y
 CONFIG_PROC_DEVICETREE=y
+
+#
+# Advanced setup
+#
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_KERNEL_START=0x90000000
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -169,7 +189,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_NOMMU_INITIAL_TRIM_EXCESS=1
 
 #
@@ -237,6 +257,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -254,7 +275,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -353,6 +378,7 @@ CONFIG_MTD_UCLINUX=y
 # UBI - Unsorted block images
 #
 # CONFIG_MTD_UBI is not set
+CONFIG_OF_DEVICE=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
@@ -364,6 +390,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_XIP is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
+# CONFIG_XILINX_SYSACE is not set
 CONFIG_MISC_DEVICES=y
 # CONFIG_ENCLOSURE_SERVICES is not set
 # CONFIG_C2PORT is not set
@@ -383,7 +410,6 @@ CONFIG_MISC_DEVICES=y
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -402,7 +428,7 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
-# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_NETDEV_10000=y
 
@@ -463,23 +489,25 @@ CONFIG_HW_RANDOM=y
 # CONFIG_HW_RANDOM_TIMERIOMEM is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
+# CONFIG_XILINX_HWICAP is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
 # CONFIG_THERMAL_HWMON is not set
 # CONFIG_WATCHDOG is not set
-CONFIG_SSB_POSSIBLE=y
-
-#
-# Sonics Silicon Backplane
-#
-# CONFIG_SSB is not set
 
 #
 # Multifunction device drivers
@@ -489,22 +517,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -520,9 +533,10 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
 # CONFIG_DISPLAY_SUPPORT is not set
 # CONFIG_SOUND is not set
 CONFIG_USB_SUPPORT=y
-# CONFIG_USB_ARCH_HAS_HCD is not set
+CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 # CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
 # CONFIG_USB_OTG_WHITELIST is not set
 # CONFIG_USB_OTG_BLACKLIST_HUB is not set
 
@@ -543,9 +557,12 @@ CONFIG_USB_SUPPORT=y
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_RTC_CLASS is not set
-# CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -558,12 +575,15 @@ CONFIG_EXT2_FS=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
@@ -813,6 +833,5 @@ CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_ZLIB_INFLATE=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
-CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
index 0de612ad7cb2e5b2ca2ef8f98b4616768ab8d6c2..6d2e1d418be74f7dbc3797e82a497b8bcab93bc8 100644 (file)
@@ -1,95 +1,7 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
 #ifndef _ASM_MICROBLAZE_ATOMIC_H
 #define _ASM_MICROBLAZE_ATOMIC_H
 
-#include <linux/types.h>
-#include <linux/compiler.h> /* likely */
-#include <asm/system.h> /* local_irq_XXX and friends */
-
-#define ATOMIC_INIT(i)         { (i) }
-#define atomic_read(v)         ((v)->counter)
-#define atomic_set(v, i)       (((v)->counter) = (i))
-
-#define atomic_inc(v)          (atomic_add_return(1, (v)))
-#define atomic_dec(v)          (atomic_sub_return(1, (v)))
-
-#define atomic_add(i, v)       (atomic_add_return(i, (v)))
-#define atomic_sub(i, v)       (atomic_sub_return(i, (v)))
-
-#define atomic_inc_return(v)   (atomic_add_return(1, (v)))
-#define atomic_dec_return(v)   (atomic_sub_return(1, (v)))
-
-#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
-#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
-
-#define atomic_inc_not_zero(v) (atomic_add_unless((v), 1, 0))
-
-#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0)
-
-static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
-{
-       int ret;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       ret = v->counter;
-       if (likely(ret == old))
-               v->counter = new;
-       local_irq_restore(flags);
-
-       return ret;
-}
-
-static inline int atomic_add_unless(atomic_t *v, int a, int u)
-{
-       int c, old;
-
-       c = atomic_read(v);
-       while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)
-               c = old;
-       return c != u;
-}
-
-static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
-{
-       unsigned long flags;
-
-       local_irq_save(flags);
-       *addr &= ~mask;
-       local_irq_restore(flags);
-}
-
-/**
- * atomic_add_return - add and return
- * @i: integer value to add
- * @v: pointer of type atomic_t
- *
- * Atomically adds @i to @v and returns @i + @v
- */
-static inline int atomic_add_return(int i, atomic_t *v)
-{
-       unsigned long flags;
-       int val;
-
-       local_irq_save(flags);
-       val = v->counter;
-       v->counter = val += i;
-       local_irq_restore(flags);
-
-       return val;
-}
-
-static inline int atomic_sub_return(int i, atomic_t *v)
-{
-       return atomic_add_return(-i, v);
-}
+#include <asm-generic/atomic.h>
 
 /*
  * Atomically test *v and decrement if it is greater than 0.
@@ -109,15 +21,4 @@ static inline int atomic_dec_if_positive(atomic_t *v)
        return res;
 }
 
-#define atomic_add_negative(a, v)      (atomic_add_return((a), (v)) < 0)
-#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
-
-/* Atomic operations are already serializing */
-#define smp_mb__before_atomic_dec()    barrier()
-#define smp_mb__after_atomic_dec()     barrier()
-#define smp_mb__before_atomic_inc()    barrier()
-#define smp_mb__after_atomic_inc()     barrier()
-
-#include <asm-generic/atomic-long.h>
-
 #endif /* _ASM_MICROBLAZE_ATOMIC_H */
index d6df1fd4e1e87522f22b494f465bdca17c0a3e5c..a72468f15c8b1cc8c696a4949e9365d0c975923e 100644 (file)
@@ -1,27 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_BITOPS_H
-#define _ASM_MICROBLAZE_BITOPS_H
-
-/*
- * Copyright 1992, Linus Torvalds.
- */
-
-#include <asm/byteorder.h> /* swab32 */
-#include <asm/system.h> /* save_flags */
-
-/*
- * clear_bit() doesn't provide any barrier for the compiler.
- */
-#define smp_mb__before_clear_bit()     barrier()
-#define smp_mb__after_clear_bit()      barrier()
 #include <asm-generic/bitops.h>
-#include <asm-generic/bitops/__fls.h>
-
-#endif /* _ASM_MICROBLAZE_BITOPS_H */
index 8eb2cdde11d7c28f417cd5f38420e51f33a36056..b12fd89e42e913ef67f0c05d95b98a21c1470c70 100644 (file)
@@ -1,15 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_BUG_H
-#define _ASM_MICROBLAZE_BUG_H
-
-#include <linux/kernel.h>
 #include <asm-generic/bug.h>
-
-#endif /* _ASM_MICROBLAZE_BUG_H */
index f2c6593653fb0217d0387523a0471ee2c28e3166..61791e1ad9f55cba48fafdf065e6fd05d9e95600 100644 (file)
@@ -1,17 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_BUGS_H
-#define _ASM_MICROBLAZE_BUGS_H
-
-static inline void check_bugs(void)
-{
-       /* nothing to do */
-}
-
-#endif /* _ASM_MICROBLAZE_BUGS_H */
+#include <asm-generic/bugs.h>
index 97ea46b5cf80a2a1071b5b89dc9a85cb2e8e3f28..128bf03b54b7e9435abe99f8af19ef4eae91b611 100644 (file)
 #ifndef _ASM_MICROBLAZE_CHECKSUM_H
 #define _ASM_MICROBLAZE_CHECKSUM_H
 
-#include <linux/in6.h>
-
 /*
  * computes the checksum of the TCP/UDP pseudo-header
  * returns a 16-bit checksum, already complemented
  */
+#define csum_tcpudp_nofold     csum_tcpudp_nofold
 static inline __wsum
 csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
                   unsigned short proto, __wsum sum)
@@ -30,71 +29,6 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
        return sum;
 }
 
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-extern __wsum csum_partial(const void *buff, int len, __wsum sum);
-
-/*
- * the same as csum_partial, but copies from src while it
- * checksums
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-extern __wsum csum_partial_copy(const void *src, void *dst, int len,
-                                                               __wsum sum);
-
-/*
- * the same as csum_partial_copy, but copies from user space.
- *
- * here even more important to align src and dst on a 32-bit (or even
- * better 64-bit) boundary
- */
-extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,
-                                       int len, __wsum sum, int *csum_err);
-
-#define csum_partial_copy_nocheck(src, dst, len, sum)  \
-       csum_partial_copy((src), (dst), (len), (sum))
-
-/*
- *     This is a version of ip_compute_csum() optimized for IP headers,
- *     which always checksum on 4 octet boundaries.
- *
- */
-extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);
-
-/*
- *     Fold a partial checksum
- */
-static inline __sum16 csum_fold(__wsum csum)
-{
-       u32 sum = (__force u32)csum;
-       sum = (sum & 0xffff) + (sum >> 16);
-       sum = (sum & 0xffff) + (sum >> 16);
-       return (__force __sum16)~sum;
-}
-
-static inline __sum16
-csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len,
-                 unsigned short proto, __wsum sum)
-{
-       return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-extern __sum16 ip_compute_csum(const void *buff, int len);
+#include <asm-generic/checksum.h>
 
 #endif /* _ASM_MICROBLAZE_CHECKSUM_H */
diff --git a/arch/microblaze/include/asm/fb.h b/arch/microblaze/include/asm/fb.h
new file mode 100644 (file)
index 0000000..3a4988e
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/fb.h>
index 0f2d6b013e11ead33ee6e1ca594c9a5214eccce9..cd1ac9aad56c443598725e0e19d07fa3c7f038db 100644 (file)
@@ -9,21 +9,9 @@
 #ifndef _ASM_MICROBLAZE_HARDIRQ_H
 #define _ASM_MICROBLAZE_HARDIRQ_H
 
-#include <linux/cache.h>
-#include <linux/irq.h>
-#include <asm/irq.h>
-#include <asm/current.h>
-#include <linux/ptrace.h>
-
 /* should be defined in each interrupt controller driver */
 extern unsigned int get_irq(struct pt_regs *regs);
 
-typedef struct {
-       unsigned int __softirq_pending;
-} ____cacheline_aligned irq_cpustat_t;
-
-void ack_bad_irq(unsigned int irq);
-
-#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+#include <asm-generic/hardirq.h>
 
 #endif /* _ASM_MICROBLAZE_HARDIRQ_H */
index 5c173424d0744bdd6cfdda945e57985adff9060c..7c3ec13b44d860c8180a3bc15460e1dbeec7886c 100644 (file)
@@ -14,7 +14,6 @@
 #include <asm/byteorder.h>
 #include <asm/page.h>
 #include <linux/types.h>
-#include <asm/byteorder.h>
 #include <linux/mm.h>          /* Get struct page {...} */
 
 
index 03582b2492047cdd98dcdd897ef45e899fa026fc..ec34c760665eaee4e4ee74311bdf6967bbad5b68 100644 (file)
@@ -1,91 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_IOCTLS_H
-#define _ASM_MICROBLAZE_IOCTLS_H
-
-#include <linux/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS         0x5401
-#define TCSETS         0x5402
-#define TCSETSW                0x5403
-#define TCSETSF                0x5404
-#define TCGETA         0x5405
-#define TCSETA         0x5406
-#define TCSETAW                0x5407
-#define TCSETAF                0x5408
-#define TCSBRK         0x5409
-#define TCXONC         0x540A
-#define TCFLSH         0x540B
-#define TIOCEXCL       0x540C
-#define TIOCNXCL       0x540D
-#define TIOCSCTTY      0x540E
-#define TIOCGPGRP      0x540F
-#define TIOCSPGRP      0x5410
-#define TIOCOUTQ       0x5411
-#define TIOCSTI                0x5412
-#define TIOCGWINSZ     0x5413
-#define TIOCSWINSZ     0x5414
-#define TIOCMGET       0x5415
-#define TIOCMBIS       0x5416
-#define TIOCMBIC       0x5417
-#define TIOCMSET       0x5418
-#define TIOCGSOFTCAR   0x5419
-#define TIOCSSOFTCAR   0x541A
-#define FIONREAD       0x541B
-#define TIOCINQ                FIONREAD
-#define TIOCLINUX      0x541C
-#define TIOCCONS       0x541D
-#define TIOCGSERIAL    0x541E
-#define TIOCSSERIAL    0x541F
-#define TIOCPKT                0x5420
-#define FIONBIO                0x5421
-#define TIOCNOTTY      0x5422
-#define TIOCSETD       0x5423
-#define TIOCGETD       0x5424
-#define TCSBRKP                0x5425 /* Needed for POSIX tcsendbreak() */
-#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */
-#define TIOCSBRK       0x5427 /* BSD compatibility */
-#define TIOCCBRK       0x5428 /* BSD compatibility */
-#define TIOCGSID       0x5429 /* Return the session ID of FD */
-/* Get Pty Number (of pty-mux device) */
-#define TIOCGPTN       _IOR('T', 0x30, unsigned int)
-#define TIOCSPTLCK     _IOW('T', 0x31, int) /* Lock/unlock Pty */
-
-#define FIONCLEX       0x5450 /* these numbers need to be adjusted. */
-#define FIOCLEX                0x5451
-#define FIOASYNC       0x5452
-#define TIOCSERCONFIG  0x5453
-#define TIOCSERGWILD   0x5454
-#define TIOCSERSWILD   0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR  0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT     0x545C /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x545D /* read serial port inline interrupt counts */
-
-#define        FIOQSIZE        0x545E
-
-/* Used for packet mode */
-#define TIOCPKT_DATA           0
-#define TIOCPKT_FLUSHREAD      1
-#define TIOCPKT_FLUSHWRITE     2
-#define TIOCPKT_STOP           4
-#define TIOCPKT_START          8
-#define TIOCPKT_NOSTOP         16
-#define TIOCPKT_DOSTOP         32
-
-#define TIOCSER_TEMT   0x01 /* Transmitter physically empty */
-
-#endif /* _ASM_MICROBLAZE_IOCTLS_H */
+#include <asm-generic/ioctls.h>
index b056fa4206544a6d148dcf3eb8bb7fb29ed9edcf..84c7e51cb6d0befd2b3c013c8bbbbaad6ae02297 100644 (file)
@@ -1,36 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_IPCBUF_H
-#define _ASM_MICROBLAZE_IPCBUF_H
-
-/*
- * The user_ipc_perm structure for microblaze architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 32-bit mode_t and seq
- * - 2 miscellaneous 32-bit values
- */
-
-struct ipc64_perm {
-       __kernel_key_t          key;
-       __kernel_uid32_t        uid;
-       __kernel_gid32_t        gid;
-       __kernel_uid32_t        cuid;
-       __kernel_gid32_t        cgid;
-       __kernel_mode_t         mode;
-       unsigned short          __pad1;
-       unsigned short          seq;
-       unsigned short          __pad2;
-       unsigned long           __unused1;
-       unsigned long           __unused2;
-};
-
-#endif /* _ASM_MICROBLAZE_IPCBUF_H */
+#include <asm-generic/ipcbuf.h>
index db515deaa720c066c65c0bb85cce1ded59da015a..90f050535ebef0f51881fdc451bac5df84816a9d 100644 (file)
@@ -10,6 +10,7 @@
 #define _ASM_MICROBLAZE_IRQ_H
 
 #define NR_IRQS 32
+#include <asm-generic/irq.h>
 
 #include <linux/interrupt.h>
 
@@ -17,11 +18,6 @@ extern unsigned int nr_irq;
 
 #define NO_IRQ (-1)
 
-static inline int irq_canonicalize(int irq)
-{
-       return irq;
-}
-
 struct pt_regs;
 extern void do_IRQ(struct pt_regs *regs);
 
index 4914b1329445ed1b7f3bef722b3984bd7f726533..8eebf89f5ab17884a98543f3b37a3b710355083b 100644 (file)
@@ -1,25 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_MMAN_H
-#define _ASM_MICROBLAZE_MMAN_H
-
 #include <asm-generic/mman.h>
-
-#define MAP_GROWSDOWN  0x0100 /* stack-like segment */
-#define MAP_DENYWRITE  0x0800 /* ETXTBSY */
-#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
-#define MAP_LOCKED     0x2000 /* pages are locked */
-#define MAP_NORESERVE  0x4000 /* don't check for reservations */
-#define MAP_POPULATE   0x8000 /* populate (prefault) pagetables */
-#define MAP_NONBLOCK   0x10000 /* do not block on IO */
-
-#define MCL_CURRENT    1 /* lock all current mappings */
-#define MCL_FUTURE     2 /* lock all future mappings */
-
-#endif /* _ASM_MICROBLAZE_MMAN_H */
index 66cad6a99d77b41a8c5b50f140de1c3daf356121..8d6a654ceffb1b408532a27170d40909526aa157 100644 (file)
 #define _ASM_MICROBLAZE_MMU_H
 
 # ifndef CONFIG_MMU
-#  ifndef __ASSEMBLY__
-typedef struct {
-       struct vm_list_struct   *vmlist;
-       unsigned long           end_brk;
-} mm_context_t;
-#  endif /* __ASSEMBLY__ */
+#  include <asm-generic/mmu.h>
 # else /* CONFIG_MMU */
 #  ifdef __KERNEL__
 #   ifndef __ASSEMBLY__
index 385fed16bbfb12eb04281c838037c475fb72c8fa..24eab1674d3eeb53621c9f6afc7807a7f89d2c16 100644 (file)
@@ -1,5 +1,5 @@
 #ifdef CONFIG_MMU
 # include "mmu_context_mm.h"
 #else
-# include "mmu_context_no.h"
+# include <asm-generic/mmu_context.h>
 #endif
diff --git a/arch/microblaze/include/asm/mmu_context_no.h b/arch/microblaze/include/asm/mmu_context_no.h
deleted file mode 100644 (file)
index ba55671..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
- * Copyright (C) 2008-2009 PetaLogix
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_MMU_CONTEXT_H
-#define _ASM_MICROBLAZE_MMU_CONTEXT_H
-
-# define init_new_context(tsk, mm)             ({ 0; })
-
-# define enter_lazy_tlb(mm, tsk)               do {} while (0)
-# define change_mm_context(old, ctx, _pml4)    do {} while (0)
-# define destroy_context(mm)                   do {} while (0)
-# define deactivate_mm(tsk, mm)                        do {} while (0)
-# define switch_mm(prev, next, tsk)            do {} while (0)
-# define activate_mm(prev, next)               do {} while (0)
-
-#endif /* _ASM_MICROBLAZE_MMU_CONTEXT_H */
index 914565a90315138e2a091d5df5b642bb07df023a..7be1347fce42c0649e8e0a7d7b7941bd4f43db63 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef _ASM_MICROBLAZE_MODULE_H
 #define _ASM_MICROBLAZE_MODULE_H
 
+#include <asm-generic/module.h>
+
 /* Microblaze Relocations */
 #define R_MICROBLAZE_NONE 0
 #define R_MICROBLAZE_32 1
 /* Keep this the last entry. */
 #define R_MICROBLAZE_NUM 11
 
-struct mod_arch_specific {
-       int foo;
-};
-
-#define Elf_Shdr       Elf32_Shdr
-#define Elf_Sym                Elf32_Sym
-#define Elf_Ehdr       Elf32_Ehdr
-
 typedef struct { volatile int counter; } module_t;
 
 #endif /* _ASM_MICROBLAZE_MODULE_H */
index 09dd97097211c5c2653716b93f27575839a7a547..809134c644a677032e9eb2ae5d5a844806bc347e 100644 (file)
@@ -1,31 +1 @@
-#ifndef _ASM_MICROBLAZE_MSGBUF_H
-#define _ASM_MICROBLAZE_MSGBUF_H
-
-/*
- * The msqid64_ds structure for microblaze architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
-       struct ipc64_perm msg_perm;
-       __kernel_time_t msg_stime; /* last msgsnd time */
-       unsigned long __unused1;
-       __kernel_time_t msg_rtime; /* last msgrcv time */
-       unsigned long __unused2;
-       __kernel_time_t msg_ctime; /* last change time */
-       unsigned long __unused3;
-       unsigned long msg_cbytes; /* current number of bytes on queue */
-       unsigned long msg_qnum; /* number of messages in queue */
-       unsigned long msg_qbytes; /* max number of bytes on queue */
-       __kernel_pid_t msg_lspid; /* pid of last msgsnd */
-       __kernel_pid_t msg_lrpid; /* last receive pid */
-       unsigned long __unused4;
-       unsigned long __unused5;
-};
-
-#endif /* _ASM_MICROBLAZE_MSGBUF_H */
+#include <asm-generic/msgbuf.h>
index 8c538a49616d818fce6eab212ed147a743e29468..965d45427975907ae67efb45e20c8f500fd1ad3a 100644 (file)
@@ -1,30 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_PARAM_H
-#define _ASM_MICROBLAZE_PARAM_H
-
-#ifdef __KERNEL__
-#define HZ             CONFIG_HZ       /* internal kernel timer frequency */
-#define USER_HZ                100             /* for user interfaces in "ticks" */
-#define CLOCKS_PER_SEC (USER_HZ)       /* frequency at which times() counts */
-#endif /* __KERNEL__ */
-
-#ifndef HZ
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE  4096
-
-#ifndef NOGROUP
-#define NOGROUP                (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64      /* max length of hostname */
-
-#endif /* _ASM_MICROBLAZE_PARAM_H */
+#include <asm-generic/param.h>
diff --git a/arch/microblaze/include/asm/parport.h b/arch/microblaze/include/asm/parport.h
new file mode 100644 (file)
index 0000000..cf252af
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/parport.h>
index ca03794cf3f0e748e3ee6690e84f9b958139bf61..9f0df5faf2c88d1d89b37ba56c7b535e0e29f4ba 100644 (file)
@@ -1 +1 @@
-#include <linux/io.h>
+#include <asm-generic/pci.h>
index 59a757e46ba552ad57736103ea42c3378e83af90..b0131da1387bb131cd9e7666519eedb9591302e3 100644 (file)
@@ -180,7 +180,7 @@ extern inline void pte_free(struct mm_struct *mm, struct page *ptepage)
        __free_page(ptepage);
 }
 
-#define __pte_free_tlb(tlb, pte)       pte_free((tlb)->mm, (pte))
+#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, (pte))
 
 #define pmd_populate(mm, pmd, pte)     (pmd_val(*(pmd)) = page_address(pte))
 
@@ -193,7 +193,7 @@ extern inline void pte_free(struct mm_struct *mm, struct page *ptepage)
  */
 #define pmd_alloc_one(mm, address)     ({ BUG(); ((pmd_t *)2); })
 /*#define pmd_free(mm, x)                      do { } while (0)*/
-#define __pmd_free_tlb(tlb, x)         do { } while (0)
+#define __pmd_free_tlb(tlb, x, addr)   do { } while (0)
 #define pgd_populate(mm, pmd, pte)     BUG()
 
 extern int do_check_pgt_cache(int, int);
index 4c57a586a989e6695be8b14a2337d34f87f7f751..cc3a4dfc3eaa94c75dcc37f396a52b8edc373086 100644 (file)
@@ -185,6 +185,7 @@ static inline pte_t pte_mkspecial(pte_t pte)        { return pte; }
 
 /* Definitions for MicroBlaze. */
 #define        _PAGE_GUARDED   0x001   /* G: page is guarded from prefetch */
+#define _PAGE_FILE     0x001   /* when !present: nonlinear file mapping */
 #define _PAGE_PRESENT  0x002   /* software: PTE contains a translation */
 #define        _PAGE_NO_CACHE  0x004   /* I: caching is inhibited */
 #define        _PAGE_WRITETHRU 0x008   /* W: caching is write-through */
@@ -320,8 +321,7 @@ static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
 static inline int pte_exec(pte_t pte)  { return pte_val(pte) & _PAGE_EXEC; }
 static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
-/* FIXME */
-static inline int pte_file(pte_t pte)          { return 0; }
+static inline int pte_file(pte_t pte)  { return pte_val(pte) & _PAGE_FILE; }
 
 static inline void pte_uncache(pte_t pte) { pte_val(pte) |= _PAGE_NO_CACHE; }
 static inline void pte_cache(pte_t pte)   { pte_val(pte) &= ~_PAGE_NO_CACHE; }
@@ -488,7 +488,7 @@ static inline pmd_t *pmd_offset(pgd_t *dir, unsigned long address)
 /* Encode and decode a nonlinear file mapping entry */
 #define PTE_FILE_MAX_BITS      29
 #define pte_to_pgoff(pte)      (pte_val(pte) >> 3)
-#define pgoff_to_pte(off)      ((pte_t) { ((off) << 3) })
+#define pgoff_to_pte(off)      ((pte_t) { ((off) << 3) | _PAGE_FILE })
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
index 8c758b231f376780dad5b30a0ae8b8b29da54b00..0e15039673e34f46df971fcb21444321345ac0de 100644 (file)
@@ -1,73 +1,9 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
 #ifndef _ASM_MICROBLAZE_POSIX_TYPES_H
 #define _ASM_MICROBLAZE_POSIX_TYPES_H
 
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc. Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned long  __kernel_ino_t;
 typedef unsigned short __kernel_mode_t;
-typedef unsigned int   __kernel_nlink_t;
-typedef long           __kernel_off_t;
-typedef int            __kernel_pid_t;
-typedef unsigned int   __kernel_ipc_pid_t;
-typedef unsigned int   __kernel_uid_t;
-typedef unsigned int   __kernel_gid_t;
-typedef unsigned long  __kernel_size_t;
-typedef long           __kernel_ssize_t;
-typedef int            __kernel_ptrdiff_t;
-typedef long           __kernel_time_t;
-typedef long           __kernel_suseconds_t;
-typedef long           __kernel_clock_t;
-typedef int            __kernel_timer_t;
-typedef int            __kernel_clockid_t;
-typedef int            __kernel_daddr_t;
-typedef char           *__kernel_caddr_t;
-typedef unsigned short __kernel_uid16_t;
-typedef unsigned short __kernel_gid16_t;
-typedef unsigned int   __kernel_uid32_t;
-typedef unsigned int   __kernel_gid32_t;
-
-typedef unsigned int   __kernel_old_uid_t;
-typedef unsigned int   __kernel_old_gid_t;
-typedef unsigned int   __kernel_old_dev_t;
-
-#ifdef __GNUC__
-typedef long long      __kernel_loff_t;
-#endif
-
-typedef struct {
-#if defined(__KERNEL__) || defined(__USE_ALL)
-       int     val[2];
-#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
-       int     __val[2];
-#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
-
-#undef __FD_SET
-#define        __FD_SET(d, set)        ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
-
-#undef __FD_CLR
-#define        __FD_CLR(d, set)        ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-
-#undef __FD_ISSET
-#define        __FD_ISSET(d, set)      (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d)))
-
-#undef __FD_ZERO
-#define __FD_ZERO(fdsetp) (memset(fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+#define __kernel_mode_t __kernel_mode_t
 
-#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+#include <asm-generic/posix_types.h>
 
 #endif /* _ASM_MICROBLAZE_POSIX_TYPES_H */
index 20f7b3a926e850ca5d621265d5933eb26359fad4..37e6f305a68ee161c8cf170b162b7de39cadf1a1 100644 (file)
 #define _ASM_MICROBLAZE_PROM_H
 #ifdef __KERNEL__
 
+/* Definitions used by the flattened device tree */
+#define OF_DT_HEADER           0xd00dfeed /* marker */
+#define OF_DT_BEGIN_NODE       0x1 /* Start of node, full name */
+#define OF_DT_END_NODE         0x2 /* End node */
+#define OF_DT_PROP             0x3 /* Property: name off, size, content */
+#define OF_DT_NOP              0x4 /* nop */
+#define OF_DT_END              0x9
+
+#define OF_DT_VERSION          0x10
+
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 #include <linux/proc_fs.h>
 #include <linux/platform_device.h>
 #define of_prop_cmp(s1, s2)            strcmp((s1), (s2))
 #define of_node_cmp(s1, s2)            strcasecmp((s1), (s2))
 
-/* Definitions used by the flattened device tree */
-#define OF_DT_HEADER           0xd00dfeed /* marker */
-#define OF_DT_BEGIN_NODE       0x1 /* Start of node, full name */
-#define OF_DT_END_NODE         0x2 /* End node */
-#define OF_DT_PROP             0x3 /* Property: name off, size, content */
-#define OF_DT_NOP              0x4 /* nop */
-#define OF_DT_END              0x9
-
-#define OF_DT_VERSION          0x10
-
 /*
  * This is what gets passed to the kernel by prom_init or kexec
  *
@@ -309,5 +311,6 @@ extern void __iomem *of_iomap(struct device_node *device, int index);
  */
 #include <linux/of.h>
 
+#endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_MICROBLAZE_PROM_H */
index 08ff1d049b4264a4d191abb970c0391fbb5cfc24..35d786fe93ae0dcba7e1cf434606e9e61d1b05c2 100644 (file)
@@ -1,28 +1 @@
-/*
- * Copyright (C) 2008 Michal Simek <monstr@monstr.eu>
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_SCATTERLIST_H
-#define _ASM_MICROBLAZE_SCATTERLIST_H
-
-struct scatterlist {
-#ifdef CONFIG_DEBUG_SG
-       unsigned long   sg_magic;
-#endif
-       unsigned long   page_link;
-       dma_addr_t      dma_address;
-       unsigned int    offset;
-       unsigned int    length;
-};
-
-#define sg_dma_address(sg)      ((sg)->dma_address)
-#define sg_dma_len(sg)          ((sg)->length)
-
-#define ISA_DMA_THRESHOLD (~0UL)
-
-#endif /* _ASM_MICROBLAZE_SCATTERLIST_H */
+#include <asm-generic/scatterlist.h>
index b804ed71a57e51d5eb186f3c1f196c17e5057546..7673b83cfef73397301a171e86cf492b771ad9b4 100644 (file)
@@ -1,34 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_SEMBUF_H
-#define _ASM_MICROBLAZE_SEMBUF_H
-
-/*
- * The semid64_ds structure for microblaze architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
-       struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
-       __kernel_time_t sem_otime; /* last semop time */
-       unsigned long   __unused1;
-       __kernel_time_t sem_ctime; /* last change time */
-       unsigned long   __unused2;
-       unsigned long   sem_nsems; /* no. of semaphores in array */
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-
-#endif /* _ASM_MICROBLAZE_SEMBUF_H */
+#include <asm-generic/sembuf.h>
index 39bfc8ce6af58348b1ede012394fda0802296bf6..a0cb0caff15241a41973f67b68756510b8bfe90e 100644 (file)
@@ -1,14 +1 @@
-/*
- * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
- *
- * 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.
- */
-
-#ifndef _ASM_MICROBLAZE_SERIAL_H
-#define _ASM_MICROBLAZE_SERIAL_H
-
-# define BASE_BAUD (1843200 / 16)
-
-#endif /* _ASM_MICROBLAZE_SERIAL_H */
+#include <asm-generic/serial.h>
index f829c584361858e93ceb0468e30d3a7e3cdc398e..83c05fc2de385c3260286bf12fed846617c8c095 100644 (file)
@@ -1,42 +1 @@
-#ifndef _ASM_MICROBLAZE_SHMBUF_H
-#define _ASM_MICROBLAZE_SHMBUF_H
-
-/*
- * The shmid64_ds structure for microblaze architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
-       struct ipc64_perm       shm_perm; /* operation perms */
-       size_t                  shm_segsz; /* size of segment (bytes) */
-       __kernel_time_t         shm_atime; /* last attach time */
-       unsigned long           __unused1;
-       __kernel_time_t         shm_dtime; /* last detach time */
-       unsigned long           __unused2;
-       __kernel_time_t         shm_ctime; /* last change time */
-       unsigned long           __unused3;
-       __kernel_pid_t          shm_cpid; /* pid of creator */
-       __kernel_pid_t          shm_lpid; /* pid of last operator */
-       unsigned long           shm_nattch; /* no. of current attaches */
-       unsigned long           __unused4;
-       unsigned long           __unused5;
-};
-
-struct shminfo64 {
-       unsigned long   shmmax;
-       unsigned long   shmmin;
-       unsigned long   shmmni;
-       unsigned long   shmseg;
-       unsigned long   shmall;
-       unsigned long   __unused1;
-       unsigned long   __unused2;
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-#endif /* _ASM_MICROBLAZE_SHMBUF_H */
+#include <asm-generic/shmbuf.h>
index 9f5fc2b3b6a3cbf6b7eb7aa83fc23a1eb75005c1..93f30deb95d0803ee9b84ade84d3c6738894603a 100644 (file)
@@ -1,6 +1 @@
-#ifndef _ASM_MICROBLAZE_SHMPARAM_H
-#define _ASM_MICROBLAZE_SHMPARAM_H
-
-#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
-
-#endif /* _ASM_MICROBLAZE_SHMPARAM_H */
+#include <asm-generic/shmparam.h>
index f162911a8f50cfebff36d7d07ee4223e4a1e6f68..0815d29d82e5f5f14d6e570f8768d184d63912a9 100644 (file)
@@ -1,15 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_SIGINFO_H
-#define _ASM_MICROBLAZE_SIGINFO_H
-
-#include <linux/types.h>
 #include <asm-generic/siginfo.h>
-
-#endif /* _ASM_MICROBLAZE_SIGINFO_H */
index 46bc2267d9497a751de01b75324120b384f4ce5f..7b1573ce19de50ed695751b2af1bd8dfc54b86e8 100644 (file)
@@ -1,165 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *     Yasushi SHOJI <yashi@atmark-techno.com>
- *     Tetsuya OHKAWA <tetsuya@atmark-techno.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_SIGNAL_H
-#define _ASM_MICROBLAZE_SIGNAL_H
-
-#define SIGHUP         1
-#define SIGINT         2
-#define SIGQUIT                3
-#define SIGILL         4
-#define SIGTRAP                5
-#define SIGABRT                6
-#define SIGIOT         6
-#define SIGBUS         7
-#define SIGFPE         8
-#define SIGKILL                9
-#define SIGUSR1                10
-#define SIGSEGV                11
-#define SIGUSR2                12
-#define SIGPIPE                13
-#define SIGALRM                14
-#define SIGTERM                15
-#define SIGSTKFLT      16
-#define SIGCHLD                17
-#define SIGCONT                18
-#define SIGSTOP                19
-#define SIGTSTP                20
-#define SIGTTIN                21
-#define SIGTTOU                22
-#define SIGURG         23
-#define SIGXCPU                24
-#define SIGXFSZ                25
-#define SIGVTALRM      26
-#define SIGPROF                27
-#define SIGWINCH       28
-#define SIGIO          29
-#define SIGPOLL                SIGIO
-/*
-#define SIGLOST                29
-*/
-#define SIGPWR         30
-#define SIGSYS         31
-#define        SIGUNUSED       31
-
-/* These should not be considered constants from userland. */
-#define SIGRTMIN       32
-#define SIGRTMAX       _NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP   0x00000001
-#define SA_NOCLDWAIT   0x00000002
-#define SA_SIGINFO     0x00000004
-#define SA_ONSTACK     0x08000000
-#define SA_RESTART     0x10000000
-#define SA_NODEFER     0x40000000
-#define SA_RESETHAND   0x80000000
-
-#define SA_NOMASK      SA_NODEFER
-#define SA_ONESHOT     SA_RESETHAND
-
-#define SA_RESTORER    0x04000000
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
-#define MINSIGSTKSZ    2048
-#define SIGSTKSZ       8192
-
-# ifndef __ASSEMBLY__
-# include <linux/types.h>
-# include <asm-generic/signal-defs.h>
-
-/* Avoid too many header ordering problems. */
-struct siginfo;
-
-#  ifdef __KERNEL__
-/*
- * Most things should be clean enough to redefine this at will, if care
- * is taken to make libc match.
- */
-#  define _NSIG                64
-#  define _NSIG_BPW    32
-#  define _NSIG_WORDS  (_NSIG / _NSIG_BPW)
-
-typedef unsigned long old_sigset_t; /* at least 32 bits */
-
-typedef struct {
-       unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-struct old_sigaction {
-       __sighandler_t sa_handler;
-       old_sigset_t sa_mask;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-};
-
-struct sigaction {
-       __sighandler_t sa_handler;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-       sigset_t sa_mask; /* mask last for extensibility */
-};
-
-struct k_sigaction {
-       struct sigaction sa;
-};
-
-#  include <asm/sigcontext.h>
-#  undef __HAVE_ARCH_SIG_BITOPS
-
-#  define ptrace_signal_deliver(regs, cookie) do { } while (0)
-
-#  else /* !__KERNEL__ */
-
-/* Here we must cater to libcs that poke about in kernel headers. */
-
-#  define NSIG         32
-typedef unsigned long sigset_t;
-
-struct sigaction {
-       union {
-       __sighandler_t _sa_handler;
-       void (*_sa_sigaction)(int, struct siginfo *, void *);
-       } _u;
-       sigset_t sa_mask;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-};
-
-#  define sa_handler   _u._sa_handler
-#  define sa_sigaction _u._sa_sigaction
-
-#  endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
-       void *ss_sp;
-       int ss_flags;
-       size_t ss_size;
-} stack_t;
-
-# endif /* __ASSEMBLY__ */
-#endif /* _ASM_MICROBLAZE_SIGNAL_H */
+#include <asm-generic/signal.h>
index 8259368603149ea09320b079b1d41bebfb385211..6b71384b9d8b42ac6cce8a955a73220bda4957d5 100644 (file)
@@ -1,69 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_SOCKET_H
-#define _ASM_MICROBLAZE_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockoptions(2) */
-#define SOL_SOCKET     1
-
-#define SO_DEBUG       1
-#define SO_REUSEADDR   2
-#define SO_TYPE                3
-#define SO_ERROR       4
-#define SO_DONTROUTE   5
-#define SO_BROADCAST   6
-#define SO_SNDBUF      7
-#define SO_RCVBUF      8
-#define SO_SNDBUFFORCE 32
-#define SO_RCVBUFFORCE 33
-#define SO_KEEPALIVE   9
-#define SO_OOBINLINE   10
-#define SO_NO_CHECK    11
-#define SO_PRIORITY    12
-#define SO_LINGER      13
-#define SO_BSDCOMPAT   14
-/* To add :#define SO_REUSEPORT 15 */
-#define SO_PASSCRED    16
-#define SO_PEERCRED    17
-#define SO_RCVLOWAT    18
-#define SO_SNDLOWAT    19
-#define SO_RCVTIMEO    20
-#define SO_SNDTIMEO    21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION             22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT       23
-#define SO_SECURITY_ENCRYPTION_NETWORK         24
-
-#define SO_BINDTODEVICE        25
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER       26
-#define SO_DETACH_FILTER       27
-
-#define SO_PEERNAME            28
-#define SO_TIMESTAMP           29
-#define SCM_TIMESTAMP          SO_TIMESTAMP
-
-#define SO_ACCEPTCONN          30
-
-#define SO_PEERSEC             31
-#define SO_PASSSEC             34
-
-#define SO_TIMESTAMPNS         35
-#define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
-
-#define SO_MARK                        36
-
-#define SO_TIMESTAMPING                37
-#define SCM_TIMESTAMPING       SO_TIMESTAMPING
-
-#endif /* _ASM_MICROBLAZE_SOCKET_H */
+#include <asm-generic/socket.h>
index 9fff57a701e1e0a35d0c165c7e83bc6e624b202f..def6d4746ee7fef64057f79e8d76ac41688671d9 100644 (file)
@@ -1,23 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_SOCKIOS_H
-#define _ASM_MICROBLAZE_SOCKIOS_H
-
-#include <linux/ioctl.h>
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN      0x8901
-#define SIOCSPGRP      0x8902
-#define FIOGETOWN      0x8903
-#define SIOCGPGRP      0x8904
-#define SIOCATMARK     0x8905
-#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
-#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
-
-#endif /* _ASM_MICROBLAZE_SOCKIOS_H */
+#include <asm-generic/sockios.h>
index a15f77520bfd74ac2dff80e4780d37c7b3574ed9..3dc90fa92c704d8fb07d66b034daadd44ee6376b 100644 (file)
@@ -1,68 +1 @@
-/*
- * Microblaze stat structure
- *
- * Copyright (C) 2001,02,03 NEC Electronics Corporation
- * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
- *
- * 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.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
-
-#ifndef _ASM_MICROBLAZE_STAT_H
-#define _ASM_MICROBLAZE_STAT_H
-
-#include <linux/posix_types.h>
-
-#define STAT_HAVE_NSEC 1
-
-struct stat {
-       unsigned long   st_dev;
-       unsigned long   st_ino;
-       unsigned int    st_mode;
-       unsigned int    st_nlink;
-       unsigned int    st_uid;
-       unsigned int    st_gid;
-       unsigned long   st_rdev;
-       unsigned long   __pad1;
-       long            st_size;
-       int             st_blksize;
-       int             __pad2;
-       long            st_blocks;
-       int             st_atime;
-       unsigned int    st_atime_nsec;
-       int             st_mtime;
-       unsigned int    st_mtime_nsec;
-       int             st_ctime;
-       unsigned int    st_ctime_nsec;
-       unsigned long   __unused4;
-       unsigned long   __unused5;
-};
-
-struct stat64 {
-       unsigned long long      st_dev;         /* Device.  */
-       unsigned long long      st_ino;         /* File serial number.  */
-       unsigned int            st_mode;        /* File mode.  */
-       unsigned int            st_nlink;       /* Link count.  */
-       unsigned int            st_uid;         /* User ID of the file's owner.  */
-       unsigned int            st_gid;         /* Group ID of the file's group. */
-       unsigned long long      st_rdev;        /* Device number, if device.  */
-       unsigned long long      __pad1;
-       long long               st_size;        /* Size of file, in bytes.  */
-       int                     st_blksize;     /* Optimal block size for I/O.  */
-       int                     __pad2;
-       long long               st_blocks;      /* Number 512-byte blocks allocated. */
-       int                     st_atime;       /* Time of last access.  */
-       unsigned int            st_atime_nsec;
-       int                     st_mtime;       /* Time of last modification.  */
-       unsigned int            st_mtime_nsec;
-       int                     st_ctime;       /* Time of last status change.  */
-       unsigned int            st_ctime_nsec;
-       unsigned int            __unused4;
-       unsigned int            __unused5;
-};
-
-#endif /* _ASM_MICROBLAZE_STAT_H */
-
+#include <asm-generic/stat.h>
index b375d7b65ad73b7b7578da5dfc71ba71115f59a5..7847e563ab66f18af1951d9cf94bf353daf54596 100644 (file)
@@ -1,8 +1 @@
-#ifndef _ASM_MICROBLAZE_SWAB_H
-#define _ASM_MICROBLAZE_SWAB_H
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-#define __SWAB_64_THRU_32__
-#endif
-
-#endif /* _ASM_MICROBLAZE_SWAB_H */
+#include <asm-generic/swab.h>
index ddea9eb31f8da76aa4a3a820a7ee8a9c0744dae7..720761cc741f43209e8081afd8dde3d5fb028a40 100644 (file)
@@ -1,48 +1,8 @@
 #ifndef __ASM_MICROBLAZE_SYSCALLS_H
-#define __ASM_MICROBLAZE_SYSCALLS_H
-#ifdef __KERNEL__
 
-#include <linux/compiler.h>
-#include <linux/linkage.h>
-#include <linux/types.h>
-#include <linux/signal.h>
+asmlinkage long sys_clone(int flags, unsigned long stack, struct pt_regs *regs);
+#define sys_clone sys_clone
 
-/* FIXME will be removed */
-asmlinkage int sys_ipc(uint call, int first, int second,
-                               int third, void *ptr, long fifth);
+#include <asm-generic/syscalls.h>
 
-struct pt_regs;
-asmlinkage int sys_vfork(struct pt_regs *regs);
-asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs);
-asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv,
-                       char __user *__user *envp, struct pt_regs *regs);
-
-asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len,
-                       unsigned long prot, unsigned long flags,
-                       unsigned long fd, unsigned long pgoff);
-
-asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
-                       unsigned long prot, unsigned long flags,
-                       unsigned long fd, off_t offset);
-
-/* from signal.c */
-asmlinkage int sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs);
-
-asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
-               struct pt_regs *regs);
-
-asmlinkage int sys_sigaction(int sig, const struct old_sigaction *act,
-               struct old_sigaction *oact);
-
-asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act,
-               struct sigaction __user *oact, size_t sigsetsize);
-
-asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
-               struct pt_regs *regs);
-
-asmlinkage int sys_sigreturn(struct pt_regs *regs);
-
-asmlinkage int sys_rt_sigreturn(struct pt_regs *regs);
-
-#endif /* __KERNEL__ */
 #endif /* __ASM_MICROBLAZE_SYSCALLS_H */
index c4e308850b5d6af1be1e1c0fd8487fd307e8ba22..b1ed6159066006bd3d635f57126316a12f25962a 100644 (file)
@@ -13,6 +13,9 @@
 #include <asm/setup.h>
 #include <asm/irqflags.h>
 
+#include <asm-generic/cmpxchg.h>
+#include <asm-generic/cmpxchg-local.h>
+
 struct task_struct;
 struct thread_info;
 
index a1b64bc4724ac0344b4f0d6b259719f808f2c643..3935b106de79bf2f8469b849576268ac1ca30bb2 100644 (file)
@@ -1,203 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_TERMBITS_H
-#define _ASM_MICROBLAZE_TERMBITS_H
-
-#include <linux/posix_types.h>
-
-typedef unsigned char  cc_t;
-typedef unsigned int   speed_t;
-typedef unsigned int   tcflag_t;
-
-#define NCCS 19
-struct termios {
-       tcflag_t c_iflag; /* input mode flags */
-       tcflag_t c_oflag; /* output mode flags */
-       tcflag_t c_cflag; /* control mode flags */
-       tcflag_t c_lflag; /* local mode flags */
-       cc_t c_line; /* line discipline */
-       cc_t c_cc[NCCS]; /* control characters */
-};
-
-struct ktermios {
-       tcflag_t c_iflag; /* input mode flags */
-       tcflag_t c_oflag; /* output mode flags */
-       tcflag_t c_cflag; /* control mode flags */
-       tcflag_t c_lflag; /* local mode flags */
-       cc_t c_line; /* line discipline */
-       cc_t c_cc[NCCS]; /* control characters */
-       speed_t c_ispeed; /* input speed */
-       speed_t c_ospeed; /* output speed */
-};
-
-/* c_cc characters */
-
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-/* c_iflag bits */
-
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK  0000020
-#define ISTRIP 0000040
-#define INLCR  0000100
-#define IGNCR  0000200
-#define ICRNL  0000400
-#define IUCLC  0001000
-#define IXON   0002000
-#define IXANY  0004000
-#define IXOFF  0010000
-#define IMAXBEL        0020000
-#define IUTF8  0040000
-
-/* c_oflag bits */
-
-#define OPOST  0000001
-#define OLCUC  0000002
-#define ONLCR  0000004
-#define OCRNL  0000010
-#define ONOCR  0000020
-#define ONLRET 0000040
-#define OFILL  0000100
-#define OFDEL  0000200
-#define NLDLY  0000400
-#define NL0    0000000
-#define NL1    0000400
-#define CRDLY  0003000
-#define CR0    0000000
-#define CR1    0001000
-#define CR2    0002000
-#define CR3    0003000
-#define TABDLY 0014000
-#define TAB0   0000000
-#define TAB1   0004000
-#define TAB2   0010000
-#define TAB3   0014000
-#define XTABS  0014000
-#define BSDLY  0020000
-#define BS0    0000000
-#define BS1    0020000
-#define VTDLY  0040000
-#define VT0    0000000
-#define VT1    0040000
-#define FFDLY  0100000
-#define FF0    0000000
-#define FF1    0100000
-
-/* c_cflag bit meaning */
-
-#define CBAUD  0010017
-#define B0     0000000 /* hang up */
-#define B50    0000001
-#define B75    0000002
-#define B110   0000003
-#define B134   0000004
-#define B150   0000005
-#define B200   0000006
-#define B300   0000007
-#define B600   0000010
-#define B1200  0000011
-#define B1800  0000012
-#define B2400  0000013
-#define B4800  0000014
-#define B9600  0000015
-#define B19200 0000016
-#define B38400 0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE  0000060
-#define CS5    0000000
-#define CS6    0000020
-#define CS7    0000040
-#define CS8    0000060
-#define CSTOPB 0000100
-#define CREAD  0000200
-#define PARENB 0000400
-#define PARODD 0001000
-#define HUPCL  0002000
-#define CLOCAL 0004000
-#define CBAUDEX        0010000
-#define B57600 0010001
-#define B115200        0010002
-#define B230400        0010003
-#define B460800        0010004
-#define B500000        0010005
-#define B576000        0010006
-#define B921600        0010007
-#define BOTHER         0010000
-#define B1000000       0010010
-#define B1152000       0010011
-#define B1500000       0010012
-#define B2000000       0010013
-#define B2500000       0010014
-#define B3000000       0010015
-#define B3500000       0010016
-#define B4000000       0010017
-#define CIBAUD         002003600000 /* input baud rate (not used) */
-#define CMSPAR         010000000000 /* mark or space (stick) parity */
-#define CRTSCTS                020000000000 /* flow control */
-
-#define IBSHIFT        16              /* Shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-
-#define ISIG   0000001
-#define ICANON 0000002
-#define XCASE  0000004
-#define ECHO   0000010
-#define ECHOE  0000020
-#define ECHOK  0000040
-#define ECHONL 0000100
-#define NOFLSH 0000200
-#define TOSTOP 0000400
-#define ECHOCTL        0001000
-#define ECHOPRT        0002000
-#define ECHOKE 0004000
-#define FLUSHO 0010000
-#define PENDIN 0040000
-#define IEXTEN 0100000
-
-/* tcflow() and TCXONC use these */
-
-#define        TCOOFF          0
-#define        TCOON           1
-#define        TCIOFF          2
-#define        TCION           3
-
-/* tcflush() and TCFLSH use these */
-
-#define        TCIFLUSH        0
-#define        TCOFLUSH        1
-#define        TCIOFLUSH       2
-
-/* tcsetattr uses these */
-
-#define        TCSANOW         0
-#define        TCSADRAIN       1
-#define        TCSAFLUSH       2
-
-#endif /* _ASM_MICROBLAZE_TERMBITS_H */
+#include <asm-generic/termbits.h>
index 47a46d1fbe26fa4e1ddd1bf7b66f3290ea1facc8..280d78a9d96637ccbc93bc4c0debc88eb9443bba 100644 (file)
@@ -1,88 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_TERMIOS_H
-#define _ASM_MICROBLAZE_TERMIOS_H
-
-#include <linux/string.h>
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-       unsigned short c_iflag; /* input mode flags */
-       unsigned short c_oflag; /* output mode flags */
-       unsigned short c_cflag; /* control mode flags */
-       unsigned short c_lflag; /* local mode flags */
-       unsigned char c_line; /* line discipline */
-       unsigned char c_cc[NCC]; /* control characters */
-};
-
-#ifdef __KERNEL__
-/*     intr=^C         quit=^|         erase=del       kill=^U
-       eof=^D          vtime=\0        vmin=\1         sxtc=\0
-       start=^Q        stop=^S         susp=^Z         eol=\0
-       reprint=^R      discard=^U      werase=^W       lnext=^V
-       eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-#endif
-
-/* Modem lines */
-
-#define TIOCM_LE       0x001
-#define TIOCM_DTR      0x002
-#define TIOCM_RTS      0x004
-#define TIOCM_ST       0x008
-#define TIOCM_SR       0x010
-#define TIOCM_CTS      0x020
-#define TIOCM_CAR      0x040
-#define TIOCM_RNG      0x080
-#define TIOCM_DSR      0x100
-#define TIOCM_CD       TIOCM_CAR
-#define TIOCM_RI       TIOCM_RNG
-#define TIOCM_OUT1     0x2000
-#define TIOCM_OUT2     0x4000
-#define TIOCM_LOOP     0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-/* Line disciplines */
-
-#define N_TTY          0
-#define N_SLIP         1
-#define N_MOUSE                2
-#define N_PPP          3
-#define N_STRIP                4
-#define N_AX25         5
-#define N_X25          6 /* X.25 async */
-#define N_6PACK                7
-#define N_MASC         8 /* Reserved for Mobitex module <kaz@cafe.net> */
-#define N_R3964                9 /* Reserved for Simatic R3964 module */
-#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA         11 /* Linux IR - http://irda.sourceforge.net/ */
-#define N_SMSBLOCK     12 /* SMS block mode - for talking to GSM data cards
-                               about SMS messages */
-#define N_HDLC         13 /* synchronous HDLC */
-#define N_SYNC_PPP     14
-#define N_HCI          15 /* Bluetooth HCI UART */
-
-#ifdef __KERNEL__
-
-#include <asm-generic/termios-base.h>
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_MICROBLAZE_TERMIOS_H */
+#include <asm-generic/termios.h>
index 7fac44498445f82595431e75c28fcf61a6731e21..6e92885d381a80ee3adc680632415c3911ecdb64 100644 (file)
@@ -75,8 +75,6 @@ struct thread_info {
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #define INIT_THREAD_INFO(tsk)                  \
 {                                              \
@@ -84,7 +82,7 @@ struct thread_info {
        .exec_domain    = &default_exec_domain, \
        .flags          = 0,                    \
        .cpu            = 0,                    \
-       .preempt_count  = 1,                    \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .addr_limit     = KERNEL_DS,            \
        .restart_block = {                      \
                .fn = do_no_restart_syscall,    \
index 678525dc6d0b1ee8e9f7a67b6c6951b676cde889..befcf3de5532c2df283b45a55816d4037a6f2759 100644 (file)
@@ -9,10 +9,8 @@
 #ifndef _ASM_MICROBLAZE_TIMEX_H
 #define _ASM_MICROBLAZE_TIMEX_H
 
-#define CLOCK_TICK_RATE 1000 /* Timer input freq. */
-
-typedef unsigned long cycles_t;
+#include <asm-generic/timex.h>
 
-#define get_cycles()   (0)
+#define CLOCK_TICK_RATE 1000 /* Timer input freq. */
 
 #endif /* _ASM_TIMEX_H */
index c472d280113285780afb447948ff543bb6a57fd9..e8abd4a0349c381f45d1daeb7972db0235fd3e12 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef _ASM_MICROBLAZE_TLB_H
 #define _ASM_MICROBLAZE_TLB_H
 
-#define tlb_flush(tlb) do {} while (0)
+#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
 
 #include <asm-generic/tlb.h>
 
index bebc018318f5527a33d6f7b3d409bbf24cf5c322..b9e79bc580dd6cf47ae1c6a939eb8c67e6f5f7e5 100644 (file)
@@ -1,38 +1 @@
-/*
- * Copyright (C) Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_TYPES_H
-#define _ASM_MICROBLAZE_TYPES_H
-
-/*
- * This file is never included by application software unless
- * explicitly requested (e.g., via linux/types.h) in which case the
- * application is Linux specific so (user-) name space pollution is
- * not a major issue.  However, for interoperability, libraries still
- * need to be careful to avoid a name clashes.
- */
-
-#include <asm-generic/int-ll64.h>
-
-# ifndef __ASSEMBLY__
-
-typedef unsigned short umode_t;
-
-/*
- * These aren't exported outside the kernel to avoid name space clashes
- */
-#  ifdef __KERNEL__
-#  define BITS_PER_LONG 32
-
-/* Dma addresses are 32-bits wide. */
-
-typedef u32 dma_addr_t;
-
-#  endif/* __KERNEL__ */
-# endif /* __ASSEMBLY__ */
-#endif /* _ASM_MICROBLAZE_TYPES_H */
+#include <asm-generic/types.h>
index 65adad61e7e90b4bbf05cc161caaf4a6a6757290..5431b4631a7ad479bc23baf72de4563c68b8efb8 100644 (file)
@@ -189,7 +189,7 @@ extern long strnlen_user(const char *src, long count);
 
 #define __put_user(x, ptr)                                             \
 ({                                                                     \
-       __typeof__(*(ptr)) __gu_val = x;                                \
+       __typeof__(*(ptr)) volatile __gu_val = (x);                     \
        long __gu_err = 0;                                              \
        switch (sizeof(__gu_val)) {                                     \
        case 1:                                                         \
index 11f6bb3ae3a4efd27d978a80dcb76651d0a6d20f..9bc07b9f30fba10518b48cadc01d9aa4eaa4260f 100644 (file)
@@ -1,22 +1 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_UCONTEXT_H
-#define _ASM_MICROBLAZE_UCONTEXT_H
-
-#include <asm/sigcontext.h>
-
-struct ucontext {
-       unsigned long           uc_flags;
-       struct ucontext         *uc_link;
-       stack_t                 uc_stack;
-       struct sigcontext       uc_mcontext;
-       sigset_t                uc_sigmask; /* mask last for extensibility */
-};
-
-#endif /* _ASM_MICROBLAZE_UCONTEXT_H */
+#include <asm-generic/ucontext.h>
index b5e2f5fa5c53559adaf1cd1dd593b4c57aa34404..0b852327c0e7bcaf73d45daa15d5f047533f7485 100644 (file)
 #define __NR_accept04          362 /* new */
 #define __NR_preadv            363 /* new */
 #define __NR_pwritev           364 /* new */
+#define __NR_rt_tgsigqueueinfo 365 /* new */
+#define __NR_perf_counter_open 366 /* new */
 
-#define __NR_syscalls          365
+#define __NR_syscalls          367
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-/* #define __ARCH_WANT_SYS_RT_SIGSUSPEND */
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 
 /*
  * "Conditional" syscalls
index 8b137891791fe96927ad78e64b0aad7bded08bdc..89d82fd8fcf17bcea5c5d0644d4ceda64883bde8 100644 (file)
@@ -1 +1 @@
-
+#include <asm-generic/vga.h>
index f4a5e19a20eb98f6848e01f3d2708d8e105446b2..d487729683de8a0b66c6d082a8cefb096621687d 100644 (file)
@@ -17,4 +17,4 @@ obj-$(CONFIG_HEART_BEAT)      += heartbeat.o
 obj-$(CONFIG_MODULES)          += microblaze_ksyms.o module.o
 obj-$(CONFIG_MMU)              += misc.o
 
-obj-y  += entry$(MMUEXT).o
+obj-y  += entry$(MMU).o
index 153f57c57b6d90ef008d706b4e34319f14045949..c259786e7faa1c51853d3a0e31621ea1ddd154c7 100644 (file)
@@ -22,7 +22,7 @@
 
 #define CI(c, p) { ci->c = PVR_##p(pvr); }
 #define err_printk(x) \
-       early_printk("ERROR: Microblaze " x " - different for PVR and DTS\n");
+       early_printk("ERROR: Microblaze " x "-different for PVR and DTS\n");
 
 void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
 {
index 450ca6bb828db34ae43b3a1d35a6a16ef265c4f5..adb448f93d5fd3157c89b2336ca52488da6ecb42 100644 (file)
@@ -18,7 +18,7 @@ static const char family_string[] = CONFIG_XILINX_MICROBLAZE0_FAMILY;
 static const char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER;
 
 #define err_printk(x) \
-       early_printk("ERROR: Microblaze " x "- different for kernel and DTS\n");
+       early_printk("ERROR: Microblaze " x "-different for kernel and DTS\n");
 
 void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
 {
index a10bea119b946f0b637befe039705c432cdce888..c411c6757deb845a984ae734e108fa216ceb18c0 100644 (file)
@@ -26,6 +26,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = {
        {"7.10.b", 0x09},
        {"7.10.c", 0x0a},
        {"7.10.d", 0x0b},
+       {"7.20.a", 0x0c},
+       {"7.20.b", 0x0d},
        /* FIXME There is no keycode defined in MBV for these versions */
        {"2.10.a", 0x10},
        {"3.00.a", 0x20},
index 1fce6b803f54905b69ffadca0162a4db0593ed66..9083d85376a4dc57b6e7c535869eb4b3f11570f5 100644 (file)
@@ -551,30 +551,22 @@ no_work_pending:
        rtid    r14, 0
        nop
 
-sys_vfork_wrapper:
-       brid    sys_vfork
+sys_vfork:
+       brid    microblaze_vfork
        addk    r5, r1, r0
 
-sys_clone_wrapper:
-       brid    sys_clone
+sys_clone:
+       brid    microblaze_clone
        addk    r7, r1, r0
 
-sys_execve_wrapper:
-       brid    sys_execve
+sys_execve:
+       brid    microblaze_execve
        addk    r8, r1, r0
 
-sys_sigreturn_wrapper:
-       brid    sys_sigreturn
-       addk    r5, r1, r0
-
 sys_rt_sigreturn_wrapper:
        brid    sys_rt_sigreturn
        addk    r5, r1, r0
 
-sys_sigsuspend_wrapper:
-       brid    sys_rt_sigsuspend
-       addk    r6, r1, r0
-
 sys_rt_sigsuspend_wrapper:
        brid    sys_rt_sigsuspend
        addk    r7, r1, r0
index 91a0e7b185dd998c0b51981adc43e81ced768361..c7353e79f4a22f2ddb70d7b25d5e8c79783d8f0e 100644 (file)
@@ -429,12 +429,11 @@ C_ENTRY(ret_from_fork):
        brid    ret_from_trap;  /* Do normal trap return */
        nop;
 
-C_ENTRY(sys_vfork_wrapper):
+C_ENTRY(sys_vfork):
+       brid    microblaze_vfork        /* Do real work (tail-call) */
        la      r5, r1, PTO
-       brid    sys_vfork       /* Do real work (tail-call) */
-       nop
 
-C_ENTRY(sys_clone_wrapper):
+C_ENTRY(sys_clone):
        bnei    r6, 1f;                 /* See if child SP arg (arg 1) is 0. */
        lwi     r6, r1, PTO+PT_R1;      /* If so, use paret's stack ptr */
 1:     la      r7, r1, PTO;                    /* Arg 2: parent context */
@@ -444,20 +443,9 @@ C_ENTRY(sys_clone_wrapper):
        brid    do_fork         /* Do real work (tail-call) */
        nop;
 
-C_ENTRY(sys_execve_wrapper):
+C_ENTRY(sys_execve):
        la      r8, r1, PTO;            /* add user context as 4th arg */
-       brid    sys_execve;     /* Do real work (tail-call).*/
-       nop;
-
-C_ENTRY(sys_sigsuspend_wrapper):
-       swi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
-       swi     r4, r1, PTO+PT_R4;
-       la      r6, r1, PTO;            /* add user context as 2nd arg */
-       bralid  r15, sys_sigsuspend; /* Do real work.*/
-       nop;
-       lwi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
-       lwi     r4, r1, PTO+PT_R4;
-       bri ret_from_trap /* fall through will not work here due to align */
+       brid    microblaze_execve;      /* Do real work (tail-call).*/
        nop;
 
 C_ENTRY(sys_rt_sigsuspend_wrapper):
@@ -471,18 +459,6 @@ C_ENTRY(sys_rt_sigsuspend_wrapper):
        bri ret_from_trap /* fall through will not work here due to align */
        nop;
 
-
-C_ENTRY(sys_sigreturn_wrapper):
-       swi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
-       swi     r4, r1, PTO+PT_R4;
-       la      r5, r1, PTO;            /* add user context as 1st arg */
-       brlid   r15, sys_sigreturn;     /* Do real work.*/
-       nop;
-       lwi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
-       lwi     r4, r1, PTO+PT_R4;
-       bri ret_from_trap /* fall through will not work here due to align */
-       nop;
-
 C_ENTRY(sys_rt_sigreturn_wrapper):
        swi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
        swi     r4, r1, PTO+PT_R4;
index e568d6ec621bfa400bc5b506b9ff6afbe327c002..e41c6ce2a7be3e50589e48e7f661852afabd7709 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/linkage.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
+#include <asm/prom.h>          /* for OF_DT_HEADER */
 
 #ifdef CONFIG_MMU
 #include <asm/setup.h> /* COMMAND_LINE_SIZE */
@@ -54,11 +55,19 @@ ENTRY(_start)
        andi    r1, r1, ~2
        mts     rmsr, r1
 
-/* save fdt to kernel location */
-/* r7 stores pointer to fdt blob */
-       beqi    r7, no_fdt_arg
+/* r7 may point to an FDT, or there may be one linked in.
+   if it's in r7, we've got to save it away ASAP.
+   We ensure r7 points to a valid FDT, just in case the bootloader
+   is broken or non-existent */
+       beqi    r7, no_fdt_arg                  /* NULL pointer?  don't copy */
+       lw      r11, r0, r7                     /* Does r7 point to a */
+       rsubi   r11, r11, OF_DT_HEADER          /* valid FDT? */
+       beqi    r11, _prepare_copy_fdt
+       or      r7, r0, r0              /* clear R7 when not valid DTB */
+       bnei    r11, no_fdt_arg                 /* No - get out of here */
+_prepare_copy_fdt:
        or      r11, r0, r0 /* incremment */
-       ori     r4, r0, TOPHYS(_fdt_start) /* save bram context */
+       ori     r4, r0, TOPHYS(_fdt_start)
        ori     r3, r0, (0x4000 - 4)
 _copy_fdt:
        lw      r12, r7, r11 /* r12 = r7 + r11 */
index 9d591cd74fc221293fa1d647f530c0e29120dbe4..3288c9737671adc6362ba6a079a717d342fa487a 100644 (file)
@@ -74,6 +74,7 @@
 
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
+#include <asm/signal.h>
 #include <asm/asm-offsets.h>
 
 /* Helpful Macros */
@@ -428,19 +429,9 @@ handle_unaligned_ex:
        mfs     r17, rbtr;      /* ESR[DS] set - return address in BTR */
        nop
 _no_delayslot:
-#endif
-
-#ifdef CONFIG_MMU
-       /* Check if unaligned address is last on a 4k page */
-               andi    r5, r4, 0xffc
-               xori    r5, r5, 0xffc
-               bnei    r5, _unaligned_ex2
-       _unaligned_ex1:
-               RESTORE_STATE;
-/* Another page must be accessed or physical address not in page table */
-               bri     unaligned_data_trap
-
-       _unaligned_ex2:
+       /* jump to high level unaligned handler */
+       RESTORE_STATE;
+       bri     unaligned_data_trap
 #endif
        andi    r6, r3, 0x3E0; /* Mask and extract the register operand */
        srl     r6, r6; /* r6 >> 5 */
@@ -450,45 +441,6 @@ _no_delayslot:
        srl     r6, r6;
        /* Store the register operand in a temporary location */
        sbi     r6, r0, TOPHYS(ex_reg_op);
-#ifdef CONFIG_MMU
-       /* Get physical address */
-       /* If we are faulting a kernel address, we have to use the
-        * kernel page tables.
-        */
-       ori     r5, r0, CONFIG_KERNEL_START
-       cmpu    r5, r4, r5
-       bgti    r5, _unaligned_ex3
-       ori     r5, r0, swapper_pg_dir
-       bri     _unaligned_ex4
-
-       /* Get the PGD for the current thread. */
-_unaligned_ex3: /* user thread */
-       addi    r5 ,CURRENT_TASK, TOPHYS(0); /* get current task address */
-       lwi     r5, r5, TASK_THREAD + PGDIR
-_unaligned_ex4:
-       tophys(r5,r5)
-       BSRLI(r6,r4,20)                 /* Create L1 (pgdir/pmd) address */
-       andi    r6, r6, 0xffc
-/* Assume pgdir aligned on 4K boundary, no need for "andi r5,r5,0xfffff003" */
-       or      r5, r5, r6
-       lwi     r6, r5, 0               /* Get L1 entry */
-       andi    r5, r6, 0xfffff000      /* Extract L2 (pte) base address. */
-       beqi    r5, _unaligned_ex1      /* Bail if no table */
-
-       tophys(r5,r5)
-       BSRLI(r6,r4,10)                 /* Compute PTE address */
-       andi    r6, r6, 0xffc
-       andi    r5, r5, 0xfffff003
-       or      r5, r5, r6
-       lwi     r5, r5, 0               /* Get Linux PTE */
-
-       andi    r6, r5, _PAGE_PRESENT
-       beqi    r6, _unaligned_ex1      /* Bail if no page */
-
-       andi    r5, r5, 0xfffff000      /* Extract RPN */
-       andi    r4, r4, 0x00000fff      /* Extract offset */
-       or      r4, r4, r5              /* Create physical address */
-#endif /* CONFIG_MMU */
 
        andi    r6, r3, 0x400; /* Extract ESR[S] */
        bnei    r6, ex_sw;
@@ -959,15 +911,15 @@ _unaligned_data_exception:
        andi    r6, r3, 0x800;  /* Extract ESR[W] - delay slot */
 ex_lw_vm:
        beqid   r6, ex_lhw_vm;
-       lbui    r5, r4, 0;      /* Exception address in r4 - delay slot */
+load1: lbui    r5, r4, 0;      /* Exception address in r4 - delay slot */
 /* Load a word, byte-by-byte from destination address and save it in tmp space*/
        la      r6, r0, ex_tmp_data_loc_0;
        sbi     r5, r6, 0;
-       lbui    r5, r4, 1;
+load2: lbui    r5, r4, 1;
        sbi     r5, r6, 1;
-       lbui    r5, r4, 2;
+load3: lbui    r5, r4, 2;
        sbi     r5, r6, 2;
-       lbui    r5, r4, 3;
+load4: lbui    r5, r4, 3;
        sbi     r5, r6, 3;
        brid    ex_lw_tail_vm;
 /* Get the destination register value into r3 - delay slot */
@@ -977,7 +929,7 @@ ex_lhw_vm:
         * save it in tmp space */
        la      r6, r0, ex_tmp_data_loc_0;
        sbi     r5, r6, 0;
-       lbui    r5, r4, 1;
+load5: lbui    r5, r4, 1;
        sbi     r5, r6, 1;
        lhui    r3, r6, 0;      /* Get the destination register value into r3 */
 ex_lw_tail_vm:
@@ -996,22 +948,53 @@ ex_sw_tail_vm:
        swi     r3, r5, 0;      /* Get the word - delay slot */
        /* Store the word, byte-by-byte into destination address */
        lbui    r3, r5, 0;
-       sbi     r3, r4, 0;
+store1:        sbi     r3, r4, 0;
        lbui    r3, r5, 1;
-       sbi     r3, r4, 1;
+store2:        sbi     r3, r4, 1;
        lbui    r3, r5, 2;
-       sbi     r3, r4, 2;
+store3:        sbi     r3, r4, 2;
        lbui    r3, r5, 3;
        brid    ret_from_exc;
-       sbi     r3, r4, 3;      /* Delay slot */
+store4:        sbi     r3, r4, 3;      /* Delay slot */
 ex_shw_vm:
        /* Store the lower half-word, byte-by-byte into destination address */
        lbui    r3, r5, 2;
-       sbi     r3, r4, 0;
+store5:        sbi     r3, r4, 0;
        lbui    r3, r5, 3;
        brid    ret_from_exc;
-       sbi     r3, r4, 1;      /* Delay slot */
+store6:        sbi     r3, r4, 1;      /* Delay slot */
 ex_sw_end_vm:                  /* Exception handling of store word, ends. */
+
+/* We have to prevent cases that get/put_user macros get unaligned pointer
+ * to bad page area. We have to find out which origin instruction caused it
+ * and called fixup for that origin instruction not instruction in unaligned
+ * handler */
+ex_unaligned_fixup:
+       ori     r5, r7, 0 /* setup pointer to pt_regs */
+       lwi     r6, r7, PT_PC; /* faulting address is one instruction above */
+       addik   r6, r6, -4 /* for finding proper fixup */
+       swi     r6, r7, PT_PC; /* a save back it to PT_PC */
+       addik   r7, r0, SIGSEGV
+       /* call bad_page_fault for finding aligned fixup, fixup address is saved
+        * in PT_PC which is used as return address from exception */
+       la      r15, r0, ret_from_exc-8 /* setup return address */
+       brid    bad_page_fault
+       nop
+
+/* We prevent all load/store because it could failed any attempt to access */
+.section __ex_table,"a";
+       .word   load1,ex_unaligned_fixup;
+       .word   load2,ex_unaligned_fixup;
+       .word   load3,ex_unaligned_fixup;
+       .word   load4,ex_unaligned_fixup;
+       .word   load5,ex_unaligned_fixup;
+       .word   store1,ex_unaligned_fixup;
+       .word   store2,ex_unaligned_fixup;
+       .word   store3,ex_unaligned_fixup;
+       .word   store4,ex_unaligned_fixup;
+       .word   store5,ex_unaligned_fixup;
+       .word   store6,ex_unaligned_fixup;
+.previous;
 .end _unaligned_data_exception
 #endif /* CONFIG_MMU */
 
index b15605299a57f448b57f0c9cb534cf511c796eb3..6eea6f92b84e19780b781bdad3da277fed57a4bb 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/irq.h>
 #include <asm/page.h>
 #include <linux/io.h>
+#include <linux/bug.h>
 
 #include <asm/prom.h>
 #include <asm/irq.h>
@@ -130,6 +131,7 @@ void __init init_IRQ(void)
                if (intc)
                        break;
        }
+       BUG_ON(!intc);
 
        intc_baseaddr = *(int *) of_get_property(intc, "reg", NULL);
        intc_baseaddr = (unsigned long) ioremap(intc_baseaddr, PAGE_SIZE);
index f688ee93e3b98747394f5630beff65501cfabc6e..7d5ddd62d4d23e6d9673a538e6e251bad4b10feb 100644 (file)
@@ -30,15 +30,6 @@ unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
 }
 EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
 
-/*
- * 'what should we do if we get a hw irq event on an illegal vector'.
- * each architecture has to answer this themselves.
- */
-void ack_bad_irq(unsigned int irq)
-{
-       printk(KERN_WARNING "unexpected IRQ trap at vector %02x\n", irq);
-}
-
 static u32 concurrent_irq;
 
 void do_IRQ(struct pt_regs *regs)
index 51414171326f4bb32010585d4cef295e9de8afc4..5a45b1adfef1c91f25b191d968238c95854ee674 100644 (file)
@@ -57,7 +57,6 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
        Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
        Elf32_Sym *sym;
        unsigned long int *location;
-       unsigned long int locoffs;
        unsigned long int value;
 #if __GNUC__ < 4
        unsigned long int old_value;
@@ -113,10 +112,12 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
                        break;
 
                case R_MICROBLAZE_64_PCREL:
-                       locoffs = (location[0] & 0xFFFF) << 16 |
+#if __GNUC__ < 4
+                       old_value = (location[0] & 0xFFFF) << 16 |
                                (location[1] & 0xFFFF);
-                       value -= (unsigned long int)(location) + 4 +
-                               locoffs;
+                       value -= old_value;
+#endif
+                       value -= (unsigned long int)(location) + 4;
                        location[0] = (location[0] & 0xFFFF0000) |
                                        (value >> 16);
                        location[1] = (location[1] & 0xFFFF0000) |
@@ -125,6 +126,14 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
                                value);
                        break;
 
+               case R_MICROBLAZE_32_PCREL_LO:
+                       pr_debug("R_MICROBLAZE_32_PCREL_LO\n");
+                       break;
+
+               case R_MICROBLAZE_64_NONE:
+                       pr_debug("R_MICROBLAZE_NONE\n");
+                       break;
+
                case R_MICROBLAZE_NONE:
                        pr_debug("R_MICROBLAZE_NONE\n");
                        break;
@@ -133,7 +142,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
                        printk(KERN_ERR "module %s: "
                                "Unknown relocation: %u\n",
                                module->name,
-                               ELF32_R_TYPE(rela->r_info));
+                               ELF32_R_TYPE(rela[i].r_info));
                        return -ENOEXEC;
                }
        }
index b86aa623e36d053f95c61de5533782c0d92a8bb2..53ff39af6a5c0eebfcf156dd02969d231896229d 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/ptrace.h>
 #include <linux/signal.h>
 
index 8709bea09604585958cd95d72c107c65d1396855..2a97bf513b64c691e81b4bd9867f537aefb6f606 100644 (file)
@@ -138,8 +138,12 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
        setup_early_printk(NULL);
 #endif
 
-       early_printk("Ramdisk addr 0x%08x, FDT 0x%08x\n", ram, fdt);
-       printk(KERN_NOTICE "Found FDT at 0x%08x\n", fdt);
+       early_printk("Ramdisk addr 0x%08x, ", ram);
+       if (fdt)
+               early_printk("FDT at 0x%08x\n", fdt);
+       else
+               early_printk("Compiled-in FDT at 0x%08x\n",
+                                       (unsigned int)_fdt_start);
 
 #ifdef CONFIG_MTD_UCLINUX
        early_printk("Found romfs @ 0x%08x (0x%08x)\n",
index 4c0e6521b1140e6d92183fb165b03076253a889d..1c80e4fc40cef1fc0513951c449452ff23139c96 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
 
 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
 
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-asmlinkage int
-sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs)
-{
-       sigset_t saveset;
-
-       mask &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
-       siginitset(&current->blocked, mask);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       regs->r3 = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(regs, &saveset, 1))
-                       return -EINTR;
-       }
-}
-
-asmlinkage int
-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
-               struct pt_regs *regs)
-{
-       sigset_t saveset, newset;
-
-       /* XXX: Don't preclude handling different sized sigset_t's. */
-       if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
-
-       if (copy_from_user(&newset, unewset, sizeof(newset)))
-               return -EFAULT;
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       regs->r3 = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(regs, &saveset, 1))
-                       return -EINTR;
-       }
-}
-
-asmlinkage int
-sys_sigaction(int sig, const struct old_sigaction *act,
-               struct old_sigaction *oact)
-{
-       struct k_sigaction new_ka, old_ka;
-       int ret;
-
-       if (act) {
-               old_sigset_t mask;
-               if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
-                       __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-                       __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
-                       return -EFAULT;
-               __get_user(new_ka.sa.sa_flags, &act->sa_flags);
-               __get_user(mask, &act->sa_mask);
-               siginitset(&new_ka.sa.sa_mask, mask);
-       }
 
-       ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
-
-       if (!ret && oact) {
-               if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
-                       __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-                       __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
-                       return -EFAULT;
-               __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-               __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
-       }
-
-       return ret;
-}
-
-asmlinkage int
+asmlinkage long
 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
                struct pt_regs *regs)
 {
@@ -139,7 +55,6 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
 /*
  * Do a signal return; undo the signal stack.
  */
-
 struct sigframe {
        struct sigcontext sc;
        unsigned long extramask[_NSIG_WORDS-1];
@@ -176,40 +91,7 @@ static int restore_sigcontext(struct pt_regs *regs,
        return err;
 }
 
-asmlinkage int sys_sigreturn(struct pt_regs *regs)
-{
-       struct sigframe *frame =
-                       (struct sigframe *)(regs->r1 + STATE_SAVE_ARG_SPACE);
-
-       sigset_t set;
-       int rval;
-
-       if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
-               goto badframe;
-
-       if (__get_user(set.sig[0], &frame->sc.oldmask)
-               || (_NSIG_WORDS > 1
-               && __copy_from_user(&set.sig[1], &frame->extramask,
-                                       sizeof(frame->extramask))))
-               goto badframe;
-
-       sigdelsetmask(&set, ~_BLOCKABLE);
-
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       if (restore_sigcontext(regs, &frame->sc, &rval))
-               goto badframe;
-       return rval;
-
-badframe:
-       force_sig(SIGSEGV, current);
-       return 0;
-}
-
-asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
 {
        struct rt_sigframe __user *frame =
                (struct rt_sigframe __user *)(regs->r1 + STATE_SAVE_ARG_SPACE);
@@ -324,21 +206,17 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        /* Set up to return from userspace. If provided, use a stub
         already in userspace. */
        /* minus 8 is offset to cater for "rtsd r15,8" */
-       if (ka->sa.sa_flags & SA_RESTORER) {
-               regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8;
-       } else {
-               /* addi r12, r0, __NR_sigreturn */
-               err |= __put_user(0x31800000 | __NR_rt_sigreturn ,
-                               frame->tramp + 0);
-               /* brki r14, 0x8 */
-               err |= __put_user(0xb9cc0008, frame->tramp + 1);
-
-               /* Return from sighandler will jump to the tramp.
-                Negative 8 offset because return is rtsd r15, 8 */
-               regs->r15 = ((unsigned long)frame->tramp)-8;
-
-               __invalidate_cache_sigtramp((unsigned long)frame->tramp);
-       }
+       /* addi r12, r0, __NR_sigreturn */
+       err |= __put_user(0x31800000 | __NR_rt_sigreturn ,
+                       frame->tramp + 0);
+       /* brki r14, 0x8 */
+       err |= __put_user(0xb9cc0008, frame->tramp + 1);
+
+       /* Return from sighandler will jump to the tramp.
+        Negative 8 offset because return is rtsd r15, 8 */
+       regs->r15 = ((unsigned long)frame->tramp)-8;
+
+       __invalidate_cache_sigtramp((unsigned long)frame->tramp);
 
        if (err)
                goto give_sigsegv;
@@ -405,7 +283,7 @@ do_restart:
  * OK, we're invoking a handler
  */
 
-static void
+static int
 handle_signal(unsigned long sig, struct k_sigaction *ka,
                siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
 {
@@ -426,6 +304,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
                recalc_sigpending();
                spin_unlock_irq(&current->sighand->siglock);
        }
+       return 1;
 }
 
 /*
@@ -456,7 +335,9 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
        if (kernel_mode(regs))
                return 1;
 
-       if (!oldset)
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
+               oldset = &current->saved_sigmask;
+       else
                oldset = &current->blocked;
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
@@ -464,13 +345,31 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
                /* Whee! Actually deliver the signal. */
                if (in_syscall)
                        handle_restart(regs, &ka, 1);
-               handle_signal(signr, &ka, &info, oldset, regs);
+               if (handle_signal(signr, &ka, &info, oldset, regs)) {
+                       /*
+                        * A signal was successfully delivered; the saved
+                        * sigmask will have been stored in the signal frame,
+                        * and will be restored by sigreturn, so we can simply
+                        * clear the TS_RESTORE_SIGMASK flag.
+                        */
+                       current_thread_info()->status &=
+                           ~TS_RESTORE_SIGMASK;
+               }
                return 1;
        }
 
        if (in_syscall)
                handle_restart(regs, NULL, 0);
 
+       /*
+        * If there's no signal to deliver, we just put the saved sigmask
+        * back.
+        */
+       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
+               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+       }
+
        /* Did we come from a system call? */
        return 0;
 }
index 31905ff590b704db07206f1d11d7acc84386d9ea..b96f1682bb24800d8c89316ad18007e27a45ca55 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/unistd.h>
 
 #include <asm/syscalls.h>
-/*
- * sys_ipc() is the de-multiplexer for the SysV IPC calls..
- *
- * This is really horribly ugly. This will be remove with new toolchain.
- */
-asmlinkage int
-sys_ipc(uint call, int first, int second, int third, void *ptr, long fifth)
-{
-       int version, ret;
-
-       version = call >> 16; /* hack for backward compatibility */
-       call &= 0xffff;
-
-       ret = -EINVAL;
-       switch (call) {
-       case SEMOP:
-               ret = sys_semop(first, (struct sembuf *)ptr, second);
-               break;
-       case SEMGET:
-               ret = sys_semget(first, second, third);
-               break;
-       case SEMCTL:
-       {
-               union semun fourth;
-
-               if (!ptr)
-                       break;
-               ret = (access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT)
-                               || (get_user(fourth.__pad, (void **)ptr)) ;
-               if (ret)
-                       break;
-               ret = sys_semctl(first, second, third, fourth);
-               break;
-       }
-       case MSGSND:
-               ret = sys_msgsnd(first, (struct msgbuf *) ptr, second, third);
-               break;
-       case MSGRCV:
-               switch (version) {
-               case 0: {
-                       struct ipc_kludge tmp;
-
-                       if (!ptr)
-                               break;
-                       ret = (access_ok(VERIFY_READ, ptr, sizeof(tmp))
-                               ? 0 : -EFAULT) || copy_from_user(&tmp,
-                               (struct ipc_kludge *) ptr, sizeof(tmp));
-                       if (ret)
-                               break;
-                       ret = sys_msgrcv(first, tmp.msgp, second, tmp.msgtyp,
-                                       third);
-                       break;
-                       }
-               default:
-                       ret = sys_msgrcv(first, (struct msgbuf *) ptr,
-                                       second, fifth, third);
-                       break;
-               }
-               break;
-       case MSGGET:
-               ret = sys_msgget((key_t) first, second);
-               break;
-       case MSGCTL:
-               ret = sys_msgctl(first, second, (struct msqid_ds *) ptr);
-               break;
-       case SHMAT:
-               switch (version) {
-               default: {
-                       ulong raddr;
-                       ret = access_ok(VERIFY_WRITE, (ulong *) third,
-                                       sizeof(ulong)) ? 0 : -EFAULT;
-                       if (ret)
-                               break;
-                       ret = do_shmat(first, (char *) ptr, second, &raddr);
-                       if (ret)
-                               break;
-                       ret = put_user(raddr, (ulong *) third);
-                       break;
-                       }
-               case 1: /* iBCS2 emulator entry point */
-                       if (!segment_eq(get_fs(), get_ds()))
-                               break;
-                       ret = do_shmat(first, (char *) ptr, second,
-                                       (ulong *) third);
-                       break;
-               }
-               break;
-       case SHMDT:
-               ret = sys_shmdt((char *)ptr);
-               break;
-       case SHMGET:
-               ret = sys_shmget(first, second, third);
-               break;
-       case SHMCTL:
-               ret = sys_shmctl(first, second, (struct shmid_ds *) ptr);
-               break;
-       }
-       return ret;
-}
 
-asmlinkage int sys_vfork(struct pt_regs *regs)
+asmlinkage long microblaze_vfork(struct pt_regs *regs)
 {
        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r1,
                                                regs, 0, NULL, NULL);
 }
 
-asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs)
+asmlinkage long microblaze_clone(int flags, unsigned long stack, struct pt_regs *regs)
 {
        if (!stack)
                stack = regs->r1;
        return do_fork(flags, stack, regs, 0, NULL, NULL);
 }
 
-asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv,
+asmlinkage long microblaze_execve(char __user *filenamei, char __user *__user *argv,
                        char __user *__user *envp, struct pt_regs *regs)
 {
        int error;
@@ -163,8 +63,8 @@ out:
        return error;
 }
 
-asmlinkage unsigned long
-sys_mmap2(unsigned long addr, size_t len,
+asmlinkage long
+sys_mmap2(unsigned long addr, unsigned long len,
        unsigned long prot, unsigned long flags,
        unsigned long fd, unsigned long pgoff)
 {
@@ -189,18 +89,18 @@ out:
        return ret;
 }
 
-asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
+asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
                        unsigned long prot, unsigned long flags,
-                       unsigned long fd, off_t offset)
+                       unsigned long fd, off_t pgoff)
 {
        int err = -EINVAL;
 
-       if (offset & ~PAGE_MASK) {
+       if (pgoff & ~PAGE_MASK) {
                printk(KERN_INFO "no pagemask in mmap\r\n");
                goto out;
        }
 
-       err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+       err = sys_mmap2(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);
 out:
        return err;
 }
index 376d1789f7c065e436fdf39d7b3e2f8f2318494f..457216097dfdda2f6cb9f5d07fed6bab53bf80b6 100644 (file)
@@ -15,7 +15,7 @@ ENTRY(sys_call_table)
        .long sys_creat
        .long sys_link
        .long sys_unlink                /* 10 */
-       .long sys_execve_wrapper
+       .long sys_execve
        .long sys_chdir
        .long sys_time
        .long sys_mknod
@@ -71,12 +71,12 @@ ENTRY(sys_call_table)
        .long sys_getppid
        .long sys_getpgrp               /* 65 */
        .long sys_setsid
-       .long sys_sigaction
+       .long sys_ni_syscall            /* sys_sigaction */
        .long sys_sgetmask
        .long sys_ssetmask
        .long sys_setreuid              /* 70 */
        .long sys_setregid
-       .long sys_sigsuspend_wrapper
+       .long sys_ni_syscall            /* sys_sigsuspend_wrapper */
        .long sys_sigpending
        .long sys_sethostname
        .long sys_setrlimit             /* 75 */
@@ -121,10 +121,10 @@ ENTRY(sys_call_table)
        .long sys_wait4
        .long sys_swapoff               /* 115 */
        .long sys_sysinfo
-       .long sys_ipc
+       .long sys_ni_syscall            /* old sys_ipc */
        .long sys_fsync
-       .long sys_sigreturn_wrapper
-       .long sys_clone_wrapper         /* 120 */
+       .long sys_ni_syscall            /* sys_sigreturn_wrapper */
+       .long sys_clone         /* 120 */
        .long sys_setdomainname
        .long sys_newuname
        .long sys_ni_syscall            /* modify_ldt */
@@ -194,7 +194,7 @@ ENTRY(sys_call_table)
        .long sys_sendfile
        .long sys_ni_syscall            /* reserved for streams1 */
        .long sys_ni_syscall            /* reserved for streams2 */
-       .long sys_vfork_wrapper         /* 190 */
+       .long sys_vfork         /* 190 */
        .long sys_getrlimit
        .long sys_mmap2                 /* mmap2 */
        .long sys_truncate64
@@ -313,7 +313,7 @@ ENTRY(sys_call_table)
        .long sys_fchmodat
        .long sys_faccessat
        .long sys_ni_syscall /* pselect6 */
-       .long sys_ni_syscall /* sys_ppoll */
+       .long sys_ppoll
        .long sys_unshare               /* 310 */
        .long sys_set_robust_list
        .long sys_get_robust_list
@@ -369,3 +369,5 @@ ENTRY(sys_call_table)
        .long sys_ni_syscall
        .long sys_ni_syscall
        .long sys_ni_syscall
+       .long sys_rt_tgsigqueueinfo     /* 365 */
+       .long sys_perf_counter_open
index bdfa2f9f0c8125f0d6e288f3b85d54b02dee2b4e..5499deae7fa68cb155e4e6aefe9b53c0da8c7298 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/io.h>
+#include <linux/bug.h>
 #include <asm/cpuinfo.h>
 #include <asm/setup.h>
 #include <asm/prom.h>
@@ -234,6 +235,7 @@ void __init time_init(void)
                if (timer)
                        break;
        }
+       BUG_ON(!timer);
 
        timer_baseaddr = *(int *) of_get_property(timer, "reg", NULL);
        timer_baseaddr = (unsigned long) ioremap(timer_baseaddr, PAGE_SIZE);
index 71c8cb6c9e43767a4ebd43f9e4c54d3e9820928b..b579db068c06fd3346a1458879145ef8f50063b3 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile
 #
 
-lib-y :=  memset.o checksum.o
+lib-y :=  memset.o
 
 ifeq ($(CONFIG_OPT_LIB_ASM),y)
 lib-y += fastcopy.o
diff --git a/arch/microblaze/lib/checksum.c b/arch/microblaze/lib/checksum.c
deleted file mode 100644 (file)
index f08e745..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- *
- * INET                An implementation of the TCP/IP protocol suite for the LINUX
- *             operating system.  INET is implemented using the  BSD Socket
- *             interface as the means of communication with the user level.
- *
- *             IP/TCP/UDP checksumming routines
- *
- * Authors:    Jorge Cwik, <jorge@laser.satlink.net>
- *             Arnt Gulbrandsen, <agulbra@nvg.unit.no>
- *             Tom May, <ftom@netcom.com>
- *             Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
- *             Lots of code moved from tcp.c and ip.c; see those files
- *             for more names.
- *
- * 03/02/96    Jes Sorensen, Andreas Schwab, Roman Hodek:
- *             Fixed some nasty bugs, causing some horrible crashes.
- *             A: At some points, the sum (%0) was used as
- *             length-counter instead of the length counter
- *             (%1). Thanks to Roman Hodek for pointing this out.
- *             B: GCC seems to mess up if one uses too many
- *             data-registers to hold input values and one tries to
- *             specify d0 and d1 as scratch registers. Letting gcc
- *             choose these registers itself solves the problem.
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- */
-
-/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access
- kills, so most of the assembly has to go. */
-
-#include <linux/module.h>
-#include <net/checksum.h>
-
-#include <asm/byteorder.h>
-
-static inline unsigned short from32to16(unsigned long x)
-{
-       /* add up 16-bit and 16-bit for 16+c bit */
-       x = (x & 0xffff) + (x >> 16);
-       /* add up carry.. */
-       x = (x & 0xffff) + (x >> 16);
-       return x;
-}
-
-static unsigned int do_csum(const unsigned char *buff, int len)
-{
-       int odd, count;
-       unsigned long result = 0;
-
-       if (len <= 0)
-               goto out;
-       odd = 1 & (unsigned long) buff;
-       if (odd) {
-               result = *buff;
-               len--;
-               buff++;
-       }
-       count = len >> 1;               /* nr of 16-bit words.. */
-       if (count) {
-               if (2 & (unsigned long) buff) {
-                       result += *(unsigned short *) buff;
-                       count--;
-                       len -= 2;
-                       buff += 2;
-               }
-               count >>= 1;            /* nr of 32-bit words.. */
-               if (count) {
-                       unsigned long carry = 0;
-                       do {
-                               unsigned long w = *(unsigned long *) buff;
-                               count--;
-                               buff += 4;
-                               result += carry;
-                               result += w;
-                               carry = (w > result);
-                       } while (count);
-                       result += carry;
-                       result = (result & 0xffff) + (result >> 16);
-               }
-               if (len & 2) {
-                       result += *(unsigned short *) buff;
-                       buff += 2;
-               }
-       }
-       if (len & 1)
-               result += (*buff << 8);
-       result = from32to16(result);
-       if (odd)
-               result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
-out:
-       return result;
-}
-
-/*
- *     This is a version of ip_compute_csum() optimized for IP headers,
- *     which always checksum on 4 octet boundaries.
- */
-__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
-{
-       return (__force __sum16)~do_csum(iph, ihl*4);
-}
-EXPORT_SYMBOL(ip_fast_csum);
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-__wsum csum_partial(const void *buff, int len, __wsum wsum)
-{
-       unsigned int sum = (__force unsigned int)wsum;
-       unsigned int result = do_csum(buff, len);
-
-       /* add in old sum, and carry.. */
-       result += sum;
-       if (sum > result)
-               result += 1;
-       return (__force __wsum)result;
-}
-EXPORT_SYMBOL(csum_partial);
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-__sum16 ip_compute_csum(const void *buff, int len)
-{
-       return (__force __sum16)~do_csum(buff, len);
-}
-EXPORT_SYMBOL(ip_compute_csum);
-
-/*
- * copy from fs while checksumming, otherwise like csum_partial
- */
-__wsum
-csum_partial_copy_from_user(const void __user *src, void *dst, int len,
-                                               __wsum sum, int *csum_err)
-{
-       int missing;
-
-       missing = __copy_from_user(dst, src, len);
-       if (missing) {
-               memset(dst + len - missing, 0, missing);
-               *csum_err = -EFAULT;
-       } else
-               *csum_err = 0;
-
-       return csum_partial(dst, len, sum);
-}
-EXPORT_SYMBOL(csum_partial_copy_from_user);
-
-/*
- * copy from ds while checksumming, otherwise like csum_partial
- */
-__wsum
-csum_partial_copy(const void *src, void *dst, int len, __wsum sum)
-{
-       memcpy(dst, src, len);
-       return csum_partial(dst, len, sum);
-}
-EXPORT_SYMBOL(csum_partial_copy);
index 956607a63f4c21327b1b1d749031cbbd7510ee58..d9d249a66ff2eda43688483cb1cab0aba3434de9 100644 (file)
@@ -69,7 +69,7 @@ static int store_updates_sp(struct pt_regs *regs)
  * It is called from do_page_fault above and from some of the procedures
  * in traps.c.
  */
-static void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
+void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
 {
        const struct exception_table_entry *fixup;
 /* MS: no context */
@@ -122,15 +122,10 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
        }
 #endif /* CONFIG_KGDB */
 
-       if (in_atomic() || mm == NULL) {
-               /* FIXME */
-               if (kernel_mode(regs)) {
-                       printk(KERN_EMERG
-                               "Page fault in kernel mode - Oooou!!! pid %d\n",
-                               current->pid);
-                       _exception(SIGSEGV, regs, code, address);
-                       return;
-               }
+       if (in_atomic() || !mm) {
+               if (kernel_mode(regs))
+                       goto bad_area_nosemaphore;
+
                /* in_atomic() in user mode is really bad,
                   as is current->mm == NULL. */
                printk(KERN_EMERG "Page fault in user mode with "
index b5a701cd71e08d86ceec067f011c98b4abe0f419..f207f1a94dbcd0d627ca8ab94668dbf791fef847 100644 (file)
@@ -80,15 +80,15 @@ void __init setup_memory(void)
                        memory_size = memory_end - memory_start;
                        PAGE_OFFSET = memory_start;
                        printk(KERN_INFO "%s: Main mem: 0x%x-0x%x, "
-                               "size 0x%08x\n", __func__, memory_start,
-                                               memory_end, memory_size);
+                               "size 0x%08x\n", __func__, (u32) memory_start,
+                                       (u32) memory_end, (u32) memory_size);
                        break;
                }
        }
 
        if (!memory_start || !memory_end) {
                panic("%s: Missing memory setting 0x%08x-0x%08x\n",
-                       __func__, memory_start, memory_end);
+                       __func__, (u32) memory_start, (u32) memory_end);
        }
 
        /* reservation of region where is the kernel */
@@ -130,13 +130,13 @@ void __init setup_memory(void)
         * (in case the address isn't page-aligned).
         */
 #ifndef CONFIG_MMU
-       map_size = init_bootmem_node(NODE_DATA(0), PFN_UP(TOPHYS((u32)_end)),
+       map_size = init_bootmem_node(NODE_DATA(0), PFN_UP(TOPHYS((u32)klimit)),
                                        min_low_pfn, max_low_pfn);
 #else
        map_size = init_bootmem_node(&contig_page_data,
-               PFN_UP(TOPHYS((u32)_end)), min_low_pfn, max_low_pfn);
+               PFN_UP(TOPHYS((u32)klimit)), min_low_pfn, max_low_pfn);
 #endif
-       lmb_reserve(PFN_UP(TOPHYS((u32)_end)) << PAGE_SHIFT, map_size);
+       lmb_reserve(PFN_UP(TOPHYS((u32)klimit)) << PAGE_SHIFT, map_size);
 
        /* free bootmem is whole main memory */
        free_bootmem(memory_start, memory_size);
index 8c4be1f301cf2f9b1310eae61502ebd33b5391f1..3ca0fe1a91231441d9767fdcd56a9caafe203c83 100644 (file)
@@ -22,6 +22,26 @@ choice
 config MACH_ALCHEMY
        bool "Alchemy processor based machines"
 
+config AR7
+       bool "Texas Instruments AR7"
+       select BOOT_ELF32
+       select DMA_NONCOHERENT
+       select CEVT_R4K
+       select CSRC_R4K
+       select IRQ_CPU
+       select NO_EXCEPT_FILL
+       select SWAP_IO_SPACE
+       select SYS_HAS_CPU_MIPS32_R1
+       select SYS_HAS_EARLY_PRINTK
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_LITTLE_ENDIAN
+       select GENERIC_GPIO
+       select GCD
+       select VLYNQ
+       help
+         Support for the Texas Instruments AR7 System-on-a-Chip
+         family: TNETD7100, 7200 and 7300.
+
 config BASLER_EXCITE
        bool "Basler eXcite smart camera"
        select CEVT_R4K
@@ -209,7 +229,7 @@ config MIPS_MALTA
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
        select SYS_SUPPORTS_LITTLE_ENDIAN
-       select SYS_SUPPORTS_MIPS_CMP if BROKEN  # because SYNC_R4K is broken
+       select SYS_SUPPORTS_MIPS_CMP
        select SYS_SUPPORTS_MULTITHREADING
        select SYS_SUPPORTS_SMARTMIPS
        help
@@ -247,6 +267,7 @@ config MACH_VR41XX
        select CEVT_R4K
        select CSRC_R4K
        select SYS_HAS_CPU_VR41XX
+       select ARCH_REQUIRE_GPIOLIB
 
 config NXP_STB220
        bool "NXP STB220 board"
@@ -1635,7 +1656,7 @@ config MIPS_APSP_KSPD
 config MIPS_CMP
        bool "MIPS CMP framework support"
        depends on SYS_SUPPORTS_MIPS_CMP
-       select SYNC_R4K if BROKEN
+       select SYNC_R4K
        select SYS_SUPPORTS_SMP
        select SYS_SUPPORTS_SCHED_SMT if SMP
        select WEAK_ORDERING
@@ -2147,11 +2168,11 @@ menu "Power management options"
 
 config ARCH_HIBERNATION_POSSIBLE
        def_bool y
-       depends on SYS_SUPPORTS_HOTPLUG_CPU
+       depends on SYS_SUPPORTS_HOTPLUG_CPU || !SMP
 
 config ARCH_SUSPEND_POSSIBLE
        def_bool y
-       depends on SYS_SUPPORTS_HOTPLUG_CPU
+       depends on SYS_SUPPORTS_HOTPLUG_CPU || !SMP
 
 source "kernel/power/Kconfig"
 
index 807572a6a4d2df80335ee2334518c9ae5726841f..861da514a468a7cf84bdb0d32cd703921f7853e0 100644 (file)
@@ -172,6 +172,13 @@ libs-y                             += arch/mips/fw/lib/
 # Board-dependent options and extra files
 #
 
+#
+# Texas Instruments AR7
+#
+core-$(CONFIG_AR7)             += arch/mips/ar7/
+cflags-$(CONFIG_AR7)           += -I$(srctree)/arch/mips/include/asm/mach-ar7
+load-$(CONFIG_AR7)             += 0xffffffff94100000
+
 #
 # Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
 #
index 8b5914d1241fe5fb4b67d0150fb5135a3f0d2a75..e30e42add697ef728d0180cd0ea25d9414ee53d2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * MTX-1 platform devices registration
  *
- * Copyright (C) 2007, Florian Fainelli <florian@openwrt.org>
+ * Copyright (C) 2007-2009, Florian Fainelli <florian@openwrt.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
@@ -142,7 +142,17 @@ static struct __initdata platform_device * mtx1_devs[] = {
 
 static int __init mtx1_register_devices(void)
 {
-       gpio_direction_input(207);
+       int rc;
+
+       rc = gpio_request(mtx1_gpio_button[0].gpio,
+                                       mtx1_gpio_button[0].desc);
+       if (rc < 0) {
+               printk(KERN_INFO "mtx1: failed to request %d\n",
+                                       mtx1_gpio_button[0].gpio);
+               goto out;
+       }
+       gpio_direction_input(mtx1_gpio_button[0].gpio);
+out:
        return platform_add_devices(mtx1_devs, ARRAY_SIZE(mtx1_devs));
 }
 
diff --git a/arch/mips/ar7/Makefile b/arch/mips/ar7/Makefile
new file mode 100644 (file)
index 0000000..26bc5da
--- /dev/null
@@ -0,0 +1,11 @@
+
+obj-y := \
+       prom.o \
+       setup.o \
+       memory.o \
+       irq.o \
+       time.o \
+       platform.o \
+       gpio.o \
+       clock.o
+EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/ar7/clock.c b/arch/mips/ar7/clock.c
new file mode 100644 (file)
index 0000000..cc65c8e
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/gcd.h>
+#include <linux/io.h>
+
+#include <asm/addrspace.h>
+#include <asm/mach-ar7/ar7.h>
+
+#define BOOT_PLL_SOURCE_MASK   0x3
+#define CPU_PLL_SOURCE_SHIFT   16
+#define BUS_PLL_SOURCE_SHIFT   14
+#define USB_PLL_SOURCE_SHIFT   18
+#define DSP_PLL_SOURCE_SHIFT   22
+#define BOOT_PLL_SOURCE_AFE    0
+#define BOOT_PLL_SOURCE_BUS    0
+#define BOOT_PLL_SOURCE_REF    1
+#define BOOT_PLL_SOURCE_XTAL   2
+#define BOOT_PLL_SOURCE_CPU    3
+#define BOOT_PLL_BYPASS                0x00000020
+#define BOOT_PLL_ASYNC_MODE    0x02000000
+#define BOOT_PLL_2TO1_MODE     0x00008000
+
+#define TNETD7200_CLOCK_ID_CPU 0
+#define TNETD7200_CLOCK_ID_DSP 1
+#define TNETD7200_CLOCK_ID_USB 2
+
+#define TNETD7200_DEF_CPU_CLK  211000000
+#define TNETD7200_DEF_DSP_CLK  125000000
+#define TNETD7200_DEF_USB_CLK  48000000
+
+struct tnetd7300_clock {
+       u32 ctrl;
+#define PREDIV_MASK    0x001f0000
+#define PREDIV_SHIFT   16
+#define POSTDIV_MASK   0x0000001f
+       u32 unused1[3];
+       u32 pll;
+#define MUL_MASK       0x0000f000
+#define MUL_SHIFT      12
+#define PLL_MODE_MASK  0x00000001
+#define PLL_NDIV       0x00000800
+#define PLL_DIV                0x00000002
+#define PLL_STATUS     0x00000001
+       u32 unused2[3];
+};
+
+struct tnetd7300_clocks {
+       struct tnetd7300_clock bus;
+       struct tnetd7300_clock cpu;
+       struct tnetd7300_clock usb;
+       struct tnetd7300_clock dsp;
+};
+
+struct tnetd7200_clock {
+       u32 ctrl;
+       u32 unused1[3];
+#define DIVISOR_ENABLE_MASK 0x00008000
+       u32 mul;
+       u32 prediv;
+       u32 postdiv;
+       u32 postdiv2;
+       u32 unused2[6];
+       u32 cmd;
+       u32 status;
+       u32 cmden;
+       u32 padding[15];
+};
+
+struct tnetd7200_clocks {
+       struct tnetd7200_clock cpu;
+       struct tnetd7200_clock dsp;
+       struct tnetd7200_clock usb;
+};
+
+int ar7_cpu_clock = 150000000;
+EXPORT_SYMBOL(ar7_cpu_clock);
+int ar7_bus_clock = 125000000;
+EXPORT_SYMBOL(ar7_bus_clock);
+int ar7_dsp_clock;
+EXPORT_SYMBOL(ar7_dsp_clock);
+
+static void approximate(int base, int target, int *prediv,
+                       int *postdiv, int *mul)
+{
+       int i, j, k, freq, res = target;
+       for (i = 1; i <= 16; i++)
+               for (j = 1; j <= 32; j++)
+                       for (k = 1; k <= 32; k++) {
+                               freq = abs(base / j * i / k - target);
+                               if (freq < res) {
+                                       res = freq;
+                                       *mul = i;
+                                       *prediv = j;
+                                       *postdiv = k;
+                               }
+                       }
+}
+
+static void calculate(int base, int target, int *prediv, int *postdiv,
+       int *mul)
+{
+       int tmp_gcd, tmp_base, tmp_freq;
+
+       for (*prediv = 1; *prediv <= 32; (*prediv)++) {
+               tmp_base = base / *prediv;
+               tmp_gcd = gcd(target, tmp_base);
+               *mul = target / tmp_gcd;
+               *postdiv = tmp_base / tmp_gcd;
+               if ((*mul < 1) || (*mul >= 16))
+                       continue;
+               if ((*postdiv > 0) & (*postdiv <= 32))
+                       break;
+       }
+
+       if (base / *prediv * *mul / *postdiv != target) {
+               approximate(base, target, prediv, postdiv, mul);
+               tmp_freq = base / *prediv * *mul / *postdiv;
+               printk(KERN_WARNING
+                      "Adjusted requested frequency %d to %d\n",
+                      target, tmp_freq);
+       }
+
+       printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n",
+              *prediv, *postdiv, *mul);
+}
+
+static int tnetd7300_dsp_clock(void)
+{
+       u32 didr1, didr2;
+       u8 rev = ar7_chip_rev();
+       didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18));
+       didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c));
+       if (didr2 & (1 << 23))
+               return 0;
+       if ((rev >= 0x23) && (rev != 0x57))
+               return 250000000;
+       if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22))
+           > 4208000)
+               return 250000000;
+       return 0;
+}
+
+static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock,
+       u32 *bootcr, u32 bus_clock)
+{
+       int product;
+       int base_clock = AR7_REF_CLOCK;
+       u32 ctrl = readl(&clock->ctrl);
+       u32 pll = readl(&clock->pll);
+       int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1;
+       int postdiv = (ctrl & POSTDIV_MASK) + 1;
+       int divisor = prediv * postdiv;
+       int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1;
+
+       switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
+       case BOOT_PLL_SOURCE_BUS:
+               base_clock = bus_clock;
+               break;
+       case BOOT_PLL_SOURCE_REF:
+               base_clock = AR7_REF_CLOCK;
+               break;
+       case BOOT_PLL_SOURCE_XTAL:
+               base_clock = AR7_XTAL_CLOCK;
+               break;
+       case BOOT_PLL_SOURCE_CPU:
+               base_clock = ar7_cpu_clock;
+               break;
+       }
+
+       if (*bootcr & BOOT_PLL_BYPASS)
+               return base_clock / divisor;
+
+       if ((pll & PLL_MODE_MASK) == 0)
+               return (base_clock >> (mul / 16 + 1)) / divisor;
+
+       if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) {
+               product = (mul & 1) ?
+                       (base_clock * mul) >> 1 :
+                       (base_clock * (mul - 1)) >> 2;
+               return product / divisor;
+       }
+
+       if (mul == 16)
+               return base_clock / divisor;
+
+       return base_clock * mul / divisor;
+}
+
+static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
+       u32 *bootcr, u32 frequency)
+{
+       int prediv, postdiv, mul;
+       int base_clock = ar7_bus_clock;
+
+       switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) {
+       case BOOT_PLL_SOURCE_BUS:
+               base_clock = ar7_bus_clock;
+               break;
+       case BOOT_PLL_SOURCE_REF:
+               base_clock = AR7_REF_CLOCK;
+               break;
+       case BOOT_PLL_SOURCE_XTAL:
+               base_clock = AR7_XTAL_CLOCK;
+               break;
+       case BOOT_PLL_SOURCE_CPU:
+               base_clock = ar7_cpu_clock;
+               break;
+       }
+
+       calculate(base_clock, frequency, &prediv, &postdiv, &mul);
+
+       writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
+       msleep(1);
+       writel(4, &clock->pll);
+       while (readl(&clock->pll) & PLL_STATUS)
+               ;
+       writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
+       msleep(75);
+}
+
+static void __init tnetd7300_init_clocks(void)
+{
+       u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
+       struct tnetd7300_clocks *clocks =
+                                       ioremap_nocache(UR8_REGS_CLOCKS,
+                                       sizeof(struct tnetd7300_clocks));
+
+       ar7_bus_clock = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT,
+               &clocks->bus, bootcr, AR7_AFE_CLOCK);
+
+       if (*bootcr & BOOT_PLL_ASYNC_MODE)
+               ar7_cpu_clock = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT,
+                       &clocks->cpu, bootcr, AR7_AFE_CLOCK);
+       else
+               ar7_cpu_clock = ar7_bus_clock;
+
+       if (ar7_dsp_clock == 250000000)
+               tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp,
+                       bootcr, ar7_dsp_clock);
+
+       iounmap(clocks);
+       iounmap(bootcr);
+}
+
+static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock,
+       int prediv, int postdiv, int postdiv2, int mul, u32 frequency)
+{
+       printk(KERN_INFO
+               "Clocks: base = %d, frequency = %u, prediv = %d, "
+               "postdiv = %d, postdiv2 = %d, mul = %d\n",
+               base, frequency, prediv, postdiv, postdiv2, mul);
+
+       writel(0, &clock->ctrl);
+       writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv);
+       writel((mul - 1) & 0xF, &clock->mul);
+
+       while (readl(&clock->status) & 0x1)
+               ; /* nop */
+
+       writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv);
+
+       writel(readl(&clock->cmden) | 1, &clock->cmden);
+       writel(readl(&clock->cmd) | 1, &clock->cmd);
+
+       while (readl(&clock->status) & 0x1)
+               ; /* nop */
+
+       writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2);
+
+       writel(readl(&clock->cmden) | 1, &clock->cmden);
+       writel(readl(&clock->cmd) | 1, &clock->cmd);
+
+       while (readl(&clock->status) & 0x1)
+               ; /* nop */
+
+       writel(readl(&clock->ctrl) | 1, &clock->ctrl);
+}
+
+static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr)
+{
+       if (*bootcr & BOOT_PLL_ASYNC_MODE)
+               /* Async */
+               switch (clock_id) {
+               case TNETD7200_CLOCK_ID_DSP:
+                       return AR7_REF_CLOCK;
+               default:
+                       return AR7_AFE_CLOCK;
+               }
+       else
+               /* Sync */
+               if (*bootcr & BOOT_PLL_2TO1_MODE)
+                       /* 2:1 */
+                       switch (clock_id) {
+                       case TNETD7200_CLOCK_ID_DSP:
+                               return AR7_REF_CLOCK;
+                       default:
+                               return AR7_AFE_CLOCK;
+                       }
+               else
+                       /* 1:1 */
+                       return AR7_REF_CLOCK;
+}
+
+
+static void __init tnetd7200_init_clocks(void)
+{
+       u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4);
+       struct tnetd7200_clocks *clocks =
+                                       ioremap_nocache(AR7_REGS_CLOCKS,
+                                       sizeof(struct tnetd7200_clocks));
+       int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv;
+       int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv;
+       int usb_base, usb_mul, usb_prediv, usb_postdiv;
+
+       cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr);
+       dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr);
+
+       if (*bootcr & BOOT_PLL_ASYNC_MODE) {
+               printk(KERN_INFO "Clocks: Async mode\n");
+
+               printk(KERN_INFO "Clocks: Setting DSP clock\n");
+               calculate(dsp_base, TNETD7200_DEF_DSP_CLK,
+                       &dsp_prediv, &dsp_postdiv, &dsp_mul);
+               ar7_bus_clock =
+                       ((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv;
+               tnetd7200_set_clock(dsp_base, &clocks->dsp,
+                       dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2,
+                       ar7_bus_clock);
+
+               printk(KERN_INFO "Clocks: Setting CPU clock\n");
+               calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
+                       &cpu_postdiv, &cpu_mul);
+               ar7_cpu_clock =
+                       ((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv;
+               tnetd7200_set_clock(cpu_base, &clocks->cpu,
+                       cpu_prediv, cpu_postdiv, -1, cpu_mul,
+                       ar7_cpu_clock);
+
+       } else
+               if (*bootcr & BOOT_PLL_2TO1_MODE) {
+                       printk(KERN_INFO "Clocks: Sync 2:1 mode\n");
+
+                       printk(KERN_INFO "Clocks: Setting CPU clock\n");
+                       calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv,
+                               &cpu_postdiv, &cpu_mul);
+                       ar7_cpu_clock = ((cpu_base / cpu_prediv) * cpu_mul)
+                                                               / cpu_postdiv;
+                       tnetd7200_set_clock(cpu_base, &clocks->cpu,
+                               cpu_prediv, cpu_postdiv, -1, cpu_mul,
+                               ar7_cpu_clock);
+
+                       printk(KERN_INFO "Clocks: Setting DSP clock\n");
+                       calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
+                               &dsp_postdiv, &dsp_mul);
+                       ar7_bus_clock = ar7_cpu_clock / 2;
+                       tnetd7200_set_clock(dsp_base, &clocks->dsp,
+                               dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
+                               dsp_mul * 2, ar7_bus_clock);
+               } else {
+                       printk(KERN_INFO "Clocks: Sync 1:1 mode\n");
+
+                       printk(KERN_INFO "Clocks: Setting DSP clock\n");
+                       calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv,
+                               &dsp_postdiv, &dsp_mul);
+                       ar7_bus_clock = ((dsp_base / dsp_prediv) * dsp_mul)
+                                                               / dsp_postdiv;
+                       tnetd7200_set_clock(dsp_base, &clocks->dsp,
+                               dsp_prediv, dsp_postdiv * 2, dsp_postdiv,
+                               dsp_mul * 2, ar7_bus_clock);
+
+                       ar7_cpu_clock = ar7_bus_clock;
+               }
+
+       printk(KERN_INFO "Clocks: Setting USB clock\n");
+       usb_base = ar7_bus_clock;
+       calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv,
+               &usb_postdiv, &usb_mul);
+       tnetd7200_set_clock(usb_base, &clocks->usb,
+               usb_prediv, usb_postdiv, -1, usb_mul,
+               TNETD7200_DEF_USB_CLK);
+
+       ar7_dsp_clock = ar7_cpu_clock;
+
+       iounmap(clocks);
+       iounmap(bootcr);
+}
+
+int __init ar7_init_clocks(void)
+{
+       switch (ar7_chip_id()) {
+       case AR7_CHIP_7100:
+       case AR7_CHIP_7200:
+               tnetd7200_init_clocks();
+               break;
+       case AR7_CHIP_7300:
+               ar7_dsp_clock = tnetd7300_dsp_clock();
+               tnetd7300_init_clocks();
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+arch_initcall(ar7_init_clocks);
diff --git a/arch/mips/ar7/gpio.c b/arch/mips/ar7/gpio.c
new file mode 100644 (file)
index 0000000..74e14a3
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+
+#include <asm/mach-ar7/gpio.h>
+
+static const char *ar7_gpio_list[AR7_GPIO_MAX];
+
+int gpio_request(unsigned gpio, const char *label)
+{
+       if (gpio >= AR7_GPIO_MAX)
+               return -EINVAL;
+
+       if (ar7_gpio_list[gpio])
+               return -EBUSY;
+
+       if (label)
+               ar7_gpio_list[gpio] = label;
+       else
+               ar7_gpio_list[gpio] = "busy";
+
+       return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+       BUG_ON(!ar7_gpio_list[gpio]);
+       ar7_gpio_list[gpio] = NULL;
+}
+EXPORT_SYMBOL(gpio_free);
diff --git a/arch/mips/ar7/irq.c b/arch/mips/ar7/irq.c
new file mode 100644 (file)
index 0000000..c781556
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/mach-ar7/ar7.h>
+
+#define EXCEPT_OFFSET  0x80
+#define PACE_OFFSET    0xA0
+#define CHNLS_OFFSET   0x200
+
+#define REG_OFFSET(irq, reg)   ((irq) / 32 * 0x4 + reg * 0x10)
+#define SEC_REG_OFFSET(reg)    (EXCEPT_OFFSET + reg * 0x8)
+#define SEC_SR_OFFSET          (SEC_REG_OFFSET(0))     /* 0x80 */
+#define CR_OFFSET(irq)         (REG_OFFSET(irq, 1))    /* 0x10 */
+#define SEC_CR_OFFSET          (SEC_REG_OFFSET(1))     /* 0x88 */
+#define ESR_OFFSET(irq)                (REG_OFFSET(irq, 2))    /* 0x20 */
+#define SEC_ESR_OFFSET         (SEC_REG_OFFSET(2))     /* 0x90 */
+#define ECR_OFFSET(irq)                (REG_OFFSET(irq, 3))    /* 0x30 */
+#define SEC_ECR_OFFSET         (SEC_REG_OFFSET(3))     /* 0x98 */
+#define PIR_OFFSET             (0x40)
+#define MSR_OFFSET             (0x44)
+#define PM_OFFSET(irq)         (REG_OFFSET(irq, 5))    /* 0x50 */
+#define TM_OFFSET(irq)         (REG_OFFSET(irq, 6))    /* 0x60 */
+
+#define REG(addr) ((u32 *)(KSEG1ADDR(AR7_REGS_IRQ) + addr))
+
+#define CHNL_OFFSET(chnl) (CHNLS_OFFSET + (chnl * 4))
+
+static int ar7_irq_base;
+
+static void ar7_unmask_irq(unsigned int irq)
+{
+       writel(1 << ((irq - ar7_irq_base) % 32),
+              REG(ESR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_mask_irq(unsigned int irq)
+{
+       writel(1 << ((irq - ar7_irq_base) % 32),
+              REG(ECR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_ack_irq(unsigned int irq)
+{
+       writel(1 << ((irq - ar7_irq_base) % 32),
+              REG(CR_OFFSET(irq - ar7_irq_base)));
+}
+
+static void ar7_unmask_sec_irq(unsigned int irq)
+{
+       writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET));
+}
+
+static void ar7_mask_sec_irq(unsigned int irq)
+{
+       writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET));
+}
+
+static void ar7_ack_sec_irq(unsigned int irq)
+{
+       writel(1 << (irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET));
+}
+
+static struct irq_chip ar7_irq_type = {
+       .name = "AR7",
+       .unmask = ar7_unmask_irq,
+       .mask = ar7_mask_irq,
+       .ack = ar7_ack_irq
+};
+
+static struct irq_chip ar7_sec_irq_type = {
+       .name = "AR7",
+       .unmask = ar7_unmask_sec_irq,
+       .mask = ar7_mask_sec_irq,
+       .ack = ar7_ack_sec_irq,
+};
+
+static struct irqaction ar7_cascade_action = {
+       .handler = no_action,
+       .name = "AR7 cascade interrupt"
+};
+
+static void __init ar7_irq_init(int base)
+{
+       int i;
+       /*
+        * Disable interrupts and clear pending
+        */
+       writel(0xffffffff, REG(ECR_OFFSET(0)));
+       writel(0xff, REG(ECR_OFFSET(32)));
+       writel(0xffffffff, REG(SEC_ECR_OFFSET));
+       writel(0xffffffff, REG(CR_OFFSET(0)));
+       writel(0xff, REG(CR_OFFSET(32)));
+       writel(0xffffffff, REG(SEC_CR_OFFSET));
+
+       ar7_irq_base = base;
+
+       for (i = 0; i < 40; i++) {
+               writel(i, REG(CHNL_OFFSET(i)));
+               /* Primary IRQ's */
+               set_irq_chip_and_handler(base + i, &ar7_irq_type,
+                                        handle_level_irq);
+               /* Secondary IRQ's */
+               if (i < 32)
+                       set_irq_chip_and_handler(base + i + 40,
+                                                &ar7_sec_irq_type,
+                                                handle_level_irq);
+       }
+
+       setup_irq(2, &ar7_cascade_action);
+       setup_irq(ar7_irq_base, &ar7_cascade_action);
+       set_c0_status(IE_IRQ0);
+}
+
+void __init arch_init_irq(void)
+{
+       mips_cpu_irq_init();
+       ar7_irq_init(8);
+}
+
+static void ar7_cascade(void)
+{
+       u32 status;
+       int i, irq;
+
+       /* Primary IRQ's */
+       irq = readl(REG(PIR_OFFSET)) & 0x3f;
+       if (irq) {
+               do_IRQ(ar7_irq_base + irq);
+               return;
+       }
+
+       /* Secondary IRQ's are cascaded through primary '0' */
+       writel(1, REG(CR_OFFSET(irq)));
+       status = readl(REG(SEC_SR_OFFSET));
+       for (i = 0; i < 32; i++) {
+               if (status & 1) {
+                       do_IRQ(ar7_irq_base + i + 40);
+                       return;
+               }
+               status >>= 1;
+       }
+
+       spurious_interrupt();
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+       unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+       if (pending & STATUSF_IP7)              /* cpu timer */
+               do_IRQ(7);
+       else if (pending & STATUSF_IP2)         /* int0 hardware line */
+               ar7_cascade();
+       else
+               spurious_interrupt();
+}
diff --git a/arch/mips/ar7/memory.c b/arch/mips/ar7/memory.c
new file mode 100644 (file)
index 0000000..696c723
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 Eugene Konev <ejka@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/pfn.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <linux/swap.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+#include <asm/sections.h>
+
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mips-boards/prom.h>
+
+static int __init memsize(void)
+{
+       u32 size = (64 << 20);
+       u32 *addr = (u32 *)KSEG1ADDR(AR7_SDRAM_BASE + size - 4);
+       u32 *kernel_end = (u32 *)KSEG1ADDR(CPHYSADDR((u32)&_end));
+       u32 *tmpaddr = addr;
+
+       while (tmpaddr > kernel_end) {
+               *tmpaddr = (u32)tmpaddr;
+               size >>= 1;
+               tmpaddr -= size >> 2;
+       }
+
+       do {
+               tmpaddr += size >> 2;
+               if (*tmpaddr != (u32)tmpaddr)
+                       break;
+               size <<= 1;
+       } while (size < (64 << 20));
+
+       writel((u32)tmpaddr, &addr);
+
+       return size;
+}
+
+void __init prom_meminit(void)
+{
+       unsigned long pages;
+
+       pages = memsize() >> PAGE_SHIFT;
+       add_memory_region(PHYS_OFFSET, pages << PAGE_SHIFT,
+                         BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+       /* Nothing to free */
+}
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
new file mode 100644 (file)
index 0000000..2ecab61
--- /dev/null
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/vlynq.h>
+#include <linux/leds.h>
+#include <linux/string.h>
+#include <linux/etherdevice.h>
+
+#include <asm/addrspace.h>
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/gpio.h>
+#include <asm/mach-ar7/prom.h>
+
+struct plat_vlynq_data {
+       struct plat_vlynq_ops ops;
+       int gpio_bit;
+       int reset_bit;
+};
+
+
+static int vlynq_on(struct vlynq_device *dev)
+{
+       int result;
+       struct plat_vlynq_data *pdata = dev->dev.platform_data;
+
+       result = gpio_request(pdata->gpio_bit, "vlynq");
+       if (result)
+               goto out;
+
+       ar7_device_reset(pdata->reset_bit);
+
+       result = ar7_gpio_disable(pdata->gpio_bit);
+       if (result)
+               goto out_enabled;
+
+       result = ar7_gpio_enable(pdata->gpio_bit);
+       if (result)
+               goto out_enabled;
+
+       result = gpio_direction_output(pdata->gpio_bit, 0);
+       if (result)
+               goto out_gpio_enabled;
+
+       msleep(50);
+
+       gpio_set_value(pdata->gpio_bit, 1);
+       msleep(50);
+
+       return 0;
+
+out_gpio_enabled:
+       ar7_gpio_disable(pdata->gpio_bit);
+out_enabled:
+       ar7_device_disable(pdata->reset_bit);
+       gpio_free(pdata->gpio_bit);
+out:
+       return result;
+}
+
+static void vlynq_off(struct vlynq_device *dev)
+{
+       struct plat_vlynq_data *pdata = dev->dev.platform_data;
+       ar7_gpio_disable(pdata->gpio_bit);
+       gpio_free(pdata->gpio_bit);
+       ar7_device_disable(pdata->reset_bit);
+}
+
+static struct resource physmap_flash_resource = {
+       .name = "mem",
+       .flags = IORESOURCE_MEM,
+       .start = 0x10000000,
+       .end = 0x107fffff,
+};
+
+static struct resource cpmac_low_res[] = {
+       {
+               .name = "regs",
+               .flags = IORESOURCE_MEM,
+               .start = AR7_REGS_MAC0,
+               .end = AR7_REGS_MAC0 + 0x7ff,
+       },
+       {
+               .name = "irq",
+               .flags = IORESOURCE_IRQ,
+               .start = 27,
+               .end = 27,
+       },
+};
+
+static struct resource cpmac_high_res[] = {
+       {
+               .name = "regs",
+               .flags = IORESOURCE_MEM,
+               .start = AR7_REGS_MAC1,
+               .end = AR7_REGS_MAC1 + 0x7ff,
+       },
+       {
+               .name = "irq",
+               .flags = IORESOURCE_IRQ,
+               .start = 41,
+               .end = 41,
+       },
+};
+
+static struct resource vlynq_low_res[] = {
+       {
+               .name = "regs",
+               .flags = IORESOURCE_MEM,
+               .start = AR7_REGS_VLYNQ0,
+               .end = AR7_REGS_VLYNQ0 + 0xff,
+       },
+       {
+               .name = "irq",
+               .flags = IORESOURCE_IRQ,
+               .start = 29,
+               .end = 29,
+       },
+       {
+               .name = "mem",
+               .flags = IORESOURCE_MEM,
+               .start = 0x04000000,
+               .end = 0x04ffffff,
+       },
+       {
+               .name = "devirq",
+               .flags = IORESOURCE_IRQ,
+               .start = 80,
+               .end = 111,
+       },
+};
+
+static struct resource vlynq_high_res[] = {
+       {
+               .name = "regs",
+               .flags = IORESOURCE_MEM,
+               .start = AR7_REGS_VLYNQ1,
+               .end = AR7_REGS_VLYNQ1 + 0xff,
+       },
+       {
+               .name = "irq",
+               .flags = IORESOURCE_IRQ,
+               .start = 33,
+               .end = 33,
+       },
+       {
+               .name = "mem",
+               .flags = IORESOURCE_MEM,
+               .start = 0x0c000000,
+               .end = 0x0cffffff,
+       },
+       {
+               .name = "devirq",
+               .flags = IORESOURCE_IRQ,
+               .start = 112,
+               .end = 143,
+       },
+};
+
+static struct resource usb_res[] = {
+       {
+               .name = "regs",
+               .flags = IORESOURCE_MEM,
+               .start = AR7_REGS_USB,
+               .end = AR7_REGS_USB + 0xff,
+       },
+       {
+               .name = "irq",
+               .flags = IORESOURCE_IRQ,
+               .start = 32,
+               .end = 32,
+       },
+       {
+               .name = "mem",
+               .flags = IORESOURCE_MEM,
+               .start = 0x03400000,
+               .end = 0x034001fff,
+       },
+};
+
+static struct physmap_flash_data physmap_flash_data = {
+       .width = 2,
+};
+
+static struct plat_cpmac_data cpmac_low_data = {
+       .reset_bit = 17,
+       .power_bit = 20,
+       .phy_mask = 0x80000000,
+};
+
+static struct plat_cpmac_data cpmac_high_data = {
+       .reset_bit = 21,
+       .power_bit = 22,
+       .phy_mask = 0x7fffffff,
+};
+
+static struct plat_vlynq_data vlynq_low_data = {
+       .ops.on = vlynq_on,
+       .ops.off = vlynq_off,
+       .reset_bit = 20,
+       .gpio_bit = 18,
+};
+
+static struct plat_vlynq_data vlynq_high_data = {
+       .ops.on = vlynq_on,
+       .ops.off = vlynq_off,
+       .reset_bit = 16,
+       .gpio_bit = 19,
+};
+
+static struct platform_device physmap_flash = {
+       .id = 0,
+       .name = "physmap-flash",
+       .dev.platform_data = &physmap_flash_data,
+       .resource = &physmap_flash_resource,
+       .num_resources = 1,
+};
+
+static u64 cpmac_dma_mask = DMA_BIT_MASK(32);
+static struct platform_device cpmac_low = {
+       .id = 0,
+       .name = "cpmac",
+       .dev = {
+               .dma_mask = &cpmac_dma_mask,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data = &cpmac_low_data,
+       },
+       .resource = cpmac_low_res,
+       .num_resources = ARRAY_SIZE(cpmac_low_res),
+};
+
+static struct platform_device cpmac_high = {
+       .id = 1,
+       .name = "cpmac",
+       .dev = {
+               .dma_mask = &cpmac_dma_mask,
+               .coherent_dma_mask = DMA_BIT_MASK(32),
+               .platform_data = &cpmac_high_data,
+       },
+       .resource = cpmac_high_res,
+       .num_resources = ARRAY_SIZE(cpmac_high_res),
+};
+
+static struct platform_device vlynq_low = {
+       .id = 0,
+       .name = "vlynq",
+       .dev.platform_data = &vlynq_low_data,
+       .resource = vlynq_low_res,
+       .num_resources = ARRAY_SIZE(vlynq_low_res),
+};
+
+static struct platform_device vlynq_high = {
+       .id = 1,
+       .name = "vlynq",
+       .dev.platform_data = &vlynq_high_data,
+       .resource = vlynq_high_res,
+       .num_resources = ARRAY_SIZE(vlynq_high_res),
+};
+
+
+static struct gpio_led default_leds[] = {
+       {
+               .name = "status",
+               .gpio = 8,
+               .active_low = 1,
+       },
+};
+
+static struct gpio_led dsl502t_leds[] = {
+       {
+               .name = "status",
+               .gpio = 9,
+               .active_low = 1,
+       },
+       {
+               .name = "ethernet",
+               .gpio = 7,
+               .active_low = 1,
+       },
+       {
+               .name = "usb",
+               .gpio = 12,
+               .active_low = 1,
+       },
+};
+
+static struct gpio_led dg834g_leds[] = {
+       {
+               .name = "ppp",
+               .gpio = 6,
+               .active_low = 1,
+       },
+       {
+               .name = "status",
+               .gpio = 7,
+               .active_low = 1,
+       },
+       {
+               .name = "adsl",
+               .gpio = 8,
+               .active_low = 1,
+       },
+       {
+               .name = "wifi",
+               .gpio = 12,
+               .active_low = 1,
+       },
+       {
+               .name = "power",
+               .gpio = 14,
+               .active_low = 1,
+               .default_trigger = "default-on",
+       },
+};
+
+static struct gpio_led fb_sl_leds[] = {
+       {
+               .name = "1",
+               .gpio = 7,
+       },
+       {
+               .name = "2",
+               .gpio = 13,
+               .active_low = 1,
+       },
+       {
+               .name = "3",
+               .gpio = 10,
+               .active_low = 1,
+       },
+       {
+               .name = "4",
+               .gpio = 12,
+               .active_low = 1,
+       },
+       {
+               .name = "5",
+               .gpio = 9,
+               .active_low = 1,
+       },
+};
+
+static struct gpio_led fb_fon_leds[] = {
+       {
+               .name = "1",
+               .gpio = 8,
+       },
+       {
+               .name = "2",
+               .gpio = 3,
+               .active_low = 1,
+       },
+       {
+               .name = "3",
+               .gpio = 5,
+       },
+       {
+               .name = "4",
+               .gpio = 4,
+               .active_low = 1,
+       },
+       {
+               .name = "5",
+               .gpio = 11,
+               .active_low = 1,
+       },
+};
+
+static struct gpio_led_platform_data ar7_led_data;
+
+static struct platform_device ar7_gpio_leds = {
+       .name = "leds-gpio",
+       .id = -1,
+       .dev = {
+               .platform_data = &ar7_led_data,
+       }
+};
+
+static struct platform_device ar7_udc = {
+       .id = -1,
+       .name = "ar7_udc",
+       .resource = usb_res,
+       .num_resources = ARRAY_SIZE(usb_res),
+};
+
+static inline unsigned char char2hex(char h)
+{
+       switch (h) {
+       case '0': case '1': case '2': case '3': case '4':
+       case '5': case '6': case '7': case '8': case '9':
+               return h - '0';
+       case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+               return h - 'A' + 10;
+       case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+               return h - 'a' + 10;
+       default:
+               return 0;
+       }
+}
+
+static void cpmac_get_mac(int instance, unsigned char *dev_addr)
+{
+       int i;
+       char name[5], default_mac[ETH_ALEN], *mac;
+
+       mac = NULL;
+       sprintf(name, "mac%c", 'a' + instance);
+       mac = prom_getenv(name);
+       if (!mac) {
+               sprintf(name, "mac%c", 'a');
+               mac = prom_getenv(name);
+       }
+       if (!mac) {
+               random_ether_addr(default_mac);
+               mac = default_mac;
+       }
+       for (i = 0; i < 6; i++)
+               dev_addr[i] = (char2hex(mac[i * 3]) << 4) +
+                       char2hex(mac[i * 3 + 1]);
+}
+
+static void __init detect_leds(void)
+{
+       char *prid, *usb_prod;
+
+       /* Default LEDs */
+       ar7_led_data.num_leds = ARRAY_SIZE(default_leds);
+       ar7_led_data.leds = default_leds;
+
+       /* FIXME: the whole thing is unreliable */
+       prid = prom_getenv("ProductID");
+       usb_prod = prom_getenv("usb_prod");
+
+       /* If we can't get the product id from PROM, use the default LEDs */
+       if (!prid)
+               return;
+
+       if (strstr(prid, "Fritz_Box_FON")) {
+               ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds);
+               ar7_led_data.leds = fb_fon_leds;
+       } else if (strstr(prid, "Fritz_Box_")) {
+               ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds);
+               ar7_led_data.leds = fb_sl_leds;
+       } else if ((!strcmp(prid, "AR7RD") || !strcmp(prid, "AR7DB"))
+               && usb_prod != NULL && strstr(usb_prod, "DSL-502T")) {
+               ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds);
+               ar7_led_data.leds = dsl502t_leds;
+       } else if (strstr(prid, "DG834")) {
+               ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds);
+               ar7_led_data.leds = dg834g_leds;
+       }
+}
+
+static int __init ar7_register_devices(void)
+{
+       int res;
+#ifdef CONFIG_SERIAL_8250
+       static struct uart_port uart_port[2];
+
+       memset(uart_port, 0, sizeof(struct uart_port) * 2);
+
+       uart_port[0].type = PORT_16550A;
+       uart_port[0].line = 0;
+       uart_port[0].irq = AR7_IRQ_UART0;
+       uart_port[0].uartclk = ar7_bus_freq() / 2;
+       uart_port[0].iotype = UPIO_MEM32;
+       uart_port[0].mapbase = AR7_REGS_UART0;
+       uart_port[0].membase = ioremap(uart_port[0].mapbase, 256);
+       uart_port[0].regshift = 2;
+       res = early_serial_setup(&uart_port[0]);
+       if (res)
+               return res;
+
+
+       /* Only TNETD73xx have a second serial port */
+       if (ar7_has_second_uart()) {
+               uart_port[1].type = PORT_16550A;
+               uart_port[1].line = 1;
+               uart_port[1].irq = AR7_IRQ_UART1;
+               uart_port[1].uartclk = ar7_bus_freq() / 2;
+               uart_port[1].iotype = UPIO_MEM32;
+               uart_port[1].mapbase = UR8_REGS_UART1;
+               uart_port[1].membase = ioremap(uart_port[1].mapbase, 256);
+               uart_port[1].regshift = 2;
+               res = early_serial_setup(&uart_port[1]);
+               if (res)
+                       return res;
+       }
+#endif /* CONFIG_SERIAL_8250 */
+       res = platform_device_register(&physmap_flash);
+       if (res)
+               return res;
+
+       ar7_device_disable(vlynq_low_data.reset_bit);
+       res = platform_device_register(&vlynq_low);
+       if (res)
+               return res;
+
+       if (ar7_has_high_vlynq()) {
+               ar7_device_disable(vlynq_high_data.reset_bit);
+               res = platform_device_register(&vlynq_high);
+               if (res)
+                       return res;
+       }
+
+       if (ar7_has_high_cpmac()) {
+               cpmac_get_mac(1, cpmac_high_data.dev_addr);
+               res = platform_device_register(&cpmac_high);
+               if (res)
+                       return res;
+       } else {
+               cpmac_low_data.phy_mask = 0xffffffff;
+       }
+
+       cpmac_get_mac(0, cpmac_low_data.dev_addr);
+       res = platform_device_register(&cpmac_low);
+       if (res)
+               return res;
+
+       detect_leds();
+       res = platform_device_register(&ar7_gpio_leds);
+       if (res)
+               return res;
+
+       res = platform_device_register(&ar7_udc);
+
+       return res;
+}
+arch_initcall(ar7_register_devices);
diff --git a/arch/mips/ar7/prom.c b/arch/mips/ar7/prom.c
new file mode 100644 (file)
index 0000000..5ad6f1d
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Putting things on the screen/serial line using YAMONs facilities.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/serial_reg.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/io.h>
+#include <asm/bootinfo.h>
+
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/prom.h>
+
+#define MAX_ENTRY 80
+
+struct env_var {
+       char *name;
+       char *value;
+};
+
+static struct env_var adam2_env[MAX_ENTRY];
+
+char *prom_getenv(const char *name)
+{
+       int i;
+       for (i = 0; (i < MAX_ENTRY) && adam2_env[i].name; i++)
+               if (!strcmp(name, adam2_env[i].name))
+                       return adam2_env[i].value;
+
+       return NULL;
+}
+EXPORT_SYMBOL(prom_getenv);
+
+char * __init prom_getcmdline(void)
+{
+       return &(arcs_cmdline[0]);
+}
+
+static void  __init ar7_init_cmdline(int argc, char *argv[])
+{
+       char *cp;
+       int actr;
+
+       actr = 1; /* Always ignore argv[0] */
+
+       cp = &(arcs_cmdline[0]);
+       while (actr < argc) {
+               strcpy(cp, argv[actr]);
+               cp += strlen(argv[actr]);
+               *cp++ = ' ';
+               actr++;
+       }
+       if (cp != &(arcs_cmdline[0])) {
+               /* get rid of trailing space */
+               --cp;
+               *cp = '\0';
+       }
+}
+
+struct psbl_rec {
+       u32 psbl_size;
+       u32 env_base;
+       u32 env_size;
+       u32 ffs_base;
+       u32 ffs_size;
+};
+
+static __initdata char psp_env_version[] = "TIENV0.8";
+
+struct psp_env_chunk {
+       u8 num;
+       u8 ctrl;
+       u16 csum;
+       u8 len;
+       char data[11];
+} __attribute__ ((packed));
+
+struct psp_var_map_entry {
+       u8 num;
+       char *value;
+};
+
+static struct psp_var_map_entry psp_var_map[] = {
+       { 1, "cpufrequency" },
+       { 2, "memsize" },
+       { 3, "flashsize" },
+       { 4, "modetty0" },
+       { 5, "modetty1" },
+       { 8, "maca" },
+       { 9, "macb" },
+       { 28, "sysfrequency" },
+       { 38, "mipsfrequency" },
+};
+
+/*
+
+Well-known variable (num is looked up in table above for matching variable name)
+Example: cpufrequency=211968000
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 01 |CTRL|CHECKSUM | 01 | _2 | _1 | _1 | _9 | _6 | _8 | _0 | _0 | _0 | \0 | FF
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Name=Value pair in a single chunk
+Example: NAME=VALUE
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 00 |CTRL|CHECKSUM | 01 | _N | _A | _M | _E | _0 | _V | _A | _L | _U | _E | \0
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Name=Value pair in 2 chunks (len is the number of chunks)
+Example: bootloaderVersion=1.3.7.15
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| 00 |CTRL|CHECKSUM | 02 | _b | _o | _o | _t | _l | _o | _a | _d | _e | _r | _V
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+| _e | _r | _s | _i | _o | _n | \0 | _1 | _. | _3 | _. | _7 | _. | _1 | _5 | \0
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+Data is padded with 0xFF
+
+*/
+
+#define PSP_ENV_SIZE  4096
+
+static char psp_env_data[PSP_ENV_SIZE] = { 0, };
+
+static char * __init lookup_psp_var_map(u8 num)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(psp_var_map); i++)
+               if (psp_var_map[i].num == num)
+                       return psp_var_map[i].value;
+
+       return NULL;
+}
+
+static void __init add_adam2_var(char *name, char *value)
+{
+       int i;
+       for (i = 0; i < MAX_ENTRY; i++) {
+               if (!adam2_env[i].name) {
+                       adam2_env[i].name = name;
+                       adam2_env[i].value = value;
+                       return;
+               } else if (!strcmp(adam2_env[i].name, name)) {
+                       adam2_env[i].value = value;
+                       return;
+               }
+       }
+}
+
+static int __init parse_psp_env(void *psp_env_base)
+{
+       int i, n;
+       char *name, *value;
+       struct psp_env_chunk *chunks = (struct psp_env_chunk *)psp_env_data;
+
+       memcpy_fromio(chunks, psp_env_base, PSP_ENV_SIZE);
+
+       i = 1;
+       n = PSP_ENV_SIZE / sizeof(struct psp_env_chunk);
+       while (i < n) {
+               if ((chunks[i].num == 0xff) || ((i + chunks[i].len) > n))
+                       break;
+               value = chunks[i].data;
+               if (chunks[i].num) {
+                       name = lookup_psp_var_map(chunks[i].num);
+               } else {
+                       name = value;
+                       value += strlen(name) + 1;
+               }
+               if (name)
+                       add_adam2_var(name, value);
+               i += chunks[i].len;
+       }
+       return 0;
+}
+
+static void __init ar7_init_env(struct env_var *env)
+{
+       int i;
+       struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x14000300));
+       void *psp_env = (void *)KSEG1ADDR(psbl->env_base);
+
+       if (strcmp(psp_env, psp_env_version) == 0) {
+               parse_psp_env(psp_env);
+       } else {
+               for (i = 0; i < MAX_ENTRY; i++, env++)
+                       if (env->name)
+                               add_adam2_var(env->name, env->value);
+       }
+}
+
+static void __init console_config(void)
+{
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       char console_string[40];
+       int baud = 0;
+       char parity = '\0', bits = '\0', flow = '\0';
+       char *s, *p;
+
+       if (strstr(prom_getcmdline(), "console="))
+               return;
+
+#ifdef CONFIG_KGDB
+       if (!strstr(prom_getcmdline(), "nokgdb")) {
+               strcat(prom_getcmdline(), " console=kgdb");
+               kgdb_enabled = 1;
+               return;
+       }
+#endif
+
+       s = prom_getenv("modetty0");
+       if (s) {
+               baud = simple_strtoul(s, &p, 10);
+               s = p;
+               if (*s == ',')
+                       s++;
+               if (*s)
+                       parity = *s++;
+               if (*s == ',')
+                       s++;
+               if (*s)
+                       bits = *s++;
+               if (*s == ',')
+                       s++;
+               if (*s == 'h')
+                       flow = 'r';
+       }
+
+       if (baud == 0)
+               baud = 38400;
+       if (parity != 'n' && parity != 'o' && parity != 'e')
+               parity = 'n';
+       if (bits != '7' && bits != '8')
+               bits = '8';
+
+       if (flow == 'r')
+               sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
+                       parity, bits, flow);
+       else
+               sprintf(console_string, " console=ttyS0,%d%c%c", baud, parity,
+                       bits);
+       strcat(prom_getcmdline(), console_string);
+#endif
+}
+
+void __init prom_init(void)
+{
+       ar7_init_cmdline(fw_arg0, (char **)fw_arg1);
+       ar7_init_env((struct env_var *)fw_arg2);
+       console_config();
+}
+
+#define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4)))
+static inline unsigned int serial_in(int offset)
+{
+       return readl((void *)PORT(offset));
+}
+
+static inline void serial_out(int offset, int value)
+{
+       writel(value, (void *)PORT(offset));
+}
+
+char prom_getchar(void)
+{
+       while (!(serial_in(UART_LSR) & UART_LSR_DR))
+               ;
+       return serial_in(UART_RX);
+}
+
+int prom_putchar(char c)
+{
+       while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0)
+               ;
+       serial_out(UART_TX, c);
+       return 1;
+}
+
diff --git a/arch/mips/ar7/setup.c b/arch/mips/ar7/setup.c
new file mode 100644 (file)
index 0000000..39f6b5b
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/pm.h>
+#include <linux/time.h>
+
+#include <asm/reboot.h>
+#include <asm/mach-ar7/ar7.h>
+#include <asm/mach-ar7/prom.h>
+
+static void ar7_machine_restart(char *command)
+{
+       u32 *softres_reg = ioremap(AR7_REGS_RESET +
+                                         AR7_RESET_SOFTWARE, 1);
+       writel(1, softres_reg);
+}
+
+static void ar7_machine_halt(void)
+{
+       while (1)
+               ;
+}
+
+static void ar7_machine_power_off(void)
+{
+       u32 *power_reg = (u32 *)ioremap(AR7_REGS_POWER, 1);
+       u32 power_state = readl(power_reg) | (3 << 30);
+       writel(power_state, power_reg);
+       ar7_machine_halt();
+}
+
+const char *get_system_type(void)
+{
+       u16 chip_id = ar7_chip_id();
+       switch (chip_id) {
+       case AR7_CHIP_7300:
+               return "TI AR7 (TNETD7300)";
+       case AR7_CHIP_7100:
+               return "TI AR7 (TNETD7100)";
+       case AR7_CHIP_7200:
+               return "TI AR7 (TNETD7200)";
+       default:
+               return "TI AR7 (Unknown)";
+       }
+}
+
+static int __init ar7_init_console(void)
+{
+       return 0;
+}
+console_initcall(ar7_init_console);
+
+/*
+ * Initializes basic routines and structures pointers, memory size (as
+ * given by the bios and saves the command line.
+ */
+
+void __init plat_mem_setup(void)
+{
+       unsigned long io_base;
+
+       _machine_restart = ar7_machine_restart;
+       _machine_halt = ar7_machine_halt;
+       pm_power_off = ar7_machine_power_off;
+       panic_timeout = 3;
+
+       io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000);
+       if (!io_base)
+               panic("Can't remap IO base!\n");
+       set_io_port_base(io_base);
+
+       prom_meminit();
+
+       printk(KERN_INFO "%s, ID: 0x%04x, Revision: 0x%02x\n",
+                                       get_system_type(),
+               ar7_chip_id(), ar7_chip_rev());
+}
diff --git a/arch/mips/ar7/time.c b/arch/mips/ar7/time.c
new file mode 100644 (file)
index 0000000..a1fba89
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Setting up the clock on the MIPS boards.
+ */
+
+#include <linux/init.h>
+#include <linux/time.h>
+
+#include <asm/time.h>
+#include <asm/mach-ar7/ar7.h>
+
+void __init plat_time_init(void)
+{
+       mips_hpt_frequency = ar7_cpu_freq() / 2;
+}
index 7c0528b0e34ccabd1668bcd5c3b4436076f00e76..d6903c3f3d513c0cd0990138aaada2445d27562b 100644 (file)
@@ -14,9 +14,5 @@ obj-y += dma-octeon.o flash_setup.o
 obj-y += octeon-memcpy.o
 
 obj-$(CONFIG_SMP)                     += smp.o
-obj-$(CONFIG_PCI)                     += pci-common.o
-obj-$(CONFIG_PCI)                     += pci.o
-obj-$(CONFIG_PCI)                     += pcie.o
-obj-$(CONFIG_PCI_MSI)                 += msi.o
 
 EXTRA_CFLAGS += -Werror
index 627c162a615980df13bffda63dc8517d66ac5695..4b92bfc662db0b629e253a92336a9396b41555ac 100644 (file)
@@ -29,7 +29,7 @@
 #include <dma-coherence.h>
 
 #ifdef CONFIG_PCI
-#include "pci-common.h"
+#include <asm/octeon/pci-octeon.h>
 #endif
 
 #define BAR2_PCI_ADDRESS 0x8000000000ul
diff --git a/arch/mips/cavium-octeon/pci-common.c b/arch/mips/cavium-octeon/pci-common.c
deleted file mode 100644 (file)
index cd029f8..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2005-2007 Cavium Networks
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include "pci-common.h"
-
-typeof(pcibios_map_irq) *octeon_pcibios_map_irq;
-enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID;
-
-/**
- * Map a PCI device to the appropriate interrupt line
- *
- * @param dev    The Linux PCI device structure for the device to map
- * @param slot   The slot number for this device on __BUS 0__. Linux
- *               enumerates through all the bridges and figures out the
- *               slot on Bus 0 where this device eventually hooks to.
- * @param pin    The PCI interrupt pin read from the device, then swizzled
- *               as it goes through each bridge.
- * @return Interrupt number for the device
- */
-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
-       if (octeon_pcibios_map_irq)
-               return octeon_pcibios_map_irq(dev, slot, pin);
-       else
-               panic("octeon_pcibios_map_irq doesn't point to a "
-                     "pcibios_map_irq() function");
-}
-
-
-/**
- * Called to perform platform specific PCI setup
- *
- * @param dev
- * @return
- */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-       uint16_t config;
-       uint32_t dconfig;
-       int pos;
-       /*
-        * Force the Cache line setting to 64 bytes. The standard
-        * Linux bus scan doesn't seem to set it. Octeon really has
-        * 128 byte lines, but Intel bridges get really upset if you
-        * try and set values above 64 bytes. Value is specified in
-        * 32bit words.
-        */
-       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 64 / 4);
-       /* Set latency timers for all devices */
-       pci_write_config_byte(dev, PCI_LATENCY_TIMER, 48);
-
-       /* Enable reporting System errors and parity errors on all devices */
-       /* Enable parity checking and error reporting */
-       pci_read_config_word(dev, PCI_COMMAND, &config);
-       config |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
-       pci_write_config_word(dev, PCI_COMMAND, config);
-
-       if (dev->subordinate) {
-               /* Set latency timers on sub bridges */
-               pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 48);
-               /* More bridge error detection */
-               pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &config);
-               config |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR;
-               pci_write_config_word(dev, PCI_BRIDGE_CONTROL, config);
-       }
-
-       /* Enable the PCIe normal error reporting */
-       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
-       if (pos) {
-               /* Update Device Control */
-               pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config);
-               /* Correctable Error Reporting */
-               config |= PCI_EXP_DEVCTL_CERE;
-               /* Non-Fatal Error Reporting */
-               config |= PCI_EXP_DEVCTL_NFERE;
-               /* Fatal Error Reporting */
-               config |= PCI_EXP_DEVCTL_FERE;
-               /* Unsupported Request */
-               config |= PCI_EXP_DEVCTL_URRE;
-               pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config);
-       }
-
-       /* Find the Advanced Error Reporting capability */
-       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
-       if (pos) {
-               /* Clear Uncorrectable Error Status */
-               pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
-                                     &dconfig);
-               pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
-                                      dconfig);
-               /* Enable reporting of all uncorrectable errors */
-               /* Uncorrectable Error Mask - turned on bits disable errors */
-               pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, 0);
-               /*
-                * Leave severity at HW default. This only controls if
-                * errors are reported as uncorrectable or
-                * correctable, not if the error is reported.
-                */
-               /* PCI_ERR_UNCOR_SEVER - Uncorrectable Error Severity */
-               /* Clear Correctable Error Status */
-               pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &dconfig);
-               pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, dconfig);
-               /* Enable reporting of all correctable errors */
-               /* Correctable Error Mask - turned on bits disable errors */
-               pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, 0);
-               /* Advanced Error Capabilities */
-               pci_read_config_dword(dev, pos + PCI_ERR_CAP, &dconfig);
-               /* ECRC Generation Enable */
-               if (config & PCI_ERR_CAP_ECRC_GENC)
-                       config |= PCI_ERR_CAP_ECRC_GENE;
-               /* ECRC Check Enable */
-               if (config & PCI_ERR_CAP_ECRC_CHKC)
-                       config |= PCI_ERR_CAP_ECRC_CHKE;
-               pci_write_config_dword(dev, pos + PCI_ERR_CAP, dconfig);
-               /* PCI_ERR_HEADER_LOG - Header Log Register (16 bytes) */
-               /* Report all errors to the root complex */
-               pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND,
-                                      PCI_ERR_ROOT_CMD_COR_EN |
-                                      PCI_ERR_ROOT_CMD_NONFATAL_EN |
-                                      PCI_ERR_ROOT_CMD_FATAL_EN);
-               /* Clear the Root status register */
-               pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &dconfig);
-               pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, dconfig);
-       }
-
-       return 0;
-}
index 0b891a9c6253125ddd54e863ff1d23b8299d4e25..32d51a31dc4803667a690a328d76190eb08adf81 100644 (file)
@@ -194,11 +194,11 @@ static void octeon_init_secondary(void)
 void octeon_prepare_cpus(unsigned int max_cpus)
 {
        cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffffffff);
-       if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_SHARED,
+       if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_DISABLED,
                        "mailbox0", mailbox_interrupt)) {
                panic("Cannot request_irq(OCTEON_IRQ_MBOX0)\n");
        }
-       if (request_irq(OCTEON_IRQ_MBOX1, mailbox_interrupt, IRQF_SHARED,
+       if (request_irq(OCTEON_IRQ_MBOX1, mailbox_interrupt, IRQF_DISABLED,
                        "mailbox1", mailbox_interrupt)) {
                panic("Cannot request_irq(OCTEON_IRQ_MBOX1)\n");
        }
index 9e143989c7b8b889dcabc900fa86058d9c1517b2..4eaec8b46e0ce16280b70f261e1199fcf0959ee6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Cobalt buttons platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 0720e4fae3112c41fb3c52cff618ad22bb5d4134..0f1cd90f37edcbcfcfa37447831045777374fbc5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt LCD platform device.
  *
- *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 1c6ebd468b07ff3f440f5fd2401c7f78b4d1c3f6..d3ce6fa1dc74cec54c66d6e973ae03eeb429e2e0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt LED platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 2b088ef3839a4b69d275b3b2e30eedc31051198c..691d620b6766a078b51c051ceeb4c57af4e76033 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt MTD device.
  *
- *  Copyright (C) 2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2006  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index e70794b8bcba897dc818a196c44581e4b6cac7ab..3ab39898b4e46b3a3b7c5615b8b5fe85b5e8473b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt RTC platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 53b8d0d6da90824ccc2d4447526f205bf36ed506..7cb51f57275e584bdf4d7ba61762e004023f01d7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Registration of Cobalt UART platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 4a570e7145fe65fc0d551f60600feb916541bc3c..0162f9edc693c57bcf35c614be66289eb3db7f90 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Cobalt time initialization.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/configs/ar7_defconfig b/arch/mips/configs/ar7_defconfig
new file mode 100644 (file)
index 0000000..dad5b67
--- /dev/null
@@ -0,0 +1,1182 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30
+# Wed Jun 24 14:08:59 2009
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MACH_ALCHEMY is not set
+CONFIG_AR7=y
+# CONFIG_BASLER_EXCITE is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_LEMOTE_FULONG is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_NEC_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_CEVT_R4K_LIB=y
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K_LIB=y
+CONFIG_CSRC_R4K=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+# CONFIG_HOTPLUG_CPU is not set
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_GPIO=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_NO_EXCEPT_FILL=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_LOONGSON2 is not set
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+# CONFIG_CPU_CAVIUM_OCTEON is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_HARDWARE_WATCHPOINTS=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_32KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=100
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_KEXEC=y
+# CONFIG_SECCOMP is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_RELAY=y
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_KALLSYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+# CONFIG_PCSPKR_PLATFORM is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Performance Counters
+#
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_SLOW_WORK is not set
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_PROBE_INITRD_HEADER=y
+# CONFIG_FREEZER is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_MMU=y
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options
+#
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_PM is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 is not set
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_TCP_CONG_ADVANCED=y
+# CONFIG_TCP_CONG_BIC is not set
+# CONFIG_TCP_CONG_CUBIC is not set
+CONFIG_TCP_CONG_WESTWOOD=y
+# CONFIG_TCP_CONG_HTCP is not set
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_DEFAULT_BIC is not set
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+CONFIG_DEFAULT_WESTWOOD=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="westwood"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+# CONFIG_BRIDGE_NETFILTER is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+CONFIG_NF_CONNTRACK=m
+# CONFIG_NF_CT_ACCT is not set
+CONFIG_NF_CONNTRACK_MARK=y
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CT_PROTO_DCCP is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CT_PROTO_UDPLITE is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+# CONFIG_NF_CONNTRACK_H323 is not set
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+CONFIG_NF_CONNTRACK_TFTP=m
+# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_HL is not set
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+# CONFIG_NETFILTER_XT_TARGET_MARK is not set
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+# CONFIG_NETFILTER_XT_MATCH_HL is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=m
+# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+# CONFIG_IP_NF_MATCH_AH is not set
+# CONFIG_IP_NF_MATCH_ECN is not set
+# CONFIG_IP_NF_MATCH_TTL is not set
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+# CONFIG_IP_NF_TARGET_NETMAP is not set
+# CONFIG_IP_NF_TARGET_REDIRECT is not set
+# CONFIG_NF_NAT_SNMP_BASIC is not set
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+# CONFIG_NF_NAT_SIP is not set
+CONFIG_IP_NF_MANGLE=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+# CONFIG_IP_NF_TARGET_ECN is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+CONFIG_IP_NF_RAW=m
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+CONFIG_ATM=m
+# CONFIG_ATM_CLIP is not set
+# CONFIG_ATM_LANE is not set
+CONFIG_ATM_BR2684=m
+CONFIG_ATM_BR2684_IPFILTER=y
+CONFIG_STP=y
+CONFIG_BRIDGE=y
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=y
+# 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_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_ATM is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_INGRESS is not set
+
+#
+# Classification
+#
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_EMATCH is not set
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=y
+# CONFIG_NET_ACT_GACT is not set
+# CONFIG_NET_ACT_MIRRED is not set
+# CONFIG_NET_ACT_IPT is not set
+# CONFIG_NET_ACT_NAT is not set
+# CONFIG_NET_ACT_PEDIT is not set
+# CONFIG_NET_ACT_SIMP is not set
+# CONFIG_NET_ACT_SKBEDIT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+# CONFIG_AX25 is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=m
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_DEFAULT_PS=y
+CONFIG_MAC80211_DEFAULT_PS_VALUE=1
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+# CONFIG_MAC80211_LEDS is not set
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=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
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS 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=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_IFB is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+CONFIG_CPMAC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+# CONFIG_LIBERTAS is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_RT2X00 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM 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=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AR7_WDT=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+CONFIG_SSB_SERIAL=y
+CONFIG_SSB_DRIVER_MIPS=y
+CONFIG_SSB_EMBEDDED=y
+CONFIG_SSB_DRIVER_EXTIF=y
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_GPIO is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+CONFIG_VLYNQ=y
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# 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_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+# CONFIG_CRAMFS is not set
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# 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=y
+# 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
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_NLS is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_CMDLINE="rootfstype=squashfs,jffs2"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_AEAD2=m
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_RNG2=m
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=m
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
index 6a17c9b508eaa06dea5f66791e06e9f6f3d8dfc5..7abce661b90f7826b67c587c9c6c185fa9dc4eeb 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     linux/arch/mips/dec/ecc-berr.c
- *
  *     Bus error event handling code for systems equipped with ECC
  *     handling logic, i.e. DECstation/DECsystem 5000/200 (KN02),
  *     5000/240 (KN03), 5000/260 (KN05) and DECsystem 5900 (KN03),
index 00cecdcc75f215cb6e5a6581442774996fcc26f3..82c85281878143cfc6cc4d85131f978cc49c2467 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/mips/dec/int-handler.S
- *
  * Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen
  * Copyright (C) 2000, 2001, 2002, 2003, 2005  Maciej W. Rozycki
  *
index 3acb133668dc12f5731aab6b611c8756a6fa89a1..cb41954fc321db609af7408922717588605be809 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     linux/arch/mips/dec/ioasic-irq.c
- *
  *     DEC I/O ASIC interrupts.
  *
  *     Copyright (c) 2002, 2003  Maciej W. Rozycki
index d3b8002bf1e77db470427692de4a1e0da8bfe40e..b0dc6d53edd61fbb88283b8e4f18dae73ad5aacf 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     linux/arch/mips/dec/kn01-berr.c
- *
  *     Bus error event handling code for DECstation/DECsystem 3100
  *     and 2100 (KN01) systems equipped with parity error detection
  *     logic.
index 02439dc0ba83136209b0945a1cb77d39601e244b..ed90a8deabccf78d57c23eb956354fd2b205c262 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     linux/arch/mips/dec/kn02-irq.c
- *
  *     DECstation 5000/200 (KN02) Control and Status Register
  *     interrupts.
  *
index 5f04545c3606da25d1054c743e139478e32e4929..07ca5405d48d5c0c357683d31e6a7991f57ddade 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     linux/arch/mips/dec/kn02xa-berr.c
- *
  *     Bus error event handling code for 5000-series systems equipped
  *     with parity error detection logic, i.e. DECstation/DECsystem
  *     5000/120, /125, /133 (KN02-BA), 5000/150 (KN04-BA) and Personal
index e523454bda3af5588524fa283bbe165338342a73..8c8498159e434fa039f7ecae3e290ee0c31d6677 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     arch/mips/dec/prom/call_o32.S
- *
  *     O32 interface for the 64 (or N32) ABI.
  *
  *     Copyright (C) 2002  Maciej W. Rozycki
index 078e1a12421d736896f670c4019d7fc879b17395..caa6e047caf1c3ec59dffd5569b5bad9c8a7247b 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     arch/mips/dec/prom/console.c
- *
  *     DECstation PROM-based early console support.
  *
  *     Copyright (C) 2004, 2007  Maciej W. Rozycki
index 1359c03ded5111adb0892029b59ebffbd26eee7f..463136e6685ac80e70359a24f747cc9a221ad999 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/arch/mips/dec/time.c
- *
  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
  *  Copyright (C) 2000, 2003  Maciej W. Rozycki
  *
index c392d28c1ef1b652fc8c229337a175816f871895..f27d84d1904fb4b6bc38d1e81981cf8c4d41f613 100644 (file)
@@ -1,7 +1,4 @@
 #
-#  arch/mips/emma2rh/common/Makefile
-#       Makefile for the common code of NEC EMMA2RH based board.
-#
 #  Copyright (C) NEC Electronics Corporation 2005-2006
 #
 #  This program is free software; you can redistribute it and/or modify
index 120f53fbdb4583d3019f7a2af10a3ca8fe220a80..708f08761406fe3bfdbd308822f163a2ae7c9822 100644 (file)
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/emma2rh/common/prom.c
- *      This file is prom file.
- *
  *  Copyright (C) NEC Electronics Corporation 2004-2006
  *
  *  This file is based on the arch/mips/ddb5xxx/common/prom.c
index 16e0017ba91914b1236497598d36fb18154e4157..f8ba2508fa2b2b13d853b1ca0fc930e635d3f293 100644 (file)
@@ -1,7 +1,4 @@
 #
-#  arch/mips/emma2rh/markeins/Makefile
-#       Makefile for the common code of NEC EMMA2RH based board.
-#
 #  Copyright (C) NEC Electronics Corporation 2005-2006
 #
 #  This program is free software; you can redistribute it and/or modify
index 43828ae796ec9d0d3276b50ffe5b8f0c29ea1b2f..9504b7ee0b7c0d51a5adf1c3fd4fa702d414b660 100644 (file)
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/emma2rh/markeins/irq.c
- *      This file defines the irq handler for EMMA2RH.
- *
  *  Copyright (C) NEC Electronics Corporation 2004-2006
  *
  *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c
index 377a181b6561d630197bec4a42a2eff460f8e3f1..49755896857fdd0d4382820d258d5a7220ec3e7a 100644 (file)
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/emma2rh/markeins/led.c
- *      This file defines the led display for Mark-eins.
- *
  *  Copyright (C) NEC Electronics Corporation 2004-2006
  *
  *  This program is free software; you can redistribute it and/or modify
index 80ae12ef87db8d31d4b2a2df247a4ca4507801ba..b05b08b92a3466f8745e0d283f123e4ede1000ff 100644 (file)
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/emma2rh/markeins/platofrm.c
- *      This file sets up platform devices for EMMA2RH Mark-eins.
- *
  *  Copyright(C) MontaVista Software Inc, 2006
  *
  *  Author: dmitry pervushin <dpervushin@ru.mvista.com>
index 67f456500084c63f78568e986922d17ab9d42bb7..335dc8c1a1bb47826fecec2aee444ab017b5acb8 100644 (file)
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/emma2rh/markeins/setup.c
- *      This file is setup for EMMA2RH Mark-eins.
- *
  *  Copyright (C) NEC Electronics Corporation 2004-2006
  *
  *  This file is based on the arch/mips/ddb5xxx/ddb5477/setup.c.
index bdf7d1d4081a19e494ebd84bb7418dde399815a7..e0a68713b3c3ee0f07cda100fcfb79146f311324 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     arch/mips/dec/prom/call_o32.S
- *
  *     O32 interface for the 64 (or N32) ABI.
  *
  *     Copyright (C) 2002  Maciej W. Rozycki
index 5ec1c2ffd3a5e24b8c588156288c26195ebfb84e..6f9d0858f596e1ad53445c051a057b0cad348b22 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Registration of WRPPMC UART platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/include/asm/amon.h b/arch/mips/include/asm/amon.h
new file mode 100644 (file)
index 0000000..c3dc1a6
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Amon support
+ */
+
+int amon_cpu_avail(int);
+void amon_cpu_start(int, unsigned long, unsigned long,
+                   unsigned long, unsigned long);
index ba1702e86931bff400708ee1c6d23089c9e705ed..3af0b8fb3b8c23500f9cd7476f769ae36cc05cfc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  DS1287 timer functions.
  *
- *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index d58f128aa747be974ac10ffd5fb1749d3292f505..7990694cda221dbd9f0da1c2b11b4f8e77688680 100644 (file)
@@ -316,9 +316,13 @@ extern void elf_dump_regs(elf_greg_t *, struct pt_regs *regs);
 extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
 extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
 
+#ifndef ELF_CORE_COPY_REGS
 #define ELF_CORE_COPY_REGS(elf_regs, regs)                     \
        elf_dump_regs((elf_greg_t *)&(elf_regs), regs);
+#endif
+#ifndef ELF_CORE_COPY_TASK_REGS
 #define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
+#endif
 #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs)                  \
        dump_task_fpu(tsk, elf_fpregs)
 
index 30aea91de626122d6f27af5195c504deb56988b4..2afb2fe11b300a84d4332970788058b78c35eeb2 100644 (file)
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/include/asm/emma/emma2rh.h
- *      This file is EMMA2RH common header.
- *
  *  Copyright (C) NEC Electronics Corporation 2005-2006
  *
  *  This file based on include/asm-mips/ddb5xxx/ddb5xxx.h
index 973b0628490db4dfa36af9d6d13bc9217785e2da..2618bf230248b5e1711e7a2a83bae5f7eae9f9d1 100644 (file)
@@ -1,7 +1,4 @@
 /*
- *  include/asm-mips/emma2rh/markeins.h
- *      This file is EMMA2RH board depended header.
- *
  *  Copyright (C) NEC Electronics Corporation 2005-2006
  *
  *  This file based on include/asm-mips/ddb5xxx/ddb5xxx.h
index d74a8a4ca861a9d5b2de96e995e5e7b1302b26d5..36fd969d64d6fc83a1b37daf5a22fe3b46c504b1 100644 (file)
 #define GCMP_CCB_DINTGROUP_OFS         0x0030          /* DINT Group Participate */
 #define GCMP_CCB_DBGGROUP_OFS          0x0100          /* DebugBreak Group */
 
+extern int __init gcmp_probe(unsigned long, unsigned long);
+
 #endif /* _ASM_GCMPREGS_H */
index 954807d9d66ae82233cc48362c0ebeb7ce144eff..a8f57341f12364eca41411cf8041bbcbfa176bea 100644 (file)
 #define GIC_TRIG_EDGE                  1
 #define GIC_TRIG_LEVEL                 0
 
+#ifdef CONFIG_SMP
+#define GIC_NUM_INTRS                  (24 + NR_CPUS * 2)
+#else
 #define GIC_NUM_INTRS                  32
+#endif
 
 #define MSK(n) ((1 << (n)) - 1)
 #define REG32(addr)            (*(volatile unsigned int *) (addr))
@@ -483,5 +487,7 @@ extern void gic_init(unsigned long gic_base_addr,
 
 extern unsigned int gic_get_int(void);
 extern void gic_send_ipi(unsigned int intr);
+extern unsigned int plat_ipi_call_int_xlate(unsigned int);
+extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
 
 #endif /* _ASM_GICREGS_H */
index f9a7c3ac2e6677445e25a47df7248b1fd2773f19..250a2407b599c32b51b71d803bce7c4694666854 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Galileo/Marvell GT641xx IRQ definitions.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff --git a/arch/mips/include/asm/mach-ar7/ar7.h b/arch/mips/include/asm/mach-ar7/ar7.h
new file mode 100644 (file)
index 0000000..de71694
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __AR7_H__
+#define __AR7_H__
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+
+#include <asm/addrspace.h>
+
+#define AR7_SDRAM_BASE 0x14000000
+
+#define AR7_REGS_BASE  0x08610000
+
+#define AR7_REGS_MAC0  (AR7_REGS_BASE + 0x0000)
+#define AR7_REGS_GPIO  (AR7_REGS_BASE + 0x0900)
+/* 0x08610A00 - 0x08610BFF (512 bytes, 128 bytes / clock) */
+#define AR7_REGS_POWER (AR7_REGS_BASE + 0x0a00)
+#define AR7_REGS_CLOCKS (AR7_REGS_POWER + 0x80)
+#define UR8_REGS_CLOCKS (AR7_REGS_POWER + 0x20)
+#define AR7_REGS_UART0 (AR7_REGS_BASE + 0x0e00)
+#define AR7_REGS_USB   (AR7_REGS_BASE + 0x1200)
+#define AR7_REGS_RESET (AR7_REGS_BASE + 0x1600)
+#define AR7_REGS_VLYNQ0        (AR7_REGS_BASE + 0x1800)
+#define AR7_REGS_DCL   (AR7_REGS_BASE + 0x1a00)
+#define AR7_REGS_VLYNQ1        (AR7_REGS_BASE + 0x1c00)
+#define AR7_REGS_MDIO  (AR7_REGS_BASE + 0x1e00)
+#define AR7_REGS_IRQ   (AR7_REGS_BASE + 0x2400)
+#define AR7_REGS_MAC1  (AR7_REGS_BASE + 0x2800)
+
+#define AR7_REGS_WDT   (AR7_REGS_BASE + 0x1f00)
+#define UR8_REGS_WDT   (AR7_REGS_BASE + 0x0b00)
+#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00)
+
+#define AR7_RESET_PEREPHERIAL  0x0
+#define AR7_RESET_SOFTWARE     0x4
+#define AR7_RESET_STATUS       0x8
+
+#define AR7_RESET_BIT_CPMAC_LO 17
+#define AR7_RESET_BIT_CPMAC_HI 21
+#define AR7_RESET_BIT_MDIO     22
+#define AR7_RESET_BIT_EPHY     26
+
+/* GPIO control registers */
+#define AR7_GPIO_INPUT 0x0
+#define AR7_GPIO_OUTPUT        0x4
+#define AR7_GPIO_DIR   0x8
+#define AR7_GPIO_ENABLE        0xc
+
+#define AR7_CHIP_7100  0x18
+#define AR7_CHIP_7200  0x2b
+#define AR7_CHIP_7300  0x05
+
+/* Interrupts */
+#define AR7_IRQ_UART0  15
+#define AR7_IRQ_UART1  16
+
+/* Clocks */
+#define AR7_AFE_CLOCK  35328000
+#define AR7_REF_CLOCK  25000000
+#define AR7_XTAL_CLOCK 24000000
+
+struct plat_cpmac_data {
+       int reset_bit;
+       int power_bit;
+       u32 phy_mask;
+       char dev_addr[6];
+};
+
+struct plat_dsl_data {
+       int reset_bit_dsl;
+       int reset_bit_sar;
+};
+
+extern int ar7_cpu_clock, ar7_bus_clock, ar7_dsp_clock;
+
+static inline u16 ar7_chip_id(void)
+{
+       return readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff;
+}
+
+static inline u8 ar7_chip_rev(void)
+{
+       return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) >> 16) & 0xff;
+}
+
+static inline int ar7_cpu_freq(void)
+{
+       return ar7_cpu_clock;
+}
+
+static inline int ar7_bus_freq(void)
+{
+       return ar7_bus_clock;
+}
+
+static inline int ar7_vbus_freq(void)
+{
+       return ar7_bus_clock / 2;
+}
+#define ar7_cpmac_freq ar7_vbus_freq
+
+static inline int ar7_dsp_freq(void)
+{
+       return ar7_dsp_clock;
+}
+
+static inline int ar7_has_high_cpmac(void)
+{
+       u16 chip_id = ar7_chip_id();
+       switch (chip_id) {
+       case AR7_CHIP_7100:
+       case AR7_CHIP_7200:
+               return 0;
+       case AR7_CHIP_7300:
+               return 1;
+       default:
+               return -ENXIO;
+       }
+}
+#define ar7_has_high_vlynq ar7_has_high_cpmac
+#define ar7_has_second_uart ar7_has_high_cpmac
+
+static inline void ar7_device_enable(u32 bit)
+{
+       void *reset_reg =
+               (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
+       writel(readl(reset_reg) | (1 << bit), reset_reg);
+       msleep(20);
+}
+
+static inline void ar7_device_disable(u32 bit)
+{
+       void *reset_reg =
+               (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL);
+       writel(readl(reset_reg) & ~(1 << bit), reset_reg);
+       msleep(20);
+}
+
+static inline void ar7_device_reset(u32 bit)
+{
+       ar7_device_disable(bit);
+       ar7_device_enable(bit);
+}
+
+static inline void ar7_device_on(u32 bit)
+{
+       void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
+       writel(readl(power_reg) | (1 << bit), power_reg);
+       msleep(20);
+}
+
+static inline void ar7_device_off(u32 bit)
+{
+       void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER);
+       writel(readl(power_reg) & ~(1 << bit), power_reg);
+       msleep(20);
+}
+
+#endif /* __AR7_H__ */
diff --git a/arch/mips/include/asm/mach-ar7/gpio.h b/arch/mips/include/asm/mach-ar7/gpio.h
new file mode 100644 (file)
index 0000000..cbe9c4f
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __AR7_GPIO_H__
+#define __AR7_GPIO_H__
+
+#include <asm/mach-ar7/ar7.h>
+
+#define AR7_GPIO_MAX 32
+
+extern int gpio_request(unsigned gpio, const char *label);
+extern void gpio_free(unsigned gpio);
+
+/* Common GPIO layer */
+static inline int gpio_get_value(unsigned gpio)
+{
+       void __iomem *gpio_in =
+               (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_INPUT);
+
+       return readl(gpio_in) & (1 << gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+       void __iomem *gpio_out =
+               (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_OUTPUT);
+       unsigned tmp;
+
+       tmp = readl(gpio_out) & ~(1 << gpio);
+       if (value)
+               tmp |= 1 << gpio;
+       writel(tmp, gpio_out);
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+       void __iomem *gpio_dir =
+               (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR);
+
+       if (gpio >= AR7_GPIO_MAX)
+               return -EINVAL;
+
+       writel(readl(gpio_dir) | (1 << gpio), gpio_dir);
+
+       return 0;
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+       void __iomem *gpio_dir =
+               (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR);
+
+       if (gpio >= AR7_GPIO_MAX)
+               return -EINVAL;
+
+       gpio_set_value(gpio, value);
+       writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir);
+
+       return 0;
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+       return -EINVAL;
+}
+
+static inline int irq_to_gpio(unsigned irq)
+{
+       return -EINVAL;
+}
+
+/* Board specific GPIO functions */
+static inline int ar7_gpio_enable(unsigned gpio)
+{
+       void __iomem *gpio_en =
+               (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE);
+
+       writel(readl(gpio_en) | (1 << gpio), gpio_en);
+
+       return 0;
+}
+
+static inline int ar7_gpio_disable(unsigned gpio)
+{
+       void __iomem *gpio_en =
+               (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE);
+
+       writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
+
+       return 0;
+}
+
+#include <asm-generic/gpio.h>
+
+#endif
diff --git a/arch/mips/include/asm/mach-ar7/irq.h b/arch/mips/include/asm/mach-ar7/irq.h
new file mode 100644 (file)
index 0000000..39e9757
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Shamelessly copied from asm-mips/mach-emma2rh/
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_AR7_IRQ_H
+#define __ASM_AR7_IRQ_H
+
+#define NR_IRQS        256
+
+#include_next <irq.h>
+
+#endif /* __ASM_AR7_IRQ_H */
diff --git a/arch/mips/include/asm/mach-ar7/prom.h b/arch/mips/include/asm/mach-ar7/prom.h
new file mode 100644 (file)
index 0000000..088f61f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2006, 2007 Florian Fainelli <florian@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __PROM_H__
+#define __PROM_H__
+
+extern char *prom_getenv(const char *name);
+extern void prom_meminit(void);
+
+#endif /* __PROM_H__ */
diff --git a/arch/mips/include/asm/mach-ar7/spaces.h b/arch/mips/include/asm/mach-ar7/spaces.h
new file mode 100644 (file)
index 0000000..ac28f27
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
+ * Copyright (C) 2000, 2002  Maciej W. Rozycki
+ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_AR7_SPACES_H
+#define _ASM_AR7_SPACES_H
+
+/*
+ * This handles the memory map.
+ * We handle pages at KSEG0 for kernels with 32 bit address space.
+ */
+#define PAGE_OFFSET            0x94000000UL
+#define PHYS_OFFSET            0x14000000UL
+
+#include <asm/mach-generic/spaces.h>
+
+#endif /* __ASM_AR7_SPACES_H */
diff --git a/arch/mips/include/asm/mach-ar7/war.h b/arch/mips/include/asm/mach-ar7/war.h
new file mode 100644 (file)
index 0000000..f4862b5
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MIPS_MACH_AR7_WAR_H
+#define __ASM_MIPS_MACH_AR7_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR    0
+#define R4600_V1_HIT_CACHEOP_WAR       0
+#define R4600_V2_HIT_CACHEOP_WAR       0
+#define R5432_CP0_INTERRUPT_WAR                0
+#define BCM1250_M3_WAR                 0
+#define SIBYTE_1956_WAR                        0
+#define MIPS4K_ICACHE_REFILL_WAR       0
+#define MIPS_CACHE_SYNC_WAR            0
+#define TX49XX_ICACHE_INDEX_INV_WAR    0
+#define RM9000_CDEX_SMP_WAR            0
+#define ICACHE_REFILLS_WORKAROUND_WAR  0
+#define R10000_LLSC_WAR                        0
+#define MIPS34K_MISSED_ITLB_WAR                0
+
+#endif /* __ASM_MIPS_MACH_AR7_WAR_H */
index 57c8c9ac585162b6a16a32d912d7d438d0a772be..9da9acf5dcba4754642404fc05380946aa4a7ff8 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright (C) 1997 Cobalt Microserver
  * Copyright (C) 1997, 2003 Ralf Baechle
  * Copyright (C) 2001-2003 Liam Davies (ldavies@agile.tv)
- * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org>
  */
 #ifndef _ASM_COBALT_IRQ_H
 #define _ASM_COBALT_IRQ_H
index ae9c5523c7effae9679ce4c3b79a290121d58fd0..f8afec3f294330ea4322211f7b640f4146aabad8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2006  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
similarity index 52%
rename from arch/mips/cavium-octeon/pci-common.h
rename to arch/mips/include/asm/octeon/pci-octeon.h
index 74ae79991e456410f35424b09b4d180feceab6cc..6ac5d3e3398eaff20144dafc5190910eb8f4ef13 100644 (file)
@@ -3,23 +3,29 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2005-2007 Cavium Networks
+ * Copyright (C) 2005-2009 Cavium Networks
  */
-#ifndef __OCTEON_PCI_COMMON_H__
-#define __OCTEON_PCI_COMMON_H__
+
+#ifndef __PCI_OCTEON_H__
+#define __PCI_OCTEON_H__
 
 #include <linux/pci.h>
 
 /* Some PCI cards require delays when accessing config space. */
 #define PCI_CONFIG_SPACE_DELAY 10000
 
-/* pcibios_map_irq() is defined inside pci-common.c. All it does is call the
-   Octeon specific version pointed to by this variable. This function needs to
-   change for PCI or PCIe based hosts */
-extern typeof(pcibios_map_irq) *octeon_pcibios_map_irq;
+/*
+ * pcibios_map_irq() is defined inside pci-octeon.c. All it does is
+ * call the Octeon specific version pointed to by this variable. This
+ * function needs to change for PCI or PCIe based hosts.
+ */
+extern int (*octeon_pcibios_map_irq)(const struct pci_dev *dev,
+                                    u8 slot, u8 pin);
 
-/* The following defines are only used when octeon_dma_bar_type =
-   OCTEON_DMA_BAR_TYPE_BIG */
+/*
+ * The following defines are used when octeon_dma_bar_type =
+ * OCTEON_DMA_BAR_TYPE_BIG
+ */
 #define OCTEON_PCI_BAR1_HOLE_BITS 5
 #define OCTEON_PCI_BAR1_HOLE_SIZE (1ul<<(OCTEON_PCI_BAR1_HOLE_BITS+3))
 
@@ -30,9 +36,9 @@ enum octeon_dma_bar_type {
        OCTEON_DMA_BAR_TYPE_PCIE
 };
 
-/**
- * This is a variable to tell the DMA mapping system in dma-octeon.c
- * how to map PCI DMA addresses.
+/*
+ * This tells the DMA mapping system in dma-octeon.c how to map PCI
+ * DMA addresses.
  */
 extern enum octeon_dma_bar_type octeon_dma_bar_type;
 
index dc0eaa7312816112a006cb6af0a0b0b6f5022979..4320239cf4ef1c73e57ffba2288f9226dbbe8c2f 100644 (file)
 #define PAGE_SIZE      (1UL << PAGE_SHIFT)
 #define PAGE_MASK       (~((1 << PAGE_SHIFT) - 1))
 
+#ifdef CONFIG_HUGETLB_PAGE
 #define HPAGE_SHIFT    (PAGE_SHIFT + PAGE_SHIFT - 3)
 #define HPAGE_SIZE     ((1UL) << HPAGE_SHIFT)
 #define HPAGE_MASK     (~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT - PAGE_SHIFT)
+#endif /* CONFIG_HUGETLB_PAGE */
 
 #ifndef __ASSEMBLY__
 
@@ -165,7 +167,14 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 
 #ifdef CONFIG_FLATMEM
 
-#define pfn_valid(pfn)         ((pfn) >= ARCH_PFN_OFFSET && (pfn) < max_mapnr)
+#define pfn_valid(pfn)                                                 \
+({                                                                     \
+       unsigned long __pfn = (pfn);                                    \
+       /* avoid <linux/bootmem.h> include hell */                      \
+       extern unsigned long min_low_pfn;                               \
+                                                                       \
+       __pfn >= min_low_pfn && __pfn < max_mapnr;                      \
+})
 
 #elif defined(CONFIG_SPARSEMEM)
 
index 1275831dda29b65ae90d2046f781a747cb4a3df0..3738f4b48cbd63b75b9b91095c6ef9807f26866d 100644 (file)
@@ -98,23 +98,12 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
        __free_pages(pte, PTE_ORDER);
 }
 
-#define __pte_free_tlb(tlb,pte)                                \
+#define __pte_free_tlb(tlb,pte,address)                        \
 do {                                                   \
        pgtable_page_dtor(pte);                         \
        tlb_remove_page((tlb), pte);                    \
 } while (0)
 
-#ifdef CONFIG_32BIT
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-#define pmd_free(mm, x)                        do { } while (0)
-#define __pmd_free_tlb(tlb, x)         do { } while (0)
-
-#endif
-
 #ifdef CONFIG_64BIT
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
@@ -132,7 +121,7 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
        free_pages((unsigned long)pmd, PMD_ORDER);
 }
 
-#define __pmd_free_tlb(tlb, x) pmd_free((tlb)->mm, x)
+#define __pmd_free_tlb(tlb, x, addr)   pmd_free((tlb)->mm, x)
 
 #endif
 
index 0bf48fc1892b5e97c8f746ddef0f1673b58cb043..9e2ee429c52945809ad8bac3ec47f8560508aeb8 100644 (file)
@@ -23,6 +23,8 @@
 #if defined(CONFIG_PMC_MSP7120_EVAL) || defined(CONFIG_PMC_MSP7120_GW) || \
        defined(CONFIG_PMC_MSP7120_FPGA)
 #define MIPS34K_MISSED_ITLB_WAR         1
+#else
+#define MIPS34K_MISSED_ITLB_WAR         0
 #endif
 
 #endif /* __ASM_MIPS_PMC_SIERRA_WAR_H */
index 0f926aa0cb472746101b1fe905fc243db392f6cc..087a8884ef06e261e46f3480040cd9667066bdd8 100644 (file)
@@ -311,8 +311,9 @@ extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long
 
 unsigned long get_wchan(struct task_struct *p);
 
-#define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + THREAD_SIZE - 32)
-#define task_pt_regs(tsk) ((struct pt_regs *)__KSTK_TOS(tsk) - 1)
+#define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + \
+                        THREAD_SIZE - 32 - sizeof(struct pt_regs))
+#define task_pt_regs(tsk) ((struct pt_regs *)__KSTK_TOS(tsk))
 #define KSTK_EIP(tsk) (task_pt_regs(tsk)->cp0_epc)
 #define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[29])
 #define KSTK_STATUS(tsk) (task_pt_regs(tsk)->cp0_status)
index 634b55d7e7f6d1ada10dfa02175c11a81790f78d..910e71a12466de2f1fb3f1fab82c6203ef062e63 100644 (file)
@@ -69,7 +69,7 @@
 
 #endif
 
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && !defined(WANT_COMPAT_REG_H)
 
 #define EF_R0                   0
 #define EF_R1                   1
index 99993c0d6c12bb3ea50996991c8072ed254d7155..97c2f81b4b43af66d766778ea2c17dcca6d8303b 100644 (file)
@@ -38,7 +38,11 @@ static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
 }
 #define __arch_swab32 __arch_swab32
 
-#ifdef CONFIG_CPU_MIPS64_R2
+/*
+ * Having already checked for CONFIG_CPU_MIPSR2, enable the
+ * optimized version for 64-bit kernel on r2 CPUs.
+ */
+#ifdef CONFIG_64BIT
 static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
 {
        __asm__(
@@ -50,6 +54,6 @@ static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
        return x;
 }
 #define __arch_swab64 __arch_swab64
-#endif /* CONFIG_CPU_MIPS64_R2 */
+#endif /* CONFIG_64BIT */
 #endif /* CONFIG_CPU_MIPSR2 */
 #endif /* _ASM_SWAB_H */
index 143a48136a4b0f7e599adf1ce41d2bea290a7777..f9df720d2e40e215aa0cb21561f467d6d95a2b6b 100644 (file)
@@ -39,8 +39,6 @@ struct thread_info {
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #define INIT_THREAD_INFO(tsk)                  \
 {                                              \
@@ -48,7 +46,7 @@ struct thread_info {
        .exec_domain    = &default_exec_domain, \
        .flags          = _TIF_FIXADE,          \
        .cpu            = 0,                    \
-       .preempt_count  = 1,                    \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .addr_limit     = KERNEL_DS,            \
        .restart_block  = {                     \
                .fn = do_no_restart_syscall,    \
index 40005010827cb4f72c1734778a520a74c7958153..e753a777949b589a1187975e97bb7659915a3ef7 100644 (file)
 #define __NR_inotify_init1             (__NR_Linux + 329)
 #define __NR_preadv                    (__NR_Linux + 330)
 #define __NR_pwritev                   (__NR_Linux + 331)
+#define __NR_rt_tgsigqueueinfo         (__NR_Linux + 332)
+#define __NR_perf_counter_open         (__NR_Linux + 333)
+#define __NR_accept4                   (__NR_Linux + 334)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            331
+#define __NR_Linux_syscalls            334
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                331
+#define __NR_O32_Linux_syscalls                334
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_inotify_init1             (__NR_Linux + 288)
 #define __NR_preadv                    (__NR_Linux + 289)
 #define __NR_pwritev                   (__NR_Linux + 290)
+#define __NR_rt_tgsigqueueinfo         (__NR_Linux + 291)
+#define __NR_perf_counter_open         (__NR_Linux + 292)
+#define __NR_accept4                   (__NR_Linux + 293)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            290
+#define __NR_Linux_syscalls            293
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         290
+#define __NR_64_Linux_syscalls         293
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_inotify_init1             (__NR_Linux + 292)
 #define __NR_preadv                    (__NR_Linux + 293)
 #define __NR_pwritev                   (__NR_Linux + 294)
+#define __NR_rt_tgsigqueueinfo         (__NR_Linux + 295)
+#define __NR_perf_counter_open         (__NR_Linux + 296)
+#define __NR_accept4                   (__NR_Linux + 297)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            294
+#define __NR_Linux_syscalls            297
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                294
+#define __NR_N32_Linux_syscalls                297
 
 #ifdef __KERNEL__
 
index e0ee05a3dfcccfd3c1bc13e1d843793bfb78f8ba..fcc6569414faaf2fda683289894fa78a32e8f985 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  capcella.h, Include file for ZAO Networks Capcella.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 0bcdd3a5c2560b6817174af92d1e1dbfe2a9cd07..6a90bc1d916b4aa58ddc57ae6edd8ee40ae9b4ee 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Include file for NEC VR4100 series General-purpose I/O Unit.
  *
- *  Copyright (C) 2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005-2009  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -41,7 +41,8 @@ typedef enum {
        IRQ_SIGNAL_HOLD,
 } irq_signal_t;
 
-extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal);
+extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
+                                  irq_signal_t signal);
 
 typedef enum {
        IRQ_LEVEL_LOW,
@@ -50,23 +51,6 @@ typedef enum {
 
 extern void vr41xx_set_irq_level(unsigned int pin, irq_level_t level);
 
-typedef enum {
-       GPIO_DATA_LOW,
-       GPIO_DATA_HIGH,
-       GPIO_DATA_INVAL,
-} gpio_data_t;
-
-extern gpio_data_t vr41xx_gpio_get_pin(unsigned int pin);
-extern int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data);
-
-typedef enum {
-       GPIO_INPUT,
-       GPIO_OUTPUT,
-       GPIO_OUTPUT_DISABLE,
-} gpio_direction_t;
-
-extern int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir);
-
 typedef enum {
        GPIO_PULL_DOWN,
        GPIO_PULL_UP,
index d315dfbc08f2c269fcc4b0c1ebfde5b0b38c5292..b07f7321751dd577004e4e3025acc272a09d31f2 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 2001, 2002 Paul Mundt
  * Copyright (C) 2002 MontaVista Software, Inc.
  * Copyright (C) 2002 TimeSys Corp.
- * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2003-2006 Yoichi Yuasa <yuasa@linux-mips.org>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
index 1d67df843dc32d93f9feada3ab2a3d0df5fe0454..130d09d8c8cbbc285a44fca21063569a4004454b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  mpc30x.h, Include file for Victor MP-C303/304.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 6fc01ce1977706fbb09325299342d55d7b073358..c231a3d6cfd8fb5ccb01b1da7cdb72238c1a84b3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Include file for NEC VR4100 series PCI Control Unit.
  *
- *  Copyright (C) 2004-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index da9f6e3734099b31198cf31dd77b6070e158fdbb..ca806bc4ddc8a8857247e3985672a8d343c49a0f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Include file for NEC VR4100 series Serial Interface Unit.
  *
- *  Copyright (C) 2005-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index dc981b4be0a404bd0ff3090baccbcd22be8d20ed..c78e8243b447e3b4fde3d697d58be19d125a6c45 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  tb0219.h, Include file for TANBAC TB0219.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  Modified for TANBAC TB0219:
  *  Copyright (C) 2003 Megasolution Inc.  <matsu@megasolution.jp>
index de527dcfa5f31b0301430c170aa36cc0afba32bf..36f5f798e4169cb4a05db452960fcb97bbffa9be 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  tb0226.h, Include file for TANBAC TB0226.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 22be64971cc69202823ddb79ff83f32500f1a7da..7b96a43b72ba5e09351f48e21a7d7d01006d1624 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 2001, 2002 Paul Mundt
  * Copyright (C) 2002 MontaVista Software, Inc.
  * Copyright (C) 2002 TimeSys Corp.
- * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2003-2008 Yoichi Yuasa <yuasa@linux-mips.org>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
index f0fd636723be1d2663e16ada6af9aeab32a225cb..0d64d0f464185c0c9c383fcad2e1d30416afc854 100644 (file)
@@ -190,7 +190,7 @@ int vdma_free(unsigned long laddr)
                return -1;
        }
 
-       while (pgtbl[i].owner == laddr && i < VDMA_PGTBL_ENTRIES) {
+       while (i < VDMA_PGTBL_ENTRIES && pgtbl[i].owner == laddr) {
                pgtbl[i].owner = VDMA_PAGE_EMPTY;
                i++;
        }
index e1333d7319e275a065546490baa8401b87c9bf47..ff448233dab55737ca2ba1aa54edfa252263b924 100644 (file)
@@ -53,6 +53,23 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 #define ELF_ET_DYN_BASE         (TASK32_SIZE / 3 * 2)
 
 #include <asm/processor.h>
+
+/*
+ * When this file is selected, we are definitely running a 64bit kernel.
+ * So using the right regs define in asm/reg.h
+ */
+#define WANT_COMPAT_REG_H
+
+/* These MUST be defined before elf.h gets included */
+extern void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs);
+#define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs);
+#define ELF_CORE_COPY_TASK_REGS(_tsk, _dest)                           \
+({                                                                     \
+       int __res = 1;                                                  \
+       elf32_core_copy_regs(*(_dest), task_pt_regs(_tsk));             \
+       __res;                                                          \
+})
+
 #include <linux/module.h>
 #include <linux/elfcore.h>
 #include <linux/compat.h>
@@ -110,9 +127,6 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
        value->tv_usec = rem / NSEC_PER_USEC;
 }
 
-#undef ELF_CORE_COPY_REGS
-#define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs);
-
 void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs)
 {
        int i;
index 1ada45ea07003d426cf591b2d639d45ffda0c53b..6996da4d74a276ed1d61cf07459fb7ac82dfd7db 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  DS1287 clockevent driver
  *
- *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index e9b787feedcb7595fb763e057cfb18a06fb1ede1..92351e00ae0e2ff3f98f8d7432aebf88d659966f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  GT641xx clockevent routines.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index b551f48d3a076483eccd3b543f6188c4f87797df..23da108506b0a325a8c0c4f8de12d744129d2676 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  DEC I/O ASIC's counter clocksource
  *
- *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 492a0a8d70fbf9ddc6e695ae8250e562f03f0ab5..531ce7b1612479305c05602def67bd7e100f7992 100644 (file)
@@ -188,7 +188,8 @@ NESTED(kernel_entry, 16, sp)                        # kernel entry point
 
        MTC0            zero, CP0_CONTEXT       # clear context register
        PTR_LA          $28, init_thread_union
-       PTR_LI          sp, _THREAD_SIZE - 32
+       /* Set the SP after an empty pt_regs.  */
+       PTR_LI          sp, _THREAD_SIZE - 32 - PT_SIZE
        PTR_ADDU        sp, $28
        set_saved_sp    sp, t0, t1
        PTR_SUBU        sp, 4 * SZREG           # init stack pointer
index 39000f103f2caf250cdd26297e0c70cd33e3b201..d2072cd385922db78c5b1278622ad4d4243a4949 100644 (file)
@@ -107,9 +107,7 @@ static unsigned int gic_irq_startup(unsigned int irq)
 {
        pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
-       GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))),
-                1 << (irq % 32));
+       GIC_SET_INTR_MASK(irq, 1);
        return 0;
 }
 
@@ -120,8 +118,7 @@ static void gic_irq_ack(unsigned int irq)
 #endif
        pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))),
-                1 << (irq % 32));
+       GIC_CLR_INTR_MASK(irq, 1);
 
        if (_intrmap[irq].trigtype == GIC_TRIG_EDGE) {
                if (!gic_wedgeb2bok)
@@ -138,18 +135,14 @@ static void gic_mask_irq(unsigned int irq)
 {
        pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
-       GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_RMASK_31_0_OFS + (irq / 32))),
-                1 << (irq % 32));
+       GIC_CLR_INTR_MASK(irq, 1);
 }
 
 static void gic_unmask_irq(unsigned int irq)
 {
        pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
        irq -= _irqbase;
-       /* FIXME: this is wrong for !GICISWORDLITTLEENDIAN */
-       GICWRITE(GIC_REG_ADDR(SHARED, (GIC_SH_SMASK_31_0_OFS + (irq / 32))),
-                1 << (irq % 32));
+       GIC_SET_INTR_MASK(irq, 1);
 }
 
 #ifdef CONFIG_SMP
@@ -254,6 +247,10 @@ static void __init gic_basic_init(void)
                if (cpu == X)
                        continue;
 
+               if (cpu == 0 && i != 0 && _intrmap[i].intrnum == 0 &&
+                                       _intrmap[i].ipiflag == 0)
+                       continue;
+
                setup_intr(_intrmap[i].intrnum,
                                _intrmap[i].cpunum,
                                _intrmap[i].pin,
index 1b81b131f43c9acff2f39b9b954651555020a06a..ebcc5f7ad9c21e6155413e826613c5dc39c58220 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  GT641xx IRQ routines.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index a4d1462c27f7adcc3b327fbca87669cc55553e8f..9b78029bea7026f237a337f981f0dd98c90661b5 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/arch/mips/kernel/irq_txx9.c
- *
  * Based on linux/arch/mips/jmr3927/rbhma3100/irq.c,
  *          linux/arch/mips/tx4927/common/tx4927_irq.c,
  *          linux/arch/mips/tx4938/common/irq.c
index 3e9100dcc12db963337da41a7b47e6b8d1faed59..6f51dda87fce8869dec4697046bcee532e14a9ee 100644 (file)
@@ -98,7 +98,8 @@ static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v)
 static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
 {
        if (v % 4) {
-               printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
+               pr_err("module %s: dangerous R_MIPS_26 REL relocation\n",
+                      me->name);
                return -ENOEXEC;
        }
 
@@ -118,7 +119,8 @@ static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
 static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
 {
        if (v % 4) {
-               printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
+               pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n",
+                      me->name);
                return -ENOEXEC;
        }
 
@@ -222,7 +224,7 @@ static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v)
        return 0;
 
 out_danger:
-       printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name);
+       pr_err("module %s: dangerous R_MIPS_LO16 REL relocation\n", me->name);
 
        return -ENOEXEC;
 }
@@ -301,7 +303,7 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
                /* This is the symbol it is referring to */
                sym = (Elf_Sym *)sechdrs[symindex].sh_addr
                        + ELF_MIPS_R_SYM(rel[i]);
-               if (!sym->st_value) {
+               if (IS_ERR_VALUE(sym->st_value)) {
                        /* Ignore unresolved weak symbol */
                        if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
                                continue;
@@ -341,7 +343,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
                /* This is the symbol it is referring to */
                sym = (Elf_Sym *)sechdrs[symindex].sh_addr
                        + ELF_MIPS_R_SYM(rel[i]);
-               if (!sym->st_value) {
+               if (IS_ERR_VALUE(sym->st_value)) {
                        /* Ignore unresolved weak symbol */
                        if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
                                continue;
index e0a4ac18fa07e72f62d38089aa9d3ba9f472c51f..26109c4d51704ae5ca9a1d83cacc4fe30b3c399d 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/arch/mips/kernel/proc.c
- *
  *  Copyright (C) 1995, 1996, 2001  Ralf Baechle
  *  Copyright (C) 2001, 2004  MIPS Technologies, Inc.
  *  Copyright (C) 2004  Maciej W. Rozycki
index c09d681b7181dbc15851cc9f425ae98ba6e3c561..f3d73e1831c1567ccb674429eb83492feb2942e1 100644 (file)
@@ -115,7 +115,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 {
        struct thread_info *ti = task_thread_info(p);
        struct pt_regs *childregs;
-       long childksp;
+       unsigned long childksp;
        p->set_child_tid = p->clear_child_tid = NULL;
 
        childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32;
@@ -132,6 +132,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 
        /* set up new TSS. */
        childregs = (struct pt_regs *) childksp - 1;
+       /*  Put the stack after the struct pt_regs.  */
+       childksp = (unsigned long) childregs;
        *childregs = *regs;
        childregs->regs[7] = 0; /* Clear error flag */
 
index c4f9ac17474a2157d7a6ab12e0c485cd61b11c48..32644b4a07144979be8d1466ad639787abcf795d 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/user.h>
 #include <linux/security.h>
 
index 0b31b9bda0486988128d39d07d52ac2c0d0ad8d8..b57082123536f217726600918330e7e3e92abda9 100644 (file)
@@ -652,6 +652,9 @@ einval:     li      v0, -ENOSYS
        sys     sys_inotify_init1       1
        sys     sys_preadv              6       /* 4330 */
        sys     sys_pwritev             6
+       sys     sys_rt_tgsigqueueinfo   4
+       sys     sys_perf_counter_open   5
+       sys     sys_accept4             4
        .endm
 
        /* We pre-compute the number of _instruction_ bytes needed to
index c647fd6e722f7acb2872ad0f01491b6f2a2637e9..3d866f24e06442995b7c1c106e628b28e7c4fb18 100644 (file)
@@ -489,4 +489,7 @@ sys_call_table:
        PTR     sys_inotify_init1
        PTR     sys_preadv
        PTR     sys_pwritev                     /* 5390 */
+       PTR     sys_rt_tgsigqueueinfo
+       PTR     sys_perf_counter_open
+       PTR     sys_accept4
        .size   sys_call_table,.-sys_call_table
index 93cc672f4522169977739553eeb1001ddb40bd2b..e855b118a0794f851920eec5c2e291f297e418ff 100644 (file)
@@ -415,4 +415,7 @@ EXPORT(sysn32_call_table)
        PTR     sys_inotify_init1
        PTR     sys_preadv
        PTR     sys_pwritev
+       PTR     compat_sys_rt_tgsigqueueinfo    /* 5295 */
+       PTR     sys_perf_counter_open
+       PTR     sys_accept4
        .size   sysn32_call_table,.-sysn32_call_table
index a5598b2339dd451a4586d3dde4b30050a48c5290..0c49f1a660bebf5968e59a4689a9fcd471a7ebd9 100644 (file)
@@ -535,4 +535,7 @@ sys_call_table:
        PTR     sys_inotify_init1
        PTR     compat_sys_preadv               /* 4330 */
        PTR     compat_sys_pwritev
+       PTR     compat_sys_rt_tgsigqueueinfo
+       PTR     sys_perf_counter_open
+       PTR     sys_accept4
        .size   sys_call_table,.-sys_call_table
index 653be061b9ec6745c17cac05f6f5827ed2013b17..ad0ff5dc4d59bfbcdef6e967f1317b0ea2459c3a 100644 (file)
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/mips_mt.h>
-
-/*
- * Crude manipulation of the CPU masks to control which
- * which CPU's are brought online during initialisation
- *
- * Beware... this needs to be called after CPU discovery
- * but before CPU bringup
- */
-static int __init allowcpus(char *str)
-{
-       cpumask_t cpu_allow_map;
-       char buf[256];
-       int len;
-
-       cpus_clear(cpu_allow_map);
-       if (cpulist_parse(str, &cpu_allow_map) == 0) {
-               cpu_set(0, cpu_allow_map);
-               cpus_and(cpu_possible_map, cpu_possible_map, cpu_allow_map);
-               len = cpulist_scnprintf(buf, sizeof(buf)-1, &cpu_possible_map);
-               buf[len] = '\0';
-               pr_debug("Allowable CPUs: %s\n", buf);
-               return 1;
-       } else
-               return 0;
-}
-__setup("allowcpus=", allowcpus);
+#include <asm/amon.h>
+#include <asm/gic.h>
 
 static void ipi_call_function(unsigned int cpu)
 {
-       unsigned int action = 0;
-
        pr_debug("CPU%d: %s cpu %d status %08x\n",
                 smp_processor_id(), __func__, cpu, read_c0_status());
 
-       switch (cpu) {
-       case 0:
-               action = GIC_IPI_EXT_INTR_CALLFNC_VPE0;
-               break;
-       case 1:
-               action = GIC_IPI_EXT_INTR_CALLFNC_VPE1;
-               break;
-       case 2:
-               action = GIC_IPI_EXT_INTR_CALLFNC_VPE2;
-               break;
-       case 3:
-               action = GIC_IPI_EXT_INTR_CALLFNC_VPE3;
-               break;
-       }
-       gic_send_ipi(action);
+       gic_send_ipi(plat_ipi_call_int_xlate(cpu));
 }
 
 
 static void ipi_resched(unsigned int cpu)
 {
-       unsigned int action = 0;
-
        pr_debug("CPU%d: %s cpu %d status %08x\n",
                 smp_processor_id(), __func__, cpu, read_c0_status());
 
-       switch (cpu) {
-       case 0:
-               action = GIC_IPI_EXT_INTR_RESCHED_VPE0;
-               break;
-       case 1:
-               action = GIC_IPI_EXT_INTR_RESCHED_VPE1;
-               break;
-       case 2:
-               action = GIC_IPI_EXT_INTR_RESCHED_VPE2;
-               break;
-       case 3:
-               action = GIC_IPI_EXT_INTR_RESCHED_VPE3;
-               break;
-       }
-       gic_send_ipi(action);
+       gic_send_ipi(plat_ipi_resched_int_xlate(cpu));
 }
 
 /*
@@ -206,7 +150,7 @@ static void cmp_boot_secondary(int cpu, struct task_struct *idle)
                           (unsigned long)(gp + sizeof(struct thread_info)));
 #endif
 
-       amon_cpu_start(cpu, pc, sp, gp, a0);
+       amon_cpu_start(cpu, pc, sp, (unsigned long)gp, a0);
 }
 
 /*
index 8a0626cbb108ff0a1231dadb74b54b4a2d3576a9..c16bb6d6c25c64f1562ca85f7f6d5a8a7d450a37 100644 (file)
@@ -465,11 +465,8 @@ void smtc_prepare_cpus(int cpus)
        smtc_configure_tlb();
 
        for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) {
-               /*
-                * Set the MVP bits.
-                */
-               settc(tc);
-               write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_MVP);
+               if (tcpervpe[vpe] == 0)
+                       continue;
                if (vpe != 0)
                        printk(", ");
                printk("VPE %d: TC", vpe);
@@ -487,6 +484,12 @@ void smtc_prepare_cpus(int cpus)
                        tc++;
                }
                if (vpe != 0) {
+                       /*
+                        * Allow this VPE to control others.
+                        */
+                       write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() |
+                                             VPECONF0_MVP);
+
                        /*
                         * Clear any stale software interrupts from VPE's Cause
                         */
index 58f5cd76c8c3fedfdb45d46300dc34d67b030e24..d52ff77baf3f8b22f169f8e4aba269fbff2c6941 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/mips/kernel/stacktrace.c
- *
  * Stack trace management functions
  *
  *  Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
index 9021108eb9c1af0edbf67946284ebf3dad8c5513..05dd170a83f7e379ec4e40fe37c454e2c7a4e61a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Count register synchronisation.
  *
- * All CPUs will have their count registers synchronised to the CPU0 expirelo
+ * All CPUs will have their count registers synchronised to the CPU0 next time
  * value. This can cause a small timewarp for CPU0. All other CPU's should
  * not have done anything significant (but they may have had interrupts
  * enabled briefly - prom_smp_finish() should not be responsible for enabling
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irqflags.h>
-#include <linux/r4k-timer.h>
+#include <linux/cpumask.h>
 
+#include <asm/r4k-timer.h>
 #include <asm/atomic.h>
 #include <asm/barrier.h>
-#include <asm/cpumask.h>
 #include <asm/mipsregs.h>
 
-static atomic_t __initdata count_start_flag = ATOMIC_INIT(0);
-static atomic_t __initdata count_count_start = ATOMIC_INIT(0);
-static atomic_t __initdata count_count_stop = ATOMIC_INIT(0);
+static atomic_t __cpuinitdata count_start_flag = ATOMIC_INIT(0);
+static atomic_t __cpuinitdata count_count_start = ATOMIC_INIT(0);
+static atomic_t __cpuinitdata count_count_stop = ATOMIC_INIT(0);
+static atomic_t __cpuinitdata count_reference = ATOMIC_INIT(0);
 
 #define COUNTON        100
 #define NR_LOOPS 5
 
-void __init synchronise_count_master(void)
+void __cpuinit synchronise_count_master(void)
 {
        int i;
        unsigned long flags;
@@ -42,19 +43,20 @@ void __init synchronise_count_master(void)
        return;
 #endif
 
-       pr_info("Checking COUNT synchronization across %u CPUs: ",
-               num_online_cpus());
+       printk(KERN_INFO "Synchronize counters across %u CPUs: ",
+              num_online_cpus());
 
        local_irq_save(flags);
 
        /*
         * Notify the slaves that it's time to start
         */
+       atomic_set(&count_reference, read_c0_count());
        atomic_set(&count_start_flag, 1);
        smp_wmb();
 
-       /* Count will be initialised to expirelo for all CPU's */
-       initcount = expirelo;
+       /* Count will be initialised to current timer for all CPU's */
+       initcount = read_c0_count();
 
        /*
         * We loop a few times to get a primed instruction cache,
@@ -106,7 +108,7 @@ void __init synchronise_count_master(void)
        printk("done.\n");
 }
 
-void __init synchronise_count_slave(void)
+void __cpuinit synchronise_count_slave(void)
 {
        int i;
        unsigned long flags;
@@ -131,8 +133,8 @@ void __init synchronise_count_slave(void)
        while (!atomic_read(&count_start_flag))
                mb();
 
-       /* Count will be initialised to expirelo for all CPU's */
-       initcount = expirelo;
+       /* Count will be initialised to next expire for all CPU's */
+       initcount = atomic_read(&count_reference);
 
        ncpus = num_online_cpus();
        for (i = 0; i < NR_LOOPS; i++) {
@@ -156,4 +158,3 @@ void __init synchronise_count_slave(void)
        local_irq_restore(flags);
 }
 #undef NR_LOOPS
-#endif
index 3ca5f42e819dc3ab4a6793510216d38218b6bc72..9a1ab7e87fd4d00e1705f858654f841a4f198e6f 100644 (file)
@@ -73,7 +73,7 @@ static int major;
 static const int minor = 1;    /* fixed for now  */
 
 #ifdef CONFIG_MIPS_APSP_KSPD
- static struct kspd_notifications kspd_events;
+static struct kspd_notifications kspd_events;
 static int kspd_events_reqd = 0;
 #endif
 
@@ -155,10 +155,9 @@ struct {
 };
 
 static void release_progmem(void *ptr);
-extern void save_gp_address(unsigned int secbase, unsigned int rel);
 
 /* get the vpe associated with this minor */
-struct vpe *get_vpe(int minor)
+static struct vpe *get_vpe(int minor)
 {
        struct vpe *v;
 
@@ -174,7 +173,7 @@ struct vpe *get_vpe(int minor)
 }
 
 /* get the vpe associated with this minor */
-struct tc *get_tc(int index)
+static struct tc *get_tc(int index)
 {
        struct tc *t;
 
@@ -186,20 +185,8 @@ struct tc *get_tc(int index)
        return NULL;
 }
 
-struct tc *get_tc_unused(void)
-{
-       struct tc *t;
-
-       list_for_each_entry(t, &vpecontrol.tc_list, list) {
-               if (t->state == TC_STATE_UNUSED)
-                       return t;
-       }
-
-       return NULL;
-}
-
 /* allocate a vpe and associate it with this minor (or index) */
-struct vpe *alloc_vpe(int minor)
+static struct vpe *alloc_vpe(int minor)
 {
        struct vpe *v;
 
@@ -216,7 +203,7 @@ struct vpe *alloc_vpe(int minor)
 }
 
 /* allocate a tc. At startup only tc0 is running, all other can be halted. */
-struct tc *alloc_tc(int index)
+static struct tc *alloc_tc(int index)
 {
        struct tc *tc;
 
@@ -232,7 +219,7 @@ out:
 }
 
 /* clean up and free everything */
-void release_vpe(struct vpe *v)
+static void release_vpe(struct vpe *v)
 {
        list_del(&v->list);
        if (v->load_addr)
@@ -240,7 +227,7 @@ void release_vpe(struct vpe *v)
        kfree(v);
 }
 
-void dump_mtregs(void)
+static void dump_mtregs(void)
 {
        unsigned long val;
 
@@ -327,7 +314,8 @@ static void layout_sections(struct module *mod, const Elf_Ehdr * hdr,
                            || (s->sh_flags & masks[m][1])
                            || s->sh_entsize != ~0UL)
                                continue;
-                       s->sh_entsize = get_offset(&mod->core_size, s);
+                       s->sh_entsize =
+                               get_offset((unsigned long *)&mod->core_size, s);
                }
 
                if (m == 0)
@@ -461,16 +449,15 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location,
 {
        unsigned long insnlo = *location;
        Elf32_Addr val, vallo;
+       struct mips_hi16 *l, *next;
 
        /* Sign extend the addend we extract from the lo insn.  */
        vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
 
        if (mips_hi16_list != NULL) {
-               struct mips_hi16 *l;
 
                l = mips_hi16_list;
                while (l != NULL) {
-                       struct mips_hi16 *next;
                        unsigned long insn;
 
                        /*
@@ -480,7 +467,7 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location,
                                printk(KERN_DEBUG "VPE loader: "
                                       "apply_r_mips_lo16/hi16: \t"
                                       "inconsistent value information\n");
-                               return -ENOEXEC;
+                               goto out_free;
                        }
 
                        /*
@@ -518,6 +505,16 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location,
        *location = insnlo;
 
        return 0;
+
+out_free:
+       while (l != NULL) {
+               next = l->next;
+               kfree(l);
+               l = next;
+       }
+       mips_hi16_list = NULL;
+
+       return -ENOEXEC;
 }
 
 static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
@@ -541,7 +538,7 @@ static char *rstrs[] = {
        [R_MIPS_PC16] = "MIPS_PC16"
 };
 
-int apply_relocations(Elf32_Shdr *sechdrs,
+static int apply_relocations(Elf32_Shdr *sechdrs,
                      const char *strtab,
                      unsigned int symindex,
                      unsigned int relsec,
@@ -586,7 +583,7 @@ int apply_relocations(Elf32_Shdr *sechdrs,
        return 0;
 }
 
-void save_gp_address(unsigned int secbase, unsigned int rel)
+static inline void save_gp_address(unsigned int secbase, unsigned int rel)
 {
        gp_addr = secbase + rel;
        gp_offs = gp_addr - (secbase & 0xffff0000);
@@ -1387,7 +1384,7 @@ static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr,
        return len;
 
 out_einval:
-       return -EINVAL;;
+       return -EINVAL;
 }
 
 static struct device_attribute vpe_class_attributes[] = {
index 0cea932f12411f069b0bde34d6a76535178650c0..5492c42f76507cb8d3e1c23b746f371bc10e5434 100644 (file)
@@ -89,13 +89,13 @@ unsigned __cpuinit get_c0_compare_int(void)
        if (cpu_has_veic) {
                set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
                mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
-       } else {
-#endif
-              {
-               if (cpu_has_vint)
-                       set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
-               mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
+
+               return mips_cpu_timer_irq;
        }
+#endif
+       if (cpu_has_vint)
+               set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
+       mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
 
        return mips_cpu_timer_irq;
 }
index b165cdcb281815e4d95452283ac87ba8150200ed..10ab69f7183fc8b69630c3c7add7a06a22b64fe4 100644 (file)
@@ -289,7 +289,7 @@ static void  cache_parity_error_octeon(int non_recoverable)
 }
 
 /**
- * Called when the the exception is not recoverable
+ * Called when the the exception is recoverable
  */
 
 asmlinkage void cache_parity_error_octeon_recoverable(void)
@@ -298,7 +298,7 @@ asmlinkage void cache_parity_error_octeon_recoverable(void)
 }
 
 /**
- * Called when the the exception is recoverable
+ * Called when the the exception is not recoverable
  */
 
 asmlinkage void cache_parity_error_octeon_non_recoverable(void)
index 297fb9f390dc145ad1cb6bce82dc7a32409fc36d..9d25d2ba4b9ea8b0157bea763fa314a6556227f6 100644 (file)
@@ -1,5 +1,9 @@
 /*
- * linux/arch/mips/mm/extable.c
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1997, 99, 2001 - 2004 Ralf Baechle <ralf@linux-mips.org>
  */
 #include <linux/module.h>
 #include <linux/spinlock.h>
index 6751ce9ede9ed6ff6935ec058e86d5f47b992730..f956ecbb81363af8a55b4d0179e7b3b9abc50ca8 100644 (file)
@@ -171,6 +171,7 @@ out_of_memory:
         * We ran out of memory, call the OOM killer, and return the userspace
         * (which will retry the fault, or kill us if we got oom-killed).
         */
+       up_read(&mm->mmap_sem);
        pagefault_out_of_memory();
        return;
 
index 471c09aa1614ae4aebe0b3d4143cef29e9bd52e9..8c2834f5919da563a06a861206cf37164b06615c 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/sysctl.h>
index 475038a141a65038ee34792a6d06395010004a93..27c807b67feaf4fc1a8f7e745462d8dd1bcc9624 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/cacheflush.h>
 #include <asm/traps.h>
 
+#include <asm/gcmpregs.h>
 #include <asm/mips-boards/prom.h>
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/bonito64.h>
@@ -192,6 +193,8 @@ extern struct plat_smp_ops msmtc_smp_ops;
 
 void __init prom_init(void)
 {
+       int result;
+
        prom_argc = fw_arg0;
        _prom_argv = (int *) fw_arg1;
        _prom_envp = (int *) fw_arg2;
@@ -358,12 +361,21 @@ void __init prom_init(void)
 #ifdef CONFIG_SERIAL_8250_CONSOLE
        console_config();
 #endif
+       /* Early detection of CMP support */
+       result = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ);
+
 #ifdef CONFIG_MIPS_CMP
-       register_smp_ops(&cmp_smp_ops);
+       if (result)
+               register_smp_ops(&cmp_smp_ops);
 #endif
 #ifdef CONFIG_MIPS_MT_SMP
+#ifdef CONFIG_MIPS_CMP
+       if (!result)
+               register_smp_ops(&vsmp_smp_ops);
+#else
        register_smp_ops(&vsmp_smp_ops);
 #endif
+#endif
 #ifdef CONFIG_MIPS_MT_SMTC
        register_smp_ops(&msmtc_smp_ops);
 #endif
index b4eaf137e4a7143bf046c04303166e4d7446f7fc..3e0a9b35ba5cde0019c6b6efa419f1a91613732d 100644 (file)
@@ -333,6 +333,21 @@ static struct irqaction irq_call = {
 };
 #endif /* CONFIG_MIPS_MT_SMP */
 
+static int gic_resched_int_base;
+static int gic_call_int_base;
+#define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu))
+#define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu))
+
+unsigned int plat_ipi_call_int_xlate(unsigned int cpu)
+{
+       return GIC_CALL_INT(cpu);
+}
+
+unsigned int plat_ipi_resched_int_xlate(unsigned int cpu)
+{
+       return GIC_RESCHED_INT(cpu);
+}
+
 static struct irqaction i8259irq = {
        .handler = no_action,
        .name = "XT-PIC cascade"
@@ -370,7 +385,7 @@ static int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
  * Interrupts and CPUs/Core Interrupts. The nature of the External
  * Interrupts is also defined here - polarity/trigger.
  */
-static struct gic_intr_map gic_intr_map[] = {
+static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
        { GIC_EXT_INTR(0),      X,      X,              X,              X,              0 },
        { GIC_EXT_INTR(1),      X,      X,              X,              X,              0 },
        { GIC_EXT_INTR(2),      X,      X,              X,              X,              0 },
@@ -387,21 +402,14 @@ static struct gic_intr_map gic_intr_map[] = {
        { GIC_EXT_INTR(13),     0,      GIC_MAP_TO_NMI_MSK,     GIC_POL_POS, GIC_TRIG_LEVEL,    0 },
        { GIC_EXT_INTR(14),     0,      GIC_MAP_TO_NMI_MSK,     GIC_POL_POS, GIC_TRIG_LEVEL,    0 },
        { GIC_EXT_INTR(15),     X,      X,              X,              X,              0 },
-       { GIC_EXT_INTR(16),     0,      GIC_CPU_INT1,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
-       { GIC_EXT_INTR(17),     0,      GIC_CPU_INT2,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
-       { GIC_EXT_INTR(18),     1,      GIC_CPU_INT1,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
-       { GIC_EXT_INTR(19),     1,      GIC_CPU_INT2,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
-       { GIC_EXT_INTR(20),     2,      GIC_CPU_INT1,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
-       { GIC_EXT_INTR(21),     2,      GIC_CPU_INT2,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
-       { GIC_EXT_INTR(22),     3,      GIC_CPU_INT1,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
-       { GIC_EXT_INTR(23),     3,      GIC_CPU_INT2,   GIC_POL_POS, GIC_TRIG_EDGE,     1 },
+/* This is the end of the general interrupts now we do IPI ones */
 };
 #endif
 
 /*
  * GCMP needs to be detected before any SMP initialisation
  */
-static int __init gcmp_probe(unsigned long addr, unsigned long size)
+int __init gcmp_probe(unsigned long addr, unsigned long size)
 {
        if (gcmp_present >= 0)
                return gcmp_present;
@@ -416,28 +424,36 @@ static int __init gcmp_probe(unsigned long addr, unsigned long size)
 }
 
 #if defined(CONFIG_MIPS_MT_SMP)
+static void __init fill_ipi_map1(int baseintr, int cpu, int cpupin)
+{
+       int intr = baseintr + cpu;
+       gic_intr_map[intr].intrnum = GIC_EXT_INTR(intr);
+       gic_intr_map[intr].cpunum = cpu;
+       gic_intr_map[intr].pin = cpupin;
+       gic_intr_map[intr].polarity = GIC_POL_POS;
+       gic_intr_map[intr].trigtype = GIC_TRIG_EDGE;
+       gic_intr_map[intr].ipiflag = 1;
+       ipi_map[cpu] |= (1 << (cpupin + 2));
+}
+
 static void __init fill_ipi_map(void)
 {
-       int i;
+       int cpu;
 
-       for (i = 0; i < ARRAY_SIZE(gic_intr_map); i++) {
-               if (gic_intr_map[i].ipiflag && (gic_intr_map[i].cpunum != X))
-                       ipi_map[gic_intr_map[i].cpunum] |=
-                               (1 << (gic_intr_map[i].pin + 2));
+       for (cpu = 0; cpu < NR_CPUS; cpu++) {
+               fill_ipi_map1(gic_resched_int_base, cpu, GIC_CPU_INT1);
+               fill_ipi_map1(gic_call_int_base, cpu, GIC_CPU_INT2);
        }
 }
 #endif
 
 void __init arch_init_irq(void)
 {
-       int gic_present, gcmp_present;
-
        init_i8259_irqs();
 
        if (!cpu_has_veic)
                mips_cpu_irq_init();
 
-       gcmp_present = gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ);
        if (gcmp_present)  {
                GCMPGCB(GICBA) = GIC_BASE_ADDR | GCMP_GCB_GICBA_EN_MSK;
                gic_present = 1;
@@ -514,24 +530,10 @@ void __init arch_init_irq(void)
        if (gic_present) {
                /* FIXME */
                int i;
-               struct {
-                       unsigned int resched;
-                       unsigned int call;
-               } ipiirq[] = {
-                       {
-                               .resched = GIC_IPI_EXT_INTR_RESCHED_VPE0,
-                               .call =  GIC_IPI_EXT_INTR_CALLFNC_VPE0},
-                       {
-                               .resched = GIC_IPI_EXT_INTR_RESCHED_VPE1,
-                               .call =  GIC_IPI_EXT_INTR_CALLFNC_VPE1
-                       }, {
-                               .resched = GIC_IPI_EXT_INTR_RESCHED_VPE2,
-                               .call =  GIC_IPI_EXT_INTR_CALLFNC_VPE2
-                       }, {
-                               .resched = GIC_IPI_EXT_INTR_RESCHED_VPE3,
-                               .call =  GIC_IPI_EXT_INTR_CALLFNC_VPE3
-                       }
-               };
+
+               gic_call_int_base = GIC_NUM_INTRS - NR_CPUS;
+               gic_resched_int_base = gic_call_int_base - NR_CPUS;
+
                fill_ipi_map();
                gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map, ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
                if (!gcmp_present) {
@@ -553,12 +555,15 @@ void __init arch_init_irq(void)
                printk("CPU%d: status register now %08x\n", smp_processor_id(), read_c0_status());
                write_c0_status(0x1100dc00);
                printk("CPU%d: status register frc %08x\n", smp_processor_id(), read_c0_status());
-               for (i = 0; i < ARRAY_SIZE(ipiirq); i++) {
-                       setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, &irq_resched);
-                       setup_irq(MIPS_GIC_IRQ_BASE + ipiirq[i].call, &irq_call);
-
-                       set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].resched, handle_percpu_irq);
-                       set_irq_handler(MIPS_GIC_IRQ_BASE + ipiirq[i].call, handle_percpu_irq);
+               for (i = 0; i < NR_CPUS; i++) {
+                       setup_irq(MIPS_GIC_IRQ_BASE +
+                                       GIC_RESCHED_INT(i), &irq_resched);
+                       setup_irq(MIPS_GIC_IRQ_BASE +
+                                       GIC_CALL_INT(i), &irq_call);
+                       set_irq_handler(MIPS_GIC_IRQ_BASE +
+                                       GIC_RESCHED_INT(i), handle_percpu_irq);
+                       set_irq_handler(MIPS_GIC_IRQ_BASE +
+                                       GIC_CALL_INT(i), handle_percpu_irq);
                }
        } else {
                /* set up ipi interrupts */
index 42dee4da37bad5ad5d0b2932b475bf99577d9e2c..f48d60e8429017b52352e8e0b59bc18faa0e9061 100644 (file)
@@ -28,9 +28,6 @@
 #include <asm/reboot.h>
 #include <asm/mips-boards/generic.h>
 
-static void mips_machine_restart(char *command);
-static void mips_machine_halt(void);
-
 static void mips_machine_restart(char *command)
 {
        unsigned int __iomem *softres_reg =
index 8df43e9e4d901f3ecc65380e767c2014bd1cb9ba..18b192784877d9f8f9da3bc46174d9d07acce5bb 100644 (file)
@@ -138,7 +138,7 @@ __init void plat_time_init(void)
         * HZ timer interrupts per second.
         */
        mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p));
-       cpj = (mips_hpt_frequency + HZ / 2) / HZ;
+       cpj = DIV_ROUND_CLOSEST(mips_hpt_frequency, HZ);
        write_c0_count(0);
        timer_ack();
 
index e8a97f59e0661e585fc40565212d0e7d74130d1f..63d8a297c58da4f85abf378fa4da6e7e2c9ed5e6 100644 (file)
@@ -52,3 +52,8 @@ obj-$(CONFIG_VICTOR_MPC30X)   += fixup-mpc30x.o
 obj-$(CONFIG_ZAO_CAPCELLA)     += fixup-capcella.o
 obj-$(CONFIG_WR_PPMC)          += fixup-wrppmc.o
 obj-$(CONFIG_MIKROTIK_RB532)   += pci-rc32434.o ops-rc32434.o fixup-rc32434.o
+obj-$(CONFIG_CPU_CAVIUM_OCTEON)        += pci-octeon.o pcie-octeon.o
+
+ifdef CONFIG_PCI_MSI
+obj-$(CONFIG_CPU_CAVIUM_OCTEON)        += msi-octeon.o
+endif
index 1416bca6d1a3f8962bd23e76d34d0668c703d767..1c02f5737367aa7e75569afeb98aebcd3ebb5327 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  fixup-cappcela.c, The ZAO Networks Capcella specific PCI fixups.
  *
- *  Copyright (C) 2002,2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002,2004  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index fba5aad00d513566aa368d774761d0da77658bfa..0d9ccf4dfc5abc5b7263361eef22444861507a86 100644 (file)
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/pci/fixup-emma2rh.c
- *      This file defines the PCI configration.
- *
  *  Copyright (C) NEC Electronics Corporation 2004-2006
  *
  *  This file is based on the arch/mips/ddb5xxx/ddb5477/pci.c
index 5911596257222dec18a807e3fdae132ac2548a50..e08f49cb6875abd65d50b7cb1cee964f816d96b7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  fixup-mpc30x.c, The Victor MP-C303/304 specific PCI fixups.
  *
- *  Copyright (C) 2002,2004  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002,2004  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 0ad39e53f7b1a0122d185c952fa03b5c64a99c79..f0bb9146e6c038424281cd45bb5b3ebc9dab0815 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     arch/mips/pci/fixup-sb1250.c
- *
  *     Copyright (C) 2004, 2006  MIPS Technologies, Inc.  All rights reserved.
  *         Author:     Maciej W. Rozycki <macro@mips.com>
  *
index ed87733f679682d778b4b31a1cd62c10ffbe3f45..8084b17d44066a3f1ca658902f4b191939c91d84 100644 (file)
@@ -2,7 +2,7 @@
  *  fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups.
  *
  *  Copyright (C) 2003  Megasolution Inc. <matsu@megasolution.jp>
- *  Copyright (C) 2004-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index e3eedf4bf9bd088567074cd3dc12df6f28fac811..4196ccf3ea3da5e6783de7acd913f68d2fc218bc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  fixup-tb0226.c, The TANBAC TB0226 specific PCI fixups.
  *
- *  Copyright (C) 2002-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 267ab3dc3d421420cde426812bf71ce6d661acaa..2fe29db4372595d5393ab11b38c8ac3f0fff466d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  fixup-tb0287.c, The TANBAC TB0287 specific PCI fixups.
  *
- *  Copyright (C) 2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
similarity index 88%
rename from arch/mips/cavium-octeon/msi.c
rename to arch/mips/pci/msi-octeon.c
index 964b03b75a8f29b775ea0b19d80c1d23763230dc..03742e64765717ec3976c0eb7d7e77c8d8a283e0 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2005-2007 Cavium Networks
+ * Copyright (C) 2005-2009 Cavium Networks
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -16,8 +16,7 @@
 #include <asm/octeon/cvmx-pci-defs.h>
 #include <asm/octeon/cvmx-npei-defs.h>
 #include <asm/octeon/cvmx-pexp-defs.h>
-
-#include "pci-common.h"
+#include <asm/octeon/pci-octeon.h>
 
 /*
  * Each bit in msi_free_irq_bitmask represents a MSI interrupt that is
@@ -47,8 +46,8 @@ static DEFINE_SPINLOCK(msi_free_irq_bitmask_lock);
  * programming the MSI control bits [6:4] before calling
  * pci_enable_msi().
  *
- * @param dev    Device requesting MSI interrupts
- * @param desc   MSI descriptor
+ * @dev:    Device requesting MSI interrupts
+ * @desc:   MSI descriptor
  *
  * Returns 0 on success.
  */
@@ -213,14 +212,9 @@ void arch_teardown_msi_irq(unsigned int irq)
 }
 
 
-/**
+/*
  * Called by the interrupt handling code when an MSI interrupt
  * occurs.
- *
- * @param cpl
- * @param dev_id
- *
- * @return
  */
 static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id)
 {
@@ -256,31 +250,37 @@ static irqreturn_t octeon_msi_interrupt(int cpl, void *dev_id)
 }
 
 
-/**
+/*
  * Initializes the MSI interrupt handling code
- *
- * @return
  */
 int octeon_msi_initialize(void)
 {
-       int r;
        if (octeon_has_feature(OCTEON_FEATURE_PCIE)) {
-               r = request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt,
+               if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt,
                                IRQF_SHARED,
-                               "MSI[0:63]", octeon_msi_interrupt);
+                               "MSI[0:63]", octeon_msi_interrupt))
+                       panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed");
        } else if (octeon_is_pci_host()) {
-               r = request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt,
+               if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt,
                                IRQF_SHARED,
-                               "MSI[0:15]", octeon_msi_interrupt);
-               r += request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt,
-                                IRQF_SHARED,
-                                "MSI[16:31]", octeon_msi_interrupt);
-               r += request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt,
-                                IRQF_SHARED,
-                                "MSI[32:47]", octeon_msi_interrupt);
-               r += request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt,
-                                IRQF_SHARED,
-                                "MSI[48:63]", octeon_msi_interrupt);
+                               "MSI[0:15]", octeon_msi_interrupt))
+                       panic("request_irq(OCTEON_IRQ_PCI_MSI0) failed");
+
+               if (request_irq(OCTEON_IRQ_PCI_MSI1, octeon_msi_interrupt,
+                               IRQF_SHARED,
+                               "MSI[16:31]", octeon_msi_interrupt))
+                       panic("request_irq(OCTEON_IRQ_PCI_MSI1) failed");
+
+               if (request_irq(OCTEON_IRQ_PCI_MSI2, octeon_msi_interrupt,
+                               IRQF_SHARED,
+                               "MSI[32:47]", octeon_msi_interrupt))
+                       panic("request_irq(OCTEON_IRQ_PCI_MSI2) failed");
+
+               if (request_irq(OCTEON_IRQ_PCI_MSI3, octeon_msi_interrupt,
+                               IRQF_SHARED,
+                               "MSI[48:63]", octeon_msi_interrupt))
+                       panic("request_irq(OCTEON_IRQ_PCI_MSI3) failed");
+
        }
        return 0;
 }
index 5947a70b0b7fca38135209bad0e1ed33042cf09b..710aef5c070e839539a309b88fab97735316c501 100644 (file)
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/pci/ops-emma2rh.c
- *      This file defines the PCI operation for EMMA2RH.
- *
  *  Copyright (C) NEC Electronics Corporation 2004-2006
  *
  *  This file is based on the arch/mips/pci/ops-vr41xx.c
index 900c6b32576c3db47e301655f42b5ca4f4c69f4b..28962a7c66066140865072556c741441ee9b2fd8 100644 (file)
@@ -2,8 +2,8 @@
  *  ops-vr41xx.c, PCI configuration routines for the PCIU of NEC VR4100 series.
  *
  *  Copyright (C) 2001-2003 MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2004-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  */
 #include <linux/pci.h>
index 2df4190232cd4163a3afccc5de8e2d50bd9af91b..773e34ff4d1cd9638cdedf8a5b620f45059f7c89 100644 (file)
@@ -1,7 +1,4 @@
 /*
- *  arch/mips/pci/pci-emma2rh.c
- *      This file defines the PCI configration.
- *
  *  Copyright (C) NEC Electronics Corporation 2004-2006
  *
  *  This file is based on the arch/mips/ddb5xxx/ddb5477/pci.c
similarity index 78%
rename from arch/mips/cavium-octeon/pci.c
rename to arch/mips/pci/pci-octeon.c
index 67c0ff5e92f1a528a7b133c1df206001cbf7532f..9cb0c807f564bdc00ac7e0f3f4e6ee43d4c1d730 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2005-2007 Cavium Networks
+ * Copyright (C) 2005-2009 Cavium Networks
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -17,8 +17,7 @@
 #include <asm/octeon/octeon.h>
 #include <asm/octeon/cvmx-npi-defs.h>
 #include <asm/octeon/cvmx-pci-defs.h>
-
-#include "pci-common.h"
+#include <asm/octeon/pci-octeon.h>
 
 #define USE_OCTEON_INTERNAL_ARBITER
 
@@ -54,6 +53,126 @@ union octeon_pci_address {
        } s;
 };
 
+int __initdata (*octeon_pcibios_map_irq)(const struct pci_dev *dev,
+                                        u8 slot, u8 pin);
+enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID;
+
+/**
+ * Map a PCI device to the appropriate interrupt line
+ *
+ * @dev:    The Linux PCI device structure for the device to map
+ * @slot:   The slot number for this device on __BUS 0__. Linux
+ *               enumerates through all the bridges and figures out the
+ *               slot on Bus 0 where this device eventually hooks to.
+ * @pin:    The PCI interrupt pin read from the device, then swizzled
+ *               as it goes through each bridge.
+ * Returns Interrupt number for the device
+ */
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+       if (octeon_pcibios_map_irq)
+               return octeon_pcibios_map_irq(dev, slot, pin);
+       else
+               panic("octeon_pcibios_map_irq not set.");
+}
+
+
+/*
+ * Called to perform platform specific PCI setup
+ */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+       uint16_t config;
+       uint32_t dconfig;
+       int pos;
+       /*
+        * Force the Cache line setting to 64 bytes. The standard
+        * Linux bus scan doesn't seem to set it. Octeon really has
+        * 128 byte lines, but Intel bridges get really upset if you
+        * try and set values above 64 bytes. Value is specified in
+        * 32bit words.
+        */
+       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 64 / 4);
+       /* Set latency timers for all devices */
+       pci_write_config_byte(dev, PCI_LATENCY_TIMER, 48);
+
+       /* Enable reporting System errors and parity errors on all devices */
+       /* Enable parity checking and error reporting */
+       pci_read_config_word(dev, PCI_COMMAND, &config);
+       config |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+       pci_write_config_word(dev, PCI_COMMAND, config);
+
+       if (dev->subordinate) {
+               /* Set latency timers on sub bridges */
+               pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 48);
+               /* More bridge error detection */
+               pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &config);
+               config |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR;
+               pci_write_config_word(dev, PCI_BRIDGE_CONTROL, config);
+       }
+
+       /* Enable the PCIe normal error reporting */
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (pos) {
+               /* Update Device Control */
+               pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config);
+               /* Correctable Error Reporting */
+               config |= PCI_EXP_DEVCTL_CERE;
+               /* Non-Fatal Error Reporting */
+               config |= PCI_EXP_DEVCTL_NFERE;
+               /* Fatal Error Reporting */
+               config |= PCI_EXP_DEVCTL_FERE;
+               /* Unsupported Request */
+               config |= PCI_EXP_DEVCTL_URRE;
+               pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config);
+       }
+
+       /* Find the Advanced Error Reporting capability */
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+       if (pos) {
+               /* Clear Uncorrectable Error Status */
+               pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
+                                     &dconfig);
+               pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
+                                      dconfig);
+               /* Enable reporting of all uncorrectable errors */
+               /* Uncorrectable Error Mask - turned on bits disable errors */
+               pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, 0);
+               /*
+                * Leave severity at HW default. This only controls if
+                * errors are reported as uncorrectable or
+                * correctable, not if the error is reported.
+                */
+               /* PCI_ERR_UNCOR_SEVER - Uncorrectable Error Severity */
+               /* Clear Correctable Error Status */
+               pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &dconfig);
+               pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, dconfig);
+               /* Enable reporting of all correctable errors */
+               /* Correctable Error Mask - turned on bits disable errors */
+               pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, 0);
+               /* Advanced Error Capabilities */
+               pci_read_config_dword(dev, pos + PCI_ERR_CAP, &dconfig);
+               /* ECRC Generation Enable */
+               if (config & PCI_ERR_CAP_ECRC_GENC)
+                       config |= PCI_ERR_CAP_ECRC_GENE;
+               /* ECRC Check Enable */
+               if (config & PCI_ERR_CAP_ECRC_CHKC)
+                       config |= PCI_ERR_CAP_ECRC_CHKE;
+               pci_write_config_dword(dev, pos + PCI_ERR_CAP, dconfig);
+               /* PCI_ERR_HEADER_LOG - Header Log Register (16 bytes) */
+               /* Report all errors to the root complex */
+               pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND,
+                                      PCI_ERR_ROOT_CMD_COR_EN |
+                                      PCI_ERR_ROOT_CMD_NONFATAL_EN |
+                                      PCI_ERR_ROOT_CMD_FATAL_EN);
+               /* Clear the Root status register */
+               pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &dconfig);
+               pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, dconfig);
+       }
+
+       return 0;
+}
+
 /**
  * Return the mapping of PCI device number to IRQ line. Each
  * character in the return string represents the interrupt
@@ -136,9 +255,8 @@ int __init octeon_pci_pcibios_map_irq(const struct pci_dev *dev,
 }
 
 
-/**
+/*
  * Read a value from configuration space
- *
  */
 static int octeon_read_config(struct pci_bus *bus, unsigned int devfn,
                              int reg, int size, u32 *val)
@@ -174,15 +292,8 @@ static int octeon_read_config(struct pci_bus *bus, unsigned int devfn,
 }
 
 
-/**
+/*
  * Write a value to PCI configuration space
- *
- * @bus:
- * @devfn:
- * @reg:
- * @size:
- * @val:
- * Returns
  */
 static int octeon_write_config(struct pci_bus *bus, unsigned int devfn,
                               int reg, int size, u32 val)
@@ -251,10 +362,8 @@ static struct pci_controller octeon_pci_controller = {
 };
 
 
-/**
+/*
  * Low level initialize the Octeon PCI controller
- *
- * Returns
  */
 static void octeon_pci_initialize(void)
 {
@@ -398,7 +507,7 @@ static void octeon_pci_initialize(void)
                pci_int_arb_cfg.s.en = 1;       /* Internal arbiter enable */
                cvmx_write_csr(CVMX_NPI_PCI_INT_ARB_CFG, pci_int_arb_cfg.u64);
        }
-#endif                         /* USE_OCTEON_INTERNAL_ARBITER */
+#endif /* USE_OCTEON_INTERNAL_ARBITER */
 
        /*
         * Preferrably written to 1 to set MLTD. [RDSATI,TRTAE,
@@ -457,10 +566,8 @@ static void octeon_pci_initialize(void)
 }
 
 
-/**
+/*
  * Initialize the Octeon PCI controller
- *
- * Returns
  */
 static int __init octeon_pci_setup(void)
 {
index aaa900596792db52eb6fdac89944e1bdd4c11146..a5807406a7f168bc62535319b84effd5756644e6 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/arch/mips/pci/pci-tx4927.c
- *
  * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
  *         and RBTX49xx patch from CELF patch archive.
  *
index 1ea257bc3b8faafc0bd8dae93198f67d645f6dba..20e45f30b2ef4274037dcac4ae63665a13c49c7f 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/arch/mips/pci/pci-tx4938.c
- *
  * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
  *         and RBTX49xx patch from CELF patch archive.
  *
index 5fecf1cdc325559f20334a517b2a68c06ceed03d..9ef840693baf820fa336453d6fc47a4738c783a3 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/arch/mips/pci/pci-tx4939.c
- *
  * Based on linux/arch/mips/txx9/rbtx4939/setup.c,
  *         and RBTX49xx patch from CELF patch archive.
  *
index d1e049b55f34f07f2035f830fd82d7324f8fbe41..56525711f8b75deb270b6c6b7f32db0b38289029 100644 (file)
@@ -2,8 +2,8 @@
  *  pci-vr41xx.c, PCI Control Unit routines for the NEC VR4100 series.
  *
  *  Copyright (C) 2001-2003 MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2004-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2004-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *  Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -22,7 +22,7 @@
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  */
 #include <linux/init.h>
index 8a35e32b8376f734f61da3a74ec5b8726f5f1e48..6b1ae2eb1c065bc3b5b547ec6ff6258e14f05926 100644 (file)
@@ -2,8 +2,8 @@
  *  pci-vr41xx.h, Include file for PCI Control Unit of the NEC VR4100 series.
  *
  *  Copyright (C) 2002  MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2004-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
similarity index 97%
rename from arch/mips/cavium-octeon/pcie.c
rename to arch/mips/pci/pcie-octeon.c
index 49d14081b3b5aa2585911f812732a04cf61a7f12..6aa5c542d52dff2a72670722ad882ef79418594e 100644 (file)
@@ -18,8 +18,7 @@
 #include <asm/octeon/cvmx-pescx-defs.h>
 #include <asm/octeon/cvmx-pexp-defs.h>
 #include <asm/octeon/cvmx-helper-errata.h>
-
-#include "pci-common.h"
+#include <asm/octeon/pci-octeon.h>
 
 union cvmx_pcie_address {
        uint64_t u64;
@@ -976,13 +975,13 @@ static int cvmx_pcie_rc_initialize(int pcie_port)
 /**
  * Map a PCI device to the appropriate interrupt line
  *
- * @param dev    The Linux PCI device structure for the device to map
- * @param slot   The slot number for this device on __BUS 0__. Linux
+ * @dev:    The Linux PCI device structure for the device to map
+ * @slot:   The slot number for this device on __BUS 0__. Linux
  *               enumerates through all the bridges and figures out the
  *               slot on Bus 0 where this device eventually hooks to.
- * @param pin    The PCI interrupt pin read from the device, then swizzled
+ * @pin:    The PCI interrupt pin read from the device, then swizzled
  *               as it goes through each bridge.
- * @return Interrupt number for the device
+ * Returns Interrupt number for the device
  */
 int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev,
                                       u8 slot, u8 pin)
@@ -1025,12 +1024,12 @@ int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev,
 /**
  * Read a value from configuration space
  *
- * @param bus
- * @param devfn
- * @param reg
- * @param size
- * @param val
- * @return
+ * @bus:
+ * @devfn:
+ * @reg:
+ * @size:
+ * @val:
+ * Returns
  */
 static inline int octeon_pcie_read_config(int pcie_port, struct pci_bus *bus,
                                          unsigned int devfn, int reg, int size,
@@ -1041,19 +1040,29 @@ static inline int octeon_pcie_read_config(int pcie_port, struct pci_bus *bus,
        int bus_number = bus->number;
 
        /*
-        * We need to force the bus number to be zero on the root
-        * bus. Linux numbers the 2nd root bus to start after all
-        * buses on root 0.
+        * For the top level bus make sure our hardware bus number
+        * matches the software one.
         */
-       if (bus->parent == NULL)
-               bus_number = 0;
+       if (bus->parent == NULL) {
+               union cvmx_pciercx_cfg006 pciercx_cfg006;
+               pciercx_cfg006.u32 = cvmx_pcie_cfgx_read(pcie_port,
+                       CVMX_PCIERCX_CFG006(pcie_port));
+               if (pciercx_cfg006.s.pbnum != bus_number) {
+                       pciercx_cfg006.s.pbnum = bus_number;
+                       pciercx_cfg006.s.sbnum = bus_number;
+                       pciercx_cfg006.s.subbnum = bus_number;
+                       cvmx_pcie_cfgx_write(pcie_port,
+                               CVMX_PCIERCX_CFG006(pcie_port),
+                               pciercx_cfg006.u32);
+               }
+       }
 
        /*
         * PCIe only has a single device connected to Octeon. It is
         * always device ID 0. Don't bother doing reads for other
         * device IDs on the first segment.
         */
-       if ((bus_number == 0) && (devfn >> 3 != 0))
+       if ((bus->parent == NULL) && (devfn >> 3 != 0))
                return PCIBIOS_FUNC_NOT_SUPPORTED;
 
        /*
@@ -1071,7 +1080,7 @@ static inline int octeon_pcie_read_config(int pcie_port, struct pci_bus *bus,
                 * bridge only respondes to device ID 0, function
                 * 0-1
                 */
-               if ((bus_number == 0) && (devfn >= 2))
+               if ((bus->parent == NULL) && (devfn >= 2))
                        return PCIBIOS_FUNC_NOT_SUPPORTED;
                /*
                 * The PCI-X slots are device ID 2,3. Choose one of
@@ -1156,25 +1165,18 @@ static int octeon_pcie1_read_config(struct pci_bus *bus, unsigned int devfn,
 /**
  * Write a value to PCI configuration space
  *
- * @param bus
- * @param devfn
- * @param reg
- * @param size
- * @param val
- * @return
+ * @bus:
+ * @devfn:
+ * @reg:
+ * @size:
+ * @val:
+ * Returns
  */
 static inline int octeon_pcie_write_config(int pcie_port, struct pci_bus *bus,
                                           unsigned int devfn, int reg,
                                           int size, u32 val)
 {
        int bus_number = bus->number;
-       /*
-        * We need to force the bus number to be zero on the root
-        * bus. Linux numbers the 2nd root bus to start after all
-        * busses on root 0.
-        */
-       if (bus->parent == NULL)
-               bus_number = 0;
 
        switch (size) {
        case 4:
@@ -1254,7 +1256,7 @@ static struct pci_controller octeon_pcie1_controller = {
 /**
  * Initialize the Octeon PCIe controllers
  *
- * @return
+ * Returns
  */
 static int __init octeon_pcie_setup(void)
 {
index 69848c5813e2ae5f9d34929d46733e031207f102..aaccbe524386f89829861bfc8ea4683eb2312b2d 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * @file /arch/mips/pmc-sierra/msp71xx/gpio.c
- *
  * Generic PMC MSP71xx GPIO handling. These base gpio are controlled by two
  * types of registers. The data register sets the output level when in output
  * mode and when in input mode will contain the value at the input. The config
index fc6dbc6cf1c0c865b5bcd73132dc344444f4c09d..2a99f360fae4ba62f5242759e3644033dfc62b29 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * @file /arch/mips/pmc-sierra/msp71xx/gpio_extended.c
- *
  * Generic PMC MSP71xx EXTENDED (EXD) GPIO handling. The extended gpio is
  * a set of hardware registers that have no need for explicit locking as
  * it is handled by unique method of writing individual set/clr bits.
index f5f1b8d2bb9ae9a4df1fd2278c88754e796da566..61f390232346509556862dce70afea4aa2662447 100644 (file)
@@ -45,13 +45,6 @@ static inline void mask_msp_slp_irq(unsigned int irq)
  */
 static inline void ack_msp_slp_irq(unsigned int irq)
 {
-       mask_slp_irq(irq);
-
-       /*
-        * only really necessary for 18, 16-14 and sometimes 3:0 (since
-        * these can be edge sensitive) but it doesn't hurt  for the others.
-        */
-
        /* check for PER interrupt range */
        if (irq < MSP_PER_INTBASE)
                *SLP_INT_STS_REG = (1 << (irq - MSP_SLP_INTBASE));
@@ -62,8 +55,7 @@ static inline void ack_msp_slp_irq(unsigned int irq)
 static struct irq_chip msp_slp_irq_controller = {
        .name = "MSP_SLP",
        .ack = ack_msp_slp_irq,
-       .mask = ack_msp_slp_irq,
-       .mask_ack = ack_msp_slp_irq,
+       .mask = mask_msp_slp_irq,
        .unmask = unmask_msp_slp_irq,
 };
 
@@ -79,7 +71,7 @@ void __init msp_slp_irq_init(void)
 
        /* initialize all the IRQ descriptors */
        for (i = MSP_SLP_INTBASE; i < MSP_PER_INTBASE + 32; i++)
-               set_irq_chip_and_handler(i, &msp_slp_irq_controller
+               set_irq_chip_and_handler(i, &msp_slp_irq_controller,
                                         handle_level_irq);
 }
 
index caf5e9a0acc77de5b2ff40ac22aaf9615e2005db..fc990cb319415b41e30df315b5f078e576f8a88a 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c
- *
  *  Copyright (C) 2003 PMC-Sierra Inc.
  *  Author: Manish Lachwani (lachwani@pmc-sierra.com)
  *
index 4282ac9d01d24d091c4bf3a0f194d87787c0feac..062505054d4269c7a9684ad50a42c4fb2b90ad9a 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     arch/mips/sibyte/swarm/swarm-i2c.c
- *
  *     Broadcom BCM91250A (SWARM), etc. I2C platform setup.
  *
  *     Copyright (c) 2008  Maciej W. Rozycki
index ef6ea6e97873549ea2398d711aef6f9379d38be3..70f9626f8227bacc296c600e444441392f8c9ba4 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/arch/mips/txx9/generic/mem_tx4927.c
- *
  * common tx4927 memory interface
  *
  * Author: MontaVista Software, Inc.
index 3b7d77d61ce06f0ee0ccae573f31bef1e555267b..a205e2ba8e7b4e65b442cc56349808f01d88f3f6 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/arch/mips/txx9/generic/setup.c
- *
  * Based on linux/arch/mips/txx9/rbtx4938/setup.c,
  *         and RBTX49xx patch from CELF patch archive.
  *
index c033ffe71cdfc0e35c1fbd64323ebe54293ae94a..b0c241ecf603c3549a98b385176ad701eb7532c6 100644 (file)
@@ -512,10 +512,10 @@ static void __init rbtx4939_setup(void)
        rbtx4939_ebusc_setup();
        /* always enable ATA0 */
        txx9_set64(&tx4939_ccfgptr->pcfg, TX4939_PCFG_ATA0MODE);
-       rbtx4939_update_ioc_pen();
        if (txx9_master_clock == 0)
                txx9_master_clock = 20000000;
        tx4939_setup();
+       rbtx4939_update_ioc_pen();
 #ifdef HAVE_RBTX4939_IOSWAB
        ioswabw = rbtx4939_ioswabw;
        __mem_ioswabw = rbtx4939_mem_ioswabw;
index 6d9bab8905877fe1b7b0324a4670bd424584b706..719f4a5b984458103ac95de630b0c6d3dfb9d7ae 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  setup.c, Setup for the CASIO CASSIOPEIA E-11/15/55/65.
  *
- *  Copyright (C) 2002-2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2006  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index d77c330a0d592b49b700597529ec48a0f03e2f4a..6346c59c9f9d96d361396944c4e40e4fb20052e6 100644 (file)
@@ -2,8 +2,8 @@
  *  bcu.c, Bus Control Unit routines for the NEC VR4100 series.
  *
  *  Copyright (C) 2002  MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
- *  Copyright (C) 2003-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  *  - Added support for NEC VR4111 and VR4121.
  *
- *  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Yoichi Yuasa <yuasa@linux-mips.org>
  *  - Added support for NEC VR4133.
  */
 #include <linux/kernel.h>
index ad0e8e3409d9099d3d6450a31533c1204574b152..8ba7d04a5ec58e4b05cf1d792eb766698b66e850 100644 (file)
@@ -2,8 +2,8 @@
  *  cmu.c, Clock Mask Unit routines for the NEC VR4100 series.
  *
  *  Copyright (C) 2001-2002  MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copuright (C) 2003-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copuright (C) 2003-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  *  - Added support for NEC VR4111 and VR4121.
  *
- *  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Yoichi Yuasa <yuasa@linux-mips.org>
  *  - Added support for NEC VR4133.
  */
 #include <linux/init.h>
index 2b272f1496fe97e55b57975e1850ad32e2ee26e0..22cc6f2100a1acba6d15f983804c3ee46660bdaa 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  NEC VR4100 series GIU platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 3f23d9fda662621e2879ff37a2d1ecbef24cf1a5..6d39e222b170b1db7250cb990c7726f875127305 100644 (file)
@@ -2,8 +2,8 @@
  *  icu.c, Interrupt Control Unit routines for the NEC VR4100 series.
  *
  *  Copyright (C) 2001-2002  MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2003-2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *    Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2003-2006  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  */
 /*
  * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
+ *  MontaVista Software Inc. <source@mvista.com>
  *  - New creation, NEC VR4122 and VR4131 are supported.
  *  - Added support for NEC VR4111 and VR4121.
  *
- *  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Yoichi Yuasa <yuasa@linux-mips.org>
  *  - Coped with INTASSIGN of NEC VR4133.
  */
 #include <linux/errno.h>
index c64995342ba82f12922267674f46936fbf2b9571..1386e6f081c86aa370e3ddf31179b07b668f9ba0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  init.c, Common initialization routines for NEC VR4100 series.
  *
- *  Copyright (C) 2003-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2003-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 9cc389109b19f42ee82f5d09f69b8d3e8de27024..bef06872f012d6ecb055aafeae92d9ed6f962135 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Interrupt handing routines for NEC VR4100 series.
  *
- *  Copyright (C) 2005-2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005-2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 028aaf75eb216690a5217cfa69fb1bb65a4d4d5f..692b4e85b7fc98475ed33b5a8f3b9efd6733aa67 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  pmu.c, Power Management Unit routines for NEC VR4100 series.
  *
- *  Copyright (C) 2003-2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2003-2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 9f26c14edcac25cfdbf588babf855c9b0b1d8109..ebc5dcf0ed8e29dad672a529e6cf6abf45c66f6c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  NEC VR4100 series RTC platform device.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 654dee6208be2258ce85ef608c0cc7a639696ad4..54eae56108fb94db06a5add150e8baad4ef5dbfe 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  NEC VR4100 series SIU platform device.
  *
- *  Copyright (C) 2007-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index e0c1ac5e988e48335b471f8bf752ac21485a851f..ff841422b6389317567054761990d7d39ff4cb3b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  type.c, System type for NEC VR4100 series.
  *
- *  Copyright (C) 2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 9eef297eca1a9ec1d52dbe7f3cda2a5ff200a4c8..3982f378a3e603242ebffe85fa45e6e4dbb52ae5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  setup.c, Setup for the IBM WorkPad z50.
  *
- *  Copyright (C) 2002-2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2002-2006  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index e58b9a46e1b14a0a8274479de290872ef28063fd..19aecc90f7a43f7b572f1ce7054bff0d70faae89 100644 (file)
@@ -59,7 +59,6 @@ void pcibios_penalize_isa_irq(int irq);
 #include <linux/slab.h>
 #include <asm/scatterlist.h>
 #include <linux/string.h>
-#include <linux/mm.h>
 #include <asm/io.h>
 
 struct pci_dev;
@@ -70,10 +69,6 @@ struct pci_dev;
  */
 #define PCI_DMA_BUS_IS_PHYS    (1)
 
-
-/* This is always fine. */
-#define pci_dac_dma_supported(pci_dev, mask)   (0)
-
 /* Return the index of the PCI controller for device. */
 static inline int pci_controller_num(struct pci_dev *dev)
 {
index ec057e1bd4cf3e72538d4b8c5ae3a83b4c887694..a19f11327cd87ce9dd2c578c1ecf25bf655d083f 100644 (file)
@@ -51,6 +51,6 @@ static inline void pte_free(struct mm_struct *mm, struct page *pte)
 }
 
 
-#define __pte_free_tlb(tlb, pte) tlb_remove_page((tlb), (pte))
+#define __pte_free_tlb(tlb, pte, addr) tlb_remove_page((tlb), (pte))
 
 #endif /* _ASM_PGALLOC_H */
index 78a3881f3c1250f39eea83dc80a320c826ed650d..58d64f8b2cc3d44769ecdcee23c3ccb9477a4239 100644 (file)
@@ -65,8 +65,6 @@ struct thread_info {
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #ifndef __ASSEMBLY__
 
@@ -76,7 +74,7 @@ struct thread_info {
        .exec_domain    = &default_exec_domain, \
        .flags          = 0,                    \
        .cpu            = 0,                    \
-       .preempt_count  = 1,                    \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .addr_limit     = KERNEL_DS,            \
        .restart_block = {                      \
                .fn = do_no_restart_syscall,    \
index fef5b434dadcc6977212b6b1c821efbf211ead85..fad68616af32b4a9e73ed955975f9422d7026483 100644 (file)
 #define __NR_inotify_init1     333
 #define __NR_preadv            334
 #define __NR_pwritev           335
+#define __NR_rt_tgsigqueueinfo 336
+#define __NR_perf_counter_open 337
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 326
+#define NR_syscalls 338
 
 /*
  * specify the deprecated syscalls we want to support on this arch
index 7408a27199f342fd26679db7a326aa0b07885f53..e0d2563af4f24ad68ea2a0b0a72a76489257a99e 100644 (file)
@@ -722,6 +722,8 @@ ENTRY(sys_call_table)
        .long sys_inotify_init1
        .long sys_preadv
        .long sys_pwritev               /* 335 */
+       .long sys_rt_tgsigqueueinfo
+       .long sys_perf_counter_open
 
 
 nr_syscalls=(.-sys_call_table)/4
index e143339ad28e00869d9b23c1d882d994cdd89d62..cf847dabc1bd3a7cd810628ea2500bbfd8b922a7 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index 9f7572a0f5784a30d9ff16bbcfa407d10fc8a066..feb2f2e810db7c785ea5a7562ac77dfb79666a79 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
index bca5a84dc72cced1e6c597a02ec725181a651cfb..3e52a105432791ccab5860dac6fbc4f2b0436db1 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/syscalls.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
@@ -21,7 +20,6 @@
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
-#include <linux/syscalls.h>
 #include <linux/tty.h>
 
 #include <asm/uaccess.h>
index 681ad8c9e4fb68b59eebd992a7ee32f8be747e18..91365adba4f5568925d3398545d3b9bcc9ed9f96 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
@@ -136,8 +135,7 @@ void show_trace(unsigned long *sp)
        unsigned long *stack, addr, module_start, module_end;
        int i;
 
-       printk(KERN_EMERG "\n"
-              KERN_EMERG "Call Trace:");
+       printk(KERN_EMERG "\nCall Trace:");
 
        stack = sp;
        i = 0;
@@ -153,7 +151,7 @@ void show_trace(unsigned long *sp)
                        printk("\n");
 #else
                        if ((i % 6) == 0)
-                               printk("\n" KERN_EMERG "  ");
+                               printk(KERN_EMERG "  ");
                        printk("[<%08lx>] ", addr);
                        i++;
 #endif
@@ -180,7 +178,7 @@ void show_stack(struct task_struct *task, unsigned long *sp)
                if (((long) stack & (THREAD_SIZE - 1)) == 0)
                        break;
                if ((i % 8) == 0)
-                       printk("\n" KERN_EMERG "  ");
+                       printk(KERN_EMERG "  ");
                printk("%08lx ", *stack++);
        }
 
@@ -264,8 +262,7 @@ void show_registers(struct pt_regs *regs)
                show_stack(current, (unsigned long *) sp);
 
 #if 0
-               printk(KERN_EMERG "\n"
-                      KERN_EMERG "Code: ");
+               printk(KERN_EMERG "\nCode: ");
                if (regs->pc < PAGE_OFFSET)
                        goto bad;
 
@@ -311,16 +308,14 @@ void die(const char *str, struct pt_regs *regs, enum exception_code code)
 {
        console_verbose();
        spin_lock_irq(&die_lock);
-       printk(KERN_EMERG "\n"
-              KERN_EMERG "%s: %04x\n",
+       printk(KERN_EMERG "\n%s: %04x\n",
               str, code & 0xffff);
        show_registers(regs);
 
        if (regs->pc >= 0x02000000 && regs->pc < 0x04000000 &&
            (regs->epsw & (EPSW_IM | EPSW_IE)) != (EPSW_IM | EPSW_IE)) {
                printk(KERN_EMERG "Exception in usermode interrupt handler\n");
-               printk(KERN_EMERG "\n"
-                      KERN_EMERG "  Please connect to kernel debugger !!\n");
+               printk(KERN_EMERG "\nPlease connect to kernel debugger !!\n");
                asm volatile ("0: bra 0b");
        }
 
@@ -429,9 +424,8 @@ asmlinkage void io_bus_error(u32 bcberr, u32 bcbear, struct pt_regs *regs)
 {
        console_verbose();
 
-       printk(KERN_EMERG "\n"
-              KERN_EMERG "Asynchronous I/O Bus Error\n"
-              KERN_EMERG "==========================\n");
+       printk(KERN_EMERG "Asynchronous I/O Bus Error\n");
+       printk(KERN_EMERG "==========================\n");
 
        if (bcberr & BCBERR_BEME)
                printk(KERN_EMERG "- Multiple recorded errors\n");
index bcebcefb4ad7abee8b96bd69e4d231e355fb44d6..f4aa079346543f4ecfc47388bec429c66cf35733 100644 (file)
@@ -61,7 +61,7 @@ SECTIONS
        _edata = .;             /* End of data section */
   }
 
-  .data.init_task : { INIT_TASK(THREAD_SIZE); }
+  .data.init_task : { INIT_TASK_DATA(THREAD_SIZE); }
 
   /* might get freed after init */
   . = ALIGN(PAGE_SIZE);
@@ -107,7 +107,7 @@ SECTIONS
   __init_end = .;
   /* freed after init ends here */
 
-  BSS(4)
+  BSS_SECTION(0, PAGE_SIZE, 4)
 
   _end = . ;
 
index a62e1e138bc101c112872eae8b4eb9e0ce61d8cf..53bb17d0f0687764ab1d8a4e05d6cdfc81c03e25 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/vt_kern.h>             /* For unblank_screen() */
index 94c4a43580657a74b594561180759b5d2b43c37c..30016251f658507ec5a6501c35028dd74be22716 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
index 9038f39d9d736320996f95e6bae5d10473895da0..06f8d5b5b0f96d4bbb30cc5653cc6490d47df93e 100644 (file)
@@ -16,6 +16,8 @@ config PARISC
        select RTC_DRV_GENERIC
        select INIT_ALL_POSSIBLE
        select BUG
+       select HAVE_PERF_COUNTERS
+       select GENERIC_ATOMIC64 if !64BIT
        help
          The PA-RISC microprocessor is designed by Hewlett-Packard and used
          in many of their workstations & servers (HP9000 700 and 800 series,
index 7eeaff944360335c8548b0f25e1828432ea55f9b..8bc9e96699b2a690456aa75585a9f89c05cad7bf 100644 (file)
@@ -222,13 +222,13 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
-#define atomic_add(i,v)        ((void)(__atomic_add_return( ((int)(i)),(v))))
-#define atomic_sub(i,v)        ((void)(__atomic_add_return(-((int)(i)),(v))))
+#define atomic_add(i,v)        ((void)(__atomic_add_return( (i),(v))))
+#define atomic_sub(i,v)        ((void)(__atomic_add_return(-(i),(v))))
 #define atomic_inc(v)  ((void)(__atomic_add_return(   1,(v))))
 #define atomic_dec(v)  ((void)(__atomic_add_return(  -1,(v))))
 
-#define atomic_add_return(i,v) (__atomic_add_return( ((int)(i)),(v)))
-#define atomic_sub_return(i,v) (__atomic_add_return(-((int)(i)),(v)))
+#define atomic_add_return(i,v) (__atomic_add_return( (i),(v)))
+#define atomic_sub_return(i,v) (__atomic_add_return(-(i),(v)))
 #define atomic_inc_return(v)   (__atomic_add_return(   1,(v)))
 #define atomic_dec_return(v)   (__atomic_add_return(  -1,(v)))
 
@@ -336,7 +336,11 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 
 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
 
-#endif /* CONFIG_64BIT */
+#else /* CONFIG_64BIT */
+
+#include <asm-generic/atomic64.h>
+
+#endif /* !CONFIG_64BIT */
 
 #include <asm-generic/atomic-long.h>
 
index 31ad0f05af3d4dec0a66bba5d02a118f748d5896..f7a18f96870347172594335092840aa10a060683 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: dma.h,v 1.2 1999/04/27 00:46:18 deller Exp $
- * linux/include/asm/dma.h: Defines for using and allocating dma channels.
+/* asm/dma.h: Defines for using and allocating dma channels.
  * Written by Hennus Bergman, 1992.
  * High DMA channel support & info by Hannu Savolainen
  * and John Boyd, Nov. 1992.
diff --git a/arch/parisc/include/asm/perf_counter.h b/arch/parisc/include/asm/perf_counter.h
new file mode 100644 (file)
index 0000000..dc9e829
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __ASM_PARISC_PERF_COUNTER_H
+#define __ASM_PARISC_PERF_COUNTER_H
+
+/* parisc only supports software counters through this interface. */
+static inline void set_perf_counter_pending(void) { }
+
+#endif /* __ASM_PARISC_PERF_COUNTER_H */
index 9d64df8754ba5203c9a7299038ab5c01ea68185b..9ce66e9d1c2b845275c41aaaf290a5fb5e123ba1 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/types.h>
 #include <asm/system.h>
 #include <asm/percpu.h>
+
 #endif /* __ASSEMBLY__ */
 
 #define KERNEL_STACK_SIZE      (4*PAGE_SIZE)
@@ -127,6 +128,8 @@ struct thread_struct {
        unsigned long  flags;
 }; 
 
+#define task_pt_regs(tsk) ((struct pt_regs *)&((tsk)->thread.regs))
+
 /* Thread struct flags. */
 #define PARISC_UAC_NOPRINT     (1UL << 0)      /* see prctl and unaligned.c */
 #define PARISC_UAC_SIGBUS      (1UL << 1)
index ee80c920b464e549848664794ac742a9e4714fd9..d91357bca5b4cc18a3c143f948f24c7afef379cc 100644 (file)
@@ -168,8 +168,8 @@ static inline void set_eiem(unsigned long val)
 /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*.  */
 #define __ldcw(a) ({                                           \
        unsigned __ret;                                         \
-       __asm__ __volatile__(__LDCW " 0(%1),%0"                 \
-               : "=r" (__ret) : "r" (a));                      \
+       __asm__ __volatile__(__LDCW " 0(%2),%0"                 \
+               : "=r" (__ret), "+m" (*(a)) : "r" (a));         \
        __ret;                                                  \
 })
 
index 0407959da489d54a72b4ccab371cc21e996e79a3..4ce0edfbe9694dc4daaed2253a625e9d46a25c72 100644 (file)
@@ -23,7 +23,7 @@ struct thread_info {
        .flags          = 0,                    \
        .cpu            = 0,                    \
        .addr_limit     = KERNEL_DS,            \
-       .preempt_count  = 1,                    \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .restart_block  = {                     \
                .fn = do_no_restart_syscall     \
        }                                       \
index 383b1db310ee71e18789112587f9ba3e818bdd25..07924903989eed2a8ce2d93cb349332918e1db6e 100644 (file)
@@ -21,7 +21,7 @@ do {  if (!(tlb)->fullmm)     \
 
 #include <asm-generic/tlb.h>
 
-#define __pmd_free_tlb(tlb, pmd)       pmd_free((tlb)->mm, pmd)
-#define __pte_free_tlb(tlb, pte)       pte_free((tlb)->mm, pte)
+#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd)
+#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
 
 #endif
index 1f6fd4fc05b91b518f4f574b3ada13ddd24b285a..8f1a8100bf2df394f0ca78e90dbec9f33d33125d 100644 (file)
  * N class systems, only one PxTLB inter processor broadcast can be
  * active at any one time on the Merced bus.  This tlb purge
  * synchronisation is fairly lightweight and harmless so we activate
- * it on all SMP systems not just the N class.  We also need to have
- * preemption disabled on uniprocessor machines, and spin_lock does that
- * nicely.
+ * it on all systems not just the N class.
  */
 extern spinlock_t pa_tlb_lock;
 
-#define purge_tlb_start(x) spin_lock(&pa_tlb_lock)
-#define purge_tlb_end(x) spin_unlock(&pa_tlb_lock)
+#define purge_tlb_start(flags) spin_lock_irqsave(&pa_tlb_lock, flags)
+#define purge_tlb_end(flags)   spin_unlock_irqrestore(&pa_tlb_lock, flags)
 
 extern void flush_tlb_all(void);
 extern void flush_tlb_all_local(void *);
@@ -63,14 +61,16 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
 static inline void flush_tlb_page(struct vm_area_struct *vma,
        unsigned long addr)
 {
+       unsigned long flags;
+
        /* For one page, it's not worth testing the split_tlb variable */
 
        mb();
        mtsp(vma->vm_mm->context,1);
-       purge_tlb_start();
+       purge_tlb_start(flags);
        pdtlb(addr);
        pitlb(addr);
-       purge_tlb_end();
+       purge_tlb_end(flags);
 }
 
 void __flush_tlb_range(unsigned long sid,
index ef26b009dc5da1f323a7fc77d329e6c520b5e40f..f3d3b8b012c494e9783511da12c37277c4d7c920 100644 (file)
 #define __NR_dup3              (__NR_Linux + 312)
 #define __NR_pipe2             (__NR_Linux + 313)
 #define __NR_inotify_init1     (__NR_Linux + 314)
+#define __NR_preadv            (__NR_Linux + 315)
+#define __NR_pwritev           (__NR_Linux + 316)
+#define __NR_rt_tgsigqueueinfo (__NR_Linux + 317)
+#define __NR_perf_counter_open (__NR_Linux + 318)
 
-#define __NR_Linux_syscalls    (__NR_inotify_init1 + 1)
+#define __NR_Linux_syscalls    (__NR_perf_counter_open + 1)
 
 
 #define __IGNORE_select                /* newselect */
index 837530ea32e783e6671ce2793bf08f30424b6808..b6ed34de14e15899cbcfccdbfa25cd80649282a6 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: cache.c,v 1.4 2000/01/25 00:11:38 prumpf Exp $
- *
+/*
  * 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.
@@ -398,12 +397,13 @@ EXPORT_SYMBOL(flush_kernel_icache_range_asm);
 
 void clear_user_page_asm(void *page, unsigned long vaddr)
 {
+       unsigned long flags;
        /* This function is implemented in assembly in pacache.S */
        extern void __clear_user_page_asm(void *page, unsigned long vaddr);
 
-       purge_tlb_start();
+       purge_tlb_start(flags);
        __clear_user_page_asm(page, vaddr);
-       purge_tlb_end();
+       purge_tlb_end(flags);
 }
 
 #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */
@@ -444,20 +444,24 @@ extern void clear_user_page_asm(void *page, unsigned long vaddr);
 
 void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
 {
+       unsigned long flags;
+
        purge_kernel_dcache_page((unsigned long)page);
-       purge_tlb_start();
+       purge_tlb_start(flags);
        pdtlb_kernel(page);
-       purge_tlb_end();
+       purge_tlb_end(flags);
        clear_user_page_asm(page, vaddr);
 }
 EXPORT_SYMBOL(clear_user_page);
 
 void flush_kernel_dcache_page_addr(void *addr)
 {
+       unsigned long flags;
+
        flush_kernel_dcache_page_asm(addr);
-       purge_tlb_start();
+       purge_tlb_start(flags);
        pdtlb_kernel(addr);
-       purge_tlb_end();
+       purge_tlb_end(flags);
 }
 EXPORT_SYMBOL(flush_kernel_dcache_page_addr);
 
@@ -490,8 +494,10 @@ void __flush_tlb_range(unsigned long sid, unsigned long start,
        if (npages >= 512)  /* 2MB of space: arbitrary, should be tuned */
                flush_tlb_all();
        else {
+               unsigned long flags;
+
                mtsp(sid, 1);
-               purge_tlb_start();
+               purge_tlb_start(flags);
                if (split_tlb) {
                        while (npages--) {
                                pdtlb(start);
@@ -504,7 +510,7 @@ void __flush_tlb_range(unsigned long sid, unsigned long start,
                                start += PAGE_SIZE;
                        }
                }
-               purge_tlb_end();
+               purge_tlb_end(flags);
        }
 }
 
index ae3e70cd1e14e4acf2da03717d77d0b9ea0d7faa..e552e547cb93fd88050ee800d62f2f2667b3ba5d 100644 (file)
         * on most of those machines only handles cache transactions.
         */
        extrd,u,*=      \pte,_PAGE_NO_CACHE_BIT+32,1,%r0
-       dep           1,12,1,\prot
+       depdi           1,12,1,\prot
 
        /* Drop prot bits and convert to page addr for iitlbt and idtlbt */
        convert_for_tlb_insert20 \pte
index bd1f7f1ff74e7b6589c4a97f6fcebd28453a1d19..d228d823787991f138cea6651bbb6787701b7db5 100644 (file)
@@ -170,23 +170,27 @@ static void __init pagezero_memconfig(void)
 static int __init 
 pat_query_module(ulong pcell_loc, ulong mod_index)
 {
-       pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
+       pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell;
        unsigned long bytecnt;
        unsigned long temp;     /* 64-bit scratch value */
        long status;            /* PDC return value status */
        struct parisc_device *dev;
 
+       pa_pdc_cell = kmalloc(sizeof (*pa_pdc_cell), GFP_KERNEL);
+       if (!pa_pdc_cell)
+               panic("couldn't allocate memory for PDC_PAT_CELL!");
+
        /* return cell module (PA or Processor view) */
        status = pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index,
-                                    PA_VIEW, &pa_pdc_cell);
+                                    PA_VIEW, pa_pdc_cell);
 
        if (status != PDC_OK) {
                /* no more cell modules or error */
                return status;
        }
 
-       temp = pa_pdc_cell.cba;
-       dev = alloc_pa_dev(PAT_GET_CBA(temp), &pa_pdc_cell.mod_path);
+       temp = pa_pdc_cell->cba;
+       dev = alloc_pa_dev(PAT_GET_CBA(temp), &(pa_pdc_cell->mod_path));
        if (!dev) {
                return PDC_OK;
        }
@@ -203,8 +207,8 @@ pat_query_module(ulong pcell_loc, ulong mod_index)
 
        /* save generic info returned from the call */
        /* REVISIT: who is the consumer of this? not sure yet... */
-       dev->mod_info = pa_pdc_cell.mod_info;   /* pass to PAT_GET_ENTITY() */
-       dev->pmod_loc = pa_pdc_cell.mod_location;
+       dev->mod_info = pa_pdc_cell->mod_info;  /* pass to PAT_GET_ENTITY() */
+       dev->pmod_loc = pa_pdc_cell->mod_location;
 
        register_parisc_device(dev);    /* advertise device */
 
@@ -216,14 +220,14 @@ pat_query_module(ulong pcell_loc, ulong mod_index)
 
        case PAT_ENTITY_PROC:
                printk(KERN_DEBUG "PAT_ENTITY_PROC: id_eid 0x%lx\n",
-                       pa_pdc_cell.mod[0]);
+                       pa_pdc_cell->mod[0]);
                break;
 
        case PAT_ENTITY_MEM:
                printk(KERN_DEBUG 
                        "PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lx\n",
-                       pa_pdc_cell.mod[0], pa_pdc_cell.mod[1], 
-                       pa_pdc_cell.mod[2]);
+                       pa_pdc_cell->mod[0], pa_pdc_cell->mod[1],
+                       pa_pdc_cell->mod[2]);
                break;
        case PAT_ENTITY_CA:
                printk(KERN_DEBUG "PAT_ENTITY_CA: %ld\n", pcell_loc);
@@ -243,23 +247,26 @@ pat_query_module(ulong pcell_loc, ulong mod_index)
  print_ranges:
                pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index,
                                    IO_VIEW, &io_pdc_cell);
-               printk(KERN_DEBUG "ranges %ld\n", pa_pdc_cell.mod[1]);
-               for (i = 0; i < pa_pdc_cell.mod[1]; i++) {
+               printk(KERN_DEBUG "ranges %ld\n", pa_pdc_cell->mod[1]);
+               for (i = 0; i < pa_pdc_cell->mod[1]; i++) {
                        printk(KERN_DEBUG 
                                "  PA_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", 
-                               i, pa_pdc_cell.mod[2 + i * 3],  /* type */
-                               pa_pdc_cell.mod[3 + i * 3],     /* start */
-                               pa_pdc_cell.mod[4 + i * 3]);    /* finish (ie end) */
+                               i, pa_pdc_cell->mod[2 + i * 3], /* type */
+                               pa_pdc_cell->mod[3 + i * 3],    /* start */
+                               pa_pdc_cell->mod[4 + i * 3]);   /* finish (ie end) */
                        printk(KERN_DEBUG 
                                "  IO_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", 
-                               i, io_pdc_cell.mod[2 + i * 3],  /* type */
-                               io_pdc_cell.mod[3 + i * 3],     /* start */
-                               io_pdc_cell.mod[4 + i * 3]);    /* finish (ie end) */
+                               i, io_pdc_cell->mod[2 + i * 3], /* type */
+                               io_pdc_cell->mod[3 + i * 3],    /* start */
+                               io_pdc_cell->mod[4 + i * 3]);   /* finish (ie end) */
                }
                printk(KERN_DEBUG "\n");
                break;
        }
 #endif /* DEBUG_PAT */
+
+       kfree(pa_pdc_cell);
+
        return PDC_OK;
 }
 
index 8007f1e6572986559789a2520603a77336c72214..330f536a9324798afda4580d152c09eb3b04c141 100644 (file)
@@ -120,7 +120,7 @@ int cpu_check_affinity(unsigned int irq, const struct cpumask *dest)
        if (CHECK_IRQ_PER_CPU(irq)) {
                /* Bad linux design decision.  The mask has already
                 * been set; we must reset it */
-               cpumask_setall(&irq_desc[irq].affinity);
+               cpumask_setall(irq_desc[irq].affinity);
                return -EINVAL;
        }
 
@@ -138,13 +138,13 @@ static int cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest)
        if (cpu_dest < 0)
                return -1;
 
-       cpumask_copy(&irq_desc[irq].affinity, dest);
+       cpumask_copy(irq_desc[irq].affinity, dest);
 
        return 0;
 }
 #endif
 
-static struct hw_interrupt_type cpu_interrupt_type = {
+static struct irq_chip cpu_interrupt_type = {
        .typename       = "CPU",
        .startup        = cpu_startup_irq,
        .shutdown       = cpu_disable_irq,
@@ -299,7 +299,7 @@ int txn_alloc_irq(unsigned int bits_wide)
 unsigned long txn_affinity_addr(unsigned int irq, int cpu)
 {
 #ifdef CONFIG_SMP
-       cpumask_copy(&irq_desc[irq].affinity, cpumask_of(cpu));
+       cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
 #endif
 
        return per_cpu(cpu_data, cpu).txn_addr;
@@ -356,7 +356,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
        irq = eirr_to_irq(eirr_val);
 
 #ifdef CONFIG_SMP
-       cpumask_copy(&dest, &irq_desc[irq].affinity);
+       cpumask_copy(&dest, irq_desc[irq].affinity);
        if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) &&
            !cpu_isset(smp_processor_id(), dest)) {
                int cpu = first_cpu(dest);
index ef5caf2e6ed0820944c9ea891dd33c49c2a5ceda..61ee0eec4e699b93f3555770c18bc2b221c8f0de 100644 (file)
  * the bottom of the table, which has a maximum signed displacement of
  * 0x3fff; however, since we're only going forward, this becomes
  * 0x1fff, and thus, since each GOT entry is 8 bytes long we can have
- * at most 1023 entries */
-#define MAX_GOTS       1023
+ * at most 1023 entries.
+ * To overcome this 14bit displacement with some kernel modules, we'll
+ * use instead the unusal 16bit displacement method (see reassemble_16a)
+ * which gives us a maximum positive displacement of 0x7fff, and as such
+ * allows us to allocate up to 4095 GOT entries. */
+#define MAX_GOTS       4095
 
 /* three functions to determine where in the module core
  * or init pieces the location is */
@@ -145,12 +149,40 @@ struct stub_entry {
 /* The reassemble_* functions prepare an immediate value for
    insertion into an opcode. pa-risc uses all sorts of weird bitfields
    in the instruction to hold the value.  */
+static inline int sign_unext(int x, int len)
+{
+       int len_ones;
+
+       len_ones = (1 << len) - 1;
+       return x & len_ones;
+}
+
+static inline int low_sign_unext(int x, int len)
+{
+       int sign, temp;
+
+       sign = (x >> (len-1)) & 1;
+       temp = sign_unext(x, len-1);
+       return (temp << 1) | sign;
+}
+
 static inline int reassemble_14(int as14)
 {
        return (((as14 & 0x1fff) << 1) |
                ((as14 & 0x2000) >> 13));
 }
 
+static inline int reassemble_16a(int as16)
+{
+       int s, t;
+
+       /* Unusual 16-bit encoding, for wide mode only.  */
+       t = (as16 << 1) & 0xffff;
+       s = (as16 & 0x8000);
+       return (t ^ s ^ (s >> 1)) | (s >> 15);
+}
+
+
 static inline int reassemble_17(int as17)
 {
        return (((as17 & 0x10000) >> 16) |
@@ -407,6 +439,7 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
        enum elf_stub_type stub_type, Elf_Addr loc0, unsigned int targetsec)
 {
        struct stub_entry *stub;
+       int __maybe_unused d;
 
        /* initialize stub_offset to point in front of the section */
        if (!me->arch.section[targetsec].stub_offset) {
@@ -460,12 +493,19 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
  */
        switch (stub_type) {
        case ELF_STUB_GOT:
-               stub->insns[0] = 0x537b0000;    /* ldd 0(%dp),%dp       */
+               d = get_got(me, value, addend);
+               if (d <= 15) {
+                       /* Format 5 */
+                       stub->insns[0] = 0x0f6010db; /* ldd 0(%dp),%dp  */
+                       stub->insns[0] |= low_sign_unext(d, 5) << 16;
+               } else {
+                       /* Format 3 */
+                       stub->insns[0] = 0x537b0000; /* ldd 0(%dp),%dp  */
+                       stub->insns[0] |= reassemble_16a(d);
+               }
                stub->insns[1] = 0x53610020;    /* ldd 10(%dp),%r1      */
                stub->insns[2] = 0xe820d000;    /* bve (%r1)            */
                stub->insns[3] = 0x537b0030;    /* ldd 18(%dp),%dp      */
-
-               stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff);
                break;
        case ELF_STUB_MILLI:
                stub->insns[0] = 0x20200000;    /* ldil 0,%r1           */
index 7d927eac932b9ccf598bc710bba8e965b2bcd539..c07f618ff7da9264fc9aa242cfaf1515b72d8af5 100644 (file)
@@ -90,12 +90,14 @@ static inline int map_pte_uncached(pte_t * pte,
        if (end > PMD_SIZE)
                end = PMD_SIZE;
        do {
+               unsigned long flags;
+
                if (!pte_none(*pte))
                        printk(KERN_ERR "map_pte_uncached: page already exists\n");
                set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC));
-               purge_tlb_start();
+               purge_tlb_start(flags);
                pdtlb_kernel(orig_vaddr);
-               purge_tlb_end();
+               purge_tlb_end(flags);
                vaddr += PAGE_SIZE;
                orig_vaddr += PAGE_SIZE;
                (*paddr_ptr) += PAGE_SIZE;
@@ -168,11 +170,13 @@ static inline void unmap_uncached_pte(pmd_t * pmd, unsigned long vaddr,
        if (end > PMD_SIZE)
                end = PMD_SIZE;
        do {
+               unsigned long flags;
                pte_t page = *pte;
+
                pte_clear(&init_mm, vaddr, pte);
-               purge_tlb_start();
+               purge_tlb_start(flags);
                pdtlb_kernel(orig_vaddr);
-               purge_tlb_end();
+               purge_tlb_end(flags);
                vaddr += PAGE_SIZE;
                orig_vaddr += PAGE_SIZE;
                pte++;
index 6936386c9861a3721aba9a857158e8cc9133743e..f7064abc3bb6e60a544e3bfb97c12f468768fd89 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: pci.c,v 1.6 2000/01/29 00:12:05 grundler Exp $
- *
+/*
  * 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.
index 61c07078c072d69c60769e4273339c3ac8fe8d62..1f3aa8db02030a1509253b6d0d51d4910f522761 100644 (file)
@@ -156,7 +156,7 @@ void machine_power_off(void)
         * software. The user has to press the button himself. */
 
        printk(KERN_EMERG "System shut down completed.\n"
-              KERN_EMERG "Please power this system off now.");
+              "Please power this system off now.");
 }
 
 void (*pm_power_off)(void) = machine_power_off;
index e09d0f7fb6b047ad2c2cf34d95046f89f2263874..c8fb61ed32f4eeee5bb27b648468e10da0962034 100644 (file)
@@ -1,5 +1,4 @@
-/*    $Id: processor.c,v 1.1 2002/07/20 16:27:06 rhirst Exp $
- *
+/*
  *    Initial setup-routines for HP 9000 based hardware.
  *
  *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
@@ -121,22 +120,28 @@ static int __cpuinit processor_probe(struct parisc_device *dev)
        if (is_pdc_pat()) {
                ulong status;
                unsigned long bytecnt;
-               pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
+               pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell;
 #undef USE_PAT_CPUID
 #ifdef USE_PAT_CPUID
                struct pdc_pat_cpu_num cpu_info;
 #endif
 
+               pa_pdc_cell = kmalloc(sizeof (*pa_pdc_cell), GFP_KERNEL);
+               if (!pa_pdc_cell)
+                       panic("couldn't allocate memory for PDC_PAT_CELL!");
+
                status = pdc_pat_cell_module(&bytecnt, dev->pcell_loc,
-                       dev->mod_index, PA_VIEW, &pa_pdc_cell);
+                       dev->mod_index, PA_VIEW, pa_pdc_cell);
 
                BUG_ON(PDC_OK != status);
 
                /* verify it's the same as what do_pat_inventory() found */
-               BUG_ON(dev->mod_info != pa_pdc_cell.mod_info);
-               BUG_ON(dev->pmod_loc != pa_pdc_cell.mod_location);
+               BUG_ON(dev->mod_info != pa_pdc_cell->mod_info);
+               BUG_ON(dev->pmod_loc != pa_pdc_cell->mod_location);
+
+               txn_addr = pa_pdc_cell->mod[0];   /* id_eid for IO sapic */
 
-               txn_addr = pa_pdc_cell.mod[0];   /* id_eid for IO sapic */
+               kfree(pa_pdc_cell);
 
 #ifdef USE_PAT_CPUID
 /* We need contiguous numbers for cpuid. Firmware's notion
index 82131ca8e05c28790bbc133690e2267f1be67034..cb71f3dac99525a525027fa2f532a20e4c3caa93 100644 (file)
@@ -1,5 +1,4 @@
-/*    $Id: setup.c,v 1.8 2000/02/02 04:42:38 prumpf Exp $
- *
+/*
  *    Initial setup-routines for HP 9000 based hardware.
  *
  *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
index 1adb40c8166965ae1c397abe272187a42639fcf6..92a0acaa0d1213042bd871e83a2024cc1ae59aa6 100644 (file)
@@ -174,68 +174,6 @@ asmlinkage long sys32_sched_rr_get_interval(pid_t pid,
        return ret;
 }
 
-/*** copied from mips64 ***/
-/*
- * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
- * 64-bit unsigned longs.
- */
-
-static inline int
-get_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
-{
-       n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
-       if (ufdset) {
-               unsigned long odd;
-
-               if (!access_ok(VERIFY_WRITE, ufdset, n*sizeof(u32)))
-                       return -EFAULT;
-
-               odd = n & 1UL;
-               n &= ~1UL;
-               while (n) {
-                       unsigned long h, l;
-                       __get_user(l, ufdset);
-                       __get_user(h, ufdset+1);
-                       ufdset += 2;
-                       *fdset++ = h << 32 | l;
-                       n -= 2;
-               }
-               if (odd)
-                       __get_user(*fdset, ufdset);
-       } else {
-               /* Tricky, must clear full unsigned long in the
-                * kernel fdset at the end, this makes sure that
-                * actually happens.
-                */
-               memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
-       }
-       return 0;
-}
-
-static inline void
-set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
-{
-       unsigned long odd;
-       n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
-
-       if (!ufdset)
-               return;
-
-       odd = n & 1UL;
-       n &= ~1UL;
-       while (n) {
-               unsigned long h, l;
-               l = *fdset++;
-               h = l >> 32;
-               __put_user(l, ufdset);
-               __put_user(h, ufdset+1);
-               ufdset += 2;
-               n -= 2;
-       }
-       if (odd)
-               __put_user(*fdset, ufdset);
-}
-
 struct msgbuf32 {
     int mtype;
     char mtext[1];
index 03b9a01bc16cf49340db4d69329a08338e47650f..cf145eb026b34f9049075b2c6bf348ebef2ceb43 100644 (file)
        ENTRY_SAME(dup3)
        ENTRY_SAME(pipe2)
        ENTRY_SAME(inotify_init1)
+       ENTRY_COMP(preadv)              /* 315 */
+       ENTRY_COMP(pwritev)
+       ENTRY_COMP(rt_tgsigqueueinfo)
+       ENTRY_SAME(perf_counter_open)
 
        /* Nothing yet */
 
index d4dd05674c6234b495acdb25431bb5fd9a437261..a79c6f9e7e2c441f0d2d7feda117ae14c72ad065 100644 (file)
@@ -56,9 +56,9 @@ static unsigned long clocktick __read_mostly; /* timer cycles per tick */
  */
 irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
 {
-       unsigned long now;
+       unsigned long now, now2;
        unsigned long next_tick;
-       unsigned long cycles_elapsed, ticks_elapsed;
+       unsigned long cycles_elapsed, ticks_elapsed = 1;
        unsigned long cycles_remainder;
        unsigned int cpu = smp_processor_id();
        struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu);
@@ -71,44 +71,24 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
        /* Initialize next_tick to the expected tick time. */
        next_tick = cpuinfo->it_value;
 
-       /* Get current interval timer.
-        * CR16 reads as 64 bits in CPU wide mode.
-        * CR16 reads as 32 bits in CPU narrow mode.
-        */
+       /* Get current cycle counter (Control Register 16). */
        now = mfctl(16);
 
        cycles_elapsed = now - next_tick;
 
-       if ((cycles_elapsed >> 5) < cpt) {
+       if ((cycles_elapsed >> 6) < cpt) {
                /* use "cheap" math (add/subtract) instead
                 * of the more expensive div/mul method
                 */
                cycles_remainder = cycles_elapsed;
-               ticks_elapsed = 1;
                while (cycles_remainder > cpt) {
                        cycles_remainder -= cpt;
                        ticks_elapsed++;
                }
        } else {
+               /* TODO: Reduce this to one fdiv op */
                cycles_remainder = cycles_elapsed % cpt;
-               ticks_elapsed = 1 + cycles_elapsed / cpt;
-       }
-
-       /* Can we differentiate between "early CR16" (aka Scenario 1) and
-        * "long delay" (aka Scenario 3)? I don't think so.
-        *
-        * We expected timer_interrupt to be delivered at least a few hundred
-        * cycles after the IT fires. But it's arbitrary how much time passes
-        * before we call it "late". I've picked one second.
-        */
-       if (unlikely(ticks_elapsed > HZ)) {
-               /* Scenario 3: very long delay?  bad in any case */
-               printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!"
-                       " cycles %lX rem %lX "
-                       " next/now %lX/%lX\n",
-                       cpu,
-                       cycles_elapsed, cycles_remainder,
-                       next_tick, now );
+               ticks_elapsed += cycles_elapsed / cpt;
        }
 
        /* convert from "division remainder" to "remainder of clock tick" */
@@ -122,18 +102,56 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
 
        cpuinfo->it_value = next_tick;
 
-       /* Skip one clocktick on purpose if we are likely to miss next_tick.
-        * We want to avoid the new next_tick being less than CR16.
-        * If that happened, itimer wouldn't fire until CR16 wrapped.
-        * We'll catch the tick we missed on the tick after that.
+       /* Program the IT when to deliver the next interrupt.
+        * Only bottom 32-bits of next_tick are writable in CR16!
         */
-       if (!(cycles_remainder >> 13))
-               next_tick += cpt;
-
-       /* Program the IT when to deliver the next interrupt. */
-       /* Only bottom 32-bits of next_tick are written to cr16.  */
        mtctl(next_tick, 16);
 
+       /* Skip one clocktick on purpose if we missed next_tick.
+        * The new CR16 must be "later" than current CR16 otherwise
+        * itimer would not fire until CR16 wrapped - e.g 4 seconds
+        * later on a 1Ghz processor. We'll account for the missed
+        * tick on the next timer interrupt.
+        *
+        * "next_tick - now" will always give the difference regardless
+        * if one or the other wrapped. If "now" is "bigger" we'll end up
+        * with a very large unsigned number.
+        */
+       now2 = mfctl(16);
+       if (next_tick - now2 > cpt)
+               mtctl(next_tick+cpt, 16);
+
+#if 1
+/*
+ * GGG: DEBUG code for how many cycles programming CR16 used.
+ */
+       if (unlikely(now2 - now > 0x3000))      /* 12K cycles */
+               printk (KERN_CRIT "timer_interrupt(CPU %d): SLOW! 0x%lx cycles!"
+                       " cyc %lX rem %lX "
+                       " next/now %lX/%lX\n",
+                       cpu, now2 - now, cycles_elapsed, cycles_remainder,
+                       next_tick, now );
+#endif
+
+       /* Can we differentiate between "early CR16" (aka Scenario 1) and
+        * "long delay" (aka Scenario 3)? I don't think so.
+        *
+        * Timer_interrupt will be delivered at least a few hundred cycles
+        * after the IT fires. But it's arbitrary how much time passes
+        * before we call it "late". I've picked one second.
+        *
+        * It's important NO printk's are between reading CR16 and
+        * setting up the next value. May introduce huge variance.
+        */
+       if (unlikely(ticks_elapsed > HZ)) {
+               /* Scenario 3: very long delay?  bad in any case */
+               printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!"
+                       " cycles %lX rem %lX "
+                       " next/now %lX/%lX\n",
+                       cpu,
+                       cycles_elapsed, cycles_remainder,
+                       next_tick, now );
+       }
 
        /* Done mucking with unreliable delivery of interrupts.
         * Go do system house keeping.
@@ -173,7 +191,7 @@ EXPORT_SYMBOL(profile_pc);
 
 /* clock source code */
 
-static cycle_t read_cr16(void)
+static cycle_t read_cr16(struct clocksource *cs)
 {
        return get_cycles();
 }
index c32f5d6d778ec7bd10c028cf40db645af659686a..8b58bf0b7d5aa47fd6f54317c74a0528e253b86c 100644 (file)
@@ -250,15 +250,14 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
        oops_enter();
 
        /* Amuse the user in a SPARC fashion */
-       if (err) printk(
-KERN_CRIT "      _______________________________ \n"
-KERN_CRIT "     < Your System ate a SPARC! Gah! >\n"
-KERN_CRIT "      ------------------------------- \n"
-KERN_CRIT "             \\   ^__^\n"
-KERN_CRIT "              \\  (xx)\\_______\n"
-KERN_CRIT "                 (__)\\       )\\/\\\n"
-KERN_CRIT "                  U  ||----w |\n"
-KERN_CRIT "                     ||     ||\n");
+       if (err) printk(KERN_CRIT
+                       "      _______________________________ \n"
+                       "     < Your System ate a SPARC! Gah! >\n"
+                       "      ------------------------------- \n"
+                       "             \\   ^__^\n"
+                       "                 (__)\\       )\\/\\\n"
+                       "                  U  ||----w |\n"
+                       "                     ||     ||\n");
        
        /* unlock the pdc lock if necessary */
        pdc_emergency_unlock();
@@ -533,7 +532,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
                /* Kill the user process later */
                regs->iaoq[0] = 0 | 3;
                regs->iaoq[1] = regs->iaoq[0] + 4;
-               regs->iasq[0] = regs->iasq[0] = regs->sr[7];
+               regs->iasq[0] = regs->iasq[1] = regs->sr[7];
                regs->gr[0] &= ~PSW_B;
                return;
        }
@@ -797,7 +796,8 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
                else
                        printk(KERN_DEBUG "User Fault (long pointer) (fault %d) ",
                               code);
-               printk("pid=%d command='%s'\n", task_pid_nr(current), current->comm);
+               printk(KERN_CONT "pid=%d command='%s'\n",
+                      task_pid_nr(current), current->comm);
                show_regs(regs);
 #endif
                si.si_signo = SIGSEGV;
index 462696d30d3bd601b366afcd4e0d0048a61050f3..ae66d31f9ecf7d713d3c995a23330980d361c067 100644 (file)
@@ -13,8 +13,6 @@
  *             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.
- *
- * $Id: checksum.c,v 1.3 1997/12/01 17:57:34 ralf Exp $
  */
 #include <linux/module.h>
 #include <linux/types.h>
index bbda909c866e57c1327b6ccd47cf9bab8dc992d4..abf41f4632a9fca1b8df2c4ba963c2e328e553e7 100644 (file)
@@ -405,7 +405,7 @@ byte_copy:
 
 unaligned_copy:
        /* possibly we are aligned on a word, but not on a double... */
-       if (likely(t1 & (sizeof(unsigned int)-1)) == 0) {
+       if (likely((t1 & (sizeof(unsigned int)-1)) == 0)) {
                t2 = src & (sizeof(unsigned int) - 1);
 
                if (unlikely(t2 != 0)) {
index 66c8a9f6a27eba49f17798873e97419a6104c282..3ca1c61492182d3321c2fe7d2cf00d003ff5a8a5 100644 (file)
@@ -40,7 +40,7 @@
  * END_DESC
 */
 
-
+#include <linux/kernel.h>
 #include "float.h"
 #include "sgl_float.h"
 #include "dbl_float.h"
index bfb6dd6ab380c3a2b762575d28e36008900658f4..c6afbfc957703f800610a96f0caa8008f53e598e 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: fault.c,v 1.5 2000/01/26 16:20:29 jsm Exp $
- *
+/*
  * 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.
index 4356ceb1e366d9ed010706ac21dceb8ac24ba151..b0831d9e35cba677d153af1ac7efd0583fc618aa 100644 (file)
@@ -370,34 +370,22 @@ static void __init setup_bootmem(void)
 
 void free_initmem(void)
 {
-       unsigned long addr, init_begin, init_end;
-
-       printk(KERN_INFO "Freeing unused kernel memory: ");
+       unsigned long addr;
+       unsigned long init_begin = (unsigned long)__init_begin;
+       unsigned long init_end = (unsigned long)__init_end;
 
 #ifdef CONFIG_DEBUG_KERNEL
        /* Attempt to catch anyone trying to execute code here
         * by filling the page with BRK insns.
-        * 
-        * If we disable interrupts for all CPUs, then IPI stops working.
-        * Kinda breaks the global cache flushing.
         */
-       local_irq_disable();
-
-       memset(__init_begin, 0x00,
-               (unsigned long)__init_end - (unsigned long)__init_begin);
-
-       flush_data_cache();
-       asm volatile("sync" : : );
-       flush_icache_range((unsigned long)__init_begin, (unsigned long)__init_end);
-       asm volatile("sync" : : );
-
-       local_irq_enable();
+       memset((void *)init_begin, 0x00, init_end - init_begin);
+       flush_icache_range(init_begin, init_end);
 #endif
        
        /* align __init_begin and __init_end to page size,
           ignoring linker script where we might have tried to save RAM */
-       init_begin = PAGE_ALIGN((unsigned long)(__init_begin));
-       init_end   = PAGE_ALIGN((unsigned long)(__init_end));
+       init_begin = PAGE_ALIGN(init_begin);
+       init_end = PAGE_ALIGN(init_end);
        for (addr = init_begin; addr < init_end; addr += PAGE_SIZE) {
                ClearPageReserved(virt_to_page(addr));
                init_page_count(virt_to_page(addr));
@@ -409,7 +397,8 @@ void free_initmem(void)
        /* set up a new led state on systems shipped LED State panel */
        pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BCOMPLETE);
        
-       printk("%luk freed\n", (init_end - init_begin) >> 10);
+       printk(KERN_INFO "Freeing unused kernel memory: %luk freed\n",
+               (init_end - init_begin) >> 10);
 }
 
 
index bf6cedfa05dbfbef2073ec2b9d652dd21fac504d..d00131ca0835e71cb8cd25d19f9f9f43557083df 100644 (file)
@@ -62,7 +62,6 @@ config HAVE_LATENCYTOP_SUPPORT
 
 config TRACE_IRQFLAGS_SUPPORT
        bool
-       depends on PPC64
        default y
 
 config LOCKDEP_SUPPORT
index 2f50acd11a6029a82fa22c98d5fb2d30e5e47d39..3d80c3e9cf6003b2fe9bfe512c660a2961d81a32 100644 (file)
@@ -36,3 +36,13 @@ zImage.pseries
 zconf.h
 zlib.h
 zutil.h
+fdt.c
+fdt.h
+fdt_ro.c
+fdt_rw.c
+fdt_strerror.c
+fdt_sw.c
+fdt_wip.c
+libfdt.h
+libfdt_internal.h
+
index 26549fca2ed449e7dcf58a190db56c525d09d261..49ac36b16dd78d6b4e68ccfac530602d719ef20e 100644 (file)
@@ -70,8 +70,8 @@
                        devsel-speed = <0x00000001>;
                        min-grant = <0>;
                        max-latency = <0>;
-                       /* First 64k for I/O at 0x0 on PCI mapped to 0x0 on ISA. */
-                       ranges = <0x00000001 0 0x01000000 0 0x00000000 0x00010000>;
+                       /* First 4k for I/O at 0x0 on PCI mapped to 0x0 on ISA. */
+                       ranges = <0x00000001 0 0x01000000 0 0x00000000 0x00001000>;
                        interrupt-parent = <&i8259>;
                        #interrupt-cells = <2>;
                        #address-cells = <2>;
index 224b4f0704b84f98d7517239bf8a8402bddd5cd1..4f06dbc0d27e8e96a454175c969c26a28f7be037 100644 (file)
                bus-range = <0 0>;
                ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
                          0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
-                         0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+                         0x01000000 0x0 0x00000000 0xe0300000 0x0 0x00100000>;
                sleep = <&pmc 0x00010000>;
                clock-frequency = <66666666>;
                #interrupt-cells = <1>;
index 474ea2fa3f86b8f708f7a17071d6e22cd0e91cd2..aabf3437cadf6f38426c10cf672b3ca2e8ef5dc9 100644 (file)
                bus-range = <0 0>;
                ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
                          0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
-                         0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+                         0x01000000 0x0 0x00000000 0xe0300000 0x0 0x00100000>;
                sleep = <&pmc 0x00010000>;
                clock-frequency = <66666666>;
                #interrupt-cells = <1>;
index d4838af8d37954e1614346cd2dc3a4f2f7f9c155..9b1da864d89043c0887fa6e69ace6a6c25b28b81 100644 (file)
                bus-range = <0x0 0x0>;
                ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000
                          0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000
-                         0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
+                         0x01000000 0x0 0x00000000 0xe0300000 0x0 0x00100000>;
                sleep = <&pmc 0x00010000>;
                clock-frequency = <66666666>;
                #interrupt-cells = <1>;
index a8dcb018c4a591425c4d0b960542830313b41f40..9e4ce99e1613643f60430f001813f2da0977a6e1 100644 (file)
                        /* Filled in by U-Boot */
                        clock-frequency = <0>;
                        status = "disabled";
+                       sdhci,1-bit-only;
                };
 
                crypto@30000 {
                                reg = <0x6>;
                                device_type = "ethernet-phy";
                        };
+                       tbi-phy@11 {
+                               reg = <0x11>;
+                               device_type = "tbi-phy";
+                       };
                };
                mdio@3520 {
                        #address-cells = <1>;
index 01bfb56bbe802a96d2c4a965df1651483d5d8ae6..31605ee4afb69444d9aa5f8c523f9eba9c5f5879 100644 (file)
                                compatible = "gpio-leds";
                                green {
                                        gpios = <&GPIO1 0 0>;
-                                       default-state = "on";
+                                       default-state = "keep";
                                };
                                red {
                                        gpios = <&GPIO1 1 0>;
+                                       default-state = "keep";
                                };
                        };
 
index 3b77f092abe12d4ef3c234d0e62a1985ce498a74..787635f23d8fd0ca3772416c4240055754c3680f 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc2
-# Fri Jan 23 07:57:16 2009
+# Linux kernel version: 2.6.30
+# Tue Jun  9 23:35:36 2009
 #
 # CONFIG_PPC64 is not set
 
@@ -41,6 +41,7 @@ CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
@@ -53,10 +54,12 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 CONFIG_PPC_DCR_NATIVE=y
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_PPC_DCR=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -74,7 +77,17 @@ CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_GROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
@@ -82,27 +95,29 @@ CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_USER_SCHED=y
 # CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_HOTPLUG is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
@@ -110,10 +125,13 @@ CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
 CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 # CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
@@ -121,6 +139,7 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+# CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -133,7 +152,6 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -149,11 +167,6 @@ CONFIG_DEFAULT_AS=y
 # CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
-CONFIG_CLASSIC_RCU=y
-# CONFIG_TREE_RCU is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_FREEZER is not set
 
 #
@@ -173,10 +186,11 @@ CONFIG_WARP=y
 # CONFIG_ARCHES is not set
 # CONFIG_CANYONLANDS is not set
 # CONFIG_GLACIER is not set
+# CONFIG_REDWOOD is not set
 # CONFIG_YOSEMITE is not set
 # CONFIG_XILINX_VIRTEX440_GENERIC_BOARD is not set
 # CONFIG_PPC44x_SIMPLE is not set
-# CONFIG_PPC4xx_GPIO is not set
+CONFIG_PPC4xx_GPIO=y
 CONFIG_440EP=y
 CONFIG_IBM440EP_ERR42=y
 # CONFIG_IPIC is not set
@@ -235,9 +249,13 @@ CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
 CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_STDBINUTILS=y
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
 CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_PROC_DEVICETREE=y
 CONFIG_CMDLINE_BOOL=y
@@ -256,6 +274,7 @@ CONFIG_PPC_PCI_CHOICE=y
 # CONFIG_PCI_DOMAINS is not set
 # CONFIG_PCI_SYSCALL is not set
 # CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
 # CONFIG_HAS_RAPIDIO is not set
 
 #
@@ -271,14 +290,12 @@ CONFIG_PAGE_OFFSET=0xc0000000
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0xc0000000
-CONFIG_CONSISTENT_START=0xff100000
 CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
 # Networking options
 #
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -353,6 +370,7 @@ CONFIG_VLAN_8021Q=y
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -365,7 +383,6 @@ CONFIG_VLAN_8021Q=y
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
 # CONFIG_WIRELESS is not set
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
@@ -378,8 +395,12 @@ CONFIG_VLAN_8021Q=y
 #
 # Generic Driver Options
 #
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_STANDALONE is not set
 CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
@@ -471,13 +492,21 @@ CONFIG_MTD_NAND_NDFC=y
 # LPDDR flash memory drivers
 #
 # CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
 
 #
 # UBI - Unsorted block images
 #
-# CONFIG_MTD_UBI is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
@@ -495,10 +524,17 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_XILINX_SYSACE is not set
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_MISC_DEVICES=y
-# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
 # CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -529,7 +565,7 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
 # CONFIG_SCSI_SCAN_ASYNC is not set
-CONFIG_SCSI_WAIT_SCAN=m
+# CONFIG_SCSI_WAIT_SCAN is not set
 
 #
 # SCSI Transports
@@ -541,10 +577,12 @@ CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_SRP_ATTRS is not set
 # CONFIG_SCSI_LOWLEVEL is not set
 # CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
 # CONFIG_ATA is not set
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -554,6 +592,8 @@ CONFIG_NETDEVICES=y
 # CONFIG_PHYLIB is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
 CONFIG_IBM_NEW_EMAC=y
 CONFIG_IBM_NEW_EMAC_RXB=128
 CONFIG_IBM_NEW_EMAC_TXB=64
@@ -577,7 +617,6 @@ CONFIG_IBM_NEW_EMAC_ZMII=y
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -646,6 +685,7 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_HVC_UDBG is not set
 # CONFIG_IPMI_HANDLER is not set
 CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
 # CONFIG_NVRAM is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
@@ -663,6 +703,7 @@ CONFIG_I2C_HELPER_AUTO=y
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_GPIO is not set
 CONFIG_I2C_IBM_IIC=y
 # CONFIG_I2C_MPC is not set
 # CONFIG_I2C_OCORES is not set
@@ -685,12 +726,9 @@ CONFIG_I2C_IBM_IIC=y
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-CONFIG_EEPROM_AT24=y
-CONFIG_EEPROM_LEGACY=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
 # CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
@@ -699,7 +737,30 @@ CONFIG_EEPROM_LEGACY=y
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
-# CONFIG_GPIOLIB is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_XILINX is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
 # CONFIG_W1 is not set
 # CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
@@ -721,6 +782,7 @@ CONFIG_SENSORS_AD7414=y
 # CONFIG_SENSORS_F71805F is not set
 # CONFIG_SENSORS_F71882FG is not set
 # CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_GL520SM is not set
 # CONFIG_SENSORS_IT87 is not set
@@ -735,11 +797,15 @@ CONFIG_SENSORS_AD7414=y
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_LM92 is not set
 # CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
 # CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_MAX6650 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
 # CONFIG_SENSORS_DME1737 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47M192 is not set
@@ -785,6 +851,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
 # CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
@@ -870,11 +937,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
 #
 
 #
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
@@ -915,7 +982,6 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
 # CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_FTDI_ELAN is not set
 # CONFIG_USB_APPLEDISPLAY is not set
@@ -929,6 +995,8 @@ CONFIG_USB_STORAGE=y
 #
 # OTG and related infrastructure
 #
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
 CONFIG_MMC=y
 # CONFIG_MMC_DEBUG is not set
 # CONFIG_MMC_UNSAFE_RESUME is not set
@@ -946,6 +1014,7 @@ CONFIG_MMC_BLOCK_BOUNCE=y
 #
 # CONFIG_MMC_SDHCI is not set
 # CONFIG_MMC_WBSD is not set
+CONFIG_MMC_PIKASD=y
 # CONFIG_MEMSTICK is not set
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
@@ -953,16 +1022,31 @@ CONFIG_LEDS_CLASS=y
 #
 # LED drivers
 #
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_GPIO_PLATFORM is not set
+CONFIG_LEDS_GPIO_OF=y
+# CONFIG_LEDS_LP5521 is not set
 # CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
 
 #
 # LED Triggers
 #
-# CONFIG_LEDS_TRIGGERS is not set
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_EDAC is not set
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
 # CONFIG_STAGING is not set
 
@@ -973,6 +1057,7 @@ CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
 # CONFIG_EXT4_FS is not set
 CONFIG_JBD=y
@@ -992,6 +1077,11 @@ CONFIG_INOTIFY_USER=y
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
 #
 # CD-ROM/DVD Filesystems
 #
@@ -1039,6 +1129,12 @@ CONFIG_JFFS2_ZLIB=y
 # CONFIG_JFFS2_LZO is not set
 CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
 CONFIG_CRAMFS=y
 # CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
@@ -1049,6 +1145,7 @@ CONFIG_CRAMFS=y
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -1060,7 +1157,6 @@ CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -1115,6 +1211,7 @@ CONFIG_NLS_ISO8859_15=y
 # CONFIG_NLS_KOI8_U is not set
 CONFIG_NLS_UTF8=y
 # CONFIG_DLM is not set
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
@@ -1122,7 +1219,7 @@ CONFIG_NLS_UTF8=y
 CONFIG_BITREVERSE=y
 CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=y
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=y
 CONFIG_CRC_T10DIF=y
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
@@ -1130,16 +1227,19 @@ CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_DECOMPRESS_GZIP=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
 
 #
 # Kernel hacking
 #
-# CONFIG_PRINTK_TIME is not set
+CONFIG_PRINTK_TIME=y
 CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
@@ -1152,11 +1252,15 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
 CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_DEBUG_SLAB is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
@@ -1180,9 +1284,12 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
 
 #
 # Tracers
@@ -1190,24 +1297,27 @@ CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 # CONFIG_FUNCTION_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
 # CONFIG_BOOT_TRACER is not set
 # CONFIG_TRACE_BRANCH_PROFILING is not set
 # CONFIG_STACK_TRACER is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
 # CONFIG_XMON is not set
 CONFIG_IRQSTACKS=y
 # CONFIG_VIRQ_DEBUG is not set
-CONFIG_BDI_SWITCH=y
+# CONFIG_BDI_SWITCH is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
 #
@@ -1223,6 +1333,8 @@ CONFIG_CRYPTO=y
 # Crypto core or helper
 #
 # CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
 # CONFIG_CRYPTO_MANAGER is not set
 # CONFIG_CRYPTO_MANAGER2 is not set
 # CONFIG_CRYPTO_GF128MUL is not set
@@ -1294,13 +1406,15 @@ CONFIG_CRYPTO=y
 #
 # Compression
 #
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
 
 #
 # Random Number Generation
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_PPC4XX is not set
 # CONFIG_PPC_CLOCK is not set
 # CONFIG_VIRTUALIZATION is not set
index 278939713775356ddd40ec1aca9810dd49199594..a2df0635b6de09c0a899c74cb28078895dec6c69 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:05 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:02 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 CONFIG_FSL_EMB_PERFMON=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,6 +56,7 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 CONFIG_REDBOOT=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
@@ -60,6 +64,7 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -108,7 +113,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -121,9 +125,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -136,6 +147,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -148,7 +163,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -190,6 +205,7 @@ CONFIG_PPC_83xx=y
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 CONFIG_ASP834x=y
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC834x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -235,6 +251,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -255,9 +272,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -366,6 +383,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -383,7 +401,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -490,6 +512,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -525,7 +548,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -545,14 +570,17 @@ CONFIG_HAVE_IDE=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -599,6 +627,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -618,8 +647,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -786,13 +817,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -847,6 +882,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -900,24 +936,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -960,6 +981,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1069,6 +1091,7 @@ CONFIG_RTC_DRV_DS1374=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1096,6 +1119,10 @@ CONFIG_RTC_DRV_DS1374=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1115,10 +1142,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1192,6 +1221,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1287,6 +1317,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1312,22 +1343,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index bf0853f29f3139c81d1eb4f9a587b2ec62874300..93ebd443a18fdf1077591834ee3110a5e7452d88 100644 (file)
@@ -1,25 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.28
-# Fri Apr  3 10:34:33 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:03 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
+CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,21 +33,22 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_GENERIC_NVRAM=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_PPC_OF=y
 CONFIG_OF=y
@@ -52,11 +56,14 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -71,19 +78,30 @@ CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SYSVIPC=y
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
 # CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
 # CONFIG_SYSFS_DEPRECATED_V2 is not set
 # CONFIG_RELAY is not set
 # CONFIG_NAMESPACES is not set
 # CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
@@ -93,17 +111,23 @@ CONFIG_KALLSYMS_ALL=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
 CONFIG_EPOLL=y
 CONFIG_SIGNALFD=y
 CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
 # CONFIG_SLOB is not set
@@ -116,10 +140,15 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 # CONFIG_MODULE_FORCE_LOAD is not set
@@ -127,11 +156,8 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -147,14 +173,11 @@ CONFIG_IOSCHED_NOOP=y
 # CONFIG_DEFAULT_CFQ is not set
 CONFIG_DEFAULT_NOOP=y
 CONFIG_DEFAULT_IOSCHED="noop"
-CONFIG_CLASSIC_RCU=y
 # CONFIG_FREEZER is not set
 
 #
 # Platform support
 #
-CONFIG_PPC_MULTIPLATFORM=y
-CONFIG_CLASSIC32=y
 # CONFIG_PPC_CHRP is not set
 # CONFIG_MPC5121_ADS is not set
 # CONFIG_MPC5121_GENERIC is not set
@@ -179,6 +202,8 @@ CONFIG_PPC_83xx=y
 CONFIG_KMETER1=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
+# CONFIG_AMIGAONE is not set
+CONFIG_PPC_OF_BOOT_TRAMPOLINE=y
 CONFIG_IPIC=y
 # CONFIG_MPIC is not set
 # CONFIG_MPIC_WEIRD is not set
@@ -194,6 +219,8 @@ CONFIG_IPIC=y
 CONFIG_QUICC_ENGINE=y
 # CONFIG_QE_GPIO is not set
 # CONFIG_FSL_ULI1575 is not set
+# CONFIG_SIMPLE_GPIO is not set
+# CONFIG_MCU_MPC8349EMITX is not set
 
 #
 # Kernel options
@@ -212,16 +239,17 @@ CONFIG_SCHED_HRTICK=y
 # CONFIG_PREEMPT_NONE is not set
 # CONFIG_PREEMPT_VOLUNTARY is not set
 CONFIG_PREEMPT=y
-# CONFIG_PREEMPT_RCU is not set
 CONFIG_BINFMT_ELF=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
 # CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
@@ -233,12 +261,17 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_MIGRATION=y
-# CONFIG_RESOURCES_64BIT is not set
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_PPC_4K_PAGES=y
+# CONFIG_PPC_16K_PAGES is not set
+# CONFIG_PPC_64K_PAGES is not set
+# CONFIG_PPC_256K_PAGES is not set
 CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
@@ -331,7 +364,10 @@ CONFIG_LLC=m
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
 
 #
 # Network testing
@@ -342,8 +378,8 @@ CONFIG_LLC=m
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
 # CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
 
@@ -362,6 +398,7 @@ CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
 # CONFIG_MTD_REDBOOT_PARTS is not set
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_OF_PARTS=y
@@ -430,6 +467,11 @@ CONFIG_MTD_PHRAM=y
 # CONFIG_MTD_NAND is not set
 # CONFIG_MTD_ONENAND is not set
 
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
 #
 # UBI - Unsorted block images
 #
@@ -445,7 +487,6 @@ CONFIG_MTD_UBI_DEBUG=y
 # CONFIG_MTD_UBI_DEBUG_MSG is not set
 # CONFIG_MTD_UBI_DEBUG_PARANOID is not set
 # CONFIG_MTD_UBI_DEBUG_DISABLE_BGT is not set
-# CONFIG_MTD_UBI_DEBUG_USERSPACE_IO is not set
 # CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS is not set
 # CONFIG_MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES is not set
 # CONFIG_MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES is not set
@@ -459,6 +500,7 @@ CONFIG_MTD_UBI_DEBUG=y
 # CONFIG_MTD_UBI_DEBUG_MSG_IO is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -505,10 +547,15 @@ CONFIG_MARVELL_PHY=y
 # CONFIG_BROADCOM_PHY is not set
 # CONFIG_ICPLUS_PHY is not set
 # CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
 # CONFIG_FIXED_PHY is not set
 # CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
+# CONFIG_ETHOC is not set
+# CONFIG_DNET is not set
 # CONFIG_IBM_NEW_EMAC_ZMII is not set
 # CONFIG_IBM_NEW_EMAC_RGMII is not set
 # CONFIG_IBM_NEW_EMAC_TAH is not set
@@ -517,11 +564,12 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
+CONFIG_FSL_PQ_MDIO=y
 # CONFIG_GIANFAR is not set
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
-# CONFIG_UGETH_FILTERING is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
 # CONFIG_MV643XX_ETH is not set
 # CONFIG_NETDEV_10000 is not set
@@ -531,7 +579,10 @@ CONFIG_UCC_GETH=y
 #
 # CONFIG_WLAN_PRE80211 is not set
 # CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
 CONFIG_WAN=y
 CONFIG_HDLC=y
 # CONFIG_HDLC_RAW is not set
@@ -543,8 +594,6 @@ CONFIG_HDLC=y
 #
 # X.25/LAPB support is disabled
 #
-CONFIG_HDLC_KM=y
-CONFIG_FS_UCC_HDLC=y
 # CONFIG_DLCI is not set
 CONFIG_PPP=y
 CONFIG_PPP_MULTILINK=y
@@ -600,16 +649,18 @@ CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_OF_PLATFORM is not set
 # CONFIG_SERIAL_QE is not set
 CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_HVC_UDBG is not set
 # CONFIG_IPMI_HANDLER is not set
 CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
 # CONFIG_NVRAM is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
-CONFIG_BOOTCOUNT=y
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_CHARDEV=y
@@ -642,20 +693,20 @@ CONFIG_I2C_MPC=y
 # Miscellaneous I2C Chip support
 #
 # CONFIG_DS1682 is not set
-# CONFIG_AT24 is not set
-# CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_MCU_MPC8349EMITX is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -677,27 +728,15 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_CORE is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_PMIC_DA903X is not set
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -720,11 +759,16 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_EDAC is not set
 # CONFIG_RTC_CLASS is not set
 # CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
 CONFIG_UIO=y
 # CONFIG_UIO_PDRV is not set
 # CONFIG_UIO_PDRV_GENIRQ is not set
 # CONFIG_UIO_SMX is not set
 # CONFIG_UIO_SERCOS3 is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -736,9 +780,12 @@ CONFIG_UIO=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -747,6 +794,11 @@ CONFIG_INOTIFY_USER=y
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_FUSE_FS is not set
 
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
 #
 # CD-ROM/DVD Filesystems
 #
@@ -772,10 +824,7 @@ CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
@@ -796,6 +845,7 @@ CONFIG_JFFS2_RTIME=y
 # CONFIG_JFFS2_RUBIN is not set
 # CONFIG_UBIFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_OMFS_FS is not set
@@ -804,6 +854,7 @@ CONFIG_JFFS2_RTIME=y
 # CONFIG_ROMFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
@@ -815,7 +866,6 @@ CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -845,11 +895,13 @@ CONFIG_PARTITION_ADVANCED=y
 # CONFIG_DLM is not set
 CONFIG_UCC_FAST=y
 CONFIG_UCC=y
+# CONFIG_BINARY_PRINTF is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
 # CONFIG_CRC_CCITT is not set
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_T10DIF is not set
@@ -859,11 +911,12 @@ CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -883,13 +936,18 @@ CONFIG_DEBUG_FS=y
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_HAVE_FUNCTION_TRACER=y
-
-#
-# Tracers
-#
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
+CONFIG_PRINT_STACK_DEPTH=64
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_IRQSTACKS is not set
 # CONFIG_VIRQ_DEBUG is not set
 # CONFIG_BOOTX_TEXT is not set
index c5c0fe71a438c32c2a74f92ca3aaa3c58868087a..ff33a7db2eab76340fe18f71d1b35f5969cb65a3 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:06 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:04 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@ CONFIG_MPC831x_RDB=y
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC831x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -234,6 +250,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -254,9 +271,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -366,6 +383,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -383,7 +401,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -503,6 +525,7 @@ CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -539,7 +562,9 @@ CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -562,10 +587,6 @@ CONFIG_SCSI_PROC_FS=y
 # CONFIG_BLK_DEV_SR is not set
 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 is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -583,6 +604,7 @@ CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -591,6 +613,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -610,7 +633,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -643,14 +665,17 @@ CONFIG_MD_RAID1=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -714,6 +739,8 @@ CONFIG_E100=y
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -735,8 +762,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -924,7 +953,6 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -938,13 +966,18 @@ CONFIG_SPI_MASTER=y
 # SPI Master Controller Drivers
 #
 CONFIG_SPI_BITBANG=y
-CONFIG_SPI_MPC83xx=y
+# CONFIG_SPI_MPC8xxx is not set
 
 #
 # SPI Protocol Masters
 #
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -1002,6 +1035,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1056,24 +1090,10 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1135,6 +1155,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1144,9 +1165,9 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1235,8 +1256,9 @@ CONFIG_USB_GADGET_SELECTED=y
 # CONFIG_USB_GADGET_OMAP is not set
 # CONFIG_USB_GADGET_PXA25X is not set
 # CONFIG_USB_GADGET_PXA27X is not set
-# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
 # CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
 # CONFIG_USB_GADGET_M66592 is not set
 # CONFIG_USB_GADGET_AMD5536UDC is not set
 # CONFIG_USB_GADGET_FSL_QE is not set
@@ -1244,9 +1266,11 @@ CONFIG_USB_GADGET_SELECTED=y
 CONFIG_USB_GADGET_NET2280=y
 CONFIG_USB_NET2280=y
 # CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
 CONFIG_USB_GADGET_DUALSPEED=y
 # CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
 CONFIG_USB_ETH=y
 CONFIG_USB_ETH_RNDIS=y
 # CONFIG_USB_GADGETFS is not set
@@ -1298,6 +1322,7 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1332,6 +1357,10 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1351,10 +1380,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1428,6 +1459,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1464,7 +1496,46 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 # CONFIG_SYSV68_PARTITION is not set
-# CONFIG_NLS is not set
+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_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
 # CONFIG_DLM is not set
 # CONFIG_BINARY_PRINTF is not set
 
@@ -1488,6 +1559,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1518,6 +1590,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1529,7 +1604,6 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1543,16 +1617,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1560,6 +1633,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index af4952feba3668440c7ef478d7ce6084525344b0..76237d46670284a16de39929a82bc79b0792ff23 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:06 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:05 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@ CONFIG_MPC831x_RDB=y
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC831x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -234,6 +250,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -254,9 +271,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -366,6 +383,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -383,7 +401,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -503,6 +525,7 @@ CONFIG_MTD_NAND_IDS=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -539,7 +562,9 @@ CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -562,10 +587,6 @@ CONFIG_SCSI_PROC_FS=y
 # CONFIG_BLK_DEV_SR is not set
 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 is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -583,6 +604,7 @@ CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -591,6 +613,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -610,7 +633,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -704,14 +726,17 @@ CONFIG_MD_RAID1=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -775,6 +800,8 @@ CONFIG_E100=y
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -796,8 +823,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -985,7 +1014,6 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -999,13 +1027,18 @@ CONFIG_SPI_MASTER=y
 # SPI Master Controller Drivers
 #
 CONFIG_SPI_BITBANG=y
-CONFIG_SPI_MPC83xx=y
+# CONFIG_SPI_MPC8xxx is not set
 
 #
 # SPI Protocol Masters
 #
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -1063,6 +1096,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1117,24 +1151,10 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1196,6 +1216,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1205,9 +1226,9 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1296,8 +1317,9 @@ CONFIG_USB_GADGET_SELECTED=y
 # CONFIG_USB_GADGET_OMAP is not set
 # CONFIG_USB_GADGET_PXA25X is not set
 # CONFIG_USB_GADGET_PXA27X is not set
-# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
 # CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
 # CONFIG_USB_GADGET_M66592 is not set
 # CONFIG_USB_GADGET_AMD5536UDC is not set
 # CONFIG_USB_GADGET_FSL_QE is not set
@@ -1305,9 +1327,11 @@ CONFIG_USB_GADGET_SELECTED=y
 CONFIG_USB_GADGET_NET2280=y
 CONFIG_USB_NET2280=y
 # CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
 CONFIG_USB_GADGET_DUALSPEED=y
 # CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
 CONFIG_USB_ETH=y
 CONFIG_USB_ETH_RNDIS=y
 # CONFIG_USB_GADGETFS is not set
@@ -1359,6 +1383,7 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1393,6 +1418,10 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1412,10 +1441,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1489,6 +1520,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1525,7 +1557,46 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 # CONFIG_SYSV68_PARTITION is not set
-# CONFIG_NLS is not set
+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_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
 # CONFIG_DLM is not set
 # CONFIG_BINARY_PRINTF is not set
 
@@ -1549,6 +1620,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1579,6 +1651,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1590,7 +1665,6 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1604,16 +1678,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1621,6 +1694,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index 8c8f660b4fc7206617051a39137c3797c4939feb..e0e36a113409473f2582ccd643e8cd9f61d896fa 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:07 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:06 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@ CONFIG_MPC832x_MDS=y
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC832x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -235,6 +251,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -255,9 +272,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -366,6 +383,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -383,7 +401,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -404,6 +426,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -438,7 +461,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -461,10 +486,6 @@ CONFIG_SCSI_PROC_FS=y
 # 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
@@ -482,6 +503,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -490,6 +512,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -509,7 +532,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -532,14 +554,17 @@ CONFIG_SCSI_LOWLEVEL=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -586,6 +611,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -605,11 +631,13 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 # CONFIG_GIANFAR is not set
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -787,13 +815,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -848,6 +880,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -896,23 +929,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -996,6 +1015,7 @@ CONFIG_RTC_DRV_DS1374=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1023,6 +1043,10 @@ CONFIG_RTC_DRV_DS1374=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1042,10 +1066,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1108,6 +1134,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1165,6 +1192,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1190,22 +1218,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index 227dbba767952056bf8bc4e3c62c299497c205fd..4f27d45482238d224206494c34edba2ae41cb426 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:08 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:07 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@ CONFIG_MPC832x_RDB=y
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC832x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -235,6 +251,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -255,9 +272,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -366,6 +383,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -383,7 +401,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -405,6 +427,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -441,7 +464,9 @@ CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -464,10 +489,6 @@ CONFIG_BLK_DEV_SD=y
 # 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
@@ -485,6 +506,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -493,6 +515,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -512,7 +535,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -535,14 +557,17 @@ CONFIG_SCSI_LOWLEVEL=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -590,6 +615,8 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -609,11 +636,13 @@ CONFIG_E1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 # CONFIG_GIANFAR is not set
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -804,7 +833,6 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -817,13 +845,18 @@ CONFIG_SPI_MASTER=y
 # SPI Master Controller Drivers
 #
 CONFIG_SPI_BITBANG=y
-CONFIG_SPI_MPC83xx=y
+# CONFIG_SPI_MPC8xxx is not set
 
 #
 # SPI Protocol Masters
 #
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -881,6 +914,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -935,24 +969,10 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1014,6 +1034,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1023,9 +1044,9 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1127,6 +1148,8 @@ CONFIG_MMC_BLOCK_BOUNCE=y
 # CONFIG_MMC_WBSD is not set
 # CONFIG_MMC_TIFM_SD is not set
 CONFIG_MMC_SPI=y
+# CONFIG_MMC_CB710 is not set
+# CONFIG_MMC_VIA_SDMMC is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
 # CONFIG_ACCESSIBILITY is not set
@@ -1136,6 +1159,10 @@ CONFIG_MMC_SPI=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1155,10 +1182,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1224,6 +1253,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1325,6 +1355,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1350,22 +1381,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index 24ee7fcac87ebbf1cbfaf72c7907881fb80e5414..648dac0c9d8d1ed9dab138d299a77376c570db5d 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:09 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:07 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@ CONFIG_MPC834x_ITX=y
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC834x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -234,6 +250,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -254,9 +271,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -365,6 +382,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -382,7 +400,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -487,6 +509,7 @@ CONFIG_MTD_PHYSMAP=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -523,7 +546,9 @@ CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -594,10 +619,6 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_BLK_DEV_SR is not set
 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 is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -615,6 +636,7 @@ CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -623,6 +645,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -642,7 +665,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -737,14 +759,17 @@ CONFIG_MD_RAID1=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -791,8 +816,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -960,7 +987,6 @@ CONFIG_I2C_MPC=y
 CONFIG_SENSORS_PCF8574=y
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -973,13 +999,18 @@ CONFIG_SPI_MASTER=y
 # SPI Master Controller Drivers
 #
 CONFIG_SPI_BITBANG=y
-CONFIG_SPI_MPC83xx=y
+# CONFIG_SPI_MPC8xxx is not set
 
 #
 # SPI Protocol Masters
 #
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -1026,24 +1057,10 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1085,6 +1102,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1208,6 +1226,7 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1242,6 +1261,10 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1261,10 +1284,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1331,6 +1356,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1429,6 +1455,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1454,22 +1481,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index 7f39543205a9287a284c1cbef04c9e03a05b7d6a..bf6deb831dc3e1e90e4d618daac13d152ea216dd 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:10 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:08 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@ CONFIG_MPC834x_ITX=y
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC834x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -234,6 +250,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -254,9 +271,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -365,6 +382,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -382,7 +400,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -487,6 +509,7 @@ CONFIG_MTD_PHYSMAP=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -523,7 +546,9 @@ CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -546,10 +571,6 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_BLK_DEV_SR is not set
 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 is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -567,6 +588,7 @@ CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -575,6 +597,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -594,7 +617,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -617,14 +639,17 @@ CONFIG_SCSI_LOWLEVEL=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -671,8 +696,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -840,7 +867,6 @@ CONFIG_I2C_MPC=y
 CONFIG_SENSORS_PCF8574=y
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -853,13 +879,18 @@ CONFIG_SPI_MASTER=y
 # SPI Master Controller Drivers
 #
 CONFIG_SPI_BITBANG=y
-CONFIG_SPI_MPC83xx=y
+# CONFIG_SPI_MPC8xxx is not set
 
 #
 # SPI Protocol Masters
 #
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -906,24 +937,10 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -965,6 +982,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1087,6 +1105,7 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1121,6 +1140,10 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1140,10 +1163,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1210,6 +1235,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1308,6 +1334,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1333,22 +1360,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index 1cd1fcac22c8c61eb8f1020143c339439bf3f5e5..3236c47712c2cab3279b98c0e9b53759c742b44e 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:11 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:09 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@ CONFIG_MPC834x_MDS=y
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC834x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -234,6 +250,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -254,9 +271,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -365,6 +382,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -382,7 +400,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -403,6 +425,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -437,7 +460,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -457,14 +482,17 @@ CONFIG_HAVE_IDE=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -527,6 +555,7 @@ CONFIG_E100=y
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -548,8 +577,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -724,13 +755,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -785,6 +820,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -833,23 +869,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -933,6 +955,7 @@ CONFIG_RTC_DRV_DS1374=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -960,6 +983,10 @@ CONFIG_RTC_DRV_DS1374=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -979,10 +1006,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1045,6 +1074,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1100,6 +1130,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1125,22 +1156,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index ce5177393a0d174d4f3b536d1efcbbdb4559a2c4..8c5299d74813b523115001bbbe0a4d2dbb89fa35 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:12 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:10 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,9 +124,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -135,6 +146,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -147,7 +162,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -189,6 +204,7 @@ CONFIG_MPC836x_MDS=y
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_AMIGAONE is not set
@@ -233,6 +249,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -253,9 +270,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -364,6 +381,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -381,7 +399,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -485,6 +507,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -519,7 +542,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -542,10 +567,6 @@ CONFIG_SCSI_PROC_FS=y
 # 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
@@ -563,6 +584,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -571,6 +593,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -590,7 +613,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -613,14 +635,17 @@ CONFIG_SCSI_LOWLEVEL=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -667,6 +692,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -686,11 +712,13 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 # CONFIG_GIANFAR is not set
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -868,13 +896,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -929,6 +961,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -977,23 +1010,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1077,6 +1096,7 @@ CONFIG_RTC_DRV_DS1374=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1104,6 +1124,10 @@ CONFIG_RTC_DRV_DS1374=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1123,10 +1147,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1190,6 +1216,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1247,6 +1274,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1272,22 +1300,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index 7f1d1383a249c3ddf39bd4222dfc83661cfd5a80..ff31667a890bd36ff8d18e3d34e86284a16e8e77 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:13 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:12 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -54,12 +57,14 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -108,7 +113,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -121,9 +125,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -136,6 +147,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -148,7 +163,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -190,6 +205,7 @@ CONFIG_MPC836x_RDK=y
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
 # CONFIG_AMIGAONE is not set
@@ -233,6 +249,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -253,9 +270,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -366,6 +383,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -383,7 +401,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -498,6 +520,7 @@ CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -533,7 +556,9 @@ CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -553,14 +578,17 @@ CONFIG_HAVE_IDE=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -607,11 +635,13 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 # CONFIG_GIANFAR is not set
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -777,7 +807,6 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -791,13 +820,18 @@ CONFIG_SPI_MASTER=y
 #
 CONFIG_SPI_BITBANG=y
 # CONFIG_SPI_GPIO is not set
-CONFIG_SPI_MPC83xx=y
+# CONFIG_SPI_MPC8xxx is not set
 
 #
 # SPI Protocol Masters
 #
 CONFIG_SPI_SPIDEV=y
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -865,23 +899,10 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -990,6 +1011,10 @@ CONFIG_HID=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1009,10 +1034,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1086,6 +1113,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1145,6 +1173,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1170,22 +1199,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index bf636fd560ad7c925a79503eb1a58de09a6f8f3a..e285ec0fe9582e349f379888fa721ce6d6e684b2 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:12 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:11 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -108,7 +113,6 @@ CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -121,8 +125,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -136,6 +147,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -148,7 +163,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -190,6 +205,7 @@ CONFIG_MPC837x_MDS=y
 # CONFIG_MPC837x_RDB is not set
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC837x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -234,6 +250,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -254,9 +271,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -365,6 +382,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -382,7 +400,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -403,6 +425,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -437,7 +460,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -460,10 +485,6 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_BLK_DEV_SR is not set
 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 is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -481,6 +502,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -489,6 +511,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -508,7 +531,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -592,14 +614,17 @@ CONFIG_ATA_SFF=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -646,6 +671,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -665,8 +691,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -844,13 +872,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -905,6 +937,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -953,23 +986,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1026,6 +1045,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1045,10 +1068,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1111,6 +1136,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1170,6 +1196,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1193,22 +1220,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index fe6454eacbdb4286eb818dee3c08fe4e9cb2715c..1ab3e4cd30182a02aeb9d5f02aa65669ae90a6a9 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:14 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:13 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -108,7 +113,6 @@ CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -121,8 +125,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -136,6 +147,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -148,7 +163,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -190,6 +205,7 @@ CONFIG_PPC_83xx=y
 CONFIG_MPC837x_RDB=y
 # CONFIG_SBC834x is not set
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC837x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -234,6 +250,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -254,9 +271,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -360,6 +377,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -377,7 +395,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -398,6 +420,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -433,7 +456,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -456,10 +481,6 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_BLK_DEV_SR is not set
 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 is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -476,6 +497,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -484,6 +506,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -503,7 +526,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -598,14 +620,17 @@ CONFIG_MD_RAID6_PQ=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -652,6 +677,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -671,8 +697,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -842,13 +870,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -903,6 +935,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -956,24 +989,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1011,7 +1029,7 @@ CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1028,10 +1046,11 @@ CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1057,6 +1076,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1141,6 +1161,10 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1160,10 +1184,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1226,6 +1252,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1262,7 +1289,46 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 # CONFIG_SYSV68_PARTITION is not set
-# CONFIG_NLS is not set
+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_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
 # CONFIG_DLM is not set
 # CONFIG_BINARY_PRINTF is not set
 
@@ -1285,6 +1351,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1308,22 +1375,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index fe08f672cb27f2012c44ea3633e00cb0debda90c..a592b5efdc4d9a58036a277c360a671bfe7a4c6a 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:15 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:13 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,12 +56,14 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -107,7 +112,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -120,8 +124,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -134,6 +145,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -146,7 +161,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -188,6 +203,7 @@ CONFIG_PPC_83xx=y
 # CONFIG_MPC837x_RDB is not set
 CONFIG_SBC834x=y
 # CONFIG_ASP834x is not set
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC834x=y
 # CONFIG_PPC_86xx is not set
 # CONFIG_EMBEDDED6xx is not set
@@ -232,6 +248,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -252,9 +269,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -363,6 +380,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -380,7 +398,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -401,6 +423,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -435,7 +458,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -455,14 +480,17 @@ CONFIG_HAVE_IDE=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -509,6 +537,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -528,8 +557,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -688,13 +719,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -749,6 +784,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -797,23 +833,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -851,6 +873,10 @@ CONFIG_HID=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -862,10 +888,12 @@ CONFIG_HID=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -928,6 +956,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -971,6 +1000,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -994,22 +1024,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index 09146ddaa3caafd8b471d29c1e225fc394a040b7..ff04e1028f5e2d4b26dacba4862dd3bcd451b54c 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:16 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:14 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -57,11 +58,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -108,7 +111,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -121,8 +123,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -136,6 +145,11 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -143,7 +157,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -176,6 +190,7 @@ CONFIG_MPC85xx=y
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 CONFIG_KSI8560=y
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -224,6 +239,7 @@ CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -242,9 +258,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -346,6 +362,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -363,7 +380,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -466,6 +487,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -520,7 +542,6 @@ CONFIG_IDE_PROC_FS=y
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -560,6 +581,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
 CONFIG_FS_ENET_HAS_FCC=y
@@ -567,6 +589,7 @@ CONFIG_FS_ENET_MDIO_FCC=y
 CONFIG_NETDEV_1000=y
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 CONFIG_NETDEV_10000=y
 
 #
@@ -654,6 +677,11 @@ CONFIG_GEN_RTC=y
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -710,22 +738,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -777,6 +790,10 @@ CONFIG_USB_SUPPORT=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -797,10 +814,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -916,6 +935,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -946,6 +966,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -958,7 +981,6 @@ CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -972,16 +994,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -990,9 +1011,13 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
index 7b43be7586b6af55665e5157ef1dac3e6c726d61..fb10cc83702e9681b457fb9cf45d974c89e9df71 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:17 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:15 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -56,11 +57,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -111,7 +114,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -124,8 +126,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -138,6 +147,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -145,7 +158,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -178,6 +191,7 @@ CONFIG_MPC8540_ADS=y
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -226,6 +240,7 @@ CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -244,9 +259,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -348,6 +363,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -365,7 +381,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -387,6 +407,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -423,7 +444,6 @@ CONFIG_HAVE_IDE=y
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -462,9 +482,11 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 CONFIG_NETDEV_10000=y
 
 #
@@ -555,6 +577,11 @@ CONFIG_GEN_RTC=y
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -590,22 +617,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -657,6 +669,10 @@ CONFIG_USB_SUPPORT=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -676,10 +692,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -794,6 +812,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -824,6 +843,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -835,7 +857,6 @@ CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -849,16 +870,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -866,6 +886,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index 62adb71a5d4f72586bca8df78175cf17b81e02c6..5c8ce6978825c49f39f956af7fd30c0b3f669f1d 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:17 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:16 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -57,11 +58,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -112,7 +115,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -125,9 +127,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -141,6 +150,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -148,7 +161,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -181,6 +194,7 @@ CONFIG_MPC8560_ADS=y
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -229,6 +243,7 @@ CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -247,9 +262,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -360,6 +375,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -377,7 +393,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -400,6 +420,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -431,6 +452,7 @@ CONFIG_MISC_DEVICES=y
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -450,14 +472,17 @@ CONFIG_HAVE_IDE=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -504,6 +529,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
@@ -527,8 +553,10 @@ CONFIG_E1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -646,6 +674,11 @@ CONFIG_GEN_RTC=y
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -707,22 +740,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -779,6 +797,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -798,10 +820,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -916,6 +940,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -946,6 +971,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -957,7 +985,6 @@ CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -971,16 +998,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -988,6 +1014,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index 41209e3a654527d62b2ca60b5b9205904863f570..158e63e8607f96c72b4a540b7ba9c87d0ee6c48a 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:18 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:17 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -56,11 +57,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -111,7 +114,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -124,9 +126,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -139,6 +148,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -146,7 +159,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -179,6 +192,7 @@ CONFIG_MPC85xx_CDS=y
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -227,6 +241,7 @@ CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -245,9 +260,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -358,6 +373,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -375,7 +391,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -397,6 +417,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -428,6 +449,7 @@ CONFIG_MISC_DEVICES=y
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -502,14 +524,17 @@ CONFIG_BLK_DEV_IDEDMA=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -556,6 +581,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -575,8 +601,10 @@ CONFIG_E1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -698,6 +726,11 @@ CONFIG_GEN_RTC=y
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -737,22 +770,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -809,6 +827,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -828,10 +850,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -946,6 +970,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -976,6 +1001,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -987,7 +1015,6 @@ CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1001,16 +1028,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1018,6 +1044,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index 6c36c9c7abfd891969f36a02ad22bf02f0664868..2726fca1d6948fba74973f2d825b417ef07e5b01 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:19 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:18 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -56,11 +57,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -110,7 +113,6 @@ CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -123,8 +125,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -137,6 +146,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -144,7 +157,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -177,6 +190,7 @@ CONFIG_MPC85xx=y
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -224,6 +238,7 @@ CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -242,9 +257,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -354,6 +369,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -371,7 +387,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -391,6 +411,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -422,6 +443,7 @@ CONFIG_MISC_DEVICES=y
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -441,14 +463,17 @@ CONFIG_HAVE_IDE=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -495,6 +520,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -514,8 +540,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -637,6 +665,11 @@ CONFIG_GEN_RTC=y
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -676,22 +709,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -721,6 +739,10 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -732,10 +754,12 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -838,6 +862,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -861,22 +886,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
index 4aaf1a6bdc7df872741eb93f2349370efb34dddf..b0c469823b02fe520dae707a5d34df0e40be034e 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:20 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:19 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -56,11 +57,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -111,7 +114,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -124,7 +126,14 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -137,6 +146,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -144,7 +157,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -177,6 +190,7 @@ CONFIG_MPC85xx=y
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -224,6 +238,7 @@ CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 # CONFIG_MATH_EMULATION is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -242,9 +257,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -346,6 +361,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -363,7 +379,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -385,6 +405,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -421,7 +442,6 @@ CONFIG_HAVE_IDE=y
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -460,9 +480,11 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 CONFIG_NETDEV_10000=y
 
 #
@@ -551,6 +573,11 @@ CONFIG_LEGACY_PTY_COUNT=256
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -586,22 +613,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -690,6 +702,10 @@ CONFIG_RTC_DRV_M48T59=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -701,10 +717,12 @@ CONFIG_RTC_DRV_M48T59=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -819,6 +837,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -848,6 +867,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -859,7 +881,6 @@ CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -873,16 +894,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -890,6 +910,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index 79984589db6923cf67acd7263a8468fd5675e5a9..04c85dada845fc90d5f0d3876cb04b01ed9691b9 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:21 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:19 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -56,11 +57,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -109,7 +112,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -122,9 +124,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -137,6 +146,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -149,7 +162,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -182,6 +195,7 @@ CONFIG_MPC85xx=y
 # CONFIG_MPC85xx_DS is not set
 CONFIG_SOCRATES=y
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -229,6 +243,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -247,9 +262,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -357,6 +372,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -373,6 +389,7 @@ CONFIG_CAN_BCM=y
 # CAN Device Drivers
 #
 # CONFIG_CAN_VCAN is not set
+# CONFIG_CAN_DEV is not set
 # CONFIG_CAN_DEBUG_DEVICES is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -382,7 +399,11 @@ CONFIG_WIRELESS=y
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -499,6 +520,7 @@ CONFIG_MTD_NAND_SOCRATES=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
 CONFIG_OF_SPI=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -535,7 +557,9 @@ CONFIG_MISC_DEVICES=y
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_AT25 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -558,10 +582,6 @@ CONFIG_BLK_DEV_SD=y
 # 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
@@ -588,14 +608,17 @@ CONFIG_SCSI_WAIT_SCAN=m
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -643,6 +666,8 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -662,8 +687,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -733,6 +760,7 @@ CONFIG_INPUT_TOUCHSCREEN=y
 # CONFIG_TOUCHSCREEN_AD7879_I2C is not set
 # CONFIG_TOUCHSCREEN_AD7879_SPI is not set
 # CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
@@ -746,6 +774,7 @@ CONFIG_INPUT_TOUCHSCREEN=y
 # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
 # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
 # CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -862,7 +891,6 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
@@ -875,12 +903,18 @@ CONFIG_SPI_MASTER=y
 # SPI Master Controller Drivers
 #
 # CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_MPC8xxx is not set
 
 #
 # SPI Protocol Masters
 #
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -938,6 +972,7 @@ CONFIG_SENSORS_LM75=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -973,24 +1008,10 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1110,7 +1131,7 @@ CONFIG_USB_HID=y
 # CONFIG_HID_CHERRY is not set
 # CONFIG_HID_CHICONY is not set
 # CONFIG_HID_CYPRESS is not set
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 # CONFIG_HID_EZKEY is not set
 # CONFIG_HID_KYE is not set
 # CONFIG_HID_GYRATION is not set
@@ -1124,10 +1145,11 @@ CONFIG_USB_HID=y
 # CONFIG_HID_SAMSUNG is not set
 # CONFIG_HID_SONY is not set
 # CONFIG_HID_SUNPLUS is not set
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-# CONFIG_THRUSTMASTER_FF is not set
-# CONFIG_ZEROPLUS_FF is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1153,6 +1175,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1162,9 +1185,9 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1284,6 +1307,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1318,6 +1342,10 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1337,10 +1365,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1449,7 +1479,46 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 # CONFIG_SYSV68_PARTITION is not set
-# CONFIG_NLS is not set
+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_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
 # CONFIG_DLM is not set
 # CONFIG_BINARY_PRINTF is not set
 
@@ -1473,6 +1542,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1498,22 +1568,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
index bd1bfcddbd0c8b1ca7d53dbf62c72b650580bfe1..e7e81d6769fe797425d98897965c5d2ae830503a 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:22 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:20 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -57,11 +58,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -112,7 +115,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -125,9 +127,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -142,6 +151,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -153,7 +166,7 @@ CONFIG_MODULES=y
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -186,6 +199,7 @@ CONFIG_MPC85xx=y
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 CONFIG_STX_GP3=y
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -234,6 +248,7 @@ CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -252,9 +267,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -425,6 +440,7 @@ CONFIG_IP_NF_FILTER=m
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -442,7 +458,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -466,6 +486,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=m
+CONFIG_OF_MDIO=y
 CONFIG_PARPORT=m
 CONFIG_PARPORT_PC=m
 # CONFIG_PARPORT_PC_FIFO is not set
@@ -507,7 +528,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -581,10 +604,6 @@ CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=m
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
@@ -602,6 +621,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -610,6 +630,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -631,7 +652,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_PPA is not set
 # CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -654,14 +674,17 @@ CONFIG_SCSI_LOWLEVEL=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -708,6 +731,7 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_NET_POCKET is not set
 # CONFIG_ATL2 is not set
 # CONFIG_FS_ENET is not set
@@ -729,8 +753,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -802,12 +828,13 @@ CONFIG_INPUT_EVDEV=m
 #
 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_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
-# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_PS2_ALPS=y
@@ -821,6 +848,7 @@ CONFIG_MOUSE_PS2_TRACKPOINT=y
 # CONFIG_MOUSE_BCM5974 is not set
 # CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
@@ -911,6 +939,7 @@ CONFIG_I2C_ALGOBIT=m
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
 # CONFIG_I2C_CPM is not set
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 # CONFIG_I2C_MPC is not set
 # CONFIG_I2C_OCORES is not set
@@ -941,13 +970,17 @@ CONFIG_I2C_ALGOBIT=m
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -1027,6 +1060,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1060,23 +1094,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1143,6 +1163,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1162,10 +1186,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1316,6 +1342,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1346,6 +1373,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1358,7 +1388,6 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1372,16 +1401,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1389,6 +1417,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index 767600145fb2146714f9321ce74c4209277cfaa8..2c407523aad2f38fdf885cdfb3d5176db476e85a 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:23 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:21 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -56,11 +57,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -109,7 +112,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -122,9 +124,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -137,6 +146,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -144,7 +157,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -177,6 +190,7 @@ CONFIG_MPC85xx=y
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 CONFIG_TQM8540=y
 # CONFIG_TQM8541 is not set
@@ -225,6 +239,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -243,9 +258,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -353,6 +368,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -370,7 +386,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -471,6 +491,7 @@ CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -505,7 +526,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -580,14 +603,17 @@ CONFIG_BLK_DEV_IDEDMA=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -650,6 +676,7 @@ CONFIG_E100=y
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -671,8 +698,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -850,13 +879,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -911,6 +944,7 @@ CONFIG_SENSORS_LM75=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -945,23 +979,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1018,6 +1038,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1037,10 +1061,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1167,6 +1193,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1192,22 +1219,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
index 52fafc006dd035c3896fe2ea9a3b70c053a02e32..845731dc51c6746ea35898dd0cfecf1d4017b1f8 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:23 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:22 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -57,11 +58,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -110,7 +113,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -123,9 +125,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -139,6 +148,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -146,7 +159,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -179,6 +192,7 @@ CONFIG_MPC85xx=y
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 CONFIG_TQM8541=y
@@ -228,6 +242,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -246,9 +261,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -356,6 +371,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -373,7 +389,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -475,6 +495,7 @@ CONFIG_MTD_CFI_UTIL=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -509,7 +530,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -584,14 +607,17 @@ CONFIG_BLK_DEV_IDEDMA=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -654,6 +680,7 @@ CONFIG_E100=y
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -676,8 +703,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -831,6 +860,7 @@ CONFIG_I2C_HELPER_AUTO=y
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
 # CONFIG_I2C_CPM is not set
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
@@ -859,13 +889,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -944,6 +978,7 @@ CONFIG_SENSORS_LM75=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -979,23 +1014,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1052,6 +1073,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1071,10 +1096,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1201,6 +1228,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1226,22 +1254,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
index 8b4faae7a9a13f8ab054736f4920e022bf4e3568..4f228a9052744d3261c258084bb5cb7109f8c3ac 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:24 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:23 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -56,11 +57,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -111,7 +114,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -124,9 +126,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -140,6 +149,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -152,7 +165,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -185,6 +198,7 @@ CONFIG_MPC85xx=y
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -234,6 +248,7 @@ CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -252,9 +267,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -281,6 +296,8 @@ CONFIG_PCI_DOMAINS=y
 CONFIG_PCI_SYSCALL=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
 # CONFIG_PCIEASPM is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
@@ -368,6 +385,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -497,6 +515,7 @@ CONFIG_MTD_NAND_FSL_UPM=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -531,7 +550,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -551,14 +572,17 @@ CONFIG_HAVE_IDE=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -605,6 +629,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -624,8 +649,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -801,13 +828,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -862,6 +893,7 @@ CONFIG_SENSORS_LM75=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -896,23 +928,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -977,6 +995,7 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1004,6 +1023,10 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1015,10 +1038,12 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1145,6 +1170,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1175,6 +1201,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1187,7 +1216,6 @@ CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1201,16 +1229,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1218,6 +1245,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index 170360934cec116df43a3a1f70dbcc0ae6825ab5..9196724bebc712e33df068385d734373aaa7d525 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:25 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:24 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -57,11 +58,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -110,7 +113,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -123,9 +125,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -139,6 +148,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -146,7 +159,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -179,6 +192,7 @@ CONFIG_MPC85xx=y
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -228,6 +242,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -246,9 +261,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -356,6 +371,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -373,7 +389,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -475,6 +495,7 @@ CONFIG_MTD_CFI_UTIL=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -509,7 +530,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -584,14 +607,17 @@ CONFIG_BLK_DEV_IDEDMA=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -654,6 +680,7 @@ CONFIG_E100=y
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -676,8 +703,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -831,6 +860,7 @@ CONFIG_I2C_HELPER_AUTO=y
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
 # CONFIG_I2C_CPM is not set
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
@@ -859,13 +889,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -944,6 +978,7 @@ CONFIG_SENSORS_LM75=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -979,23 +1014,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1052,6 +1073,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1071,10 +1096,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1201,6 +1228,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1226,22 +1254,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
index f41cc2444d489aafc46a60d2c0dd7f6efc328957..2e49a6e9faf2775e35a0ccd32b64d6dbcb1b71d0 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:26 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:25 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -57,11 +58,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -110,7 +113,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -123,9 +125,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -139,6 +148,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -146,7 +159,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -179,6 +192,7 @@ CONFIG_MPC85xx=y
 # CONFIG_MPC85xx_DS is not set
 # CONFIG_SOCRATES is not set
 # CONFIG_KSI8560 is not set
+# CONFIG_XES_MPC85xx is not set
 # CONFIG_STX_GP3 is not set
 # CONFIG_TQM8540 is not set
 # CONFIG_TQM8541 is not set
@@ -228,6 +242,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -246,9 +261,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -356,6 +371,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -373,7 +389,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -475,6 +495,7 @@ CONFIG_MTD_CFI_UTIL=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -509,7 +530,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -584,14 +607,17 @@ CONFIG_BLK_DEV_IDEDMA=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -654,6 +680,7 @@ CONFIG_E100=y
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -676,8 +703,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -831,6 +860,7 @@ CONFIG_I2C_HELPER_AUTO=y
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
 # CONFIG_I2C_CPM is not set
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
@@ -859,13 +889,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -944,6 +978,7 @@ CONFIG_SENSORS_LM75=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -979,23 +1014,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1052,6 +1073,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1071,10 +1096,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1201,6 +1228,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1226,22 +1254,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
index 2552cbefba6b3d7dd941491f77eb95176132dda8..1025da2bf0691b603be35b9be72e585f3e17139a 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc6
-# Thu Jun 11 11:25:17 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:25 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -35,15 +35,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -64,6 +65,7 @@ CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -114,7 +116,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -127,9 +128,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -144,6 +152,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -157,7 +169,7 @@ CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -239,6 +251,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -258,9 +271,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -287,6 +300,8 @@ CONFIG_PCI_DOMAINS=y
 CONFIG_PCI_SYSCALL=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
 # CONFIG_PCIEASPM is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 CONFIG_PCI_MSI=y
@@ -404,6 +419,7 @@ CONFIG_IPV6_NDISC_NODETYPE=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -540,6 +556,7 @@ CONFIG_MTD_NAND_FSL_UPM=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -575,7 +592,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -599,10 +618,6 @@ CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 CONFIG_SCSI_LOGGING=y
@@ -619,6 +634,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -627,6 +643,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -646,7 +663,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -730,14 +746,17 @@ CONFIG_PATA_ALI=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -784,6 +803,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -803,8 +823,10 @@ CONFIG_E1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -986,13 +1008,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_DS1682 is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -1072,6 +1098,7 @@ CONFIG_SENSORS_LM90=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1126,23 +1153,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1187,7 +1200,7 @@ CONFIG_USB_HID=y
 # CONFIG_HID_CHERRY is not set
 # CONFIG_HID_CHICONY is not set
 # CONFIG_HID_CYPRESS is not set
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 # CONFIG_HID_EZKEY is not set
 # CONFIG_HID_KYE is not set
 # CONFIG_HID_GYRATION is not set
@@ -1201,10 +1214,11 @@ CONFIG_USB_HID=y
 # CONFIG_HID_SAMSUNG is not set
 # CONFIG_HID_SONY is not set
 # CONFIG_HID_SUNPLUS is not set
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-# CONFIG_THRUSTMASTER_FF is not set
-# CONFIG_ZEROPLUS_FF is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1230,6 +1244,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 # CONFIG_USB_EHCI_HCD is not set
 # CONFIG_USB_OXU210HP_HCD is not set
 # CONFIG_USB_ISP116X_HCD is not set
@@ -1325,7 +1340,7 @@ CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_GPIO_PLATFORM=y
 CONFIG_LEDS_GPIO_OF=y
-# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP3944 is not set
 CONFIG_LEDS_PCA955X=y
 # CONFIG_LEDS_BD2802 is not set
 
@@ -1352,8 +1367,6 @@ CONFIG_EDAC=y
 # CONFIG_EDAC_DEBUG is not set
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_MPC85XX=y
-# CONFIG_EDAC_AMD8131 is not set
-# CONFIG_EDAC_AMD8111 is not set
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -1385,6 +1398,7 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1425,6 +1439,10 @@ CONFIG_NET_DMA=y
 # CONFIG_DMATEST is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1444,11 +1462,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1629,6 +1648,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1659,6 +1679,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1671,7 +1694,6 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1685,16 +1707,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1702,6 +1723,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index b6a23af57f46fd8bb7b6826c90d1b1b5a4ac69f8..527ad1a5e802020cc186f7f632d6d5bbb99aeaa3 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:31 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:31 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PPC32=y
@@ -32,16 +34,17 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_LOCKBREAK=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -56,11 +59,13 @@ CONFIG_PPC_UDBG_16550=y
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -112,9 +117,7 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -127,8 +130,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -143,6 +153,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -156,7 +170,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -216,7 +230,7 @@ CONFIG_MPIC=y
 #
 # Kernel options
 #
-# CONFIG_HIGHMEM is not set
+CONFIG_HIGHMEM=y
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -235,6 +249,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -256,9 +271,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -285,14 +300,32 @@ CONFIG_PCI_DOMAINS=y
 CONFIG_PCI_SYSCALL=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
 # CONFIG_PCIEASPM is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
 # CONFIG_PCI_LEGACY is not set
-CONFIG_PCI_DEBUG=y
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCI_IOV is not set
-# CONFIG_PCCARD is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_LOAD_CIS is not set
+# CONFIG_PCMCIA_IOCTL is not set
+# CONFIG_CARDBUS is not set
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+# CONFIG_YENTA_O2 is not set
+# CONFIG_YENTA_RICOH is not set
+CONFIG_YENTA_TI=y
+# CONFIG_YENTA_TOSHIBA is not set
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+CONFIG_PCCARD_NONSTATIC=y
 # CONFIG_HOTPLUG_PCI is not set
 # CONFIG_HAS_RAPIDIO is not set
 
@@ -353,8 +386,8 @@ CONFIG_INET_XFRM_TUNNEL=m
 CONFIG_INET_TUNNEL=m
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-# CONFIG_INET_LRO is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_LRO=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -380,174 +413,26 @@ CONFIG_IPV6_NDISC_NODETYPE=y
 CONFIG_IPV6_TUNNEL=m
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_IPV6_MROUTE is not set
-# CONFIG_NETLABEL is not set
 # CONFIG_NETWORK_SECMARK is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-CONFIG_NETFILTER_ADVANCED=y
-CONFIG_BRIDGE_NETFILTER=y
-
-#
-# Core Netfilter Configuration
-#
-# CONFIG_NETFILTER_NETLINK_QUEUE is not set
-# CONFIG_NETFILTER_NETLINK_LOG is not set
-# CONFIG_NF_CONNTRACK is not set
-# CONFIG_NETFILTER_TPROXY is not set
-CONFIG_NETFILTER_XTABLES=m
-# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
-# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
-# CONFIG_NETFILTER_XT_TARGET_HL is not set
-# CONFIG_NETFILTER_XT_TARGET_MARK is not set
-# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
-# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
-# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
-# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
-# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
-# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
-# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
-# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
-# CONFIG_NETFILTER_XT_MATCH_ESP is not set
-# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
-CONFIG_NETFILTER_XT_MATCH_HL=m
-# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
-# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
-# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
-# CONFIG_NETFILTER_XT_MATCH_MAC is not set
-# CONFIG_NETFILTER_XT_MATCH_MARK is not set
-# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
-# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
-# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
-# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
-# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
-# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
-# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
-# CONFIG_NETFILTER_XT_MATCH_REALM is not set
-# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
-# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
-# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
-# CONFIG_NETFILTER_XT_MATCH_STRING is not set
-# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
-# CONFIG_NETFILTER_XT_MATCH_TIME is not set
-# CONFIG_NETFILTER_XT_MATCH_U32 is not set
-# CONFIG_IP_VS is not set
-
-#
-# IP: Netfilter Configuration
-#
-# CONFIG_NF_DEFRAG_IPV4 is not set
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-# CONFIG_IP_NF_MATCH_AH is not set
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_TTL=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_MANGLE=m
-CONFIG_IP_NF_TARGET_ECN=m
-# CONFIG_IP_NF_TARGET_TTL is not set
-CONFIG_IP_NF_RAW=m
-# CONFIG_IP_NF_SECURITY is not set
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-
-#
-# IPv6: Netfilter Configuration
-#
-CONFIG_IP6_NF_QUEUE=m
-CONFIG_IP6_NF_IPTABLES=m
-# CONFIG_IP6_NF_MATCH_AH is not set
-CONFIG_IP6_NF_MATCH_EUI64=m
-CONFIG_IP6_NF_MATCH_FRAG=m
-CONFIG_IP6_NF_MATCH_OPTS=m
-CONFIG_IP6_NF_MATCH_HL=m
-CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-# CONFIG_IP6_NF_MATCH_MH is not set
-CONFIG_IP6_NF_MATCH_RT=m
-# CONFIG_IP6_NF_TARGET_HL is not set
-CONFIG_IP6_NF_TARGET_LOG=m
-CONFIG_IP6_NF_FILTER=m
-# CONFIG_IP6_NF_TARGET_REJECT is not set
-CONFIG_IP6_NF_MANGLE=m
-CONFIG_IP6_NF_RAW=m
-# CONFIG_IP6_NF_SECURITY is not set
-# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
-CONFIG_IP_SCTP=m
-# CONFIG_SCTP_DBG_MSG is not set
-# CONFIG_SCTP_DBG_OBJCNT is not set
-# CONFIG_SCTP_HMAC_NONE is not set
-# CONFIG_SCTP_HMAC_SHA1 is not set
-CONFIG_SCTP_HMAC_MD5=y
-CONFIG_TIPC=m
-# CONFIG_TIPC_ADVANCED is not set
-# CONFIG_TIPC_DEBUG is not set
-CONFIG_ATM=m
-CONFIG_ATM_CLIP=m
-# CONFIG_ATM_CLIP_NO_ICMP is not set
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
-# CONFIG_ATM_BR2684_IPFILTER is not set
-CONFIG_STP=m
-CONFIG_BRIDGE=m
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_NET_DSA is not set
-CONFIG_VLAN_8021Q=m
-# CONFIG_VLAN_8021Q_GVRP is not set
+# CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
-CONFIG_LLC=m
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_ECONET is not set
-CONFIG_WAN_ROUTER=m
+# CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
-CONFIG_NET_SCHED=y
-
-#
-# Queueing/Scheduling
-#
-CONFIG_NET_SCH_CBQ=m
-CONFIG_NET_SCH_HTB=m
-CONFIG_NET_SCH_HFSC=m
-CONFIG_NET_SCH_ATM=m
-CONFIG_NET_SCH_PRIO=m
-# CONFIG_NET_SCH_MULTIQ is not set
-CONFIG_NET_SCH_RED=m
-CONFIG_NET_SCH_SFQ=m
-CONFIG_NET_SCH_TEQL=m
-CONFIG_NET_SCH_TBF=m
-CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_NETEM=m
-# CONFIG_NET_SCH_DRR is not set
-
-#
-# Classification
-#
-CONFIG_NET_CLS=y
-# CONFIG_NET_CLS_BASIC is not set
-CONFIG_NET_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_ROUTE=y
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-# CONFIG_CLS_U32_PERF is not set
-# CONFIG_CLS_U32_MARK is not set
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-# CONFIG_NET_CLS_FLOW is not set
-# CONFIG_NET_EMATCH is not set
-# CONFIG_NET_CLS_ACT is not set
-# CONFIG_NET_CLS_IND is not set
-CONFIG_NET_SCH_FIFO=y
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
 #
@@ -560,12 +445,7 @@ CONFIG_NET_PKTGEN=m
 # CONFIG_BT is not set
 # CONFIG_AF_RXRPC is not set
 CONFIG_FIB_RULES=y
-CONFIG_WIRELESS=y
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_OLD_REGULATORY=y
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+# CONFIG_WIRELESS is not set
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -580,9 +460,9 @@ CONFIG_WIRELESS_OLD_REGULATORY=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
-# CONFIG_DEBUG_DRIVER is not set
-# CONFIG_DEBUG_DEVRES is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_SYS_HYPERVISOR is not set
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
@@ -672,6 +552,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -707,9 +588,60 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
-# CONFIG_IDE is not set
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_PLATFORM is not set
+
+#
+# PCI IDE chipsets support
+#
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 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_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8172 is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SL82C105 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_TC86C001 is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
 
 #
 # SCSI device support
@@ -731,10 +663,6 @@ CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR 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
@@ -751,6 +679,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -759,6 +688,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -778,7 +708,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -791,6 +720,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
 CONFIG_ATA=y
@@ -842,6 +772,7 @@ CONFIG_SATA_SIL=y
 # CONFIG_PATA_NS87415 is not set
 # CONFIG_PATA_OPTI is not set
 # CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PCMCIA is not set
 # CONFIG_PATA_PDC_OLD is not set
 # CONFIG_PATA_RADISYS is not set
 # CONFIG_PATA_RZ1000 is not set
@@ -862,14 +793,17 @@ CONFIG_SATA_SIL=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 # CONFIG_MACVLAN is not set
@@ -916,6 +850,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -935,8 +870,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -963,22 +900,8 @@ CONFIG_GIANFAR=y
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+# CONFIG_NET_PCMCIA is not set
 # CONFIG_WAN is not set
-CONFIG_ATM_DRIVERS=y
-# CONFIG_ATM_DUMMY is not set
-# CONFIG_ATM_TCP is not set
-# CONFIG_ATM_LANAI is not set
-# CONFIG_ATM_ENI is not set
-# CONFIG_ATM_FIRESTREAM is not set
-# CONFIG_ATM_ZATM is not set
-# CONFIG_ATM_NICSTAR is not set
-# CONFIG_ATM_IDT77252 is not set
-# CONFIG_ATM_AMBASSADOR is not set
-# CONFIG_ATM_HORIZON is not set
-# CONFIG_ATM_IA is not set
-# CONFIG_ATM_FORE200E is not set
-# CONFIG_ATM_HE is not set
-# CONFIG_ATM_SOLOS is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 CONFIG_PPP=m
@@ -990,7 +913,6 @@ CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
 # CONFIG_PPP_MPPE is not set
 CONFIG_PPPOE=m
-CONFIG_PPPOATM=m
 # CONFIG_PPPOL2TP is not set
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
@@ -1010,7 +932,7 @@ CONFIG_NET_POLL_CONTROLLER=y
 # Input device support
 #
 CONFIG_INPUT=y
-CONFIG_INPUT_FF_MEMLESS=m
+# CONFIG_INPUT_FF_MEMLESS is not set
 # CONFIG_INPUT_POLLDEV is not set
 
 #
@@ -1058,6 +980,7 @@ CONFIG_DEVKMEM=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_SERIAL_8250_PCI is not set
+# CONFIG_SERIAL_8250_CS is not set
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -1080,6 +1003,14 @@ CONFIG_HW_RANDOM=y
 CONFIG_NVRAM=y
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_IPWIRELESS is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 CONFIG_DEVPORT=y
@@ -1143,18 +1074,21 @@ CONFIG_DS1682=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
-# CONFIG_DEBUG_GPIO is not set
-# CONFIG_GPIO_SYSFS is not set
+CONFIG_GPIO_SYSFS=y
 
 #
 # Memory mapped GPIO expanders:
@@ -1229,6 +1163,7 @@ CONFIG_SENSORS_LM92=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1284,24 +1219,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1346,7 +1266,7 @@ CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1363,10 +1283,11 @@ CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1392,6 +1313,7 @@ CONFIG_USB=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1401,6 +1323,8 @@ CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
 # CONFIG_USB_OHCI_HCD_PPC_OF is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
@@ -1475,7 +1399,6 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_VST is not set
-# CONFIG_USB_ATM is not set
 # CONFIG_USB_GADGET is not set
 
 #
@@ -1521,6 +1444,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 CONFIG_RTC_DRV_RX8581=y
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1548,6 +1472,10 @@ CONFIG_RTC_DRV_RX8581=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1569,10 +1497,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1589,8 +1519,11 @@ CONFIG_INOTIFY_USER=y
 #
 # CD-ROM/DVD Filesystems
 #
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
@@ -1598,8 +1531,8 @@ CONFIG_INOTIFY_USER=y
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -1649,6 +1582,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1723,13 +1657,13 @@ CONFIG_NLS_UTF8=m
 #
 CONFIG_BITREVERSE=y
 CONFIG_GENERIC_FIND_LAST_BIT=y
-CONFIG_CRC_CCITT=m
+CONFIG_CRC_CCITT=y
 # CONFIG_CRC16 is not set
-# CONFIG_CRC_T10DIF is not set
-# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
 CONFIG_CRC32=y
 # CONFIG_CRC7 is not set
-CONFIG_LIBCRC32C=m
+CONFIG_LIBCRC32C=y
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_DECOMPRESS_GZIP=y
@@ -1738,6 +1672,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1750,75 +1685,24 @@ CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DEBUG_SHIRQ is not set
-CONFIG_DETECT_SOFTLOCKUP=y
-# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
-CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
-CONFIG_SCHED_DEBUG=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_TIMER_STATS is not set
-# CONFIG_DEBUG_OBJECTS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_RT_MUTEXES is not set
-# CONFIG_RT_MUTEX_TESTER is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_MUTEXES is not set
-# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
-# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
-# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_KERNEL is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_DEBUG_VM is not set
-# CONFIG_DEBUG_WRITECOUNT is not set
 # CONFIG_DEBUG_MEMORY_INIT is not set
-# CONFIG_DEBUG_LIST is not set
-# CONFIG_DEBUG_SG is not set
-# CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
-# CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_BACKTRACE_SELF_TEST is not set
-# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
-# CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
 CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_PREEMPT_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
-# CONFIG_DEBUG_STACKOVERFLOW is not set
-# CONFIG_DEBUG_STACK_USAGE is not set
-# CONFIG_CODE_PATCHING_SELFTEST is not set
-# CONFIG_FTR_FIXUP_SELFTEST is not set
-# CONFIG_MSI_BITMAP_SELFTEST is not set
-# CONFIG_XMON is not set
 # CONFIG_IRQSTACKS is not set
-# CONFIG_BDI_SWITCH is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
 
@@ -1826,15 +1710,9 @@ CONFIG_PRINT_STACK_DEPTH=64
 # Security options
 #
 # CONFIG_KEYS is not set
-CONFIG_SECURITY=y
+# CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
-CONFIG_SECURITY_NETWORK=y
-# CONFIG_SECURITY_NETWORK_XFRM is not set
-# CONFIG_SECURITY_PATH is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
-# CONFIG_SECURITY_ROOTPLUG is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
-# CONFIG_SECURITY_TOMOYO is not set
 CONFIG_CRYPTO=y
 
 #
@@ -1854,11 +1732,11 @@ CONFIG_CRYPTO_PCOMP=y
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_MANAGER2=y
 # CONFIG_CRYPTO_GF128MUL is not set
-CONFIG_CRYPTO_NULL=m
+# CONFIG_CRYPTO_NULL is not set
 CONFIG_CRYPTO_WORKQUEUE=y
 # CONFIG_CRYPTO_CRYPTD is not set
 CONFIG_CRYPTO_AUTHENC=m
-CONFIG_CRYPTO_TEST=m
+# CONFIG_CRYPTO_TEST is not set
 
 #
 # Authenticated Encryption with Associated Data
@@ -1873,53 +1751,52 @@ CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CBC=y
 # CONFIG_CRYPTO_CTR is not set
 # CONFIG_CRYPTO_CTS is not set
-CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_ECB is not set
 # CONFIG_CRYPTO_LRW is not set
-CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_PCBC is not set
 # CONFIG_CRYPTO_XTS is not set
 
 #
 # Hash modes
 #
-CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_HMAC=m
 # CONFIG_CRYPTO_XCBC is not set
 
 #
 # Digest
 #
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_MD4 is not set
 CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_RMD128 is not set
 # CONFIG_CRYPTO_RMD160 is not set
 # CONFIG_CRYPTO_RMD256 is not set
 # CONFIG_CRYPTO_RMD320 is not set
 CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
 # CONFIG_CRYPTO_TGR192 is not set
-CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_WP512 is not set
 
 #
 # Ciphers
 #
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_BLOWFISH=m
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_CAMELLIA is not set
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_FCRYPT is not set
-CONFIG_CRYPTO_KHAZAD=m
+# CONFIG_CRYPTO_KHAZAD is not set
 # CONFIG_CRYPTO_SALSA20 is not set
 # CONFIG_CRYPTO_SEED is not set
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
 
 #
 # Compression
index a66910e6334548fd2335016b6eecf49789f5376f..cd338d493bedcaf960576f65082c4ad8e1ed89e0 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:29 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:29 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PPC32=y
@@ -32,16 +34,17 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_LOCKBREAK=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -56,11 +59,13 @@ CONFIG_PPC_UDBG_16550=y
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -91,7 +96,11 @@ CONFIG_CLASSIC_RCU=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_GROUP_SCHED is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
 # CONFIG_CGROUPS is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
@@ -109,7 +118,6 @@ CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -122,8 +130,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -138,6 +153,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -151,7 +170,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -168,7 +187,6 @@ CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
 # CONFIG_FREEZER is not set
-CONFIG_PPC_MSI_BITMAP=y
 
 #
 # Platform support
@@ -212,7 +230,7 @@ CONFIG_MPIC=y
 #
 # Kernel options
 #
-# CONFIG_HIGHMEM is not set
+CONFIG_HIGHMEM=y
 CONFIG_TICK_ONESHOT=y
 # CONFIG_NO_HZ is not set
 CONFIG_HIGH_RES_TIMERS=y
@@ -231,6 +249,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -252,9 +271,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -281,13 +300,32 @@ CONFIG_PCI_DOMAINS=y
 CONFIG_PCI_SYSCALL=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
 # CONFIG_PCIEASPM is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
-CONFIG_PCI_MSI=y
+# CONFIG_PCI_MSI is not set
 # CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_STUB is not set
 # CONFIG_PCI_IOV is not set
-# CONFIG_PCCARD is not set
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+# CONFIG_PCMCIA_LOAD_CIS is not set
+# CONFIG_PCMCIA_IOCTL is not set
+# CONFIG_CARDBUS is not set
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+# CONFIG_YENTA_O2 is not set
+# CONFIG_YENTA_RICOH is not set
+CONFIG_YENTA_TI=y
+# CONFIG_YENTA_TOSHIBA is not set
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+CONFIG_PCCARD_NONSTATIC=y
 # CONFIG_HOTPLUG_PCI is not set
 # CONFIG_HAS_RAPIDIO is not set
 
@@ -393,6 +431,7 @@ CONFIG_IPV6_TUNNEL=m
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -421,7 +460,9 @@ CONFIG_FIB_RULES=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_SYS_HYPERVISOR is not set
 # CONFIG_CONNECTOR is not set
 CONFIG_MTD=y
@@ -511,6 +552,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -546,9 +588,60 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
-# CONFIG_IDE is not set
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+CONFIG_BLK_DEV_IDECS=y
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_PLATFORM is not set
+
+#
+# PCI IDE chipsets support
+#
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 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_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8172 is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SL82C105 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_TC86C001 is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
 
 #
 # SCSI device support
@@ -570,10 +663,6 @@ CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR 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
@@ -590,6 +679,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -598,6 +688,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -617,7 +708,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -630,6 +720,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set
 # CONFIG_SCSI_DH is not set
 # CONFIG_SCSI_OSD_INITIATOR is not set
 CONFIG_ATA=y
@@ -647,14 +738,17 @@ CONFIG_SATA_SIL24=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 # CONFIG_MACVLAN is not set
@@ -701,6 +795,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -720,8 +815,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -748,6 +845,7 @@ CONFIG_GIANFAR=y
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+# CONFIG_NET_PCMCIA is not set
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -827,6 +925,7 @@ CONFIG_DEVKMEM=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_SERIAL_8250_PCI is not set
+# CONFIG_SERIAL_8250_CS is not set
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -849,6 +948,14 @@ CONFIG_HW_RANDOM=y
 CONFIG_NVRAM=y
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_IPWIRELESS is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 CONFIG_DEVPORT=y
@@ -912,13 +1019,17 @@ CONFIG_DS1682=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -997,6 +1108,7 @@ CONFIG_SENSORS_LM92=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1052,24 +1164,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1114,7 +1211,7 @@ CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1131,10 +1228,11 @@ CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-# CONFIG_THRUSTMASTER_FF is not set
-# CONFIG_ZEROPLUS_FF is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1160,6 +1258,7 @@ CONFIG_USB=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1169,6 +1268,8 @@ CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
 # CONFIG_USB_OHCI_HCD_PPC_OF is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
@@ -1288,6 +1389,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 CONFIG_RTC_DRV_RX8581=y
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1315,6 +1417,10 @@ CONFIG_RTC_DRV_RX8581=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1336,10 +1442,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1419,6 +1527,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1508,6 +1617,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1531,23 +1641,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_PREEMPT_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index c6a7fc82b69a65d672e702956a372c06e1c9bfc3..ba47883f4aa00b09b7d001543c6e6c16345b9c4d 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:30 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:30 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PPC32=y
@@ -32,16 +34,17 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_LOCKBREAK=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -56,11 +59,13 @@ CONFIG_PPC_UDBG_16550=y
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -114,7 +119,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -127,8 +131,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -143,6 +154,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -156,7 +171,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -235,6 +250,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -256,9 +272,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -285,6 +301,8 @@ CONFIG_PCI_DOMAINS=y
 CONFIG_PCI_SYSCALL=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
 # CONFIG_PCIEASPM is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
@@ -510,6 +528,7 @@ CONFIG_LLC=m
 # CONFIG_ECONET is not set
 CONFIG_WAN_ROUTER=m
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 CONFIG_NET_SCHED=y
 
 #
@@ -566,7 +585,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -678,6 +701,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -713,7 +737,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -737,10 +763,6 @@ CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR 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
@@ -757,6 +779,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -765,6 +788,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -784,7 +808,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -868,14 +891,17 @@ CONFIG_SATA_SIL=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 # CONFIG_MACVLAN is not set
@@ -922,6 +948,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -941,8 +968,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -1149,13 +1178,17 @@ CONFIG_DS1682=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -1235,6 +1268,7 @@ CONFIG_SENSORS_LM92=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1290,24 +1324,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1352,7 +1371,7 @@ CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1369,10 +1388,11 @@ CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1398,6 +1418,7 @@ CONFIG_USB=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1407,6 +1428,8 @@ CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
 # CONFIG_USB_OHCI_HCD_PPC_OF is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
@@ -1527,6 +1550,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 CONFIG_RTC_DRV_RX8581=y
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1554,6 +1578,10 @@ CONFIG_RTC_DRV_RX8581=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1575,10 +1603,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1645,6 +1675,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1734,6 +1765,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1759,10 +1791,14 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1774,7 +1810,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1788,17 +1823,16 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1806,6 +1840,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
@@ -1829,7 +1866,6 @@ CONFIG_SECURITY_NETWORK=y
 # CONFIG_SECURITY_PATH is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
 # CONFIG_SECURITY_ROOTPLUG is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
 # CONFIG_SECURITY_TOMOYO is not set
 CONFIG_CRYPTO=y
 
index cfd2efcc6bce1f19b955d847cd917ca45bd50d8f..a61f183f718693f56e367d7d0188ce681b988ec4 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:28 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:27 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -53,11 +56,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -109,7 +114,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -122,9 +126,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -138,6 +149,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -150,7 +165,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -230,6 +245,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -250,9 +266,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -279,6 +295,8 @@ CONFIG_PCI_DOMAINS=y
 CONFIG_PCI_SYSCALL=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
 # CONFIG_PCIEASPM is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
@@ -381,6 +399,7 @@ CONFIG_IPV6_NDISC_NODETYPE=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -398,7 +417,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -549,7 +572,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -620,10 +645,6 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_BLK_DEV_SR is not set
 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 is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -640,6 +661,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -648,6 +670,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -667,7 +690,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -751,14 +773,17 @@ CONFIG_PATA_ALI=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -792,6 +817,7 @@ CONFIG_ULI526X=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
@@ -959,13 +985,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -993,23 +1023,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1106,6 +1122,11 @@ CONFIG_SND_PCM_OSS_PLUGINS=y
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
 # CONFIG_SND_MTPAV is not set
@@ -1130,6 +1151,7 @@ CONFIG_SND_PCI=y
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
 # CONFIG_SND_CS5530 is not set
+# CONFIG_SND_CTXFI is not set
 # CONFIG_SND_DARLA20 is not set
 # CONFIG_SND_GINA20 is not set
 # CONFIG_SND_LAYLA20 is not set
@@ -1160,6 +1182,7 @@ CONFIG_SND_PCI=y
 # CONFIG_SND_INTEL8X0 is not set
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
 # CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -1251,6 +1274,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1278,6 +1302,10 @@ CONFIG_RTC_DRV_CMOS=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1297,12 +1325,15 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
@@ -1464,6 +1495,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1494,6 +1526,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1506,7 +1541,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1520,16 +1554,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1537,6 +1570,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index 0bee3e303942f58e2c13898b700c4ff77dd218c4..7016ce73260576bacd3a788c9fa7da9b21822ed9 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:28 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:28 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PPC32=y
@@ -32,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -54,11 +57,13 @@ CONFIG_PPC_UDBG_16550=y
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -113,7 +118,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -126,9 +130,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -143,6 +154,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -156,7 +171,7 @@ CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -234,7 +249,9 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
-# CONFIG_IOMMU_HELPER is not set
+CONFIG_IOMMU_HELPER=y
+CONFIG_SWIOTLB=y
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -256,9 +273,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -401,6 +418,7 @@ CONFIG_SCTP_HMAC_MD5=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -419,7 +437,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -444,6 +466,7 @@ CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -479,7 +502,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 CONFIG_EEPROM_LEGACY=y
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -503,10 +528,6 @@ CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 CONFIG_SCSI_LOGGING=y
@@ -524,6 +545,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -532,6 +554,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -551,7 +574,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -635,14 +657,17 @@ CONFIG_PATA_ALI=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -689,6 +714,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -708,8 +734,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -909,13 +937,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -943,76 +975,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-CONFIG_DVB_CORE=m
-CONFIG_VIDEO_MEDIA=m
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=m
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=m
-CONFIG_MEDIA_TUNER_TDA8290=m
-CONFIG_MEDIA_TUNER_TDA9887=m
-CONFIG_MEDIA_TUNER_TEA5761=m
-CONFIG_MEDIA_TUNER_TEA5767=m
-CONFIG_MEDIA_TUNER_MT20XX=m
-CONFIG_MEDIA_TUNER_XC2028=m
-CONFIG_MEDIA_TUNER_XC5000=m
-CONFIG_MEDIA_TUNER_MC44S803=m
-# CONFIG_DVB_DYNAMIC_MINORS is not set
-CONFIG_DVB_CAPTURE_DRIVERS=y
-
-#
-# Supported SAA7146 based PCI Adapters
-#
-# CONFIG_TTPCI_EEPROM is not set
-# CONFIG_DVB_BUDGET_CORE is not set
-
-#
-# Supported USB Adapters
-#
-# CONFIG_DVB_USB is not set
-# CONFIG_DVB_TTUSB_BUDGET is not set
-# CONFIG_DVB_TTUSB_DEC is not set
-# CONFIG_DVB_SIANO_SMS1XXX is not set
-
-#
-# Supported FlexCopII (B2C2) Adapters
-#
-# CONFIG_DVB_B2C2_FLEXCOP is not set
-
-#
-# Supported BT878 Adapters
-#
-
-#
-# Supported Pluto2 Adapters
-#
-# CONFIG_DVB_PLUTO2 is not set
-
-#
-# Supported SDMC DM1105 Adapters
-#
-# CONFIG_DVB_DM1105 is not set
-
-#
-# Supported DVB Frontends
-#
-# CONFIG_DVB_FE_CUSTOMISE is not set
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1052,6 +1017,11 @@ CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_AC97_CODEC=y
 CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
@@ -1078,6 +1048,7 @@ CONFIG_SND_PCI=y
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
 # CONFIG_SND_CS5530 is not set
+# CONFIG_SND_CTXFI is not set
 # CONFIG_SND_DARLA20 is not set
 # CONFIG_SND_GINA20 is not set
 # CONFIG_SND_LAYLA20 is not set
@@ -1108,6 +1079,7 @@ CONFIG_SND_PCI=y
 CONFIG_SND_INTEL8X0=y
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
 # CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -1152,7 +1124,7 @@ CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1169,10 +1141,11 @@ CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1198,6 +1171,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1207,9 +1181,9 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1329,6 +1303,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1356,6 +1331,10 @@ CONFIG_RTC_DRV_CMOS=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1375,11 +1354,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1454,6 +1434,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
@@ -1555,6 +1536,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1585,6 +1567,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1597,7 +1582,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1611,16 +1595,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1628,6 +1611,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index c30a0c7158738162abf8ef8be90fa5d55bed4067..f5ca2e0cd40268d8a3f734d290da8afb408b9284 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:27 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:26 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PPC32=y
@@ -32,16 +34,17 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_LOCKBREAK=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -55,11 +58,13 @@ CONFIG_PPC_UDBG_16550=y
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -113,7 +118,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -126,8 +130,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -142,6 +153,11 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -155,7 +171,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -234,6 +250,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -255,9 +272,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -284,6 +301,8 @@ CONFIG_PCI_DOMAINS=y
 CONFIG_PCI_SYSCALL=y
 CONFIG_PCIEPORTBUS=y
 CONFIG_PCIEAER=y
+# CONFIG_PCIE_ECRC is not set
+# CONFIG_PCIEAER_INJECT is not set
 # CONFIG_PCIEASPM is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
@@ -508,6 +527,7 @@ CONFIG_LLC=m
 # CONFIG_ECONET is not set
 CONFIG_WAN_ROUTER=m
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 CONFIG_NET_SCHED=y
 
 #
@@ -564,7 +584,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -675,6 +699,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -709,7 +734,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -736,6 +763,7 @@ CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=y
 CONFIG_DM_SNAPSHOT=y
 CONFIG_DM_MIRROR=y
+# CONFIG_DM_LOG_USERSPACE is not set
 CONFIG_DM_ZERO=y
 # CONFIG_DM_MULTIPATH is not set
 # CONFIG_DM_DELAY is not set
@@ -747,14 +775,17 @@ CONFIG_DM_ZERO=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 # CONFIG_MACVLAN is not set
@@ -801,6 +832,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -820,8 +852,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -1018,13 +1052,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -1079,6 +1117,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1127,23 +1166,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1207,6 +1232,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1236,8 +1265,8 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
 # CONFIG_REISERFS_FS_SECURITY is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 CONFIG_OCFS2_FS=m
 CONFIG_OCFS2_FS_O2CB=m
 CONFIG_OCFS2_FS_STATS=y
@@ -1245,6 +1274,8 @@ CONFIG_OCFS2_DEBUG_MASKLOG=y
 # CONFIG_OCFS2_DEBUG_FS is not set
 # CONFIG_OCFS2_FS_POSIX_ACL is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1318,6 +1349,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1409,6 +1441,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1434,10 +1467,14 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_OBJECTS is not set
 # CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1449,7 +1486,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1463,17 +1499,16 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_PREEMPT_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1482,9 +1517,13 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
@@ -1505,7 +1544,6 @@ CONFIG_SECURITY_NETWORK=y
 # CONFIG_SECURITY_NETWORK_XFRM is not set
 # CONFIG_SECURITY_PATH is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
 # CONFIG_SECURITY_TOMOYO is not set
 CONFIG_CRYPTO=y
 
index 74f7f7c6fdc45d326222fd5e6c396cd13fee6cba..aece6bb5f733d5610c24e8702a31d83e533febc6 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:50 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:47 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 # CONFIG_PPC_85xx is not set
 CONFIG_PPC_8xx=y
 # CONFIG_40x is not set
@@ -27,15 +27,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -49,12 +50,14 @@ CONFIG_OF=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 CONFIG_REDBOOT=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -101,7 +104,6 @@ CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -114,8 +116,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -129,13 +138,18 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_BASE_SMALL=1
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -220,6 +234,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_MATH_EMULATION is not set
 # CONFIG_8XX_MINIMAL_FPEMU is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -239,9 +254,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -280,6 +295,7 @@ CONFIG_PAGE_OFFSET=0xc0000000
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
@@ -336,6 +352,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -353,7 +370,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -452,6 +473,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 #
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 # CONFIG_BLK_DEV is not set
 # CONFIG_MISC_DEVICES is not set
@@ -469,7 +491,6 @@ CONFIG_HAVE_IDE=y
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -508,6 +529,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
 CONFIG_FS_ENET_HAS_FEC=y
@@ -556,11 +578,11 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 #
 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_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_PS2_ALPS=y
@@ -622,6 +644,11 @@ CONFIG_GEN_RTC=y
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -644,22 +671,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -685,6 +697,10 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -696,12 +712,15 @@ CONFIG_VIDEO_OUTPUT_CONTROL=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
@@ -818,6 +837,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -846,6 +866,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_SLUB_STATS is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -857,7 +880,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -870,16 +892,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -888,9 +909,13 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
index 9ffa8de92803e5860cdfc721a2b90dbcd5b384f2..8105360d53f4d32a50e7a1d4d0ea598c900e6049 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:51 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:48 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_NOT_COHERENT_CACHE=y
 CONFIG_CHECK_CACHE_COHERENCY=y
@@ -32,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -54,11 +57,13 @@ CONFIG_OF=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -118,7 +123,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -131,16 +135,23 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
 # CONFIG_SLOB is not set
 CONFIG_PROFILING=y
 CONFIG_TRACEPOINTS=y
-# CONFIG_MARKERS is not set
+CONFIG_MARKERS=y
 CONFIG_OPROFILE=m
 CONFIG_HAVE_OPROFILE=y
 CONFIG_KPROBES=y
@@ -150,6 +161,11 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -162,7 +178,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -258,6 +274,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -279,9 +296,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -331,6 +348,7 @@ CONFIG_PAGE_OFFSET=0xc0000000
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0xc0000000
+CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
@@ -583,6 +601,7 @@ CONFIG_LLC=m
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 CONFIG_NET_SCHED=y
 
 #
@@ -663,7 +682,11 @@ CONFIG_WIRELESS_OLD_REGULATORY=y
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -772,6 +795,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=m
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -816,10 +840,6 @@ CONFIG_BLK_DEV_SR=m
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
@@ -836,6 +856,7 @@ CONFIG_SCSI_ISCSI_ATTRS=m
 CONFIG_SCSI_SRP_ATTRS=m
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
 CONFIG_BLK_DEV_3W_XXXX_RAID=m
 CONFIG_SCSI_3W_9XXX=m
 CONFIG_SCSI_ACARD=m
@@ -854,6 +875,7 @@ CONFIG_AIC79XX_RESET_DELAY_MS=15000
 CONFIG_AIC79XX_DEBUG_MASK=0
 # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 CONFIG_SCSI_ARCMSR=m
@@ -875,7 +897,6 @@ CONFIG_SCSI_GDTH=m
 CONFIG_SCSI_IPS=m
 CONFIG_SCSI_INITIO=m
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 CONFIG_SCSI_SYM53C8XX_2=m
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
@@ -903,14 +924,17 @@ CONFIG_SCSI_LPFC=m
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 # CONFIG_MACVLAN is not set
@@ -957,6 +981,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -976,6 +1001,7 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_MV643XX_ETH=y
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
@@ -1177,13 +1203,17 @@ CONFIG_I2C_MV64XXX=m
 CONFIG_SENSORS_PCF8574=m
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -1238,6 +1268,7 @@ CONFIG_SENSORS_SMSC47M1=m
 CONFIG_SENSORS_SMSC47B397=m
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 CONFIG_SENSORS_VIA686A=m
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1266,7 +1297,6 @@ CONFIG_SOFT_WATCHDOG=m
 #
 CONFIG_PCIPCWATCHDOG=m
 CONFIG_WDTPCI=m
-CONFIG_WDT_501_PCI=y
 
 #
 # USB-based Watchdog Cards
@@ -1289,23 +1319,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1354,6 +1370,7 @@ CONFIG_USB_MON=m
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=m
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1362,9 +1379,9 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=m
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1545,6 +1562,10 @@ CONFIG_DMADEVICES=y
 #
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1563,11 +1584,12 @@ CONFIG_FS_MBCACHE=m
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1652,6 +1674,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1764,6 +1787,7 @@ CONFIG_HAS_DMA=y
 CONFIG_CHECK_SIGNATURE=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1794,6 +1818,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 CONFIG_DEBUG_SPINLOCK=y
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 CONFIG_STACKTRACE=y
@@ -1807,7 +1834,6 @@ CONFIG_DEBUG_MEMORY_INIT=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_KPROBES_SANITY_TEST is not set
@@ -1824,30 +1850,34 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_RING_BUFFER_BENCHMARK is not set
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 CONFIG_DEBUG_STACKOVERFLOW=y
 CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
@@ -1869,7 +1899,6 @@ CONFIG_SECURITY_NETWORK=y
 # CONFIG_SECURITY_NETWORK_XFRM is not set
 # CONFIG_SECURITY_PATH is not set
 # CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
index 04915c3a43f666ebed6742fc6956c8fbf0aab8d0..0aa5b43ffeb2db73c9b3d51b174bd9287093f57a 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:52 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:49 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -53,11 +56,13 @@ CONFIG_OF=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -99,7 +104,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -112,8 +116,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -127,6 +138,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -134,7 +149,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
@@ -213,6 +228,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -228,9 +244,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -300,6 +316,7 @@ CONFIG_IP_PNP_BOOTP=y
 # 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
@@ -380,7 +397,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 
@@ -485,6 +506,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -520,13 +542,17 @@ CONFIG_HAVE_IDE=y
 #
 
 #
-# A new alternative FireWire stack is available with EXPERIMENTAL=y
+# You can enable one or both FireWire driver stacks.
 #
+
+#
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -573,6 +599,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
@@ -594,8 +621,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 # CONFIG_FSL_PQ_MDIO is not set
 # CONFIG_GIANFAR is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_JME is not set
@@ -685,6 +714,10 @@ CONFIG_HW_RANDOM=y
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -728,22 +761,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -771,6 +789,10 @@ CONFIG_DAB=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -787,9 +809,10 @@ CONFIG_JBD=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -935,6 +958,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -960,6 +984,9 @@ CONFIG_DEBUG_KERNEL=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -971,7 +998,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -985,22 +1011,23 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index c2a439595f4d7f0d153cf36f537584ec3b1d5347..2c292e25cc018a3ec723337db009eae2903f07aa 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:53 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:49 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 # CONFIG_PPC_85xx is not set
 CONFIG_PPC_8xx=y
 # CONFIG_40x is not set
@@ -27,15 +27,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -49,11 +50,13 @@ CONFIG_OF=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -100,7 +103,6 @@ CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -113,8 +115,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -128,13 +137,17 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_BASE_SMALL=1
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -220,6 +233,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_MATH_EMULATION is not set
 CONFIG_8XX_MINIMAL_FPEMU=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -239,9 +253,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -280,6 +294,7 @@ CONFIG_PAGE_OFFSET=0xc0000000
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
@@ -336,6 +351,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -353,7 +369,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -452,6 +472,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 #
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 # CONFIG_BLK_DEV is not set
 # CONFIG_MISC_DEVICES is not set
@@ -469,7 +490,6 @@ CONFIG_HAVE_IDE=y
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -508,6 +528,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
 CONFIG_FS_ENET_HAS_FEC=y
@@ -579,6 +600,11 @@ CONFIG_GEN_RTC=y
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -602,22 +628,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -642,6 +653,10 @@ CONFIG_DAB=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -653,12 +668,15 @@ CONFIG_DAB=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
@@ -775,6 +793,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -803,6 +822,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_SLUB_STATS is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -814,7 +836,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -827,16 +848,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -844,6 +864,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index a4053ab9e2447b0bad498e9ae3a8c3b583c44e38..45671e7dd2c7fc9d496c809fd07445e292727d4d 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:54 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:50 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -52,11 +55,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -114,7 +119,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -127,9 +131,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_COMPAT_BRK is not set
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -143,6 +154,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -155,7 +170,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -237,6 +252,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -257,9 +273,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -480,6 +496,7 @@ CONFIG_IP_NF_ARP_MANGLE=m
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -498,7 +515,11 @@ CONFIG_WIRELESS_OLD_REGULATORY=y
 CONFIG_WIRELESS_EXT=y
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -647,7 +668,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 CONFIG_EEPROM_LEGACY=m
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -670,10 +693,6 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_BLK_DEV_SR is not set
 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=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -691,6 +710,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -699,6 +719,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -718,7 +739,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -802,14 +822,17 @@ CONFIG_PATA_SIL680=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -846,6 +869,7 @@ CONFIG_TULIP_MMIO=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -865,8 +889,10 @@ CONFIG_R8169=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 # CONFIG_FSL_PQ_MDIO is not set
 # CONFIG_GIANFAR is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -1074,13 +1100,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -1135,6 +1165,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1169,23 +1200,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1245,6 +1262,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1254,9 +1272,9 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1423,6 +1441,7 @@ CONFIG_RTC_DRV_RS5C372=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1450,6 +1469,10 @@ CONFIG_RTC_DRV_RS5C372=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1469,14 +1492,16 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 CONFIG_XFS_FS=m
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_POSIX_ACL is not set
 # CONFIG_XFS_RT is not set
 # CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1548,6 +1573,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
@@ -1578,7 +1604,7 @@ CONFIG_CIFS=m
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-CONFIG_NLS=m
+CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
 CONFIG_NLS_CODEPAGE_437=m
 # CONFIG_NLS_CODEPAGE_737 is not set
@@ -1645,6 +1671,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1675,6 +1702,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1686,7 +1716,6 @@ CONFIG_DEBUG_MEMORY_INIT=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1700,16 +1729,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1717,6 +1745,8 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index 31e1df665157d4dc4ae982cff82e20e9df4338f2..e9491c1c3f31f9d6e69838e4dbed36fa488e45d6 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:55 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:51 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -53,6 +56,7 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 CONFIG_HIBERNATE_32=y
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
@@ -60,6 +64,7 @@ CONFIG_ARCH_HIBERNATION_POSSIBLE=y
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -105,7 +110,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -119,8 +123,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -134,6 +145,11 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -141,7 +157,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
@@ -225,6 +241,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -240,9 +257,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -313,6 +330,7 @@ CONFIG_IP_PNP_BOOTP=y
 # 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
@@ -374,7 +392,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 
@@ -484,6 +506,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -523,13 +546,17 @@ CONFIG_HAVE_IDE=y
 #
 
 #
-# A new alternative FireWire stack is available with EXPERIMENTAL=y
+# You can enable one or both FireWire driver stacks.
 #
+
+#
+# See the help texts for more information.
+#
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -577,6 +604,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_FS_ENET=y
 CONFIG_FS_ENET_HAS_SCC=y
@@ -654,6 +682,10 @@ CONFIG_HW_RANDOM=y
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -697,22 +729,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -740,6 +757,10 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -757,9 +778,10 @@ CONFIG_JBD=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -916,6 +938,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -941,6 +964,9 @@ CONFIG_DEBUG_KERNEL=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -952,7 +978,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -966,16 +991,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -983,9 +1007,12 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
index 24fa90792c54219c4a6954999ecc0475c0b1f7e1..1ae85a3b29423b03cd3b7b2f2ff94eb8a41f92ff 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:55 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:52 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 # CONFIG_PPC_85xx is not set
 CONFIG_PPC_8xx=y
 # CONFIG_40x is not set
@@ -27,15 +27,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -48,11 +49,13 @@ CONFIG_OF=y
 # CONFIG_PPC_UDBG_16550 is not set
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -102,7 +105,6 @@ CONFIG_EMBEDDED=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 # CONFIG_BUG is not set
@@ -115,7 +117,14 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -129,6 +138,11 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -136,7 +150,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=1
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -222,6 +236,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -241,9 +256,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -281,6 +296,7 @@ CONFIG_PAGE_OFFSET=0xc0000000
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
@@ -342,6 +358,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -359,7 +376,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -463,6 +484,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 #
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -492,7 +514,6 @@ CONFIG_HAVE_IDE=y
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -531,6 +552,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_FS_ENET=y
 CONFIG_FS_ENET_HAS_SCC=y
 # CONFIG_FS_ENET_HAS_FEC is not set
@@ -602,6 +624,11 @@ CONFIG_GEN_RTC=y
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -625,22 +652,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -665,6 +677,10 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -687,10 +703,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -823,6 +841,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -844,24 +863,14 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_IRQSTACKS is not set
 # CONFIG_VIRQ_DEBUG is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
index 642ab67c8431218c678d5c498e56728f06d66e0c..f23428c3b34e1764bfebcaa8df514297c05b58fb 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:56 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:53 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -52,11 +55,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -106,7 +111,6 @@ CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -119,9 +123,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -134,6 +145,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -141,7 +156,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -220,6 +235,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -240,9 +256,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -348,6 +364,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -365,7 +382,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -385,6 +406,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -416,6 +438,7 @@ CONFIG_MISC_DEVICES=y
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -438,10 +461,6 @@ CONFIG_BLK_DEV_SD=y
 # 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
@@ -458,6 +477,7 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -466,6 +486,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -485,7 +506,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -568,14 +588,17 @@ CONFIG_SATA_MV=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -642,6 +665,7 @@ CONFIG_8139TOO=y
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -663,7 +687,9 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_TSI108_ETH=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -785,6 +811,11 @@ CONFIG_GEN_RTC=y
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -824,22 +855,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -896,6 +912,10 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -915,11 +935,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1038,6 +1059,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1063,22 +1085,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index cb966ca2ce89b9384e548582dd4bdb249bb4ad46..02716f72db6fc54745e045cf88f260a79c8bcffe 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:57 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:54 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -53,11 +56,13 @@ CONFIG_OF=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -99,7 +104,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -112,9 +116,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -128,6 +139,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -135,7 +150,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
@@ -216,6 +231,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -231,9 +247,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -303,6 +319,7 @@ CONFIG_IP_PNP_BOOTP=y
 # 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
@@ -383,7 +400,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 
@@ -489,6 +510,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -524,13 +546,17 @@ CONFIG_HAVE_IDE=y
 #
 
 #
-# A new alternative FireWire stack is available with EXPERIMENTAL=y
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -577,6 +603,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
@@ -598,8 +625,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 # CONFIG_FSL_PQ_MDIO is not set
 # CONFIG_GIANFAR is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_JME is not set
@@ -671,12 +700,13 @@ CONFIG_INPUT_EVDEV=y
 #
 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_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
-# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_PS2_ALPS=y
@@ -741,6 +771,10 @@ CONFIG_HW_RANDOM=y
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -784,22 +818,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -828,6 +847,10 @@ CONFIG_DAB=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -847,9 +870,10 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -998,6 +1022,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1028,6 +1053,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1039,7 +1067,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1053,22 +1080,23 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index 433c303eb82b76efd4a517527634406e334e74a6..4a96cb6925b49f6e514397fe1895e278cbc51ae0 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:21:58 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:55 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_FSL_EMB_PERFMON is not set
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -31,15 +33,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -54,6 +57,7 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 CONFIG_REDBOOT=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
@@ -61,6 +65,7 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -110,7 +115,6 @@ CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -123,8 +127,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -138,6 +149,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -150,7 +165,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -192,6 +207,7 @@ CONFIG_MPC837x_MDS=y
 CONFIG_MPC837x_RDB=y
 CONFIG_SBC834x=y
 CONFIG_ASP834x=y
+# CONFIG_KMETER1 is not set
 CONFIG_PPC_MPC831x=y
 CONFIG_PPC_MPC832x=y
 CONFIG_PPC_MPC834x=y
@@ -241,6 +257,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -261,9 +278,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -374,6 +391,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -391,7 +409,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -507,6 +529,7 @@ CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -542,7 +565,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -565,10 +590,6 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_BLK_DEV_SR is not set
 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 is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -586,6 +607,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -594,6 +616,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -613,7 +636,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -697,14 +719,17 @@ CONFIG_ATA_SFF=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -751,6 +776,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -770,11 +796,13 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -965,13 +993,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -1050,6 +1082,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1104,24 +1137,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1159,7 +1177,7 @@ CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1176,10 +1194,11 @@ CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1205,6 +1224,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1291,6 +1311,10 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1310,10 +1334,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1377,6 +1403,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1413,7 +1440,46 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 # CONFIG_SYSV68_PARTITION is not set
-# CONFIG_NLS is not set
+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_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
 # CONFIG_DLM is not set
 CONFIG_UCC_FAST=y
 CONFIG_UCC=y
@@ -1438,6 +1504,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1461,22 +1528,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index c162724fed4f76f4aa1272b5437589ececf5fc7c..ada595898af117f2653875d04bef69dd74b0eec5 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Tue Apr 21 15:40:23 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:55 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -34,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -57,11 +58,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -116,7 +119,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -129,9 +131,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -146,6 +155,11 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -158,7 +172,7 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -191,6 +205,7 @@ CONFIG_MPC8536_DS=y
 CONFIG_MPC85xx_DS=y
 CONFIG_SOCRATES=y
 CONFIG_KSI8560=y
+# CONFIG_XES_MPC85xx is not set
 CONFIG_STX_GP3=y
 CONFIG_TQM8540=y
 CONFIG_TQM8541=y
@@ -241,7 +256,9 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
-# CONFIG_IOMMU_HELPER is not set
+CONFIG_IOMMU_HELPER=y
+CONFIG_SWIOTLB=y
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -260,9 +277,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -296,7 +313,8 @@ CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_IOV is not set
 # CONFIG_PCCARD is not set
 # CONFIG_HOTPLUG_PCI is not set
-# CONFIG_HAS_RAPIDIO is not set
+CONFIG_HAS_RAPIDIO=y
+# CONFIG_RAPIDIO is not set
 
 #
 # Advanced setup
@@ -406,6 +424,7 @@ CONFIG_SCTP_HMAC_MD5=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -424,7 +443,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -450,6 +473,7 @@ CONFIG_EXTRA_FIRMWARE=""
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -485,7 +509,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 CONFIG_EEPROM_LEGACY=y
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -509,10 +535,6 @@ CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 CONFIG_SCSI_LOGGING=y
@@ -530,6 +552,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -538,6 +561,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -557,7 +581,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -641,14 +664,17 @@ CONFIG_PATA_ALI=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -695,6 +721,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_FS_ENET=y
 CONFIG_FS_ENET_HAS_SCC=y
@@ -718,11 +745,13 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -897,6 +926,7 @@ CONFIG_I2C_HELPER_AUTO=y
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
 CONFIG_I2C_CPM=m
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
@@ -927,13 +957,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -987,76 +1021,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-CONFIG_DVB_CORE=m
-CONFIG_VIDEO_MEDIA=m
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=m
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=m
-CONFIG_MEDIA_TUNER_TDA8290=m
-CONFIG_MEDIA_TUNER_TDA9887=m
-CONFIG_MEDIA_TUNER_TEA5761=m
-CONFIG_MEDIA_TUNER_TEA5767=m
-CONFIG_MEDIA_TUNER_MT20XX=m
-CONFIG_MEDIA_TUNER_XC2028=m
-CONFIG_MEDIA_TUNER_XC5000=m
-CONFIG_MEDIA_TUNER_MC44S803=m
-# CONFIG_DVB_DYNAMIC_MINORS is not set
-CONFIG_DVB_CAPTURE_DRIVERS=y
-
-#
-# Supported SAA7146 based PCI Adapters
-#
-# CONFIG_TTPCI_EEPROM is not set
-# CONFIG_DVB_BUDGET_CORE is not set
-
-#
-# Supported USB Adapters
-#
-# CONFIG_DVB_USB is not set
-# CONFIG_DVB_TTUSB_BUDGET is not set
-# CONFIG_DVB_TTUSB_DEC is not set
-# CONFIG_DVB_SIANO_SMS1XXX is not set
-
-#
-# Supported FlexCopII (B2C2) Adapters
-#
-# CONFIG_DVB_B2C2_FLEXCOP is not set
-
-#
-# Supported BT878 Adapters
-#
-
-#
-# Supported Pluto2 Adapters
-#
-# CONFIG_DVB_PLUTO2 is not set
-
-#
-# Supported SDMC DM1105 Adapters
-#
-# CONFIG_DVB_DM1105 is not set
-
-#
-# Supported DVB Frontends
-#
-# CONFIG_DVB_FE_CUSTOMISE is not set
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1096,6 +1063,11 @@ CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_AC97_CODEC=y
 CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
@@ -1122,6 +1094,7 @@ CONFIG_SND_PCI=y
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
 # CONFIG_SND_CS5530 is not set
+# CONFIG_SND_CTXFI is not set
 # CONFIG_SND_DARLA20 is not set
 # CONFIG_SND_GINA20 is not set
 # CONFIG_SND_LAYLA20 is not set
@@ -1152,6 +1125,7 @@ CONFIG_SND_PCI=y
 CONFIG_SND_INTEL8X0=y
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
 # CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -1196,7 +1170,7 @@ CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1213,10 +1187,11 @@ CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1242,6 +1217,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1251,9 +1227,9 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1352,8 +1328,6 @@ CONFIG_EDAC=y
 # CONFIG_EDAC_DEBUG is not set
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_MPC85XX=y
-# CONFIG_EDAC_AMD8131 is not set
-# CONFIG_EDAC_AMD8111 is not set
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -1385,6 +1359,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1425,6 +1400,10 @@ CONFIG_DMA_ENGINE=y
 # CONFIG_DMATEST is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1445,11 +1424,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1524,6 +1504,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
@@ -1628,6 +1609,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1658,6 +1640,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1670,7 +1655,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1684,16 +1668,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1702,9 +1685,13 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
index 1aa1c508d6007050f22cc0385b5559fcbcd31c71..db082ce5a1c5c05de1edc900724ee0caeb1cb2e8 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Tue Apr 21 15:41:18 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:56 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 CONFIG_PPC_85xx=y
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
@@ -35,15 +35,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -58,11 +59,13 @@ CONFIG_PPC_UDBG_16550=y
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -117,7 +120,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -130,9 +132,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -148,6 +157,11 @@ CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -161,7 +175,7 @@ CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -194,6 +208,7 @@ CONFIG_MPC8536_DS=y
 CONFIG_MPC85xx_DS=y
 CONFIG_SOCRATES=y
 CONFIG_KSI8560=y
+# CONFIG_XES_MPC85xx is not set
 CONFIG_STX_GP3=y
 CONFIG_TQM8540=y
 CONFIG_TQM8541=y
@@ -244,7 +259,9 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
-# CONFIG_IOMMU_HELPER is not set
+CONFIG_IOMMU_HELPER=y
+CONFIG_SWIOTLB=y
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -264,9 +281,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -300,7 +317,8 @@ CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_IOV is not set
 # CONFIG_PCCARD is not set
 # CONFIG_HOTPLUG_PCI is not set
-# CONFIG_HAS_RAPIDIO is not set
+CONFIG_HAS_RAPIDIO=y
+# CONFIG_RAPIDIO is not set
 
 #
 # Advanced setup
@@ -410,6 +428,7 @@ CONFIG_SCTP_HMAC_MD5=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -428,7 +447,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -454,6 +477,7 @@ CONFIG_EXTRA_FIRMWARE=""
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -489,7 +513,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 CONFIG_EEPROM_LEGACY=y
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -513,10 +539,6 @@ CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 CONFIG_SCSI_LOGGING=y
@@ -534,6 +556,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -542,6 +565,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -561,7 +585,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -645,14 +668,17 @@ CONFIG_PATA_ALI=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -699,6 +725,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_FS_ENET=y
 CONFIG_FS_ENET_HAS_SCC=y
@@ -722,11 +749,13 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
 CONFIG_UCC_GETH=y
 # CONFIG_UGETH_MAGIC_PACKET is not set
 # CONFIG_UGETH_TX_ON_DEMAND is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -901,6 +930,7 @@ CONFIG_I2C_HELPER_AUTO=y
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
 CONFIG_I2C_CPM=m
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_GPIO is not set
 CONFIG_I2C_MPC=y
 # CONFIG_I2C_OCORES is not set
@@ -931,13 +961,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -991,76 +1025,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-CONFIG_DVB_CORE=m
-CONFIG_VIDEO_MEDIA=m
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=m
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=m
-CONFIG_MEDIA_TUNER_TDA8290=m
-CONFIG_MEDIA_TUNER_TDA9887=m
-CONFIG_MEDIA_TUNER_TEA5761=m
-CONFIG_MEDIA_TUNER_TEA5767=m
-CONFIG_MEDIA_TUNER_MT20XX=m
-CONFIG_MEDIA_TUNER_XC2028=m
-CONFIG_MEDIA_TUNER_XC5000=m
-CONFIG_MEDIA_TUNER_MC44S803=m
-# CONFIG_DVB_DYNAMIC_MINORS is not set
-CONFIG_DVB_CAPTURE_DRIVERS=y
-
-#
-# Supported SAA7146 based PCI Adapters
-#
-# CONFIG_TTPCI_EEPROM is not set
-# CONFIG_DVB_BUDGET_CORE is not set
-
-#
-# Supported USB Adapters
-#
-# CONFIG_DVB_USB is not set
-# CONFIG_DVB_TTUSB_BUDGET is not set
-# CONFIG_DVB_TTUSB_DEC is not set
-# CONFIG_DVB_SIANO_SMS1XXX is not set
-
-#
-# Supported FlexCopII (B2C2) Adapters
-#
-# CONFIG_DVB_B2C2_FLEXCOP is not set
-
-#
-# Supported BT878 Adapters
-#
-
-#
-# Supported Pluto2 Adapters
-#
-# CONFIG_DVB_PLUTO2 is not set
-
-#
-# Supported SDMC DM1105 Adapters
-#
-# CONFIG_DVB_DM1105 is not set
-
-#
-# Supported DVB Frontends
-#
-# CONFIG_DVB_FE_CUSTOMISE is not set
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1100,6 +1067,11 @@ CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_AC97_CODEC=y
 CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
@@ -1126,6 +1098,7 @@ CONFIG_SND_PCI=y
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
 # CONFIG_SND_CS5530 is not set
+# CONFIG_SND_CTXFI is not set
 # CONFIG_SND_DARLA20 is not set
 # CONFIG_SND_GINA20 is not set
 # CONFIG_SND_LAYLA20 is not set
@@ -1156,6 +1129,7 @@ CONFIG_SND_PCI=y
 CONFIG_SND_INTEL8X0=y
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
 # CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -1200,7 +1174,7 @@ CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1217,10 +1191,11 @@ CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1246,6 +1221,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1255,9 +1231,9 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1356,8 +1332,6 @@ CONFIG_EDAC=y
 # CONFIG_EDAC_DEBUG is not set
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_MPC85XX=y
-# CONFIG_EDAC_AMD8131 is not set
-# CONFIG_EDAC_AMD8111 is not set
 CONFIG_RTC_LIB=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_HCTOSYS=y
@@ -1389,6 +1363,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1429,6 +1404,10 @@ CONFIG_DMA_ENGINE=y
 # CONFIG_DMATEST is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1449,11 +1428,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1528,6 +1508,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
@@ -1632,6 +1613,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1662,6 +1644,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1674,7 +1659,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1688,16 +1672,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1706,9 +1689,13 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
index 3add6f62b21e8512f3e8087893aaa095d6f7a6f0..6809b61ed3de35c2f143eead2507a27b6e65e1f0 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:00 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:57 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 # CONFIG_PPC_85xx is not set
 CONFIG_PPC_8xx=y
 # CONFIG_40x is not set
@@ -27,15 +27,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -48,11 +49,13 @@ CONFIG_OF=y
 # CONFIG_PPC_UDBG_16550 is not set
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -98,7 +101,6 @@ CONFIG_EMBEDDED=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 # CONFIG_BUG is not set
@@ -111,8 +113,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -126,6 +135,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -133,7 +146,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=1
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -219,6 +232,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_MATH_EMULATION=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -238,9 +252,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -278,6 +292,7 @@ CONFIG_PAGE_OFFSET=0xc0000000
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
@@ -339,6 +354,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -356,7 +372,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -374,6 +394,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -407,7 +428,6 @@ CONFIG_HAVE_IDE=y
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -446,6 +466,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_FS_ENET=y
 CONFIG_FS_ENET_HAS_SCC=y
 CONFIG_FS_ENET_HAS_FEC=y
@@ -453,6 +474,7 @@ CONFIG_FS_ENET_MDIO_FEC=y
 CONFIG_NETDEV_1000=y
 # CONFIG_FSL_PQ_MDIO is not set
 # CONFIG_GIANFAR is not set
+# CONFIG_MV643XX_ETH is not set
 CONFIG_NETDEV_10000=y
 
 #
@@ -496,11 +518,11 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 #
 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_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_PS2_ALPS=y
@@ -562,6 +584,11 @@ CONFIG_GEN_RTC=y
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -597,22 +624,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -664,6 +676,10 @@ CONFIG_USB_SUPPORT=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -685,10 +701,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -808,6 +826,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -831,22 +850,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_PPC_EARLY_DEBUG is not set
index 5bb1b8eb0b490dc6e4f4032041db4d64ba5257ab..0e8684a3138dfcade29e658f6981c6931e46864f 100644 (file)
@@ -1,26 +1,28 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:00 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:58 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_PHYS_64BIT is not set
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PPC32=y
@@ -32,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -55,11 +58,13 @@ CONFIG_PPC_UDBG_16550=y
 CONFIG_GENERIC_TBSYNC=y
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -114,7 +119,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -127,9 +131,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -144,6 +155,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -157,7 +172,7 @@ CONFIG_MODVERSIONS=y
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_STOP_MACHINE=y
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -236,7 +251,9 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=m
-# CONFIG_IOMMU_HELPER is not set
+CONFIG_IOMMU_HELPER=y
+CONFIG_SWIOTLB=y
+CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -258,9 +275,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -403,6 +420,7 @@ CONFIG_SCTP_HMAC_MD5=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -421,7 +439,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -447,6 +469,7 @@ CONFIG_EXTRA_FIRMWARE=""
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -482,7 +505,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 CONFIG_EEPROM_LEGACY=y
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -506,10 +531,6 @@ CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 CONFIG_SCSI_LOGGING=y
@@ -527,6 +548,7 @@ CONFIG_SCSI_WAIT_SCAN=m
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -535,6 +557,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -554,7 +577,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -638,14 +660,17 @@ CONFIG_PATA_ALI=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=y
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -692,6 +717,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -711,8 +737,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_FSL_PQ_MDIO=y
 CONFIG_GIANFAR=y
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -913,13 +941,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -973,76 +1005,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-CONFIG_DVB_CORE=m
-CONFIG_VIDEO_MEDIA=m
-
-#
-# Multimedia drivers
-#
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=m
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=m
-CONFIG_MEDIA_TUNER_TDA8290=m
-CONFIG_MEDIA_TUNER_TDA9887=m
-CONFIG_MEDIA_TUNER_TEA5761=m
-CONFIG_MEDIA_TUNER_TEA5767=m
-CONFIG_MEDIA_TUNER_MT20XX=m
-CONFIG_MEDIA_TUNER_XC2028=m
-CONFIG_MEDIA_TUNER_XC5000=m
-CONFIG_MEDIA_TUNER_MC44S803=m
-# CONFIG_DVB_DYNAMIC_MINORS is not set
-CONFIG_DVB_CAPTURE_DRIVERS=y
-
-#
-# Supported SAA7146 based PCI Adapters
-#
-# CONFIG_TTPCI_EEPROM is not set
-# CONFIG_DVB_BUDGET_CORE is not set
-
-#
-# Supported USB Adapters
-#
-# CONFIG_DVB_USB is not set
-# CONFIG_DVB_TTUSB_BUDGET is not set
-# CONFIG_DVB_TTUSB_DEC is not set
-# CONFIG_DVB_SIANO_SMS1XXX is not set
-
-#
-# Supported FlexCopII (B2C2) Adapters
-#
-# CONFIG_DVB_B2C2_FLEXCOP is not set
-
-#
-# Supported BT878 Adapters
-#
-
-#
-# Supported Pluto2 Adapters
-#
-# CONFIG_DVB_PLUTO2 is not set
-
-#
-# Supported SDMC DM1105 Adapters
-#
-# CONFIG_DVB_DM1105 is not set
-
-#
-# Supported DVB Frontends
-#
-# CONFIG_DVB_FE_CUSTOMISE is not set
-CONFIG_DAB=y
-# CONFIG_USB_DABUSB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1082,6 +1047,11 @@ CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 CONFIG_SND_VMASTER=y
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 CONFIG_SND_AC97_CODEC=y
 CONFIG_SND_DRIVERS=y
 # CONFIG_SND_DUMMY is not set
@@ -1108,6 +1078,7 @@ CONFIG_SND_PCI=y
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_CS46XX is not set
 # CONFIG_SND_CS5530 is not set
+# CONFIG_SND_CTXFI is not set
 # CONFIG_SND_DARLA20 is not set
 # CONFIG_SND_GINA20 is not set
 # CONFIG_SND_LAYLA20 is not set
@@ -1138,6 +1109,7 @@ CONFIG_SND_PCI=y
 CONFIG_SND_INTEL8X0=y
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LX6464ES is not set
 # CONFIG_SND_MAESTRO3 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -1182,7 +1154,7 @@ CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
-# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_DRAGONRISE is not set
 CONFIG_HID_EZKEY=y
 # CONFIG_HID_KYE is not set
 CONFIG_HID_GYRATION=y
@@ -1199,10 +1171,11 @@ CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
 # CONFIG_HID_TOPSEED is not set
-CONFIG_THRUSTMASTER_FF=m
-CONFIG_ZEROPLUS_FF=m
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -1228,6 +1201,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1237,9 +1211,9 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
 CONFIG_USB_OHCI_HCD_PCI=y
 CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1360,6 +1334,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1387,6 +1362,10 @@ CONFIG_RTC_DRV_CMOS=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1406,11 +1385,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1485,6 +1465,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
@@ -1586,6 +1567,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1616,6 +1598,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1628,7 +1613,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1642,16 +1626,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -1659,6 +1642,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index 42e64ebc279d08f92ef8942dc7f94778c5ccf31d..dbe8e869a827f79a381dcfafb5601c3a9662bdb4 100644 (file)
@@ -1,14 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:01 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:31:59 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-# CONFIG_6xx is not set
+# CONFIG_PPC_BOOK3S_32 is not set
 # CONFIG_PPC_85xx is not set
 CONFIG_PPC_8xx=y
 # CONFIG_40x is not set
@@ -27,15 +27,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -49,11 +50,13 @@ CONFIG_OF=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -100,7 +103,6 @@ CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -113,8 +115,15 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 # CONFIG_VM_EVENT_COUNTERS is not set
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -128,13 +137,17 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
 CONFIG_BASE_SMALL=1
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -227,6 +240,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_MATH_EMULATION is not set
 CONFIG_8XX_MINIMAL_FPEMU=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -246,9 +260,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -287,6 +301,7 @@ CONFIG_PAGE_OFFSET=0xc0000000
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
@@ -343,6 +358,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -360,7 +376,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -463,6 +483,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 #
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 # CONFIG_BLK_DEV is not set
 # CONFIG_MISC_DEVICES is not set
@@ -480,7 +501,6 @@ CONFIG_HAVE_IDE=y
 # CONFIG_MD is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -519,6 +539,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
 CONFIG_FS_ENET_HAS_FEC=y
@@ -590,6 +611,11 @@ CONFIG_GEN_RTC=y
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -613,22 +639,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -653,6 +664,10 @@ CONFIG_DAB=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -664,12 +679,15 @@ CONFIG_DAB=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
@@ -786,6 +804,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -814,6 +833,9 @@ CONFIG_SCHED_DEBUG=y
 # CONFIG_SLUB_STATS is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -825,7 +847,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -838,16 +859,15 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
@@ -855,6 +875,9 @@ CONFIG_TRACING_SUPPORT=y
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_KMEMCHECK is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index 129d80860f2a2893734b186c2e3d4c68d236ef05..ff96bb43c32d9542ac5ba0254d96cbdb2dd0f080 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:02 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:00 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
@@ -53,11 +56,13 @@ CONFIG_OF=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 CONFIG_DEFAULT_UIMAGE=y
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -103,7 +108,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -116,9 +120,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -132,6 +143,10 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -139,7 +154,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
 #
@@ -219,6 +234,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -234,9 +250,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -307,6 +323,7 @@ CONFIG_IP_PNP_BOOTP=y
 # 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
@@ -387,7 +404,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 
@@ -493,6 +514,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_GPIO=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -518,6 +540,7 @@ CONFIG_MISC_DEVICES=y
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -583,13 +606,17 @@ CONFIG_IDE_PROC_FS=y
 #
 
 #
-# A new alternative FireWire stack is available with EXPERIMENTAL=y
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
+# CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -636,6 +663,7 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_FS_ENET=y
 # CONFIG_FS_ENET_HAS_SCC is not set
@@ -657,8 +685,10 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 # CONFIG_FSL_PQ_MDIO is not set
 # CONFIG_GIANFAR is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_JME is not set
@@ -730,12 +760,13 @@ CONFIG_INPUT_EVDEV=y
 #
 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_GPIO is not set
+# CONFIG_KEYBOARD_MATRIX is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
-# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 CONFIG_MOUSE_PS2_ALPS=y
@@ -802,6 +833,10 @@ CONFIG_HW_RANDOM=y
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
@@ -845,22 +880,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-CONFIG_DAB=y
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -903,8 +923,9 @@ CONFIG_USB_GADGET_SELECTED=y
 # CONFIG_USB_GADGET_OMAP is not set
 # CONFIG_USB_GADGET_PXA25X is not set
 # CONFIG_USB_GADGET_PXA27X is not set
-# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
 # CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
 CONFIG_USB_GADGET_M66592=y
 CONFIG_USB_M66592=y
 # CONFIG_USB_GADGET_AMD5536UDC is not set
@@ -912,9 +933,11 @@ CONFIG_USB_M66592=y
 # CONFIG_USB_GADGET_CI13XXX is not set
 # CONFIG_USB_GADGET_NET2280 is not set
 # CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
 CONFIG_USB_GADGET_DUALSPEED=y
 # CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
 CONFIG_USB_ETH=y
 CONFIG_USB_ETH_RNDIS=y
 # CONFIG_USB_GADGETFS is not set
@@ -939,6 +962,10 @@ CONFIG_USB_ETH_RNDIS=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -958,9 +985,10 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1110,6 +1138,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1140,6 +1169,9 @@ CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1151,7 +1183,6 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1165,22 +1196,23 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
+CONFIG_FTRACE=y
 # CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
 # CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
 # CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
 # CONFIG_STACK_TRACER is not set
 # CONFIG_KMEMTRACE is not set
 # CONFIG_WORKQUEUE_TRACER is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
index e9f287f313fa372d46d1fe0abd11761d39b42a05..1293c465d7fa56015010822fc8f15830f850ec6d 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:03 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:01 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 CONFIG_ALTIVEC=y
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_NOT_COHERENT_CACHE=y
 CONFIG_CHECK_CACHE_COHERENCY=y
@@ -32,15 +34,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -54,11 +57,13 @@ CONFIG_OF=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -114,7 +119,6 @@ CONFIG_ANON_INODES=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -127,9 +131,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -142,6 +153,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -149,7 +164,7 @@ CONFIG_RT_MUTEXES=y
 CONFIG_BASE_SMALL=0
 # CONFIG_MODULES is not set
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -228,6 +243,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_PPC_NEED_DMA_SYNC_OPS=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
@@ -249,9 +265,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -296,6 +312,7 @@ CONFIG_PAGE_OFFSET=0xc0000000
 CONFIG_KERNEL_START=0xc0000000
 CONFIG_PHYSICAL_START=0x00000000
 CONFIG_TASK_SIZE=0xc0000000
+CONFIG_CONSISTENT_SIZE=0x00200000
 CONFIG_NET=y
 
 #
@@ -357,6 +374,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -374,7 +392,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -479,6 +501,7 @@ CONFIG_MTD_PHYSMAP_OF=y
 # CONFIG_MTD_UBI is not set
 CONFIG_OF_DEVICE=y
 CONFIG_OF_I2C=y
+CONFIG_OF_MDIO=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
@@ -514,7 +537,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -591,10 +616,6 @@ CONFIG_BLK_DEV_SD=y
 # 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
@@ -611,6 +632,7 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -619,6 +641,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -638,7 +661,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -721,7 +743,11 @@ CONFIG_SATA_MV=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
@@ -730,7 +756,6 @@ CONFIG_MACINTOSH_DRIVERS=y
 # CONFIG_MAC_EMUMOUSEBTN is not set
 # CONFIG_WINDFARM is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -797,6 +822,7 @@ CONFIG_8139TOO=y
 # CONFIG_SMSC9420 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
+# CONFIG_KS8842 is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_SC92031 is not set
 # CONFIG_ATL2 is not set
@@ -818,6 +844,7 @@ CONFIG_E1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 CONFIG_MV643XX_ETH=y
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
@@ -1007,13 +1034,17 @@ CONFIG_I2C_MV64XXX=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -1068,6 +1099,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -1102,23 +1134,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1163,6 +1181,7 @@ CONFIG_HID_BELKIN=y
 CONFIG_HID_CHERRY=y
 CONFIG_HID_CHICONY=y
 CONFIG_HID_CYPRESS=y
+CONFIG_HID_DRAGONRISE=y
 # CONFIG_DRAGONRISE_FF is not set
 CONFIG_HID_EZKEY=y
 CONFIG_HID_KYE=y
@@ -1180,9 +1199,14 @@ CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
 # CONFIG_GREENASIA_FF is not set
+CONFIG_HID_SMARTJOYPLUS=y
+# CONFIG_SMARTJOYPLUS_FF is not set
 CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
 CONFIG_THRUSTMASTER_FF=y
+CONFIG_HID_ZEROPLUS=y
 CONFIG_ZEROPLUS_FF=y
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -1207,6 +1231,7 @@ CONFIG_USB_MON=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1215,6 +1240,8 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
 # CONFIG_USB_OHCI_HCD_PPC_OF is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
@@ -1322,6 +1349,7 @@ CONFIG_RTC_DRV_MAX6900=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1349,6 +1377,10 @@ CONFIG_RTC_DRV_MAX6900=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1368,11 +1400,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1469,7 +1502,46 @@ CONFIG_MSDOS_PARTITION=y
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 # CONFIG_SYSV68_PARTITION is not set
-# CONFIG_NLS is not set
+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_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
 # CONFIG_DLM is not set
 # CONFIG_BINARY_PRINTF is not set
 
@@ -1494,6 +1566,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1519,22 +1592,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index e28e65e7a0e19ea1cc862c94360b1623fe3278ff..7de127e4ceeffbf36f4ae9e718d9b9896c733198 100644 (file)
@@ -1,13 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc5
-# Fri May 15 10:37:00 2009
+# Linux kernel version: 2.6.31-rc7
+# Mon Aug 24 17:38:50 2009
 #
 CONFIG_PPC64=y
 
 #
 # Processor support
 #
+CONFIG_PPC_BOOK3S_64=y
 CONFIG_PPC_BOOK3S=y
 # CONFIG_POWER4_ONLY is not set
 CONFIG_POWER3=y
@@ -20,6 +21,7 @@ CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_64=y
 CONFIG_PPC_MM_SLICES=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_64BIT=y
@@ -31,6 +33,7 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_HAVE_SETUP_PER_CPU_AREA=y
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
@@ -41,7 +44,6 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_ARCH_HAS_ILOG2_U64=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_ARCH_NO_VIRT_TO_BUS=y
 CONFIG_PPC=y
@@ -62,6 +64,7 @@ CONFIG_DTC=y
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -113,7 +116,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_EXTRA_PASS=y
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -126,7 +128,14 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -145,6 +154,11 @@ CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_DMA_ATTRS=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -210,7 +224,7 @@ CONFIG_PPC_CELL=y
 #
 # Cell Broadband Engine options
 #
-CONFIG_SPU_FS=y
+CONFIG_SPU_FS=m
 CONFIG_SPU_FS_64K_LS=y
 # CONFIG_SPU_TRACE is not set
 CONFIG_SPU_BASE=y
@@ -255,6 +269,7 @@ CONFIG_BINFMT_MISC=y
 CONFIG_HUGETLB_PAGE_SIZE_VARIABLE=y
 # CONFIG_IOMMU_VMERGE is not set
 CONFIG_IOMMU_HELPER=y
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -285,9 +300,9 @@ CONFIG_MIGRATION=y
 CONFIG_PHYS_ADDR_T_64BIT=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_ARCH_MEMORY_PROBE=y
 CONFIG_PPC_HAS_HASH_64K=y
 CONFIG_PPC_4K_PAGES=y
@@ -399,6 +414,7 @@ CONFIG_IPV6_NDISC_NODETYPE=y
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -433,11 +449,14 @@ CONFIG_BT_HCIBTUSB=m
 CONFIG_WIRELESS=y
 CONFIG_CFG80211=m
 # CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_DEBUGFS is not set
 # CONFIG_WIRELESS_OLD_REGULATORY is not set
 CONFIG_WIRELESS_EXT=y
 # CONFIG_WIRELESS_EXT_SYSFS is not set
 # CONFIG_LIB80211 is not set
 CONFIG_MAC80211=m
+CONFIG_MAC80211_DEFAULT_PS=y
+CONFIG_MAC80211_DEFAULT_PS_VALUE=1
 
 #
 # Rate control algorithm selection
@@ -447,7 +466,6 @@ CONFIG_MAC80211_RC_PID=y
 CONFIG_MAC80211_RC_DEFAULT_PID=y
 # CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
 CONFIG_MAC80211_RC_DEFAULT="pid"
-# CONFIG_MAC80211_MESH is not set
 # CONFIG_MAC80211_LEDS is not set
 # CONFIG_MAC80211_DEBUGFS is not set
 # CONFIG_MAC80211_DEBUG_MENU is not set
@@ -472,77 +490,7 @@ CONFIG_EXTRA_FIRMWARE=""
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 # CONFIG_CONNECTOR is not set
-CONFIG_MTD=y
-CONFIG_MTD_DEBUG=y
-CONFIG_MTD_DEBUG_VERBOSE=0
-# CONFIG_MTD_CONCAT is not set
-# CONFIG_MTD_PARTITIONS is not set
-# CONFIG_MTD_TESTS is not set
-
-#
-# User Modules And Translation Layers
-#
-# CONFIG_MTD_CHAR is not set
-CONFIG_MTD_BLKDEVS=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
-# CONFIG_SSFDC is not set
-# CONFIG_MTD_OOPS is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-# CONFIG_MTD_CFI is not set
-# CONFIG_MTD_JEDECPROBE 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_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-# CONFIG_MTD_NAND is not set
-# CONFIG_MTD_ONENAND is not set
-
-#
-# LPDDR flash memory drivers
-#
-# CONFIG_MTD_LPDDR is not set
-
-#
-# UBI - Unsorted block images
-#
-# CONFIG_MTD_UBI is not set
+# CONFIG_MTD is not set
 CONFIG_OF_DEVICE=y
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
@@ -590,10 +538,6 @@ CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=m
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -626,7 +570,6 @@ CONFIG_BLK_DEV_DM=m
 # CONFIG_DM_UEVENT is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -646,10 +589,11 @@ CONFIG_MII=m
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 CONFIG_NETDEV_1000=y
 CONFIG_GELIC_NET=y
 CONFIG_GELIC_WIRELESS=y
-CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE=y
+# CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE is not set
 # CONFIG_NETDEV_10000 is not set
 
 #
@@ -669,8 +613,7 @@ CONFIG_WLAN_80211=y
 # CONFIG_HOSTAP is not set
 # CONFIG_B43 is not set
 # CONFIG_B43LEGACY is not set
-CONFIG_ZD1211RW=m
-# CONFIG_ZD1211RW_DEBUG is not set
+# CONFIG_ZD1211RW is not set
 # CONFIG_RT2X00 is not set
 
 #
@@ -682,7 +625,7 @@ CONFIG_ZD1211RW=m
 #
 # CONFIG_USB_CATC is not set
 # CONFIG_USB_KAWETH is not set
-CONFIG_USB_PEGASUS=m
+# CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 CONFIG_USB_USBNET=m
 CONFIG_USB_NET_AX8817X=m
@@ -693,10 +636,11 @@ CONFIG_USB_NET_AX8817X=m
 # CONFIG_USB_NET_GL620A is not set
 # CONFIG_USB_NET_NET1080 is not set
 # CONFIG_USB_NET_PLUSB is not set
-CONFIG_USB_NET_MCS7830=m
+# CONFIG_USB_NET_MCS7830 is not set
 # CONFIG_USB_NET_RNDIS_HOST is not set
 # CONFIG_USB_NET_CDC_SUBSET is not set
 # CONFIG_USB_NET_ZAURUS is not set
+# CONFIG_USB_NET_INT51X1 is not set
 # CONFIG_WAN is not set
 CONFIG_PPP=m
 CONFIG_PPP_MULTILINK=y
@@ -771,8 +715,7 @@ CONFIG_DEVKMEM=y
 #
 CONFIG_UNIX98_PTYS=y
 # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_LEGACY_PTYS is not set
 # CONFIG_HVC_UDBG is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
@@ -782,6 +725,11 @@ CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_TCG_TPM is not set
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -805,22 +753,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -898,6 +831,11 @@ CONFIG_SND_SUPPORT_OLD_API=y
 CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
 # CONFIG_SND_DRIVERS is not set
 CONFIG_SND_PPC=y
 CONFIG_SND_PS3=m
@@ -930,29 +868,34 @@ CONFIG_USB_HIDDEV=y
 # Special HID drivers
 #
 # CONFIG_HID_A4TECH is not set
-# CONFIG_HID_APPLE is not set
-# CONFIG_HID_BELKIN is not set
-# CONFIG_HID_CHERRY is not set
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_CHERRY=m
 # CONFIG_HID_CHICONY is not set
 # CONFIG_HID_CYPRESS is not set
-# CONFIG_DRAGONRISE_FF is not set
-# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_DRAGONRISE is not set
+CONFIG_HID_EZKEY=m
 # CONFIG_HID_KYE is not set
 # CONFIG_HID_GYRATION is not set
 # CONFIG_HID_KENSINGTON is not set
-# CONFIG_HID_LOGITECH is not set
-# CONFIG_HID_MICROSOFT is not set
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
 # CONFIG_HID_MONTEREY is not set
 # CONFIG_HID_NTRIG is not set
 # CONFIG_HID_PANTHERLORD is not set
 # CONFIG_HID_PETALYNX is not set
 # CONFIG_HID_SAMSUNG is not set
 CONFIG_HID_SONY=m
-# CONFIG_HID_SUNPLUS is not set
-# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_SUNPLUS=m
+# CONFIG_HID_GREENASIA is not set
+CONFIG_HID_SMARTJOYPLUS=m
+# CONFIG_SMARTJOYPLUS_FF is not set
 # CONFIG_HID_TOPSEED is not set
-# CONFIG_THRUSTMASTER_FF is not set
-# CONFIG_ZEROPLUS_FF is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_ZEROPLUS is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
@@ -988,6 +931,8 @@ CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
 # CONFIG_USB_OHCI_HCD_PPC_OF is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
@@ -1115,6 +1060,10 @@ CONFIG_RTC_DRV_PS3=m
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1141,11 +1090,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1205,7 +1155,6 @@ CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
@@ -1222,6 +1171,7 @@ CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V3_ACL is not set
 CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 CONFIG_LOCKD=y
@@ -1359,7 +1309,6 @@ CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_DEBUG_LIST=y
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
-# CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
@@ -1374,31 +1323,21 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
 CONFIG_TRACING=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_IRQSOFF_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_FTRACE is not set
 # CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_PPC_EMULATED_STATS is not set
 # CONFIG_CODE_PATCHING_SELFTEST is not set
 # CONFIG_FTR_FIXUP_SELFTEST is not set
 # CONFIG_MSI_BITMAP_SELFTEST is not set
index bd4a8d435c50e9428be4c27ccb8c5b775c3caec7..28384dc010036c79cd875e7c2e6e01af70b389ac 100644 (file)
@@ -1,25 +1,27 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc3
-# Wed May 13 17:22:04 2009
+# Linux kernel version: 2.6.31-rc4
+# Wed Jul 29 23:32:01 2009
 #
 # CONFIG_PPC64 is not set
 
 #
 # Processor support
 #
-CONFIG_6xx=y
+CONFIG_PPC_BOOK3S_32=y
 # CONFIG_PPC_85xx is not set
 # CONFIG_PPC_8xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_E200 is not set
 CONFIG_PPC_BOOK3S=y
+CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 # CONFIG_ALTIVEC is not set
 CONFIG_PPC_STD_MMU=y
 CONFIG_PPC_STD_MMU_32=y
 # CONFIG_PPC_MM_SLICES is not set
+CONFIG_PPC_HAVE_PMU_SUPPORT=y
 # CONFIG_SMP is not set
 CONFIG_PPC32=y
 CONFIG_WORD_SIZE=32
@@ -30,15 +32,16 @@ CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_TIME_VSYSCALL=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
 CONFIG_IRQ_PER_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_ARCH_HAS_ILOG2_U32=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 # CONFIG_ARCH_NO_VIRT_TO_BUS is not set
 CONFIG_PPC=y
@@ -52,11 +55,13 @@ CONFIG_PPC_UDBG_16550=y
 # CONFIG_GENERIC_TBSYNC is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_GENERIC_BUG=y
+CONFIG_DTC=y
 # CONFIG_DEFAULT_UIMAGE is not set
 # CONFIG_PPC_DCR_NATIVE is not set
 # CONFIG_PPC_DCR_MMIO is not set
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -101,7 +106,6 @@ CONFIG_ANON_INODES=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 # CONFIG_KALLSYMS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -114,9 +118,16 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
+
+#
+# Performance Counters
+#
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
 CONFIG_SLUB_DEBUG=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 # CONFIG_SLAB is not set
 CONFIG_SLUB=y
@@ -129,6 +140,10 @@ CONFIG_HAVE_IOREMAP_PROT=y
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -141,7 +156,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-CONFIG_LBD=y
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -222,6 +237,7 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_HAVE_AOUT is not set
 CONFIG_BINFMT_MISC=y
 # CONFIG_IOMMU_HELPER is not set
+# CONFIG_SWIOTLB is not set
 CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 CONFIG_ARCH_HAS_WALK_MEMORY=y
 CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
@@ -242,9 +258,9 @@ CONFIG_MIGRATION=y
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_PPC_4K_PAGES=y
 # CONFIG_PPC_16K_PAGES is not set
 # CONFIG_PPC_64K_PAGES is not set
@@ -347,6 +363,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -364,7 +381,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -501,7 +522,9 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 CONFIG_IDE=y
 
@@ -579,10 +602,6 @@ CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR 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
@@ -599,6 +618,7 @@ CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -607,6 +627,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_ARCMSR is not set
@@ -626,7 +647,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -660,14 +680,17 @@ CONFIG_MD_RAID6_PQ=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -695,8 +718,10 @@ CONFIG_R8169=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 # CONFIG_FSL_PQ_MDIO is not set
 # CONFIG_GIANFAR is not set
+# CONFIG_MV643XX_ETH is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -845,13 +870,17 @@ CONFIG_I2C_MPC=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -879,23 +908,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -937,6 +952,7 @@ CONFIG_USB_DEVICE_CLASS=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -946,6 +962,8 @@ CONFIG_USB_EHCI_HCD_PPC_OF=y
 # CONFIG_USB_ISP116X_HCD is not set
 # CONFIG_USB_ISP1760_HCD is not set
 CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_HCD_PPC_OF_BE is not set
+# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set
 # CONFIG_USB_OHCI_HCD_PPC_OF is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
@@ -1064,6 +1082,7 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1091,6 +1110,10 @@ CONFIG_RTC_DRV_DS1307=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1110,7 +1133,6 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-CONFIG_FILE_LOCKING=y
 CONFIG_XFS_FS=m
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_POSIX_ACL is not set
@@ -1119,6 +1141,8 @@ CONFIG_XFS_FS=m
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -1273,6 +1297,7 @@ CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_HAVE_LMB=y
 CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
 
 #
 # Kernel hacking
@@ -1298,22 +1323,11 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
 CONFIG_HAVE_DYNAMIC_FTRACE=y
 CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
 CONFIG_TRACING_SUPPORT=y
-
-#
-# Tracers
-#
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_EVENT_TRACER is not set
-# CONFIG_BOOT_TRACER is not set
-# CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_KMEMTRACE is not set
-# CONFIG_WORKQUEUE_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_PPC_DISABLE_WERROR is not set
+CONFIG_PPC_WERROR=y
 CONFIG_PRINT_STACK_DEPTH=64
 # CONFIG_IRQSTACKS is not set
 # CONFIG_BOOTX_TEXT is not set
index 2ff798744c1d6eba3bd71a99f3875cdc71f26888..7685ffde882105fc81eba44d5a918309d5bbd66c 100644 (file)
@@ -598,8 +598,6 @@ typedef struct risc_timer_pram {
 #define CICR_IEN               ((uint)0x00000080)      /* Int. enable */
 #define CICR_SPS               ((uint)0x00000001)      /* SCC Spread */
 
-#define IMAP_ADDR              (get_immrbase())
-
 #define CPM_PIN_INPUT     0
 #define CPM_PIN_OUTPUT    1
 #define CPM_PIN_PRIMARY   0
index 1e2eb41fa0577ff8ecceb2d9711220c82ea22fab..52e4d54da2a9845d16db0773ca81310178707723 100644 (file)
@@ -63,6 +63,8 @@ extern void udelay(unsigned long usecs);
                        udelay(delay);                                         \
                else                                                           \
                        cpu_relax();                                           \
+       if (!__ret)                                                            \
+               __ret = (condition);                                           \
        __ret;                                                                 \
 })
 
index 3d9e887c3c0cfb0a970e30c6318b4b1804d08549..b44aaabdd1a685f2c52c98fe3cf7ae798c779e31 100644 (file)
@@ -309,7 +309,9 @@ static inline void dma_sync_single_for_cpu(struct device *dev,
        struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
        BUG_ON(!dma_ops);
-       dma_ops->sync_single_range_for_cpu(dev, dma_handle, 0,
+
+       if (dma_ops->sync_single_range_for_cpu)
+               dma_ops->sync_single_range_for_cpu(dev, dma_handle, 0,
                                           size, direction);
 }
 
@@ -320,7 +322,9 @@ static inline void dma_sync_single_for_device(struct device *dev,
        struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
        BUG_ON(!dma_ops);
-       dma_ops->sync_single_range_for_device(dev, dma_handle,
+
+       if (dma_ops->sync_single_range_for_device)
+               dma_ops->sync_single_range_for_device(dev, dma_handle,
                                              0, size, direction);
 }
 
@@ -331,7 +335,9 @@ static inline void dma_sync_sg_for_cpu(struct device *dev,
        struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
        BUG_ON(!dma_ops);
-       dma_ops->sync_sg_for_cpu(dev, sgl, nents, direction);
+
+       if (dma_ops->sync_sg_for_cpu)
+               dma_ops->sync_sg_for_cpu(dev, sgl, nents, direction);
 }
 
 static inline void dma_sync_sg_for_device(struct device *dev,
@@ -341,7 +347,9 @@ static inline void dma_sync_sg_for_device(struct device *dev,
        struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
        BUG_ON(!dma_ops);
-       dma_ops->sync_sg_for_device(dev, sgl, nents, direction);
+
+       if (dma_ops->sync_sg_for_device)
+               dma_ops->sync_sg_for_device(dev, sgl, nents, direction);
 }
 
 static inline void dma_sync_single_range_for_cpu(struct device *dev,
@@ -351,7 +359,9 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev,
        struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
        BUG_ON(!dma_ops);
-       dma_ops->sync_single_range_for_cpu(dev, dma_handle,
+
+       if (dma_ops->sync_single_range_for_cpu)
+               dma_ops->sync_single_range_for_cpu(dev, dma_handle,
                                           offset, size, direction);
 }
 
@@ -362,7 +372,9 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
        struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
        BUG_ON(!dma_ops);
-       dma_ops->sync_single_range_for_device(dev, dma_handle, offset,
+
+       if (dma_ops->sync_single_range_for_device)
+               dma_ops->sync_single_range_for_device(dev, dma_handle, offset,
                                              size, direction);
 }
 #else /* CONFIG_PPC_NEED_DMA_SYNC_OPS */
index 684a73f4324f4ad203c71ef4eb09b5045ab60516..a74c4ee6c0205dbad7e938ab76e012bfa6491c28 100644 (file)
@@ -22,9 +22,7 @@
 
 #ifdef __KERNEL__
 
-#include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/highmem.h>
 #include <asm/kmap_types.h>
 #include <asm/tlbflush.h>
 #include <asm/page.h>
@@ -62,6 +60,9 @@ extern pte_t *pkmap_page_table;
 
 extern void *kmap_high(struct page *page);
 extern void kunmap_high(struct page *page);
+extern void *kmap_atomic_prot(struct page *page, enum km_type type,
+                             pgprot_t prot);
+extern void kunmap_atomic(void *kvaddr, enum km_type type);
 
 static inline void *kmap(struct page *page)
 {
@@ -79,62 +80,11 @@ static inline void kunmap(struct page *page)
        kunmap_high(page);
 }
 
-/*
- * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
- * gives a more generic (and caching) interface. But kmap_atomic can
- * be used in IRQ contexts, so in some (very limited) cases we need
- * it.
- */
-static inline void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
-{
-       unsigned int idx;
-       unsigned long vaddr;
-
-       /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
-       pagefault_disable();
-       if (!PageHighMem(page))
-               return page_address(page);
-
-       debug_kmap_atomic(type);
-       idx = type + KM_TYPE_NR*smp_processor_id();
-       vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-#ifdef CONFIG_DEBUG_HIGHMEM
-       BUG_ON(!pte_none(*(kmap_pte-idx)));
-#endif
-       __set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot), 1);
-       local_flush_tlb_page(NULL, vaddr);
-
-       return (void*) vaddr;
-}
-
 static inline void *kmap_atomic(struct page *page, enum km_type type)
 {
        return kmap_atomic_prot(page, type, kmap_prot);
 }
 
-static inline void kunmap_atomic(void *kvaddr, enum km_type type)
-{
-#ifdef CONFIG_DEBUG_HIGHMEM
-       unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-       enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
-
-       if (vaddr < __fix_to_virt(FIX_KMAP_END)) {
-               pagefault_enable();
-               return;
-       }
-
-       BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
-
-       /*
-        * force other mappings to Oops if they'll try to access
-        * this pte without first remap it
-        */
-       pte_clear(&init_mm, vaddr, kmap_pte-idx);
-       local_flush_tlb_page(NULL, vaddr);
-#endif
-       pagefault_enable();
-}
-
 static inline struct page *kmap_atomic_to_page(void *ptr)
 {
        unsigned long idx, vaddr = (unsigned long) ptr;
@@ -148,6 +98,7 @@ static inline struct page *kmap_atomic_to_page(void *ptr)
        return pte_page(*pte);
 }
 
+
 #define flush_cache_kmaps()    flush_cache_all()
 
 #endif /* __KERNEL__ */
index 867ab8ed69b303658a07d6c67d660eece712d5cf..8b505eaaa38a173b0f86154654879ad914d35fb7 100644 (file)
@@ -68,13 +68,13 @@ static inline int irqs_disabled_flags(unsigned long flags)
 
 #if defined(CONFIG_BOOKE)
 #define SET_MSR_EE(x)  mtmsr(x)
-#define local_irq_restore(flags)       __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
+#define raw_local_irq_restore(flags)   __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory")
 #else
 #define SET_MSR_EE(x)  mtmsr(x)
-#define local_irq_restore(flags)       mtmsr(flags)
+#define raw_local_irq_restore(flags)   mtmsr(flags)
 #endif
 
-static inline void local_irq_disable(void)
+static inline void raw_local_irq_disable(void)
 {
 #ifdef CONFIG_BOOKE
        __asm__ __volatile__("wrteei 0": : :"memory");
@@ -86,7 +86,7 @@ static inline void local_irq_disable(void)
 #endif
 }
 
-static inline void local_irq_enable(void)
+static inline void raw_local_irq_enable(void)
 {
 #ifdef CONFIG_BOOKE
        __asm__ __volatile__("wrteei 1": : :"memory");
@@ -98,7 +98,7 @@ static inline void local_irq_enable(void)
 #endif
 }
 
-static inline void local_irq_save_ptr(unsigned long *flags)
+static inline void raw_local_irq_save_ptr(unsigned long *flags)
 {
        unsigned long msr;
        msr = mfmsr();
@@ -110,12 +110,12 @@ static inline void local_irq_save_ptr(unsigned long *flags)
 #endif
 }
 
-#define local_save_flags(flags)        ((flags) = mfmsr())
-#define local_irq_save(flags)  local_irq_save_ptr(&flags)
-#define irqs_disabled()                ((mfmsr() & MSR_EE) == 0)
+#define raw_local_save_flags(flags)    ((flags) = mfmsr())
+#define raw_local_irq_save(flags)      raw_local_irq_save_ptr(&flags)
+#define raw_irqs_disabled()            ((mfmsr() & MSR_EE) == 0)
+#define raw_irqs_disabled_flags(flags) (((flags) & MSR_EE) == 0)
 
-#define hard_irq_enable()      local_irq_enable()
-#define hard_irq_disable()     local_irq_disable()
+#define hard_irq_disable()             raw_local_irq_disable()
 
 static inline int irqs_disabled_flags(unsigned long flags)
 {
index dfdf13c9fefd9d4f64b0d1f0eebb70b7050fc598..fddc3ed715fa7abf1c55cbfccbc2bef7193e0348 100644 (file)
@@ -34,7 +34,7 @@
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 
 /* We don't currently support large pages. */
-#define KVM_PAGES_PER_HPAGE (1<<31)
+#define KVM_PAGES_PER_HPAGE (1UL << 31)
 
 struct kvm;
 struct kvm_run;
index 8ccd4e155768fa749edf3f65fbc0c5a951ef9819..0ea0639fcf75be1c4393e4437aceaf7bb7ca87eb 100644 (file)
@@ -61,6 +61,8 @@ struct pt_regs;
 extern unsigned long perf_misc_flags(struct pt_regs *regs);
 extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
 
+#define PERF_COUNTER_INDEX_OFFSET      1
+
 /*
  * Only override the default definitions in include/linux/perf_counter.h
  * if we have hardware PMU support.
index 0815eb40acae214b8947a4da26d565bfaf4fb8a7..c9500d666a1de37687346d7b7cfae5dd2f81ac7a 100644 (file)
@@ -16,7 +16,7 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
  */
 /* #define pmd_alloc_one(mm,address)       ({ BUG(); ((pmd_t *)2); }) */
 #define pmd_free(mm, x)                do { } while (0)
-#define __pmd_free_tlb(tlb,x)          do { } while (0)
+#define __pmd_free_tlb(tlb,x,a)                do { } while (0)
 /* #define pgd_populate(mm, pmd, pte)      BUG() */
 
 #ifndef CONFIG_BOOKE
index afda2bdd860f8bc8eb20dbb915701fface743ce6..e6f069c4f713a7b2c7ce76e3da593693d2fc1d79 100644 (file)
@@ -118,11 +118,11 @@ static inline void pgtable_free(pgtable_free_t pgf)
                kmem_cache_free(pgtable_cache[cachenum], p);
 }
 
-#define __pmd_free_tlb(tlb, pmd)       \
+#define __pmd_free_tlb(tlb, pmd,addr)                \
        pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \
                PMD_CACHE_NUM, PMD_TABLE_SIZE-1))
 #ifndef CONFIG_PPC_64K_PAGES
-#define __pud_free_tlb(tlb, pud)       \
+#define __pud_free_tlb(tlb, pud, addr)               \
        pgtable_free_tlb(tlb, pgtable_free_cache(pud, \
                PUD_CACHE_NUM, PUD_TABLE_SIZE-1))
 #endif /* CONFIG_PPC_64K_PAGES */
index 5d8480265a77561bfa48cb2b82eb2fca9b4a4fd2..1730e5e298d61b07df858de4e32078c7ff4201e4 100644 (file)
@@ -38,14 +38,14 @@ static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum,
 extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf);
 
 #ifdef CONFIG_SMP
-#define __pte_free_tlb(tlb,ptepage)    \
+#define __pte_free_tlb(tlb,ptepage,address)            \
 do { \
        pgtable_page_dtor(ptepage); \
        pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \
-               PTE_NONCACHE_NUM, PTE_TABLE_SIZE-1)); \
+                                       PTE_NONCACHE_NUM, PTE_TABLE_SIZE-1)); \
 } while (0)
 #else
-#define __pte_free_tlb(tlb, pte      pte_free((tlb)->mm, (pte))
+#define __pte_free_tlb(tlb, pte, address)      pte_free((tlb)->mm, (pte))
 #endif
 
 
index e05d26fa372fc84ae833799e072dca5a39a94d37..82b72207c51c9113600ce8b8fc5297115623142c 100644 (file)
@@ -47,7 +47,8 @@
  * generic accessors and iterators here
  */
 #define __real_pte(e,p)        ((real_pte_t) { \
-       (e), pte_val(*((p) + PTRS_PER_PTE)) })
+                       (e), ((e) & _PAGE_COMBO) ? \
+                               (pte_val(*((p) + PTRS_PER_PTE))) : 0 })
 #define __rpte_to_hidx(r,index)        ((pte_val((r).pte) & _PAGE_COMBO) ? \
         (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf))
 #define __rpte_to_pte(r)       ((r).pte)
index 01c12339b30444270d8f2a0be248f6860571d21f..168fce726201d3799fc3878e3a7620e1575a6dfd 100644 (file)
@@ -58,7 +58,7 @@ struct rtas_t {
        unsigned long entry;            /* physical address pointer */
        unsigned long base;             /* physical address pointer */
        unsigned long size;
-       spinlock_t lock;
+       raw_spinlock_t lock;
        struct rtas_args args;
        struct device_node *dev;        /* virtual address pointer */
 };
@@ -245,5 +245,8 @@ static inline u32 rtas_config_addr(int busno, int devfn, int reg)
                        (devfn << 8) | (reg & 0xff);
 }
 
+extern void __cpuinit rtas_give_timebase(void);
+extern void __cpuinit rtas_take_timebase(void);
+
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_RTAS_H */
index 9aba5a38a7c4f32a011c6af5c3bd22e28e88d8a6..c8b329255678802bc34e27c85e84bf5338be25ea 100644 (file)
@@ -46,15 +46,13 @@ struct thread_info {
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #define INIT_THREAD_INFO(tsk)                  \
 {                                              \
        .task =         &tsk,                   \
        .exec_domain =  &default_exec_domain,   \
        .cpu =          0,                      \
-       .preempt_count = 1,                     \
+       .preempt_count = INIT_PREEMPT_COUNT,    \
        .restart_block = {                      \
                .fn = do_no_restart_syscall,    \
        },                                      \
index 20a60d661ba867a2491fb09e0c6d48f5b2576bce..ccf129d47d84d26ff702bf7c5c507a2f206ea5a5 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/lmb.h>
 #include <asm/bug.h>
 #include <asm/abs_addr.h>
 
@@ -90,11 +91,10 @@ static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg,
 static int dma_direct_dma_supported(struct device *dev, u64 mask)
 {
 #ifdef CONFIG_PPC64
-       /* Could be improved to check for memory though it better be
-        * done via some global so platforms can set the limit in case
+       /* Could be improved so platforms can set the limit in case
         * they have limited DMA windows
         */
-       return mask >= DMA_BIT_MASK(32);
+       return mask >= (lmb_end_of_DRAM() - 1);
 #else
        return 1;
 #endif
index 4dd38f129153f7c90340cde840774dc11da22500..3cadba60a4b6c5ff88f964b32e1298e49c48b542 100644 (file)
@@ -191,11 +191,49 @@ transfer_to_handler_cont:
        mflr    r9
        lwz     r11,0(r9)               /* virtual address of handler */
        lwz     r9,4(r9)                /* where to go when done */
+#ifdef CONFIG_TRACE_IRQFLAGS
+       lis     r12,reenable_mmu@h
+       ori     r12,r12,reenable_mmu@l
+       mtspr   SPRN_SRR0,r12
+       mtspr   SPRN_SRR1,r10
+       SYNC
+       RFI
+reenable_mmu:                          /* re-enable mmu so we can */
+       mfmsr   r10
+       lwz     r12,_MSR(r1)
+       xor     r10,r10,r12
+       andi.   r10,r10,MSR_EE          /* Did EE change? */
+       beq     1f
+
+       /* Save handler and return address into the 2 unused words
+        * of the STACK_FRAME_OVERHEAD (sneak sneak sneak). Everything
+        * else can be recovered from the pt_regs except r3 which for
+        * normal interrupts has been set to pt_regs and for syscalls
+        * is an argument, so we temporarily use ORIG_GPR3 to save it
+        */
+       stw     r9,8(r1)
+       stw     r11,12(r1)
+       stw     r3,ORIG_GPR3(r1)
+       bl      trace_hardirqs_off
+       lwz     r0,GPR0(r1)
+       lwz     r3,ORIG_GPR3(r1)
+       lwz     r4,GPR4(r1)
+       lwz     r5,GPR5(r1)
+       lwz     r6,GPR6(r1)
+       lwz     r7,GPR7(r1)
+       lwz     r8,GPR8(r1)
+       lwz     r9,8(r1)
+       lwz     r11,12(r1)
+1:     mtctr   r11
+       mtlr    r9
+       bctr                            /* jump to handler */
+#else /* CONFIG_TRACE_IRQFLAGS */
        mtspr   SPRN_SRR0,r11
        mtspr   SPRN_SRR1,r10
        mtlr    r9
        SYNC
        RFI                             /* jump to handler, enable MMU */
+#endif /* CONFIG_TRACE_IRQFLAGS */
 
 #if defined (CONFIG_6xx) || defined(CONFIG_E500)
 4:     rlwinm  r12,r12,0,~_TLF_NAPPING
@@ -251,6 +289,31 @@ _GLOBAL(DoSyscall)
 #ifdef SHOW_SYSCALLS
        bl      do_show_syscall
 #endif /* SHOW_SYSCALLS */
+#ifdef CONFIG_TRACE_IRQFLAGS
+       /* Return from syscalls can (and generally will) hard enable
+        * interrupts. You aren't supposed to call a syscall with
+        * interrupts disabled in the first place. However, to ensure
+        * that we get it right vs. lockdep if it happens, we force
+        * that hard enable here with appropriate tracing if we see
+        * that we have been called with interrupts off
+        */
+       mfmsr   r11
+       andi.   r12,r11,MSR_EE
+       bne+    1f
+       /* We came in with interrupts disabled, we enable them now */
+       bl      trace_hardirqs_on
+       mfmsr   r11
+       lwz     r0,GPR0(r1)
+       lwz     r3,GPR3(r1)
+       lwz     r4,GPR4(r1)
+       ori     r11,r11,MSR_EE
+       lwz     r5,GPR5(r1)
+       lwz     r6,GPR6(r1)
+       lwz     r7,GPR7(r1)
+       lwz     r8,GPR8(r1)
+       mtmsr   r11
+1:
+#endif /* CONFIG_TRACE_IRQFLAGS */
        rlwinm  r10,r1,0,0,(31-THREAD_SHIFT)    /* current_thread_info() */
        lwz     r11,TI_FLAGS(r10)
        andi.   r11,r11,_TIF_SYSCALL_T_OR_A
@@ -275,6 +338,7 @@ ret_from_syscall:
        rlwinm  r12,r1,0,0,(31-THREAD_SHIFT)    /* current_thread_info() */
        /* disable interrupts so current_thread_info()->flags can't change */
        LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
+       /* Note: We don't bother telling lockdep about it */
        SYNC
        MTMSRD(r10)
        lwz     r9,TI_FLAGS(r12)
@@ -288,6 +352,19 @@ ret_from_syscall:
        oris    r11,r11,0x1000  /* Set SO bit in CR */
        stw     r11,_CCR(r1)
 syscall_exit_cont:
+       lwz     r8,_MSR(r1)
+#ifdef CONFIG_TRACE_IRQFLAGS
+       /* If we are going to return from the syscall with interrupts
+        * off, we trace that here. It shouldn't happen though but we
+        * want to catch the bugger if it does right ?
+        */
+       andi.   r10,r8,MSR_EE
+       bne+    1f
+       stw     r3,GPR3(r1)
+       bl      trace_hardirqs_off
+       lwz     r3,GPR3(r1)
+1:
+#endif /* CONFIG_TRACE_IRQFLAGS */
 #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
        /* If the process has its own DBCR0 value, load it up.  The internal
           debug mode bit tells us that dbcr0 should be loaded. */
@@ -311,7 +388,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
        mtlr    r4
        mtcr    r5
        lwz     r7,_NIP(r1)
-       lwz     r8,_MSR(r1)
        FIX_SRR1(r8, r0)
        lwz     r2,GPR2(r1)
        lwz     r1,GPR1(r1)
@@ -394,7 +470,9 @@ syscall_exit_work:
        andi.   r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
        beq     ret_from_except
 
-       /* Re-enable interrupts */
+       /* Re-enable interrupts. There is no need to trace that with
+        * lockdep as we are supposed to have IRQs on at this point
+        */
        ori     r10,r10,MSR_EE
        SYNC
        MTMSRD(r10)
@@ -705,6 +783,7 @@ ret_from_except:
        /* Hard-disable interrupts so that current_thread_info()->flags
         * can't change between when we test it and when we return
         * from the interrupt. */
+       /* Note: We don't bother telling lockdep about it */
        LOAD_MSR_KERNEL(r10,MSR_KERNEL)
        SYNC                    /* Some chip revs have problems here... */
        MTMSRD(r10)             /* disable interrupts */
@@ -744,11 +823,24 @@ resume_kernel:
        beq+    restore
        andi.   r0,r3,MSR_EE    /* interrupts off? */
        beq     restore         /* don't schedule if so */
+#ifdef CONFIG_TRACE_IRQFLAGS
+       /* Lockdep thinks irqs are enabled, we need to call
+        * preempt_schedule_irq with IRQs off, so we inform lockdep
+        * now that we -did- turn them off already
+        */
+       bl      trace_hardirqs_off
+#endif
 1:     bl      preempt_schedule_irq
        rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
        lwz     r3,TI_FLAGS(r9)
        andi.   r0,r3,_TIF_NEED_RESCHED
        bne-    1b
+#ifdef CONFIG_TRACE_IRQFLAGS
+       /* And now, to properly rebalance the above, we tell lockdep they
+        * are being turned back on, which will happen when we return
+        */
+       bl      trace_hardirqs_on
+#endif
 #else
 resume_kernel:
 #endif /* CONFIG_PREEMPT */
@@ -765,6 +857,28 @@ restore:
        stw     r6,icache_44x_need_flush@l(r4)
 1:
 #endif  /* CONFIG_44x */
+
+       lwz     r9,_MSR(r1)
+#ifdef CONFIG_TRACE_IRQFLAGS
+       /* Lockdep doesn't know about the fact that IRQs are temporarily turned
+        * off in this assembly code while peeking at TI_FLAGS() and such. However
+        * we need to inform it if the exception turned interrupts off, and we
+        * are about to trun them back on.
+        *
+        * The problem here sadly is that we don't know whether the exceptions was
+        * one that turned interrupts off or not. So we always tell lockdep about
+        * turning them on here when we go back to wherever we came from with EE
+        * on, even if that may meen some redudant calls being tracked. Maybe later
+        * we could encode what the exception did somewhere or test the exception
+        * type in the pt_regs but that sounds overkill
+        */
+       andi.   r10,r9,MSR_EE
+       beq     1f
+       bl      trace_hardirqs_on
+       lwz     r9,_MSR(r1)
+1:
+#endif /* CONFIG_TRACE_IRQFLAGS */
+
        lwz     r0,GPR0(r1)
        lwz     r2,GPR2(r1)
        REST_4GPRS(3, r1)
@@ -782,7 +896,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
        stwcx.  r0,0,r1                 /* to clear the reservation */
 
 #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
-       lwz     r9,_MSR(r1)
        andi.   r10,r9,MSR_RI           /* check if this exception occurred */
        beql    nonrecoverable          /* at a bad place (MSR:RI = 0) */
 
@@ -805,7 +918,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
        MTMSRD(r10)             /* clear the RI bit */
        .globl exc_exit_restart
 exc_exit_restart:
-       lwz     r9,_MSR(r1)
        lwz     r12,_NIP(r1)
        FIX_SRR1(r9,r10)
        mtspr   SPRN_SRR0,r12
@@ -1035,11 +1147,18 @@ do_work:                        /* r10 contains MSR_KERNEL here */
        beq     do_user_signal
 
 do_resched:                    /* r10 contains MSR_KERNEL here */
+       /* Note: We don't need to inform lockdep that we are enabling
+        * interrupts here. As far as it knows, they are already enabled
+        */
        ori     r10,r10,MSR_EE
        SYNC
        MTMSRD(r10)             /* hard-enable interrupts */
        bl      schedule
 recheck:
+       /* Note: And we don't tell it we are disabling them again
+        * neither. Those disable/enable cycles used to peek at
+        * TI_FLAGS aren't advertised.
+        */
        LOAD_MSR_KERNEL(r10,MSR_KERNEL)
        SYNC
        MTMSRD(r10)             /* disable interrupts */
index 48469463f89e7a309e93e5d536da4ec1f0373f99..fc2132942754e06e09c5f6c169143da89b0b2761 100644 (file)
@@ -1124,9 +1124,8 @@ mmu_off:
        RFI
 
 /*
- * Use the first pair of BAT registers to map the 1st 16MB
- * of RAM to PAGE_OFFSET.  From this point on we can't safely
- * call OF any more.
+ * On 601, we use 3 BATs to map up to 24M of RAM at _PAGE_OFFSET
+ * (we keep one for debugging) and on others, we use one 256M BAT.
  */
 initial_bats:
        lis     r11,PAGE_OFFSET@h
@@ -1136,12 +1135,16 @@ initial_bats:
        bne     4f
        ori     r11,r11,4               /* set up BAT registers for 601 */
        li      r8,0x7f                 /* valid, block length = 8MB */
-       oris    r9,r11,0x800000@h       /* set up BAT reg for 2nd 8M */
-       oris    r10,r8,0x800000@h       /* set up BAT reg for 2nd 8M */
        mtspr   SPRN_IBAT0U,r11         /* N.B. 601 has valid bit in */
        mtspr   SPRN_IBAT0L,r8          /* lower BAT register */
-       mtspr   SPRN_IBAT1U,r9
-       mtspr   SPRN_IBAT1L,r10
+       addis   r11,r11,0x800000@h
+       addis   r8,r8,0x800000@h
+       mtspr   SPRN_IBAT1U,r11
+       mtspr   SPRN_IBAT1L,r8
+       addis   r11,r11,0x800000@h
+       addis   r8,r8,0x800000@h
+       mtspr   SPRN_IBAT2U,r11
+       mtspr   SPRN_IBAT2L,r8
        isync
        blr
 
index 75ff47fed7bfcadf9d69028297b09796c9e8a342..cc466d039af6c8ec2a3984c2597dc6cceae2da67 100644 (file)
@@ -10,7 +10,6 @@
  */
 #include <linux/string.h>
 #include <linux/perf_counter.h>
-#include <linux/string.h>
 #include <asm/reg.h>
 #include <asm/cputable.h>
 
@@ -408,7 +407,8 @@ struct power_pmu mpc7450_pmu = {
 
 static int init_mpc7450_pmu(void)
 {
-       if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/7450"))
+       if (!cur_cpu_spec->oprofile_cpu_type ||
+           strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/7450"))
                return -ENODEV;
 
        return register_power_pmu(&mpc7450_pmu);
index fa983a59c4ce1084d939da4ea6fce17d91036f2a..a359cb08e9006168a60ba87b9e34df0c02256d51 100644 (file)
@@ -76,7 +76,7 @@ struct of_device *of_device_alloc(struct device_node *np,
        dev->dev.archdata.of_node = np;
 
        if (bus_id)
-               dev_set_name(&dev->dev, bus_id);
+               dev_set_name(&dev->dev, "%s", bus_id);
        else
                of_device_make_bus_id(dev);
 
index 809fdf94b95fb4b10c117a88927fbafecba83979..70e1f57f7dd864bb2ec9d2f2e5e16c301e647a19 100644 (file)
@@ -518,6 +518,8 @@ void hw_perf_disable(void)
        struct cpu_hw_counters *cpuhw;
        unsigned long flags;
 
+       if (!ppmu)
+               return;
        local_irq_save(flags);
        cpuhw = &__get_cpu_var(cpu_hw_counters);
 
@@ -572,6 +574,8 @@ void hw_perf_enable(void)
        int n_lim;
        int idx;
 
+       if (!ppmu)
+               return;
        local_irq_save(flags);
        cpuhw = &__get_cpu_var(cpu_hw_counters);
        if (!cpuhw->disabled) {
@@ -737,6 +741,8 @@ int hw_perf_group_sched_in(struct perf_counter *group_leader,
        long i, n, n0;
        struct perf_counter *sub;
 
+       if (!ppmu)
+               return 0;
        cpuhw = &__get_cpu_var(cpu_hw_counters);
        n0 = cpuhw->n_counters;
        n = collect_events(group_leader, ppmu->n_counter - n0,
@@ -1281,6 +1287,8 @@ void hw_perf_counter_setup(int cpu)
 {
        struct cpu_hw_counters *cpuhw = &per_cpu(cpu_hw_counters, cpu);
 
+       if (!ppmu)
+               return;
        memset(cpuhw, 0, sizeof(*cpuhw));
        cpuhw->mmcr[0] = MMCR0_FC;
 }
index db90b0c5c27bbc05f9d66dc8a70c18f108e9ecf3..3c90a3d9173e47a60109312be18603851e163c28 100644 (file)
@@ -606,7 +606,8 @@ static struct power_pmu power4_pmu = {
 
 static int init_power4_pmu(void)
 {
-       if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power4"))
+       if (!cur_cpu_spec->oprofile_cpu_type ||
+           strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power4"))
                return -ENODEV;
 
        return register_power_pmu(&power4_pmu);
index f4adca8e98a423a92941ad00c83ab6c174a7484e..31918af3e3553d551e9870fb2d4060727dab75f5 100644 (file)
@@ -678,8 +678,9 @@ static struct power_pmu power5p_pmu = {
 
 static int init_power5p_pmu(void)
 {
-       if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5+")
-           && strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5++"))
+       if (!cur_cpu_spec->oprofile_cpu_type ||
+           (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5+")
+            && strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5++")))
                return -ENODEV;
 
        return register_power_pmu(&power5p_pmu);
index 29b2c6c0e83a2a37b582fe1e98a986ff0daefaba..867f6f663963d411dfc654ddc72caf198d0ed5cb 100644 (file)
@@ -618,7 +618,8 @@ static struct power_pmu power5_pmu = {
 
 static int init_power5_pmu(void)
 {
-       if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5"))
+       if (!cur_cpu_spec->oprofile_cpu_type ||
+           strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5"))
                return -ENODEV;
 
        return register_power_pmu(&power5_pmu);
index 09ae5bf5bda78fb86b64b1d14d44f9722b63b9a6..fa21890531da732cf466e11869ff69d028188324 100644 (file)
@@ -537,7 +537,8 @@ static struct power_pmu power6_pmu = {
 
 static int init_power6_pmu(void)
 {
-       if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power6"))
+       if (!cur_cpu_spec->oprofile_cpu_type ||
+           strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power6"))
                return -ENODEV;
 
        return register_power_pmu(&power6_pmu);
index 5d755ef7ac8f21d97fbe5ef347b38c44a0f17e23..018d094d92f91d2af529f0eff119f3b3f27983ef 100644 (file)
@@ -317,7 +317,7 @@ static int power7_generic_events[] = {
  */
 static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
        [C(L1D)] = {            /*      RESULT_ACCESS   RESULT_MISS */
-               [C(OP_READ)] = {        0x400f0,        0xc880  },
+               [C(OP_READ)] = {        0xc880,         0x400f0 },
                [C(OP_WRITE)] = {       0,              0x300f0 },
                [C(OP_PREFETCH)] = {    0xd8b8,         0       },
        },
@@ -327,8 +327,8 @@ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
                [C(OP_PREFETCH)] = {    0x408a,         0       },
        },
        [C(LL)] = {             /*      RESULT_ACCESS   RESULT_MISS */
-               [C(OP_READ)] = {        0x6080,         0x6084  },
-               [C(OP_WRITE)] = {       0x6082,         0x6086  },
+               [C(OP_READ)] = {        0x16080,        0x26080 },
+               [C(OP_WRITE)] = {       0x16082,        0x26082 },
                [C(OP_PREFETCH)] = {    0,              0       },
        },
        [C(DTLB)] = {           /*      RESULT_ACCESS   RESULT_MISS */
@@ -358,6 +358,7 @@ static struct power_pmu power7_pmu = {
        .get_constraint         = power7_get_constraint,
        .get_alternatives       = power7_get_alternatives,
        .disable_pmc            = power7_disable_pmc,
+       .flags                  = PPMU_ALT_SIPR,
        .n_generic              = ARRAY_SIZE(power7_generic_events),
        .generic_events         = power7_generic_events,
        .cache_events           = &power7_cache_events,
@@ -365,7 +366,8 @@ static struct power_pmu power7_pmu = {
 
 static int init_power7_pmu(void)
 {
-       if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power7"))
+       if (!cur_cpu_spec->oprofile_cpu_type ||
+           strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power7"))
                return -ENODEV;
 
        return register_power_pmu(&power7_pmu);
index 6637c87fe70eb27812578d9c7d2f51a904f6f1b8..75dccb71a04337fc3f26dd0902de37e279886651 100644 (file)
@@ -10,7 +10,6 @@
  */
 #include <linux/string.h>
 #include <linux/perf_counter.h>
-#include <linux/string.h>
 #include <asm/reg.h>
 #include <asm/cputable.h>
 
@@ -489,8 +488,9 @@ static struct power_pmu ppc970_pmu = {
 
 static int init_ppc970_pmu(void)
 {
-       if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970")
-           && strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970MP"))
+       if (!cur_cpu_spec->oprofile_cpu_type ||
+           (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970")
+            && strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970MP")))
                return -ENODEV;
 
        return register_power_pmu(&ppc970_pmu);
index 3e7135bbe40f648c9a76c82b57fbd72a4e2aba95..892a9f2e6d76a40c44b7d67d5bff9a8912863020 100644 (file)
@@ -528,7 +528,7 @@ void show_regs(struct pt_regs * regs)
 
        for (i = 0;  i < 32;  i++) {
                if ((i % REGS_PER_LINE) == 0)
-                       printk("\n" KERN_INFO "GPR%02d: ", i);
+                       printk("\nGPR%02d: ", i);
                printk(REG " ", regs->gpr[i]);
                if (i == LAST_VOLATILE && !FULL_REGS(regs))
                        break;
index 9fa2c7dcd05a4501034395e6f587523cffb969d0..ef149880c145bf5d0ac639e87ba57c094b86bf51 100644 (file)
@@ -736,15 +736,16 @@ void user_disable_single_step(struct task_struct *task)
 {
        struct pt_regs *regs = task->thread.regs;
 
-
-#if defined(CONFIG_BOOKE)
-       /* If DAC then do not single step, skip */
-       if (task->thread.dabr)
-               return;
-#endif
-
        if (regs != NULL) {
-#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
+#if defined(CONFIG_BOOKE)
+               /* If DAC don't clear DBCRO_IDM or MSR_DE */
+               if (task->thread.dabr)
+                       task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT);
+               else {
+                       task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM);
+                       regs->msr &= ~MSR_DE;
+               }
+#elif defined(CONFIG_40x)
                task->thread.dbcr0 &= ~(DBCR0_IC | DBCR0_BT | DBCR0_IDM);
                regs->msr &= ~MSR_DE;
 #else
index 297632cba047e5ee980950059bee841217978631..8a6daf4129f67ffb143e762a3972a1419b30d0bd 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/regset.h>
index ee4c7609b649e29222209cc666b0f28532844b51..c434823b8c83a02b9ccd161e2e22bea1c52a1c65 100644 (file)
 #include <asm/syscalls.h>
 #include <asm/smp.h>
 #include <asm/atomic.h>
+#include <asm/time.h>
 
 struct rtas_t rtas = {
-       .lock = SPIN_LOCK_UNLOCKED
+       .lock = __RAW_SPIN_LOCK_UNLOCKED
 };
 EXPORT_SYMBOL(rtas);
 
@@ -67,6 +68,28 @@ unsigned long rtas_rmo_buf;
 void (*rtas_flash_term_hook)(int);
 EXPORT_SYMBOL(rtas_flash_term_hook);
 
+/* RTAS use home made raw locking instead of spin_lock_irqsave
+ * because those can be called from within really nasty contexts
+ * such as having the timebase stopped which would lockup with
+ * normal locks and spinlock debugging enabled
+ */
+static unsigned long lock_rtas(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       preempt_disable();
+       __raw_spin_lock_flags(&rtas.lock, flags);
+       return flags;
+}
+
+static void unlock_rtas(unsigned long flags)
+{
+       __raw_spin_unlock(&rtas.lock);
+       local_irq_restore(flags);
+       preempt_enable();
+}
+
 /*
  * call_rtas_display_status and call_rtas_display_status_delay
  * are designed only for very early low-level debugging, which
@@ -79,7 +102,7 @@ static void call_rtas_display_status(char c)
 
        if (!rtas.base)
                return;
-       spin_lock_irqsave(&rtas.lock, s);
+       s = lock_rtas();
 
        args->token = 10;
        args->nargs = 1;
@@ -89,7 +112,7 @@ static void call_rtas_display_status(char c)
 
        enter_rtas(__pa(args));
 
-       spin_unlock_irqrestore(&rtas.lock, s);
+       unlock_rtas(s);
 }
 
 static void call_rtas_display_status_delay(char c)
@@ -411,8 +434,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
        if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
                return -1;
 
-       /* Gotta do something different here, use global lock for now... */
-       spin_lock_irqsave(&rtas.lock, s);
+       s = lock_rtas();
        rtas_args = &rtas.args;
 
        rtas_args->token = token;
@@ -439,8 +461,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
                        outputs[i] = rtas_args->rets[i+1];
        ret = (nret > 0)? rtas_args->rets[0]: 0;
 
-       /* Gotta do something different here, use global lock for now... */
-       spin_unlock_irqrestore(&rtas.lock, s);
+       unlock_rtas(s);
 
        if (buff_copy) {
                log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0);
@@ -837,7 +858,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
 
        buff_copy = get_errorlog_buffer();
 
-       spin_lock_irqsave(&rtas.lock, flags);
+       flags = lock_rtas();
 
        rtas.args = args;
        enter_rtas(__pa(&rtas.args));
@@ -848,7 +869,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
        if (args.rets[0] == -1)
                errbuf = __fetch_rtas_last_error(buff_copy);
 
-       spin_unlock_irqrestore(&rtas.lock, flags);
+       unlock_rtas(flags);
 
        if (buff_copy) {
                if (errbuf)
@@ -951,3 +972,33 @@ int __init early_init_dt_scan_rtas(unsigned long node,
        /* break now */
        return 1;
 }
+
+static raw_spinlock_t timebase_lock;
+static u64 timebase = 0;
+
+void __cpuinit rtas_give_timebase(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       hard_irq_disable();
+       __raw_spin_lock(&timebase_lock);
+       rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
+       timebase = get_tb();
+       __raw_spin_unlock(&timebase_lock);
+
+       while (timebase)
+               barrier();
+       rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
+       local_irq_restore(flags);
+}
+
+void __cpuinit rtas_take_timebase(void)
+{
+       while (!timebase)
+               barrier();
+       __raw_spin_lock(&timebase_lock);
+       set_tb(timebase >> 32, timebase & 0xffffffff);
+       timebase = 0;
+       __raw_spin_unlock(&timebase_lock);
+}
index 1d154248cf40e934aaf295d33e7ca466295ec91a..e1e3059cf34b9472ea06f1d71b1cc9114ee8ead2 100644 (file)
@@ -119,6 +119,8 @@ notrace unsigned long __init early_init(unsigned long dt_ptr)
  */
 notrace void __init machine_init(unsigned long dt_ptr)
 {
+       lockdep_init();
+
        /* Enable early debugging if any specified (see udbg.h) */
        udbg_early_init();
 
index 65484b2200b36add20b48dc38caf3f80971c4d29..0b47de07302d1306dcedf5dff3188a0a5514fd47 100644 (file)
@@ -68,7 +68,8 @@ EXPORT_PER_CPU_SYMBOL(cpu_core_map);
 /* SMP operations for this machine */
 struct smp_ops_t *smp_ops;
 
-static volatile unsigned int cpu_callin_map[NR_CPUS];
+/* Can't be static due to PowerMac hackery */
+volatile unsigned int cpu_callin_map[NR_CPUS];
 
 int smt_enabled_at_boot = 1;
 
index 0362a891e54ee3736707ae0b4066237fd529fadd..acb74a17bbbfa1bc2a916a872e8296bcd71aa0c1 100644 (file)
@@ -219,7 +219,7 @@ void udbg_init_pas_realmode(void)
 #ifdef CONFIG_PPC_EARLY_DEBUG_44x
 #include <platforms/44x/44x.h>
 
-static int udbg_44x_as1_flush(void)
+static void udbg_44x_as1_flush(void)
 {
        if (udbg_comport) {
                while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
index ef36cbbc5882281ccb26ca2c0b4fd14bf23a06d3..ea4d64644d029a283fe17e379d03be319d845b2e 100644 (file)
@@ -80,10 +80,10 @@ _GLOBAL(load_up_altivec)
        mtvscr  vr0
        REST_32VRS(0,r4,r5)
 #ifndef CONFIG_SMP
-       /* Update last_task_used_math to 'current' */
+       /* Update last_task_used_altivec to 'current' */
        subi    r4,r5,THREAD            /* Back to 'current' */
        fromreal(r4)
-       PPC_STL r4,ADDROFF(last_task_used_math)(r3)
+       PPC_STL r4,ADDROFF(last_task_used_altivec)(r3)
 #endif /* CONFIG_SMP */
        /* restore registers and return */
        blr
@@ -172,7 +172,7 @@ _GLOBAL(load_up_vsx)
        oris    r12,r12,MSR_VSX@h
        std     r12,_MSR(r1)
 #ifndef CONFIG_SMP
-       /* Update last_task_used_math to 'current' */
+       /* Update last_task_used_vsx to 'current' */
        ld      r4,PACACURRENT(r13)
        std     r4,0(r3)
 #endif /* CONFIG_SMP */
index 2d2192e48de73f18c2ea968962569b424a345978..3e68363405b79facfba31f3740afef46669fe039 100644 (file)
@@ -30,3 +30,4 @@ obj-$(CONFIG_PPC_MM_SLICES)   += slice.o
 obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
 obj-$(CONFIG_PPC_SUBPAGE_PROT) += subpage-prot.o
 obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o
+obj-$(CONFIG_HIGHMEM)          += highmem.o
index bc400c78c97fb4030b28cbd6c7b4794bba70b199..bc122a120bf009c7b6457e56936d5e9f47071dd6 100644 (file)
@@ -159,7 +159,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
        int psize;
 #endif
 
-       pr_debug("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read");
+       pr_devel("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read");
 
        start &= PAGE_MASK;
        addr = start;
@@ -170,7 +170,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
                                        start, len)))
                goto slow_irqon;
 
-       pr_debug("  aligned: %lx .. %lx\n", start, end);
+       pr_devel("  aligned: %lx .. %lx\n", start, end);
 
 #ifdef CONFIG_HUGETLB_PAGE
        /* We bail out on slice boundary crossing when hugetlb is
@@ -234,7 +234,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
                do {
                        VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, a)].shift);
                        ptep = huge_pte_offset(mm, a);
-                       pr_debug(" %016lx: huge ptep %p\n", a, ptep);
+                       pr_devel(" %016lx: huge ptep %p\n", a, ptep);
                        if (!ptep || !gup_huge_pte(ptep, hstate, &a, end, write, pages,
                                                   &nr))
                                goto slow;
@@ -249,7 +249,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
 #ifdef CONFIG_PPC64
                        VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, addr)].shift);
 #endif
-                       pr_debug("  %016lx: normal pgd %p\n", addr,
+                       pr_devel("  %016lx: normal pgd %p\n", addr,
                                 (void *)pgd_val(pgd));
                        next = pgd_addr_end(addr, end);
                        if (pgd_none(pgd))
@@ -269,7 +269,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
 slow:
                local_irq_enable();
 slow_irqon:
-               pr_debug("  slow path ! nr = %d\n", nr);
+               pr_devel("  slow path ! nr = %d\n", nr);
 
                /* Try to get the remaining pages with get_user_pages */
                start += nr << PAGE_SHIFT;
diff --git a/arch/powerpc/mm/highmem.c b/arch/powerpc/mm/highmem.c
new file mode 100644 (file)
index 0000000..c2186c7
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * highmem.c: virtual kernel memory mappings for high memory
+ *
+ * PowerPC version, stolen from the i386 version.
+ *
+ * Used in CONFIG_HIGHMEM systems for memory pages which
+ * are not addressable by direct kernel virtual addresses.
+ *
+ * Copyright (C) 1999 Gerhard Wichert, Siemens AG
+ *                   Gerhard.Wichert@pdb.siemens.de
+ *
+ *
+ * Redesigned the x86 32-bit VM architecture to deal with
+ * up to 16 Terrabyte physical memory. With current x86 CPUs
+ * we now support up to 64 Gigabytes physical RAM.
+ *
+ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+ *
+ * Reworked for PowerPC by various contributors. Moved from
+ * highmem.h by Benjamin Herrenschmidt (c) 2009 IBM Corp.
+ */
+
+#include <linux/highmem.h>
+#include <linux/module.h>
+
+/*
+ * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
+ * gives a more generic (and caching) interface. But kmap_atomic can
+ * be used in IRQ contexts, so in some (very limited) cases we need
+ * it.
+ */
+void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
+{
+       unsigned int idx;
+       unsigned long vaddr;
+
+       /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
+       pagefault_disable();
+       if (!PageHighMem(page))
+               return page_address(page);
+
+       debug_kmap_atomic(type);
+       idx = type + KM_TYPE_NR*smp_processor_id();
+       vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+       BUG_ON(!pte_none(*(kmap_pte-idx)));
+#endif
+       __set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot), 1);
+       local_flush_tlb_page(NULL, vaddr);
+
+       return (void*) vaddr;
+}
+EXPORT_SYMBOL(kmap_atomic_prot);
+
+void kunmap_atomic(void *kvaddr, enum km_type type)
+{
+#ifdef CONFIG_DEBUG_HIGHMEM
+       unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+       enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+
+       if (vaddr < __fix_to_virt(FIX_KMAP_END)) {
+               pagefault_enable();
+               return;
+       }
+
+       BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+
+       /*
+        * force other mappings to Oops if they'll try to access
+        * this pte without first remap it
+        */
+       pte_clear(&init_mm, vaddr, kmap_pte-idx);
+       local_flush_tlb_page(NULL, vaddr);
+#endif
+       pagefault_enable();
+}
+EXPORT_SYMBOL(kunmap_atomic);
index 9920d6a7cf290cc02339da13d337fa6eddbf021a..c46ef2ffa3d95673febbbe9be0d167a5879ec04f 100644 (file)
@@ -305,7 +305,7 @@ static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
 
        pmd = pmd_offset(pud, start);
        pud_clear(pud);
-       pmd_free_tlb(tlb, pmd);
+       pmd_free_tlb(tlb, pmd, start);
 }
 
 static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
@@ -348,7 +348,7 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
 
        pud = pud_offset(pgd, start);
        pgd_clear(pgd);
-       pud_free_tlb(tlb, pud);
+       pud_free_tlb(tlb, pud, start);
 }
 
 /*
index 8343986809c03fe2b3e952e411ec31a611fffe8b..b1a727def15b4a49b01f850ef76d8388d7ce1853 100644 (file)
@@ -89,7 +89,7 @@ static unsigned int steal_context_smp(unsigned int id)
                                id = first_context;
                        continue;
                }
-               pr_debug("[%d] steal context %d from mm @%p\n",
+               pr_devel("[%d] steal context %d from mm @%p\n",
                         smp_processor_id(), id, mm);
 
                /* Mark this mm has having no context anymore */
@@ -126,7 +126,7 @@ static unsigned int steal_context_up(unsigned int id)
        /* Pick up the victim mm */
        mm = context_mm[id];
 
-       pr_debug("[%d] steal context %d from mm @%p\n", cpu, id, mm);
+       pr_devel("[%d] steal context %d from mm @%p\n", cpu, id, mm);
 
        /* Flush the TLB for that context */
        local_flush_tlb_mm(mm);
@@ -180,7 +180,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
        spin_lock(&context_lock);
 
 #ifndef DEBUG_STEAL_ONLY
-       pr_debug("[%d] activating context for mm @%p, active=%d, id=%d\n",
+       pr_devel("[%d] activating context for mm @%p, active=%d, id=%d\n",
                 cpu, next, next->context.active, next->context.id);
 #endif
 
@@ -189,7 +189,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
        next->context.active++;
        if (prev) {
 #ifndef DEBUG_STEAL_ONLY
-               pr_debug(" old context %p active was: %d\n",
+               pr_devel(" old context %p active was: %d\n",
                         prev, prev->context.active);
 #endif
                WARN_ON(prev->context.active < 1);
@@ -217,6 +217,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
                        id = steal_context_smp(id);
                        if (id == MMU_NO_CONTEXT)
                                goto again;
+                       goto stolen;
                }
 #endif /* CONFIG_SMP */
                id = steal_context_up(id);
@@ -236,7 +237,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
        next->context.id = id;
 
 #ifndef DEBUG_STEAL_ONLY
-       pr_debug("[%d] picked up new id %d, nrf is now %d\n",
+       pr_devel("[%d] picked up new id %d, nrf is now %d\n",
                 cpu, id, nr_free_contexts);
 #endif
 
@@ -247,7 +248,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
         * local TLB for it and unmark it before we use it
         */
        if (test_bit(id, stale_map[cpu])) {
-               pr_debug("[%d] flushing stale context %d for mm @%p !\n",
+               pr_devel("[%d] flushing stale context %d for mm @%p !\n",
                         cpu, id, next);
                local_flush_tlb_mm(next);
 
@@ -314,13 +315,13 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self,
        switch (action) {
        case CPU_ONLINE:
        case CPU_ONLINE_FROZEN:
-               pr_debug("MMU: Allocating stale context map for CPU %d\n", cpu);
+               pr_devel("MMU: Allocating stale context map for CPU %d\n", cpu);
                stale_map[cpu] = kzalloc(CTX_MAP_SIZE, GFP_KERNEL);
                break;
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
-               pr_debug("MMU: Freeing stale context map for CPU %d\n", cpu);
+               pr_devel("MMU: Freeing stale context map for CPU %d\n", cpu);
                kfree(stale_map[cpu]);
                stale_map[cpu] = NULL;
                break;
index ae1d67cc090cfcdb4fd8cfd9ae390cf24c123a32..627767d6169bd4e4300528f4c37907693beea6a7 100644 (file)
@@ -129,12 +129,12 @@ static pte_t do_dcache_icache_coherency(pte_t pte)
        page = pfn_to_page(pfn);
 
        if (!PageReserved(page) && !test_bit(PG_arch_1, &page->flags)) {
-               pr_debug("do_dcache_icache_coherency... flushing\n");
+               pr_devel("do_dcache_icache_coherency... flushing\n");
                flush_dcache_icache_page(page);
                set_bit(PG_arch_1, &page->flags);
        }
        else
-               pr_debug("do_dcache_icache_coherency... already clean\n");
+               pr_devel("do_dcache_icache_coherency... already clean\n");
        return __pte(pte_val(pte) | _PAGE_HWEXEC);
 }
 
index 3b52c80e5e33866141630e1e4ddbe587f7dd519d..5b7038f248b60ea5b7b7d1e0f432a5dad5fa285e 100644 (file)
@@ -14,8 +14,6 @@
  *      2 of the License, or (at your option) any later version.
  */
 
-#undef DEBUG
-
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
 #include <linux/compiler.h>
 #include <asm/udbg.h>
 
-#ifdef DEBUG
-#define DBG(fmt...) printk(fmt)
-#else
-#define DBG pr_debug
-#endif
 
 extern void slb_allocate_realmode(unsigned long ea);
 extern void slb_allocate_user(unsigned long ea);
@@ -285,13 +278,13 @@ void slb_initialize(void)
                patch_slb_encoding(slb_compare_rr_to_size,
                                   mmu_slb_size);
 
-               DBG("SLB: linear  LLP = %04lx\n", linear_llp);
-               DBG("SLB: io      LLP = %04lx\n", io_llp);
+               pr_devel("SLB: linear  LLP = %04lx\n", linear_llp);
+               pr_devel("SLB: io      LLP = %04lx\n", io_llp);
 
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
                patch_slb_encoding(slb_miss_kernel_load_vmemmap,
                                   SLB_VSID_KERNEL | vmemmap_llp);
-               DBG("SLB: vmemmap LLP = %04lx\n", vmemmap_llp);
+               pr_devel("SLB: vmemmap LLP = %04lx\n", vmemmap_llp);
 #endif
        }
 
index 1be1b5e597962727bf41607684d6767b98548238..937eb90677d9ef658b4a2e7d9ebd982a9e0820f7 100644 (file)
@@ -72,7 +72,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
         */
        if (huge) {
 #ifdef CONFIG_HUGETLB_PAGE
-               psize = get_slice_psize(mm, addr);;
+               psize = get_slice_psize(mm, addr);
 #else
                BUG();
                psize = pte_pagesize_index(mm, addr, pte); /* shutup gcc */
index 258fa4411e9e48dde2c9bfdffce352c49e3d9a21..c591339daf58aff5f5b721bc883baeea8928e44e 100644 (file)
@@ -185,7 +185,7 @@ struct vma_to_fileoffset_map *create_vma_map(const struct spu *aSpu,
                        goto fail;
 
                if (shdr_str.sh_type != SHT_STRTAB)
-                       goto fail;;
+                       goto fail;
 
                for (j = 0; j < shdr.sh_size / sizeof (sym); j++) {
                        if (copy_from_user(&sym, spu_elf_start +
index 42e09a9f77e264ecd0a87cd580a2254f1216de4c..e5c1b096c3e124186d9a4a4ae5c3f1cac8b06d06 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/of_gpio.h>
+#include <linux/of_i2c.h>
 
 #include <asm/machdep.h>
 #include <asm/prom.h>
@@ -63,9 +64,6 @@ define_machine(warp) {
 };
 
 
-static u32 post_info;
-
-/* I am not sure this is the best place for this... */
 static int __init warp_post_info(void)
 {
        struct device_node *np;
@@ -87,10 +85,9 @@ static int __init warp_post_info(void)
 
        iounmap(fpga);
 
-       if (post1 || post2) {
+       if (post1 || post2)
                printk(KERN_INFO "Warp POST %08x %08x\n", post1, post2);
-               post_info = 1;
-       } else
+       else
                printk(KERN_INFO "Warp POST OK\n");
 
        return 0;
@@ -166,6 +163,9 @@ static irqreturn_t temp_isr(int irq, void *context)
                value ^= 1;
                mdelay(500);
        }
+
+       /* Not reached */
+       return IRQ_HANDLED;
 }
 
 static int pika_setup_leds(void)
@@ -179,24 +179,19 @@ static int pika_setup_leds(void)
        }
 
        for_each_child_of_node(np, child)
-               if (strcmp(child->name, "green") == 0) {
+               if (strcmp(child->name, "green") == 0)
                        green_led = of_get_gpio(child, 0);
-                       /* Turn back on the green LED */
-                       gpio_set_value(green_led, 1);
-               } else if (strcmp(child->name, "red") == 0) {
+               else if (strcmp(child->name, "red") == 0)
                        red_led = of_get_gpio(child, 0);
-                       /* Set based on post */
-                       gpio_set_value(red_led, post_info);
-               }
 
        of_node_put(np);
 
        return 0;
 }
 
-static void pika_setup_critical_temp(struct i2c_client *client)
+static void pika_setup_critical_temp(struct device_node *np,
+                                    struct i2c_client *client)
 {
-       struct device_node *np;
        int irq, rc;
 
        /* Do this before enabling critical temp interrupt since we
@@ -208,14 +203,7 @@ static void pika_setup_critical_temp(struct i2c_client *client)
        i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */
        i2c_smbus_write_byte_data(client, 3,  0); /* Tlow */
 
-       np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
-       if (np == NULL) {
-               printk(KERN_ERR __FILE__ ": Unable to find ad7414\n");
-               return;
-       }
-
        irq = irq_of_parse_and_map(np, 0);
-       of_node_put(np);
        if (irq  == NO_IRQ) {
                printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n");
                return;
@@ -244,32 +232,24 @@ static inline void pika_dtm_check_fan(void __iomem *fpga)
 
 static int pika_dtm_thread(void __iomem *fpga)
 {
-       struct i2c_adapter *adap;
+       struct device_node *np;
        struct i2c_client *client;
 
-       /* We loop in case either driver was compiled as a module and
-        * has not been insmoded yet.
-        */
-       while (!(adap = i2c_get_adapter(0))) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(HZ);
-       }
-
-       while (1) {
-               list_for_each_entry(client, &adap->clients, list)
-                       if (client->addr == 0x4a)
-                               goto found_it;
+       np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
+       if (np == NULL)
+               return -ENOENT;
 
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(HZ);
+       client = of_find_i2c_device_by_node(np);
+       if (client == NULL) {
+               of_node_put(np);
+               return -ENOENT;
        }
 
-found_it:
-       pika_setup_critical_temp(client);
+       pika_setup_critical_temp(np, client);
 
-       i2c_put_adapter(adap);
+       of_node_put(np);
 
-       printk(KERN_INFO "PIKA DTM thread running.\n");
+       printk(KERN_INFO "Warp DTM thread running.\n");
 
        while (!kthread_should_stop()) {
                int val;
@@ -291,7 +271,6 @@ found_it:
        return 0;
 }
 
-
 static int __init pika_dtm_start(void)
 {
        struct task_struct *dtm_thread;
index ddf0bdc0fc8ba1a6845fb283a5330d21ab0701ce..7ee979f323d18c2da64e8597973bba0823ed1e8b 100644 (file)
@@ -147,7 +147,7 @@ int __init pq2ads_pci_init_irq(void)
                goto out;
        }
 
-       priv = alloc_bootmem(sizeof(struct pq2ads_pci_pic));
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv) {
                of_node_put(np);
                ret = -ENOMEM;
index 77f90b35635681f818e448645fcfa9a174dd4e67..bfb32834ab0c442f78c7cbf870ffedf6c34b17a1 100644 (file)
@@ -233,6 +233,19 @@ static void __init mpc85xx_mds_setup_arch(void)
                        /* Turn UCC1 & UCC2 on */
                        setbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
                        setbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
+               } else if (machine_is(mpc8569_mds)) {
+#define BCSR7_UCC12_GETHnRST   (0x1 << 2)
+#define BCSR8_UEM_MARVELL_RST  (0x1 << 1)
+                       /*
+                        * U-Boot mangles interrupt polarity for Marvell PHYs,
+                        * so reset built-in and UEM Marvell PHYs, this puts
+                        * the PHYs into their normal state.
+                        */
+                       clrbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);
+                       setbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);
+
+                       setbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);
+                       clrbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);
                }
                iounmap(bcsr_regs);
        }
@@ -285,6 +298,7 @@ static struct of_device_id mpc85xx_ids[] = {
        { .type = "qe", },
        { .compatible = "fsl,qe", },
        { .compatible = "gianfar", },
+       { .compatible = "fsl,rapidio-delta", },
        {},
 };
 
index cc0b0db8a6f31bc54f0fd8c483afcc8c67e68786..62c592ede641c4a374a7760fd67604cfc9b2f9de 100644 (file)
@@ -52,20 +52,19 @@ smp_85xx_kick_cpu(int nr)
 
        pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
 
-       local_irq_save(flags);
-
        np = of_get_cpu_node(nr, NULL);
        cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL);
 
        if (cpu_rel_addr == NULL) {
                printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr);
-               local_irq_restore(flags);
                return;
        }
 
        /* Map the spin table */
        bptr_vaddr = ioremap(*cpu_rel_addr, SIZE_BOOT_ENTRY);
 
+       local_irq_save(flags);
+
        out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr);
        out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
 
@@ -73,10 +72,10 @@ smp_85xx_kick_cpu(int nr)
        while ((__secondary_hold_acknowledge != nr) && (++n < 1000))
                mdelay(1);
 
-       iounmap(bptr_vaddr);
-
        local_irq_restore(flags);
 
+       iounmap(bptr_vaddr);
+
        pr_debug("waited %d msecs for CPU #%d.\n", n, nr);
 }
 
index d0e8443b12c6412d471c15ac1b7f8b66b9a319d9..747d8fb3ab82af2c5e26ddfd3e91966bb799bbc3 100644 (file)
@@ -102,10 +102,11 @@ static struct of_device_id __initdata socrates_of_bus_ids[] = {
        {},
 };
 
-static void __init socrates_init(void)
+static int __init socrates_publish_devices(void)
 {
-       of_platform_bus_probe(NULL, socrates_of_bus_ids, NULL);
+       return of_platform_bus_probe(NULL, socrates_of_bus_ids, NULL);
 }
+machine_device_initcall(socrates, socrates_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
@@ -124,7 +125,6 @@ define_machine(socrates) {
        .name                   = "Socrates",
        .probe                  = socrates_probe,
        .setup_arch             = socrates_setup_arch,
-       .init                   = socrates_init,
        .init_IRQ               = socrates_pic_init,
        .get_irq                = mpic_get_irq,
        .restart                = fsl_rstcr_restart,
index ee01532786e4e6fb897905e8438377e8cf5e0e92..1b426050a2f91952cb588f2a61388430e387780a 100644 (file)
@@ -32,7 +32,6 @@
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/fsl_pci.h>
-#include <linux/of_platform.h>
 
 /* A few bit definitions needed for fixups on some boards */
 #define MPC85xx_L2CTL_L2E              0x80000000 /* L2 enable */
index c71498dbf211780675293c205d258cd17350f987..aca5741ddc6777663dcc55c9a840d963b83128f7 100644 (file)
@@ -85,7 +85,7 @@ static inline void axon_msi_debug_setup(struct device_node *dn,
 
 static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
 {
-       pr_debug("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
+       pr_devel("axon_msi: dcr_write(0x%x, 0x%x)\n", val, dcr_n);
 
        dcr_write(msic->dcr_host, dcr_n, val);
 }
@@ -98,7 +98,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
        int retry = 0;
 
        write_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG);
-       pr_debug("axon_msi: original write_offset 0x%x\n", write_offset);
+       pr_devel("axon_msi: original write_offset 0x%x\n", write_offset);
 
        /* write_offset doesn't wrap properly, so we have to mask it */
        write_offset &= MSIC_FIFO_SIZE_MASK;
@@ -108,7 +108,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
                msi  = le32_to_cpu(msic->fifo_virt[idx]);
                msi &= 0xFFFF;
 
-               pr_debug("axon_msi: woff %x roff %x msi %x\n",
+               pr_devel("axon_msi: woff %x roff %x msi %x\n",
                          write_offset, msic->read_offset, msi);
 
                if (msi < NR_IRQS && irq_map[msi].host == msic->irq_host) {
@@ -123,12 +123,12 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
                         */
                        udelay(1);
                        retry++;
-                       pr_debug("axon_msi: invalid irq 0x%x!\n", msi);
+                       pr_devel("axon_msi: invalid irq 0x%x!\n", msi);
                        continue;
                }
 
                if (retry) {
-                       pr_debug("axon_msi: late irq 0x%x, retry %d\n",
+                       pr_devel("axon_msi: late irq 0x%x, retry %d\n",
                                 msi, retry);
                        retry = 0;
                }
@@ -332,7 +332,7 @@ static int axon_msi_shutdown(struct of_device *device)
        struct axon_msic *msic = dev_get_drvdata(&device->dev);
        u32 tmp;
 
-       pr_debug("axon_msi: disabling %s\n",
+       pr_devel("axon_msi: disabling %s\n",
                  msic->irq_host->of_node->full_name);
        tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
        tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
@@ -349,7 +349,7 @@ static int axon_msi_probe(struct of_device *device,
        unsigned int virq;
        int dcr_base, dcr_len;
 
-       pr_debug("axon_msi: setting up dn %s\n", dn->full_name);
+       pr_devel("axon_msi: setting up dn %s\n", dn->full_name);
 
        msic = kzalloc(sizeof(struct axon_msic), GFP_KERNEL);
        if (!msic) {
@@ -403,7 +403,7 @@ static int axon_msi_probe(struct of_device *device,
 
        set_irq_data(virq, msic);
        set_irq_chained_handler(virq, axon_msi_cascade);
-       pr_debug("axon_msi: irq 0x%x setup for axon_msi\n", virq);
+       pr_devel("axon_msi: irq 0x%x setup for axon_msi\n", virq);
 
        /* Enable the MSIC hardware */
        msic_dcr_write(msic, MSIC_BASE_ADDR_HI_REG, msic->fifo_phys >> 32);
@@ -484,13 +484,13 @@ void axon_msi_debug_setup(struct device_node *dn, struct axon_msic *msic)
 
        addr = of_translate_address(dn, of_get_property(dn, "reg", NULL));
        if (addr == OF_BAD_ADDR) {
-               pr_debug("axon_msi: couldn't translate reg property\n");
+               pr_devel("axon_msi: couldn't translate reg property\n");
                return;
        }
 
        msic->trigger = ioremap(addr, 0x4);
        if (!msic->trigger) {
-               pr_debug("axon_msi: ioremap failed\n");
+               pr_devel("axon_msi: ioremap failed\n");
                return;
        }
 
@@ -498,7 +498,7 @@ void axon_msi_debug_setup(struct device_node *dn, struct axon_msic *msic)
 
        if (!debugfs_create_file(name, 0600, powerpc_debugfs_root,
                                 msic, &fops_msic)) {
-               pr_debug("axon_msi: debugfs_create_file failed!\n");
+               pr_devel("axon_msi: debugfs_create_file failed!\n");
                return;
        }
 }
index 9046803c827670a273c5b43d13cee1367ffa16fe..bc97fada48c664662ee59808c9f6424820d42f6a 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/prom.h>
 #include <asm/smp.h>
 #include <asm/paca.h>
-#include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/cputable.h>
 #include <asm/firmware.h>
@@ -140,31 +139,6 @@ static void __devinit smp_cell_setup_cpu(int cpu)
        mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER);
 }
 
-static DEFINE_SPINLOCK(timebase_lock);
-static unsigned long timebase = 0;
-
-static void __devinit cell_give_timebase(void)
-{
-       spin_lock(&timebase_lock);
-       rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
-       timebase = get_tb();
-       spin_unlock(&timebase_lock);
-
-       while (timebase)
-               barrier();
-       rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
-}
-
-static void __devinit cell_take_timebase(void)
-{
-       while (!timebase)
-               barrier();
-       spin_lock(&timebase_lock);
-       set_tb(timebase >> 32, timebase & 0xffffffff);
-       timebase = 0;
-       spin_unlock(&timebase_lock);
-}
-
 static void __devinit smp_cell_kick_cpu(int nr)
 {
        BUG_ON(nr < 0 || nr >= NR_CPUS);
@@ -224,8 +198,8 @@ void __init smp_init_cell(void)
 
        /* Non-lpar has additional take/give timebase */
        if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
-               smp_ops->give_timebase = cell_give_timebase;
-               smp_ops->take_timebase = cell_take_timebase;
+               smp_ops->give_timebase = rtas_give_timebase;
+               smp_ops->take_timebase = rtas_take_timebase;
        }
 
        DBG(" <- smp_init_cell()\n");
index 10a4a4d063b6411b04db150f4bd00980aa67a6ee..02cafecc90e32b9562adf267dd689d742605abc3 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/smp.h>
-#include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/mpic.h>
 #include <asm/rtas.h>
@@ -42,40 +41,12 @@ static void __devinit smp_chrp_setup_cpu(int cpu_nr)
        mpic_setup_this_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);
-       rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
-       timebase_upper = get_tbu();
-       timebase_lower = get_tbl();
-       spin_unlock(&timebase_lock);
-
-       while (timebase_upper || timebase_lower)
-               barrier();
-       rtas_call(rtas_token("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_mpic_message_pass,
        .probe = smp_mpic_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,
+       .give_timebase = rtas_give_timebase,
+       .take_timebase = rtas_take_timebase,
 };
index 153051eb6d9330643e0c3924273a3e6d04a8921f..a4619347aa7e61a702e7a7f6c584080a31d5f4fb 100644 (file)
@@ -71,20 +71,25 @@ static void pas_restart(char *cmd)
 }
 
 #ifdef CONFIG_SMP
-static DEFINE_SPINLOCK(timebase_lock);
+static raw_spinlock_t timebase_lock;
 static unsigned long timebase;
 
 static void __devinit pas_give_timebase(void)
 {
-       spin_lock(&timebase_lock);
+       unsigned long flags;
+
+       local_irq_save(flags);
+       hard_irq_disable();
+       __raw_spin_lock(&timebase_lock);
        mtspr(SPRN_TBCTL, TBCTL_FREEZE);
        isync();
        timebase = get_tb();
-       spin_unlock(&timebase_lock);
+       __raw_spin_unlock(&timebase_lock);
 
        while (timebase)
                barrier();
        mtspr(SPRN_TBCTL, TBCTL_RESTART);
+       local_irq_restore(flags);
 }
 
 static void __devinit pas_take_timebase(void)
@@ -92,10 +97,10 @@ static void __devinit pas_take_timebase(void)
        while (!timebase)
                smp_rmb();
 
-       spin_lock(&timebase_lock);
+       __raw_spin_lock(&timebase_lock);
        set_tb(timebase >> 32, timebase & 0xffffffff);
        timebase = 0;
-       spin_unlock(&timebase_lock);
+       __raw_spin_unlock(&timebase_lock);
 }
 
 struct smp_ops_t pas_smp_ops = {
index 22ecfbe7183dec52e8f907a4ef9a8b23fdfe6a71..708c751333770b216009d1d4d112a0b0a74c08d1 100644 (file)
@@ -251,7 +251,7 @@ static void g5_pfunc_switch_volt(int speed_mode)
 static struct pmf_function *pfunc_cpu_setfreq_high;
 static struct pmf_function *pfunc_cpu_setfreq_low;
 static struct pmf_function *pfunc_cpu_getfreq;
-static struct pmf_function *pfunc_slewing_done;;
+static struct pmf_function *pfunc_slewing_done;
 
 static int g5_pfunc_switch_freq(int speed_mode)
 {
index dce736349107b3b7aa427956a610250c43709458..d212006a5b3c0d4ca5213acdf1d02e0939add083 100644 (file)
@@ -609,7 +609,7 @@ static int pmacpic_find_viaint(void)
        np = of_find_node_by_name(NULL, "via-pmu");
        if (np == NULL)
                goto not_found;
-       viaint = irq_of_parse_and_map(np, 0);;
+       viaint = irq_of_parse_and_map(np, 0);
 
 not_found:
 #endif /* CONFIG_ADB_PMU */
index 86f69a4eb49bfc669012b2681500fd5f0c29e981..c20522656367c9ecbb02f91c86fcab197f080617 100644 (file)
@@ -103,11 +103,6 @@ unsigned long smu_cmdbuf_abs;
 EXPORT_SYMBOL(smu_cmdbuf_abs);
 #endif
 
-#ifdef CONFIG_SMP
-extern struct smp_ops_t psurge_smp_ops;
-extern struct smp_ops_t core99_smp_ops;
-#endif /* CONFIG_SMP */
-
 static void pmac_show_cpuinfo(struct seq_file *m)
 {
        struct device_node *np;
@@ -341,34 +336,6 @@ static void __init pmac_setup_arch(void)
                ROOT_DEV = DEFAULT_ROOT_DEVICE;
 #endif
 
-#ifdef CONFIG_SMP
-       /* Check for Core99 */
-       ic = of_find_node_by_name(NULL, "uni-n");
-       if (!ic)
-               ic = of_find_node_by_name(NULL, "u3");
-       if (!ic)
-               ic = of_find_node_by_name(NULL, "u4");
-       if (ic) {
-               of_node_put(ic);
-               smp_ops = &core99_smp_ops;
-       }
-#ifdef CONFIG_PPC32
-       else {
-               /*
-                * We have to set bits in cpu_possible_map here since the
-                * secondary CPU(s) aren't in the device tree, and
-                * setup_per_cpu_areas only allocates per-cpu data for
-                * CPUs in the cpu_possible_map.
-                */
-               int cpu;
-
-               for (cpu = 1; cpu < 4 && cpu < NR_CPUS; ++cpu)
-                       cpu_set(cpu, cpu_possible_map);
-               smp_ops = &psurge_smp_ops;
-       }
-#endif
-#endif /* CONFIG_SMP */
-
 #ifdef CONFIG_ADB
        if (strstr(cmd_line, "adb_sync")) {
                extern int __adb_probe_sync;
@@ -512,6 +479,14 @@ static void __init pmac_init_early(void)
 #ifdef CONFIG_PPC64
        iommu_init_early_dart();
 #endif
+
+       /* SMP Init has to be done early as we need to patch up
+        * cpu_possible_map before interrupt stacks are allocated
+        * or kaboom...
+        */
+#ifdef CONFIG_SMP
+       pmac_setup_smp();
+#endif
 }
 
 static int __init pmac_declare_of_platform_devices(void)
index cf1dbe758890df60d441cfbd79421db63e40834f..6d4da7b46b419a751891e74b02554d6b7e0a89e1 100644 (file)
 extern void __secondary_start_pmac_0(void);
 extern int pmac_pfunc_base_install(void);
 
-#ifdef CONFIG_PPC32
+static void (*pmac_tb_freeze)(int freeze);
+static u64 timebase;
+static int tb_req;
 
-/* Sync flag for HW tb sync */
-static volatile int sec_tb_reset = 0;
+#ifdef CONFIG_PPC32
 
 /*
  * Powersurge (old powermac SMP) support.
@@ -294,6 +295,9 @@ static int __init smp_psurge_probe(void)
                psurge_quad_init();
                /* All released cards using this HW design have 4 CPUs */
                ncpus = 4;
+               /* No sure how timebase sync works on those, let's use SW */
+               smp_ops->give_timebase = smp_generic_give_timebase;
+               smp_ops->take_timebase = smp_generic_take_timebase;
        } else {
                iounmap(quad_base);
                if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
@@ -308,18 +312,15 @@ static int __init smp_psurge_probe(void)
        psurge_start = ioremap(PSURGE_START, 4);
        psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
 
-       /*
-        * This is necessary because OF doesn't know about the
+       /* This is necessary because OF doesn't know about the
         * secondary cpu(s), and thus there aren't nodes in the
         * device tree for them, and smp_setup_cpu_maps hasn't
-        * set their bits in cpu_possible_map and cpu_present_map.
+        * set their bits in cpu_present_map.
         */
        if (ncpus > NR_CPUS)
                ncpus = NR_CPUS;
-       for (i = 1; i < ncpus ; ++i) {
+       for (i = 1; i < ncpus ; ++i)
                cpu_set(i, cpu_present_map);
-               set_hard_smp_processor_id(i, i);
-       }
 
        if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352);
 
@@ -329,8 +330,14 @@ static int __init smp_psurge_probe(void)
 static void __init smp_psurge_kick_cpu(int nr)
 {
        unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8;
-       unsigned long a;
-       int i;
+       unsigned long a, flags;
+       int i, j;
+
+       /* Defining this here is evil ... but I prefer hiding that
+        * crap to avoid giving people ideas that they can do the
+        * same.
+        */
+       extern volatile unsigned int cpu_callin_map[NR_CPUS];
 
        /* may need to flush here if secondary bats aren't setup */
        for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
@@ -339,47 +346,52 @@ static void __init smp_psurge_kick_cpu(int nr)
 
        if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);
 
+       /* This is going to freeze the timeebase, we disable interrupts */
+       local_irq_save(flags);
+
        out_be32(psurge_start, start);
        mb();
 
        psurge_set_ipi(nr);
+
        /*
         * We can't use udelay here because the timebase is now frozen.
         */
        for (i = 0; i < 2000; ++i)
-               barrier();
+               asm volatile("nop" : : : "memory");
        psurge_clr_ipi(nr);
 
-       if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
-}
-
-/*
- * With the dual-cpu powersurge board, the decrementers and timebases
- * of both cpus are frozen after the secondary cpu is started up,
- * until we give the secondary cpu another interrupt.  This routine
- * uses this to get the timebases synchronized.
- *  -- paulus.
- */
-static void __init psurge_dual_sync_tb(int cpu_nr)
-{
-       int t;
-
-       set_dec(tb_ticks_per_jiffy);
-       /* XXX fixme */
-       set_tb(0, 0);
-
-       if (cpu_nr > 0) {
+       /*
+        * Also, because the timebase is frozen, we must not return to the
+        * caller which will try to do udelay's etc... Instead, we wait -here-
+        * for the CPU to callin.
+        */
+       for (i = 0; i < 100000 && !cpu_callin_map[nr]; ++i) {
+               for (j = 1; j < 10000; j++)
+                       asm volatile("nop" : : : "memory");
+               asm volatile("sync" : : : "memory");
+       }
+       if (!cpu_callin_map[nr])
+               goto stuck;
+
+       /* And we do the TB sync here too for standard dual CPU cards */
+       if (psurge_type == PSURGE_DUAL) {
+               while(!tb_req)
+                       barrier();
+               tb_req = 0;
+               mb();
+               timebase = get_tb();
+               mb();
+               while (timebase)
+                       barrier();
                mb();
-               sec_tb_reset = 1;
-               return;
        }
+ stuck:
+       /* now interrupt the secondary, restarting both TBs */
+       if (psurge_type == PSURGE_DUAL)
+               psurge_set_ipi(1);
 
-       /* wait for the secondary to have reset its TB before proceeding */
-       for (t = 10000000; t > 0 && !sec_tb_reset; --t)
-               ;
-
-       /* now interrupt the secondary, starting both TBs */
-       psurge_set_ipi(1);
+       if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
 }
 
 static struct irqaction psurge_irqaction = {
@@ -390,36 +402,35 @@ static struct irqaction psurge_irqaction = {
 
 static void __init smp_psurge_setup_cpu(int cpu_nr)
 {
+       if (cpu_nr != 0)
+               return;
 
-       if (cpu_nr == 0) {
-               /* If we failed to start the second CPU, we should still
-                * send it an IPI to start the timebase & DEC or we might
-                * have them stuck.
-                */
-               if (num_online_cpus() < 2) {
-                       if (psurge_type == PSURGE_DUAL)
-                               psurge_set_ipi(1);
-                       return;
-               }
-               /* reset the entry point so if we get another intr we won't
-                * try to startup again */
-               out_be32(psurge_start, 0x100);
-               if (setup_irq(30, &psurge_irqaction))
-                       printk(KERN_ERR "Couldn't get primary IPI interrupt");
-       }
-
-       if (psurge_type == PSURGE_DUAL)
-               psurge_dual_sync_tb(cpu_nr);
+       /* reset the entry point so if we get another intr we won't
+        * try to startup again */
+       out_be32(psurge_start, 0x100);
+       if (setup_irq(30, &psurge_irqaction))
+               printk(KERN_ERR "Couldn't get primary IPI interrupt");
 }
 
 void __init smp_psurge_take_timebase(void)
 {
-       /* Dummy implementation */
+       if (psurge_type != PSURGE_DUAL)
+               return;
+
+       tb_req = 1;
+       mb();
+       while (!timebase)
+               barrier();
+       mb();
+       set_tb(timebase >> 32, timebase & 0xffffffff);
+       timebase = 0;
+       mb();
+       set_dec(tb_ticks_per_jiffy/2);
 }
 
 void __init smp_psurge_give_timebase(void)
 {
-       /* Dummy implementation */
+       /* Nothing to do here */
 }
 
 /* PowerSurge-style Macs */
@@ -437,9 +448,6 @@ struct smp_ops_t psurge_smp_ops = {
  * Core 99 and later support
  */
 
-static void (*pmac_tb_freeze)(int freeze);
-static u64 timebase;
-static int tb_req;
 
 static void smp_core99_give_timebase(void)
 {
@@ -478,7 +486,6 @@ static void __devinit smp_core99_take_timebase(void)
        set_tb(timebase >> 32, timebase & 0xffffffff);
        timebase = 0;
        mb();
-       set_dec(tb_ticks_per_jiffy/2);
 
        local_irq_restore(flags);
 }
@@ -920,3 +927,34 @@ struct smp_ops_t core99_smp_ops = {
 # endif
 #endif
 };
+
+void __init pmac_setup_smp(void)
+{
+       struct device_node *np;
+
+       /* Check for Core99 */
+       np = of_find_node_by_name(NULL, "uni-n");
+       if (!np)
+               np = of_find_node_by_name(NULL, "u3");
+       if (!np)
+               np = of_find_node_by_name(NULL, "u4");
+       if (np) {
+               of_node_put(np);
+               smp_ops = &core99_smp_ops;
+       }
+#ifdef CONFIG_PPC32
+       else {
+               /* We have to set bits in cpu_possible_map here since the
+                * secondary CPU(s) aren't in the device tree. Various
+                * things won't be initialized for CPUs not in the possible
+                * map, so we really need to fix it up here.
+                */
+               int cpu;
+
+               for (cpu = 1; cpu < 4 && cpu < NR_CPUS; ++cpu)
+                       cpu_set(cpu, cpu_possible_map);
+               smp_ops = &psurge_smp_ops;
+       }
+#endif /* CONFIG_PPC32 */
+}
+
index 9fead0faf38bbd5930fe0dd0f75fcc1f2711c296..3f763c5284acc2e682f0f9a3832159565bf3598b 100644 (file)
@@ -284,7 +284,6 @@ static int ps3_sb_free_mmio_region(struct ps3_mmio_region *r)
        int result;
 
        dump_mmio_region(r);
-;
        result = lv1_unmap_device_mmio_region(r->dev->bus_id, r->dev->dev_id,
                r->lpar_addr);
 
index b178a1e66c915e8ab6e85b0eec51830b6a05adf1..40b5cb433005f615381d205e3d281dbd5b1377f4 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 
+#include <asm/firmware.h>
 #include <asm/rtc.h>
 #include <asm/lv1call.h>
 #include <asm/ps3.h>
@@ -84,6 +85,9 @@ static int __init ps3_rtc_init(void)
 {
        struct platform_device *pdev;
 
+       if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+               return -ENODEV;
+
        pdev = platform_device_register_simple("rtc-ps3", -1, NULL, 0);
        if (IS_ERR(pdev))
                return PTR_ERR(pdev);
index e3139fa5e556e78ddcdeacc4e4850b7aeeba6ed4..903eb9eec687471628c37e30026ae6aad5c35548 100644 (file)
@@ -286,7 +286,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
        unsigned long hpte_v, hpte_r;
 
        if (!(vflags & HPTE_V_BOLTED))
-               pr_debug("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
+               pr_devel("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
                         "rflags=%lx, vflags=%lx, psize=%d)\n",
                         hpte_group, va, pa, rflags, vflags, psize);
 
@@ -294,7 +294,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
        hpte_r = hpte_encode_r(pa, psize) | rflags;
 
        if (!(vflags & HPTE_V_BOLTED))
-               pr_debug(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
+               pr_devel(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
 
        /* Now fill in the actual HPTE */
        /* Set CEC cookie to 0         */
@@ -311,7 +311,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
        lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot);
        if (unlikely(lpar_rc == H_PTEG_FULL)) {
                if (!(vflags & HPTE_V_BOLTED))
-                       pr_debug(" full\n");
+                       pr_devel(" full\n");
                return -1;
        }
 
@@ -322,11 +322,11 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
         */
        if (unlikely(lpar_rc != H_SUCCESS)) {
                if (!(vflags & HPTE_V_BOLTED))
-                       pr_debug(" lpar err %lu\n", lpar_rc);
+                       pr_devel(" lpar err %lu\n", lpar_rc);
                return -2;
        }
        if (!(vflags & HPTE_V_BOLTED))
-               pr_debug(" -> slot: %lu\n", slot & 7);
+               pr_devel(" -> slot: %lu\n", slot & 7);
 
        /* Because of iSeries, we have to pass down the secondary
         * bucket bit here as well
@@ -418,17 +418,17 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot,
 
        want_v = hpte_encode_avpn(va, psize, ssize);
 
-       pr_debug("    update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
+       pr_devel("    update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
                 want_v, slot, flags, psize);
 
        lpar_rc = plpar_pte_protect(flags, slot, want_v);
 
        if (lpar_rc == H_NOT_FOUND) {
-               pr_debug("not found !\n");
+               pr_devel("not found !\n");
                return -1;
        }
 
-       pr_debug("ok\n");
+       pr_devel("ok\n");
 
        BUG_ON(lpar_rc != H_SUCCESS);
 
@@ -503,7 +503,7 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
        unsigned long lpar_rc;
        unsigned long dummy1, dummy2;
 
-       pr_debug("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
+       pr_devel("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
                 slot, va, psize, local);
 
        want_v = hpte_encode_avpn(va, psize, ssize);
index 1a231c389ba0122ce7f55419962af8a1bbdab25f..1f8f6cfb94f7f504b4f44f025fc02b600b392000 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/prom.h>
 #include <asm/smp.h>
 #include <asm/paca.h>
-#include <asm/time.h>
 #include <asm/machdep.h>
 #include <asm/cputable.h>
 #include <asm/firmware.h>
@@ -118,31 +117,6 @@ static void __devinit smp_xics_setup_cpu(int cpu)
 }
 #endif /* CONFIG_XICS */
 
-static DEFINE_SPINLOCK(timebase_lock);
-static unsigned long timebase = 0;
-
-static void __devinit pSeries_give_timebase(void)
-{
-       spin_lock(&timebase_lock);
-       rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL);
-       timebase = get_tb();
-       spin_unlock(&timebase_lock);
-
-       while (timebase)
-               barrier();
-       rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
-}
-
-static void __devinit pSeries_take_timebase(void)
-{
-       while (!timebase)
-               barrier();
-       spin_lock(&timebase_lock);
-       set_tb(timebase >> 32, timebase & 0xffffffff);
-       timebase = 0;
-       spin_unlock(&timebase_lock);
-}
-
 static void __devinit smp_pSeries_kick_cpu(int nr)
 {
        BUG_ON(nr < 0 || nr >= NR_CPUS);
@@ -209,8 +183,8 @@ static void __init smp_init_pseries(void)
 
        /* Non-lpar has additional take/give timebase */
        if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
-               smp_ops->give_timebase = pSeries_give_timebase;
-               smp_ops->take_timebase = pSeries_take_timebase;
+               smp_ops->give_timebase = rtas_give_timebase;
+               smp_ops->take_timebase = rtas_take_timebase;
        }
 
        pr_debug(" <- smp_init_pSeries()\n");
index be3581a8c294c8de4d083b1b2c5710381a35c2d9..419f8a637ffe5b73db8c69080e118c2fdab00444 100644 (file)
@@ -190,10 +190,10 @@ static void xics_unmask_irq(unsigned int virq)
        int call_status;
        int server;
 
-       pr_debug("xics: unmask virq %d\n", virq);
+       pr_devel("xics: unmask virq %d\n", virq);
 
        irq = (unsigned int)irq_map[virq].hwirq;
-       pr_debug(" -> map to hwirq 0x%x\n", irq);
+       pr_devel(" -> map to hwirq 0x%x\n", irq);
        if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
                return;
 
@@ -252,7 +252,7 @@ static void xics_mask_irq(unsigned int virq)
 {
        unsigned int irq;
 
-       pr_debug("xics: mask virq %d\n", virq);
+       pr_devel("xics: mask virq %d\n", virq);
 
        irq = (unsigned int)irq_map[virq].hwirq;
        if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
@@ -414,7 +414,7 @@ static int xics_host_match(struct irq_host *h, struct device_node *node)
 static int xics_host_map(struct irq_host *h, unsigned int virq,
                         irq_hw_number_t hw)
 {
-       pr_debug("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
+       pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
 
        /* Insert the interrupt mapping into the radix tree for fast lookup */
        irq_radix_revmap_insert(xics_host, virq, hw);
index 39db9d1155d27466ffe176887c7d9b2c320f288f..cbb3bed75d3c0c56a218e1a2678702d6ca0bcfd7 100644 (file)
@@ -965,7 +965,7 @@ static inline void fsl_rio_info(struct device *dev, u32 ccsr)
                        break;
                default:
                        str = "Unknown";
-                       break;;
+                       break;
                }
                dev_info(dev, "Hardware port width: %s\n", str);
 
index a86d3ce01ead98293dcb0e28a14bf943163b40a2..69e2630c90624cf40690d0ecfd7643a75e1d4bf5 100644 (file)
@@ -728,12 +728,10 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
        if (ret)
                return NULL;
 
-       ipic = alloc_bootmem(sizeof(struct ipic));
+       ipic = kzalloc(sizeof(*ipic), GFP_KERNEL);
        if (ipic == NULL)
                return NULL;
 
-       memset(ipic, 0, sizeof(struct ipic));
-
        ipic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
                                       NR_IPIC_INTS,
                                       &ipic_host_ops, 0);
index 9c3af5045495bb67c0259998a39dd641c65e47ea..3981ae4cb58e7f3f41fb7ffa25e9a4757bed3d6f 100644 (file)
@@ -279,28 +279,29 @@ static void _mpic_map_mmio(struct mpic *mpic, phys_addr_t phys_addr,
 }
 
 #ifdef CONFIG_PPC_DCR
-static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb,
+static void _mpic_map_dcr(struct mpic *mpic, struct device_node *node,
+                         struct mpic_reg_bank *rb,
                          unsigned int offset, unsigned int size)
 {
        const u32 *dbasep;
 
-       dbasep = of_get_property(mpic->irqhost->of_node, "dcr-reg", NULL);
+       dbasep = of_get_property(node, "dcr-reg", NULL);
 
-       rb->dhost = dcr_map(mpic->irqhost->of_node, *dbasep + offset, size);
+       rb->dhost = dcr_map(node, *dbasep + offset, size);
        BUG_ON(!DCR_MAP_OK(rb->dhost));
 }
 
-static inline void mpic_map(struct mpic *mpic, phys_addr_t phys_addr,
-                           struct mpic_reg_bank *rb, unsigned int offset,
-                           unsigned int size)
+static inline void mpic_map(struct mpic *mpic, struct device_node *node,
+                           phys_addr_t phys_addr, struct mpic_reg_bank *rb,
+                           unsigned int offset, unsigned int size)
 {
        if (mpic->flags & MPIC_USES_DCR)
-               _mpic_map_dcr(mpic, rb, offset, size);
+               _mpic_map_dcr(mpic, node, rb, offset, size);
        else
                _mpic_map_mmio(mpic, phys_addr, rb, offset, size);
 }
 #else /* CONFIG_PPC_DCR */
-#define mpic_map(m,p,b,o,s)    _mpic_map_mmio(m,p,b,o,s)
+#define mpic_map(m,n,p,b,o,s)  _mpic_map_mmio(m,p,b,o,s)
 #endif /* !CONFIG_PPC_DCR */
 
 
@@ -507,9 +508,8 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
        printk(KERN_INFO "mpic: Setting up HT PICs workarounds for U3/U4\n");
 
        /* Allocate fixups array */
-       mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup));
+       mpic->fixups = kzalloc(128 * sizeof(*mpic->fixups), GFP_KERNEL);
        BUG_ON(mpic->fixups == NULL);
-       memset(mpic->fixups, 0, 128 * sizeof(struct mpic_irq_fixup));
 
        /* Init spinlock */
        spin_lock_init(&mpic->fixup_lock);
@@ -1052,11 +1052,10 @@ struct mpic * __init mpic_alloc(struct device_node *node,
        int             intvec_top;
        u64             paddr = phys_addr;
 
-       mpic = alloc_bootmem(sizeof(struct mpic));
+       mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL);
        if (mpic == NULL)
                return NULL;
-       
-       memset(mpic, 0, sizeof(struct mpic));
+
        mpic->name = name;
 
        mpic->hc_irq = mpic_irq_chip;
@@ -1109,9 +1108,8 @@ struct mpic * __init mpic_alloc(struct device_node *node,
                        psize /= 4;
                        bits = intvec_top + 1;
                        mapsize = BITS_TO_LONGS(bits) * sizeof(unsigned long);
-                       mpic->protected = alloc_bootmem(mapsize);
+                       mpic->protected = kzalloc(mapsize, GFP_KERNEL);
                        BUG_ON(mpic->protected == NULL);
-                       memset(mpic->protected, 0, mapsize);
                        for (i = 0; i < psize; i++) {
                                if (psrc[i] > intvec_top)
                                        continue;
@@ -1152,8 +1150,8 @@ struct mpic * __init mpic_alloc(struct device_node *node,
        }
 
        /* Map the global registers */
-       mpic_map(mpic, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000);
-       mpic_map(mpic, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
+       mpic_map(mpic, node, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000);
+       mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
 
        /* Reset */
        if (flags & MPIC_WANTS_RESET) {
@@ -1194,7 +1192,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
 
        /* Map the per-CPU registers */
        for (i = 0; i < mpic->num_cpus; i++) {
-               mpic_map(mpic, paddr, &mpic->cpuregs[i],
+               mpic_map(mpic, node, paddr, &mpic->cpuregs[i],
                         MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE),
                         0x1000);
        }
@@ -1202,7 +1200,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
        /* Initialize main ISU if none provided */
        if (mpic->isu_size == 0) {
                mpic->isu_size = mpic->num_sources;
-               mpic_map(mpic, paddr, &mpic->isus[0],
+               mpic_map(mpic, node, paddr, &mpic->isus[0],
                         MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
        }
        mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
@@ -1256,8 +1254,10 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
 
        BUG_ON(isu_num >= MPIC_MAX_ISU);
 
-       mpic_map(mpic, paddr, &mpic->isus[isu_num], 0,
+       mpic_map(mpic, mpic->irqhost->of_node,
+                paddr, &mpic->isus[isu_num], 0,
                 MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
+
        if ((isu_first + mpic->isu_size) > mpic->num_sources)
                mpic->num_sources = isu_first + mpic->isu_size;
 }
@@ -1351,7 +1351,8 @@ void __init mpic_init(struct mpic *mpic)
 
 #ifdef CONFIG_PM
        /* allocate memory to save mpic state */
-       mpic->save_data = alloc_bootmem(mpic->num_sources * sizeof(struct mpic_irq_save));
+       mpic->save_data = kmalloc(mpic->num_sources * sizeof(*mpic->save_data),
+                                 GFP_KERNEL);
        BUG_ON(mpic->save_data == NULL);
 #endif
 }
index daefc93ddffec42eb4e15ccfb218e127ccee4032..6ff9d71b4c0d877e99aedef1fd9d3820bd424a3d 100644 (file)
@@ -1531,7 +1531,7 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
                 */
 
                /* Calculate window size */
-               sa = (0xffffffffffffffffull << ilog2(ep_size));;
+               sa = (0xffffffffffffffffull << ilog2(ep_size));
 
                /* Setup BAR0 */
                out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
@@ -1550,7 +1550,7 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
                out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(ep_addr));
        } else {
                /* Calculate window size */
-               sa = (0xffffffffffffffffull << ilog2(size));;
+               sa = (0xffffffffffffffffull << ilog2(size));
                if (res->flags & IORESOURCE_PREFETCH)
                        sa |= 0x8;
 
index b28b0e512d67d91a2c1fb108f94cc9eea90e4b03..237e3654f48ca6b1059c7d2017ccd31544b215e2 100644 (file)
@@ -112,6 +112,7 @@ int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input)
 {
        unsigned long flags;
        u8 mcn_shift = 0, dev_shift = 0;
+       u32 ret;
 
        spin_lock_irqsave(&qe_lock, flags);
        if (cmd == QE_RESET) {
@@ -139,11 +140,13 @@ int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input)
        }
 
        /* wait for the QE_CR_FLG to clear */
-       while(in_be32(&qe_immr->cp.cecr) & QE_CR_FLG)
-               cpu_relax();
+       ret = spin_event_timeout((in_be32(&qe_immr->cp.cecr) & QE_CR_FLG) == 0,
+                          100, 0);
+       /* On timeout (e.g. failure), the expression will be false (ret == 0),
+          otherwise it will be true (ret == 1). */
        spin_unlock_irqrestore(&qe_lock, flags);
 
-       return 0;
+       return ret == 1;
 }
 EXPORT_SYMBOL(qe_issue_cmd);
 
index 63cdf9887f3672dd4e16310b591b91d564de20bd..074905c3ee5a94d80fb3e0daa86e88b8f77f9650 100644 (file)
@@ -333,12 +333,10 @@ void __init qe_ic_init(struct device_node *node, unsigned int flags,
        if (ret)
                return;
 
-       qe_ic = alloc_bootmem(sizeof(struct qe_ic));
+       qe_ic = kzalloc(sizeof(*qe_ic), GFP_KERNEL);
        if (qe_ic == NULL)
                return;
 
-       memset(qe_ic, 0, sizeof(struct qe_ic));
-
        qe_ic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
                                        NR_QE_IC_INTS, &qe_ic_host_ops, 0);
        if (qe_ic->irqhost == NULL)
index d35405c5943482c86efea86739099ed8c2f3da1e..466ce9ace1270ec881a4ae2f18e92a70648af40b 100644 (file)
@@ -258,11 +258,10 @@ static struct uic * __init uic_init_one(struct device_node *node)
 
        BUG_ON(! of_device_is_compatible(node, "ibm,uic"));
 
-       uic = alloc_bootmem(sizeof(*uic));
+       uic = kzalloc(sizeof(*uic), GFP_KERNEL);
        if (! uic)
                return NULL; /* FIXME: panic? */
 
-       memset(uic, 0, sizeof(*uic));
        spin_lock_init(&uic->lock);
        indexp = of_get_property(node, "cell-index", &len);
        if (!indexp || (len != sizeof(u32))) {
index 3ee1fd37bbfc3b819107a8dd4d9b2496f59ecc84..40edad520770e335c1afc7a7af0463f159972ef4 100644 (file)
@@ -234,7 +234,6 @@ static void xilinx_i8259_cascade(unsigned int irq, struct irq_desc *desc)
                generic_handle_irq(cascade_irq);
 
        /* Let xilinx_intc end the interrupt */
-       desc->chip->ack(irq);
        desc->chip->unmask(irq);
 }
 
index e577839f3073e5a6e5687193817ddcb6e354c423..2ae5d72f47edaad3198a030c0ee7ed09deeea6b8 100644 (file)
@@ -95,6 +95,11 @@ config S390
        select HAVE_ARCH_TRACEHOOK
        select INIT_ALL_POSSIBLE
        select HAVE_PERF_COUNTERS
+       select GENERIC_ATOMIC64 if !64BIT
+
+config SCHED_OMIT_FRAME_POINTER
+       bool
+       default y
 
 source "init/Kconfig"
 
@@ -116,6 +121,9 @@ config 32BIT
        bool
        default y if !64BIT
 
+config KTIME_SCALAR
+       def_bool 32BIT
+
 config SMP
        bool "Symmetric multi-processing support"
        ---help---
index fca9dffcc669b186f779785ae8d1ac3a9858c356..c7d0abfb0f0089a9ed9b716a31928c563abc18e2 100644 (file)
@@ -268,7 +268,12 @@ static __inline__ int atomic64_add_unless(atomic64_t *v,
 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
 
 #undef __CSG_LOOP
-#endif
+
+#else /* __s390x__ */
+
+#include <asm-generic/atomic64.h>
+
+#endif /* __s390x__ */
 
 #define smp_mb__before_atomic_dec()    smp_mb()
 #define smp_mb__after_atomic_dec()     smp_mb()
index a27d0d5a6f8689fa81f558686cad2f378487be42..1cd02f6073a06c0b58e8188d04eb9ebc3e4d7d7d 100644 (file)
@@ -99,7 +99,9 @@ struct kvm_s390_sie_block {
        __u8    reservedd0[48];         /* 0x00d0 */
        __u64   gcr[16];                /* 0x0100 */
        __u64   gbea;                   /* 0x0180 */
-       __u8    reserved188[120];       /* 0x0188 */
+       __u8    reserved188[24];        /* 0x0188 */
+       __u32   fac;                    /* 0x01a0 */
+       __u8    reserved1a4[92];        /* 0x01a4 */
 } __attribute__((packed));
 
 struct kvm_vcpu_stat {
index a7205a3828cb1553b89bb6730263c6549f26fbb9..7015188c2cc275b5cb86ad4ee1d4e326239f9fcc 100644 (file)
@@ -6,3 +6,5 @@
 
 static inline void set_perf_counter_pending(void) {}
 static inline void clear_perf_counter_pending(void) {}
+
+#define PERF_COUNTER_INDEX_OFFSET 0
index 925bcc6490354c3f2fa2c5dbbca8b37b553b1bd6..ba1cab9fc1f92cd19acfe34d2353cce8a0858c7e 100644 (file)
@@ -61,7 +61,7 @@ struct thread_info {
        .exec_domain    = &default_exec_domain, \
        .flags          = 0,                    \
        .cpu            = 0,                    \
-       .preempt_count  = 1,                    \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .restart_block  = {                     \
                .fn = do_no_restart_syscall,    \
        },                                      \
index 3d8a96d39d9d6a9a999c0f493911af00e204b605..81150b0536890b7d664052a33f22d397bb05b852 100644 (file)
@@ -96,7 +96,8 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
  * pte_free_tlb frees a pte table and clears the CRSTE for the
  * page table from the tlb.
  */
-static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte)
+static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
+                               unsigned long address)
 {
        if (!tlb->fullmm) {
                tlb->array[tlb->nr_ptes++] = pte;
@@ -113,7 +114,8 @@ static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte)
  * as the pgd. pmd_free_tlb checks the asce_limit against 2GB
  * to avoid the double free of the pmd in this case.
  */
-static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
+                               unsigned long address)
 {
 #ifdef __s390x__
        if (tlb->mm->context.asce_limit <= (1UL << 31))
@@ -134,7 +136,8 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
  * as the pgd. pud_free_tlb checks the asce_limit against 4TB
  * to avoid the double free of the pud in this case.
  */
-static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
+static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
+                               unsigned long address)
 {
 #ifdef __s390x__
        if (tlb->mm->context.asce_limit <= (1UL << 42))
index d2f270c995d9baefa6ac75a743c4d5d165441b57..db943a7ec51331f5f471c23f838e454eb46c99b2 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
index f9b144049dc983ef16419a415feadb14e2c0374b..cae14c499511c6f5358170906764a95045ed4b39 100644 (file)
@@ -208,9 +208,12 @@ static noinline __init void detect_machine_type(void)
                machine_flags |= MACHINE_FLAG_KVM;
        else
                machine_flags |= MACHINE_FLAG_VM;
+
+       /* Store machine flags for setting up lowcore early */
+       S390_lowcore.machine_flags = machine_flags;
 }
 
-static void early_pgm_check_handler(void)
+static __init void early_pgm_check_handler(void)
 {
        unsigned long addr;
        const struct exception_table_entry *fixup;
@@ -222,7 +225,7 @@ static void early_pgm_check_handler(void)
        S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE;
 }
 
-void setup_lowcore_early(void)
+static noinline __init void setup_lowcore_early(void)
 {
        psw_t psw;
 
index b8bf4b140065226bbb8f48e3f4eadd07e8c04b7b..371a2d88f4ac7b6e170134b96b4924c69f8a8b99 100644 (file)
@@ -70,6 +70,7 @@ struct shutdown_action {
        char *name;
        void (*fn) (struct shutdown_trigger *trigger);
        int (*init) (void);
+       int init_rc;
 };
 
 static char *ipl_type_str(enum ipl_type type)
@@ -1486,11 +1487,13 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger,
        int i;
 
        for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
-               if (!shutdown_actions_list[i])
-                       continue;
                if (sysfs_streq(buf, shutdown_actions_list[i]->name)) {
-                       trigger->action = shutdown_actions_list[i];
-                       return len;
+                       if (shutdown_actions_list[i]->init_rc) {
+                               return shutdown_actions_list[i]->init_rc;
+                       } else {
+                               trigger->action = shutdown_actions_list[i];
+                               return len;
+                       }
                }
        }
        return -EINVAL;
@@ -1640,8 +1643,8 @@ static void __init shutdown_actions_init(void)
        for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) {
                if (!shutdown_actions_list[i]->init)
                        continue;
-               if (shutdown_actions_list[i]->init())
-                       shutdown_actions_list[i] = NULL;
+               shutdown_actions_list[i]->init_rc =
+                       shutdown_actions_list[i]->init();
        }
 }
 
index 490b39934d65aa8a98cc76f5772b10f3ef9735ea..43acd73105b7f06f279776a9c96be780ae1927ce 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
index 9717717c6fea5595b364e8b321ee6fa284580396..cbb897bc50bd5d56606c190cafb69f5c4670d8fb 100644 (file)
@@ -154,6 +154,20 @@ static int __init condev_setup(char *str)
 
 __setup("condev=", condev_setup);
 
+static void __init set_preferred_console(void)
+{
+       if (MACHINE_IS_KVM) {
+               add_preferred_console("hvc", 0, NULL);
+               s390_virtio_console_init();
+               return;
+       }
+
+       if (CONSOLE_IS_3215 || CONSOLE_IS_SCLP)
+               add_preferred_console("ttyS", 0, NULL);
+       if (CONSOLE_IS_3270)
+               add_preferred_console("tty3270", 0, NULL);
+}
+
 static int __init conmode_setup(char *str)
 {
 #if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
@@ -168,6 +182,7 @@ static int __init conmode_setup(char *str)
        if (strncmp(str, "3270", 5) == 0)
                SET_CONSOLE_3270;
 #endif
+       set_preferred_console();
         return 1;
 }
 
@@ -780,9 +795,6 @@ static void __init setup_hwcaps(void)
 void __init
 setup_arch(char **cmdline_p)
 {
-       /* set up preferred console */
-       add_preferred_console("ttyS", 0, NULL);
-
         /*
          * print what head.S has found out about the machine
          */
@@ -802,11 +814,9 @@ setup_arch(char **cmdline_p)
        if (MACHINE_IS_VM)
                pr_info("Linux is running as a z/VM "
                        "guest operating system in 64-bit mode\n");
-       else if (MACHINE_IS_KVM) {
+       else if (MACHINE_IS_KVM)
                pr_info("Linux is running under KVM in 64-bit mode\n");
-               add_preferred_console("hvc", 0, NULL);
-               s390_virtio_console_init();
-       } else
+       else
                pr_info("Linux is running natively in 64-bit mode\n");
 #endif /* CONFIG_64BIT */
 
@@ -851,6 +861,7 @@ setup_arch(char **cmdline_p)
 
         /* Setup default console */
        conmode_default();
+       set_preferred_console();
 
        /* Setup zfcpdump support */
        setup_zfcpdump(console_devno);
index 2270730f535451f647aeea1e51abdc36ac8af542..be2cae083406206c949330ee1a267fb7136a969e 100644 (file)
@@ -687,13 +687,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 #ifndef CONFIG_64BIT
        if (MACHINE_HAS_IEEE)
                lowcore->extended_save_area_addr = (u32) save_area;
-#else
-       if (vdso_alloc_per_cpu(smp_processor_id(), lowcore))
-               BUG();
 #endif
        set_prefix((u32)(unsigned long) lowcore);
        local_mcck_enable();
        local_irq_enable();
+#ifdef CONFIG_64BIT
+       if (vdso_alloc_per_cpu(smp_processor_id(), &S390_lowcore))
+               BUG();
+#endif
        for_each_possible_cpu(cpu)
                if (cpu != smp_processor_id())
                        smp_create_idle(cpu);
index 79dbfee831ec00cf05e0fef2c8b993f1da911697..49106c6e6f88336ab9e3d641e97ba25b8179df04 100644 (file)
@@ -88,10 +88,17 @@ __kernel_clock_gettime:
        llilh   %r4,0x0100
        sar     %a4,%r4
        lghi    %r4,0
+       epsw    %r5,0
        sacf    512                             /* Magic ectg instruction */
        .insn   ssf,0xc80100000000,__VDSO_ECTG_BASE(4),__VDSO_ECTG_USER(4),4
-       sacf    0
-       sar     %a4,%r2
+       tml     %r5,0x4000
+       jo      11f
+       tml     %r5,0x8000
+       jno     10f
+       sacf    256
+       j       11f
+10:    sacf    0
+11:    sar     %a4,%r2
        algr    %r1,%r0                         /* r1 = cputime as TOD value */
        mghi    %r1,1000                        /* convert to nanoseconds */
        srlg    %r1,%r1,12                      /* r1 = cputime in nanosec */
index f04f5301b1b42fdd06207c93a84bd6568594cd72..4d613415c435932f9fb14ce0d8bd92d350ac2f85 100644 (file)
@@ -386,7 +386,7 @@ no_timer:
        }
        __unset_cpu_idle(vcpu);
        __set_current_state(TASK_RUNNING);
-       remove_wait_queue(&vcpu->wq, &wait);
+       remove_wait_queue(&vcpu->arch.local_int.wq, &wait);
        spin_unlock_bh(&vcpu->arch.local_int.lock);
        spin_unlock(&vcpu->arch.local_int.float_int->lock);
        hrtimer_try_to_cancel(&vcpu->arch.ckc_timer);
index c18b21d6991cebacdb8dfb4358017db75782eb44..90d9d1ba258b0458b23df8892a20a792523f1b14 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/lowcore.h>
 #include <asm/pgtable.h>
 #include <asm/nmi.h>
+#include <asm/system.h>
 #include "kvm-s390.h"
 #include "gaccess.h"
 
@@ -69,6 +70,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { NULL }
 };
 
+static unsigned long long *facilities;
 
 /* Section: not file related */
 void kvm_arch_hardware_enable(void *garbage)
@@ -288,6 +290,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        vcpu->arch.sie_block->gmsor = vcpu->kvm->arch.guest_origin;
        vcpu->arch.sie_block->ecb   = 2;
        vcpu->arch.sie_block->eca   = 0xC1002001U;
+       vcpu->arch.sie_block->fac   = (int) (long) facilities;
        hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
        tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet,
                     (unsigned long) vcpu);
@@ -739,11 +742,29 @@ gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
 
 static int __init kvm_s390_init(void)
 {
-       return kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE);
+       int ret;
+       ret = kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE);
+       if (ret)
+               return ret;
+
+       /*
+        * guests can ask for up to 255+1 double words, we need a full page
+        * to hold the maximum amount of facilites. On the other hand, we
+        * only set facilities that are known to work in KVM.
+        */
+       facilities = (unsigned long long *) get_zeroed_page(GFP_DMA);
+       if (!facilities) {
+               kvm_exit();
+               return -ENOMEM;
+       }
+       stfle(facilities, 1);
+       facilities[0] &= 0xff00fff3f0700000ULL;
+       return 0;
 }
 
 static void __exit kvm_s390_exit(void)
 {
+       free_page((unsigned long) facilities);
        kvm_exit();
 }
 
index 93ecd06e1a749fc866177c5bd5c6bcdd6ae82e81..d426aac8095de3552177158bc88fa72e1ef9a82e 100644 (file)
@@ -158,7 +158,7 @@ static int handle_stfl(struct kvm_vcpu *vcpu)
 
        vcpu->stat.instruction_stfl++;
        /* only pass the facility bits, which we can handle */
-       facility_list &= 0xfe00fff3;
+       facility_list &= 0xff00fff3;
 
        rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list),
                           &facility_list, sizeof(facility_list));
index 36678835034d9f49a748f448fd943073e9974564..0ef81d6776e97c934792027415267ad95d579136 100644 (file)
@@ -169,7 +169,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
                             unsigned long *reg)
 {
        struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
-       struct kvm_s390_local_interrupt *li;
+       struct kvm_s390_local_interrupt *li = NULL;
        struct kvm_s390_interrupt_info *inti;
        int rc;
        u8 tmp;
@@ -189,9 +189,10 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
                return 2; /* busy */
 
        spin_lock(&fi->lock);
-       li = fi->local_int[cpu_addr];
+       if (cpu_addr < KVM_MAX_VCPUS)
+               li = fi->local_int[cpu_addr];
 
-       if ((cpu_addr >= KVM_MAX_VCPUS) || (li == NULL)) {
+       if (li == NULL) {
                rc = 1; /* incorrect state */
                *reg &= SIGP_STAT_INCORRECT_STATE;
                kfree(inti);
index ab6735df2d2155b2755170048701f979272e6f03..97975ec7a27471253a8da274af72d14a16e9f171 100644 (file)
@@ -3,6 +3,6 @@
 #
 
 lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
-obj-$(CONFIG_32BIT) += div64.o qrnnd.o
+obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o
 lib-$(CONFIG_64BIT) += uaccess_mvcos.o
 lib-$(CONFIG_SMP) += spinlock.o
index 3f5f680726ed1e03bc74cc40a4217a93ab89e837..97c1eca83cc24274e796c491f60d5851252de150 100644 (file)
@@ -36,9 +36,11 @@ static void __udelay_disabled(unsigned long usecs)
        cr0 = (cr0_saved & 0xffff00e0) | 0x00000800;
        __ctl_load(cr0 , 0, 0);
        mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
+       lockdep_off();
        trace_hardirqs_on();
        __load_psw_mask(mask);
        local_irq_disable();
+       lockdep_on();
        __ctl_load(cr0_saved, 0, 0);
        local_tick_enable(clock_saved);
        set_clock_comparator(S390_lowcore.clock_comparator);
diff --git a/arch/s390/lib/ucmpdi2.c b/arch/s390/lib/ucmpdi2.c
new file mode 100644 (file)
index 0000000..3e05ff5
--- /dev/null
@@ -0,0 +1,26 @@
+#include <linux/module.h>
+
+union ull_union {
+       unsigned long long ull;
+       struct {
+               unsigned int high;
+               unsigned int low;
+       } ui;
+};
+
+int __ucmpdi2(unsigned long long a, unsigned long long b)
+{
+       union ull_union au = {.ull = a};
+       union ull_union bu = {.ull = b};
+
+       if (au.ui.high < bu.ui.high)
+               return 0;
+       else if (au.ui.high > bu.ui.high)
+               return 2;
+       if (au.ui.low < bu.ui.low)
+               return 0;
+       else if (au.ui.low > bu.ui.low)
+               return 2;
+       return 1;
+}
+EXPORT_SYMBOL(__ucmpdi2);
index 74eb26bf1970ee4f92bf3d6f34e3036471a6302d..e5e119fe03b2c18b0664c4ed48653889380aa7ac 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/compat.h>
 #include <linux/smp.h>
 #include <linux/kdebug.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/module.h>
index e6a4fe9f5f247154eab2ba960bf2c376ffdd9a27..bd1f5c6b0b8c57f12e96ec41f7f8f7538c222855 100644 (file)
@@ -7,24 +7,36 @@
  *
  */
 
+#include <asm/system.h>
 
-/*
- * save CPU registers before creating a hibernation image and before
- * restoring the memory state from it
- */
 void save_processor_state(void)
 {
-       /* implentation contained in the
-        * swsusp_arch_suspend function
+       /* swsusp_arch_suspend() actually saves all cpu register contents.
+        * Machine checks must be disabled since swsusp_arch_suspend() stores
+        * register contents to their lowcore save areas. That's the same
+        * place where register contents on machine checks would be saved.
+        * To avoid register corruption disable machine checks.
+        * We must also disable machine checks in the new psw mask for
+        * program checks, since swsusp_arch_suspend() may generate program
+        * checks. Disabling machine checks for all other new psw masks is
+        * just paranoia.
         */
+       local_mcck_disable();
+       /* Disable lowcore protection */
+       __ctl_clear_bit(0,28);
+       S390_lowcore.external_new_psw.mask &= ~PSW_MASK_MCHECK;
+       S390_lowcore.svc_new_psw.mask &= ~PSW_MASK_MCHECK;
+       S390_lowcore.io_new_psw.mask &= ~PSW_MASK_MCHECK;
+       S390_lowcore.program_new_psw.mask &= ~PSW_MASK_MCHECK;
 }
 
-/*
- * restore the contents of CPU registers
- */
 void restore_processor_state(void)
 {
-       /* implentation contained in the
-        * swsusp_arch_resume function
-        */
+       S390_lowcore.external_new_psw.mask |= PSW_MASK_MCHECK;
+       S390_lowcore.svc_new_psw.mask |= PSW_MASK_MCHECK;
+       S390_lowcore.io_new_psw.mask |= PSW_MASK_MCHECK;
+       S390_lowcore.program_new_psw.mask |= PSW_MASK_MCHECK;
+       /* Enable lowcore protection */
+       __ctl_set_bit(0,28);
+       local_mcck_enable();
 }
index 76d688da32fa3d65ee22d80041daa0baca8565bb..b26df5c5933e1d682f0dfb8f13239269b36a8bf8 100644 (file)
@@ -32,19 +32,14 @@ swsusp_arch_suspend:
        /* Deactivate DAT */
        stnsm   __SF_EMPTY(%r15),0xfb
 
-       /* Switch off lowcore protection */
-       stctg   %c0,%c0,__SF_EMPTY(%r15)
-       ni      __SF_EMPTY+4(%r15),0xef
-       lctlg   %c0,%c0,__SF_EMPTY(%r15)
-
        /* Store prefix register on stack */
        stpx    __SF_EMPTY(%r15)
 
-       /* Setup base register for lowcore (absolute 0) */
-       llgf    %r1,__SF_EMPTY(%r15)
+       /* Save prefix register contents for lowcore */
+       llgf    %r4,__SF_EMPTY(%r15)
 
        /* Get pointer to save area */
-       aghi    %r1,0x1000
+       lghi    %r1,0x1000
 
        /* Store registers */
        mvc     0x318(4,%r1),__SF_EMPTY(%r15)   /* move prefix to lowcore */
@@ -79,17 +74,15 @@ swsusp_arch_suspend:
        xc      __SF_EMPTY(4,%r15),__SF_EMPTY(%r15)
        spx     __SF_EMPTY(%r15)
 
-       /* Setup lowcore */
-       brasl   %r14,setup_lowcore_early
+       lghi    %r2,0
+       lghi    %r3,2*PAGE_SIZE
+       lghi    %r5,2*PAGE_SIZE
+1:     mvcle   %r2,%r4,0
+       jo      1b
 
        /* Save image */
        brasl   %r14,swsusp_save
 
-       /* Switch on lowcore protection */
-       stctg   %c0,%c0,__SF_EMPTY(%r15)
-       oi      __SF_EMPTY+4(%r15),0x10
-       lctlg   %c0,%c0,__SF_EMPTY(%r15)
-
        /* Restore prefix register and return */
        lghi    %r1,0x1000
        spx     0x318(%r1)
@@ -117,11 +110,6 @@ swsusp_arch_resume:
        /* Deactivate DAT */
        stnsm   __SF_EMPTY(%r15),0xfb
 
-       /* Switch off lowcore protection */
-       stctg   %c0,%c0,__SF_EMPTY(%r15)
-       ni      __SF_EMPTY+4(%r15),0xef
-       lctlg   %c0,%c0,__SF_EMPTY(%r15)
-
        /* Set prefix page to zero */
        xc      __SF_EMPTY(4,%r15),__SF_EMPTY(%r15)
        spx     __SF_EMPTY(%r15)
@@ -175,7 +163,7 @@ swsusp_arch_resume:
        /* Load old stack */
        lg      %r15,0x2f8(%r13)
 
-       /* Pointer to save arae */
+       /* Pointer to save area */
        lghi    %r13,0x1000
 
 #ifdef CONFIG_SMP
@@ -187,11 +175,6 @@ swsusp_arch_resume:
        /* Restore prefix register */
        spx     0x318(%r13)
 
-       /* Switch on lowcore protection */
-       stctg   %c0,%c0,__SF_EMPTY(%r15)
-       oi      __SF_EMPTY+4(%r15),0x10
-       lctlg   %c0,%c0,__SF_EMPTY(%r15)
-
        /* Activate DAT */
        stosm   __SF_EMPTY(%r15),0x04
 
index 8ece0b5bd0282495f872bc71f0ad56227d312b12..39224b57c6efe5ae5d37a45c68d34811fbc0f047 100644 (file)
@@ -61,10 +61,6 @@ config EARLY_PRINTK
          select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using
          the kernel command line option to toggle back and forth.
 
-config DEBUG_BOOTMEM
-       depends on DEBUG_KERNEL
-       bool "Debug BOOTMEM initialization"
-
 config DEBUG_STACKOVERFLOW
        bool "Check for stack overflows"
        depends on DEBUG_KERNEL && SUPERH32
index 7ffd1b4315bd9711119d9319b7a4204c1d332fe2..b9c88cc519e2f1e5d48c3bed83326b6820407a5e 100644 (file)
@@ -547,7 +547,7 @@ static int __init ap325rxa_devices_setup(void)
        return platform_add_devices(ap325rxa_devices,
                                ARRAY_SIZE(ap325rxa_devices));
 }
-device_initcall(ap325rxa_devices_setup);
+arch_initcall(ap325rxa_devices_setup);
 
 /* Return the board specific boot mode pin configuration */
 static int ap325rxa_mode_pins(void)
index f70f4644deb4e835ed54fdea8f3a39a6d3ee2ebd..f9b2e4df35b9c10e33d3638e9a7c88787e2f4be3 100644 (file)
@@ -608,7 +608,7 @@ static int __init migor_devices_setup(void)
 
        return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
 }
-__initcall(migor_devices_setup);
+arch_initcall(migor_devices_setup);
 
 /* Return the board specific boot mode pin configuration */
 static int migor_mode_pins(void)
index 9c3a33210d61750a71a2ae55d8fc7a7c5936403d..180455642a432ce08bd639f02b06826209cd9ac5 100644 (file)
@@ -50,7 +50,7 @@ unsigned char se7206_inb_p(unsigned long port)
 
 unsigned short se7206_inw(unsigned long port)
 {
-       return *port2adr(port);;
+       return *port2adr(port);
 }
 
 void se7206_outb(unsigned char value, unsigned long port)
index 9cd04bd558b88930583774a29837d5aa8424518d..15456a0773bfc598e3e49f97292861cd50eb9c63 100644 (file)
 #include <linux/smc91x.h>
 #include <linux/gpio.h>
 #include <linux/input.h>
+#include <linux/usb/r8a66597.h>
 #include <video/sh_mobile_lcdc.h>
 #include <media/sh_mobile_ceu.h>
 #include <asm/io.h>
 #include <asm/heartbeat.h>
+#include <asm/sh_eth.h>
+#include <asm/clock.h>
 #include <asm/sh_keysc.h>
 #include <cpu/sh7724.h>
 #include <mach-se/mach/se7724.h>
@@ -235,7 +238,7 @@ static struct platform_device ceu1_device = {
        },
 };
 
-/* KEYSC */
+/* KEYSC in SoC (Needs SW33-2 set to ON) */
 static struct sh_keysc_info keysc_info = {
        .mode = SH_KEYSC_MODE_1,
        .scan_timing = 10,
@@ -252,12 +255,13 @@ static struct sh_keysc_info keysc_info = {
 
 static struct resource keysc_resources[] = {
        [0] = {
-               .start  = 0x1a204000,
-               .end    = 0x1a20400f,
+               .name   = "KEYSC",
+               .start  = 0x044b0000,
+               .end    = 0x044b000f,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = IRQ0_KEY,
+               .start  = 79,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -272,6 +276,62 @@ static struct platform_device keysc_device = {
        },
 };
 
+/* SH Eth */
+static struct resource sh_eth_resources[] = {
+       [0] = {
+               .start = SH_ETH_ADDR,
+               .end   = SH_ETH_ADDR + 0x1FC,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = 91,
+               .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
+       },
+};
+
+struct sh_eth_plat_data sh_eth_plat = {
+       .phy = 0x1f, /* SMSC LAN8187 */
+       .edmac_endian = EDMAC_LITTLE_ENDIAN,
+};
+
+static struct platform_device sh_eth_device = {
+       .name = "sh-eth",
+       .id     = 0,
+       .dev = {
+               .platform_data = &sh_eth_plat,
+       },
+       .num_resources = ARRAY_SIZE(sh_eth_resources),
+       .resource = sh_eth_resources,
+};
+
+static struct r8a66597_platdata sh7724_usb0_host_data = {
+};
+
+static struct resource sh7724_usb0_host_resources[] = {
+       [0] = {
+               .start  = 0xa4d80000,
+               .end    = 0xa4d800ff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 65,
+               .end    = 65,
+               .flags  = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+       },
+};
+
+static struct platform_device sh7724_usb0_host_device = {
+       .name           = "r8a66597_hcd",
+       .id             = 0,
+       .dev = {
+               .dma_mask               = NULL,         /*  not use dma */
+               .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &sh7724_usb0_host_data,
+       },
+       .num_resources  = ARRAY_SIZE(sh7724_usb0_host_resources),
+       .resource       = sh7724_usb0_host_resources,
+};
+
 static struct platform_device *ms7724se_devices[] __initdata = {
        &heartbeat_device,
        &smc91x_eth_device,
@@ -280,11 +340,62 @@ static struct platform_device *ms7724se_devices[] __initdata = {
        &ceu0_device,
        &ceu1_device,
        &keysc_device,
+       &sh_eth_device,
+       &sh7724_usb0_host_device,
 };
 
+#define EEPROM_OP   0xBA206000
+#define EEPROM_ADR  0xBA206004
+#define EEPROM_DATA 0xBA20600C
+#define EEPROM_STAT 0xBA206010
+#define EEPROM_STRT 0xBA206014
+static int __init sh_eth_is_eeprom_ready(void)
+{
+       int t = 10000;
+
+       while (t--) {
+               if (!ctrl_inw(EEPROM_STAT))
+                       return 1;
+               cpu_relax();
+       }
+
+       printk(KERN_ERR "ms7724se can not access to eeprom\n");
+       return 0;
+}
+
+static void __init sh_eth_init(void)
+{
+       int i;
+       u16 mac[3];
+
+       /* check EEPROM status */
+       if (!sh_eth_is_eeprom_ready())
+               return;
+
+       /* read MAC addr from EEPROM */
+       for (i = 0 ; i < 3 ; i++) {
+               ctrl_outw(0x0, EEPROM_OP); /* read */
+               ctrl_outw(i*2, EEPROM_ADR);
+               ctrl_outw(0x1, EEPROM_STRT);
+               if (!sh_eth_is_eeprom_ready())
+                       return;
+
+               mac[i] = ctrl_inw(EEPROM_DATA);
+               mac[i] = ((mac[i] & 0xFF) << 8) | (mac[i] >> 8); /* swap */
+       }
+
+       /* reset sh-eth */
+       ctrl_outl(0x1, SH_ETH_ADDR + 0x0);
+
+       /* set MAC addr */
+       ctrl_outl(((mac[0] << 16) | (mac[1])), SH_ETH_MAHR);
+       ctrl_outl((mac[2]), SH_ETH_MALR);
+}
+
 #define SW4140    0xBA201000
 #define FPGA_OUT  0xBA200400
 #define PORT_HIZA 0xA4050158
+#define PORT_MSELCRB 0xA4050182
 
 #define SW41_A    0x0100
 #define SW41_B    0x0200
@@ -294,6 +405,7 @@ static struct platform_device *ms7724se_devices[] __initdata = {
 #define SW41_F    0x2000
 #define SW41_G    0x4000
 #define SW41_H    0x8000
+
 static int __init devices_setup(void)
 {
        u16 sw = ctrl_inw(SW4140); /* select camera, monitor */
@@ -302,9 +414,16 @@ static int __init devices_setup(void)
        ctrl_outw(ctrl_inw(FPGA_OUT) &
                  ~((1 << 1)  | /* LAN */
                    (1 << 6)  | /* VIDEO DAC */
-                   (1 << 12)), /* USB0 */
+                   (1 << 12) | /* USB0 */
+                   (1 << 14)), /* RMII */
                  FPGA_OUT);
 
+       /* turn on USB clocks, use external clock */
+       ctrl_outw((ctrl_inw(PORT_MSELCRB) & ~0xc000) | 0x8000, PORT_MSELCRB);
+
+       /* enable USB0 port */
+       ctrl_outw(0x0600, 0xa40501d4);
+
        /* enable IRQ 0,1,2 */
        gpio_request(GPIO_FN_INTC_IRQ0, NULL);
        gpio_request(GPIO_FN_INTC_IRQ1, NULL);
@@ -374,7 +493,7 @@ static int __init devices_setup(void)
        gpio_request(GPIO_FN_VIO0_CLK, NULL);
        gpio_request(GPIO_FN_VIO0_FLD, NULL);
        gpio_request(GPIO_FN_VIO0_HD,  NULL);
-       platform_resource_setup_memory(&ceu0_device, "ceu", 4 << 20);
+       platform_resource_setup_memory(&ceu0_device, "ceu0", 4 << 20);
 
        /* enable CEU1 */
        gpio_request(GPIO_FN_VIO1_D7,  NULL);
@@ -389,7 +508,7 @@ static int __init devices_setup(void)
        gpio_request(GPIO_FN_VIO1_HD,  NULL);
        gpio_request(GPIO_FN_VIO1_VD,  NULL);
        gpio_request(GPIO_FN_VIO1_CLK, NULL);
-       platform_resource_setup_memory(&ceu1_device, "ceu", 4 << 20);
+       platform_resource_setup_memory(&ceu1_device, "ceu1", 4 << 20);
 
        /* KEYSC */
        gpio_request(GPIO_FN_KEYOUT5_IN5, NULL);
@@ -404,6 +523,28 @@ static int __init devices_setup(void)
        gpio_request(GPIO_FN_KEYOUT1,     NULL);
        gpio_request(GPIO_FN_KEYOUT0,     NULL);
 
+       /*
+        * enable SH-Eth
+        *
+        * please remove J33 pin from your board !!
+        *
+        * ms7724 board should not use GPIO_FN_LNKSTA pin
+        * So, This time PTX5 is set to input pin
+        */
+       gpio_request(GPIO_FN_RMII_RXD0,    NULL);
+       gpio_request(GPIO_FN_RMII_RXD1,    NULL);
+       gpio_request(GPIO_FN_RMII_TXD0,    NULL);
+       gpio_request(GPIO_FN_RMII_TXD1,    NULL);
+       gpio_request(GPIO_FN_RMII_REF_CLK, NULL);
+       gpio_request(GPIO_FN_RMII_TX_EN,   NULL);
+       gpio_request(GPIO_FN_RMII_RX_ER,   NULL);
+       gpio_request(GPIO_FN_RMII_CRS_DV,  NULL);
+       gpio_request(GPIO_FN_MDIO,         NULL);
+       gpio_request(GPIO_FN_MDC,          NULL);
+       gpio_request(GPIO_PTX5, NULL);
+       gpio_direction_input(GPIO_PTX5);
+       sh_eth_init();
+
        if (sw & SW41_B) {
                /* SVGA */
                lcdc_info.ch[0].lcd_cfg.xres         = 800;
@@ -437,7 +578,7 @@ static int __init devices_setup(void)
        }
 
        return platform_add_devices(ms7724se_devices,
-                               ARRAY_SIZE(ms7724se_devices));
+                                   ARRAY_SIZE(ms7724se_devices));
 }
 device_initcall(devices_setup);
 
index da627d22c009ceaab56bdb09359d56c4773406ee..b18cfd39cac6082a7aa4088f0996d88e86f82f6a 100644 (file)
@@ -309,7 +309,7 @@ CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
 CONFIG_ENTRY_OFFSET=0x00001000
 CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="console=ttySC0,115200 earlyprintk=serial ip=on root=/dev/nfs ip=dhcp"
+CONFIG_CMDLINE="console=tty0 console=ttySC0,115200 earlyprintk=serial ip=on root=/dev/nfs ip=dhcp"
 
 #
 # Bus options
@@ -858,7 +858,35 @@ CONFIG_VIDEO_SH_MOBILE_CEU=y
 #
 # CONFIG_VGASTATE is not set
 # CONFIG_VIDEO_OUTPUT_CONTROL is not set
-# CONFIG_FB is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+CONFIG_FB_SYS_FOPS=y
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_SH_MOBILE_LCDC=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -870,6 +898,27 @@ CONFIG_VIDEO_SH_MOBILE_CEU=y
 # Console display driver support
 #
 CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+CONFIG_FONT_MINI_4x6=y
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_SUPERH_MONO is not set
+CONFIG_LOGO_SUPERH_VGA16=y
+# CONFIG_LOGO_SUPERH_CLUT224 is not set
 # CONFIG_SOUND is not set
 CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
index 3840270283e4416a74e348bac24430cf0b58298b..3ee783a0a075c306d08941b94371792567eac4dd 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.30
-# Thu Jun 18 16:09:05 2009
+# Mon Jun 29 16:28:43 2009
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH32=y
@@ -14,6 +14,7 @@ CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_IRQ_PER_CPU=y
 CONFIG_GENERIC_GPIO=y
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_CLOCKEVENTS=y
@@ -28,7 +29,9 @@ CONFIG_HAVE_LATENCYTOP_SUPPORT=y
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_ARCH_NO_VIRT_TO_BUS=y
 CONFIG_ARCH_HAS_DEFAULT_IDLE=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -88,10 +91,12 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+CONFIG_HAVE_PERF_COUNTERS=y
 
 #
 # Performance Counters
 #
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 # CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
@@ -107,6 +112,10 @@ CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_HAVE_CLK=y
 CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
@@ -119,7 +128,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -584,7 +593,6 @@ CONFIG_SCSI_WAIT_SCAN=m
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
-# CONFIG_SCSI_BNX2_ISCSI is not set
 # CONFIG_LIBFC is not set
 # CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -624,7 +632,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 # CONFIG_AX88796 is not set
 # CONFIG_STNIC is not set
-# CONFIG_SH_ETH is not set
+CONFIG_SH_ETH=y
 CONFIG_SMC91X=y
 # CONFIG_ENC28J60 is not set
 # CONFIG_ETHOC is not set
@@ -801,6 +809,11 @@ CONFIG_SPI_BITBANG=y
 #
 # CONFIG_SPI_SPIDEV is not set
 # CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
 # CONFIG_GPIO_SYSFS is not set
@@ -851,6 +864,8 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
 # CONFIG_REGULATOR is not set
 CONFIG_MEDIA_SUPPORT=y
 
@@ -1196,6 +1211,7 @@ CONFIG_RTC_DRV_PCF8563=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1260,6 +1276,7 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
 CONFIG_FILE_LOCKING=y
index a8153c2aa6faf20db8fd1ef661218536d046362c..d8e6bb9c0ccc75bee14438cd767630002f6400fa 100644 (file)
@@ -2,6 +2,8 @@
 #define __ASM_SH_PERF_COUNTER_H
 
 /* SH only supports software counters through this interface. */
-#define set_perf_counter_pending()     do { } while (0)
+static inline void set_perf_counter_pending(void) {}
+
+#define PERF_COUNTER_INDEX_OFFSET      0
 
 #endif /* __ASM_SH_PERF_COUNTER_H */
index 84dd2db7104c74f4f57eb4f1c7d0bfc1f4159869..63ca37bd9a9557a27735fa1dc4c53cdb066d066a 100644 (file)
@@ -73,20 +73,12 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
        quicklist_free_page(QUICK_PT, NULL, pte);
 }
 
-#define __pte_free_tlb(tlb,pte)                                \
+#define __pte_free_tlb(tlb,pte,addr)                   \
 do {                                                   \
        pgtable_page_dtor(pte);                         \
        tlb_remove_page((tlb), (pte));                  \
 } while (0)
 
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-
-#define pmd_free(mm, x)                        do { } while (0)
-#define __pmd_free_tlb(tlb,x)          do { } while (0)
-
 static inline void check_pgt_cache(void)
 {
        quicklist_trim(QUICK_PGD, NULL, 25, 16);
index 5bc34681d99451ae8485a75e4c92b1c24285acbb..6f83f2cc45c16887e126cbffa5e14a28f9b63104 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/err.h>
 #include <asm/ptrace.h>
 
 /* The system call number is given by the user in R3 */
index f09ac4806294007a883b0a472ed2d6654a7ef19f..d570ac2e5cb99838b486c0f65cf120ba710e20e5 100644 (file)
@@ -51,7 +51,7 @@ struct thread_info {
        .exec_domain    = &default_exec_domain, \
        .flags          = 0,                    \
        .cpu            = 0,                    \
-       .preempt_count  = 1,                    \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .addr_limit     = KERNEL_DS,            \
        .restart_block  = {                     \
                .fn = do_no_restart_syscall,    \
index 9c16f737074afb62b552170227fdf4571c66912d..da8fe7ab87283904adac91d7fae1a7bea65af497 100644 (file)
@@ -91,9 +91,9 @@ tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
 }
 
 #define tlb_remove_page(tlb,page)      free_page_and_swap_cache(page)
-#define pte_free_tlb(tlb, ptep)                pte_free((tlb)->mm, ptep)
-#define pmd_free_tlb(tlb, pmdp)                pmd_free((tlb)->mm, pmdp)
-#define pud_free_tlb(tlb, pudp)                pud_free((tlb)->mm, pudp)
+#define pte_free_tlb(tlb, ptep, addr)  pte_free((tlb)->mm, ptep)
+#define pmd_free_tlb(tlb, pmdp, addr)  pmd_free((tlb)->mm, pmdp)
+#define pud_free_tlb(tlb, pudp, addr)  pud_free((tlb)->mm, pudp)
 
 #define tlb_migrate_finish(mm)         do { } while (0)
 
index 74164b60d0dbb43872ee74df4dffcb43ac239577..29514a39d0f5135afe8ba400a262e2ec77f72f49 100644 (file)
  */
 #include <asm/addrspace.h>
 
+/* SH Eth */
+#define SH_ETH_ADDR    (0xA4600000)
+#define SH_ETH_MAHR    (SH_ETH_ADDR + 0x1C0)
+#define SH_ETH_MALR    (SH_ETH_ADDR + 0x1C8)
+
 #define PA_LED         (0xba203000)    /* 8bit LED */
 #define IRQ_MODE       (0xba200010)
 #define IRQ0_SR                (0xba200014)
index 13798733f2db93f6db46bf40d4347a3162fcde75..8555c05e86677f7cf3512b4d773ccd781e8a4cac 100644 (file)
@@ -187,7 +187,7 @@ static int __init sh7619_devices_setup(void)
        return platform_add_devices(sh7619_devices,
                                    ARRAY_SIZE(sh7619_devices));
 }
-__initcall(sh7619_devices_setup);
+arch_initcall(sh7619_devices_setup);
 
 void __init plat_irq_setup(void)
 {
index 869c2da4820b3b763142146ab1b16deb288dcc06..b67376445315b47045433ef7118d7460faba99e4 100644 (file)
@@ -238,7 +238,7 @@ static int __init mxg_devices_setup(void)
        return platform_add_devices(mxg_devices,
                                    ARRAY_SIZE(mxg_devices));
 }
-__initcall(mxg_devices_setup);
+arch_initcall(mxg_devices_setup);
 
 void __init plat_irq_setup(void)
 {
index d8febe12806620cee8058b874a454039bc029f89..fbde5b75deb9152ba615c28af7c68652bc224ba8 100644 (file)
@@ -357,7 +357,7 @@ static int __init sh7201_devices_setup(void)
        return platform_add_devices(sh7201_devices,
                                    ARRAY_SIZE(sh7201_devices));
 }
-__initcall(sh7201_devices_setup);
+arch_initcall(sh7201_devices_setup);
 
 void __init plat_irq_setup(void)
 {
index 62e3039d2398ad0071044b0d1f4a7423d08e9d4d..d3fd536c9a842e08634a982c3c7b4330d749f05e 100644 (file)
@@ -367,7 +367,7 @@ static int __init sh7203_devices_setup(void)
        return platform_add_devices(sh7203_devices,
                                    ARRAY_SIZE(sh7203_devices));
 }
-__initcall(sh7203_devices_setup);
+arch_initcall(sh7203_devices_setup);
 
 void __init plat_irq_setup(void)
 {
index 3e6f3d7a58be990cbaa06b5022ab1624be92b8fb..a9ccc5e8d9e98af493bf45ed7fdeb4430c0cc11b 100644 (file)
@@ -338,7 +338,7 @@ static int __init sh7206_devices_setup(void)
        return platform_add_devices(sh7206_devices,
                                    ARRAY_SIZE(sh7206_devices));
 }
-__initcall(sh7206_devices_setup);
+arch_initcall(sh7206_devices_setup);
 
 void __init plat_irq_setup(void)
 {
index 88f742fed9edf445269743a6f5198c656ebc9117..c231059838780cc294d6f5f5cc7ea0a167eada0c 100644 (file)
@@ -222,7 +222,7 @@ static int __init sh7705_devices_setup(void)
        return platform_add_devices(sh7705_devices,
                                    ARRAY_SIZE(sh7705_devices));
 }
-__initcall(sh7705_devices_setup);
+arch_initcall(sh7705_devices_setup);
 
 static struct platform_device *sh7705_early_devices[] __initdata = {
        &tmu0_device,
index c56306798584f68989ab9d5c82c89071141122e1..347ab35d0697bf6cb0899f18b87153cb69117b32 100644 (file)
@@ -250,7 +250,7 @@ static int __init sh770x_devices_setup(void)
        return platform_add_devices(sh770x_devices,
                ARRAY_SIZE(sh770x_devices));
 }
-__initcall(sh770x_devices_setup);
+arch_initcall(sh770x_devices_setup);
 
 static struct platform_device *sh770x_early_devices[] __initdata = {
        &tmu0_device,
index efa76c8148f4e4d2ab7807852d07c3aa5e3cc918..717e90ae1097a00efb701ba958013c844f6a55a4 100644 (file)
@@ -226,7 +226,7 @@ static int __init sh7710_devices_setup(void)
        return platform_add_devices(sh7710_devices,
                                    ARRAY_SIZE(sh7710_devices));
 }
-__initcall(sh7710_devices_setup);
+arch_initcall(sh7710_devices_setup);
 
 static struct platform_device *sh7710_early_devices[] __initdata = {
        &tmu0_device,
index 5b2107798edbe3fc804a19940c63def3e0dc850b..74d8baaf8e9675c2f740a45e30b2cffcbd66ffc6 100644 (file)
@@ -388,7 +388,7 @@ static int __init sh7720_devices_setup(void)
        return platform_add_devices(sh7720_devices,
                                    ARRAY_SIZE(sh7720_devices));
 }
-__initcall(sh7720_devices_setup);
+arch_initcall(sh7720_devices_setup);
 
 static struct platform_device *sh7720_early_devices[] __initdata = {
        &cmt0_device,
index 6d088d12359172f8b8b9d9e99ee3162ad46f06a5..de4827df19aacc41dcb589128c6d6e62f7a147e6 100644 (file)
@@ -138,7 +138,7 @@ static int __init sh4202_devices_setup(void)
        return platform_add_devices(sh4202_devices,
                                    ARRAY_SIZE(sh4202_devices));
 }
-__initcall(sh4202_devices_setup);
+arch_initcall(sh4202_devices_setup);
 
 static struct platform_device *sh4202_early_devices[] __initdata = {
        &tmu0_device,
index 851672d15cf4a15e5f3b2208681417a269d1ba99..1b8b122e8f3dd46f5898ba0710432f83c5578b2e 100644 (file)
@@ -239,7 +239,7 @@ static int __init sh7750_devices_setup(void)
        return platform_add_devices(sh7750_devices,
                                    ARRAY_SIZE(sh7750_devices));
 }
-__initcall(sh7750_devices_setup);
+arch_initcall(sh7750_devices_setup);
 
 static struct platform_device *sh7750_early_devices[] __initdata = {
        &tmu0_device,
index 5b822519bd90cb7593b74338b9442adc734caab9..7fbb7be9284ca86950ead92da5ca337f0c0e7b99 100644 (file)
@@ -265,7 +265,7 @@ static int __init sh7760_devices_setup(void)
        return platform_add_devices(sh7760_devices,
                                    ARRAY_SIZE(sh7760_devices));
 }
-__initcall(sh7760_devices_setup);
+arch_initcall(sh7760_devices_setup);
 
 static struct platform_device *sh7760_early_devices[] __initdata = {
        &tmu0_device,
index 6307e087c8642f1527323414bf24d71a73dda184..ac4d5672ec1a25ff053191fa7c60bd46dfaf5da5 100644 (file)
@@ -325,7 +325,7 @@ static int __init sh7343_devices_setup(void)
        return platform_add_devices(sh7343_devices,
                                    ARRAY_SIZE(sh7343_devices));
 }
-__initcall(sh7343_devices_setup);
+arch_initcall(sh7343_devices_setup);
 
 static struct platform_device *sh7343_early_devices[] __initdata = {
        &cmt_device,
index c18f7d09281bbd80d333d2773b321b907044fd68..1a956b1beccc5f320f7e7fd206669bd2d69c2ac8 100644 (file)
@@ -318,7 +318,7 @@ static int __init sh7366_devices_setup(void)
        return platform_add_devices(sh7366_devices,
                                    ARRAY_SIZE(sh7366_devices));
 }
-__initcall(sh7366_devices_setup);
+arch_initcall(sh7366_devices_setup);
 
 static struct platform_device *sh7366_early_devices[] __initdata = {
        &cmt_device,
index ea524a2da3e477ffe15176a672b5936add4fa435..cda76ebf87c386a4e51f51a62f874971e41c9cd2 100644 (file)
@@ -359,7 +359,7 @@ static int __init sh7722_devices_setup(void)
        return platform_add_devices(sh7722_devices,
                                    ARRAY_SIZE(sh7722_devices));
 }
-__initcall(sh7722_devices_setup);
+arch_initcall(sh7722_devices_setup);
 
 static struct platform_device *sh7722_early_devices[] __initdata = {
        &cmt_device,
index e1bb80b2a27b55c948f95e2e15e146fe5ff82319..b45dace9539fdf23cf0af0d46159438f0f045f29 100644 (file)
@@ -473,7 +473,7 @@ static int __init sh7723_devices_setup(void)
        return platform_add_devices(sh7723_devices,
                                    ARRAY_SIZE(sh7723_devices));
 }
-__initcall(sh7723_devices_setup);
+arch_initcall(sh7723_devices_setup);
 
 static struct platform_device *sh7723_early_devices[] __initdata = {
        &cmt_device,
index e5ac9eb11c63a813612ea490f5a9ab218af925e5..a04edaab9a29172316262cd9da0549d0c8848e37 100644 (file)
@@ -508,7 +508,7 @@ static int __init sh7724_devices_setup(void)
        return platform_add_devices(sh7724_devices,
                                    ARRAY_SIZE(sh7724_devices));
 }
-device_initcall(sh7724_devices_setup);
+arch_initcall(sh7724_devices_setup);
 
 static struct platform_device *sh7724_early_devices[] __initdata = {
        &cmt_device,
index f1e0c0d36da74121e6a3d40933da1813c7bbe6e2..4659fff6b842057defff64a65b506714170d3c99 100644 (file)
@@ -314,7 +314,7 @@ static int __init sh7763_devices_setup(void)
        return platform_add_devices(sh7763_devices,
                                    ARRAY_SIZE(sh7763_devices));
 }
-__initcall(sh7763_devices_setup);
+arch_initcall(sh7763_devices_setup);
 
 static struct platform_device *sh7763_early_devices[] __initdata = {
        &tmu0_device,
index 1e86209db284357791338b5ba9f2bd771f7f358c..eead08d89d32548932e32e6840702e068a538a89 100644 (file)
@@ -368,7 +368,7 @@ static int __init sh7770_devices_setup(void)
        return platform_add_devices(sh7770_devices,
                                    ARRAY_SIZE(sh7770_devices));
 }
-__initcall(sh7770_devices_setup);
+arch_initcall(sh7770_devices_setup);
 
 static struct platform_device *sh7770_early_devices[] __initdata = {
        &tmu0_device,
index 715e05b431e5e7f4b8c027f608803fab0d8edaba..2c901f446959d3fe70fa4e08128b35f14e01d038 100644 (file)
@@ -256,7 +256,7 @@ static int __init sh7780_devices_setup(void)
        return platform_add_devices(sh7780_devices,
                                    ARRAY_SIZE(sh7780_devices));
 }
-__initcall(sh7780_devices_setup);
+arch_initcall(sh7780_devices_setup);
 
 static struct platform_device *sh7780_early_devices[] __initdata = {
        &tmu0_device,
index af561402570bdb411a026a1127b5e42a54fdc524..7f6c718b6c36e4de8722cf41b571f3c0700bd703 100644 (file)
@@ -263,7 +263,7 @@ static int __init sh7785_devices_setup(void)
        return platform_add_devices(sh7785_devices,
                                    ARRAY_SIZE(sh7785_devices));
 }
-__initcall(sh7785_devices_setup);
+arch_initcall(sh7785_devices_setup);
 
 static struct platform_device *sh7785_early_devices[] __initdata = {
        &tmu0_device,
index b70049470a0bae775c1db1cf9cb34ef79edbec86..0104a8ec53691a4ad26c6f80476d4f8c2a9ff361 100644 (file)
@@ -547,7 +547,7 @@ static int __init sh7786_devices_setup(void)
        return platform_add_devices(sh7786_devices,
                                    ARRAY_SIZE(sh7786_devices));
 }
-device_initcall(sh7786_devices_setup);
+arch_initcall(sh7786_devices_setup);
 
 void __init plat_early_device_setup(void)
 {
index 53c65fd9ccef726d015cd71b664a151842e4731d..07f078961c715813a8dfbdbcff0777a06782b5c3 100644 (file)
@@ -256,7 +256,7 @@ static int __init shx3_devices_setup(void)
        return platform_add_devices(shx3_devices,
                                    ARRAY_SIZE(shx3_devices));
 }
-__initcall(shx3_devices_setup);
+arch_initcall(shx3_devices_setup);
 
 void __init plat_early_device_setup(void)
 {
index f5ff1ac57fc2879a9cd39978fe77038e2c8981a6..6a0f82f700323ce02d06fe91f7eb766b48a9b349 100644 (file)
@@ -186,7 +186,7 @@ static int __init sh5_devices_setup(void)
        return platform_add_devices(sh5_devices,
                                    ARRAY_SIZE(sh5_devices));
 }
-__initcall(sh5_devices_setup);
+arch_initcall(sh5_devices_setup);
 
 void __init plat_early_device_setup(void)
 {
index 5d888ef53d82b02e5eec2ebe1b29d63f2f7afa46..baf2d7d46b05ba35fe936d2788128d0c1ebe9df5 100644 (file)
@@ -26,8 +26,30 @@ ENTRY(sh_mobile_standby)
 
        tst     #SUSP_SH_SF, r0
        bt      skip_set_sf
+#ifdef CONFIG_CPU_SUBTYPE_SH7724
+       /* DBSC: put memory in self-refresh mode */
 
-       /* SDRAM: disable power down and put in self-refresh mode */
+       mov.l   dben_reg, r4
+       mov.l   dben_data0, r1
+       mov.l   r1, @r4
+
+       mov.l   dbrfpdn0_reg, r4
+       mov.l   dbrfpdn0_data0, r1
+       mov.l   r1, @r4
+
+       mov.l   dbcmdcnt_reg, r4
+       mov.l   dbcmdcnt_data0, r1
+       mov.l   r1, @r4
+
+       mov.l   dbcmdcnt_reg, r4
+       mov.l   dbcmdcnt_data1, r1
+       mov.l   r1, @r4
+
+       mov.l   dbrfpdn0_reg, r4
+       mov.l   dbrfpdn0_data1, r1
+       mov.l   r1, @r4
+#else
+       /* SBSC: disable power down and put in self-refresh mode */
        mov.l   1f, r4
        mov.l   2f, r1
        mov.l   @r4, r2
@@ -35,6 +57,7 @@ ENTRY(sh_mobile_standby)
        mov.l   3f, r3
        and     r3, r2
        mov.l   r2, @r4
+#endif
 
 skip_set_sf:
        tst     #SUSP_SH_SLEEP, r0
@@ -84,7 +107,36 @@ done_sleep:
        tst     #SUSP_SH_SF, r0
        bt      skip_restore_sf
 
-       /* SDRAM: set auto-refresh mode */
+#ifdef CONFIG_CPU_SUBTYPE_SH7724
+       /* DBSC: put memory in auto-refresh mode */
+
+       mov.l   dbrfpdn0_reg, r4
+       mov.l   dbrfpdn0_data0, r1
+       mov.l   r1, @r4
+
+       /* sleep 140 ns */
+       nop
+       nop
+       nop
+       nop
+
+       mov.l   dbcmdcnt_reg, r4
+       mov.l   dbcmdcnt_data0, r1
+       mov.l   r1, @r4
+
+       mov.l   dbcmdcnt_reg, r4
+       mov.l   dbcmdcnt_data1, r1
+       mov.l   r1, @r4
+
+       mov.l   dben_reg, r4
+       mov.l   dben_data1, r1
+       mov.l   r1, @r4
+
+       mov.l   dbrfpdn0_reg, r4
+       mov.l   dbrfpdn0_data2, r1
+       mov.l   r1, @r4
+#else
+       /* SBSC: set auto-refresh mode */
        mov.l   1f, r4
        mov.l   @r4, r2
        mov.l   4f, r3
@@ -98,15 +150,29 @@ done_sleep:
        add     r4, r3
        or      r2, r3
        mov.l   r3, @r1
+#endif
 skip_restore_sf:
        rts
         nop
 
        .balign 4
+#ifdef CONFIG_CPU_SUBTYPE_SH7724
+dben_reg:      .long   0xfd000010 /* DBEN */
+dben_data0:    .long   0
+dben_data1:    .long   1
+dbrfpdn0_reg:  .long   0xfd000040 /* DBRFPDN0 */
+dbrfpdn0_data0:        .long   0
+dbrfpdn0_data1:        .long   1
+dbrfpdn0_data2:        .long   0x00010000
+dbcmdcnt_reg:  .long   0xfd000014 /* DBCMDCNT */
+dbcmdcnt_data0:        .long   2
+dbcmdcnt_data1:        .long   4
+#else
 1:     .long   0xfe400008 /* SDCR0 */
 2:     .long   0x00000400
 3:     .long   0xffff7fff
 4:     .long   0xfffffbff
+#endif
 5:     .long   0xa4150020 /* STBCR */
 6:     .long   0xfe40001c /* RTCOR */
 7:     .long   0xfe400018 /* RTCNT */
index cc8ddbdf3d7a75005c2c9590fe386d20bb79050c..71925946f1e16d6294301581ade0bb6f0fda050a 100644 (file)
 #include <linux/mm.h>
 #include <linux/hardirq.h>
 #include <linux/kprobes.h>
-#include <linux/marker.h>
+#include <linux/perf_counter.h>
 #include <asm/io_trapped.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 
+static inline int notify_page_fault(struct pt_regs *regs, int trap)
+{
+       int ret = 0;
+
+#ifdef CONFIG_KPROBES
+       if (!user_mode(regs)) {
+               preempt_disable();
+               if (kprobe_running() && kprobe_fault_handler(regs, trap))
+                       ret = 1;
+               preempt_enable();
+       }
+#endif
+
+       return ret;
+}
+
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
@@ -87,13 +103,16 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
                return;
        }
 
+       mm = tsk->mm;
+
+       if (unlikely(notify_page_fault(regs, lookup_exception_vector())))
+               return;
+
        /* Only enable interrupts if they were on before the fault */
-       if ((regs->sr & SR_IMASK) != SR_IMASK) {
-               trace_hardirqs_on();
+       if ((regs->sr & SR_IMASK) != SR_IMASK)
                local_irq_enable();
-       }
 
-       mm = tsk->mm;
+       perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
 
        /*
         * If we're in an interrupt or have no user
@@ -141,10 +160,15 @@ survive:
                        goto do_sigbus;
                BUG();
        }
-       if (fault & VM_FAULT_MAJOR)
+       if (fault & VM_FAULT_MAJOR) {
                tsk->maj_flt++;
-       else
+               perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+                                    regs, address);
+       } else {
                tsk->min_flt++;
+               perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+                                    regs, address);
+       }
 
        up_read(&mm->mmap_sem);
        return;
@@ -245,22 +269,6 @@ do_sigbus:
                goto no_context;
 }
 
-static inline int notify_page_fault(struct pt_regs *regs, int trap)
-{
-       int ret = 0;
-
-#ifdef CONFIG_KPROBES
-       if (!user_mode(regs)) {
-               preempt_disable();
-               if (kprobe_running() && kprobe_fault_handler(regs, trap))
-                       ret = 1;
-               preempt_enable();
-       }
-#endif
-
-       return ret;
-}
-
 /*
  * Called with interrupts disabled.
  */
@@ -273,12 +281,7 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
        pmd_t *pmd;
        pte_t *pte;
        pte_t entry;
-       int ret = 0;
-
-       if (notify_page_fault(regs, lookup_exception_vector()))
-               goto out;
-
-       ret = 1;
+       int ret = 1;
 
        /*
         * We don't take page faults for P1, P2, and parts of P4, these
index 7fbfd5a11ffae73860c64941240dff7ecbc03e51..17cb7c3adf2256b0206ea3d920578c47b9a0dbfc 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 
 #include <asm/system.h>
index fcbb6e135cef319ee30c5d27a12fb75b234608e1..3ce40ea34824914f6ad30ad2abb38a0d8ca9d401 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
  * Copyright (C) 2003  Richard Curnow (/proc/tlb, bug fixes)
- * Copyright (C) 2003  Paul Mundt
+ * Copyright (C) 2003 - 2009 Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -20,6 +20,7 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
+#include <linux/perf_counter.h>
 #include <linux/interrupt.h>
 #include <asm/system.h>
 #include <asm/io.h>
@@ -115,6 +116,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
        /* Not an IO address, so reenable interrupts */
        local_irq_enable();
 
+       perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address);
+
        /*
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
@@ -195,10 +198,16 @@ survive:
                        goto do_sigbus;
                BUG();
        }
-       if (fault & VM_FAULT_MAJOR)
+
+       if (fault & VM_FAULT_MAJOR) {
                tsk->maj_flt++;
-       else
+               perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+                                    regs, address);
+       } else {
                tsk->min_flt++;
+               perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+                                    regs, address);
+       }
 
        /* If we get here, the page fault has been handled.  Do the TLB refill
           now from the newly-setup PTE, to avoid having to fault again right
index 96041a8d39e8cf2e01695c0536502440e43e0f0d..1ff0fd92475655ca551e11961a19b8c76e8777b3 100644 (file)
@@ -15,7 +15,7 @@ quiet_cmd_elftoaout   = ELFTOAOUT $@
 
 ifeq ($(CONFIG_SPARC32),y)
 quiet_cmd_piggy                = PIGGY   $@
-      cmd_piggy                = $(obj)/piggyback_32 $@ $(obj)/System.map $(ROOT_IMG)
+      cmd_piggy                = $(obj)/piggyback_32 $@ System.map $(ROOT_IMG)
 quiet_cmd_btfix                = BTFIX   $@
       cmd_btfix                = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@
 quiet_cmd_sysmap        = SYSMAP  $(obj)/System.map
@@ -58,7 +58,7 @@ $(obj)/image: $(obj)/btfix.o FORCE
 $(obj)/zImage: $(obj)/image
        $(call if_changed,strip)
 
-$(obj)/tftpboot.img: $(obj)/piggyback $(obj)/System.map $(obj)/image FORCE
+$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_32 System.map $(ROOT_IMG) FORCE
        $(call if_changed,elftoaout)
        $(call if_changed,piggy)
 
@@ -79,7 +79,7 @@ $(obj)/image: vmlinux FORCE
        $(call if_changed,strip)
        @echo '  kernel: $@ is ready'
 
-$(obj)/tftpboot.img: vmlinux $(obj)/piggyback_64 System.map $(ROOT_IMG) FORCE
+$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_64 System.map $(ROOT_IMG) FORCE
        $(call if_changed,elftoaout)
        $(call if_changed,piggy)
        @echo '  kernel: $@ is ready'
index c9f500c1a8b23b9253213baaa58a9e53aaaa9af6..e8dc9adfcd61db8a05ae092407b53a01f2efac2b 100644 (file)
@@ -70,7 +70,7 @@ void die(char *str)
 int main(int argc,char **argv)
 {
        static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 };
-       unsigned char buffer[1024], *q, *r;
+       char buffer[1024], *q, *r;
        unsigned int i, j, k, start, end, offset;
        FILE *map;
        struct stat s;
@@ -84,7 +84,7 @@ int main(int argc,char **argv)
        while (fgets (buffer, 1024, map)) {
                if (!strcmp (buffer + 8, " T start\n") || !strcmp (buffer + 16, " T start\n"))
                        start = strtoul (buffer, NULL, 16);
-               else if (!strcmp (buffer + 8, " A end\n") || !strcmp (buffer + 16, " A end\n"))
+               else if (!strcmp (buffer + 8, " A _end\n") || !strcmp (buffer + 16, " A _end\n"))
                        end = strtoul (buffer, NULL, 16);
        }
        fclose (map);
index de364bfed0bbfc3405104a3046cbbdd4d099c588..c63fd1b6bdd4f036617c7740619db05dbe6d8e7d 100644 (file)
@@ -46,6 +46,7 @@ int main(int argc,char **argv)
        struct stat s;
        int image, tail;
        
+       start = end = 0;
        if (stat (argv[3], &s) < 0) die (argv[3]);
        map = fopen (argv[2], "r");
        if (!map) die(argv[2]);
index 8bcd27af724bbc2ac36460b13d94c88aa19be2ce..a0f62a808edb91b4deafece2dcabf1f0efa9a838 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30-rc2
-# Fri Apr 17 04:04:46 2009
+# Linux kernel version: 2.6.31-rc1
+# Tue Aug 18 23:45:52 2009
 #
 # CONFIG_64BIT is not set
 CONFIG_SPARC=y
@@ -17,6 +17,7 @@ CONFIG_GENERIC_ISA_DMA=y
 CONFIG_ARCH_NO_VIRT_TO_BUS=y
 CONFIG_OF=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -74,7 +75,6 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -87,8 +87,13 @@ CONFIG_TIMERFD=y
 CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_AIO=y
+
+#
+# Performance Counters
+#
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_PCI_QUIRKS=y
+# CONFIG_STRIP_ASM_SYMS is not set
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
 # CONFIG_SLUB is not set
@@ -97,6 +102,10 @@ CONFIG_SLAB=y
 # CONFIG_MARKERS is not set
 CONFIG_HAVE_OPROFILE=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
+
+#
+# GCOV-based kernel profiling
+#
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -109,7 +118,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_BLOCK=y
-# CONFIG_LBD is not set
+CONFIG_LBDAF=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_BLK_DEV_INTEGRITY is not set
 
@@ -154,9 +163,9 @@ CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_PHYS_ADDR_T_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
 CONFIG_BOUNCE=y
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
 CONFIG_SUN_PM=y
 # CONFIG_SPARC_LED is not set
 CONFIG_SERIAL_CONSOLE=y
@@ -264,6 +273,7 @@ CONFIG_IPV6_TUNNEL=m
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
 
@@ -281,7 +291,11 @@ CONFIG_WIRELESS=y
 CONFIG_WIRELESS_OLD_REGULATORY=y
 # CONFIG_WIRELESS_EXT is not set
 # CONFIG_LIB80211 is not set
-# CONFIG_MAC80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+CONFIG_MAC80211_DEFAULT_PS_VALUE=0
 # CONFIG_WIMAX is not set
 # CONFIG_RFKILL is not set
 # CONFIG_NET_9P is not set
@@ -335,6 +349,7 @@ CONFIG_MISC_DEVICES=y
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
@@ -358,10 +373,6 @@ CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_CHR_DEV_SG=m
 # CONFIG_CHR_DEV_SCH is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
 # CONFIG_SCSI_LOGGING is not set
@@ -379,6 +390,7 @@ CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI 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
@@ -387,6 +399,7 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -401,7 +414,6 @@ CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_MVSAS is not set
 # CONFIG_SCSI_STEX is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -426,13 +438,16 @@ CONFIG_SCSI_SUNESP=y
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
 # CONFIG_I2O is not set
 CONFIG_NETDEVICES=y
-CONFIG_COMPAT_NET_DEV_OPS=y
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
@@ -463,6 +478,7 @@ CONFIG_SUNQE=m
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
 # CONFIG_ATL2 is not set
 CONFIG_NETDEV_1000=y
 # CONFIG_ACENIC is not set
@@ -482,6 +498,7 @@ CONFIG_NETDEV_1000=y
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -629,6 +646,11 @@ CONFIG_HW_RANDOM=m
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -668,22 +690,7 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_HTC_PASIC3 is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -776,6 +783,10 @@ CONFIG_RTC_DRV_M48T59=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -799,10 +810,12 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
@@ -985,6 +998,7 @@ CONFIG_KGDB=y
 CONFIG_KGDB_SERIAL_CONSOLE=y
 CONFIG_KGDB_TESTS=y
 # CONFIG_KGDB_TESTS_ON_BOOT is not set
+# CONFIG_KMEMCHECK is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_STACK_DEBUG is not set
 
index 0123a4c596cef67a537d6a3f660b0cbf0a3b74c6..fdddf7a6f7252b12b40823ad55bc705f3c38a7fa 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.30
-# Tue Jun 16 04:59:36 2009
+# Linux kernel version: 2.6.31-rc1
+# Tue Aug 18 23:56:02 2009
 #
 CONFIG_64BIT=y
 CONFIG_SPARC=y
@@ -26,6 +26,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y
 CONFIG_OF=y
 CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
 
 #
 # General setup
@@ -119,6 +120,11 @@ CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
 CONFIG_HAVE_ARCH_TRACEHOOK=y
 CONFIG_USE_GENERIC_SMP_HELPERS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
 # CONFIG_SLOW_WORK is not set
 # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
 CONFIG_SLABINFO=y
@@ -204,7 +210,6 @@ CONFIG_MIGRATION=y
 CONFIG_PHYS_ADDR_T_64BIT=y
 CONFIG_ZONE_DMA_FLAG=0
 CONFIG_NR_QUICK=1
-CONFIG_UNEVICTABLE_LRU=y
 CONFIG_HAVE_MLOCK=y
 CONFIG_HAVE_MLOCKED_PAGE_BIT=y
 CONFIG_DEFAULT_MMAP_MIN_ADDR=8192
@@ -410,6 +415,7 @@ CONFIG_MISC_DEVICES=y
 #
 # CONFIG_EEPROM_AT24 is not set
 # CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
 # CONFIG_EEPROM_93CX6 is not set
 # CONFIG_CB710_CORE is not set
 CONFIG_HAVE_IDE=y
@@ -562,6 +568,7 @@ CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
+# CONFIG_DM_LOG_USERSPACE is not set
 CONFIG_DM_ZERO=m
 # CONFIG_DM_MULTIPATH is not set
 # CONFIG_DM_DELAY is not set
@@ -573,7 +580,11 @@ CONFIG_DM_ZERO=m
 #
 
 #
-# Enable only one of the two stacks, unless you know what you are doing
+# You can enable one or both FireWire driver stacks.
+#
+
+#
+# See the help texts for more information.
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
@@ -667,6 +678,7 @@ CONFIG_E1000E=m
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=m
 CONFIG_BNX2=m
+# CONFIG_CNIC is not set
 # CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 # CONFIG_ATL1E is not set
@@ -773,6 +785,7 @@ CONFIG_MOUSE_SERIAL=y
 # CONFIG_MOUSE_APPLETOUCH is not set
 # CONFIG_MOUSE_BCM5974 is not set
 # CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
@@ -870,6 +883,7 @@ CONFIG_I2C_ALGOBIT=y
 #
 # I2C system bus drivers (mostly embedded / system-on-chip)
 #
+# CONFIG_I2C_DESIGNWARE is not set
 # CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_SIMTEC is not set
 
@@ -898,13 +912,17 @@ CONFIG_I2C_ALGOBIT=y
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_PCF8575 is not set
 # CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_MAX6875 is not set
 # CONFIG_SENSORS_TSL2550 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 # CONFIG_SPI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
 CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_W1 is not set
@@ -959,6 +977,7 @@ CONFIG_HWMON=y
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_ADS7828 is not set
 # CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP401 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
 # CONFIG_SENSORS_VT8231 is not set
@@ -994,23 +1013,9 @@ CONFIG_SSB_POSSIBLE=y
 # CONFIG_MFD_WM8400 is not set
 # CONFIG_MFD_WM8350_I2C is not set
 # CONFIG_MFD_PCF50633 is not set
+# CONFIG_AB3100_CORE is not set
 # CONFIG_REGULATOR is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
+# CONFIG_MEDIA_SUPPORT is not set
 
 #
 # Graphics support
@@ -1284,7 +1289,6 @@ CONFIG_USB=y
 #
 # Miscellaneous USB options
 #
-CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_DEVICE_CLASS is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
@@ -1296,6 +1300,7 @@ CONFIG_USB_DEVICEFS=y
 # USB Host Controller Drivers
 #
 # CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -1374,7 +1379,6 @@ CONFIG_USB_STORAGE=m
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
 # CONFIG_USB_IOWARRIOR is not set
-# CONFIG_USB_TEST is not set
 # CONFIG_USB_ISIGHTFW is not set
 # CONFIG_USB_VST is not set
 # CONFIG_USB_GADGET is not set
@@ -1420,6 +1424,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
 
 #
 # SPI RTC drivers
@@ -1448,6 +1453,10 @@ CONFIG_RTC_DRV_STARFIRE=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
 # CONFIG_STAGING is not set
 
 #
@@ -1480,11 +1489,11 @@ CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-CONFIG_FILE_LOCKING=y
 # CONFIG_XFS_FS is not set
 # CONFIG_GFS2_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
+CONFIG_FILE_LOCKING=y
 CONFIG_FSNOTIFY=y
 CONFIG_DNOTIFY=y
 CONFIG_INOTIFY=y
@@ -1560,7 +1569,7 @@ CONFIG_NETWORK_FILESYSTEMS=y
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
 CONFIG_SUN_PARTITION=y
-CONFIG_NLS=m
+CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_CODEPAGE_437 is not set
 # CONFIG_NLS_CODEPAGE_737 is not set
index 681582d2696911ce7262bfa821dc1dbff5f41d94..ca2b34456c4b00c5e5854f630286e0cfe192cc96 100644 (file)
@@ -44,8 +44,8 @@ BTFIXUPDEF_CALL(pmd_t *, pmd_alloc_one, struct mm_struct *, unsigned long)
 BTFIXUPDEF_CALL(void, free_pmd_fast, pmd_t *)
 #define free_pmd_fast(pmd)     BTFIXUP_CALL(free_pmd_fast)(pmd)
 
-#define pmd_free(mm, pmd)      free_pmd_fast(pmd)
-#define __pmd_free_tlb(tlb, pmd) pmd_free((tlb)->mm, pmd)
+#define pmd_free(mm, pmd)              free_pmd_fast(pmd)
+#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd)
 
 BTFIXUPDEF_CALL(void, pmd_populate, pmd_t *, struct page *)
 #define pmd_populate(MM, PMD, PTE)        BTFIXUP_CALL(pmd_populate)(PMD, PTE)
@@ -62,7 +62,7 @@ BTFIXUPDEF_CALL(void, free_pte_fast, pte_t *)
 #define pte_free_kernel(mm, pte)       BTFIXUP_CALL(free_pte_fast)(pte)
 
 BTFIXUPDEF_CALL(void, pte_free, pgtable_t )
-#define pte_free(mm, pte)      BTFIXUP_CALL(pte_free)(pte)
-#define __pte_free_tlb(tlb, pte)       pte_free((tlb)->mm, pte)
+#define pte_free(mm, pte)              BTFIXUP_CALL(pte_free)(pte)
+#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
 
 #endif /* _SPARC_PGALLOC_H */
index b049abf9902fdb42d4efe145d88a731dd4b6734b..0ff92fa22064f6a335233acfa39a72a6bfb88a4d 100644 (file)
@@ -726,11 +726,17 @@ extern unsigned long pte_file(pte_t);
 extern pte_t pgoff_to_pte(unsigned long);
 #define PTE_FILE_MAX_BITS      (64UL - PAGE_SHIFT - 1UL)
 
-extern unsigned long *sparc64_valid_addr_bitmap;
+extern unsigned long sparc64_valid_addr_bitmap[];
 
 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-#define kern_addr_valid(addr)  \
-       (test_bit(__pa((unsigned long)(addr))>>22, sparc64_valid_addr_bitmap))
+static inline bool kern_addr_valid(unsigned long addr)
+{
+       unsigned long paddr = __pa(addr);
+
+       if ((paddr >> 41UL) != 0UL)
+               return false;
+       return test_bit(paddr >> 22, sparc64_valid_addr_bitmap);
+}
 
 extern int page_in_phys_avail(unsigned long paddr);
 
index 0f7b0e5fb1c79ce1233437a5744a5736d6f91152..844d73a0340cd9c002a5399a10b943b8b60ce92d 100644 (file)
@@ -54,8 +54,6 @@ struct thread_info {
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #define INIT_THREAD_INFO(tsk)                          \
 {                                                      \
@@ -64,7 +62,7 @@ struct thread_info {
        .exec_domain    =       &default_exec_domain,   \
        .flags          =       0,                      \
        .cpu            =       0,                      \
-       .preempt_count  =       1,                      \
+       .preempt_count  =       INIT_PREEMPT_COUNT,     \
        .restart_block  = {                             \
                .fn     =       do_no_restart_syscall,  \
        },                                              \
index 65865726b28319238b16f109a032510a14b624e5..1b45a7bbe40751a210f748759fac6c0e3fc3b879 100644 (file)
@@ -125,8 +125,6 @@ struct thread_info {
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #ifndef __ASSEMBLY__
 
@@ -135,7 +133,7 @@ struct thread_info {
        .task           =       &tsk,                   \
        .flags          = ((unsigned long)ASI_P) << TI_FLAG_CURRENT_DS_SHIFT,   \
        .exec_domain    =       &default_exec_domain,   \
-       .preempt_count  =       1,                      \
+       .preempt_count  =       INIT_PREEMPT_COUNT,     \
        .restart_block  = {                             \
                .fn     =       do_no_restart_syscall,  \
        },                                              \
index ee38e731bfa635587afd73bac991fa69fad8ebec..dca406b9b6fc5b9b6400732d6abe3a9f1e9e528d 100644 (file)
@@ -100,9 +100,9 @@ static inline void tlb_remove_page(struct mmu_gather *mp, struct page *page)
 }
 
 #define tlb_remove_tlb_entry(mp,ptep,addr) do { } while (0)
-#define pte_free_tlb(mp, ptepage) pte_free((mp)->mm, ptepage)
-#define pmd_free_tlb(mp, pmdp) pmd_free((mp)->mm, pmdp)
-#define pud_free_tlb(tlb,pudp) __pud_free_tlb(tlb,pudp)
+#define pte_free_tlb(mp, ptepage, addr) pte_free((mp)->mm, ptepage)
+#define pmd_free_tlb(mp, pmdp, addr) pmd_free((mp)->mm, pmdp)
+#define pud_free_tlb(tlb,pudp, addr) __pud_free_tlb(tlb,pudp,addr)
 
 #define tlb_migrate_finish(mm) do { } while (0)
 #define tlb_start_vma(tlb, vma) do { } while (0)
index bd075054942bd900fecb66516b40d02c95becd0e..8daab33fc17d1808a0abd55bce2d4ac98af0a5c7 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <linux/bootmem.h>
 #include <linux/irq.h>
 
 #include <asm/ptrace.h>
@@ -887,7 +886,7 @@ void notrace init_irqwork_curcpu(void)
  * Therefore you cannot make any OBP calls, not even prom_printf,
  * from these two routines.
  */
-static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type, unsigned long qmask)
+static void __cpuinit notrace register_one_mondo(unsigned long paddr, unsigned long type, unsigned long qmask)
 {
        unsigned long num_entries = (qmask + 1) / 64;
        unsigned long status;
@@ -914,25 +913,19 @@ void __cpuinit notrace sun4v_register_mondo_queues(int this_cpu)
                           tb->nonresum_qmask);
 }
 
-static void __init alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask)
-{
-       unsigned long size = PAGE_ALIGN(qmask + 1);
-       void *p = __alloc_bootmem(size, size, 0);
-       if (!p) {
-               prom_printf("SUN4V: Error, cannot allocate mondo queue.\n");
-               prom_halt();
-       }
-
-       *pa_ptr = __pa(p);
-}
-
-static void __init alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask)
+/* Each queue region must be a power of 2 multiple of 64 bytes in
+ * size.  The base real address must be aligned to the size of the
+ * region.  Thus, an 8KB queue must be 8KB aligned, for example.
+ */
+static void __init alloc_one_queue(unsigned long *pa_ptr, unsigned long qmask)
 {
        unsigned long size = PAGE_ALIGN(qmask + 1);
-       void *p = __alloc_bootmem(size, size, 0);
+       unsigned long order = get_order(size);
+       unsigned long p;
 
+       p = __get_free_pages(GFP_KERNEL, order);
        if (!p) {
-               prom_printf("SUN4V: Error, cannot allocate kbuf page.\n");
+               prom_printf("SUN4V: Error, cannot allocate queue.\n");
                prom_halt();
        }
 
@@ -942,11 +935,11 @@ static void __init alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask)
 static void __init init_cpu_send_mondo_info(struct trap_per_cpu *tb)
 {
 #ifdef CONFIG_SMP
-       void *page;
+       unsigned long page;
 
        BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64));
 
-       page = alloc_bootmem_pages(PAGE_SIZE);
+       page = get_zeroed_page(GFP_KERNEL);
        if (!page) {
                prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n");
                prom_halt();
@@ -965,13 +958,13 @@ static void __init sun4v_init_mondo_queues(void)
        for_each_possible_cpu(cpu) {
                struct trap_per_cpu *tb = &trap_block[cpu];
 
-               alloc_one_mondo(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask);
-               alloc_one_mondo(&tb->dev_mondo_pa, tb->dev_mondo_qmask);
-               alloc_one_mondo(&tb->resum_mondo_pa, tb->resum_qmask);
-               alloc_one_kbuf(&tb->resum_kernel_buf_pa, tb->resum_qmask);
-               alloc_one_mondo(&tb->nonresum_mondo_pa, tb->nonresum_qmask);
-               alloc_one_kbuf(&tb->nonresum_kernel_buf_pa,
-                              tb->nonresum_qmask);
+               alloc_one_queue(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask);
+               alloc_one_queue(&tb->dev_mondo_pa, tb->dev_mondo_qmask);
+               alloc_one_queue(&tb->resum_mondo_pa, tb->resum_qmask);
+               alloc_one_queue(&tb->resum_kernel_buf_pa, tb->resum_qmask);
+               alloc_one_queue(&tb->nonresum_mondo_pa, tb->nonresum_qmask);
+               alloc_one_queue(&tb->nonresum_kernel_buf_pa,
+                               tb->nonresum_qmask);
        }
 }
 
@@ -999,7 +992,7 @@ void __init init_IRQ(void)
        kill_prom_timer();
 
        size = sizeof(struct ino_bucket) * NUM_IVECS;
-       ivector_table = alloc_bootmem(size);
+       ivector_table = kzalloc(size, GFP_KERNEL);
        if (!ivector_table) {
                prom_printf("Fatal error, cannot allocate ivector_table\n");
                prom_halt();
index cef8defcd7a931785acf4a8ccb8f978ee42d86bf..3ea6e8cde8c5beba98f7460d199d8a9f128057c0 100644 (file)
@@ -151,12 +151,46 @@ kvmap_dtlb_4v:
         * Must preserve %g1 and %g6 (TAG).
         */
 kvmap_dtlb_tsb4m_miss:
-       sethi           %hi(kpte_linear_bitmap), %g2
-       or              %g2, %lo(kpte_linear_bitmap), %g2
+       /* Clear the PAGE_OFFSET top virtual bits, shift
+        * down to get PFN, and make sure PFN is in range.
+        */
+       sllx            %g4, 21, %g5
 
-       /* Clear the PAGE_OFFSET top virtual bits, then shift
-        * down to get a 256MB physical address index.
+       /* Check to see if we know about valid memory at the 4MB
+        * chunk this physical address will reside within.
         */
+       srlx            %g5, 21 + 41, %g2
+       brnz,pn         %g2, kvmap_dtlb_longpath
+        nop
+
+       /* This unconditional branch and delay-slot nop gets patched
+        * by the sethi sequence once the bitmap is properly setup.
+        */
+       .globl          valid_addr_bitmap_insn
+valid_addr_bitmap_insn:
+       ba,pt           %xcc, 2f
+        nop
+       .subsection     2
+       .globl          valid_addr_bitmap_patch
+valid_addr_bitmap_patch:
+       sethi           %hi(sparc64_valid_addr_bitmap), %g7
+       or              %g7, %lo(sparc64_valid_addr_bitmap), %g7
+       .previous
+
+       srlx            %g5, 21 + 22, %g2
+       srlx            %g2, 6, %g5
+       and             %g2, 63, %g2
+       sllx            %g5, 3, %g5
+       ldx             [%g7 + %g5], %g5
+       mov             1, %g7
+       sllx            %g7, %g2, %g7
+       andcc           %g5, %g7, %g0
+       be,pn           %xcc, kvmap_dtlb_longpath
+
+2:      sethi          %hi(kpte_linear_bitmap), %g2
+       or              %g2, %lo(kpte_linear_bitmap), %g2
+
+       /* Get the 256MB physical address index. */
        sllx            %g4, 21, %g5
        mov             1, %g7
        srlx            %g5, 21 + 28, %g5
index 2c0cc72d295b079cfab695197eff38fcbd54d586..b75bf502cd424e7305959c2ca92bffd4cc88bcf4 100644 (file)
@@ -103,7 +103,7 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
        }
        if (!touched && __get_cpu_var(last_irq_sum) == sum) {
                local_inc(&__get_cpu_var(alert_counter));
-               if (local_read(&__get_cpu_var(alert_counter)) == 5 * nmi_hz)
+               if (local_read(&__get_cpu_var(alert_counter)) == 30 * nmi_hz)
                        die_nmi("BUG: NMI Watchdog detected LOCKUP",
                                regs, panic_on_timeout);
        } else {
index 8ce6285a06d55794b7a0ea68035ba65a0b39861e..7e3dfd9bb97ed677715adc641dc530e2c0d63c9b 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/security.h>
 #include <linux/signal.h>
 #include <linux/regset.h>
index a941c610e7ce0cdf8c38c38c5e3d46c32419114f..4ae91dc2feb9697c3a659aa7b993ca0636aadfb7 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/security.h>
 #include <linux/seccomp.h>
 #include <linux/audit.h>
index fa44eaf8d897b1f110e96d7e48ce8fdea686212f..3691907a43b4cdb245f540f2df15dc387a171d16 100644 (file)
@@ -1499,7 +1499,7 @@ void __init setup_per_cpu_areas(void)
        dyn_size = pcpur_size - static_size - PERCPU_MODULE_RESERVE;
 
 
-       ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpur_ptrs[0]));
+       ptrs_size = PFN_ALIGN(nr_cpu_ids * sizeof(pcpur_ptrs[0]));
        pcpur_ptrs = alloc_bootmem(ptrs_size);
 
        for_each_possible_cpu(cpu) {
@@ -1514,7 +1514,7 @@ void __init setup_per_cpu_areas(void)
 
        /* allocate address and map */
        vm.flags = VM_ALLOC;
-       vm.size = num_possible_cpus() * PCPU_CHUNK_SIZE;
+       vm.size = nr_cpu_ids * PCPU_CHUNK_SIZE;
        vm_area_register_early(&vm, PCPU_CHUNK_SIZE);
 
        for_each_possible_cpu(cpu) {
index 54fb02468f0d57ef00ce78c610609ba43d0c1702..68791cad7b74812e79c376563b029618328aac5a 100644 (file)
@@ -162,9 +162,6 @@ extern void cpu_panic(void);
  */
  
 extern struct linux_prom_registers smp_penguin_ctable;
-extern unsigned long trapbase_cpu1[];
-extern unsigned long trapbase_cpu2[];
-extern unsigned long trapbase_cpu3[];
 
 void __init smp4d_boot_cpus(void)
 {
@@ -235,25 +232,6 @@ void __init smp4d_smp_done(void)
        *prev = first;
        local_flush_cache_all();
 
-       /* Free unneeded trap tables */
-       ClearPageReserved(virt_to_page(trapbase_cpu1));
-       init_page_count(virt_to_page(trapbase_cpu1));
-       free_page((unsigned long)trapbase_cpu1);
-       totalram_pages++;
-       num_physpages++;
-
-       ClearPageReserved(virt_to_page(trapbase_cpu2));
-       init_page_count(virt_to_page(trapbase_cpu2));
-       free_page((unsigned long)trapbase_cpu2);
-       totalram_pages++;
-       num_physpages++;
-
-       ClearPageReserved(virt_to_page(trapbase_cpu3));
-       init_page_count(virt_to_page(trapbase_cpu3));
-       free_page((unsigned long)trapbase_cpu3);
-       totalram_pages++;
-       num_physpages++;
-
        /* Ok, they are spinning and ready to go. */
        smp_processors_ready = 1;
        sun4d_distribute_irqs();
index 960b113d0006f4ff61de665c2383dd4b522a4622..762d6eedd944c585d297078855f62f7580de7e7e 100644 (file)
@@ -121,9 +121,6 @@ void __cpuinit smp4m_callin(void)
  */
  
 extern struct linux_prom_registers smp_penguin_ctable;
-extern unsigned long trapbase_cpu1[];
-extern unsigned long trapbase_cpu2[];
-extern unsigned long trapbase_cpu3[];
 
 void __init smp4m_boot_cpus(void)
 {
@@ -193,29 +190,6 @@ void __init smp4m_smp_done(void)
        *prev = first;
        local_flush_cache_all();
 
-       /* Free unneeded trap tables */
-       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);
-               totalram_pages++;
-               num_physpages++;
-       }
-       if (!cpu_isset(2, cpu_present_map)) {
-               ClearPageReserved(virt_to_page(trapbase_cpu2));
-               init_page_count(virt_to_page(trapbase_cpu2));
-               free_page((unsigned long)trapbase_cpu2);
-               totalram_pages++;
-               num_physpages++;
-       }
-       if (!cpu_isset(3, cpu_present_map)) {
-               ClearPageReserved(virt_to_page(trapbase_cpu3));
-               init_page_count(virt_to_page(trapbase_cpu3));
-               free_page((unsigned long)trapbase_cpu3);
-               totalram_pages++;
-               num_physpages++;
-       }
-
        /* Ok, they are spinning and ready to go. */
 }
 
index f061c4dda9efb96dd5d8a6317169af88332b6720..aed94869ad6a6436b5d4848acb322d8900baf6ff 100644 (file)
@@ -134,10 +134,12 @@ SIGN1(sys32_getpeername, sys_getpeername, %o0)
 SIGN1(sys32_getsockname, sys_getsockname, %o0)
 SIGN2(sys32_ioprio_get, sys_ioprio_get, %o0, %o1)
 SIGN3(sys32_ioprio_set, sys_ioprio_set, %o0, %o1, %o2)
-SIGN2(sys32_splice, sys_splice, %o0, %o1)
+SIGN2(sys32_splice, sys_splice, %o0, %o2)
 SIGN2(sys32_sync_file_range, compat_sync_file_range, %o0, %o5)
 SIGN2(sys32_tee, sys_tee, %o0, %o1)
 SIGN1(sys32_vmsplice, compat_sys_vmsplice, %o0)
+SIGN1(sys32_truncate, sys_truncate, %o1)
+SIGN1(sys32_ftruncate, sys_ftruncate, %o1)
 
        .globl          sys32_mmap2
 sys32_mmap2:
index 6b3ee88e253c22035d5d0f80f39c472e59219dd1..2ee7250ba7ae6b50f08300cdaf064369e9dc47c1 100644 (file)
@@ -43,8 +43,8 @@ sys_call_table32:
 /*110*/        .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
        .word sys32_getgroups, compat_sys_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
 /*120*/        .word compat_sys_readv, compat_sys_writev, compat_sys_settimeofday, sys_fchown16, sys_fchmod
-       .word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys_truncate
-/*130*/        .word sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
+       .word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys32_truncate
+/*130*/        .word sys32_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
        .word sys_nis_syscall, sys32_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64
 /*140*/        .word sys32_sendfile64, sys_nis_syscall, sys32_futex, sys_gettid, compat_sys_getrlimit
        .word compat_sys_setrlimit, sys_pivot_root, sys32_prctl, sys_pciconfig_read, sys_pciconfig_write
index 5c12e79b4bdfe5ac1840e8e3fb30c911154f6476..da1218e8ee87a2beea896d93ec67401922623450 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/string.h>
index 358283341b4792945036fed4e32822733dd25227..c0490c7bbde0ffd187c6f0b1838108cbf9e5cd2e 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kdebug.h>
 
 #include <asm/delay.h>
index 753d128ed15885ce6143d3c167859d00a5a3627f..c28c71449a6c72652706e49cf1897c639e2f441b 100644 (file)
@@ -224,7 +224,12 @@ static struct vio_dev *vio_create_one(struct mdesc_handle *hp, u64 mp,
        if (!strcmp(type, "domain-services-port"))
                bus_id_name = "ds";
 
-       if (strlen(bus_id_name) >= BUS_ID_SIZE - 4) {
+       /*
+        * 20 char is the old driver-core name size limit, which is no more.
+        * This check can probably be removed after review and possible
+        * adaption of the vio users name length handling.
+        */
+       if (strlen(bus_id_name) >= 20 - 4) {
                printk(KERN_ERR "VIO: bus_id_name [%s] is too long.\n",
                       bus_id_name);
                return NULL;
index a5e30c642ee3bf33f136cababbb99bc20a9aba07..b99f81c4906f72ae3486c54d3cc1e69d15822383 100644 (file)
@@ -319,9 +319,10 @@ no_context:
  */
 out_of_memory:
        up_read(&mm->mmap_sem);
-       printk("VM: killing process %s\n", tsk->comm);
-       if (from_user)
-               do_group_exit(SIGKILL);
+       if (from_user) {
+               pagefault_out_of_memory();
+               return;
+       }
        goto no_context;
 
 do_sigbus:
index e5620b27c8bf6a9877367c28ca9088889f259d99..43b0da96a4fb92c4a3f5e3e1eaac67ae611832e5 100644 (file)
@@ -447,9 +447,10 @@ handle_kernel_fault:
 out_of_memory:
        insn = get_fault_insn(regs, insn);
        up_read(&mm->mmap_sem);
-       printk("VM: killing process %s\n", current->comm);
-       if (!(regs->tstate & TSTATE_PRIV))
-               do_group_exit(SIGKILL);
+       if (!(regs->tstate & TSTATE_PRIV)) {
+               pagefault_out_of_memory();
+               return;
+       }
        goto handle_kernel_fault;
 
 intr_or_no_mm:
index ed6be6ba2f4e9f7859c3e34b27fdc8e5ccc6f5ab..a70a5e1904d9d556e43fcd893b83752856d0cd3e 100644 (file)
@@ -145,7 +145,8 @@ static void __init read_obp_memory(const char *property,
             cmp_p64, NULL);
 }
 
-unsigned long *sparc64_valid_addr_bitmap __read_mostly;
+unsigned long sparc64_valid_addr_bitmap[VALID_ADDR_BITMAP_BYTES /
+                                       sizeof(unsigned long)];
 EXPORT_SYMBOL(sparc64_valid_addr_bitmap);
 
 /* Kernel physical address base and size in bytes.  */
@@ -1874,7 +1875,7 @@ static int pavail_rescan_ents __initdata;
  * memory list again, and make sure it provides at least as much
  * memory as 'pavail' does.
  */
-static void __init setup_valid_addr_bitmap_from_pavail(void)
+static void __init setup_valid_addr_bitmap_from_pavail(unsigned long *bitmap)
 {
        int i;
 
@@ -1897,8 +1898,7 @@ static void __init setup_valid_addr_bitmap_from_pavail(void)
 
                                if (new_start <= old_start &&
                                    new_end >= (old_start + PAGE_SIZE)) {
-                                       set_bit(old_start >> 22,
-                                               sparc64_valid_addr_bitmap);
+                                       set_bit(old_start >> 22, bitmap);
                                        goto do_next_page;
                                }
                        }
@@ -1919,20 +1919,21 @@ static void __init setup_valid_addr_bitmap_from_pavail(void)
        }
 }
 
+static void __init patch_tlb_miss_handler_bitmap(void)
+{
+       extern unsigned int valid_addr_bitmap_insn[];
+       extern unsigned int valid_addr_bitmap_patch[];
+
+       valid_addr_bitmap_insn[1] = valid_addr_bitmap_patch[1];
+       mb();
+       valid_addr_bitmap_insn[0] = valid_addr_bitmap_patch[0];
+       flushi(&valid_addr_bitmap_insn[0]);
+}
+
 void __init mem_init(void)
 {
        unsigned long codepages, datapages, initpages;
        unsigned long addr, last;
-       int i;
-
-       i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6);
-       i += 1;
-       sparc64_valid_addr_bitmap = (unsigned long *) alloc_bootmem(i << 3);
-       if (sparc64_valid_addr_bitmap == NULL) {
-               prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n");
-               prom_halt();
-       }
-       memset(sparc64_valid_addr_bitmap, 0, i << 3);
 
        addr = PAGE_OFFSET + kern_base;
        last = PAGE_ALIGN(kern_size) + addr;
@@ -1941,15 +1942,19 @@ void __init mem_init(void)
                addr += PAGE_SIZE;
        }
 
-       setup_valid_addr_bitmap_from_pavail();
+       setup_valid_addr_bitmap_from_pavail(sparc64_valid_addr_bitmap);
+       patch_tlb_miss_handler_bitmap();
 
        high_memory = __va(last_valid_pfn << PAGE_SHIFT);
 
 #ifdef CONFIG_NEED_MULTIPLE_NODES
-       for_each_online_node(i) {
-               if (NODE_DATA(i)->node_spanned_pages != 0) {
-                       totalram_pages +=
-                               free_all_bootmem_node(NODE_DATA(i));
+       {
+               int i;
+               for_each_online_node(i) {
+                       if (NODE_DATA(i)->node_spanned_pages != 0) {
+                               totalram_pages +=
+                                       free_all_bootmem_node(NODE_DATA(i));
+                       }
                }
        }
 #else
index 16063870a489c784eee30e0cbfb0637a9548fd4b..c2f772dbd556ffaa5a75430500fbedb9cde3d3fd 100644 (file)
@@ -5,10 +5,13 @@
  * marked non-static so that assembler code can get at them.
  */
 
-#define MAX_PHYS_ADDRESS       (1UL << 42UL)
-#define KPTE_BITMAP_CHUNK_SZ   (256UL * 1024UL * 1024UL)
+#define MAX_PHYS_ADDRESS       (1UL << 41UL)
+#define KPTE_BITMAP_CHUNK_SZ           (256UL * 1024UL * 1024UL)
 #define KPTE_BITMAP_BYTES      \
        ((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 8)
+#define VALID_ADDR_BITMAP_CHUNK_SZ     (4UL * 1024UL * 1024UL)
+#define VALID_ADDR_BITMAP_BYTES        \
+       ((MAX_PHYS_ADDRESS / VALID_ADDR_BITMAP_CHUNK_SZ) / 8)
 
 extern unsigned long kern_linear_pte_xor[2];
 extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
index eedffb4fec2d64132402cd3007897275962158a4..39fc6af21b7c55ddc0e752c80c745ed6c018820a 100644 (file)
@@ -88,7 +88,7 @@ void prom_cmdline(void)
 /* Drop into the prom, but completely terminate the program.
  * No chance of continuing.
  */
-void prom_halt(void)
+void notrace prom_halt(void)
 {
 #ifdef CONFIG_SUN_LDOMS
        if (ldom_domaining_enabled)
index 660943ee4c2ac7e431822dc1f99cf9e8bac294e7..ca869266b9f3d0106e60d7b8c28f5cdcf614826b 100644 (file)
  */
 
 #include <linux/kernel.h>
+#include <linux/compiler.h>
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 
 static char ppbuf[1024];
 
-void
-prom_write(const char *buf, unsigned int n)
+void notrace prom_write(const char *buf, unsigned int n)
 {
        char ch;
 
@@ -33,8 +33,7 @@ prom_write(const char *buf, unsigned int n)
        }
 }
 
-void
-prom_printf(const char *fmt, ...)
+void notrace prom_printf(const char *fmt, ...)
 {
        va_list args;
        int i;
index 5ec17563142e22cc6f6ff1e3ec76db23666d3ec9..dd2aadc14af0ab6768723bc8fbade09e6c3203b3 100644 (file)
@@ -30,7 +30,6 @@ static void slip_init(struct net_device *dev, void *data)
 
        slip_proto_init(&spri->slip);
 
-       dev->init = NULL;
        dev->hard_header_len = 0;
        dev->header_ops = NULL;
        dev->addr_len = 0;
index f15a6e7654f36fdf17af6388172d8273ebb11f71..e376284f0fb7fdc42e1d1e026abe52408501f4d1 100644 (file)
@@ -32,7 +32,6 @@ void slirp_init(struct net_device *dev, void *data)
 
        slip_proto_init(&spri->slip);
 
-       dev->init = NULL;
        dev->hard_header_len = 0;
        dev->header_ops = NULL;
        dev->addr_len = 0;
index 90fc708b320e4c2a54425981bfb2d73b12a90ffe..378de4bbf49ff50486848893ad2a5454df69dd52 100644 (file)
@@ -79,14 +79,14 @@ dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
 }
 
 static inline void
-dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
+dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
                enum dma_data_direction direction)
 {
        BUG();
 }
 
 static inline void
-dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
            enum dma_data_direction direction)
 {
        BUG();
index 718984359f8c8876d84a2a902fa0b6fa6b4cb933..32c8ce4e15153ee6d42fb72fd7579df0400f9e69 100644 (file)
@@ -40,7 +40,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
        __free_page(pte);
 }
 
-#define __pte_free_tlb(tlb,pte)                                \
+#define __pte_free_tlb(tlb,pte, address)               \
 do {                                                   \
        pgtable_page_dtor(pte);                         \
        tlb_remove_page((tlb),(pte));                   \
@@ -53,7 +53,7 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
        free_page((unsigned long)pmd);
 }
 
-#define __pmd_free_tlb(tlb,x)   tlb_remove_page((tlb),virt_to_page(x))
+#define __pmd_free_tlb(tlb,x, address)   tlb_remove_page((tlb),virt_to_page(x))
 #endif
 
 #define check_pgt_cache()      do { } while (0)
index 62274ab9471fe6f8eb0de14368acf05b65e17691..fd911f855367a2d55506d7b002fce51cd2039ec2 100644 (file)
@@ -32,7 +32,7 @@ struct thread_info {
        .exec_domain =  &default_exec_domain,   \
        .flags =                0,              \
        .cpu =          0,                      \
-       .preempt_count =        1,              \
+       .preempt_count = INIT_PREEMPT_COUNT,    \
        .addr_limit =   KERNEL_DS,              \
        .restart_block =  {                     \
                .fn =  do_no_restart_syscall,   \
index 5240fa1c5e0860debec1fcf56daf1e3db30970ec..660caedac9eb70bb3314beb5b1e87a3d3e876bef 100644 (file)
@@ -116,11 +116,11 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
                __tlb_remove_tlb_entry(tlb, ptep, address);     \
        } while (0)
 
-#define pte_free_tlb(tlb, ptep) __pte_free_tlb(tlb, ptep)
+#define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr)
 
-#define pud_free_tlb(tlb, pudp) __pud_free_tlb(tlb, pudp)
+#define pud_free_tlb(tlb, pudp, addr) __pud_free_tlb(tlb, pudp, addr)
 
-#define pmd_free_tlb(tlb, pmdp) __pmd_free_tlb(tlb, pmdp)
+#define pmd_free_tlb(tlb, pmdp, addr) __pmd_free_tlb(tlb, pmdp, addr)
 
 #define tlb_migrate_finish(mm) do {} while (0)
 
index 56d43d0a39602b140d458f2f989779bc9512b66a..0960de54495abf48e7f290c024cb3877f70e1c69 100644 (file)
@@ -70,8 +70,8 @@ void show_stack(struct task_struct *task, unsigned long *esp)
                if (kstack_end(stack))
                        break;
                if (i && ((i % 8) == 0))
-                       printk("\n" KERN_INFO "       ");
-               printk("%08lx ", *stack++);
+                       printk(KERN_INFO "       ");
+               printk(KERN_CONT "%08lx ", *stack++);
        }
 
        show_trace(task, esp);
index d1430ef6b4f9a463c7ddc3b7be49754f5fa883bd..13ffa5df37d75120e6a3965102b24a05d3ee0fb7 100644 (file)
@@ -24,6 +24,7 @@ config X86
        select HAVE_UNSTABLE_SCHED_CLOCK
        select HAVE_IDE
        select HAVE_OPROFILE
+       select HAVE_PERF_COUNTERS if (!M386 && !M486)
        select HAVE_IOREMAP_PROT
        select HAVE_KPROBES
        select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -742,7 +743,6 @@ config X86_UP_IOAPIC
 config X86_LOCAL_APIC
        def_bool y
        depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
-       select HAVE_PERF_COUNTERS if (!M386 && !M486)
 
 config X86_IO_APIC
        def_bool y
@@ -1913,25 +1913,26 @@ config DMAR_DEFAULT_ON
          recommended you say N here while the DMAR code remains
          experimental.
 
-config DMAR_GFX_WA
-       def_bool y
-       prompt "Support for Graphics workaround"
+config DMAR_BROKEN_GFX_WA
+       def_bool n
+       prompt "Workaround broken graphics drivers (going away soon)"
        depends on DMAR
        ---help---
          Current Graphics drivers tend to use physical address
          for DMA and avoid using DMA APIs. Setting this config
          option permits the IOMMU driver to set a unity map for
          all the OS-visible memory. Hence the driver can continue
-         to use physical addresses for DMA.
+         to use physical addresses for DMA, at least until this
+         option is removed in the 2.6.32 kernel.
 
 config DMAR_FLOPPY_WA
        def_bool y
        depends on DMAR
        ---help---
-         Floppy disk drivers are know to bypass DMA API calls
+         Floppy disk drivers are known to bypass DMA API calls
          thereby failing to work when IOMMU is enabled. This
          workaround will setup a 1:1 mapping for the first
-         16M to make floppy (an ISA device) work.
+         16MiB to make floppy (an ISA device) work.
 
 config INTR_REMAP
        bool "Support for Interrupt Remapping (EXPERIMENTAL)"
index e2ff504b4ddcb7fe8e3b506f5f089276fe655e2b..f8ed0658404cc559d7c65a261330dba620017f38 100644 (file)
@@ -4,7 +4,7 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
-targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma head_$(BITS).o misc.o piggy.o
+targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma head_$(BITS).o misc.o piggy.o
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
 KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
index d660be4923634ebfc0160b468a569289c02bce90..49e0c18833e0d23361f218e3c67a51e171f600ed 100644 (file)
@@ -37,14 +37,13 @@ static int set_bios_mode(u8 mode)
        ireg.al = mode;         /* AH=0x00 Set Video Mode */
        intcall(0x10, &ireg, NULL);
 
-
        ireg.ah = 0x0f;         /* Get Current Video Mode */
        intcall(0x10, &ireg, &oreg);
 
        do_restore = 1;         /* Assume video contents were lost */
 
        /* Not all BIOSes are clean with the top bit */
-       new_mode = ireg.al & 0x7f;
+       new_mode = oreg.al & 0x7f;
 
        if (new_mode == mode)
                return 0;       /* Mode change OK */
index c700147d6ffb24b72fbbf43ff954d4cfd268f137..275dd177f1985719f239c10a148306c9c5995572 100644 (file)
@@ -45,7 +45,7 @@ static int vesa_probe(void)
        ireg.di = (size_t)&vginfo;
        intcall(0x10, &ireg, &oreg);
 
-       if (ireg.ax != 0x004f ||
+       if (oreg.ax != 0x004f ||
            vginfo.signature != VESA_MAGIC ||
            vginfo.version < 0x0102)
                return 0;       /* Not present */
@@ -70,7 +70,7 @@ static int vesa_probe(void)
                ireg.di = (size_t)&vminfo;
                intcall(0x10, &ireg, &oreg);
 
-               if (ireg.ax != 0x004f)
+               if (oreg.ax != 0x004f)
                        continue;
 
                if ((vminfo.mode_attr & 0x15) == 0x05) {
index 2503d4e64c2a79a2aab7618e9c325aadb428e74d..dc5a667ff791388074804ee547b92370c07f59c6 100644 (file)
  *
  * Atomically reads the value of @v.
  */
-#define atomic_read(v)         ((v)->counter)
+static inline int atomic_read(const atomic_t *v)
+{
+       return v->counter;
+}
 
 /**
  * atomic_set - set atomic variable
  *
  * Atomically sets the value of @v to @i.
  */
-#define atomic_set(v, i)       (((v)->counter) = (i))
+static inline void atomic_set(atomic_t *v, int i)
+{
+       v->counter = i;
+}
 
 /**
  * atomic_add - add integer to atomic variable
@@ -200,8 +206,15 @@ static inline int atomic_sub_return(int i, atomic_t *v)
        return atomic_add_return(-i, v);
 }
 
-#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
+static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+       return cmpxchg(&v->counter, old, new);
+}
+
+static inline int atomic_xchg(atomic_t *v, int new)
+{
+       return xchg(&v->counter, new);
+}
 
 /**
  * atomic_add_unless - add unless the number is already a given value
@@ -250,45 +263,12 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 /* An 64bit atomic type */
 
 typedef struct {
-       unsigned long long counter;
+       u64 __aligned(8) counter;
 } atomic64_t;
 
 #define ATOMIC64_INIT(val)     { (val) }
 
-/**
- * atomic64_read - read atomic64 variable
- * @ptr: pointer of type atomic64_t
- *
- * Atomically reads the value of @v.
- * Doesn't imply a read memory barrier.
- */
-#define __atomic64_read(ptr)           ((ptr)->counter)
-
-static inline unsigned long long
-cmpxchg8b(unsigned long long *ptr, unsigned long long old, unsigned long long new)
-{
-       asm volatile(
-
-               LOCK_PREFIX "cmpxchg8b (%[ptr])\n"
-
-                    :          "=A" (old)
-
-                    : [ptr]    "D" (ptr),
-                               "A" (old),
-                               "b" (ll_low(new)),
-                               "c" (ll_high(new))
-
-                    : "memory");
-
-       return old;
-}
-
-static inline unsigned long long
-atomic64_cmpxchg(atomic64_t *ptr, unsigned long long old_val,
-                unsigned long long new_val)
-{
-       return cmpxchg8b(&ptr->counter, old_val, new_val);
-}
+extern u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val);
 
 /**
  * atomic64_xchg - xchg atomic64 variable
@@ -298,18 +278,7 @@ atomic64_cmpxchg(atomic64_t *ptr, unsigned long long old_val,
  * Atomically xchgs the value of @ptr to @new_val and returns
  * the old value.
  */
-
-static inline unsigned long long
-atomic64_xchg(atomic64_t *ptr, unsigned long long new_val)
-{
-       unsigned long long old_val;
-
-       do {
-               old_val = atomic_read(ptr);
-       } while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val);
-
-       return old_val;
-}
+extern u64 atomic64_xchg(atomic64_t *ptr, u64 new_val);
 
 /**
  * atomic64_set - set atomic64 variable
@@ -318,10 +287,7 @@ atomic64_xchg(atomic64_t *ptr, unsigned long long new_val)
  *
  * Atomically sets the value of @ptr to @new_val.
  */
-static inline void atomic64_set(atomic64_t *ptr, unsigned long long new_val)
-{
-       atomic64_xchg(ptr, new_val);
-}
+extern void atomic64_set(atomic64_t *ptr, u64 new_val);
 
 /**
  * atomic64_read - read atomic64 variable
@@ -329,17 +295,30 @@ static inline void atomic64_set(atomic64_t *ptr, unsigned long long new_val)
  *
  * Atomically reads the value of @ptr and returns it.
  */
-static inline unsigned long long atomic64_read(atomic64_t *ptr)
+static inline u64 atomic64_read(atomic64_t *ptr)
 {
-       unsigned long long curr_val;
-
-       do {
-               curr_val = __atomic64_read(ptr);
-       } while (atomic64_cmpxchg(ptr, curr_val, curr_val) != curr_val);
-
-       return curr_val;
+       u64 res;
+
+       /*
+        * Note, we inline this atomic64_t primitive because
+        * it only clobbers EAX/EDX and leaves the others
+        * untouched. We also (somewhat subtly) rely on the
+        * fact that cmpxchg8b returns the current 64-bit value
+        * of the memory location we are touching:
+        */
+       asm volatile(
+               "mov %%ebx, %%eax\n\t"
+               "mov %%ecx, %%edx\n\t"
+               LOCK_PREFIX "cmpxchg8b %1\n"
+                       : "=&A" (res)
+                       : "m" (*ptr)
+               );
+
+       return res;
 }
 
+extern u64 atomic64_read(atomic64_t *ptr);
+
 /**
  * atomic64_add_return - add and return
  * @delta: integer value to add
@@ -347,34 +326,14 @@ static inline unsigned long long atomic64_read(atomic64_t *ptr)
  *
  * Atomically adds @delta to @ptr and returns @delta + *@ptr
  */
-static inline unsigned long long
-atomic64_add_return(unsigned long long delta, atomic64_t *ptr)
-{
-       unsigned long long old_val, new_val;
-
-       do {
-               old_val = atomic_read(ptr);
-               new_val = old_val + delta;
-
-       } while (atomic64_cmpxchg(ptr, old_val, new_val) != old_val);
-
-       return new_val;
-}
-
-static inline long atomic64_sub_return(unsigned long long delta, atomic64_t *ptr)
-{
-       return atomic64_add_return(-delta, ptr);
-}
+extern u64 atomic64_add_return(u64 delta, atomic64_t *ptr);
 
-static inline long atomic64_inc_return(atomic64_t *ptr)
-{
-       return atomic64_add_return(1, ptr);
-}
-
-static inline long atomic64_dec_return(atomic64_t *ptr)
-{
-       return atomic64_sub_return(1, ptr);
-}
+/*
+ * Other variants with different arithmetic operators:
+ */
+extern u64 atomic64_sub_return(u64 delta, atomic64_t *ptr);
+extern u64 atomic64_inc_return(atomic64_t *ptr);
+extern u64 atomic64_dec_return(atomic64_t *ptr);
 
 /**
  * atomic64_add - add integer to atomic64 variable
@@ -383,10 +342,7 @@ static inline long atomic64_dec_return(atomic64_t *ptr)
  *
  * Atomically adds @delta to @ptr.
  */
-static inline void atomic64_add(unsigned long long delta, atomic64_t *ptr)
-{
-       atomic64_add_return(delta, ptr);
-}
+extern void atomic64_add(u64 delta, atomic64_t *ptr);
 
 /**
  * atomic64_sub - subtract the atomic64 variable
@@ -395,10 +351,7 @@ static inline void atomic64_add(unsigned long long delta, atomic64_t *ptr)
  *
  * Atomically subtracts @delta from @ptr.
  */
-static inline void atomic64_sub(unsigned long long delta, atomic64_t *ptr)
-{
-       atomic64_add(-delta, ptr);
-}
+extern void atomic64_sub(u64 delta, atomic64_t *ptr);
 
 /**
  * atomic64_sub_and_test - subtract value from variable and test result
@@ -409,13 +362,7 @@ static inline void atomic64_sub(unsigned long long delta, atomic64_t *ptr)
  * true if the result is zero, or false for all
  * other cases.
  */
-static inline int
-atomic64_sub_and_test(unsigned long long delta, atomic64_t *ptr)
-{
-       unsigned long long old_val = atomic64_sub_return(delta, ptr);
-
-       return old_val == 0;
-}
+extern int atomic64_sub_and_test(u64 delta, atomic64_t *ptr);
 
 /**
  * atomic64_inc - increment atomic64 variable
@@ -423,10 +370,7 @@ atomic64_sub_and_test(unsigned long long delta, atomic64_t *ptr)
  *
  * Atomically increments @ptr by 1.
  */
-static inline void atomic64_inc(atomic64_t *ptr)
-{
-       atomic64_add(1, ptr);
-}
+extern void atomic64_inc(atomic64_t *ptr);
 
 /**
  * atomic64_dec - decrement atomic64 variable
@@ -434,10 +378,7 @@ static inline void atomic64_inc(atomic64_t *ptr)
  *
  * Atomically decrements @ptr by 1.
  */
-static inline void atomic64_dec(atomic64_t *ptr)
-{
-       atomic64_sub(1, ptr);
-}
+extern void atomic64_dec(atomic64_t *ptr);
 
 /**
  * atomic64_dec_and_test - decrement and test
@@ -447,10 +388,7 @@ static inline void atomic64_dec(atomic64_t *ptr)
  * returns true if the result is 0, or false for all other
  * cases.
  */
-static inline int atomic64_dec_and_test(atomic64_t *ptr)
-{
-       return atomic64_sub_and_test(1, ptr);
-}
+extern int atomic64_dec_and_test(atomic64_t *ptr);
 
 /**
  * atomic64_inc_and_test - increment and test
@@ -460,10 +398,7 @@ static inline int atomic64_dec_and_test(atomic64_t *ptr)
  * and returns true if the result is zero, or false for all
  * other cases.
  */
-static inline int atomic64_inc_and_test(atomic64_t *ptr)
-{
-       return atomic64_sub_and_test(-1, ptr);
-}
+extern int atomic64_inc_and_test(atomic64_t *ptr);
 
 /**
  * atomic64_add_negative - add and test if negative
@@ -474,13 +409,7 @@ static inline int atomic64_inc_and_test(atomic64_t *ptr)
  * if the result is negative, or false when
  * result is greater than or equal to zero.
  */
-static inline int
-atomic64_add_negative(unsigned long long delta, atomic64_t *ptr)
-{
-       long long old_val = atomic64_add_return(delta, ptr);
-
-       return old_val < 0;
-}
+extern int atomic64_add_negative(u64 delta, atomic64_t *ptr);
 
 #include <asm-generic/atomic-long.h>
 #endif /* _ASM_X86_ATOMIC_32_H */
index 0d6360220007b2bc3a35952a7fa4830c837ad4af..d605dc268e798b5bb9e0a5df36de3e5aa88d0e5f 100644 (file)
  *
  * Atomically reads the value of @v.
  */
-#define atomic_read(v)         ((v)->counter)
+static inline int atomic_read(const atomic_t *v)
+{
+       return v->counter;
+}
 
 /**
  * atomic_set - set atomic variable
  *
  * Atomically sets the value of @v to @i.
  */
-#define atomic_set(v, i)               (((v)->counter) = (i))
+static inline void atomic_set(atomic_t *v, int i)
+{
+       v->counter = i;
+}
 
 /**
  * atomic_add - add integer to atomic variable
@@ -192,7 +198,10 @@ static inline int atomic_sub_return(int i, atomic_t *v)
  * Atomically reads the value of @v.
  * Doesn't imply a read memory barrier.
  */
-#define atomic64_read(v)               ((v)->counter)
+static inline long atomic64_read(const atomic64_t *v)
+{
+       return v->counter;
+}
 
 /**
  * atomic64_set - set atomic64 variable
@@ -201,7 +210,10 @@ static inline int atomic_sub_return(int i, atomic_t *v)
  *
  * Atomically sets the value of @v to @i.
  */
-#define atomic64_set(v, i)             (((v)->counter) = (i))
+static inline void atomic64_set(atomic64_t *v, long i)
+{
+       v->counter = i;
+}
 
 /**
  * atomic64_add - add integer to atomic64 variable
@@ -355,11 +367,25 @@ static inline long atomic64_sub_return(long i, atomic64_t *v)
 #define atomic64_inc_return(v)  (atomic64_add_return(1, (v)))
 #define atomic64_dec_return(v)  (atomic64_sub_return(1, (v)))
 
-#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
-#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new)
+{
+       return cmpxchg(&v->counter, old, new);
+}
+
+static inline long atomic64_xchg(atomic64_t *v, long new)
+{
+       return xchg(&v->counter, new);
+}
 
-#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
-#define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
+static inline long atomic_cmpxchg(atomic_t *v, int old, int new)
+{
+       return cmpxchg(&v->counter, old, new);
+}
+
+static inline long atomic_xchg(atomic_t *v, int new)
+{
+       return xchg(&v->counter, new);
+}
 
 /**
  * atomic_add_unless - add unless the number is a given value
index 418e632d4a801aa8e86f565afeae59659d6500a0..7a1065958ba9d3f1c5a26b9862864e4707418916 100644 (file)
@@ -8,7 +8,7 @@
 
 #ifdef __KERNEL__
 
-#include <asm/page_types.h>
+#include <asm/pgtable_types.h>
 
 /* Physical address where kernel should be loaded. */
 #define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \
                                & ~(CONFIG_PHYSICAL_ALIGN - 1))
 
 /* Minimum kernel alignment, as a power of two */
-#ifdef CONFIG_x86_64
+#ifdef CONFIG_X86_64
 #define MIN_KERNEL_ALIGN_LG2   PMD_SHIFT
 #else
-#define MIN_KERNEL_ALIGN_LG2   (PAGE_SHIFT+1)
+#define MIN_KERNEL_ALIGN_LG2   (PAGE_SHIFT + THREAD_ORDER)
 #endif
 #define MIN_KERNEL_ALIGN       (_AC(1, UL) << MIN_KERNEL_ALIGN_LG2)
 
index edc90f23e70814a80491b45db2409656c1b35be4..8406ed7f99269f97c469bc9b03e0cb8d00276f84 100644 (file)
@@ -33,7 +33,7 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);
 #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6)      \
        efi_call_virt(f, a1, a2, a3, a4, a5, a6)
 
-#define efi_ioremap(addr, size)                        ioremap_cache(addr, size)
+#define efi_ioremap(addr, size, type)          ioremap_cache(addr, size)
 
 #else /* !CONFIG_X86_32 */
 
@@ -84,7 +84,8 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
        efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
                  (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
 
-extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size);
+extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
+                                u32 type);
 
 #endif /* CONFIG_X86_32 */
 
index 2d81af3974a070185ca672eb4bebf246d7eeaaa5..7b2d71df39a6ac42fc631628239f4f41c1be243b 100644 (file)
@@ -111,12 +111,9 @@ enum fixed_addresses {
 #ifdef CONFIG_PARAVIRT
        FIX_PARAVIRT_BOOTMAP,
 #endif
-       FIX_TEXT_POKE0, /* reserve 2 pages for text_poke() */
-       FIX_TEXT_POKE1,
+       FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */
+       FIX_TEXT_POKE0, /* first page is last, because allocation is backward */
        __end_of_permanent_fixed_addresses,
-#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
-       FIX_OHCI1394_BASE,
-#endif
        /*
         * 256 temporary boot-time mappings, used by early_ioremap(),
         * before ioremap() is functional.
@@ -129,6 +126,9 @@ enum fixed_addresses {
        FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
                        (__end_of_permanent_fixed_addresses & 255),
        FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1,
+#ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT
+       FIX_OHCI1394_BASE,
+#endif
 #ifdef CONFIG_X86_32
        FIX_WP_TEST,
 #endif
index daf866ed0612413f3781cdf6f863e8038daebe85..330ee807f89e7e007a93d093c08b9108b3af22d0 100644 (file)
@@ -161,6 +161,7 @@ extern int io_apic_set_pci_routing(struct device *dev, int irq,
                 struct io_apic_irq_attr *irq_attr);
 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 extern void ioapic_init_mappings(void);
+extern void ioapic_insert_resources(void);
 
 extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
 extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
@@ -180,6 +181,7 @@ extern void ioapic_write_entry(int apic, int pin,
 #define io_apic_assign_pci_irqs 0
 static const int timer_through_8259 = 0;
 static inline void ioapic_init_mappings(void)  { }
+static inline void ioapic_insert_resources(void) { }
 
 static inline void probe_nr_irqs_gsi(void)     { }
 #endif
index 2bdab21f0898dedee3ad1bf495b73b7ae0d3f997..c6ccbe7e81ad21731b251c5ce9e9bf5bd0c64116 100644 (file)
@@ -12,9 +12,15 @@ static inline unsigned long native_save_fl(void)
 {
        unsigned long flags;
 
+       /*
+        * Note: this needs to be "=r" not "=rm", because we have the
+        * stack offset from what gcc expects at the time the "pop" is
+        * executed, and so a memory reference with respect to the stack
+        * would end up using the wrong address.
+        */
        asm volatile("# __raw_save_flags\n\t"
                     "pushf ; pop %0"
-                    : "=g" (flags)
+                    : "=r" (flags)
                     : /* no input */
                     : "memory");
 
index 313389cd50d2a3dfe1285152b2d43645e40f7636..5136dad57cbb2c010c1a2854eafe13674d311d48 100644 (file)
@@ -17,8 +17,7 @@
 /* Pages for switcher itself, then two pages per cpu */
 #define TOTAL_SWITCHER_PAGES (SHARED_SWITCHER_PAGES + 2 * nr_cpu_ids)
 
-/* We map at -4M (-2M when PAE is activated) for ease of mapping
- * into the guest (one PTE page). */
+/* We map at -4M (-2M for PAE) for ease of mapping (one PTE page). */
 #ifdef CONFIG_X86_PAE
 #define SWITCHER_ADDR 0xFFE00000
 #else
index d31c4a684078080ebe48fbc4d90ebd7f67dce568..ba0eed8aa1a6d133a065963ab0cd331bf9eeacb9 100644 (file)
 #include <asm/hw_irq.h>
 #include <asm/kvm_para.h>
 
-/*G:031 But first, how does our Guest contact the Host to ask for privileged
+/*G:030
+ * But first, how does our Guest contact the Host to ask for privileged
  * operations?  There are two ways: the direct way is to make a "hypercall",
  * to make requests of the Host Itself.
  *
- * We use the KVM hypercall mechanism. Seventeen hypercalls are
- * available: the hypercall number is put in the %eax register, and the
- * arguments (when required) are placed in %ebx, %ecx, %edx and %esi.
- * If a return value makes sense, it's returned in %eax.
+ * We use the KVM hypercall mechanism, though completely different hypercall
+ * numbers. Seventeen hypercalls are available: the hypercall number is put in
+ * the %eax register, and the arguments (when required) are placed in %ebx,
+ * %ecx, %edx and %esi.  If a return value makes sense, it's returned in %eax.
  *
  * Grossly invalid calls result in Sudden Death at the hands of the vengeful
  * Host, rather than returning failure.  This reflects Winston Churchill's
- * definition of a gentleman: "someone who is only rude intentionally". */
-/*:*/
+ * definition of a gentleman: "someone who is only rude intentionally".
+:*/
 
 /* Can't use our min() macro here: needs to be a constant */
 #define LGUEST_IRQS (NR_IRQS < 32 ? NR_IRQS: 32)
 
 #define LHCALL_RING_SIZE 64
 struct hcall_args {
-       /* These map directly onto eax, ebx, ecx, edx and esi
-        * in struct lguest_regs */
+       /* These map directly onto eax/ebx/ecx/edx/esi in struct lguest_regs */
        unsigned long arg0, arg1, arg2, arg3, arg4;
 };
 
index 1692fb5050e35e010e904c54043576ff83cff746..6be7fc254b599160e33c94112d37935fe3783d55 100644 (file)
 #define MSR_IA32_MISC_ENABLE_TURBO_DISABLE     (1ULL << 38)
 #define MSR_IA32_MISC_ENABLE_IP_PREF_DISABLE   (1ULL << 39)
 
-/* Intel Model 6 */
-#define MSR_P6_EVNTSEL0                        0x00000186
-#define MSR_P6_EVNTSEL1                        0x00000187
-
 /* P4/Xeon+ specific */
 #define MSR_IA32_MCG_EAX               0x00000180
 #define MSR_IA32_MCG_EBX               0x00000181
index c97264409934be915d24d35395c1c0af5956aa7b..c86e5ed4af51dc0802291eb4b4af1af9793b938b 100644 (file)
@@ -72,7 +72,6 @@ void lapic_watchdog_stop(void);
 int lapic_watchdog_init(unsigned nmi_hz);
 int lapic_wd_event(unsigned nmi_hz);
 unsigned lapic_adjust_nmi_hz(unsigned hz);
-int lapic_watchdog_ok(void);
 void disable_lapic_nmi_watchdog(void);
 void enable_lapic_nmi_watchdog(void);
 void stop_nmi(void);
index 927958d13c1967114ebba7ac6bd8bacc9ddbd56c..1ff685ca221ceec7fd324f6409393984aec4c399 100644 (file)
@@ -91,7 +91,7 @@ extern void pci_iommu_alloc(void);
 
 #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
 
-#if defined(CONFIG_X86_64) || defined(CONFIG_DMA_API_DEBUG)
+#if defined(CONFIG_X86_64) || defined(CONFIG_DMAR) || defined(CONFIG_DMA_API_DEBUG)
 
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)       \
                dma_addr_t ADDR_NAME;
index 02ecb30982a3a61d5e655b70d3599b9a2540dd3b..103f1ddb0d85b342498beef4153267a3af93f0a0 100644 (file)
@@ -42,6 +42,7 @@
 
 #else /* ...!ASSEMBLY */
 
+#include <linux/kernel.h>
 #include <linux/stringify.h>
 
 #ifdef CONFIG_SMP
@@ -155,6 +156,15 @@ do {                                                       \
 /* We can use this directly for local CPU (faster). */
 DECLARE_PER_CPU(unsigned long, this_cpu_off);
 
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+void *pcpu_lpage_remapped(void *kaddr);
+#else
+static inline void *pcpu_lpage_remapped(void *kaddr)
+{
+       return NULL;
+}
+#endif
+
 #endif /* !__ASSEMBLY__ */
 
 #ifdef CONFIG_SMP
index 5fb33e160ea0b585b065b726ede5a855bfa22df7..fa64e401589d4ed9089c908f06c3bef2261c4d9f 100644 (file)
@@ -87,6 +87,9 @@ union cpuid10_edx {
 #ifdef CONFIG_PERF_COUNTERS
 extern void init_hw_perf_counters(void);
 extern void perf_counters_lapic_init(void);
+
+#define PERF_COUNTER_INDEX_OFFSET                      0
+
 #else
 static inline void init_hw_perf_counters(void)         { }
 static inline void perf_counters_lapic_init(void)      { }
index dd14c54ac718f465ebccf0b486b421f3d3937c6b..0e8c2a0fd9222d4b75793fb664591de22461e7d7 100644 (file)
@@ -46,7 +46,13 @@ static inline void pte_free(struct mm_struct *mm, struct page *pte)
        __free_page(pte);
 }
 
-extern void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
+extern void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte);
+
+static inline void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte,
+                                 unsigned long address)
+{
+       ___pte_free_tlb(tlb, pte);
+}
 
 static inline void pmd_populate_kernel(struct mm_struct *mm,
                                       pmd_t *pmd, pte_t *pte)
@@ -78,7 +84,13 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
        free_page((unsigned long)pmd);
 }
 
-extern void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
+extern void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd);
+
+static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
+                                 unsigned long adddress)
+{
+       ___pmd_free_tlb(tlb, pmd);
+}
 
 #ifdef CONFIG_X86_PAE
 extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
@@ -108,7 +120,14 @@ static inline void pud_free(struct mm_struct *mm, pud_t *pud)
        free_page((unsigned long)pud);
 }
 
-extern void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud);
+extern void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud);
+
+static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
+                                 unsigned long address)
+{
+       ___pud_free_tlb(tlb, pud);
+}
+
 #endif /* PAGETABLE_LEVELS > 3 */
 #endif /* PAGETABLE_LEVELS > 2 */
 
index 3cc06e3fceb8e8ba2b9a7d72b7608c520aa5b81f..16748077559abf2771ce84ec0ea38eaa82dc8298 100644 (file)
@@ -2,6 +2,7 @@
 #define _ASM_X86_PGTABLE_H
 
 #include <asm/page.h>
+#include <asm/e820.h>
 
 #include <asm/pgtable_types.h>
 
@@ -269,9 +270,16 @@ static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
 
 #define canon_pgprot(p) __pgprot(massage_pgprot(p))
 
-static inline int is_new_memtype_allowed(unsigned long flags,
-                                               unsigned long new_flags)
+static inline int is_new_memtype_allowed(u64 paddr, unsigned long size,
+                                        unsigned long flags,
+                                        unsigned long new_flags)
 {
+       /*
+        * PAT type is always WB for ISA. So no need to check.
+        */
+       if (is_ISA_range(paddr, paddr + size - 1))
+               return 1;
+
        /*
         * Certain new memtypes are not allowed with certain
         * requested memtype:
index 49fb3ecf3bb341208a45935203d121ef60eba4d0..621f56d731212748902e2ba2f3436d84985395e2 100644 (file)
@@ -22,7 +22,14 @@ extern int reboot_force;
 
 long do_arch_prctl(struct task_struct *task, int code, unsigned long addr);
 
-#define round_up(x, y) (((x) + (y) - 1) & ~((y) - 1))
-#define round_down(x, y) ((x) & ~((y) - 1))
+/*
+ * This looks more complex than it should be. But we need to
+ * get the type for the ~ right in round_down (it needs to be
+ * as wide as the result!), and we want to evaluate the macro
+ * arguments just once each.
+ */
+#define __round_mask(x,y) ((__typeof__(x))((y)-1))
+#define round_up(x,y) ((((x)-1) | __round_mask(x,y))+1)
+#define round_down(x,y) ((x) & ~__round_mask(x,y))
 
 #endif /* _ASM_X86_PROTO_H */
index b7e5db8763994cf3164ecf8273f7ec725be9215c..4e77853321dbcca412c52cf35c437bbff2442af8 100644 (file)
@@ -302,4 +302,8 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw)
 #define _raw_read_relax(lock)  cpu_relax()
 #define _raw_write_relax(lock) cpu_relax()
 
+/* The {read|write|spin}_lock() on x86 are full memory barriers. */
+static inline void smp_mb__after_lock(void) { }
+#define ARCH_HAS_SMP_MB_AFTER_LOCK
+
 #endif /* _ASM_X86_SPINLOCK_H */
index f517944b2b176618f51d9791adb9fed4f08864ae..cf86a5e73815dde6fb2e0fa997b8628555584063 100644 (file)
@@ -3,6 +3,8 @@
 
 extern int kstack_depth_to_print;
 
+int x86_is_stack_id(int id, char *name);
+
 /* Generic stack tracer with callbacks */
 
 struct stacktrace_ops {
index b0783520988b8bba544ad79dc38d4ea4580876f6..fad7d40b75f898e8a3651265f573c313a479c4ea 100644 (file)
@@ -49,7 +49,7 @@ struct thread_info {
        .exec_domain    = &default_exec_domain, \
        .flags          = 0,                    \
        .cpu            = 0,                    \
-       .preempt_count  = 1,                    \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .addr_limit     = KERNEL_DS,            \
        .restart_block = {                      \
                .fn = do_no_restart_syscall,    \
index 20e6a795e16006500dc151b8a98315b94b32fa71..d2c6c930b491916843e76d2c6838e53b5890301b 100644 (file)
@@ -212,9 +212,9 @@ extern int __get_user_bad(void);
                     : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")
 #else
 #define __put_user_asm_u64(x, ptr, retval, errret) \
-       __put_user_asm(x, ptr, retval, "q", "", "Zr", errret)
+       __put_user_asm(x, ptr, retval, "q", "", "er", errret)
 #define __put_user_asm_ex_u64(x, addr) \
-       __put_user_asm_ex(x, addr, "q", "", "Zr")
+       __put_user_asm_ex(x, addr, "q", "", "er")
 #define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu)
 #endif
 
index 8cc687326eb80f20726852c9ba66c68837e8176a..db24b215fc50668bcf3f9da0f6757016aab7956e 100644 (file)
@@ -88,11 +88,11 @@ int __copy_to_user(void __user *dst, const void *src, unsigned size)
                              ret, "l", "k", "ir", 4);
                return ret;
        case 8:__put_user_asm(*(u64 *)src, (u64 __user *)dst,
-                             ret, "q", "", "ir", 8);
+                             ret, "q", "", "er", 8);
                return ret;
        case 10:
                __put_user_asm(*(u64 *)src, (u64 __user *)dst,
-                              ret, "q", "", "ir", 10);
+                              ret, "q", "", "er", 10);
                if (unlikely(ret))
                        return ret;
                asm("":::"memory");
@@ -101,12 +101,12 @@ int __copy_to_user(void __user *dst, const void *src, unsigned size)
                return ret;
        case 16:
                __put_user_asm(*(u64 *)src, (u64 __user *)dst,
-                              ret, "q", "", "ir", 16);
+                              ret, "q", "", "er", 16);
                if (unlikely(ret))
                        return ret;
                asm("":::"memory");
                __put_user_asm(1[(u64 *)src], 1 + (u64 __user *)dst,
-                              ret, "q", "", "ir", 8);
+                              ret, "q", "", "er", 8);
                return ret;
        default:
                return copy_user_generic((__force void *)dst, src, size);
@@ -157,7 +157,7 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
                               ret, "q", "", "=r", 8);
                if (likely(!ret))
                        __put_user_asm(tmp, (u64 __user *)dst,
-                                      ret, "q", "", "ir", 8);
+                                      ret, "q", "", "er", 8);
                return ret;
        }
        default:
index bddd44f2f0ab5b3dc7dc0e8ad19fe6df52a0525a..80e2984f521c8e51ab1e863e207c0b4b221491b2 100644 (file)
@@ -133,7 +133,7 @@ struct bau_msg_payload {
  * see table 4.2.3.0.1 in broacast_assist spec.
  */
 struct bau_msg_header {
-       unsigned int dest_subnodeid:6;  /* must be zero */
+       unsigned int dest_subnodeid:6;  /* must be 0x10, for the LB */
        /* bits 5:0 */
        unsigned int base_dest_nodeid:15; /* nasid>>1 (pnode) of */
        /* bits 20:6 */                   /* first bit in node_map */
index 341070f7ad5cb62679f22f7b3fff7316c549b5d9..77a68505419a5e3a8c7a0c2a7ae6f43b34f32541 100644 (file)
@@ -175,7 +175,7 @@ DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info);
 #define UV_GLOBAL_MMR32_PNODE_BITS(p)  ((p) << (UV_GLOBAL_MMR32_PNODE_SHIFT))
 
 #define UV_GLOBAL_MMR64_PNODE_BITS(p)                                  \
-       ((unsigned long)(UV_PNODE_TO_GNODE(p)) << UV_GLOBAL_MMR64_PNODE_SHIFT)
+       (((unsigned long)(p)) << UV_GLOBAL_MMR64_PNODE_SHIFT)
 
 #define UV_APIC_PNODE_SHIFT    6
 
@@ -327,6 +327,7 @@ struct uv_blade_info {
        unsigned short  nr_possible_cpus;
        unsigned short  nr_online_cpus;
        unsigned short  pnode;
+       short           memory_nid;
 };
 extern struct uv_blade_info *uv_blade_info;
 extern short *uv_node_to_blade;
@@ -363,6 +364,12 @@ static inline int uv_blade_to_pnode(int bid)
        return uv_blade_info[bid].pnode;
 }
 
+/* Nid of memory node on blade. -1 if no blade-local memory */
+static inline int uv_blade_to_memory_nid(int bid)
+{
+       return uv_blade_info[bid].memory_nid;
+}
+
 /* Determine the number of possible cpus on a blade */
 static inline int uv_blade_nr_possible_cpus(int bid)
 {
index 6c327b852e23b528963dc4f23e59ffa13761463d..430d5b24af7b210faf695f0c3619a1d66ae8acf5 100644 (file)
@@ -26,6 +26,8 @@ CFLAGS_tsc.o          := $(nostackp)
 CFLAGS_paravirt.o      := $(nostackp)
 GCOV_PROFILE_vsyscall_64.o     := n
 GCOV_PROFILE_hpet.o            := n
+GCOV_PROFILE_tsc.o             := n
+GCOV_PROFILE_paravirt.o                := n
 
 obj-y                  := process_$(BITS).o signal.o entry_$(BITS).o
 obj-y                  += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
index 9372f0406ad4a51d654ce2a1dae5c41f7b3bf48e..6c99f5037801302fc60da447ce414a3179fad3eb 100644 (file)
@@ -1192,7 +1192,7 @@ out:
        return 0;
 }
 
-struct notifier_block device_nb = {
+static struct notifier_block device_nb = {
        .notifier_call = device_change_notifier,
 };
 
@@ -1763,7 +1763,7 @@ static void *alloc_coherent(struct device *dev, size_t size,
        flag |= __GFP_ZERO;
        virt_addr = (void *)__get_free_pages(flag, get_order(size));
        if (!virt_addr)
-               return 0;
+               return NULL;
 
        paddr = virt_to_phys(virt_addr);
 
index 10b2accd12ea5983d917b0646cf445f9c8fe8b93..c1b17e97252e08f89f2221c2228642e0ff3dad81 100644 (file)
@@ -472,6 +472,8 @@ static u8 * __init alloc_event_buffer(struct amd_iommu *iommu)
        if (iommu->evt_buf == NULL)
                return NULL;
 
+       iommu->evt_buf_size = EVT_BUFFER_SIZE;
+
        return iommu->evt_buf;
 }
 
@@ -691,6 +693,7 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
                        devid = e->devid;
                        devid_to = e->ext >> 8;
+                       set_dev_entry_from_acpi(iommu, devid   , e->flags, 0);
                        set_dev_entry_from_acpi(iommu, devid_to, e->flags, 0);
                        amd_iommu_alias_table[devid] = devid_to;
                        break;
@@ -749,11 +752,13 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu,
 
                        devid = e->devid;
                        for (dev_i = devid_start; dev_i <= devid; ++dev_i) {
-                               if (alias)
+                               if (alias) {
                                        amd_iommu_alias_table[dev_i] = devid_to;
-                               set_dev_entry_from_acpi(iommu,
-                                               amd_iommu_alias_table[dev_i],
-                                               flags, ext_flags);
+                                       set_dev_entry_from_acpi(iommu,
+                                               devid_to, flags, ext_flags);
+                               }
+                               set_dev_entry_from_acpi(iommu, dev_i,
+                                                       flags, ext_flags);
                        }
                        break;
                default:
index 8c7c042ecad1eeb406caa0b5fa6605f7d6c7a04a..0a1c2830ec662168a72c1e6780b4f4c8c10075ed 100644 (file)
@@ -140,7 +140,6 @@ int x2apic_mode;
 #ifdef CONFIG_X86_X2APIC
 /* x2apic enabled before OS handover */
 static int x2apic_preenabled;
-static int disable_x2apic;
 static __init int setup_nox2apic(char *str)
 {
        if (x2apic_enabled()) {
@@ -149,7 +148,6 @@ static __init int setup_nox2apic(char *str)
                return 0;
        }
 
-       disable_x2apic = 1;
        setup_clear_cpu_cap(X86_FEATURE_X2APIC);
        return 0;
 }
index 69328ac8de9c86e106d30af1337a80ab0d4488b1..8952a5890281cc363094cc2f67fed1159e6d7674 100644 (file)
@@ -652,7 +652,8 @@ static int es7000_mps_oem_check_cluster(struct mpc_table *mpc, char *oem,
        return ret && es7000_apic_is_cluster();
 }
 
-struct apic apic_es7000_cluster = {
+/* We've been warned by a false positive warning.Use __refdata to keep calm. */
+struct apic __refdata apic_es7000_cluster = {
 
        .name                           = "es7000",
        .probe                          = probe_es7000,
index 4d0216fcb36c4356d4f135fee9c585fac7f42c3a..d2ed6c5ddc80bcb9697079eaa48c79a01b7d48d8 100644 (file)
@@ -1716,25 +1716,19 @@ __apicdebuginit(void) print_IO_APIC(void)
        return;
 }
 
-__apicdebuginit(void) print_APIC_bitfield(int base)
+__apicdebuginit(void) print_APIC_field(int base)
 {
-       unsigned int v;
-       int i, j;
+       int i;
 
        if (apic_verbosity == APIC_QUIET)
                return;
 
-       printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG);
-       for (i = 0; i < 8; i++) {
-               v = apic_read(base + i*0x10);
-               for (j = 0; j < 32; j++) {
-                       if (v & (1<<j))
-                               printk("1");
-                       else
-                               printk("0");
-               }
-               printk("\n");
-       }
+       printk(KERN_DEBUG);
+
+       for (i = 0; i < 8; i++)
+               printk(KERN_CONT "%08x", apic_read(base + i*0x10));
+
+       printk(KERN_CONT "\n");
 }
 
 __apicdebuginit(void) print_local_APIC(void *dummy)
@@ -1745,7 +1739,7 @@ __apicdebuginit(void) print_local_APIC(void *dummy)
        if (apic_verbosity == APIC_QUIET)
                return;
 
-       printk("\n" KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
+       printk(KERN_DEBUG "printing local APIC contents on CPU#%d/%d:\n",
                smp_processor_id(), hard_smp_processor_id());
        v = apic_read(APIC_ID);
        printk(KERN_INFO "... APIC ID:      %08x (%01x)\n", v, read_apic_id());
@@ -1786,11 +1780,11 @@ __apicdebuginit(void) print_local_APIC(void *dummy)
        printk(KERN_DEBUG "... APIC SPIV: %08x\n", v);
 
        printk(KERN_DEBUG "... APIC ISR field:\n");
-       print_APIC_bitfield(APIC_ISR);
+       print_APIC_field(APIC_ISR);
        printk(KERN_DEBUG "... APIC TMR field:\n");
-       print_APIC_bitfield(APIC_TMR);
+       print_APIC_field(APIC_TMR);
        printk(KERN_DEBUG "... APIC IRR field:\n");
-       print_APIC_bitfield(APIC_IRR);
+       print_APIC_field(APIC_IRR);
 
        if (APIC_INTEGRATED(ver)) {             /* !82489DX */
                if (maxlvt > 3)         /* Due to the Pentium erratum 3AP. */
@@ -3799,6 +3793,9 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
        mmr_pnode = uv_blade_to_pnode(mmr_blade);
        uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
 
+       if (cfg->move_in_progress)
+               send_cleanup_vector(cfg);
+
        return irq;
 }
 
@@ -4187,28 +4184,20 @@ fake_ioapic_page:
        }
 }
 
-static int __init ioapic_insert_resources(void)
+void __init ioapic_insert_resources(void)
 {
        int i;
        struct resource *r = ioapic_resources;
 
        if (!r) {
-               if (nr_ioapics > 0) {
+               if (nr_ioapics > 0)
                        printk(KERN_ERR
                                "IO APIC resources couldn't be allocated.\n");
-                       return -1;
-               }
-               return 0;
+               return;
        }
 
        for (i = 0; i < nr_ioapics; i++) {
                insert_resource(&iomem_resource, r);
                r++;
        }
-
-       return 0;
 }
-
-/* Insert the IO APIC resources after PCI initialization has occured to handle
- * IO APICS that are mapped in on a BAR in PCI space. */
-late_initcall(ioapic_insert_resources);
index dbf5445727a9d69d5cd02e07ff7c675c916bb0d9..6ef00ba4c8864c2c0c9b7c6ece3266a15d224404 100644 (file)
@@ -106,6 +106,9 @@ void default_send_IPI_mask_logical(const struct cpumask *cpumask, int vector)
        unsigned long mask = cpumask_bits(cpumask)[0];
        unsigned long flags;
 
+       if (WARN_ONCE(!mask, "empty IPI mask"))
+               return;
+
        local_irq_save(flags);
        WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]);
        __default_send_IPI_dest_field(mask, vector, apic->dest_logical);
index 533e59c6fc823a7bb3813cedb74f921765b5d434..ca96e68f0d23230efb4aa74e3227d9d584d4a237 100644 (file)
@@ -493,7 +493,8 @@ static void numaq_setup_portio_remap(void)
                (u_long) xquad_portio, (u_long) num_quads*XQUAD_PORTIO_QUAD);
 }
 
-struct apic apic_numaq = {
+/* Use __refdata to keep false positive warning calm.  */
+struct apic __refdata apic_numaq = {
 
        .name                           = "NUMAQ",
        .probe                          = probe_numaq,
index bc3e880f9b82e76902b305d10920b70b05c440ac..fcec2f1d34a18ab37c68bbc14865a18174c21488 100644 (file)
@@ -44,6 +44,11 @@ static struct apic *apic_probe[] __initdata = {
        NULL,
 };
 
+static int apicid_phys_pkg_id(int initial_apic_id, int index_msb)
+{
+       return hard_smp_processor_id() >> index_msb;
+}
+
 /*
  * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
  */
@@ -69,6 +74,11 @@ void __init default_setup_apic_routing(void)
                printk(KERN_INFO "Setting APIC routing to %s\n", apic->name);
        }
 
+       if (is_vsmp_box()) {
+               /* need to update phys_pkg_id */
+               apic->phys_pkg_id = apicid_phys_pkg_id;
+       }
+
        /*
         * Now that apic routing model is selected, configure the
         * fault handling for intr remapping.
index 8e4cbb255c38d289f78083828845da5ae43b06ac..a5371ec367769a83b321c23eed6c8d2fde403797 100644 (file)
@@ -17,11 +17,13 @@ static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
        return x2apic_enabled();
 }
 
-/* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
-
+/*
+ * need to use more than cpu 0, because we need more vectors when
+ * MSI-X are used.
+ */
 static const struct cpumask *x2apic_target_cpus(void)
 {
-       return cpumask_of(0);
+       return cpu_online_mask;
 }
 
 /*
@@ -170,7 +172,7 @@ static unsigned long set_apic_id(unsigned int id)
 
 static int x2apic_cluster_phys_pkg_id(int initial_apicid, int index_msb)
 {
-       return current_cpu_data.initial_apicid >> index_msb;
+       return initial_apicid >> index_msb;
 }
 
 static void x2apic_send_IPI_self(int vector)
index a284359627e7fe23ed8a84ab00be47e0a24ae9bf..a8989aadc99a5906fc514bcfa863c728143dd2fb 100644 (file)
@@ -27,11 +27,13 @@ static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
                return 0;
 }
 
-/* Start with all IRQs pointing to boot CPU.  IRQ balancing will shift them. */
-
+/*
+ * need to use more than cpu 0, because we need more vectors when
+ * MSI-X are used.
+ */
 static const struct cpumask *x2apic_target_cpus(void)
 {
-       return cpumask_of(0);
+       return cpu_online_mask;
 }
 
 static void x2apic_vector_allocation_domain(int cpu, struct cpumask *retmask)
@@ -162,7 +164,7 @@ static unsigned long set_apic_id(unsigned int id)
 
 static int x2apic_phys_pkg_id(int initial_apicid, int index_msb)
 {
-       return current_cpu_data.initial_apicid >> index_msb;
+       return initial_apicid >> index_msb;
 }
 
 static void x2apic_send_IPI_self(int vector)
index 096d19aea2f7180b40be33870a0225ac822f71d3..601159374e8798b6d09d8c1a6d04fd2752cdaacb 100644 (file)
@@ -46,7 +46,7 @@ static int early_get_nodeid(void)
        return node_id.s.node_id;
 }
 
-static int uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 {
        if (!strcmp(oem_id, "SGI")) {
                if (!strcmp(oem_table_id, "UVL"))
@@ -253,7 +253,7 @@ static void uv_send_IPI_self(int vector)
        apic_write(APIC_SELF_IPI, vector);
 }
 
-struct apic apic_x2apic_uv_x = {
+struct apic __refdata apic_x2apic_uv_x = {
 
        .name                           = "UV large system",
        .probe                          = NULL,
@@ -261,7 +261,7 @@ struct apic apic_x2apic_uv_x = {
        .apic_id_registered             = uv_apic_id_registered,
 
        .irq_delivery_mode              = dest_Fixed,
-       .irq_dest_mode                  = 1, /* logical */
+       .irq_dest_mode                  = 0, /* physical */
 
        .target_cpus                    = uv_target_cpus,
        .disable_esr                    = 0,
@@ -362,12 +362,6 @@ static __init void get_lowmem_redirect(unsigned long *base, unsigned long *size)
        BUG();
 }
 
-static __init void map_low_mmrs(void)
-{
-       init_extra_mapping_uc(UV_GLOBAL_MMR32_BASE, UV_GLOBAL_MMR32_SIZE);
-       init_extra_mapping_uc(UV_LOCAL_MMR_BASE, UV_LOCAL_MMR_SIZE);
-}
-
 enum map_type {map_wb, map_uc};
 
 static __init void map_high(char *id, unsigned long base, int shift,
@@ -395,26 +389,6 @@ static __init void map_gru_high(int max_pnode)
                map_high("GRU", gru.s.base, shift, max_pnode, map_wb);
 }
 
-static __init void map_config_high(int max_pnode)
-{
-       union uvh_rh_gam_cfg_overlay_config_mmr_u cfg;
-       int shift = UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR_BASE_SHFT;
-
-       cfg.v = uv_read_local_mmr(UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR);
-       if (cfg.s.enable)
-               map_high("CONFIG", cfg.s.base, shift, max_pnode, map_uc);
-}
-
-static __init void map_mmr_high(int max_pnode)
-{
-       union uvh_rh_gam_mmr_overlay_config_mmr_u mmr;
-       int shift = UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT;
-
-       mmr.v = uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR);
-       if (mmr.s.enable)
-               map_high("MMR", mmr.s.base, shift, max_pnode, map_uc);
-}
-
 static __init void map_mmioh_high(int max_pnode)
 {
        union uvh_rh_gam_mmioh_overlay_config_mmr_u mmioh;
@@ -566,8 +540,6 @@ void __init uv_system_init(void)
        unsigned long mmr_base, present, paddr;
        unsigned short pnode_mask;
 
-       map_low_mmrs();
-
        m_n_config.v = uv_read_local_mmr(UVH_SI_ADDR_MAP_CONFIG);
        m_val = m_n_config.s.m_skt;
        n_val = m_n_config.s.n_skt;
@@ -591,6 +563,8 @@ void __init uv_system_init(void)
        bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
        uv_blade_info = kmalloc(bytes, GFP_KERNEL);
        BUG_ON(!uv_blade_info);
+       for (blade = 0; blade < uv_num_possible_blades(); blade++)
+               uv_blade_info[blade].memory_nid = -1;
 
        get_lowmem_redirect(&lowmem_redir_base, &lowmem_redir_size);
 
@@ -629,6 +603,9 @@ void __init uv_system_init(void)
                lcpu = uv_blade_info[blade].nr_possible_cpus;
                uv_blade_info[blade].nr_possible_cpus++;
 
+               /* Any node on the blade, else will contain -1. */
+               uv_blade_info[blade].memory_nid = nid;
+
                uv_cpu_hub_info(cpu)->lowmem_remap_base = lowmem_redir_base;
                uv_cpu_hub_info(cpu)->lowmem_remap_top = lowmem_redir_size;
                uv_cpu_hub_info(cpu)->m_val = m_val;
@@ -662,11 +639,10 @@ void __init uv_system_init(void)
                pnode = (paddr >> m_val) & pnode_mask;
                blade = boot_pnode_to_blade(pnode);
                uv_node_to_blade[nid] = blade;
+               max_pnode = max(pnode, max_pnode);
        }
 
        map_gru_high(max_pnode);
-       map_mmr_high(max_pnode);
-       map_config_high(max_pnode);
        map_mmioh_high(max_pnode);
 
        uv_cpu_init();
index 79302e9a33a43322eea70cc2f69f019426b69847..442b5508893f35b185d0cbd8056d03f8b8aa70c0 100644 (file)
@@ -811,7 +811,7 @@ static int apm_do_idle(void)
        u8 ret = 0;
        int idled = 0;
        int polling;
-       int err;
+       int err = 0;
 
        polling = !!(current_thread_info()->status & TS_POLLING);
        if (polling) {
index 3efcb2b96a150e361f9a1f66ccbfaef692b98432..c1f253dac1552f63c0795a31ce5977b681b98592 100644 (file)
@@ -7,6 +7,10 @@ ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_common.o = -pg
 endif
 
+# Make sure load_percpu_segment has no stackprotector
+nostackp := $(call cc-option, -fno-stack-protector)
+CFLAGS_common.o                := $(nostackp)
+
 obj-y                  := intel_cacheinfo.o addon_cpuid_features.o
 obj-y                  += proc.o capflags.o powerflags.o common.o
 obj-y                  += vmware.o hypervisor.o
index e5b27d8f1b47395fda285d867b776e82454ae61a..63fddcd082cdf2a3b4cc261d54608ec2dac07b64 100644 (file)
@@ -258,13 +258,15 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_X86_HT
        unsigned bits;
+       int cpu = smp_processor_id();
 
        bits = c->x86_coreid_bits;
-
        /* Low order bits define the core id (index of core in socket) */
        c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
        /* Convert the initial APIC ID into the socket ID */
        c->phys_proc_id = c->initial_apicid >> bits;
+       /* use socket ID also for last level cache */
+       per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
 #endif
 }
 
@@ -354,7 +356,7 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c)
 #endif
 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI)
        /* check CPU config space for extended APIC ID */
-       if (c->x86 >= 0xf) {
+       if (cpu_has_apic && c->x86 >= 0xf) {
                unsigned int val;
                val = read_pci_config(0, 24, 0, 0x68);
                if ((val & ((1 << 17) | (1 << 18))) == ((1 << 17) | (1 << 18)))
@@ -398,6 +400,13 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
                level = cpuid_eax(1);
                if((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58)
                        set_cpu_cap(c, X86_FEATURE_REP_GOOD);
+
+               /*
+                * Some BIOSes incorrectly force this feature, but only K8
+                * revision D (model = 0x14) and later actually support it.
+                */
+               if (c->x86_model < 0x14)
+                       clear_cpu_cap(c, X86_FEATURE_LAHF_LM);
        }
        if (c->x86 == 0x10 || c->x86 == 0x11)
                set_cpu_cap(c, X86_FEATURE_REP_GOOD);
index 6b26d4deada0ce19917e393badd4e8e785259df7..5ce60a88027b16a46edf3b1afb3430d550cd5012 100644 (file)
@@ -59,7 +59,30 @@ void __init setup_cpu_local_masks(void)
        alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask);
 }
 
-static const struct cpu_dev *this_cpu __cpuinitdata;
+static void __cpuinit default_init(struct cpuinfo_x86 *c)
+{
+#ifdef CONFIG_X86_64
+       display_cacheinfo(c);
+#else
+       /* Not much we can do here... */
+       /* Check if at least it has cpuid */
+       if (c->cpuid_level == -1) {
+               /* No cpuid. It must be an ancient CPU */
+               if (c->x86 == 4)
+                       strcpy(c->x86_model_id, "486");
+               else if (c->x86 == 3)
+                       strcpy(c->x86_model_id, "386");
+       }
+#endif
+}
+
+static const struct cpu_dev __cpuinitconst default_cpu = {
+       .c_init         = default_init,
+       .c_vendor       = "Unknown",
+       .c_x86_vendor   = X86_VENDOR_UNKNOWN,
+};
+
+static const struct cpu_dev *this_cpu __cpuinitdata = &default_cpu;
 
 DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
 #ifdef CONFIG_X86_64
@@ -332,29 +355,6 @@ void switch_to_new_gdt(int cpu)
 
 static const struct cpu_dev *__cpuinitdata cpu_devs[X86_VENDOR_NUM] = {};
 
-static void __cpuinit default_init(struct cpuinfo_x86 *c)
-{
-#ifdef CONFIG_X86_64
-       display_cacheinfo(c);
-#else
-       /* Not much we can do here... */
-       /* Check if at least it has cpuid */
-       if (c->cpuid_level == -1) {
-               /* No cpuid. It must be an ancient CPU */
-               if (c->x86 == 4)
-                       strcpy(c->x86_model_id, "486");
-               else if (c->x86 == 3)
-                       strcpy(c->x86_model_id, "386");
-       }
-#endif
-}
-
-static const struct cpu_dev __cpuinitconst default_cpu = {
-       .c_init = default_init,
-       .c_vendor = "Unknown",
-       .c_x86_vendor = X86_VENDOR_UNKNOWN,
-};
-
 static void __cpuinit get_model_name(struct cpuinfo_x86 *c)
 {
        unsigned int *v;
@@ -848,9 +848,6 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
 #if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
        numa_add_cpu(smp_processor_id());
 #endif
-
-       /* Cap the iomem address space to what is addressable on all CPUs */
-       iomem_resource.end &= (1ULL << c->x86_phys_bits) - 1;
 }
 
 #ifdef CONFIG_X86_64
index 81cbe64ed6b49a79e8e3aa8b339a6a8b4cf2d202..2a50ef891000f3c114374c1a28bdbf4f26a36d67 100644 (file)
@@ -299,7 +299,7 @@ static int transition_pstate(struct powernow_k8_data *data, u32 pstate)
 static int transition_fid_vid(struct powernow_k8_data *data,
                u32 reqfid, u32 reqvid)
 {
-       if (core_voltage_pre_transition(data, reqvid))
+       if (core_voltage_pre_transition(data, reqvid, reqfid))
                return 1;
 
        if (core_frequency_transition(data, reqfid))
@@ -327,17 +327,20 @@ static int transition_fid_vid(struct powernow_k8_data *data,
 
 /* Phase 1 - core voltage transition ... setup voltage */
 static int core_voltage_pre_transition(struct powernow_k8_data *data,
-               u32 reqvid)
+               u32 reqvid, u32 reqfid)
 {
        u32 rvosteps = data->rvo;
        u32 savefid = data->currfid;
-       u32 maxvid, lo;
+       u32 maxvid, lo, rvomult = 1;
 
        dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, "
                "reqvid 0x%x, rvo 0x%x\n",
                smp_processor_id(),
                data->currfid, data->currvid, reqvid, data->rvo);
 
+       if ((savefid < LO_FID_TABLE_TOP) && (reqfid < LO_FID_TABLE_TOP))
+               rvomult = 2;
+       rvosteps *= rvomult;
        rdmsr(MSR_FIDVID_STATUS, lo, maxvid);
        maxvid = 0x1f & (maxvid >> 16);
        dprintk("ph1 maxvid=0x%x\n", maxvid);
@@ -351,7 +354,8 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data,
                        return 1;
        }
 
-       while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
+       while ((rvosteps > 0) &&
+                       ((rvomult * data->rvo + data->currvid) > reqvid)) {
                if (data->currvid == maxvid) {
                        rvosteps = 0;
                } else {
@@ -384,13 +388,6 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
        u32 vcoreqfid, vcocurrfid, vcofiddiff;
        u32 fid_interval, savevid = data->currvid;
 
-       if ((reqfid < HI_FID_TABLE_BOTTOM) &&
-           (data->currfid < HI_FID_TABLE_BOTTOM)) {
-               printk(KERN_ERR PFX "ph2: illegal lo-lo transition "
-                               "0x%x 0x%x\n", reqfid, data->currfid);
-               return 1;
-       }
-
        if (data->currfid == reqfid) {
                printk(KERN_ERR PFX "ph2 null fid transition 0x%x\n",
                                data->currfid);
@@ -407,6 +404,9 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
        vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid
            : vcoreqfid - vcocurrfid;
 
+       if ((reqfid <= LO_FID_TABLE_TOP) && (data->currfid <= LO_FID_TABLE_TOP))
+               vcofiddiff = 0;
+
        while (vcofiddiff > 2) {
                (data->currfid & 1) ? (fid_interval = 1) : (fid_interval = 2);
 
@@ -1081,14 +1081,6 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
                return 0;
        }
 
-       if ((fid < HI_FID_TABLE_BOTTOM) &&
-           (data->currfid < HI_FID_TABLE_BOTTOM)) {
-               printk(KERN_ERR PFX
-                      "ignoring illegal change in lo freq table-%x to 0x%x\n",
-                      data->currfid, fid);
-               return 1;
-       }
-
        dprintk("cpu %d, changing to fid 0x%x, vid 0x%x\n",
                smp_processor_id(), fid, vid);
        freqs.old = find_khz_freq_from_fid(data->currfid);
@@ -1267,7 +1259,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 {
        static const char ACPI_PSS_BIOS_BUG_MSG[] =
                KERN_ERR FW_BUG PFX "No compatible ACPI _PSS objects found.\n"
-               KERN_ERR FW_BUG PFX "Try again with latest BIOS.\n";
+               FW_BUG PFX "Try again with latest BIOS.\n";
        struct powernow_k8_data *data;
        struct init_on_cpu init_on_cpu;
        int rc;
index c9c1190b5e1f057fb30652132225443c2ba2da58..02ce824073cb9463e33e0fb5a32d7f7e60814b2f 100644 (file)
@@ -215,7 +215,8 @@ struct pst_s {
 
 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "powernow-k8", msg)
 
-static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid);
+static int core_voltage_pre_transition(struct powernow_k8_data *data,
+       u32 reqvid, u32 regfid);
 static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvid);
 static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid);
 
index 284d1de968bc3e1f2867eb2f3ca8cedf9338e1f6..01213048f62f9a1a7e8a58926337c25c67b2711f 100644 (file)
@@ -194,14 +194,14 @@ static void print_mce(struct mce *m)
                       m->cs, m->ip);
                if (m->cs == __KERNEL_CS)
                        print_symbol("{%s}", m->ip);
-               printk("\n");
+               printk(KERN_CONT "\n");
        }
        printk(KERN_EMERG "TSC %llx ", m->tsc);
        if (m->addr)
-               printk("ADDR %llx ", m->addr);
+               printk(KERN_CONT "ADDR %llx ", m->addr);
        if (m->misc)
-               printk("MISC %llx ", m->misc);
-       printk("\n");
+               printk(KERN_CONT "MISC %llx ", m->misc);
+       printk(KERN_CONT "\n");
        printk(KERN_EMERG "PROCESSOR %u:%x TIME %llu SOCKET %u APIC %x\n",
                        m->cpuvendor, m->cpuid, m->time, m->socketid,
                        m->apicid);
@@ -209,13 +209,13 @@ static void print_mce(struct mce *m)
 
 static void print_mce_head(void)
 {
-       printk(KERN_EMERG "\n" KERN_EMERG "HARDWARE ERROR\n");
+       printk(KERN_EMERG "\nHARDWARE ERROR\n");
 }
 
 static void print_mce_tail(void)
 {
        printk(KERN_EMERG "This is not a software problem!\n"
-              KERN_EMERG "Run through mcelog --ascii to decode and contact your hardware vendor\n");
+              "Run through mcelog --ascii to decode and contact your hardware vendor\n");
 }
 
 #define PANIC_TIMEOUT 5 /* 5 seconds */
@@ -1117,7 +1117,7 @@ static void mcheck_timer(unsigned long data)
                *n = min(*n*2, (int)round_jiffies_relative(check_interval*HZ));
 
        t->expires = jiffies + *n;
-       add_timer(t);
+       add_timer_on(t, smp_processor_id());
 }
 
 static void mce_do_trigger(struct work_struct *work)
@@ -1226,8 +1226,13 @@ static void mce_init(void)
 }
 
 /* Add per CPU specific workarounds here */
-static void mce_cpu_quirks(struct cpuinfo_x86 *c)
+static int mce_cpu_quirks(struct cpuinfo_x86 *c)
 {
+       if (c->x86_vendor == X86_VENDOR_UNKNOWN) {
+               pr_info("MCE: unknown CPU type - not enabling MCE support.\n");
+               return -EOPNOTSUPP;
+       }
+
        /* This should be disabled by the BIOS, but isn't always */
        if (c->x86_vendor == X86_VENDOR_AMD) {
                if (c->x86 == 15 && banks > 4) {
@@ -1273,11 +1278,20 @@ static void mce_cpu_quirks(struct cpuinfo_x86 *c)
                if ((c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xe)) &&
                        monarch_timeout < 0)
                        monarch_timeout = USEC_PER_SEC;
+
+               /*
+                * There are also broken BIOSes on some Pentium M and
+                * earlier systems:
+                */
+               if (c->x86 == 6 && c->x86_model <= 13 && mce_bootlog < 0)
+                       mce_bootlog = 0;
        }
        if (monarch_timeout < 0)
                monarch_timeout = 0;
        if (mce_bootlog != 0)
                mce_panic_timeout = 30;
+
+       return 0;
 }
 
 static void __cpuinit mce_ancient_init(struct cpuinfo_x86 *c)
@@ -1321,7 +1335,7 @@ static void mce_init_timer(void)
                return;
        setup_timer(t, mcheck_timer, smp_processor_id());
        t->expires = round_jiffies(jiffies + *n);
-       add_timer(t);
+       add_timer_on(t, smp_processor_id());
 }
 
 /*
@@ -1338,11 +1352,10 @@ void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
        if (!mce_available(c))
                return;
 
-       if (mce_cap_init() < 0) {
+       if (mce_cap_init() < 0 || mce_cpu_quirks(c) < 0) {
                mce_disabled = 1;
                return;
        }
-       mce_cpu_quirks(c);
 
        machine_check_vector = do_machine_check;
 
@@ -1692,17 +1705,15 @@ static ssize_t set_trigger(struct sys_device *s, struct sysdev_attribute *attr,
                                const char *buf, size_t siz)
 {
        char *p;
-       int len;
 
        strncpy(mce_helper, buf, sizeof(mce_helper));
        mce_helper[sizeof(mce_helper)-1] = 0;
-       len = strlen(mce_helper);
        p = strchr(mce_helper, '\n');
 
-       if (*p)
+       if (p)
                *p = 0;
 
-       return len;
+       return strlen(mce_helper) + !!p;
 }
 
 static ssize_t set_ignore_ce(struct sys_device *s,
index bff8dd191dd5c9ae5f3235ad22a6239bf8e8de74..5957a93e5173f2e1e985b1a149a01f5905bb03db 100644 (file)
@@ -36,6 +36,7 @@
 
 static DEFINE_PER_CPU(__u64, next_check) = INITIAL_JIFFIES;
 static DEFINE_PER_CPU(unsigned long, thermal_throttle_count);
+static DEFINE_PER_CPU(bool, thermal_throttle_active);
 
 static atomic_t therm_throt_en         = ATOMIC_INIT(0);
 
@@ -96,27 +97,33 @@ static int therm_throt_process(int curr)
 {
        unsigned int cpu = smp_processor_id();
        __u64 tmp_jiffs = get_jiffies_64();
+       bool was_throttled = __get_cpu_var(thermal_throttle_active);
+       bool is_throttled = __get_cpu_var(thermal_throttle_active) = curr;
 
-       if (curr)
+       if (is_throttled)
                __get_cpu_var(thermal_throttle_count)++;
 
-       if (time_before64(tmp_jiffs, __get_cpu_var(next_check)))
+       if (!(was_throttled ^ is_throttled) &&
+           time_before64(tmp_jiffs, __get_cpu_var(next_check)))
                return 0;
 
        __get_cpu_var(next_check) = tmp_jiffs + CHECK_INTERVAL;
 
        /* if we just entered the thermal event */
-       if (curr) {
+       if (is_throttled) {
                printk(KERN_CRIT "CPU%d: Temperature above threshold, "
-                      "cpu clock throttled (total events = %lu)\n", cpu,
-                      __get_cpu_var(thermal_throttle_count));
+                      "cpu clock throttled (total events = %lu)\n",
+                      cpu, __get_cpu_var(thermal_throttle_count));
 
                add_taint(TAINT_MACHINE_CHECK);
-       } else {
-               printk(KERN_CRIT "CPU%d: Temperature/speed normal\n", cpu);
+               return 1;
+       }
+       if (was_throttled) {
+               printk(KERN_INFO "CPU%d: Temperature/speed normal\n", cpu);
+               return 1;
        }
 
-       return 1;
+       return 0;
 }
 
 #ifdef CONFIG_SYSFS
index 76dfef23f78957aa4e17d3337d5dc5221bd18ade..900332b800f870d9f3f9e03bf2c5fa12505bc914 100644 (file)
@@ -55,6 +55,7 @@ struct x86_pmu {
        int             num_counters_fixed;
        int             counter_bits;
        u64             counter_mask;
+       int             apic;
        u64             max_period;
        u64             intel_ctrl;
 };
@@ -65,6 +66,52 @@ static DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters) = {
        .enabled = 1,
 };
 
+/*
+ * Not sure about some of these
+ */
+static const u64 p6_perfmon_event_map[] =
+{
+  [PERF_COUNT_HW_CPU_CYCLES]           = 0x0079,
+  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,
+  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0f2e,
+  [PERF_COUNT_HW_CACHE_MISSES]         = 0x012e,
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,
+  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,
+  [PERF_COUNT_HW_BUS_CYCLES]           = 0x0062,
+};
+
+static u64 p6_pmu_event_map(int event)
+{
+       return p6_perfmon_event_map[event];
+}
+
+/*
+ * Counter setting that is specified not to count anything.
+ * We use this to effectively disable a counter.
+ *
+ * L2_RQSTS with 0 MESI unit mask.
+ */
+#define P6_NOP_COUNTER                 0x0000002EULL
+
+static u64 p6_pmu_raw_event(u64 event)
+{
+#define P6_EVNTSEL_EVENT_MASK          0x000000FFULL
+#define P6_EVNTSEL_UNIT_MASK           0x0000FF00ULL
+#define P6_EVNTSEL_EDGE_MASK           0x00040000ULL
+#define P6_EVNTSEL_INV_MASK            0x00800000ULL
+#define P6_EVNTSEL_COUNTER_MASK                0xFF000000ULL
+
+#define P6_EVNTSEL_MASK                        \
+       (P6_EVNTSEL_EVENT_MASK |        \
+        P6_EVNTSEL_UNIT_MASK  |        \
+        P6_EVNTSEL_EDGE_MASK  |        \
+        P6_EVNTSEL_INV_MASK   |        \
+        P6_EVNTSEL_COUNTER_MASK)
+
+       return event & P6_EVNTSEL_MASK;
+}
+
+
 /*
  * Intel PerfMon v3. Used on Core2 and later.
  */
@@ -401,7 +448,7 @@ static const u64 amd_hw_cache_event_ids
                [ C(RESULT_MISS)   ] = 0x0041, /* Data Cache Misses          */
        },
        [ C(OP_WRITE) ] = {
-               [ C(RESULT_ACCESS) ] = 0x0042, /* Data Cache Refills from L2 */
+               [ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */
                [ C(RESULT_MISS)   ] = 0,
        },
        [ C(OP_PREFETCH) ] = {
@@ -567,6 +614,7 @@ static DEFINE_MUTEX(pmc_reserve_mutex);
 
 static bool reserve_pmc_hardware(void)
 {
+#ifdef CONFIG_X86_LOCAL_APIC
        int i;
 
        if (nmi_watchdog == NMI_LOCAL_APIC)
@@ -581,9 +629,11 @@ static bool reserve_pmc_hardware(void)
                if (!reserve_evntsel_nmi(x86_pmu.eventsel + i))
                        goto eventsel_fail;
        }
+#endif
 
        return true;
 
+#ifdef CONFIG_X86_LOCAL_APIC
 eventsel_fail:
        for (i--; i >= 0; i--)
                release_evntsel_nmi(x86_pmu.eventsel + i);
@@ -598,10 +648,12 @@ perfctr_fail:
                enable_lapic_nmi_watchdog();
 
        return false;
+#endif
 }
 
 static void release_pmc_hardware(void)
 {
+#ifdef CONFIG_X86_LOCAL_APIC
        int i;
 
        for (i = 0; i < x86_pmu.num_counters; i++) {
@@ -611,6 +663,7 @@ static void release_pmc_hardware(void)
 
        if (nmi_watchdog == NMI_LOCAL_APIC)
                enable_lapic_nmi_watchdog();
+#endif
 }
 
 static void hw_perf_counter_destroy(struct perf_counter *counter)
@@ -666,6 +719,7 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
 {
        struct perf_counter_attr *attr = &counter->attr;
        struct hw_perf_counter *hwc = &counter->hw;
+       u64 config;
        int err;
 
        if (!x86_pmu_initialized())
@@ -701,6 +755,15 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
                hwc->sample_period = x86_pmu.max_period;
                hwc->last_period = hwc->sample_period;
                atomic64_set(&hwc->period_left, hwc->sample_period);
+       } else {
+               /*
+                * If we have a PMU initialized but no APIC
+                * interrupts, we cannot sample hardware
+                * counters (user-space has to fall back and
+                * sample via a hrtimer based software counter):
+                */
+               if (!x86_pmu.apic)
+                       return -EOPNOTSUPP;
        }
 
        counter->destroy = hw_perf_counter_destroy;
@@ -718,14 +781,40 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
 
        if (attr->config >= x86_pmu.max_events)
                return -EINVAL;
+
        /*
         * The generic map:
         */
-       hwc->config |= x86_pmu.event_map(attr->config);
+       config = x86_pmu.event_map(attr->config);
+
+       if (config == 0)
+               return -ENOENT;
+
+       if (config == -1LL)
+               return -EINVAL;
+
+       hwc->config |= config;
 
        return 0;
 }
 
+static void p6_pmu_disable_all(void)
+{
+       struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+       u64 val;
+
+       if (!cpuc->enabled)
+               return;
+
+       cpuc->enabled = 0;
+       barrier();
+
+       /* p6 only has one enable register */
+       rdmsrl(MSR_P6_EVNTSEL0, val);
+       val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
+       wrmsrl(MSR_P6_EVNTSEL0, val);
+}
+
 static void intel_pmu_disable_all(void)
 {
        wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
@@ -767,6 +856,23 @@ void hw_perf_disable(void)
        return x86_pmu.disable_all();
 }
 
+static void p6_pmu_enable_all(void)
+{
+       struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+       unsigned long val;
+
+       if (cpuc->enabled)
+               return;
+
+       cpuc->enabled = 1;
+       barrier();
+
+       /* p6 only has one enable register */
+       rdmsrl(MSR_P6_EVNTSEL0, val);
+       val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+       wrmsrl(MSR_P6_EVNTSEL0, val);
+}
+
 static void intel_pmu_enable_all(void)
 {
        wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl);
@@ -784,13 +890,13 @@ static void amd_pmu_enable_all(void)
        barrier();
 
        for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               struct perf_counter *counter = cpuc->counters[idx];
                u64 val;
 
                if (!test_bit(idx, cpuc->active_mask))
                        continue;
-               rdmsrl(MSR_K7_EVNTSEL0 + idx, val);
-               if (val & ARCH_PERFMON_EVENTSEL0_ENABLE)
-                       continue;
+
+               val = counter->hw.config;
                val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
                wrmsrl(MSR_K7_EVNTSEL0 + idx, val);
        }
@@ -819,16 +925,13 @@ static inline void intel_pmu_ack_status(u64 ack)
 
 static inline void x86_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
 {
-       int err;
-       err = checking_wrmsrl(hwc->config_base + idx,
+       (void)checking_wrmsrl(hwc->config_base + idx,
                              hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE);
 }
 
 static inline void x86_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
 {
-       int err;
-       err = checking_wrmsrl(hwc->config_base + idx,
-                             hwc->config);
+       (void)checking_wrmsrl(hwc->config_base + idx, hwc->config);
 }
 
 static inline void
@@ -836,13 +939,24 @@ intel_pmu_disable_fixed(struct hw_perf_counter *hwc, int __idx)
 {
        int idx = __idx - X86_PMC_IDX_FIXED;
        u64 ctrl_val, mask;
-       int err;
 
        mask = 0xfULL << (idx * 4);
 
        rdmsrl(hwc->config_base, ctrl_val);
        ctrl_val &= ~mask;
-       err = checking_wrmsrl(hwc->config_base, ctrl_val);
+       (void)checking_wrmsrl(hwc->config_base, ctrl_val);
+}
+
+static inline void
+p6_pmu_disable_counter(struct hw_perf_counter *hwc, int idx)
+{
+       struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+       u64 val = P6_NOP_COUNTER;
+
+       if (cpuc->enabled)
+               val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+
+       (void)checking_wrmsrl(hwc->config_base + idx, val);
 }
 
 static inline void
@@ -912,6 +1026,8 @@ x86_perf_counter_set_period(struct perf_counter *counter,
        err = checking_wrmsrl(hwc->counter_base + idx,
                             (u64)(-left) & x86_pmu.counter_mask);
 
+       perf_counter_update_userpage(counter);
+
        return ret;
 }
 
@@ -941,6 +1057,19 @@ intel_pmu_enable_fixed(struct hw_perf_counter *hwc, int __idx)
        err = checking_wrmsrl(hwc->config_base, ctrl_val);
 }
 
+static void p6_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
+{
+       struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters);
+       u64 val;
+
+       val = hwc->config;
+       if (cpuc->enabled)
+               val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+
+       (void)checking_wrmsrl(hwc->config_base + idx, val);
+}
+
+
 static void intel_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
 {
        if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
@@ -957,8 +1086,6 @@ static void amd_pmu_enable_counter(struct hw_perf_counter *hwc, int idx)
 
        if (cpuc->enabled)
                x86_pmu_enable_counter(hwc, idx);
-       else
-               x86_pmu_disable_counter(hwc, idx);
 }
 
 static int
@@ -969,13 +1096,6 @@ fixed_mode_idx(struct perf_counter *counter, struct hw_perf_counter *hwc)
        if (!x86_pmu.num_counters_fixed)
                return -1;
 
-       /*
-        * Quirk, IA32_FIXED_CTRs do not work on current Atom processors:
-        */
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
-                                       boot_cpu_data.x86_model == 28)
-               return -1;
-
        event = hwc->config & ARCH_PERFMON_EVENT_MASK;
 
        if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS)))
@@ -1041,6 +1161,8 @@ try_generic:
        x86_perf_counter_set_period(counter, hwc, idx);
        x86_pmu.enable(hwc, idx);
 
+       perf_counter_update_userpage(counter);
+
        return 0;
 }
 
@@ -1133,6 +1255,8 @@ static void x86_pmu_disable(struct perf_counter *counter)
        x86_perf_counter_update(counter, hwc, idx);
        cpuc->counters[idx] = NULL;
        clear_bit(idx, cpuc->used_mask);
+
+       perf_counter_update_userpage(counter);
 }
 
 /*
@@ -1177,6 +1301,49 @@ static void intel_pmu_reset(void)
        local_irq_restore(flags);
 }
 
+static int p6_pmu_handle_irq(struct pt_regs *regs)
+{
+       struct perf_sample_data data;
+       struct cpu_hw_counters *cpuc;
+       struct perf_counter *counter;
+       struct hw_perf_counter *hwc;
+       int idx, handled = 0;
+       u64 val;
+
+       data.regs = regs;
+       data.addr = 0;
+
+       cpuc = &__get_cpu_var(cpu_hw_counters);
+
+       for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+               if (!test_bit(idx, cpuc->active_mask))
+                       continue;
+
+               counter = cpuc->counters[idx];
+               hwc = &counter->hw;
+
+               val = x86_perf_counter_update(counter, hwc, idx);
+               if (val & (1ULL << (x86_pmu.counter_bits - 1)))
+                       continue;
+
+               /*
+                * counter overflow
+                */
+               handled         = 1;
+               data.period     = counter->hw.last_period;
+
+               if (!x86_perf_counter_set_period(counter, hwc, idx))
+                       continue;
+
+               if (perf_counter_overflow(counter, 1, &data))
+                       p6_pmu_disable_counter(hwc, idx);
+       }
+
+       if (handled)
+               inc_irq_stat(apic_perf_irqs);
+
+       return handled;
+}
 
 /*
  * This handler is triggered by the local APIC, so the APIC IRQ handling
@@ -1186,14 +1353,13 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
 {
        struct perf_sample_data data;
        struct cpu_hw_counters *cpuc;
-       int bit, cpu, loops;
+       int bit, loops;
        u64 ack, status;
 
        data.regs = regs;
        data.addr = 0;
 
-       cpu = smp_processor_id();
-       cpuc = &per_cpu(cpu_hw_counters, cpu);
+       cpuc = &__get_cpu_var(cpu_hw_counters);
 
        perf_disable();
        status = intel_pmu_get_status();
@@ -1250,14 +1416,13 @@ static int amd_pmu_handle_irq(struct pt_regs *regs)
        struct cpu_hw_counters *cpuc;
        struct perf_counter *counter;
        struct hw_perf_counter *hwc;
-       int cpu, idx, handled = 0;
+       int idx, handled = 0;
        u64 val;
 
        data.regs = regs;
        data.addr = 0;
 
-       cpu = smp_processor_id();
-       cpuc = &per_cpu(cpu_hw_counters, cpu);
+       cpuc = &__get_cpu_var(cpu_hw_counters);
 
        for (idx = 0; idx < x86_pmu.num_counters; idx++) {
                if (!test_bit(idx, cpuc->active_mask))
@@ -1300,18 +1465,22 @@ void smp_perf_pending_interrupt(struct pt_regs *regs)
 
 void set_perf_counter_pending(void)
 {
+#ifdef CONFIG_X86_LOCAL_APIC
        apic->send_IPI_self(LOCAL_PENDING_VECTOR);
+#endif
 }
 
 void perf_counters_lapic_init(void)
 {
-       if (!x86_pmu_initialized())
+#ifdef CONFIG_X86_LOCAL_APIC
+       if (!x86_pmu.apic || !x86_pmu_initialized())
                return;
 
        /*
         * Always use NMI for PMU
         */
        apic_write(APIC_LVTPC, APIC_DM_NMI);
+#endif
 }
 
 static int __kprobes
@@ -1335,7 +1504,9 @@ perf_counter_nmi_handler(struct notifier_block *self,
 
        regs = args->regs;
 
+#ifdef CONFIG_X86_LOCAL_APIC
        apic_write(APIC_LVTPC, APIC_DM_NMI);
+#endif
        /*
         * Can't rely on the handled return value to say it was our NMI, two
         * counters could trigger 'simultaneously' raising two back-to-back NMIs.
@@ -1354,6 +1525,33 @@ static __read_mostly struct notifier_block perf_counter_nmi_notifier = {
        .priority               = 1
 };
 
+static struct x86_pmu p6_pmu = {
+       .name                   = "p6",
+       .handle_irq             = p6_pmu_handle_irq,
+       .disable_all            = p6_pmu_disable_all,
+       .enable_all             = p6_pmu_enable_all,
+       .enable                 = p6_pmu_enable_counter,
+       .disable                = p6_pmu_disable_counter,
+       .eventsel               = MSR_P6_EVNTSEL0,
+       .perfctr                = MSR_P6_PERFCTR0,
+       .event_map              = p6_pmu_event_map,
+       .raw_event              = p6_pmu_raw_event,
+       .max_events             = ARRAY_SIZE(p6_perfmon_event_map),
+       .apic                   = 1,
+       .max_period             = (1ULL << 31) - 1,
+       .version                = 0,
+       .num_counters           = 2,
+       /*
+        * Counters have 40 bits implemented. However they are designed such
+        * that bits [32-39] are sign extensions of bit 31. As such the
+        * effective width of a counter for P6-like PMU is 32 bits only.
+        *
+        * See IA-32 Intel Architecture Software developer manual Vol 3B
+        */
+       .counter_bits           = 32,
+       .counter_mask           = (1ULL << 32) - 1,
+};
+
 static struct x86_pmu intel_pmu = {
        .name                   = "Intel",
        .handle_irq             = intel_pmu_handle_irq,
@@ -1366,6 +1564,7 @@ static struct x86_pmu intel_pmu = {
        .event_map              = intel_pmu_event_map,
        .raw_event              = intel_pmu_raw_event,
        .max_events             = ARRAY_SIZE(intel_perfmon_event_map),
+       .apic                   = 1,
        /*
         * Intel PMCs cannot be accessed sanely above 32 bit width,
         * so we install an artificial 1<<31 period regardless of
@@ -1389,10 +1588,43 @@ static struct x86_pmu amd_pmu = {
        .num_counters           = 4,
        .counter_bits           = 48,
        .counter_mask           = (1ULL << 48) - 1,
+       .apic                   = 1,
        /* use highest bit to detect overflow */
        .max_period             = (1ULL << 47) - 1,
 };
 
+static int p6_pmu_init(void)
+{
+       switch (boot_cpu_data.x86_model) {
+       case 1:
+       case 3:  /* Pentium Pro */
+       case 5:
+       case 6:  /* Pentium II */
+       case 7:
+       case 8:
+       case 11: /* Pentium III */
+               break;
+       case 9:
+       case 13:
+               /* Pentium M */
+               break;
+       default:
+               pr_cont("unsupported p6 CPU model %d ",
+                       boot_cpu_data.x86_model);
+               return -ENODEV;
+       }
+
+       x86_pmu = p6_pmu;
+
+       if (!cpu_has_apic) {
+               pr_info("no APIC, boot with the \"lapic\" boot parameter to force-enable it.\n");
+               pr_info("no hardware sampling interrupt available.\n");
+               x86_pmu.apic = 0;
+       }
+
+       return 0;
+}
+
 static int intel_pmu_init(void)
 {
        union cpuid10_edx edx;
@@ -1401,8 +1633,14 @@ static int intel_pmu_init(void)
        unsigned int ebx;
        int version;
 
-       if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+       if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+               /* check for P6 processor family */
+          if (boot_cpu_data.x86 == 6) {
+               return p6_pmu_init();
+          } else {
                return -ENODEV;
+          }
+       }
 
        /*
         * Check whether the Architectural PerfMon supports
@@ -1428,8 +1666,6 @@ static int intel_pmu_init(void)
         */
        x86_pmu.num_counters_fixed      = max((int)edx.split.num_counters_fixed, 3);
 
-       rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl);
-
        /*
         * Install the hw-cache-events table:
         */
@@ -1499,21 +1735,22 @@ void __init init_hw_perf_counters(void)
        pr_cont("%s PMU driver.\n", x86_pmu.name);
 
        if (x86_pmu.num_counters > X86_PMC_MAX_GENERIC) {
-               x86_pmu.num_counters = X86_PMC_MAX_GENERIC;
                WARN(1, KERN_ERR "hw perf counters %d > max(%d), clipping!",
                     x86_pmu.num_counters, X86_PMC_MAX_GENERIC);
+               x86_pmu.num_counters = X86_PMC_MAX_GENERIC;
        }
        perf_counter_mask = (1 << x86_pmu.num_counters) - 1;
        perf_max_counters = x86_pmu.num_counters;
 
        if (x86_pmu.num_counters_fixed > X86_PMC_MAX_FIXED) {
-               x86_pmu.num_counters_fixed = X86_PMC_MAX_FIXED;
                WARN(1, KERN_ERR "hw perf counters fixed %d > max(%d), clipping!",
                     x86_pmu.num_counters_fixed, X86_PMC_MAX_FIXED);
+               x86_pmu.num_counters_fixed = X86_PMC_MAX_FIXED;
        }
 
        perf_counter_mask |=
                ((1LL << x86_pmu.num_counters_fixed)-1) << X86_PMC_IDX_FIXED;
+       x86_pmu.intel_ctrl = perf_counter_mask;
 
        perf_counters_lapic_init();
        register_die_notifier(&perf_counter_nmi_notifier);
@@ -1563,6 +1800,7 @@ void callchain_store(struct perf_callchain_entry *entry, u64 ip)
 
 static DEFINE_PER_CPU(struct perf_callchain_entry, irq_entry);
 static DEFINE_PER_CPU(struct perf_callchain_entry, nmi_entry);
+static DEFINE_PER_CPU(int, in_nmi_frame);
 
 
 static void
@@ -1578,7 +1816,9 @@ static void backtrace_warning(void *data, char *msg)
 
 static int backtrace_stack(void *data, char *name)
 {
-       /* Process all stacks: */
+       per_cpu(in_nmi_frame, smp_processor_id()) =
+                       x86_is_stack_id(NMI_STACK, name);
+
        return 0;
 }
 
@@ -1586,6 +1826,9 @@ static void backtrace_address(void *data, unsigned long addr, int reliable)
 {
        struct perf_callchain_entry *entry = data;
 
+       if (per_cpu(in_nmi_frame, smp_processor_id()))
+               return;
+
        if (reliable)
                callchain_store(entry, addr);
 }
index 5c481f6205bfc3f591d32f3ef4b4cd850ba2d37a..e60ed740d2b3f4aa49412b47a97656eef07e8952 100644 (file)
@@ -803,8 +803,3 @@ int __kprobes lapic_wd_event(unsigned nmi_hz)
        wd_ops->rearm(wd, nmi_hz);
        return 1;
 }
-
-int lapic_watchdog_ok(void)
-{
-       return wd_ops != NULL;
-}
index 95ea5fa7d4445540c67bdb28ad13102df4248143..c8405718a4c3be91cab8948e95937c7c0bc568b9 100644 (file)
@@ -22,6 +22,7 @@
 #include "dumpstack.h"
 
 int panic_on_unrecovered_nmi;
+int panic_on_io_nmi;
 unsigned int code_bytes = 64;
 int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE;
 static int die_counter;
index d593cd1f58dcca22925f10e2b3669435a4a25557..bca5fba91c9ea3d62eed95643cacdb90e2a32770 100644 (file)
 
 #include "dumpstack.h"
 
+/* Just a stub for now */
+int x86_is_stack_id(int id, char *name)
+{
+       return 0;
+}
+
 void dump_trace(struct task_struct *task, struct pt_regs *regs,
                unsigned long *stack, unsigned long bp,
                const struct stacktrace_ops *ops, void *data)
index d35db5993fd68e3a740ee36ade60edf78d14fae8..54b0a3276766c3ac5180d7d6c11469a2c5f00979 100644 (file)
 
 #include "dumpstack.h"
 
-static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
-                                       unsigned *usedp, char **idp)
-{
-       static char ids[][8] = {
+
+static char x86_stack_ids[][8] = {
                [DEBUG_STACK - 1] = "#DB",
                [NMI_STACK - 1] = "NMI",
                [DOUBLEFAULT_STACK - 1] = "#DF",
@@ -33,6 +31,15 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
                        N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]"
 #endif
        };
+
+int x86_is_stack_id(int id, char *name)
+{
+       return x86_stack_ids[id - 1] == name;
+}
+
+static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
+                                       unsigned *usedp, char **idp)
+{
        unsigned k;
 
        /*
@@ -61,7 +68,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
                        if (*usedp & (1U << k))
                                break;
                        *usedp |= 1U << k;
-                       *idp = ids[k];
+                       *idp = x86_stack_ids[k];
                        return (unsigned long *)end;
                }
                /*
@@ -81,12 +88,13 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
                        do {
                                ++j;
                                end -= EXCEPTION_STKSZ;
-                               ids[j][4] = '1' + (j - N_EXCEPTION_STACKS);
+                               x86_stack_ids[j][4] = '1' +
+                                               (j - N_EXCEPTION_STACKS);
                        } while (stack < end - EXCEPTION_STKSZ);
                        if (*usedp & (1U << j))
                                break;
                        *usedp |= 1U << j;
-                       *idp = ids[j];
+                       *idp = x86_stack_ids[j];
                        return (unsigned long *)end;
                }
 #endif
index 7271fa33d79135edd790f854d7c0c91d05d0c20b..5cb5725b2bae26b97ab1f080599a13ab09cc9770 100644 (file)
@@ -627,10 +627,9 @@ __init void e820_setup_gap(void)
 #ifdef CONFIG_X86_64
        if (!found) {
                gapstart = (max_pfn << PAGE_SHIFT) + 1024*1024;
-               printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit "
-                      "address range\n"
-                      KERN_ERR "PCI: Unassigned devices with 32bit resource "
-                      "registers may break!\n");
+               printk(KERN_ERR
+       "PCI: Warning: Cannot find a gap in the 32bit address range\n"
+       "PCI: Unassigned devices with 32bit resource registers may break!\n");
        }
 #endif
 
@@ -1383,6 +1382,8 @@ static unsigned long ram_alignment(resource_size_t pos)
        return 32*1024*1024;
 }
 
+#define MAX_RESOURCE_SIZE ((resource_size_t)-1)
+
 void __init e820_reserve_resources_late(void)
 {
        int i;
@@ -1400,17 +1401,19 @@ void __init e820_reserve_resources_late(void)
         * avoid stolen RAM:
         */
        for (i = 0; i < e820.nr_map; i++) {
-               struct e820entry *entry = &e820_saved.map[i];
-               resource_size_t start, end;
+               struct e820entry *entry = &e820.map[i];
+               u64 start, end;
 
                if (entry->type != E820_RAM)
                        continue;
                start = entry->addr + entry->size;
-               end = round_up(start, ram_alignment(start));
-               if (start == end)
+               end = round_up(start, ram_alignment(start)) - 1;
+               if (end > MAX_RESOURCE_SIZE)
+                       end = MAX_RESOURCE_SIZE;
+               if (start >= end)
                        continue;
-               reserve_region_with_split(&iomem_resource, start,
-                                                 end - 1, "RAM buffer");
+               reserve_region_with_split(&iomem_resource, start, end,
+                                         "RAM buffer");
        }
 }
 
index 96f7ac0bbf01e567ebf4082ec15b73b9de7a9d2d..fe26ba3e3451872c083c10b6ccf62651fcd762a0 100644 (file)
@@ -354,7 +354,7 @@ void __init efi_init(void)
         */
        c16 = tmp = early_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
@@ -512,7 +512,7 @@ void __init efi_enter_virtual_mode(void)
                        && end_pfn <= max_pfn_mapped))
                        va = __va(md->phys_addr);
                else
-                       va = efi_ioremap(md->phys_addr, size);
+                       va = efi_ioremap(md->phys_addr, size, md->type);
 
                md->virt_addr = (u64) (unsigned long) va;
 
index 22c3b7828c50fa1f0c61e17d6680cbf19d0b6a17..ac0621a7ac3d23383ed6f284451c5bb7d960f977 100644 (file)
@@ -98,10 +98,14 @@ void __init efi_call_phys_epilog(void)
        early_runtime_code_mapping_set_exec(0);
 }
 
-void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size)
+void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
+                                u32 type)
 {
        unsigned long last_map_pfn;
 
+       if (type == EFI_MEMORY_MAPPED_IO)
+               return ioremap(phys_addr, size);
+
        last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size);
        if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size)
                return NULL;
index 8663afb5653547905ecc31bc0ec1d0c41cea2307..cc827ac9e8d35e71dcb702fd7748a79940642da2 100644 (file)
@@ -261,9 +261,7 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
  * which will be freed later
  */
 
-#ifndef CONFIG_HOTPLUG_CPU
-.section .init.text,"ax",@progbits
-#endif
+__CPUINIT
 
 #ifdef CONFIG_SMP
 ENTRY(startup_32_smp)
@@ -602,7 +600,7 @@ ignore_int:
 #endif
        iret
 
-.section .cpuinit.data,"wa"
+       __REFDATA
 .align 4
 ENTRY(initial_code)
        .long i386_start_kernel
index 696f0e475c2d6d8b8b5f2eb4a22e4d934a00e561..92b7703d3d58e6ad278e45d733fdcac1505772fa 100644 (file)
@@ -187,7 +187,7 @@ static void __init apic_intr_init(void)
 #ifdef CONFIG_X86_THERMAL_VECTOR
        alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
 #endif
-#ifdef CONFIG_X86_THRESHOLD
+#ifdef CONFIG_X86_MCE_THRESHOLD
        alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
 #endif
 #if defined(CONFIG_X86_NEW_MCE) && defined(CONFIG_X86_LOCAL_APIC)
index a78ecad0c900ff646b8c826c08cd54b094815b5a..c664d515f613576c7ccd1168afcc47bf897a0855 100644 (file)
@@ -200,7 +200,7 @@ static void kvm_leave_lazy_mmu(void)
        state->mode = paravirt_get_lazy_mode();
 }
 
-static void paravirt_ops_setup(void)
+static void __init paravirt_ops_setup(void)
 {
        pv_info.name = "KVM";
        pv_info.paravirt_enabled = 1;
index 846510b78a092324bfa7adc61ee72ee25e8792cc..2a62d843f015a4804440dce2e502bb3aea47abc7 100644 (file)
@@ -347,7 +347,7 @@ static irqreturn_t mfgpt_tick(int irq, void *dev_id)
 
 static struct irqaction mfgptirq  = {
        .handler = mfgpt_tick,
-       .flags = IRQF_DISABLED | IRQF_NOBALANCING,
+       .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER,
        .name = "mfgpt-timer"
 };
 
index 47630479b0677e3cb51ee3fb473a584fdd4dfa8e..1a041bcf506bd8efd0d27a4e99e2003e07ff6445 100644 (file)
@@ -211,11 +211,11 @@ static __init int iommu_setup(char *p)
 #ifdef CONFIG_SWIOTLB
                if (!strncmp(p, "soft", 4))
                        swiotlb = 1;
+#endif
                if (!strncmp(p, "pt", 2)) {
                        iommu_pass_through = 1;
                        return 1;
                }
-#endif
 
                gart_parse_options(p);
 
index cfd9f90638967e03277ad510625905213322bfd4..d2e56b8f48e708032e9504e8cd13f6cd29437f5e 100644 (file)
@@ -675,7 +675,7 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
  nommu:
        /* Should not happen anymore */
        printk(KERN_WARNING "PCI-DMA: More than 4GB of RAM and no IOMMU\n"
-              KERN_WARNING "falling back to iommu=soft.\n");
+              "falling back to iommu=soft.\n");
        return -1;
 }
 
index 994dd6a4a2a004bcb5d91955fb921ac8c303eb3d..071166a4ba83b893cf3a91aeb2ee52606e9bd056 100644 (file)
@@ -519,16 +519,12 @@ static void c1e_idle(void)
                if (!cpumask_test_cpu(cpu, c1e_mask)) {
                        cpumask_set_cpu(cpu, c1e_mask);
                        /*
-                        * Force broadcast so ACPI can not interfere. Needs
-                        * to run with interrupts enabled as it uses
-                        * smp_function_call.
+                        * Force broadcast so ACPI can not interfere.
                         */
-                       local_irq_enable();
                        clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
                                           &cpu);
                        printk(KERN_INFO "Switch to broadcast mode on CPU%d\n",
                               cpu);
-                       local_irq_disable();
                }
                clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 
index 4f9c55f3a7c0f7e2590a5e248428bd19aa0d5c37..03801f2f761fc312ba80353425c1cc7243a0105f 100644 (file)
@@ -60,7 +60,7 @@ static inline u64 scale_delta(u64 delta, u32 mul_frac, int shift)
                "adc  %5,%%edx ; "
                : "=A" (product), "=r" (tmp1), "=r" (tmp2)
                : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
-#elif __x86_64__
+#elif defined(__x86_64__)
        __asm__ (
                "mul %%rdx ; shrd $32,%%rdx,%%rax"
                : "=a" (product) : "0" (delta), "d" ((u64)mul_frac) );
index d2d1ce8170f06c8573ac022f4e49dfc59a371c9b..a06e8d1018449dd70e4aac4b1098b6b06c4b9bd1 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/init.h>
 #include <linux/pm.h>
 #include <linux/efi.h>
+#include <linux/dmi.h>
 #include <acpi/reboot.h>
 #include <asm/io.h>
 #include <asm/apic.h>
@@ -17,7 +18,6 @@
 #include <asm/cpu.h>
 
 #ifdef CONFIG_X86_32
-# include <linux/dmi.h>
 # include <linux/ctype.h>
 # include <linux/mc146818rtc.h>
 #else
@@ -249,6 +249,14 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"),
                },
        },
+       {       /* Handle problems with rebooting on CompuLab SBC-FITPC2 */
+               .callback = set_bios_reboot,
+               .ident = "CompuLab SBC-FITPC2",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "CompuLab"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "SBC-FITPC2"),
+               },
+       },
        { }
 };
 
@@ -396,6 +404,46 @@ EXPORT_SYMBOL(machine_real_restart);
 
 #endif /* CONFIG_X86_32 */
 
+/*
+ * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
+ */
+static int __init set_pci_reboot(const struct dmi_system_id *d)
+{
+       if (reboot_type != BOOT_CF9) {
+               reboot_type = BOOT_CF9;
+               printk(KERN_INFO "%s series board detected. "
+                      "Selecting PCI-method for reboots.\n", d->ident);
+       }
+       return 0;
+}
+
+static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
+       {       /* Handle problems with rebooting on Apple MacBook5 */
+               .callback = set_pci_reboot,
+               .ident = "Apple MacBook5",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5"),
+               },
+       },
+       {       /* Handle problems with rebooting on Apple MacBookPro5 */
+               .callback = set_pci_reboot,
+               .ident = "Apple MacBookPro5",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5"),
+               },
+       },
+       { }
+};
+
+static int __init pci_reboot_init(void)
+{
+       dmi_check_system(pci_reboot_dmi_table);
+       return 0;
+}
+core_initcall(pci_reboot_init);
+
 static inline void kb_wait(void)
 {
        int i;
index be5ae80f897fb58f68f353fcd65c9346b3834d39..63f32d220ef22e2d681078ec556698e15ff7645f 100644 (file)
@@ -289,6 +289,20 @@ void * __init extend_brk(size_t size, size_t align)
        return ret;
 }
 
+#ifdef CONFIG_X86_64
+static void __init init_gbpages(void)
+{
+       if (direct_gbpages && cpu_has_gbpages)
+               printk(KERN_INFO "Using GB pages for direct mapping\n");
+       else
+               direct_gbpages = 0;
+}
+#else
+static inline void init_gbpages(void)
+{
+}
+#endif
+
 static void __init reserve_brk(void)
 {
        if (_brk_end > _brk_start)
@@ -658,6 +672,19 @@ static struct dmi_system_id __initdata bad_bios_dmi_table[] = {
                        DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies"),
                },
        },
+       {
+       /*
+        * AMI BIOS with low memory corruption was found on Intel DG45ID board.
+        * It hase different DMI_BIOS_VENDOR = "Intel Corp.", for now we will
+        * match only DMI_BOARD_NAME and see if there is more bad products
+        * with this vendor.
+        */
+               .callback = dmi_low_memory_corruption,
+               .ident = "AMI BIOS",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "DG45ID"),
+               },
+       },
 #endif
        {}
 };
@@ -871,6 +898,8 @@ void __init setup_arch(char **cmdline_p)
 
        reserve_brk();
 
+       init_gbpages();
+
        /* max_pfn_mapped is updated here */
        max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT);
        max_pfn_mapped = max_low_pfn_mapped;
index 9c3f0823e6aa00ea93bec0babdfd2c0b19971d13..07d81916f2120f5a55ad0116620630288682bd74 100644 (file)
@@ -124,7 +124,7 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size,
 }
 
 /*
- * Remap allocator
+ * Large page remap allocator
  *
  * This allocator uses PMD page as unit.  A PMD page is allocated for
  * each cpu and each is remapped into vmalloc area using PMD mapping.
@@ -137,105 +137,185 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size,
  * better than only using 4k mappings while still being NUMA friendly.
  */
 #ifdef CONFIG_NEED_MULTIPLE_NODES
-static size_t pcpur_size __initdata;
-static void **pcpur_ptrs __initdata;
+struct pcpul_ent {
+       unsigned int    cpu;
+       void            *ptr;
+};
+
+static size_t pcpul_size;
+static struct pcpul_ent *pcpul_map;
+static struct vm_struct pcpul_vm;
 
-static struct page * __init pcpur_get_page(unsigned int cpu, int pageno)
+static struct page * __init pcpul_get_page(unsigned int cpu, int pageno)
 {
        size_t off = (size_t)pageno << PAGE_SHIFT;
 
-       if (off >= pcpur_size)
+       if (off >= pcpul_size)
                return NULL;
 
-       return virt_to_page(pcpur_ptrs[cpu] + off);
+       return virt_to_page(pcpul_map[cpu].ptr + off);
 }
 
-static ssize_t __init setup_pcpu_remap(size_t static_size)
+static ssize_t __init setup_pcpu_lpage(size_t static_size, bool chosen)
 {
-       static struct vm_struct vm;
-       size_t ptrs_size, dyn_size;
+       size_t map_size, dyn_size;
        unsigned int cpu;
+       int i, j;
        ssize_t ret;
 
-       /*
-        * If large page isn't supported, there's no benefit in doing
-        * this.  Also, on non-NUMA, embedding is better.
-        *
-        * NOTE: disabled for now.
-        */
-       if (true || !cpu_has_pse || !pcpu_need_numa())
+       if (!chosen) {
+               size_t vm_size = VMALLOC_END - VMALLOC_START;
+               size_t tot_size = nr_cpu_ids * PMD_SIZE;
+
+               /* on non-NUMA, embedding is better */
+               if (!pcpu_need_numa())
+                       return -EINVAL;
+
+               /* don't consume more than 20% of vmalloc area */
+               if (tot_size > vm_size / 5) {
+                       pr_info("PERCPU: too large chunk size %zuMB for "
+                               "large page remap\n", tot_size >> 20);
+                       return -EINVAL;
+               }
+       }
+
+       /* need PSE */
+       if (!cpu_has_pse) {
+               pr_warning("PERCPU: lpage allocator requires PSE\n");
                return -EINVAL;
+       }
 
        /*
         * Currently supports only single page.  Supporting multiple
         * pages won't be too difficult if it ever becomes necessary.
         */
-       pcpur_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE +
+       pcpul_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE +
                               PERCPU_DYNAMIC_RESERVE);
-       if (pcpur_size > PMD_SIZE) {
+       if (pcpul_size > PMD_SIZE) {
                pr_warning("PERCPU: static data is larger than large page, "
                           "can't use large page\n");
                return -EINVAL;
        }
-       dyn_size = pcpur_size - static_size - PERCPU_FIRST_CHUNK_RESERVE;
+       dyn_size = pcpul_size - static_size - PERCPU_FIRST_CHUNK_RESERVE;
 
        /* allocate pointer array and alloc large pages */
-       ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpur_ptrs[0]));
-       pcpur_ptrs = alloc_bootmem(ptrs_size);
+       map_size = PFN_ALIGN(nr_cpu_ids * sizeof(pcpul_map[0]));
+       pcpul_map = alloc_bootmem(map_size);
 
        for_each_possible_cpu(cpu) {
-               pcpur_ptrs[cpu] = pcpu_alloc_bootmem(cpu, PMD_SIZE, PMD_SIZE);
-               if (!pcpur_ptrs[cpu])
+               pcpul_map[cpu].cpu = cpu;
+               pcpul_map[cpu].ptr = pcpu_alloc_bootmem(cpu, PMD_SIZE,
+                                                       PMD_SIZE);
+               if (!pcpul_map[cpu].ptr) {
+                       pr_warning("PERCPU: failed to allocate large page "
+                                  "for cpu%u\n", cpu);
                        goto enomem;
+               }
 
                /*
-                * Only use pcpur_size bytes and give back the rest.
+                * Only use pcpul_size bytes and give back the rest.
                 *
                 * Ingo: The 2MB up-rounding bootmem is needed to make
                 * sure the partial 2MB page is still fully RAM - it's
                 * not well-specified to have a PAT-incompatible area
                 * (unmapped RAM, device memory, etc.) in that hole.
                 */
-               free_bootmem(__pa(pcpur_ptrs[cpu] + pcpur_size),
-                            PMD_SIZE - pcpur_size);
+               free_bootmem(__pa(pcpul_map[cpu].ptr + pcpul_size),
+                            PMD_SIZE - pcpul_size);
 
-               memcpy(pcpur_ptrs[cpu], __per_cpu_load, static_size);
+               memcpy(pcpul_map[cpu].ptr, __per_cpu_load, static_size);
        }
 
        /* allocate address and map */
-       vm.flags = VM_ALLOC;
-       vm.size = num_possible_cpus() * PMD_SIZE;
-       vm_area_register_early(&vm, PMD_SIZE);
+       pcpul_vm.flags = VM_ALLOC;
+       pcpul_vm.size = nr_cpu_ids * PMD_SIZE;
+       vm_area_register_early(&pcpul_vm, PMD_SIZE);
 
        for_each_possible_cpu(cpu) {
-               pmd_t *pmd;
+               pmd_t *pmd, pmd_v;
 
-               pmd = populate_extra_pmd((unsigned long)vm.addr
-                                        + cpu * PMD_SIZE);
-               set_pmd(pmd, pfn_pmd(page_to_pfn(virt_to_page(pcpur_ptrs[cpu])),
-                                    PAGE_KERNEL_LARGE));
+               pmd = populate_extra_pmd((unsigned long)pcpul_vm.addr +
+                                        cpu * PMD_SIZE);
+               pmd_v = pfn_pmd(page_to_pfn(virt_to_page(pcpul_map[cpu].ptr)),
+                               PAGE_KERNEL_LARGE);
+               set_pmd(pmd, pmd_v);
        }
 
        /* we're ready, commit */
        pr_info("PERCPU: Remapped at %p with large pages, static data "
-               "%zu bytes\n", vm.addr, static_size);
+               "%zu bytes\n", pcpul_vm.addr, static_size);
 
-       ret = pcpu_setup_first_chunk(pcpur_get_page, static_size,
+       ret = pcpu_setup_first_chunk(pcpul_get_page, static_size,
                                     PERCPU_FIRST_CHUNK_RESERVE, dyn_size,
-                                    PMD_SIZE, vm.addr, NULL);
-       goto out_free_ar;
+                                    PMD_SIZE, pcpul_vm.addr, NULL);
+
+       /* sort pcpul_map array for pcpu_lpage_remapped() */
+       for (i = 0; i < nr_cpu_ids - 1; i++)
+               for (j = i + 1; j < nr_cpu_ids; j++)
+                       if (pcpul_map[i].ptr > pcpul_map[j].ptr) {
+                               struct pcpul_ent tmp = pcpul_map[i];
+                               pcpul_map[i] = pcpul_map[j];
+                               pcpul_map[j] = tmp;
+                       }
+
+       return ret;
 
 enomem:
        for_each_possible_cpu(cpu)
-               if (pcpur_ptrs[cpu])
-                       free_bootmem(__pa(pcpur_ptrs[cpu]), PMD_SIZE);
-       ret = -ENOMEM;
-out_free_ar:
-       free_bootmem(__pa(pcpur_ptrs), ptrs_size);
-       return ret;
+               if (pcpul_map[cpu].ptr)
+                       free_bootmem(__pa(pcpul_map[cpu].ptr), pcpul_size);
+       free_bootmem(__pa(pcpul_map), map_size);
+       return -ENOMEM;
+}
+
+/**
+ * pcpu_lpage_remapped - determine whether a kaddr is in pcpul recycled area
+ * @kaddr: the kernel address in question
+ *
+ * Determine whether @kaddr falls in the pcpul recycled area.  This is
+ * used by pageattr to detect VM aliases and break up the pcpu PMD
+ * mapping such that the same physical page is not mapped under
+ * different attributes.
+ *
+ * The recycled area is always at the tail of a partially used PMD
+ * page.
+ *
+ * RETURNS:
+ * Address of corresponding remapped pcpu address if match is found;
+ * otherwise, NULL.
+ */
+void *pcpu_lpage_remapped(void *kaddr)
+{
+       void *pmd_addr = (void *)((unsigned long)kaddr & PMD_MASK);
+       unsigned long offset = (unsigned long)kaddr & ~PMD_MASK;
+       int left = 0, right = nr_cpu_ids - 1;
+       int pos;
+
+       /* pcpul in use at all? */
+       if (!pcpul_map)
+               return NULL;
+
+       /* okay, perform binary search */
+       while (left <= right) {
+               pos = (left + right) / 2;
+
+               if (pcpul_map[pos].ptr < pmd_addr)
+                       left = pos + 1;
+               else if (pcpul_map[pos].ptr > pmd_addr)
+                       right = pos - 1;
+               else {
+                       /* it shouldn't be in the area for the first chunk */
+                       WARN_ON(offset < pcpul_size);
+
+                       return pcpul_vm.addr +
+                               pcpul_map[pos].cpu * PMD_SIZE + offset;
+               }
+       }
+
+       return NULL;
 }
 #else
-static ssize_t __init setup_pcpu_remap(size_t static_size)
+static ssize_t __init setup_pcpu_lpage(size_t static_size, bool chosen)
 {
        return -EINVAL;
 }
@@ -249,7 +329,7 @@ static ssize_t __init setup_pcpu_remap(size_t static_size)
  * mapping so that it can use PMD mapping without additional TLB
  * pressure.
  */
-static ssize_t __init setup_pcpu_embed(size_t static_size)
+static ssize_t __init setup_pcpu_embed(size_t static_size, bool chosen)
 {
        size_t reserve = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE;
 
@@ -258,7 +338,7 @@ static ssize_t __init setup_pcpu_embed(size_t static_size)
         * this.  Also, embedding allocation doesn't play well with
         * NUMA.
         */
-       if (!cpu_has_pse || pcpu_need_numa())
+       if (!chosen && (!cpu_has_pse || pcpu_need_numa()))
                return -EINVAL;
 
        return pcpu_embed_first_chunk(static_size, PERCPU_FIRST_CHUNK_RESERVE,
@@ -297,7 +377,7 @@ static ssize_t __init setup_pcpu_4k(size_t static_size)
        pcpu4k_nr_static_pages = PFN_UP(static_size);
 
        /* unaligned allocations can't be freed, round up to page size */
-       pages_size = PFN_ALIGN(pcpu4k_nr_static_pages * num_possible_cpus()
+       pages_size = PFN_ALIGN(pcpu4k_nr_static_pages * nr_cpu_ids
                               * sizeof(pcpu4k_pages[0]));
        pcpu4k_pages = alloc_bootmem(pages_size);
 
@@ -308,8 +388,11 @@ static ssize_t __init setup_pcpu_4k(size_t static_size)
                        void *ptr;
 
                        ptr = pcpu_alloc_bootmem(cpu, PAGE_SIZE, PAGE_SIZE);
-                       if (!ptr)
+                       if (!ptr) {
+                               pr_warning("PERCPU: failed to allocate "
+                                          "4k page for cpu%u\n", cpu);
                                goto enomem;
+                       }
 
                        memcpy(ptr, __per_cpu_load + i * PAGE_SIZE, PAGE_SIZE);
                        pcpu4k_pages[j++] = virt_to_page(ptr);
@@ -333,6 +416,16 @@ out_free_ar:
        return ret;
 }
 
+/* for explicit first chunk allocator selection */
+static char pcpu_chosen_alloc[16] __initdata;
+
+static int __init percpu_alloc_setup(char *str)
+{
+       strncpy(pcpu_chosen_alloc, str, sizeof(pcpu_chosen_alloc) - 1);
+       return 0;
+}
+early_param("percpu_alloc", percpu_alloc_setup);
+
 static inline void setup_percpu_segment(int cpu)
 {
 #ifdef CONFIG_X86_32
@@ -346,11 +439,6 @@ static inline void setup_percpu_segment(int cpu)
 #endif
 }
 
-/*
- * Great future plan:
- * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data.
- * Always point %gs to its beginning
- */
 void __init setup_per_cpu_areas(void)
 {
        size_t static_size = __per_cpu_end - __per_cpu_start;
@@ -367,9 +455,26 @@ void __init setup_per_cpu_areas(void)
         * of large page mappings.  Please read comments on top of
         * each allocator for details.
         */
-       ret = setup_pcpu_remap(static_size);
-       if (ret < 0)
-               ret = setup_pcpu_embed(static_size);
+       ret = -EINVAL;
+       if (strlen(pcpu_chosen_alloc)) {
+               if (strcmp(pcpu_chosen_alloc, "4k")) {
+                       if (!strcmp(pcpu_chosen_alloc, "lpage"))
+                               ret = setup_pcpu_lpage(static_size, true);
+                       else if (!strcmp(pcpu_chosen_alloc, "embed"))
+                               ret = setup_pcpu_embed(static_size, true);
+                       else
+                               pr_warning("PERCPU: unknown allocator %s "
+                                          "specified\n", pcpu_chosen_alloc);
+                       if (ret < 0)
+                               pr_warning("PERCPU: %s allocator failed (%zd), "
+                                          "falling back to 4k\n",
+                                          pcpu_chosen_alloc, ret);
+               }
+       } else {
+               ret = setup_pcpu_lpage(static_size, false);
+               if (ret < 0)
+                       ret = setup_pcpu_embed(static_size, false);
+       }
        if (ret < 0)
                ret = setup_pcpu_4k(static_size);
        if (ret < 0)
index 124d40c575df376e989d5b00229fda865f0bb682..77b9689f8edba0bf7db2be473a4d27c4987846fe 100644 (file)
@@ -711,7 +711,6 @@ uv_activation_descriptor_init(int node, int pnode)
        unsigned long pa;
        unsigned long m;
        unsigned long n;
-       unsigned long mmr_image;
        struct bau_desc *adp;
        struct bau_desc *ad2;
 
@@ -727,12 +726,8 @@ uv_activation_descriptor_init(int node, int pnode)
        n = pa >> uv_nshift;
        m = pa & uv_mmask;
 
-       mmr_image = uv_read_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE);
-       if (mmr_image) {
-               uv_write_global_mmr64(pnode, (unsigned long)
-                                     UVH_LB_BAU_SB_DESCRIPTOR_BASE,
-                                     (n << UV_DESC_BASE_PNODE_SHIFT | m));
-       }
+       uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE,
+                             (n << UV_DESC_BASE_PNODE_SHIFT | m));
 
        /*
         * initializing all 8 (UV_ITEMS_PER_DESCRIPTOR) descriptors for each
@@ -749,6 +744,7 @@ uv_activation_descriptor_init(int node, int pnode)
                 * note that base_dest_nodeid is actually a nasid.
                 */
                ad2->header.base_dest_nodeid = uv_partition_base_pnode << 1;
+               ad2->header.dest_subnodeid = 0x10; /* the LB */
                ad2->header.command = UV_NET_ENDPOINT_INTD;
                ad2->header.int_both = 1;
                /*
index a0f48f5671c076fdde9bbccf10300c3724c840a9..5204332f475d86e1caa1ede6bb39fcc28b78d13f 100644 (file)
@@ -346,6 +346,9 @@ io_check_error(unsigned char reason, struct pt_regs *regs)
        printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
        show_registers(regs);
 
+       if (panic_on_io_nmi)
+               panic("NMI IOCK error: Not continuing");
+
        /* Re-enable the IOCK line, wait for a few seconds */
        reason = (reason & 0xf) | 8;
        outb(reason, 0x61);
index 6e1a368d21d4d9214feda8eb6fcabe9c043708e1..71f4368b357edf2a47fd035349bfbcd8c595e882 100644 (file)
@@ -275,15 +275,20 @@ static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin)
  * use the TSC value at the transitions to calculate a pretty
  * good value for the TSC frequencty.
  */
+static inline int pit_verify_msb(unsigned char val)
+{
+       /* Ignore LSB */
+       inb(0x42);
+       return inb(0x42) == val;
+}
+
 static inline int pit_expect_msb(unsigned char val, u64 *tscp, unsigned long *deltap)
 {
        int count;
        u64 tsc = 0;
 
        for (count = 0; count < 50000; count++) {
-               /* Ignore LSB */
-               inb(0x42);
-               if (inb(0x42) != val)
+               if (!pit_verify_msb(val))
                        break;
                tsc = get_cycles();
        }
@@ -336,8 +341,7 @@ static unsigned long quick_pit_calibrate(void)
         * to do that is to just read back the 16-bit counter
         * once from the PIT.
         */
-       inb(0x42);
-       inb(0x42);
+       pit_verify_msb(0);
 
        if (pit_expect_msb(0xff, &tsc, &d1)) {
                for (i = 1; i <= MAX_QUICK_PIT_ITERATIONS; i++) {
@@ -348,8 +352,19 @@ static unsigned long quick_pit_calibrate(void)
                         * Iterate until the error is less than 500 ppm
                         */
                        delta -= tsc;
-                       if (d1+d2 < delta >> 11)
-                               goto success;
+                       if (d1+d2 >= delta >> 11)
+                               continue;
+
+                       /*
+                        * Check the PIT one more time to verify that
+                        * all TSC reads were stable wrt the PIT.
+                        *
+                        * This also guarantees serialization of the
+                        * last cycle read ('d2') in pit_expect_msb.
+                        */
+                       if (!pit_verify_msb(0xfe - i))
+                               break;
+                       goto success;
                }
        }
        printk("Fast TSC calibration failed\n");
index b263423fbe2ae971424c5bd99c112ac984413383..95a7289e4b0cdd8cc7b88f0504a93b205f2a6934 100644 (file)
@@ -441,7 +441,7 @@ vmi_startup_ipi_hook(int phys_apicid, unsigned long start_eip,
        ap.ds = __USER_DS;
        ap.es = __USER_DS;
        ap.fs = __KERNEL_PERCPU;
-       ap.gs = 0;
+       ap.gs = __KERNEL_STACK_CANARY;
 
        ap.eflags = 0;
 
index 367e878820418789055a6a2da48aa27350ada443..9fc178255c0465e01c35c3d5439fb54866eacaf1 100644 (file)
@@ -46,11 +46,10 @@ PHDRS {
        data PT_LOAD FLAGS(7);          /* RWE */
 #ifdef CONFIG_X86_64
        user PT_LOAD FLAGS(7);          /* RWE */
-       data.init PT_LOAD FLAGS(7);     /* RWE */
 #ifdef CONFIG_SMP
        percpu PT_LOAD FLAGS(7);        /* RWE */
 #endif
-       data.init2 PT_LOAD FLAGS(7);    /* RWE */
+       init PT_LOAD FLAGS(7);          /* RWE */
 #endif
        note PT_NOTE FLAGS(0);          /* ___ */
 }
@@ -103,72 +102,43 @@ SECTIONS
                __stop___ex_table = .;
        } :text = 0x9090
 
-       RODATA
+       RO_DATA(PAGE_SIZE)
 
        /* Data */
-       . = ALIGN(PAGE_SIZE);
        .data : AT(ADDR(.data) - LOAD_OFFSET) {
                /* Start of data section */
                _sdata = .;
-               DATA_DATA
-               CONSTRUCTORS
 
-#ifdef CONFIG_X86_64
-               /* End of data section */
-               _edata = .;
-#endif
-       } :data
+               /* init_task */
+               INIT_TASK_DATA(THREAD_SIZE)
 
 #ifdef CONFIG_X86_32
-       /* 32 bit has nosave before _edata */
-       . = ALIGN(PAGE_SIZE);
-       .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
-               __nosave_begin = .;
-               *(.data.nosave)
-               . = ALIGN(PAGE_SIZE);
-               __nosave_end = .;
-       }
+               /* 32 bit has nosave before _edata */
+               NOSAVE_DATA
 #endif
 
-       . = ALIGN(PAGE_SIZE);
-       .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
-               *(.data.page_aligned)
+               PAGE_ALIGNED_DATA(PAGE_SIZE)
                *(.data.idt)
-       }
 
-#ifdef CONFIG_X86_32
-       . = ALIGN(32);
-#else
-       . = ALIGN(PAGE_SIZE);
-       . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
-#endif
-       .data.cacheline_aligned :
-               AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
-               *(.data.cacheline_aligned)
-       }
+               CACHELINE_ALIGNED_DATA(CONFIG_X86_L1_CACHE_BYTES)
 
-       /* rarely changed data like cpu maps */
-#ifdef CONFIG_X86_32
-       . = ALIGN(32);
-#else
-       . = ALIGN(CONFIG_X86_INTERNODE_CACHE_BYTES);
-#endif
-       .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) {
-               *(.data.read_mostly)
+               DATA_DATA
+               CONSTRUCTORS
+
+               /* rarely changed data like cpu maps */
+               READ_MOSTLY_DATA(CONFIG_X86_INTERNODE_CACHE_BYTES)
 
-#ifdef CONFIG_X86_32
                /* End of data section */
                _edata = .;
-#endif
-       }
+       } :data
 
 #ifdef CONFIG_X86_64
 
 #define VSYSCALL_ADDR (-10*1024*1024)
-#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data.read_mostly) + \
-                            SIZEOF(.data.read_mostly) + 4095) & ~(4095))
-#define VSYSCALL_VIRT_ADDR ((ADDR(.data.read_mostly) + \
-                            SIZEOF(.data.read_mostly) + 4095) & ~(4095))
+#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data) + SIZEOF(.data) + \
+                            PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
+#define VSYSCALL_VIRT_ADDR ((ADDR(.data) + SIZEOF(.data) + \
+                            PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
 
 #define VLOAD_OFFSET (VSYSCALL_ADDR - VSYSCALL_PHYS_ADDR)
 #define VLOAD(x) (ADDR(x) - VLOAD_OFFSET)
@@ -234,35 +204,29 @@ SECTIONS
 
 #endif /* CONFIG_X86_64 */
 
-       /* init_task */
-       . = ALIGN(THREAD_SIZE);
-       .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
-               *(.data.init_task)
+       /* Init code and data - will be freed after init */
+       . = ALIGN(PAGE_SIZE);
+       .init.begin : AT(ADDR(.init.begin) - LOAD_OFFSET) {
+               __init_begin = .; /* paired with __init_end */
        }
-#ifdef CONFIG_X86_64
-        :data.init
-#endif
 
+#if defined(CONFIG_X86_64) && defined(CONFIG_SMP)
        /*
-        * smp_locks might be freed after init
-        * start/end must be page aligned
+        * percpu offsets are zero-based on SMP.  PERCPU_VADDR() changes the
+        * output PHDR, so the next output section - .init.text - should
+        * start another segment - init.
         */
-       . = ALIGN(PAGE_SIZE);
-       .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
-               __smp_locks = .;
-               *(.smp_locks)
-               __smp_locks_end = .;
-               . = ALIGN(PAGE_SIZE);
-       }
+       PERCPU_VADDR(0, :percpu)
+#endif
 
-       /* Init code and data - will be freed after init */
-       . = ALIGN(PAGE_SIZE);
        .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
-               __init_begin = .; /* paired with __init_end */
                _sinittext = .;
                INIT_TEXT
                _einittext = .;
        }
+#ifdef CONFIG_X86_64
+       :init
+#endif
 
        .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
                INIT_DATA
@@ -333,17 +297,7 @@ SECTIONS
        }
 #endif
 
-#if defined(CONFIG_X86_64) && defined(CONFIG_SMP)
-       /*
-        * percpu offsets are zero-based on SMP.  PERCPU_VADDR() changes the
-        * output PHDR, so the next output section - __data_nosave - should
-        * start another section data.init2.  Also, pda should be at the head of
-        * percpu area.  Preallocate it and define the percpu offset symbol
-        * so that it can be accessed as a percpu variable.
-        */
-       . = ALIGN(PAGE_SIZE);
-       PERCPU_VADDR(0, :percpu)
-#else
+#if !defined(CONFIG_X86_64) || !defined(CONFIG_SMP)
        PERCPU(PAGE_SIZE)
 #endif
 
@@ -354,15 +308,22 @@ SECTIONS
                __init_end = .;
        }
 
+       /*
+        * smp_locks might be freed after init
+        * start/end must be page aligned
+        */
+       . = ALIGN(PAGE_SIZE);
+       .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
+               __smp_locks = .;
+               *(.smp_locks)
+               __smp_locks_end = .;
+               . = ALIGN(PAGE_SIZE);
+       }
+
 #ifdef CONFIG_X86_64
        .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
-               . = ALIGN(PAGE_SIZE);
-               __nosave_begin = .;
-               *(.data.nosave)
-               . = ALIGN(PAGE_SIZE);
-               __nosave_end = .;
-       } :data.init2
-       /* use another section data.init2, see PERCPU_VADDR() above */
+               NOSAVE_DATA
+       }
 #endif
 
        /* BSS */
@@ -400,8 +361,8 @@ SECTIONS
 
 
 #ifdef CONFIG_X86_32
-ASSERT((_end - LOAD_OFFSET <= KERNEL_IMAGE_SIZE),
-        "kernel image bigger than KERNEL_IMAGE_SIZE")
+. = ASSERT((_end - LOAD_OFFSET <= KERNEL_IMAGE_SIZE),
+          "kernel image bigger than KERNEL_IMAGE_SIZE");
 #else
 /*
  * Per-cpu symbols which need to be offset from __per_cpu_load
@@ -414,12 +375,12 @@ INIT_PER_CPU(irq_stack_union);
 /*
  * Build-time check on the image size:
  */
-ASSERT((_end - _text <= KERNEL_IMAGE_SIZE),
-       "kernel image bigger than KERNEL_IMAGE_SIZE")
+. = ASSERT((_end - _text <= KERNEL_IMAGE_SIZE),
+          "kernel image bigger than KERNEL_IMAGE_SIZE");
 
 #ifdef CONFIG_SMP
-ASSERT((per_cpu__irq_stack_union == 0),
-        "irq_stack_union is not at start of per-cpu area");
+. = ASSERT((per_cpu__irq_stack_union == 0),
+           "irq_stack_union is not at start of per-cpu area");
 #endif
 
 #endif /* CONFIG_X86_32 */
@@ -427,7 +388,7 @@ ASSERT((per_cpu__irq_stack_union == 0),
 #ifdef CONFIG_KEXEC
 #include <asm/kexec.h>
 
-ASSERT(kexec_control_code_size <= KEXEC_CONTROL_CODE_MAX_SIZE,
-       "kexec control code size is too big")
+. = ASSERT(kexec_control_code_size <= KEXEC_CONTROL_CODE_MAX_SIZE,
+           "kexec control code size is too big");
 #endif
 
index 4d6f0d293ee29bb303dbe5e4b81b4cb3c9e2b6e2..21f68e00524f51e32ad479f80446a515c1f6817a 100644 (file)
@@ -104,6 +104,9 @@ static s64 __kpit_elapsed(struct kvm *kvm)
        ktime_t remaining;
        struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
 
+       if (!ps->pit_timer.period)
+               return 0;
+
        /*
         * The Counter does not stop when it reaches zero. In
         * Modes 0, 1, 4, and 5 the Counter ``wraps around'' to
index 5c3d6e81a7dc61ec0b5ad6d952b77b96acb23b8f..0ef5bb2b4043af68c70ce46dbe484e3a887f8a21 100644 (file)
@@ -489,16 +489,20 @@ static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int lpage)
  *
  * If rmapp bit zero is one, (then rmap & ~1) points to a struct kvm_rmap_desc
  * containing more mappings.
+ *
+ * Returns the number of rmap entries before the spte was added or zero if
+ * the spte was not added.
+ *
  */
-static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
+static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
 {
        struct kvm_mmu_page *sp;
        struct kvm_rmap_desc *desc;
        unsigned long *rmapp;
-       int i;
+       int i, count = 0;
 
        if (!is_rmap_pte(*spte))
-               return;
+               return count;
        gfn = unalias_gfn(vcpu->kvm, gfn);
        sp = page_header(__pa(spte));
        sp->gfns[spte - sp->spt] = gfn;
@@ -515,8 +519,10 @@ static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
        } else {
                rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte);
                desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
-               while (desc->shadow_ptes[RMAP_EXT-1] && desc->more)
+               while (desc->shadow_ptes[RMAP_EXT-1] && desc->more) {
                        desc = desc->more;
+                       count += RMAP_EXT;
+               }
                if (desc->shadow_ptes[RMAP_EXT-1]) {
                        desc->more = mmu_alloc_rmap_desc(vcpu);
                        desc = desc->more;
@@ -525,6 +531,7 @@ static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
                        ;
                desc->shadow_ptes[i] = spte;
        }
+       return count;
 }
 
 static void rmap_desc_remove_entry(unsigned long *rmapp,
@@ -754,6 +761,19 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp)
        return young;
 }
 
+#define RMAP_RECYCLE_THRESHOLD 1000
+
+static void rmap_recycle(struct kvm_vcpu *vcpu, gfn_t gfn, int lpage)
+{
+       unsigned long *rmapp;
+
+       gfn = unalias_gfn(vcpu->kvm, gfn);
+       rmapp = gfn_to_rmap(vcpu->kvm, gfn, lpage);
+
+       kvm_unmap_rmapp(vcpu->kvm, rmapp);
+       kvm_flush_remote_tlbs(vcpu->kvm);
+}
+
 int kvm_age_hva(struct kvm *kvm, unsigned long hva)
 {
        return kvm_handle_hva(kvm, hva, kvm_age_rmapp);
@@ -1407,24 +1427,25 @@ static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp)
  */
 void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages)
 {
+       int used_pages;
+
+       used_pages = kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages;
+       used_pages = max(0, used_pages);
+
        /*
         * If we set the number of mmu pages to be smaller be than the
         * number of actived pages , we must to free some mmu pages before we
         * change the value
         */
 
-       if ((kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages) >
-           kvm_nr_mmu_pages) {
-               int n_used_mmu_pages = kvm->arch.n_alloc_mmu_pages
-                                      - kvm->arch.n_free_mmu_pages;
-
-               while (n_used_mmu_pages > kvm_nr_mmu_pages) {
+       if (used_pages > kvm_nr_mmu_pages) {
+               while (used_pages > kvm_nr_mmu_pages) {
                        struct kvm_mmu_page *page;
 
                        page = container_of(kvm->arch.active_mmu_pages.prev,
                                            struct kvm_mmu_page, link);
                        kvm_mmu_zap_page(kvm, page);
-                       n_used_mmu_pages--;
+                       used_pages--;
                }
                kvm->arch.n_free_mmu_pages = 0;
        }
@@ -1740,6 +1761,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
 {
        int was_rmapped = 0;
        int was_writeble = is_writeble_pte(*shadow_pte);
+       int rmap_count;
 
        pgprintk("%s: spte %llx access %x write_fault %d"
                 " user_fault %d gfn %lx\n",
@@ -1781,9 +1803,11 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
 
        page_header_update_slot(vcpu->kvm, shadow_pte, gfn);
        if (!was_rmapped) {
-               rmap_add(vcpu, shadow_pte, gfn, largepage);
+               rmap_count = rmap_add(vcpu, shadow_pte, gfn, largepage);
                if (!is_rmap_pte(*shadow_pte))
                        kvm_release_pfn_clean(pfn);
+               if (rmap_count > RMAP_RECYCLE_THRESHOLD)
+                       rmap_recycle(vcpu, gfn, largepage);
        } else {
                if (was_writeble)
                        kvm_release_pfn_dirty(pfn);
@@ -2157,7 +2181,7 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu, int level)
                else
                        /* 32 bits PSE 4MB page */
                        context->rsvd_bits_mask[1][1] = rsvd_bits(13, 21);
-               context->rsvd_bits_mask[1][0] = ~0ull;
+               context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[1][0];
                break;
        case PT32E_ROOT_LEVEL:
                context->rsvd_bits_mask[0][2] =
@@ -2170,7 +2194,7 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu, int level)
                context->rsvd_bits_mask[1][1] = exb_bit_rsvd |
                        rsvd_bits(maxphyaddr, 62) |
                        rsvd_bits(13, 20);              /* large page */
-               context->rsvd_bits_mask[1][0] = ~0ull;
+               context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[1][0];
                break;
        case PT64_ROOT_LEVEL:
                context->rsvd_bits_mask[0][3] = exb_bit_rsvd |
@@ -2186,7 +2210,7 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu, int level)
                context->rsvd_bits_mask[1][1] = exb_bit_rsvd |
                        rsvd_bits(maxphyaddr, 51) |
                        rsvd_bits(13, 20);              /* large page */
-               context->rsvd_bits_mask[1][0] = ~0ull;
+               context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[1][0];
                break;
        }
 }
index 258e4591e1ca02246801fc380ae19472b2375b0a..67785f635399fdf26e09528589e41c41a1202a7a 100644 (file)
@@ -281,7 +281,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
 {
        unsigned access = gw->pt_access;
        struct kvm_mmu_page *shadow_page;
-       u64 spte, *sptep;
+       u64 spte, *sptep = NULL;
        int direct;
        gfn_t table_gfn;
        int r;
index 71510e07e69e062b5ce1626d6273cc2f03f39ccf..b1f658ad2f06b673d489ec825a4676a176df6b04 100644 (file)
@@ -711,6 +711,7 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
                svm->vmcb->control.tsc_offset += delta;
                vcpu->cpu = cpu;
                kvm_migrate_timers(vcpu);
+               svm->asid_generation = 0;
        }
 
        for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
@@ -1031,7 +1032,6 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *svm_data)
                svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
        }
 
-       svm->vcpu.cpu = svm_data->cpu;
        svm->asid_generation = svm_data->asid_generation;
        svm->vmcb->control.asid = svm_data->next_asid++;
 }
@@ -2300,8 +2300,8 @@ static void pre_svm_run(struct vcpu_svm *svm)
        struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu);
 
        svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
-       if (svm->vcpu.cpu != cpu ||
-           svm->asid_generation != svm_data->asid_generation)
+       /* FIXME: handle wraparound of asid_generation */
+       if (svm->asid_generation != svm_data->asid_generation)
                new_asid(svm, svm_data);
 }
 
index e770bf349ec4f7f473f8639dabf4068188a4b3b5..29f912927a588bda4e9a3fc06ea2412ec04b5ebc 100644 (file)
@@ -3012,6 +3012,12 @@ static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        return 1;
 }
 
+static int handle_vmx_insn(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       kvm_queue_exception(vcpu, UD_VECTOR);
+       return 1;
+}
+
 static int handle_invlpg(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
@@ -3151,8 +3157,8 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu,
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        enum emulation_result err = EMULATE_DONE;
 
-       preempt_enable();
        local_irq_enable();
+       preempt_enable();
 
        while (!guest_state_valid(vcpu)) {
                err = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
@@ -3162,7 +3168,7 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu,
 
                if (err != EMULATE_DONE) {
                        kvm_report_emulation_failure(vcpu, "emulation failure");
-                       return;
+                       break;
                }
 
                if (signal_pending(current))
@@ -3171,8 +3177,8 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu,
                        schedule();
        }
 
-       local_irq_disable();
        preempt_disable();
+       local_irq_disable();
 
        vmx->invalid_state_emulation_result = err;
 }
@@ -3198,6 +3204,15 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu,
        [EXIT_REASON_HLT]                     = handle_halt,
        [EXIT_REASON_INVLPG]                  = handle_invlpg,
        [EXIT_REASON_VMCALL]                  = handle_vmcall,
+       [EXIT_REASON_VMCLEAR]                 = handle_vmx_insn,
+       [EXIT_REASON_VMLAUNCH]                = handle_vmx_insn,
+       [EXIT_REASON_VMPTRLD]                 = handle_vmx_insn,
+       [EXIT_REASON_VMPTRST]                 = handle_vmx_insn,
+       [EXIT_REASON_VMREAD]                  = handle_vmx_insn,
+       [EXIT_REASON_VMRESUME]                = handle_vmx_insn,
+       [EXIT_REASON_VMWRITE]                 = handle_vmx_insn,
+       [EXIT_REASON_VMOFF]                   = handle_vmx_insn,
+       [EXIT_REASON_VMON]                    = handle_vmx_insn,
        [EXIT_REASON_TPR_BELOW_THRESHOLD]     = handle_tpr_below_threshold,
        [EXIT_REASON_APIC_ACCESS]             = handle_apic_access,
        [EXIT_REASON_WBINVD]                  = handle_wbinvd,
index 249540f985132f79922736a8dd49f8febeb71bdf..3d45290118284223ffc1c3d2c66fa0ffd08ba1cf 100644 (file)
@@ -704,11 +704,48 @@ static bool msr_mtrr_valid(unsigned msr)
        return false;
 }
 
+static bool valid_pat_type(unsigned t)
+{
+       return t < 8 && (1 << t) & 0xf3; /* 0, 1, 4, 5, 6, 7 */
+}
+
+static bool valid_mtrr_type(unsigned t)
+{
+       return t < 8 && (1 << t) & 0x73; /* 0, 1, 4, 5, 6 */
+}
+
+static bool mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+{
+       int i;
+
+       if (!msr_mtrr_valid(msr))
+               return false;
+
+       if (msr == MSR_IA32_CR_PAT) {
+               for (i = 0; i < 8; i++)
+                       if (!valid_pat_type((data >> (i * 8)) & 0xff))
+                               return false;
+               return true;
+       } else if (msr == MSR_MTRRdefType) {
+               if (data & ~0xcff)
+                       return false;
+               return valid_mtrr_type(data & 0xff);
+       } else if (msr >= MSR_MTRRfix64K_00000 && msr <= MSR_MTRRfix4K_F8000) {
+               for (i = 0; i < 8 ; i++)
+                       if (!valid_mtrr_type((data >> (i * 8)) & 0xff))
+                               return false;
+               return true;
+       }
+
+       /* variable MTRRs */
+       return valid_mtrr_type(data & 0xff);
+}
+
 static int set_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 {
        u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;
 
-       if (!msr_mtrr_valid(msr))
+       if (!mtrr_valid(vcpu, msr, data))
                return 1;
 
        if (msr == MSR_MTRRdefType) {
@@ -898,6 +935,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
        case MSR_VM_HSAVE_PA:
        case MSR_P6_EVNTSEL0:
        case MSR_P6_EVNTSEL1:
+       case MSR_K7_EVNTSEL0:
                data = 0;
                break;
        case MSR_MTRRcap:
@@ -1078,14 +1116,13 @@ long kvm_arch_dev_ioctl(struct file *filp,
                if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list))
                        goto out;
                r = -E2BIG;
-               if (n < num_msrs_to_save)
+               if (n < msr_list.nmsrs)
                        goto out;
                r = -EFAULT;
                if (copy_to_user(user_msr_list->indices, &msrs_to_save,
                                 num_msrs_to_save * sizeof(u32)))
                        goto out;
-               if (copy_to_user(user_msr_list->indices
-                                + num_msrs_to_save * sizeof(u32),
+               if (copy_to_user(user_msr_list->indices + num_msrs_to_save,
                                 &emulated_msrs,
                                 ARRAY_SIZE(emulated_msrs) * sizeof(u32)))
                        goto out;
index c1b6c232e02b180287e7b0e91a41ddb34c699689..616de4628d60d4e8aea197284a637ceced25dd73 100644 (file)
@@ -1361,7 +1361,7 @@ static inline int writeback(struct x86_emulate_ctxt *ctxt,
        return 0;
 }
 
-void toggle_interruptibility(struct x86_emulate_ctxt *ctxt, u32 mask)
+static void toggle_interruptibility(struct x86_emulate_ctxt *ctxt, u32 mask)
 {
        u32 int_shadow = kvm_x86_ops->get_interrupt_shadow(ctxt->vcpu, mask);
        /*
index 7bc65f0f62c4fc51607dd443641d1273cb4ebb03..d677fa9ca6506c4851f933ab5f3af6871cf79160 100644 (file)
@@ -22,7 +22,8 @@
  *
  * So how does the kernel know it's a Guest?  We'll see that later, but let's
  * just say that we end up here where we replace the native functions various
- * "paravirt" structures with our Guest versions, then boot like normal. :*/
+ * "paravirt" structures with our Guest versions, then boot like normal.
+:*/
 
 /*
  * Copyright (C) 2006, Rusty Russell <rusty@rustcorp.com.au> IBM Corporation.
@@ -74,7 +75,8 @@
  *
  * The Guest in our tale is a simple creature: identical to the Host but
  * behaving in simplified but equivalent ways.  In particular, the Guest is the
- * same kernel as the Host (or at least, built from the same source code). :*/
+ * same kernel as the Host (or at least, built from the same source code).
+:*/
 
 struct lguest_data lguest_data = {
        .hcall_status = { [0 ... LHCALL_RING_SIZE-1] = 0xFF },
@@ -85,7 +87,8 @@ struct lguest_data lguest_data = {
        .syscall_vec = SYSCALL_VECTOR,
 };
 
-/*G:037 async_hcall() is pretty simple: I'm quite proud of it really.  We have a
+/*G:037
+ * async_hcall() is pretty simple: I'm quite proud of it really.  We have a
  * ring buffer of stored hypercalls which the Host will run though next time we
  * do a normal hypercall.  Each entry in the ring has 5 slots for the hypercall
  * arguments, and a "hcall_status" word which is 0 if the call is ready to go,
@@ -94,7 +97,8 @@ struct lguest_data lguest_data = {
  * If we come around to a slot which hasn't been finished, then the table is
  * full and we just make the hypercall directly.  This has the nice side
  * effect of causing the Host to run all the stored calls in the ring buffer
- * which empties it for next time! */
+ * which empties it for next time!
+ */
 static void async_hcall(unsigned long call, unsigned long arg1,
                        unsigned long arg2, unsigned long arg3,
                        unsigned long arg4)
@@ -103,9 +107,11 @@ static void async_hcall(unsigned long call, unsigned long arg1,
        static unsigned int next_call;
        unsigned long flags;
 
-       /* Disable interrupts if not already disabled: we don't want an
+       /*
+        * Disable interrupts if not already disabled: we don't want an
         * interrupt handler making a hypercall while we're already doing
-        * one! */
+        * one!
+        */
        local_irq_save(flags);
        if (lguest_data.hcall_status[next_call] != 0xFF) {
                /* Table full, so do normal hcall which will flush table. */
@@ -125,8 +131,9 @@ static void async_hcall(unsigned long call, unsigned long arg1,
        local_irq_restore(flags);
 }
 
-/*G:035 Notice the lazy_hcall() above, rather than hcall().  This is our first
- * real optimization trick!
+/*G:035
+ * Notice the lazy_hcall() above, rather than hcall().  This is our first real
+ * optimization trick!
  *
  * When lazy_mode is set, it means we're allowed to defer all hypercalls and do
  * them as a batch when lazy_mode is eventually turned off.  Because hypercalls
@@ -136,7 +143,8 @@ static void async_hcall(unsigned long call, unsigned long arg1,
  * lguest_leave_lazy_mode().
  *
  * So, when we're in lazy mode, we call async_hcall() to store the call for
- * future processing: */
+ * future processing:
+ */
 static void lazy_hcall1(unsigned long call,
                       unsigned long arg1)
 {
@@ -146,6 +154,7 @@ static void lazy_hcall1(unsigned long call,
                async_hcall(call, arg1, 0, 0, 0);
 }
 
+/* You can imagine what lazy_hcall2, 3 and 4 look like. :*/
 static void lazy_hcall2(unsigned long call,
                       unsigned long arg1,
                       unsigned long arg2)
@@ -181,8 +190,10 @@ static void lazy_hcall4(unsigned long call,
 }
 #endif
 
-/* When lazy mode is turned off reset the per-cpu lazy mode variable and then
- * issue the do-nothing hypercall to flush any stored calls. */
+/*G:036
+ * When lazy mode is turned off reset the per-cpu lazy mode variable and then
+ * issue the do-nothing hypercall to flush any stored calls.
+:*/
 static void lguest_leave_lazy_mmu_mode(void)
 {
        kvm_hypercall0(LHCALL_FLUSH_ASYNC);
@@ -208,9 +219,11 @@ static void lguest_end_context_switch(struct task_struct *next)
  * check there before it tries to deliver an interrupt.
  */
 
-/* save_flags() is expected to return the processor state (ie. "flags").  The
+/*
+ * save_flags() is expected to return the processor state (ie. "flags").  The
  * flags word contains all kind of stuff, but in practice Linux only cares
- * about the interrupt flag.  Our "save_flags()" just returns that. */
+ * about the interrupt flag.  Our "save_flags()" just returns that.
+ */
 static unsigned long save_fl(void)
 {
        return lguest_data.irq_enabled;
@@ -222,13 +235,15 @@ static void irq_disable(void)
        lguest_data.irq_enabled = 0;
 }
 
-/* Let's pause a moment.  Remember how I said these are called so often?
+/*
+ * Let's pause a moment.  Remember how I said these are called so often?
  * Jeremy Fitzhardinge optimized them so hard early in 2009 that he had to
  * break some rules.  In particular, these functions are assumed to save their
  * own registers if they need to: normal C functions assume they can trash the
  * eax register.  To use normal C functions, we use
  * PV_CALLEE_SAVE_REGS_THUNK(), which pushes %eax onto the stack, calls the
- * C function, then restores it. */
+ * C function, then restores it.
+ */
 PV_CALLEE_SAVE_REGS_THUNK(save_fl);
 PV_CALLEE_SAVE_REGS_THUNK(irq_disable);
 /*:*/
@@ -237,18 +252,18 @@ PV_CALLEE_SAVE_REGS_THUNK(irq_disable);
 extern void lg_irq_enable(void);
 extern void lg_restore_fl(unsigned long flags);
 
-/*M:003 Note that we don't check for outstanding interrupts when we re-enable
- * them (or when we unmask an interrupt).  This seems to work for the moment,
- * since interrupts are rare and we'll just get the interrupt on the next timer
- * tick, but now we can run with CONFIG_NO_HZ, we should revisit this.  One way
- * would be to put the "irq_enabled" field in a page by itself, and have the
- * Host write-protect it when an interrupt comes in when irqs are disabled.
- * There will then be a page fault as soon as interrupts are re-enabled.
+/*M:003
+ * We could be more efficient in our checking of outstanding interrupts, rather
+ * than using a branch.  One way would be to put the "irq_enabled" field in a
+ * page by itself, and have the Host write-protect it when an interrupt comes
+ * in when irqs are disabled.  There will then be a page fault as soon as
+ * interrupts are re-enabled.
  *
  * A better method is to implement soft interrupt disable generally for x86:
  * instead of disabling interrupts, we set a flag.  If an interrupt does come
  * in, we then disable them for real.  This is uncommon, so we could simply use
- * a hypercall for interrupt control and not worry about efficiency. :*/
+ * a hypercall for interrupt control and not worry about efficiency.
+:*/
 
 /*G:034
  * The Interrupt Descriptor Table (IDT).
@@ -261,10 +276,12 @@ extern void lg_restore_fl(unsigned long flags);
 static void lguest_write_idt_entry(gate_desc *dt,
                                   int entrynum, const gate_desc *g)
 {
-       /* The gate_desc structure is 8 bytes long: we hand it to the Host in
+       /*
+        * The gate_desc structure is 8 bytes long: we hand it to the Host in
         * two 32-bit chunks.  The whole 32-bit kernel used to hand descriptors
         * around like this; typesafety wasn't a big concern in Linux's early
-        * years. */
+        * years.
+        */
        u32 *desc = (u32 *)g;
        /* Keep the local copy up to date. */
        native_write_idt_entry(dt, entrynum, g);
@@ -272,9 +289,11 @@ static void lguest_write_idt_entry(gate_desc *dt,
        kvm_hypercall3(LHCALL_LOAD_IDT_ENTRY, entrynum, desc[0], desc[1]);
 }
 
-/* Changing to a different IDT is very rare: we keep the IDT up-to-date every
+/*
+ * Changing to a different IDT is very rare: we keep the IDT up-to-date every
  * time it is written, so we can simply loop through all entries and tell the
- * Host about them. */
+ * Host about them.
+ */
 static void lguest_load_idt(const struct desc_ptr *desc)
 {
        unsigned int i;
@@ -305,9 +324,11 @@ static void lguest_load_gdt(const struct desc_ptr *desc)
                kvm_hypercall3(LHCALL_LOAD_GDT_ENTRY, i, gdt[i].a, gdt[i].b);
 }
 
-/* For a single GDT entry which changes, we do the lazy thing: alter our GDT,
+/*
+ * For a single GDT entry which changes, we do the lazy thing: alter our GDT,
  * then tell the Host to reload the entire thing.  This operation is so rare
- * that this naive implementation is reasonable. */
+ * that this naive implementation is reasonable.
+ */
 static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum,
                                   const void *desc, int type)
 {
@@ -317,29 +338,36 @@ static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum,
                       dt[entrynum].a, dt[entrynum].b);
 }
 
-/* OK, I lied.  There are three "thread local storage" GDT entries which change
+/*
+ * OK, I lied.  There are three "thread local storage" GDT entries which change
  * on every context switch (these three entries are how glibc implements
- * __thread variables).  So we have a hypercall specifically for this case. */
+ * __thread variables).  So we have a hypercall specifically for this case.
+ */
 static void lguest_load_tls(struct thread_struct *t, unsigned int cpu)
 {
-       /* There's one problem which normal hardware doesn't have: the Host
+       /*
+        * There's one problem which normal hardware doesn't have: the Host
         * can't handle us removing entries we're currently using.  So we clear
-        * the GS register here: if it's needed it'll be reloaded anyway. */
+        * the GS register here: if it's needed it'll be reloaded anyway.
+        */
        lazy_load_gs(0);
        lazy_hcall2(LHCALL_LOAD_TLS, __pa(&t->tls_array), cpu);
 }
 
-/*G:038 That's enough excitement for now, back to ploughing through each of
- * the different pv_ops structures (we're about 1/3 of the way through).
+/*G:038
+ * That's enough excitement for now, back to ploughing through each of the
+ * different pv_ops structures (we're about 1/3 of the way through).
  *
  * This is the Local Descriptor Table, another weird Intel thingy.  Linux only
  * uses this for some strange applications like Wine.  We don't do anything
- * here, so they'll get an informative and friendly Segmentation Fault. */
+ * here, so they'll get an informative and friendly Segmentation Fault.
+ */
 static void lguest_set_ldt(const void *addr, unsigned entries)
 {
 }
 
-/* This loads a GDT entry into the "Task Register": that entry points to a
+/*
+ * This loads a GDT entry into the "Task Register": that entry points to a
  * structure called the Task State Segment.  Some comments scattered though the
  * kernel code indicate that this used for task switching in ages past, along
  * with blood sacrifice and astrology.
@@ -347,19 +375,21 @@ static void lguest_set_ldt(const void *addr, unsigned entries)
  * Now there's nothing interesting in here that we don't get told elsewhere.
  * But the native version uses the "ltr" instruction, which makes the Host
  * complain to the Guest about a Segmentation Fault and it'll oops.  So we
- * override the native version with a do-nothing version. */
+ * override the native version with a do-nothing version.
+ */
 static void lguest_load_tr_desc(void)
 {
 }
 
-/* The "cpuid" instruction is a way of querying both the CPU identity
+/*
+ * The "cpuid" instruction is a way of querying both the CPU identity
  * (manufacturer, model, etc) and its features.  It was introduced before the
  * Pentium in 1993 and keeps getting extended by both Intel, AMD and others.
  * As you might imagine, after a decade and a half this treatment, it is now a
  * giant ball of hair.  Its entry in the current Intel manual runs to 28 pages.
  *
  * This instruction even it has its own Wikipedia entry.  The Wikipedia entry
- * has been translated into 4 languages.  I am not making this up!
+ * has been translated into 5 languages.  I am not making this up!
  *
  * We could get funky here and identify ourselves as "GenuineLguest", but
  * instead we just use the real "cpuid" instruction.  Then I pretty much turned
@@ -371,7 +401,8 @@ static void lguest_load_tr_desc(void)
  * Replacing the cpuid so we can turn features off is great for the kernel, but
  * anyone (including userspace) can just use the raw "cpuid" instruction and
  * the Host won't even notice since it isn't privileged.  So we try not to get
- * too worked up about it. */
+ * too worked up about it.
+ */
 static void lguest_cpuid(unsigned int *ax, unsigned int *bx,
                         unsigned int *cx, unsigned int *dx)
 {
@@ -379,38 +410,63 @@ static void lguest_cpuid(unsigned int *ax, unsigned int *bx,
 
        native_cpuid(ax, bx, cx, dx);
        switch (function) {
-       case 1: /* Basic feature request. */
-               /* We only allow kernel to see SSE3, CMPXCHG16B and SSSE3 */
+       /*
+        * CPUID 0 gives the highest legal CPUID number (and the ID string).
+        * We futureproof our code a little by sticking to known CPUID values.
+        */
+       case 0:
+               if (*ax > 5)
+                       *ax = 5;
+               break;
+
+       /*
+        * CPUID 1 is a basic feature request.
+        *
+        * CX: we only allow kernel to see SSE3, CMPXCHG16B and SSSE3
+        * DX: SSE, SSE2, FXSR, MMX, CMOV, CMPXCHG8B, TSC, FPU and PAE.
+        */
+       case 1:
                *cx &= 0x00002201;
-               /* SSE, SSE2, FXSR, MMX, CMOV, CMPXCHG8B, TSC, FPU, PAE. */
                *dx &= 0x07808151;
-               /* The Host can do a nice optimization if it knows that the
+               /*
+                * The Host can do a nice optimization if it knows that the
                 * kernel mappings (addresses above 0xC0000000 or whatever
                 * PAGE_OFFSET is set to) haven't changed.  But Linux calls
                 * flush_tlb_user() for both user and kernel mappings unless
-                * the Page Global Enable (PGE) feature bit is set. */
+                * the Page Global Enable (PGE) feature bit is set.
+                */
                *dx |= 0x00002000;
-               /* We also lie, and say we're family id 5.  6 or greater
+               /*
+                * We also lie, and say we're family id 5.  6 or greater
                 * leads to a rdmsr in early_init_intel which we can't handle.
-                * Family ID is returned as bits 8-12 in ax. */
+                * Family ID is returned as bits 8-12 in ax.
+                */
                *ax &= 0xFFFFF0FF;
                *ax |= 0x00000500;
                break;
+       /*
+        * 0x80000000 returns the highest Extended Function, so we futureproof
+        * like we do above by limiting it to known fields.
+        */
        case 0x80000000:
-               /* Futureproof this a little: if they ask how much extended
-                * processor information there is, limit it to known fields. */
                if (*ax > 0x80000008)
                        *ax = 0x80000008;
                break;
+
+       /*
+        * PAE systems can mark pages as non-executable.  Linux calls this the
+        * NX bit.  Intel calls it XD (eXecute Disable), AMD EVP (Enhanced
+        * Virus Protection).  We just switch turn if off here, since we don't
+        * support it.
+        */
        case 0x80000001:
-               /* Here we should fix nx cap depending on host. */
-               /* For this version of PAE, we just clear NX bit. */
                *dx &= ~(1 << 20);
                break;
        }
 }
 
-/* Intel has four control registers, imaginatively named cr0, cr2, cr3 and cr4.
+/*
+ * Intel has four control registers, imaginatively named cr0, cr2, cr3 and cr4.
  * I assume there's a cr1, but it hasn't bothered us yet, so we'll not bother
  * it.  The Host needs to know when the Guest wants to change them, so we have
  * a whole series of functions like read_cr0() and write_cr0().
@@ -425,7 +481,8 @@ static void lguest_cpuid(unsigned int *ax, unsigned int *bx,
  * name like "FPUTRAP bit" be a little less cryptic?
  *
  * We store cr0 locally because the Host never changes it.  The Guest sometimes
- * wants to read it and we'd prefer not to bother the Host unnecessarily. */
+ * wants to read it and we'd prefer not to bother the Host unnecessarily.
+ */
 static unsigned long current_cr0;
 static void lguest_write_cr0(unsigned long val)
 {
@@ -438,18 +495,22 @@ static unsigned long lguest_read_cr0(void)
        return current_cr0;
 }
 
-/* Intel provided a special instruction to clear the TS bit for people too cool
+/*
+ * Intel provided a special instruction to clear the TS bit for people too cool
  * to use write_cr0() to do it.  This "clts" instruction is faster, because all
- * the vowels have been optimized out. */
+ * the vowels have been optimized out.
+ */
 static void lguest_clts(void)
 {
        lazy_hcall1(LHCALL_TS, 0);
        current_cr0 &= ~X86_CR0_TS;
 }
 
-/* cr2 is the virtual address of the last page fault, which the Guest only ever
+/*
+ * cr2 is the virtual address of the last page fault, which the Guest only ever
  * reads.  The Host kindly writes this into our "struct lguest_data", so we
- * just read it out of there. */
+ * just read it out of there.
+ */
 static unsigned long lguest_read_cr2(void)
 {
        return lguest_data.cr2;
@@ -458,10 +519,12 @@ static unsigned long lguest_read_cr2(void)
 /* See lguest_set_pte() below. */
 static bool cr3_changed = false;
 
-/* cr3 is the current toplevel pagetable page: the principle is the same as
+/*
+ * cr3 is the current toplevel pagetable page: the principle is the same as
  * cr0.  Keep a local copy, and tell the Host when it changes.  The only
  * difference is that our local copy is in lguest_data because the Host needs
- * to set it upon our initial hypercall. */
+ * to set it upon our initial hypercall.
+ */
 static void lguest_write_cr3(unsigned long cr3)
 {
        lguest_data.pgdir = cr3;
@@ -506,7 +569,7 @@ static void lguest_write_cr4(unsigned long val)
  * cr3 ---> +---------+
  *         |      --------->+---------+
  *         |         |      | PADDR1  |
- *       Top-level   |      | PADDR2  |
+ *       Mid-level   |      | PADDR2  |
  *       (PMD) page  |      |         |
  *         |         |    Lower-level |
  *         |         |    (PTE) page  |
@@ -526,21 +589,62 @@ static void lguest_write_cr4(unsigned long val)
  *    Index into top     Index into second      Offset within page
  *  page directory page    pagetable page
  *
- * The kernel spends a lot of time changing both the top-level page directory
- * and lower-level pagetable pages.  The Guest doesn't know physical addresses,
- * so while it maintains these page tables exactly like normal, it also needs
- * to keep the Host informed whenever it makes a change: the Host will create
- * the real page tables based on the Guests'.
+ * Now, unfortunately, this isn't the whole story: Intel added Physical Address
+ * Extension (PAE) to allow 32 bit systems to use 64GB of memory (ie. 36 bits).
+ * These are held in 64-bit page table entries, so we can now only fit 512
+ * entries in a page, and the neat three-level tree breaks down.
+ *
+ * The result is a four level page table:
+ *
+ * cr3 --> [ 4 Upper  ]
+ *        [   Level  ]
+ *        [  Entries ]
+ *        [(PUD Page)]---> +---------+
+ *                         |      --------->+---------+
+ *                         |         |      | PADDR1  |
+ *                       Mid-level   |      | PADDR2  |
+ *                       (PMD) page  |      |         |
+ *                         |         |    Lower-level |
+ *                         |         |    (PTE) page  |
+ *                         |         |      |         |
+ *                           ....               ....
+ *
+ *
+ * And the virtual address is decoded as:
+ *
+ *         1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ *      |<-2->|<--- 9 bits ---->|<---- 9 bits --->|<------ 12 bits ------>|
+ * Index into    Index into mid    Index into lower    Offset within page
+ * top entries   directory page     pagetable page
+ *
+ * It's too hard to switch between these two formats at runtime, so Linux only
+ * supports one or the other depending on whether CONFIG_X86_PAE is set.  Many
+ * distributions turn it on, and not just for people with silly amounts of
+ * memory: the larger PTE entries allow room for the NX bit, which lets the
+ * kernel disable execution of pages and increase security.
+ *
+ * This was a problem for lguest, which couldn't run on these distributions;
+ * then Matias Zabaljauregui figured it all out and implemented it, and only a
+ * handful of puppies were crushed in the process!
+ *
+ * Back to our point: the kernel spends a lot of time changing both the
+ * top-level page directory and lower-level pagetable pages.  The Guest doesn't
+ * know physical addresses, so while it maintains these page tables exactly
+ * like normal, it also needs to keep the Host informed whenever it makes a
+ * change: the Host will create the real page tables based on the Guests'.
  */
 
-/* The Guest calls this to set a second-level entry (pte), ie. to map a page
- * into a process' address space.  We set the entry then tell the Host the
- * toplevel and address this corresponds to.  The Guest uses one pagetable per
- * process, so we need to tell the Host which one we're changing (mm->pgd). */
+/*
+ * The Guest calls this after it has set a second-level entry (pte), ie. to map
+ * a page into a process' address space.  Wetell the Host the toplevel and
+ * address this corresponds to.  The Guest uses one pagetable per process, so
+ * we need to tell the Host which one we're changing (mm->pgd).
+ */
 static void lguest_pte_update(struct mm_struct *mm, unsigned long addr,
                               pte_t *ptep)
 {
 #ifdef CONFIG_X86_PAE
+       /* PAE needs to hand a 64 bit page table entry, so it uses two args. */
        lazy_hcall4(LHCALL_SET_PTE, __pa(mm->pgd), addr,
                    ptep->pte_low, ptep->pte_high);
 #else
@@ -548,6 +652,7 @@ static void lguest_pte_update(struct mm_struct *mm, unsigned long addr,
 #endif
 }
 
+/* This is the "set and update" combo-meal-deal version. */
 static void lguest_set_pte_at(struct mm_struct *mm, unsigned long addr,
                              pte_t *ptep, pte_t pteval)
 {
@@ -555,10 +660,13 @@ static void lguest_set_pte_at(struct mm_struct *mm, unsigned long addr,
        lguest_pte_update(mm, addr, ptep);
 }
 
-/* The Guest calls lguest_set_pud to set a top-level entry and lguest_set_pmd
+/*
+ * The Guest calls lguest_set_pud to set a top-level entry and lguest_set_pmd
  * to set a middle-level entry when PAE is activated.
+ *
  * Again, we set the entry then tell the Host which page we changed,
- * and the index of the entry we changed. */
+ * and the index of the entry we changed.
+ */
 #ifdef CONFIG_X86_PAE
 static void lguest_set_pud(pud_t *pudp, pud_t pudval)
 {
@@ -577,8 +685,7 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)
 }
 #else
 
-/* The Guest calls lguest_set_pmd to set a top-level entry when PAE is not
- * activated. */
+/* The Guest calls lguest_set_pmd to set a top-level entry when !PAE. */
 static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)
 {
        native_set_pmd(pmdp, pmdval);
@@ -587,7 +694,8 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)
 }
 #endif
 
-/* There are a couple of legacy places where the kernel sets a PTE, but we
+/*
+ * There are a couple of legacy places where the kernel sets a PTE, but we
  * don't know the top level any more.  This is useless for us, since we don't
  * know which pagetable is changing or what address, so we just tell the Host
  * to forget all of them.  Fortunately, this is very rare.
@@ -595,7 +703,8 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)
  * ... except in early boot when the kernel sets up the initial pagetables,
  * which makes booting astonishingly slow: 1.83 seconds!  So we don't even tell
  * the Host anything changed until we've done the first page table switch,
- * which brings boot back to 0.25 seconds. */
+ * which brings boot back to 0.25 seconds.
+ */
 static void lguest_set_pte(pte_t *ptep, pte_t pteval)
 {
        native_set_pte(ptep, pteval);
@@ -604,6 +713,11 @@ static void lguest_set_pte(pte_t *ptep, pte_t pteval)
 }
 
 #ifdef CONFIG_X86_PAE
+/*
+ * With 64-bit PTE values, we need to be careful setting them: if we set 32
+ * bits at a time, the hardware could see a weird half-set entry.  These
+ * versions ensure we update all 64 bits at once.
+ */
 static void lguest_set_pte_atomic(pte_t *ptep, pte_t pte)
 {
        native_set_pte_atomic(ptep, pte);
@@ -611,19 +725,21 @@ static void lguest_set_pte_atomic(pte_t *ptep, pte_t pte)
                lazy_hcall1(LHCALL_FLUSH_TLB, 1);
 }
 
-void lguest_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+static void lguest_pte_clear(struct mm_struct *mm, unsigned long addr,
+                            pte_t *ptep)
 {
        native_pte_clear(mm, addr, ptep);
        lguest_pte_update(mm, addr, ptep);
 }
 
-void lguest_pmd_clear(pmd_t *pmdp)
+static void lguest_pmd_clear(pmd_t *pmdp)
 {
        lguest_set_pmd(pmdp, __pmd(0));
 }
 #endif
 
-/* Unfortunately for Lguest, the pv_mmu_ops for page tables were based on
+/*
+ * Unfortunately for Lguest, the pv_mmu_ops for page tables were based on
  * native page table operations.  On native hardware you can set a new page
  * table entry whenever you want, but if you want to remove one you have to do
  * a TLB flush (a TLB is a little cache of page table entries kept by the CPU).
@@ -632,24 +748,29 @@ void lguest_pmd_clear(pmd_t *pmdp)
  * called when a valid entry is written, not when it's removed (ie. marked not
  * present).  Instead, this is where we come when the Guest wants to remove a
  * page table entry: we tell the Host to set that entry to 0 (ie. the present
- * bit is zero). */
+ * bit is zero).
+ */
 static void lguest_flush_tlb_single(unsigned long addr)
 {
        /* Simply set it to zero: if it was not, it will fault back in. */
        lazy_hcall3(LHCALL_SET_PTE, lguest_data.pgdir, addr, 0);
 }
 
-/* This is what happens after the Guest has removed a large number of entries.
+/*
+ * This is what happens after the Guest has removed a large number of entries.
  * This tells the Host that any of the page table entries for userspace might
- * have changed, ie. virtual addresses below PAGE_OFFSET. */
+ * have changed, ie. virtual addresses below PAGE_OFFSET.
+ */
 static void lguest_flush_tlb_user(void)
 {
        lazy_hcall1(LHCALL_FLUSH_TLB, 0);
 }
 
-/* This is called when the kernel page tables have changed.  That's not very
+/*
+ * This is called when the kernel page tables have changed.  That's not very
  * common (unless the Guest is using highmem, which makes the Guest extremely
- * slow), so it's worth separating this from the user flushing above. */
+ * slow), so it's worth separating this from the user flushing above.
+ */
 static void lguest_flush_tlb_kernel(void)
 {
        lazy_hcall1(LHCALL_FLUSH_TLB, 1);
@@ -686,26 +807,38 @@ static struct irq_chip lguest_irq_controller = {
        .unmask         = enable_lguest_irq,
 };
 
-/* This sets up the Interrupt Descriptor Table (IDT) entry for each hardware
+/*
+ * This sets up the Interrupt Descriptor Table (IDT) entry for each hardware
  * interrupt (except 128, which is used for system calls), and then tells the
  * Linux infrastructure that each interrupt is controlled by our level-based
- * lguest interrupt controller. */
+ * lguest interrupt controller.
+ */
 static void __init lguest_init_IRQ(void)
 {
        unsigned int i;
 
        for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {
-               /* Some systems map "vectors" to interrupts weirdly.  Lguest has
-                * a straightforward 1 to 1 mapping, so force that here. */
+               /* Some systems map "vectors" to interrupts weirdly.  Not us! */
                __get_cpu_var(vector_irq)[i] = i - FIRST_EXTERNAL_VECTOR;
                if (i != SYSCALL_VECTOR)
                        set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]);
        }
-       /* This call is required to set up for 4k stacks, where we have
-        * separate stacks for hard and soft interrupts. */
+
+       /*
+        * This call is required to set up for 4k stacks, where we have
+        * separate stacks for hard and soft interrupts.
+        */
        irq_ctx_init(smp_processor_id());
 }
 
+/*
+ * With CONFIG_SPARSE_IRQ, interrupt descriptors are allocated as-needed, so
+ * rather than set them in lguest_init_IRQ we are called here every time an
+ * lguest device needs an interrupt.
+ *
+ * FIXME: irq_to_desc_alloc_node() can fail due to lack of memory, we should
+ * pass that up!
+ */
 void lguest_setup_irq(unsigned int irq)
 {
        irq_to_desc_alloc_node(irq, 0);
@@ -724,31 +857,39 @@ static unsigned long lguest_get_wallclock(void)
        return lguest_data.time.tv_sec;
 }
 
-/* The TSC is an Intel thing called the Time Stamp Counter.  The Host tells us
+/*
+ * The TSC is an Intel thing called the Time Stamp Counter.  The Host tells us
  * what speed it runs at, or 0 if it's unusable as a reliable clock source.
  * This matches what we want here: if we return 0 from this function, the x86
- * TSC clock will give up and not register itself. */
+ * TSC clock will give up and not register itself.
+ */
 static unsigned long lguest_tsc_khz(void)
 {
        return lguest_data.tsc_khz;
 }
 
-/* If we can't use the TSC, the kernel falls back to our lower-priority
- * "lguest_clock", where we read the time value given to us by the Host. */
+/*
+ * If we can't use the TSC, the kernel falls back to our lower-priority
+ * "lguest_clock", where we read the time value given to us by the Host.
+ */
 static cycle_t lguest_clock_read(struct clocksource *cs)
 {
        unsigned long sec, nsec;
 
-       /* Since the time is in two parts (seconds and nanoseconds), we risk
+       /*
+        * Since the time is in two parts (seconds and nanoseconds), we risk
         * reading it just as it's changing from 99 & 0.999999999 to 100 and 0,
         * and getting 99 and 0.  As Linux tends to come apart under the stress
-        * of time travel, we must be careful: */
+        * of time travel, we must be careful:
+        */
        do {
                /* First we read the seconds part. */
                sec = lguest_data.time.tv_sec;
-               /* This read memory barrier tells the compiler and the CPU that
+               /*
+                * This read memory barrier tells the compiler and the CPU that
                 * this can't be reordered: we have to complete the above
-                * before going on. */
+                * before going on.
+                */
                rmb();
                /* Now we read the nanoseconds part. */
                nsec = lguest_data.time.tv_nsec;
@@ -772,9 +913,11 @@ static struct clocksource lguest_clock = {
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-/* We also need a "struct clock_event_device": Linux asks us to set it to go
+/*
+ * We also need a "struct clock_event_device": Linux asks us to set it to go
  * off some time in the future.  Actually, James Morris figured all this out, I
- * just applied the patch. */
+ * just applied the patch.
+ */
 static int lguest_clockevent_set_next_event(unsigned long delta,
                                            struct clock_event_device *evt)
 {
@@ -824,8 +967,10 @@ static struct clock_event_device lguest_clockevent = {
        .max_delta_ns           = LG_CLOCK_MAX_DELTA,
 };
 
-/* This is the Guest timer interrupt handler (hardware interrupt 0).  We just
- * call the clockevent infrastructure and it does whatever needs doing. */
+/*
+ * This is the Guest timer interrupt handler (hardware interrupt 0).  We just
+ * call the clockevent infrastructure and it does whatever needs doing.
+ */
 static void lguest_time_irq(unsigned int irq, struct irq_desc *desc)
 {
        unsigned long flags;
@@ -836,10 +981,12 @@ static void lguest_time_irq(unsigned int irq, struct irq_desc *desc)
        local_irq_restore(flags);
 }
 
-/* At some point in the boot process, we get asked to set up our timing
+/*
+ * At some point in the boot process, we get asked to set up our timing
  * infrastructure.  The kernel doesn't expect timer interrupts before this, but
  * we cleverly initialized the "blocked_interrupts" field of "struct
- * lguest_data" so that timer interrupts were blocked until now. */
+ * lguest_data" so that timer interrupts were blocked until now.
+ */
 static void lguest_time_init(void)
 {
        /* Set up the timer interrupt (0) to go to our simple timer routine */
@@ -863,14 +1010,16 @@ static void lguest_time_init(void)
  * to work.  They're pretty simple.
  */
 
-/* The Guest needs to tell the Host what stack it expects traps to use.  For
+/*
+ * The Guest needs to tell the Host what stack it expects traps to use.  For
  * native hardware, this is part of the Task State Segment mentioned above in
  * lguest_load_tr_desc(), but to help hypervisors there's this special call.
  *
  * We tell the Host the segment we want to use (__KERNEL_DS is the kernel data
  * segment), the privilege level (we're privilege level 1, the Host is 0 and
  * will not tolerate us trying to use that), the stack pointer, and the number
- * of pages in the stack. */
+ * of pages in the stack.
+ */
 static void lguest_load_sp0(struct tss_struct *tss,
                            struct thread_struct *thread)
 {
@@ -884,7 +1033,8 @@ static void lguest_set_debugreg(int regno, unsigned long value)
        /* FIXME: Implement */
 }
 
-/* There are times when the kernel wants to make sure that no memory writes are
+/*
+ * There are times when the kernel wants to make sure that no memory writes are
  * caught in the cache (that they've all reached real hardware devices).  This
  * doesn't matter for the Guest which has virtual hardware.
  *
@@ -898,11 +1048,13 @@ static void lguest_wbinvd(void)
 {
 }
 
-/* If the Guest expects to have an Advanced Programmable Interrupt Controller,
+/*
+ * If the Guest expects to have an Advanced Programmable Interrupt Controller,
  * we play dumb by ignoring writes and returning 0 for reads.  So it's no
  * longer Programmable nor Controlling anything, and I don't think 8 lines of
  * code qualifies for Advanced.  It will also never interrupt anything.  It
- * does, however, allow us to get through the Linux boot code. */
+ * does, however, allow us to get through the Linux boot code.
+ */
 #ifdef CONFIG_X86_LOCAL_APIC
 static void lguest_apic_write(u32 reg, u32 v)
 {
@@ -951,11 +1103,13 @@ static void lguest_safe_halt(void)
        kvm_hypercall0(LHCALL_HALT);
 }
 
-/* The SHUTDOWN hypercall takes a string to describe what's happening, and
+/*
+ * The SHUTDOWN hypercall takes a string to describe what's happening, and
  * an argument which says whether this to restart (reboot) the Guest or not.
  *
  * Note that the Host always prefers that the Guest speak in physical addresses
- * rather than virtual addresses, so we use __pa() here. */
+ * rather than virtual addresses, so we use __pa() here.
+ */
 static void lguest_power_off(void)
 {
        kvm_hypercall2(LHCALL_SHUTDOWN, __pa("Power down"),
@@ -986,8 +1140,10 @@ static __init char *lguest_memory_setup(void)
         * nice to move it back to lguest_init.  Patch welcome... */
        atomic_notifier_chain_register(&panic_notifier_list, &paniced);
 
-       /* The Linux bootloader header contains an "e820" memory map: the
-        * Launcher populated the first entry with our memory limit. */
+       /*
+        *The Linux bootloader header contains an "e820" memory map: the
+        * Launcher populated the first entry with our memory limit.
+        */
        e820_add_region(boot_params.e820_map[0].addr,
                          boot_params.e820_map[0].size,
                          boot_params.e820_map[0].type);
@@ -996,16 +1152,17 @@ static __init char *lguest_memory_setup(void)
        return "LGUEST";
 }
 
-/* We will eventually use the virtio console device to produce console output,
+/*
+ * We will eventually use the virtio console device to produce console output,
  * but before that is set up we use LHCALL_NOTIFY on normal memory to produce
- * console output. */
+ * console output.
+ */
 static __init int early_put_chars(u32 vtermno, const char *buf, int count)
 {
        char scratch[17];
        unsigned int len = count;
 
-       /* We use a nul-terminated string, so we have to make a copy.  Icky,
-        * huh? */
+       /* We use a nul-terminated string, so we make a copy.  Icky, huh? */
        if (len > sizeof(scratch) - 1)
                len = sizeof(scratch) - 1;
        scratch[len] = '\0';
@@ -1016,8 +1173,10 @@ static __init int early_put_chars(u32 vtermno, const char *buf, int count)
        return len;
 }
 
-/* Rebooting also tells the Host we're finished, but the RESTART flag tells the
- * Launcher to reboot us. */
+/*
+ * Rebooting also tells the Host we're finished, but the RESTART flag tells the
+ * Launcher to reboot us.
+ */
 static void lguest_restart(char *reason)
 {
        kvm_hypercall2(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART);
@@ -1044,7 +1203,8 @@ static void lguest_restart(char *reason)
  * fit comfortably.
  *
  * First we need assembly templates of each of the patchable Guest operations,
- * and these are in i386_head.S. */
+ * and these are in i386_head.S.
+ */
 
 /*G:060 We construct a table from the assembler templates: */
 static const struct lguest_insns
@@ -1055,9 +1215,11 @@ static const struct lguest_insns
        [PARAVIRT_PATCH(pv_irq_ops.save_fl)] = { lgstart_pushf, lgend_pushf },
 };
 
-/* Now our patch routine is fairly simple (based on the native one in
+/*
+ * Now our patch routine is fairly simple (based on the native one in
  * paravirt.c).  If we have a replacement, we copy it in and return how much of
- * the available space we used. */
+ * the available space we used.
+ */
 static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf,
                             unsigned long addr, unsigned len)
 {
@@ -1069,8 +1231,7 @@ static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf,
 
        insn_len = lguest_insns[type].end - lguest_insns[type].start;
 
-       /* Similarly if we can't fit replacement (shouldn't happen, but let's
-        * be thorough). */
+       /* Similarly if it can't fit (doesn't happen, but let's be thorough). */
        if (len < insn_len)
                return paravirt_patch_default(type, clobber, ibuf, addr, len);
 
@@ -1079,22 +1240,28 @@ static unsigned lguest_patch(u8 type, u16 clobber, void *ibuf,
        return insn_len;
 }
 
-/*G:030 Once we get to lguest_init(), we know we're a Guest.  The various
+/*G:029
+ * Once we get to lguest_init(), we know we're a Guest.  The various
  * pv_ops structures in the kernel provide points for (almost) every routine we
- * have to override to avoid privileged instructions. */
+ * have to override to avoid privileged instructions.
+ */
 __init void lguest_init(void)
 {
-       /* We're under lguest, paravirt is enabled, and we're running at
-        * privilege level 1, not 0 as normal. */
+       /* We're under lguest. */
        pv_info.name = "lguest";
+       /* Paravirt is enabled. */
        pv_info.paravirt_enabled = 1;
+       /* We're running at privilege level 1, not 0 as normal. */
        pv_info.kernel_rpl = 1;
+       /* Everyone except Xen runs with this set. */
        pv_info.shared_kernel_pmd = 1;
 
-       /* We set up all the lguest overrides for sensitive operations.  These
-        * are detailed with the operations themselves. */
+       /*
+        * We set up all the lguest overrides for sensitive operations.  These
+        * are detailed with the operations themselves.
+        */
 
-       /* interrupt-related operations */
+       /* Interrupt-related operations */
        pv_irq_ops.init_IRQ = lguest_init_IRQ;
        pv_irq_ops.save_fl = PV_CALLEE_SAVE(save_fl);
        pv_irq_ops.restore_fl = __PV_IS_CALLEE_SAVE(lg_restore_fl);
@@ -1102,11 +1269,11 @@ __init void lguest_init(void)
        pv_irq_ops.irq_enable = __PV_IS_CALLEE_SAVE(lg_irq_enable);
        pv_irq_ops.safe_halt = lguest_safe_halt;
 
-       /* init-time operations */
+       /* Setup operations */
        pv_init_ops.memory_setup = lguest_memory_setup;
        pv_init_ops.patch = lguest_patch;
 
-       /* Intercepts of various cpu instructions */
+       /* Intercepts of various CPU instructions */
        pv_cpu_ops.load_gdt = lguest_load_gdt;
        pv_cpu_ops.cpuid = lguest_cpuid;
        pv_cpu_ops.load_idt = lguest_load_idt;
@@ -1127,7 +1294,7 @@ __init void lguest_init(void)
        pv_cpu_ops.start_context_switch = paravirt_start_context_switch;
        pv_cpu_ops.end_context_switch = lguest_end_context_switch;
 
-       /* pagetable management */
+       /* Pagetable management */
        pv_mmu_ops.write_cr3 = lguest_write_cr3;
        pv_mmu_ops.flush_tlb_user = lguest_flush_tlb_user;
        pv_mmu_ops.flush_tlb_single = lguest_flush_tlb_single;
@@ -1149,54 +1316,71 @@ __init void lguest_init(void)
        pv_mmu_ops.pte_update_defer = lguest_pte_update;
 
 #ifdef CONFIG_X86_LOCAL_APIC
-       /* apic read/write intercepts */
+       /* APIC read/write intercepts */
        set_lguest_basic_apic_ops();
 #endif
 
-       /* time operations */
+       /* Time operations */
        pv_time_ops.get_wallclock = lguest_get_wallclock;
        pv_time_ops.time_init = lguest_time_init;
        pv_time_ops.get_tsc_khz = lguest_tsc_khz;
 
-       /* Now is a good time to look at the implementations of these functions
-        * before returning to the rest of lguest_init(). */
+       /*
+        * Now is a good time to look at the implementations of these functions
+        * before returning to the rest of lguest_init().
+        */
 
-       /*G:070 Now we've seen all the paravirt_ops, we return to
+       /*G:070
+        * Now we've seen all the paravirt_ops, we return to
         * lguest_init() where the rest of the fairly chaotic boot setup
-        * occurs. */
+        * occurs.
+        */
 
-       /* The stack protector is a weird thing where gcc places a canary
+       /*
+        * The stack protector is a weird thing where gcc places a canary
         * value on the stack and then checks it on return.  This file is
         * compiled with -fno-stack-protector it, so we got this far without
         * problems.  The value of the canary is kept at offset 20 from the
         * %gs register, so we need to set that up before calling C functions
-        * in other files. */
+        * in other files.
+        */
        setup_stack_canary_segment(0);
-       /* We could just call load_stack_canary_segment(), but we might as
-        * call switch_to_new_gdt() which loads the whole table and sets up
-        * the per-cpu segment descriptor register %fs as well. */
+
+       /*
+        * We could just call load_stack_canary_segment(), but we might as well
+        * call switch_to_new_gdt() which loads the whole table and sets up the
+        * per-cpu segment descriptor register %fs as well.
+        */
        switch_to_new_gdt(0);
 
-       /* As described in head_32.S, we map the first 128M of memory. */
+       /* We actually boot with all memory mapped, but let's say 128MB. */
        max_pfn_mapped = (128*1024*1024) >> PAGE_SHIFT;
 
-       /* The Host<->Guest Switcher lives at the top of our address space, and
+       /*
+        * The Host<->Guest Switcher lives at the top of our address space, and
         * the Host told us how big it is when we made LGUEST_INIT hypercall:
-        * it put the answer in lguest_data.reserve_mem  */
+        * it put the answer in lguest_data.reserve_mem
+        */
        reserve_top_address(lguest_data.reserve_mem);
 
-       /* If we don't initialize the lock dependency checker now, it crashes
-        * paravirt_disable_iospace. */
+       /*
+        * If we don't initialize the lock dependency checker now, it crashes
+        * paravirt_disable_iospace.
+        */
        lockdep_init();
 
-       /* The IDE code spends about 3 seconds probing for disks: if we reserve
+       /*
+        * The IDE code spends about 3 seconds probing for disks: if we reserve
         * all the I/O ports up front it can't get them and so doesn't probe.
         * Other device drivers are similar (but less severe).  This cuts the
-        * kernel boot time on my machine from 4.1 seconds to 0.45 seconds. */
+        * kernel boot time on my machine from 4.1 seconds to 0.45 seconds.
+        */
        paravirt_disable_iospace();
 
-       /* This is messy CPU setup stuff which the native boot code does before
-        * start_kernel, so we have to do, too: */
+       /*
+        * This is messy CPU setup stuff which the native boot code does before
+        * start_kernel, so we have to do, too:
+        */
        cpu_detect(&new_cpu_data);
        /* head.S usually sets up the first capability word, so do it here. */
        new_cpu_data.x86_capability[0] = cpuid_edx(1);
@@ -1213,22 +1397,28 @@ __init void lguest_init(void)
        acpi_ht = 0;
 #endif
 
-       /* We set the preferred console to "hvc".  This is the "hypervisor
+       /*
+        * We set the preferred console to "hvc".  This is the "hypervisor
         * virtual console" driver written by the PowerPC people, which we also
-        * adapted for lguest's use. */
+        * adapted for lguest's use.
+        */
        add_preferred_console("hvc", 0, NULL);
 
        /* Register our very early console. */
        virtio_cons_early_init(early_put_chars);
 
-       /* Last of all, we set the power management poweroff hook to point to
+       /*
+        * Last of all, we set the power management poweroff hook to point to
         * the Guest routine to power off, and the reboot hook to our restart
-        * routine. */
+        * routine.
+        */
        pm_power_off = lguest_power_off;
        machine_ops.restart = lguest_restart;
 
-       /* Now we're set up, call i386_start_kernel() in head32.c and we proceed
-        * to boot as normal.  It never returns. */
+       /*
+        * Now we're set up, call i386_start_kernel() in head32.c and we proceed
+        * to boot as normal.  It never returns.
+        */
        i386_start_kernel();
 }
 /*
index a9c8cfe61cd4d48497a648538ce5b1c7d04e7cde..27eac0faee48eca0838970b2b1e7c64fb1a2c121 100644 (file)
@@ -5,7 +5,8 @@
 #include <asm/thread_info.h>
 #include <asm/processor-flags.h>
 
-/*G:020 Our story starts with the kernel booting into startup_32 in
+/*G:020
+ * Our story starts with the kernel booting into startup_32 in
  * arch/x86/kernel/head_32.S.  It expects a boot header, which is created by
  * the bootloader (the Launcher in our case).
  *
  * data without remembering to subtract __PAGE_OFFSET!
  *
  * The .section line puts this code in .init.text so it will be discarded after
- * boot. */
+ * boot.
+ */
 .section .init.text, "ax", @progbits
 ENTRY(lguest_entry)
-       /* We make the "initialization" hypercall now to tell the Host about
-        * us, and also find out where it put our page tables. */
+       /*
+        * We make the "initialization" hypercall now to tell the Host about
+        * us, and also find out where it put our page tables.
+        */
        movl $LHCALL_LGUEST_INIT, %eax
        movl $lguest_data - __PAGE_OFFSET, %ebx
        .byte 0x0f,0x01,0xc1 /* KVM_HYPERCALL */
@@ -33,13 +37,14 @@ ENTRY(lguest_entry)
        /* Set up the initial stack so we can run C code. */
        movl $(init_thread_union+THREAD_SIZE),%esp
 
-       /* Jumps are relative, and we're running __PAGE_OFFSET too low at the
-        * moment. */
+       /* Jumps are relative: we're running __PAGE_OFFSET too low. */
        jmp lguest_init+__PAGE_OFFSET
 
-/*G:055 We create a macro which puts the assembler code between lgstart_ and
- * lgend_ markers.  These templates are put in the .text section: they can't be
- * discarded after boot as we may need to patch modules, too. */
+/*G:055
+ * We create a macro which puts the assembler code between lgstart_ and lgend_
+ * markers.  These templates are put in the .text section: they can't be
+ * discarded after boot as we may need to patch modules, too.
+ */
 .text
 #define LGUEST_PATCH(name, insns...)                   \
        lgstart_##name: insns; lgend_##name:;           \
@@ -48,83 +53,103 @@ ENTRY(lguest_entry)
 LGUEST_PATCH(cli, movl $0, lguest_data+LGUEST_DATA_irq_enabled)
 LGUEST_PATCH(pushf, movl lguest_data+LGUEST_DATA_irq_enabled, %eax)
 
-/*G:033 But using those wrappers is inefficient (we'll see why that doesn't
- * matter for save_fl and irq_disable later).  If we write our routines
- * carefully in assembler, we can avoid clobbering any registers and avoid
- * jumping through the wrapper functions.
+/*G:033
+ * But using those wrappers is inefficient (we'll see why that doesn't matter
+ * for save_fl and irq_disable later).  If we write our routines carefully in
+ * assembler, we can avoid clobbering any registers and avoid jumping through
+ * the wrapper functions.
  *
  * I skipped over our first piece of assembler, but this one is worth studying
- * in a bit more detail so I'll describe in easy stages.  First, the routine
- * to enable interrupts: */
+ * in a bit more detail so I'll describe in easy stages.  First, the routine to
+ * enable interrupts:
+ */
 ENTRY(lg_irq_enable)
-       /* The reverse of irq_disable, this sets lguest_data.irq_enabled to
-        * X86_EFLAGS_IF (ie. "Interrupts enabled"). */
+       /*
+        * The reverse of irq_disable, this sets lguest_data.irq_enabled to
+        * X86_EFLAGS_IF (ie. "Interrupts enabled").
+        */
        movl $X86_EFLAGS_IF, lguest_data+LGUEST_DATA_irq_enabled
-       /* But now we need to check if the Host wants to know: there might have
+       /*
+        * But now we need to check if the Host wants to know: there might have
         * been interrupts waiting to be delivered, in which case it will have
         * set lguest_data.irq_pending to X86_EFLAGS_IF.  If it's not zero, we
-        * jump to send_interrupts, otherwise we're done. */
+        * jump to send_interrupts, otherwise we're done.
+        */
        testl $0, lguest_data+LGUEST_DATA_irq_pending
        jnz send_interrupts
-       /* One cool thing about x86 is that you can do many things without using
+       /*
+        * One cool thing about x86 is that you can do many things without using
         * a register.  In this case, the normal path hasn't needed to save or
-        * restore any registers at all! */
+        * restore any registers at all!
+        */
        ret
 send_interrupts:
-       /* OK, now we need a register: eax is used for the hypercall number,
+       /*
+        * OK, now we need a register: eax is used for the hypercall number,
         * which is LHCALL_SEND_INTERRUPTS.
         *
         * We used not to bother with this pending detection at all, which was
         * much simpler.  Sooner or later the Host would realize it had to
         * send us an interrupt.  But that turns out to make performance 7
         * times worse on a simple tcp benchmark.  So now we do this the hard
-        * way. */
+        * way.
+        */
        pushl %eax
        movl $LHCALL_SEND_INTERRUPTS, %eax
-       /* This is a vmcall instruction (same thing that KVM uses).  Older
+       /*
+        * This is a vmcall instruction (same thing that KVM uses).  Older
         * assembler versions might not know the "vmcall" instruction, so we
-        * create one manually here. */
+        * create one manually here.
+        */
        .byte 0x0f,0x01,0xc1 /* KVM_HYPERCALL */
+       /* Put eax back the way we found it. */
        popl %eax
        ret
 
-/* Finally, the "popf" or "restore flags" routine.  The %eax register holds the
+/*
+ * Finally, the "popf" or "restore flags" routine.  The %eax register holds the
  * flags (in practice, either X86_EFLAGS_IF or 0): if it's X86_EFLAGS_IF we're
- * enabling interrupts again, if it's 0 we're leaving them off. */
+ * enabling interrupts again, if it's 0 we're leaving them off.
+ */
 ENTRY(lg_restore_fl)
        /* This is just "lguest_data.irq_enabled = flags;" */
        movl %eax, lguest_data+LGUEST_DATA_irq_enabled
-       /* Now, if the %eax value has enabled interrupts and
+       /*
+        * Now, if the %eax value has enabled interrupts and
         * lguest_data.irq_pending is set, we want to tell the Host so it can
         * deliver any outstanding interrupts.  Fortunately, both values will
         * be X86_EFLAGS_IF (ie. 512) in that case, and the "testl"
         * instruction will AND them together for us.  If both are set, we
-        * jump to send_interrupts. */
+        * jump to send_interrupts.
+        */
        testl lguest_data+LGUEST_DATA_irq_pending, %eax
        jnz send_interrupts
        /* Again, the normal path has used no extra registers.  Clever, huh? */
        ret
+/*:*/
 
 /* These demark the EIP range where host should never deliver interrupts. */
 .global lguest_noirq_start
 .global lguest_noirq_end
 
-/*M:004 When the Host reflects a trap or injects an interrupt into the Guest,
- * it sets the eflags interrupt bit on the stack based on
- * lguest_data.irq_enabled, so the Guest iret logic does the right thing when
- * restoring it.  However, when the Host sets the Guest up for direct traps,
- * such as system calls, the processor is the one to push eflags onto the
- * stack, and the interrupt bit will be 1 (in reality, interrupts are always
- * enabled in the Guest).
+/*M:004
+ * When the Host reflects a trap or injects an interrupt into the Guest, it
+ * sets the eflags interrupt bit on the stack based on lguest_data.irq_enabled,
+ * so the Guest iret logic does the right thing when restoring it.  However,
+ * when the Host sets the Guest up for direct traps, such as system calls, the
+ * processor is the one to push eflags onto the stack, and the interrupt bit
+ * will be 1 (in reality, interrupts are always enabled in the Guest).
  *
  * This turns out to be harmless: the only trap which should happen under Linux
  * with interrupts disabled is Page Fault (due to our lazy mapping of vmalloc
  * regions), which has to be reflected through the Host anyway.  If another
  * trap *does* go off when interrupts are disabled, the Guest will panic, and
- * we'll never get to this iret! :*/
+ * we'll never get to this iret!
+:*/
 
-/*G:045 There is one final paravirt_op that the Guest implements, and glancing
- * at it you can see why I left it to last.  It's *cool*!  It's in *assembler*!
+/*G:045
+ * There is one final paravirt_op that the Guest implements, and glancing at it
+ * you can see why I left it to last.  It's *cool*!  It's in *assembler*!
  *
  * The "iret" instruction is used to return from an interrupt or trap.  The
  * stack looks like this:
@@ -148,15 +173,18 @@ ENTRY(lg_restore_fl)
  * return to userspace or wherever.  Our solution to this is to surround the
  * code with lguest_noirq_start: and lguest_noirq_end: labels.  We tell the
  * Host that it is *never* to interrupt us there, even if interrupts seem to be
- * enabled. */
+ * enabled.
+ */
 ENTRY(lguest_iret)
        pushl   %eax
        movl    12(%esp), %eax
 lguest_noirq_start:
-       /* Note the %ss: segment prefix here.  Normal data accesses use the
+       /*
+        * Note the %ss: segment prefix here.  Normal data accesses use the
         * "ds" segment, but that will have already been restored for whatever
         * we're returning to (such as userspace): we can't trust it.  The %ss:
-        * prefix makes sure we use the stack segment, which is still valid. */
+        * prefix makes sure we use the stack segment, which is still valid.
+        */
        movl    %eax,%ss:lguest_data+LGUEST_DATA_irq_enabled
        popl    %eax
        iret
index f9d35632666b06bb0b9bf072176777dbd94c39cc..07c31899c9c24b8f59d0d9c8bacf9c3dd56444da 100644 (file)
@@ -10,6 +10,7 @@ lib-y += usercopy_$(BITS).o getuser.o putuser.o
 lib-y += memcpy_$(BITS).o
 
 ifeq ($(CONFIG_X86_32),y)
+        obj-y += atomic64_32.o
         lib-y += checksum_32.o
         lib-y += strstr_32.o
         lib-y += semaphore_32.o string_32.o
diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c
new file mode 100644 (file)
index 0000000..824fa0b
--- /dev/null
@@ -0,0 +1,230 @@
+#include <linux/compiler.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+#include <asm/processor.h>
+#include <asm/cmpxchg.h>
+#include <asm/atomic.h>
+
+static noinline u64 cmpxchg8b(u64 *ptr, u64 old, u64 new)
+{
+       u32 low = new;
+       u32 high = new >> 32;
+
+       asm volatile(
+               LOCK_PREFIX "cmpxchg8b %1\n"
+                    : "+A" (old), "+m" (*ptr)
+                    :  "b" (low),  "c" (high)
+                    );
+       return old;
+}
+
+u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val)
+{
+       return cmpxchg8b(&ptr->counter, old_val, new_val);
+}
+EXPORT_SYMBOL(atomic64_cmpxchg);
+
+/**
+ * atomic64_xchg - xchg atomic64 variable
+ * @ptr:      pointer to type atomic64_t
+ * @new_val:  value to assign
+ *
+ * Atomically xchgs the value of @ptr to @new_val and returns
+ * the old value.
+ */
+u64 atomic64_xchg(atomic64_t *ptr, u64 new_val)
+{
+       /*
+        * Try first with a (possibly incorrect) assumption about
+        * what we have there. We'll do two loops most likely,
+        * but we'll get an ownership MESI transaction straight away
+        * instead of a read transaction followed by a
+        * flush-for-ownership transaction:
+        */
+       u64 old_val, real_val = 0;
+
+       do {
+               old_val = real_val;
+
+               real_val = atomic64_cmpxchg(ptr, old_val, new_val);
+
+       } while (real_val != old_val);
+
+       return old_val;
+}
+EXPORT_SYMBOL(atomic64_xchg);
+
+/**
+ * atomic64_set - set atomic64 variable
+ * @ptr:      pointer to type atomic64_t
+ * @new_val:  value to assign
+ *
+ * Atomically sets the value of @ptr to @new_val.
+ */
+void atomic64_set(atomic64_t *ptr, u64 new_val)
+{
+       atomic64_xchg(ptr, new_val);
+}
+EXPORT_SYMBOL(atomic64_set);
+
+/**
+EXPORT_SYMBOL(atomic64_read);
+ * atomic64_add_return - add and return
+ * @delta: integer value to add
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically adds @delta to @ptr and returns @delta + *@ptr
+ */
+noinline u64 atomic64_add_return(u64 delta, atomic64_t *ptr)
+{
+       /*
+        * Try first with a (possibly incorrect) assumption about
+        * what we have there. We'll do two loops most likely,
+        * but we'll get an ownership MESI transaction straight away
+        * instead of a read transaction followed by a
+        * flush-for-ownership transaction:
+        */
+       u64 old_val, new_val, real_val = 0;
+
+       do {
+               old_val = real_val;
+               new_val = old_val + delta;
+
+               real_val = atomic64_cmpxchg(ptr, old_val, new_val);
+
+       } while (real_val != old_val);
+
+       return new_val;
+}
+EXPORT_SYMBOL(atomic64_add_return);
+
+u64 atomic64_sub_return(u64 delta, atomic64_t *ptr)
+{
+       return atomic64_add_return(-delta, ptr);
+}
+EXPORT_SYMBOL(atomic64_sub_return);
+
+u64 atomic64_inc_return(atomic64_t *ptr)
+{
+       return atomic64_add_return(1, ptr);
+}
+EXPORT_SYMBOL(atomic64_inc_return);
+
+u64 atomic64_dec_return(atomic64_t *ptr)
+{
+       return atomic64_sub_return(1, ptr);
+}
+EXPORT_SYMBOL(atomic64_dec_return);
+
+/**
+ * atomic64_add - add integer to atomic64 variable
+ * @delta: integer value to add
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically adds @delta to @ptr.
+ */
+void atomic64_add(u64 delta, atomic64_t *ptr)
+{
+       atomic64_add_return(delta, ptr);
+}
+EXPORT_SYMBOL(atomic64_add);
+
+/**
+ * atomic64_sub - subtract the atomic64 variable
+ * @delta: integer value to subtract
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically subtracts @delta from @ptr.
+ */
+void atomic64_sub(u64 delta, atomic64_t *ptr)
+{
+       atomic64_add(-delta, ptr);
+}
+EXPORT_SYMBOL(atomic64_sub);
+
+/**
+ * atomic64_sub_and_test - subtract value from variable and test result
+ * @delta: integer value to subtract
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically subtracts @delta from @ptr and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+int atomic64_sub_and_test(u64 delta, atomic64_t *ptr)
+{
+       u64 new_val = atomic64_sub_return(delta, ptr);
+
+       return new_val == 0;
+}
+EXPORT_SYMBOL(atomic64_sub_and_test);
+
+/**
+ * atomic64_inc - increment atomic64 variable
+ * @ptr: pointer to type atomic64_t
+ *
+ * Atomically increments @ptr by 1.
+ */
+void atomic64_inc(atomic64_t *ptr)
+{
+       atomic64_add(1, ptr);
+}
+EXPORT_SYMBOL(atomic64_inc);
+
+/**
+ * atomic64_dec - decrement atomic64 variable
+ * @ptr: pointer to type atomic64_t
+ *
+ * Atomically decrements @ptr by 1.
+ */
+void atomic64_dec(atomic64_t *ptr)
+{
+       atomic64_sub(1, ptr);
+}
+EXPORT_SYMBOL(atomic64_dec);
+
+/**
+ * atomic64_dec_and_test - decrement and test
+ * @ptr: pointer to type atomic64_t
+ *
+ * Atomically decrements @ptr by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+int atomic64_dec_and_test(atomic64_t *ptr)
+{
+       return atomic64_sub_and_test(1, ptr);
+}
+EXPORT_SYMBOL(atomic64_dec_and_test);
+
+/**
+ * atomic64_inc_and_test - increment and test
+ * @ptr: pointer to type atomic64_t
+ *
+ * Atomically increments @ptr by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+int atomic64_inc_and_test(atomic64_t *ptr)
+{
+       return atomic64_sub_and_test(-1, ptr);
+}
+EXPORT_SYMBOL(atomic64_inc_and_test);
+
+/**
+ * atomic64_add_negative - add and test if negative
+ * @delta: integer value to add
+ * @ptr:   pointer to type atomic64_t
+ *
+ * Atomically adds @delta to @ptr and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+int atomic64_add_negative(u64 delta, atomic64_t *ptr)
+{
+       s64 new_val = atomic64_add_return(delta, ptr);
+
+       return new_val < 0;
+}
+EXPORT_SYMBOL(atomic64_add_negative);
index 9a10a78bb4a414867fa68099996c6cfb66f26d2e..ebeafcce04a9bd595b645af6941429fe8fc26c62 100644 (file)
@@ -5,15 +5,14 @@
  * Zero a page.        
  * rdi page
  */                    
-       ALIGN
-clear_page_c:
+ENTRY(clear_page_c)
        CFI_STARTPROC
        movl $4096/8,%ecx
        xorl %eax,%eax
        rep stosq
        ret
        CFI_ENDPROC
-ENDPROC(clear_page)
+ENDPROC(clear_page_c)
 
 ENTRY(clear_page)
        CFI_STARTPROC
index f118c110af32f66b5a2208ecc864d86e2f249981..6ba0f7bb85eadaeebffde0d428dd8af7f932d2c9 100644 (file)
@@ -75,6 +75,7 @@ ENTRY(copy_to_user)
        jae bad_to_user
        ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
        CFI_ENDPROC
+ENDPROC(copy_to_user)
 
 /* Standard copy_from_user with segment limit checking */
 ENTRY(copy_from_user)
index f4568605d7d5c9fa7281bebfc6d8f5e2b122c8df..ff485d361182f814624e238e1ebc418c28c05e79 100644 (file)
@@ -55,8 +55,10 @@ static void delay_tsc(unsigned long loops)
 
        preempt_disable();
        cpu = smp_processor_id();
+       rdtsc_barrier();
        rdtscl(bclock);
        for (;;) {
+               rdtsc_barrier();
                rdtscl(now);
                if ((now - bclock) >= loops)
                        break;
@@ -78,6 +80,7 @@ static void delay_tsc(unsigned long loops)
                if (unlikely(cpu != smp_processor_id())) {
                        loops -= (now - bclock);
                        cpu = smp_processor_id();
+                       rdtsc_barrier();
                        rdtscl(bclock);
                }
        }
index 1440b9c0547e9bd668a7bedf683686c57f5d1db0..caa24aca8115707be495a026fe89f20baea5164a 100644 (file)
@@ -89,16 +89,13 @@ void rdmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs)
        rv.msrs   = msrs;
        rv.msr_no = msr_no;
 
-       preempt_disable();
-       /*
-        * FIXME: handle the CPU we're executing on separately for now until
-        * smp_call_function_many has been fixed to not skip it.
-        */
-       this_cpu = raw_smp_processor_id();
-       smp_call_function_single(this_cpu, __rdmsr_on_cpu, &rv, 1);
+       this_cpu = get_cpu();
+
+       if (cpumask_test_cpu(this_cpu, mask))
+               __rdmsr_on_cpu(&rv);
 
        smp_call_function_many(mask, __rdmsr_on_cpu, &rv, 1);
-       preempt_enable();
+       put_cpu();
 }
 EXPORT_SYMBOL(rdmsr_on_cpus);
 
@@ -121,16 +118,13 @@ void wrmsr_on_cpus(const cpumask_t *mask, u32 msr_no, struct msr *msrs)
        rv.msrs   = msrs;
        rv.msr_no = msr_no;
 
-       preempt_disable();
-       /*
-        * FIXME: handle the CPU we're executing on separately for now until
-        * smp_call_function_many has been fixed to not skip it.
-        */
-       this_cpu = raw_smp_processor_id();
-       smp_call_function_single(this_cpu, __wrmsr_on_cpu, &rv, 1);
+       this_cpu = get_cpu();
+
+       if (cpumask_test_cpu(this_cpu, mask))
+               __wrmsr_on_cpu(&rv);
 
        smp_call_function_many(mask, __wrmsr_on_cpu, &rv, 1);
-       preempt_enable();
+       put_cpu();
 }
 EXPORT_SYMBOL(wrmsr_on_cpus);
 
index 7c8ca91bb9ecbacbccc42df711222e7abdc32310..1f118d462acc242990eb7a796b6832d8d90bc442 100644 (file)
@@ -751,7 +751,7 @@ survive:
 
                        if (retval == -ENOMEM && is_global_init(current)) {
                                up_read(&current->mm->mmap_sem);
-                               congestion_wait(WRITE, HZ/50);
+                               congestion_wait(BLK_RW_ASYNC, HZ/50);
                                goto survive;
                        }
 
index 78a5fff857bea0906cb6748baf6ef450b259b538..bfae139182ffbf0d2c5098d824f9d9ed7d8b6827 100644 (file)
@@ -426,10 +426,11 @@ static noinline int vmalloc_fault(unsigned long address)
 }
 
 static const char errata93_warning[] =
-KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
-KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
-KERN_ERR "******* Please consider a BIOS update.\n"
-KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
+KERN_ERR 
+"******* Your BIOS seems to not contain a fix for K8 errata #93\n"
+"******* Working around it, but it may cause SEGVs or burn power.\n"
+"******* Please consider a BIOS update.\n"
+"******* Disabling USB legacy in the BIOS may also help.\n";
 
 /*
  * No vm86 mode in 64-bit mode:
@@ -696,7 +697,7 @@ show_signal_msg(struct pt_regs *regs, unsigned long error_code,
        if (!printk_ratelimit())
                return;
 
-       printk(KERN_CONT "%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
+       printk("%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
                task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
                tsk->comm, task_pid_nr(tsk), address,
                (void *)regs->ip, (void *)regs->sp, error_code);
index 58f621e8191955c2e02016df1d8e99bec8e1ed8f..2112ed55e7ea77d42f69212db733bb3355e7007b 100644 (file)
@@ -103,6 +103,7 @@ EXPORT_SYMBOL(kmap);
 EXPORT_SYMBOL(kunmap);
 EXPORT_SYMBOL(kmap_atomic);
 EXPORT_SYMBOL(kunmap_atomic);
+EXPORT_SYMBOL(kmap_atomic_prot);
 
 void __init set_highmem_pages_init(void)
 {
index f53b57e4086fffde114e8c153c67b76a7a857554..0607119cef94f2321ead2e46d467d1900a7014fb 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/system.h>
 #include <asm/tlbflush.h>
 #include <asm/tlb.h>
+#include <asm/proto.h>
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
@@ -177,20 +178,6 @@ static int __meminit save_mr(struct map_range *mr, int nr_range,
        return nr_range;
 }
 
-#ifdef CONFIG_X86_64
-static void __init init_gbpages(void)
-{
-       if (direct_gbpages && cpu_has_gbpages)
-               printk(KERN_INFO "Using GB pages for direct mapping\n");
-       else
-               direct_gbpages = 0;
-}
-#else
-static inline void init_gbpages(void)
-{
-}
-#endif
-
 /*
  * Setup the direct mapping of the physical memory at PAGE_OFFSET.
  * This runs before bootmem is initialized and gets pages directly from
@@ -210,9 +197,6 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
 
        printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end);
 
-       if (!after_bootmem)
-               init_gbpages();
-
 #if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK)
        /*
         * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages.
index c4378f4fd4a5e240125cfa60d2f1430a0bb35145..ea56b8cbb6a6dd6de89ec04d9e0543ff6908395f 100644 (file)
@@ -598,6 +598,15 @@ void __init paging_init(void)
 
        sparse_memory_present_with_active_regions(MAX_NUMNODES);
        sparse_init();
+
+       /*
+        * clear the default setting with node 0
+        * note: don't use nodes_clear here, that is really clearing when
+        *       numa support is not compiled in, and later node_set_state
+        *       will not set it back.
+        */
+       node_clear_state(0, N_NORMAL_MEMORY);
+
        free_area_init_nodes(max_zone_pfns);
 }
 
@@ -787,7 +796,7 @@ int __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
                return ret;
 
 #else
-       reserve_bootmem(phys, len, BOOTMEM_DEFAULT);
+       reserve_bootmem(phys, len, flags);
 #endif
 
        if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
index 3cfe9ced8a4c6e500b6df519dceadc7534a5730a..7e600c1962db0c77d2dcb66559b75aff79672580 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
+#include <linux/pfn.h>
 
 #include <asm/e820.h>
 #include <asm/processor.h>
@@ -590,9 +591,12 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)
        unsigned int level;
        pte_t *kpte, old_pte;
 
-       if (cpa->flags & CPA_PAGES_ARRAY)
-               address = (unsigned long)page_address(cpa->pages[cpa->curpage]);
-       else if (cpa->flags & CPA_ARRAY)
+       if (cpa->flags & CPA_PAGES_ARRAY) {
+               struct page *page = cpa->pages[cpa->curpage];
+               if (unlikely(PageHighMem(page)))
+                       return 0;
+               address = (unsigned long)page_address(page);
+       } else if (cpa->flags & CPA_ARRAY)
                address = cpa->vaddr[cpa->curpage];
        else
                address = *cpa->vaddr;
@@ -681,8 +685,9 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias);
 static int cpa_process_alias(struct cpa_data *cpa)
 {
        struct cpa_data alias_cpa;
-       int ret = 0;
-       unsigned long temp_cpa_vaddr, vaddr;
+       unsigned long laddr = (unsigned long)__va(cpa->pfn << PAGE_SHIFT);
+       unsigned long vaddr, remapped;
+       int ret;
 
        if (cpa->pfn >= max_pfn_mapped)
                return 0;
@@ -695,9 +700,12 @@ static int cpa_process_alias(struct cpa_data *cpa)
         * No need to redo, when the primary call touched the direct
         * mapping already:
         */
-       if (cpa->flags & CPA_PAGES_ARRAY)
-               vaddr = (unsigned long)page_address(cpa->pages[cpa->curpage]);
-       else if (cpa->flags & CPA_ARRAY)
+       if (cpa->flags & CPA_PAGES_ARRAY) {
+               struct page *page = cpa->pages[cpa->curpage];
+               if (unlikely(PageHighMem(page)))
+                       return 0;
+               vaddr = (unsigned long)page_address(page);
+       } else if (cpa->flags & CPA_ARRAY)
                vaddr = cpa->vaddr[cpa->curpage];
        else
                vaddr = *cpa->vaddr;
@@ -706,42 +714,55 @@ static int cpa_process_alias(struct cpa_data *cpa)
                    PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)))) {
 
                alias_cpa = *cpa;
-               temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
-               alias_cpa.vaddr = &temp_cpa_vaddr;
+               alias_cpa.vaddr = &laddr;
                alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
 
-
                ret = __change_page_attr_set_clr(&alias_cpa, 0);
+               if (ret)
+                       return ret;
        }
 
 #ifdef CONFIG_X86_64
-       if (ret)
-               return ret;
-       /*
-        * No need to redo, when the primary call touched the high
-        * mapping already:
-        */
-       if (within(vaddr, (unsigned long) _text, _brk_end))
-               return 0;
-
        /*
-        * If the physical address is inside the kernel map, we need
+        * If the primary call didn't touch the high mapping already
+        * and the physical address is inside the kernel map, we need
         * to touch the high mapped kernel as well:
         */
-       if (!within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn()))
-               return 0;
+       if (!within(vaddr, (unsigned long)_text, _brk_end) &&
+           within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn())) {
+               unsigned long temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) +
+                                              __START_KERNEL_map - phys_base;
+               alias_cpa = *cpa;
+               alias_cpa.vaddr = &temp_cpa_vaddr;
+               alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
 
-       alias_cpa = *cpa;
-       temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base;
-       alias_cpa.vaddr = &temp_cpa_vaddr;
-       alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
+               /*
+                * The high mapping range is imprecise, so ignore the
+                * return value.
+                */
+               __change_page_attr_set_clr(&alias_cpa, 0);
+       }
+#endif
 
        /*
-        * The high mapping range is imprecise, so ignore the return value.
+        * If the PMD page was partially used for per-cpu remapping,
+        * the recycled area needs to be split and modified.  Because
+        * the area is always proper subset of a PMD page
+        * cpa->numpages is guaranteed to be 1 for these areas, so
+        * there's no need to loop over and check for further remaps.
         */
-       __change_page_attr_set_clr(&alias_cpa, 0);
-#endif
-       return ret;
+       remapped = (unsigned long)pcpu_lpage_remapped((void *)laddr);
+       if (remapped) {
+               WARN_ON(cpa->numpages > 1);
+               alias_cpa = *cpa;
+               alias_cpa.vaddr = &remapped;
+               alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
+               ret = __change_page_attr_set_clr(&alias_cpa, 0);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
 }
 
 static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
@@ -982,12 +1003,15 @@ EXPORT_SYMBOL(set_memory_array_uc);
 int _set_memory_wc(unsigned long addr, int numpages)
 {
        int ret;
+       unsigned long addr_copy = addr;
+
        ret = change_page_attr_set(&addr, numpages,
                                    __pgprot(_PAGE_CACHE_UC_MINUS), 0);
-
        if (!ret) {
-               ret = change_page_attr_set(&addr, numpages,
-                                   __pgprot(_PAGE_CACHE_WC), 0);
+               ret = change_page_attr_set_clr(&addr_copy, numpages,
+                                              __pgprot(_PAGE_CACHE_WC),
+                                              __pgprot(_PAGE_CACHE_MASK),
+                                              0, 0, NULL);
        }
        return ret;
 }
@@ -1104,7 +1128,9 @@ int set_pages_array_uc(struct page **pages, int addrinarray)
        int free_idx;
 
        for (i = 0; i < addrinarray; i++) {
-               start = (unsigned long)page_address(pages[i]);
+               if (PageHighMem(pages[i]))
+                       continue;
+               start = page_to_pfn(pages[i]) << PAGE_SHIFT;
                end = start + PAGE_SIZE;
                if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL))
                        goto err_out;
@@ -1117,7 +1143,9 @@ int set_pages_array_uc(struct page **pages, int addrinarray)
 err_out:
        free_idx = i;
        for (i = 0; i < free_idx; i++) {
-               start = (unsigned long)page_address(pages[i]);
+               if (PageHighMem(pages[i]))
+                       continue;
+               start = page_to_pfn(pages[i]) << PAGE_SHIFT;
                end = start + PAGE_SIZE;
                free_memtype(start, end);
        }
@@ -1146,7 +1174,9 @@ int set_pages_array_wb(struct page **pages, int addrinarray)
                return retval;
 
        for (i = 0; i < addrinarray; i++) {
-               start = (unsigned long)page_address(pages[i]);
+               if (PageHighMem(pages[i]))
+                       continue;
+               start = page_to_pfn(pages[i]) << PAGE_SHIFT;
                end = start + PAGE_SIZE;
                free_memtype(start, end);
        }
index e6718bb280650b0a7e7500cb8d6dcda5a29c67b0..352aa9e927e26c20217725475b5c908fb91e60dd 100644 (file)
@@ -623,7 +623,8 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
                return ret;
 
        if (flags != want_flags) {
-               if (strict_prot || !is_new_memtype_allowed(want_flags, flags)) {
+               if (strict_prot ||
+                   !is_new_memtype_allowed(paddr, size, want_flags, flags)) {
                        free_memtype(paddr, paddr + size);
                        printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
                                " for %Lx-%Lx, got %s\n",
index 8e43bdd45456017cd431c2cf9b4678c5b7e9f65d..ed34f5e35999449a488be43ced0e580319b373f1 100644 (file)
@@ -25,7 +25,7 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
        return pte;
 }
 
-void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
+void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
 {
        pgtable_page_dtor(pte);
        paravirt_release_pte(page_to_pfn(pte));
@@ -33,14 +33,14 @@ void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
 }
 
 #if PAGETABLE_LEVELS > 2
-void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
 {
        paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
        tlb_remove_page(tlb, virt_to_page(pmd));
 }
 
 #if PAGETABLE_LEVELS > 3
-void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
+void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
 {
        paravirt_release_pud(__pa(pud) >> PAGE_SHIFT);
        tlb_remove_page(tlb, virt_to_page(pud));
@@ -329,7 +329,6 @@ void __init reserve_top_address(unsigned long reserve)
        printk(KERN_INFO "Reserving virtual address space above 0x%08x\n",
               (int)-reserve);
        __FIXADDR_TOP = -reserve - PAGE_SIZE;
-       __VMALLOC_RESERVE += reserve;
 #endif
 }
 
index 2dfcbf9df2ae8410228e25fb4f559cd75ed1982e..dbb5381f7b3b58ec41f026cd65d592bc1c2871ff 100644 (file)
@@ -79,8 +79,10 @@ static __init void bad_srat(void)
        acpi_numa = -1;
        for (i = 0; i < MAX_LOCAL_APIC; i++)
                apicid_to_node[i] = NUMA_NO_NODE;
-       for (i = 0; i < MAX_NUMNODES; i++)
-               nodes_add[i].start = nodes[i].end = 0;
+       for (i = 0; i < MAX_NUMNODES; i++) {
+               nodes[i].start = nodes[i].end = 0;
+               nodes_add[i].start = nodes_add[i].end = 0;
+       }
        remove_all_active_ranges();
 }
 
index 821e97017e954a8a8e74a607950c583061412d7a..c814e144a3f0724b1d4ce56a74ca03b70cc82f25 100644 (file)
@@ -183,18 +183,17 @@ static void flush_tlb_others_ipi(const struct cpumask *cpumask,
 
        f->flush_mm = mm;
        f->flush_va = va;
-       cpumask_andnot(to_cpumask(f->flush_cpumask),
-                      cpumask, cpumask_of(smp_processor_id()));
-
-       /*
-        * We have to send the IPI only to
-        * CPUs affected.
-        */
-       apic->send_IPI_mask(to_cpumask(f->flush_cpumask),
-                     INVALIDATE_TLB_VECTOR_START + sender);
+       if (cpumask_andnot(to_cpumask(f->flush_cpumask), cpumask, cpumask_of(smp_processor_id()))) {
+               /*
+                * We have to send the IPI only to
+                * CPUs affected.
+                */
+               apic->send_IPI_mask(to_cpumask(f->flush_cpumask),
+                             INVALIDATE_TLB_VECTOR_START + sender);
 
-       while (!cpumask_empty(to_cpumask(f->flush_cpumask)))
-               cpu_relax();
+               while (!cpumask_empty(to_cpumask(f->flush_cpumask)))
+                       cpu_relax();
+       }
 
        f->flush_mm = NULL;
        f->flush_va = 0;
index b07dd8d0b321d9e04fd94b307c0f51befdc20933..89b9a5cd63da1d52900a47dd0b269476dd09fb2c 100644 (file)
@@ -390,7 +390,7 @@ static int __init p4_init(char **cpu_type)
 static int force_arch_perfmon;
 static int force_cpu_type(const char *str, struct kernel_param *kp)
 {
-       if (!strcmp(str, "archperfmon")) {
+       if (!strcmp(str, "arch_perfmon")) {
                force_arch_perfmon = 1;
                printk(KERN_INFO "oprofile: forcing architectural perfmon\n");
        }
index b26626dc517c0a4f706c0b07ac3e491e6327501e..1014eb4bfc37ac15cec9e3b24b3f980a1a52e7d9 100644 (file)
@@ -68,6 +68,10 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
        unsigned long flags;
        struct resource *root;
        int max_root_bus_resources = PCI_BUS_NUM_RESOURCES;
+       u64 start, end;
+
+       if (bus_has_transparent_bridge(info->bus))
+               max_root_bus_resources -= 3;
 
        status = resource_to_addr(acpi_res, &addr);
        if (!ACPI_SUCCESS(status))
@@ -84,25 +88,24 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
        } else
                return AE_OK;
 
-       res = &info->res[info->res_num];
-       res->name = info->name;
-       res->flags = flags;
-       res->start = addr.minimum + addr.translation_offset;
-       res->end = res->start + addr.address_length - 1;
-       res->child = NULL;
-
-       if (bus_has_transparent_bridge(info->bus))
-               max_root_bus_resources -= 3;
+       start = addr.minimum + addr.translation_offset;
+       end = start + addr.address_length - 1;
        if (info->res_num >= max_root_bus_resources) {
                printk(KERN_WARNING "PCI: Failed to allocate 0x%lx-0x%lx "
                        "from %s for %s due to _CRS returning more than "
-                       "%d resource descriptors\n", (unsigned long) res->start,
-                       (unsigned long) res->end, root->name, info->name,
+                       "%d resource descriptors\n", (unsigned long) start,
+                       (unsigned long) end, root->name, info->name,
                        max_root_bus_resources);
-               info->res_num++;
                return AE_OK;
        }
 
+       res = &info->res[info->res_num];
+       res->name = info->name;
+       res->flags = flags;
+       res->start = start;
+       res->end = end;
+       res->child = NULL;
+
        if (insert_resource(root, res)) {
                printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx "
                        "from %s for %s\n", (unsigned long) res->start,
@@ -114,23 +117,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
        return AE_OK;
 }
 
-static void
-adjust_transparent_bridge_resources(struct pci_bus *bus)
-{
-       struct pci_dev *dev;
-
-       list_for_each_entry(dev, &bus->devices, bus_list) {
-               int i;
-               u16 class = dev->class >> 8;
-
-               if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) {
-                       for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++)
-                               dev->subordinate->resource[i] =
-                                               dev->bus->resource[i - 3];
-               }
-       }
-}
-
 static void
 get_current_resources(struct acpi_device *device, int busnum,
                        int domain, struct pci_bus *bus)
@@ -158,8 +144,6 @@ get_current_resources(struct acpi_device *device, int busnum,
        info.res_num = 0;
        acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
                                &info);
-       if (info.res_num)
-               adjust_transparent_bridge_resources(bus);
 
        return;
 
@@ -222,8 +206,15 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
                 */
                memcpy(bus->sysdata, sd, sizeof(*sd));
                kfree(sd);
-       } else
-               bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd);
+       } else {
+               bus = pci_create_bus(NULL, busnum, &pci_root_ops, sd);
+               if (bus) {
+                       if (pci_probe & PCI_USE__CRS)
+                               get_current_resources(device, busnum, domain,
+                                                       bus);
+                       bus->subordinate = pci_scan_child_bus(bus);
+               }
+       }
 
        if (!bus)
                kfree(sd);
@@ -238,8 +229,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
 #endif
        }
 
-       if (bus && (pci_probe & PCI_USE__CRS))
-               get_current_resources(device, busnum, domain, bus);
        return bus;
 }
 
index f893d6a6e803e266f3d36030f8744fecda130bf9..3ffa10df20b9f2dc6ccbcf6380926a73fda79026 100644 (file)
@@ -100,8 +100,9 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b)
        int j;
        struct pci_root_info *info;
 
-       /* don't go for it if _CRS is used */
-       if (pci_probe & PCI_USE__CRS)
+       /* don't go for it if _CRS is used already */
+       if (b->resource[0] != &ioport_resource ||
+           b->resource[1] != &iomem_resource)
                return;
 
        /* if only one root bus, don't need to anything */
@@ -116,6 +117,9 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b)
        if (i == pci_root_num)
                return;
 
+       printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n",
+                       b->number);
+
        info = &pci_root_info[i];
        for (j = 0; j < info->res_num; j++) {
                struct resource *res;
index 0fb56db16d1813897b7f7fea6df2af75a20fd2a0..52e62e57fedd53a385147cf1399cd84f89f7bc4b 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/pat.h>
 #include <asm/e820.h>
 #include <asm/pci_x86.h>
+#include <asm/io_apic.h>
 
 
 static int
@@ -227,6 +228,12 @@ void __init pcibios_resource_survey(void)
        pcibios_allocate_resources(1);
 
        e820_reserve_resources_late();
+       /*
+        * Insert the IO APIC resources after PCI initialization has
+        * occured to handle IO APICS that are mapped in on a BAR in
+        * PCI space, but before trying to assign unassigned pci res.
+        */
+       ioapic_insert_resources();
 }
 
 /**
index de2abbd0754481d0528ee527077d668d7b3e422b..a6a198c336238f63a2c0962fe2f94212ee6712e2 100644 (file)
@@ -1,7 +1,7 @@
 # __restore_processor_state() restores %gs after S3 resume and so should not
 # itself be stack-protected
 nostackp := $(call cc-option, -fno-stack-protector)
-CFLAGS_cpu_$(BITS).o   := $(nostackp)
+CFLAGS_cpu.o   := $(nostackp)
 
 obj-$(CONFIG_PM_SLEEP)         += cpu.o
 obj-$(CONFIG_HIBERNATION)      += hibernate_$(BITS).o hibernate_asm_$(BITS).o
index d277ef1eea511c1047b2dfb06ea784496c42a0f1..b3d20b9cac6366922d189572396d7c805c6680b2 100644 (file)
@@ -244,7 +244,7 @@ static void __restore_processor_state(struct saved_context *ctxt)
        do_fpu_end();
        mtrr_ap_init();
 
-#ifdef CONFIG_X86_32
+#ifdef CONFIG_X86_OLD_MCE
        mcheck_init(&boot_cpu_data);
 #endif
 }
index 172438f86a02aaf01b3855e36318cf0bb8aaeba1..7410640db173b842db79b835dbdc2206e01c0c2a 100644 (file)
@@ -5,6 +5,10 @@ CFLAGS_REMOVE_time.o = -pg
 CFLAGS_REMOVE_irq.o = -pg
 endif
 
+# Make sure early boot has no stackprotector
+nostackp := $(call cc-option, -fno-stack-protector)
+CFLAGS_enlighten.o             := $(nostackp)
+
 obj-y          := enlighten.o setup.o multicalls.o mmu.o irq.o \
                        time.o xen-asm.o xen-asm_$(BITS).o \
                        grant-table.o suspend.o
index 0a1700a2be9c8c9a548822ca4deef1bb475b4059..eb33aaa8415de0d7b4e13d7dd18c826829a59466 100644 (file)
@@ -215,6 +215,7 @@ static __init void xen_init_cpuid_mask(void)
                          (1 << X86_FEATURE_ACPI));  /* disable ACPI */
 
        ax = 1;
+       cx = 0;
        xen_cpuid(&ax, &bx, &cx, &dx);
 
        /* cpuid claims we support xsave; try enabling it to see what happens */
@@ -974,10 +975,6 @@ asmlinkage void __init xen_start_kernel(void)
 
        xen_domain_type = XEN_PV_DOMAIN;
 
-       BUG_ON(memcmp(xen_start_info->magic, "xen-3", 5) != 0);
-
-       xen_setup_features();
-
        /* Install Xen paravirt ops */
        pv_info = xen_info;
        pv_init_ops = xen_init_ops;
@@ -986,8 +983,15 @@ asmlinkage void __init xen_start_kernel(void)
        pv_apic_ops = xen_apic_ops;
        pv_mmu_ops = xen_mmu_ops;
 
-       xen_init_irq_ops();
+#ifdef CONFIG_X86_64
+       /*
+        * Setup percpu state.  We only need to do this for 64-bit
+        * because 32-bit already has %fs set properly.
+        */
+       load_percpu_segment(0);
+#endif
 
+       xen_init_irq_ops();
        xen_init_cpuid_mask();
 
 #ifdef CONFIG_X86_LOCAL_APIC
@@ -997,6 +1001,8 @@ asmlinkage void __init xen_start_kernel(void)
        set_xen_basic_apic_ops();
 #endif
 
+       xen_setup_features();
+
        if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) {
                pv_mmu_ops.ptep_modify_prot_start = xen_ptep_modify_prot_start;
                pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit;
@@ -1004,13 +1010,6 @@ asmlinkage void __init xen_start_kernel(void)
 
        machine_ops = xen_machine_ops;
 
-#ifdef CONFIG_X86_64
-       /*
-        * Setup percpu state.  We only need to do this for 64-bit
-        * because 32-bit already has %fs set properly.
-        */
-       load_percpu_segment(0);
-#endif
        /*
         * The only reliable way to retain the initial address of the
         * percpu gdt_page is to remember it here, so we can go and
@@ -1061,6 +1060,7 @@ asmlinkage void __init xen_start_kernel(void)
        /* set up basic CPUID stuff */
        cpu_detect(&new_cpu_data);
        new_cpu_data.hard_math = 1;
+       new_cpu_data.wp_works_ok = 1;
        new_cpu_data.x86_capability[0] = cpuid_edx(1);
 #endif
 
index 0f4fe1faf9ba46fed7f9c689f2bb2652fe25923b..13165641cc5153bb9990a634042262f2c120085a 100644 (file)
@@ -80,8 +80,6 @@ struct thread_info {
 
 /*
  * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 
 #ifndef __ASSEMBLY__
@@ -92,7 +90,7 @@ struct thread_info {
        .exec_domain    = &default_exec_domain, \
        .flags          = 0,                    \
        .cpu            = 0,                    \
-       .preempt_count  = 1,                    \
+       .preempt_count  = INIT_PREEMPT_COUNT,   \
        .addr_limit     = KERNEL_DS,            \
        .restart_block = {                      \
                .fn = do_no_restart_syscall,    \
index 31c220faca02ac9cbb3695f735e0221bdc32104a..0d766f9c1083a59cd4a073cb5da0dfc640a06415 100644 (file)
@@ -42,6 +42,6 @@
 
 #include <asm-generic/tlb.h>
 
-#define __pte_free_tlb(tlb, pte)               pte_free((tlb)->mm, pte)
+#define __pte_free_tlb(tlb, pte, address)      pte_free((tlb)->mm, pte)
 
 #endif /* _XTENSA_TLB_H */
index ba9ab9349782d3ffbf364d500f03005c433d2798..e64efac3b9db43e7383127ec56ee31030ec36ff3 100644 (file)
@@ -354,10 +354,10 @@ void show_regs(struct pt_regs * regs)
 
        for (i = 0; i < 16; i++) {
                if ((i % 8) == 0)
-                       printk ("\n" KERN_INFO "a%02d: ", i);
-               printk("%08lx ", regs->areg[i]);
+                       printk(KERN_INFO "a%02d:", i);
+               printk(KERN_CONT " %08lx", regs->areg[i]);
        }
-       printk("\n");
+       printk(KERN_CONT "\n");
 
        printk("pc: %08lx, ps: %08lx, depc: %08lx, excvaddr: %08lx\n",
               regs->pc, regs->ps, regs->depc, regs->excvaddr);
index 95a86adc33a189d9ef2fb31fb12426d62650627e..9be0b56eaee19ee494d388f07cda821ffcc29ba0 100644 (file)
@@ -48,9 +48,9 @@ config LBDAF
          If unsure, say Y.
 
 config BLK_DEV_BSG
-       bool "Block layer SG support v4 (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
-       ---help---
+       bool "Block layer SG support v4"
+       default y
+       help
          Saying Y here will enable generic SG (SCSI generic) v4 support
          for any block device.
 
@@ -60,7 +60,10 @@ config BLK_DEV_BSG
          protocols (e.g. Task Management Functions and SMP in Serial
          Attached SCSI).
 
-         If unsure, say N.
+         This option is required by recent UDEV versions to properly
+         access device serial numbers, etc.
+
+         If unsure, say Y.
 
 config BLK_DEV_INTEGRITY
        bool "Block layer data integrity support"
index e9fa4dd690f238e51c4a830bf3ccdfec0703c4d8..6c54ed0ff755b6507fb89884524111b429cff3e0 100644 (file)
@@ -5,7 +5,7 @@
 obj-$(CONFIG_BLOCK) := elevator.o blk-core.o blk-tag.o blk-sysfs.o \
                        blk-barrier.o blk-settings.o blk-ioc.o blk-map.o \
                        blk-exec.o blk-merge.o blk-softirq.o blk-timeout.o \
-                       ioctl.o genhd.o scsi_ioctl.o cmd-filter.o
+                       ioctl.o genhd.o scsi_ioctl.o
 
 obj-$(CONFIG_BLK_DEV_BSG)      += bsg.o
 obj-$(CONFIG_IOSCHED_NOOP)     += noop-iosched.o
index b06cf5c2a829c49a17dc4a23ab4421d8933b3401..e3299a77a0d8b44d08944d9577d309dc4e40011a 100644 (file)
@@ -575,13 +575,6 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
                return NULL;
        }
 
-       /*
-        * if caller didn't supply a lock, they get per-queue locking with
-        * our embedded lock
-        */
-       if (!lock)
-               lock = &q->__queue_lock;
-
        q->request_fn           = rfn;
        q->prep_rq_fn           = NULL;
        q->unplug_fn            = generic_unplug_device;
@@ -595,8 +588,6 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
 
        q->sg_reserved_size = INT_MAX;
 
-       blk_set_cmd_filter_defaults(&q->cmd_filter);
-
        /*
         * all done
         */
@@ -1172,6 +1163,11 @@ static int __make_request(struct request_queue *q, struct bio *bio)
        const int unplug = bio_unplug(bio);
        int rw_flags;
 
+       if (bio_barrier(bio) && bio_has_data(bio) &&
+           (q->next_ordered == QUEUE_ORDERED_NONE)) {
+               bio_endio(bio, -EOPNOTSUPP);
+               return 0;
+       }
        /*
         * low level driver can indicate that it wants pages above a
         * certain limit bounced to low memory (ie for highmem, or even
@@ -1472,11 +1468,6 @@ static inline void __generic_make_request(struct bio *bio)
                        err = -EOPNOTSUPP;
                        goto end_io;
                }
-               if (bio_barrier(bio) && bio_has_data(bio) &&
-                   (q->next_ordered == QUEUE_ORDERED_NONE)) {
-                       err = -EOPNOTSUPP;
-                       goto end_io;
-               }
 
                ret = q->make_request_fn(q, bio);
        } while (ret);
@@ -2145,7 +2136,7 @@ bool blk_end_request(struct request *rq, int error, unsigned int nr_bytes)
 {
        return blk_end_bidi_request(rq, error, nr_bytes, 0);
 }
-EXPORT_SYMBOL_GPL(blk_end_request);
+EXPORT_SYMBOL(blk_end_request);
 
 /**
  * blk_end_request_all - Helper function for drives to finish the request.
@@ -2166,7 +2157,7 @@ void blk_end_request_all(struct request *rq, int error)
        pending = blk_end_bidi_request(rq, error, blk_rq_bytes(rq), bidi_bytes);
        BUG_ON(pending);
 }
-EXPORT_SYMBOL_GPL(blk_end_request_all);
+EXPORT_SYMBOL(blk_end_request_all);
 
 /**
  * blk_end_request_cur - Helper function to finish the current request chunk.
@@ -2184,7 +2175,7 @@ bool blk_end_request_cur(struct request *rq, int error)
 {
        return blk_end_request(rq, error, blk_rq_cur_bytes(rq));
 }
-EXPORT_SYMBOL_GPL(blk_end_request_cur);
+EXPORT_SYMBOL(blk_end_request_cur);
 
 /**
  * __blk_end_request - Helper function for drivers to complete the request.
@@ -2203,7 +2194,7 @@ bool __blk_end_request(struct request *rq, int error, unsigned int nr_bytes)
 {
        return __blk_end_bidi_request(rq, error, nr_bytes, 0);
 }
-EXPORT_SYMBOL_GPL(__blk_end_request);
+EXPORT_SYMBOL(__blk_end_request);
 
 /**
  * __blk_end_request_all - Helper function for drives to finish the request.
@@ -2224,7 +2215,7 @@ void __blk_end_request_all(struct request *rq, int error)
        pending = __blk_end_bidi_request(rq, error, blk_rq_bytes(rq), bidi_bytes);
        BUG_ON(pending);
 }
-EXPORT_SYMBOL_GPL(__blk_end_request_all);
+EXPORT_SYMBOL(__blk_end_request_all);
 
 /**
  * __blk_end_request_cur - Helper function to finish the current request chunk.
@@ -2243,7 +2234,7 @@ bool __blk_end_request_cur(struct request *rq, int error)
 {
        return __blk_end_request(rq, error, blk_rq_cur_bytes(rq));
 }
-EXPORT_SYMBOL_GPL(__blk_end_request_cur);
+EXPORT_SYMBOL(__blk_end_request_cur);
 
 void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
                     struct bio *bio)
@@ -2365,7 +2356,7 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
                __bio_clone(bio, bio_src);
 
                if (bio_integrity(bio_src) &&
-                   bio_integrity_clone(bio, bio_src, gfp_mask))
+                   bio_integrity_clone(bio, bio_src, gfp_mask, bs))
                        goto free_and_out;
 
                if (bio_ctr && bio_ctr(bio, bio_src, data))
index 73e28d35568841e5caebd9b8b0648c5b21bee0b4..15c630813b1ca550b39f40c8745c100f6ea8b2a3 100644 (file)
@@ -379,6 +379,7 @@ void blk_integrity_unregister(struct gendisk *disk)
 
        kobject_uevent(&bi->kobj, KOBJ_REMOVE);
        kobject_del(&bi->kobj);
+       kobject_put(&bi->kobj);
        kmem_cache_free(integrity_cachep, bi);
        disk->integrity = NULL;
 }
index 39ce64432ba6d4cdcff6427851fe19aac172a2d7..e1999679a4d5156b967729c5e2b6b229a8747954 100644 (file)
@@ -350,6 +350,12 @@ static int attempt_merge(struct request_queue *q, struct request *req,
        if (blk_integrity_rq(req) != blk_integrity_rq(next))
                return 0;
 
+       /* don't merge requests of different failfast settings */
+       if (blk_failfast_dev(req)       != blk_failfast_dev(next)       ||
+           blk_failfast_transport(req) != blk_failfast_transport(next) ||
+           blk_failfast_driver(req)    != blk_failfast_driver(next))
+               return 0;
+
        /*
         * If we are allowed to merge, then append bio list
         * from next to rq and release next. merge_requests_fn
index bd582a7f5310efcbe53e39eb3f1da8abf83d2eb2..476d870650737eda44dc3177675a34afae63fd53 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/bio.h>
 #include <linux/blkdev.h>
 #include <linux/bootmem.h>     /* for max_pfn/max_low_pfn */
+#include <linux/gcd.h>
 
 #include "blk.h"
 
@@ -164,6 +165,13 @@ void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn)
 
        blk_set_default_limits(&q->limits);
 
+       /*
+        * If the caller didn't supply a lock, fall back to our embedded
+        * per-queue locks
+        */
+       if (!q->queue_lock)
+               q->queue_lock = &q->__queue_lock;
+
        /*
         * by default assume old behaviour and bounce for any highmem page
         */
@@ -377,8 +385,8 @@ void blk_queue_alignment_offset(struct request_queue *q, unsigned int offset)
 EXPORT_SYMBOL(blk_queue_alignment_offset);
 
 /**
- * blk_queue_io_min - set minimum request size for the queue
- * @q: the request queue for the device
+ * blk_limits_io_min - set minimum request size for a device
+ * @limits: the queue limits
  * @min:  smallest I/O size in bytes
  *
  * Description:
@@ -387,15 +395,35 @@ EXPORT_SYMBOL(blk_queue_alignment_offset);
  *   smallest I/O the device can perform without incurring a performance
  *   penalty.
  */
-void blk_queue_io_min(struct request_queue *q, unsigned int min)
+void blk_limits_io_min(struct queue_limits *limits, unsigned int min)
 {
-       q->limits.io_min = min;
+       limits->io_min = min;
 
-       if (q->limits.io_min < q->limits.logical_block_size)
-               q->limits.io_min = q->limits.logical_block_size;
+       if (limits->io_min < limits->logical_block_size)
+               limits->io_min = limits->logical_block_size;
 
-       if (q->limits.io_min < q->limits.physical_block_size)
-               q->limits.io_min = q->limits.physical_block_size;
+       if (limits->io_min < limits->physical_block_size)
+               limits->io_min = limits->physical_block_size;
+}
+EXPORT_SYMBOL(blk_limits_io_min);
+
+/**
+ * blk_queue_io_min - set minimum request size for the queue
+ * @q: the request queue for the device
+ * @min:  smallest I/O size in bytes
+ *
+ * Description:
+ *   Storage devices may report a granularity or preferred minimum I/O
+ *   size which is the smallest request the device can perform without
+ *   incurring a performance penalty.  For disk drives this is often the
+ *   physical block size.  For RAID arrays it is often the stripe chunk
+ *   size.  A properly aligned multiple of minimum_io_size is the
+ *   preferred request size for workloads where a high number of I/O
+ *   operations is desired.
+ */
+void blk_queue_io_min(struct request_queue *q, unsigned int min)
+{
+       blk_limits_io_min(&q->limits, min);
 }
 EXPORT_SYMBOL(blk_queue_io_min);
 
@@ -405,8 +433,12 @@ EXPORT_SYMBOL(blk_queue_io_min);
  * @opt:  optimal request size in bytes
  *
  * Description:
- *   Drivers can call this function to set the preferred I/O request
- *   size for devices that report such a value.
+ *   Storage devices may report an optimal I/O size, which is the
+ *   device's preferred unit for sustained I/O.  This is rarely reported
+ *   for disk drives.  For RAID arrays it is usually the stripe width or
+ *   the internal track size.  A properly aligned multiple of
+ *   optimal_io_size is the preferred request size for workloads where
+ *   sustained throughput is desired.
  */
 void blk_queue_io_opt(struct request_queue *q, unsigned int opt)
 {
@@ -426,27 +458,7 @@ EXPORT_SYMBOL(blk_queue_io_opt);
  **/
 void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
 {
-       /* zero is "infinity" */
-       t->limits.max_sectors = min_not_zero(queue_max_sectors(t),
-                                            queue_max_sectors(b));
-
-       t->limits.max_hw_sectors = min_not_zero(queue_max_hw_sectors(t),
-                                               queue_max_hw_sectors(b));
-
-       t->limits.seg_boundary_mask = min_not_zero(queue_segment_boundary(t),
-                                                  queue_segment_boundary(b));
-
-       t->limits.max_phys_segments = min_not_zero(queue_max_phys_segments(t),
-                                                  queue_max_phys_segments(b));
-
-       t->limits.max_hw_segments = min_not_zero(queue_max_hw_segments(t),
-                                                queue_max_hw_segments(b));
-
-       t->limits.max_segment_size = min_not_zero(queue_max_segment_size(t),
-                                                 queue_max_segment_size(b));
-
-       t->limits.logical_block_size = max(queue_logical_block_size(t),
-                                          queue_logical_block_size(b));
+       blk_stack_limits(&t->limits, &b->limits, 0);
 
        if (!t->queue_lock)
                WARN_ON_ONCE(1);
@@ -516,6 +528,16 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
                return -1;
        }
 
+       /* Find lcm() of optimal I/O size */
+       if (t->io_opt && b->io_opt)
+               t->io_opt = (t->io_opt * b->io_opt) / gcd(t->io_opt, b->io_opt);
+       else if (b->io_opt)
+               t->io_opt = b->io_opt;
+
+       /* Verify that optimal I/O size is a multiple of io_min */
+       if (t->io_min && t->io_opt % t->io_min)
+               return -1;
+
        return 0;
 }
 EXPORT_SYMBOL(blk_stack_limits);
index b1cd04087d6a4db5f8ba3e2d9b4f8db1221ed424..d3aa2aadb3e0e7d18645a2eb9333698f4984263a 100644 (file)
@@ -16,9 +16,9 @@ struct queue_sysfs_entry {
 };
 
 static ssize_t
-queue_var_show(unsigned int var, char *page)
+queue_var_show(unsigned long var, char *page)
 {
-       return sprintf(page, "%d\n", var);
+       return sprintf(page, "%lu\n", var);
 }
 
 static ssize_t
@@ -77,7 +77,8 @@ queue_requests_store(struct request_queue *q, const char *page, size_t count)
 
 static ssize_t queue_ra_show(struct request_queue *q, char *page)
 {
-       int ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10);
+       unsigned long ra_kb = q->backing_dev_info.ra_pages <<
+                                       (PAGE_CACHE_SHIFT - 10);
 
        return queue_var_show(ra_kb, (page));
 }
@@ -132,7 +133,7 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
                return -EINVAL;
 
        spin_lock_irq(q->queue_lock);
-       blk_queue_max_sectors(q, max_sectors_kb << 1);
+       q->limits.max_sectors = max_sectors_kb << 1;
        spin_unlock_irq(q->queue_lock);
 
        return ret;
@@ -189,9 +190,9 @@ static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
 
 static ssize_t queue_rq_affinity_show(struct request_queue *q, char *page)
 {
-       unsigned int set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags);
+       bool set = test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags);
 
-       return queue_var_show(set != 0, page);
+       return queue_var_show(set, page);
 }
 
 static ssize_t
index e7d47525424890e24057b7ef4199eeff2322da5a..5f184bb3ff9e12a13a0e01060c77bdc6e6bdc5e9 100644 (file)
@@ -186,7 +186,7 @@ static int blk_fill_sgv4_hdr_rq(struct request_queue *q, struct request *rq,
                return -EFAULT;
 
        if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) {
-               if (blk_verify_command(&q->cmd_filter, rq->cmd, has_write_perm))
+               if (blk_verify_command(rq->cmd, has_write_perm))
                        return -EPERM;
        } else if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
index 833ec18eaa63e2a20b847797c99511e41314b474..fd7080ed793599127647baafbed009d8e11ef1af 100644 (file)
@@ -70,6 +70,51 @@ struct cfq_rb_root {
 };
 #define CFQ_RB_ROOT    (struct cfq_rb_root) { RB_ROOT, NULL, }
 
+/*
+ * Per process-grouping structure
+ */
+struct cfq_queue {
+       /* reference count */
+       atomic_t ref;
+       /* various state flags, see below */
+       unsigned int flags;
+       /* parent cfq_data */
+       struct cfq_data *cfqd;
+       /* service_tree member */
+       struct rb_node rb_node;
+       /* service_tree key */
+       unsigned long rb_key;
+       /* prio tree member */
+       struct rb_node p_node;
+       /* prio tree root we belong to, if any */
+       struct rb_root *p_root;
+       /* sorted list of pending requests */
+       struct rb_root sort_list;
+       /* if fifo isn't expired, next request to serve */
+       struct request *next_rq;
+       /* requests queued in sort_list */
+       int queued[2];
+       /* currently allocated requests */
+       int allocated[2];
+       /* fifo list of requests in sort_list */
+       struct list_head fifo;
+
+       unsigned long slice_end;
+       long slice_resid;
+       unsigned int slice_dispatch;
+
+       /* pending metadata requests */
+       int meta_pending;
+       /* number of requests that are on the dispatch list or inside driver */
+       int dispatched;
+
+       /* io prio of this group */
+       unsigned short ioprio, org_ioprio;
+       unsigned short ioprio_class, org_ioprio_class;
+
+       pid_t pid;
+};
+
 /*
  * Per block device queue structure
  */
@@ -135,51 +180,11 @@ struct cfq_data {
        unsigned int cfq_slice_idle;
 
        struct list_head cic_list;
-};
 
-/*
- * Per process-grouping structure
- */
-struct cfq_queue {
-       /* reference count */
-       atomic_t ref;
-       /* various state flags, see below */
-       unsigned int flags;
-       /* parent cfq_data */
-       struct cfq_data *cfqd;
-       /* service_tree member */
-       struct rb_node rb_node;
-       /* service_tree key */
-       unsigned long rb_key;
-       /* prio tree member */
-       struct rb_node p_node;
-       /* prio tree root we belong to, if any */
-       struct rb_root *p_root;
-       /* sorted list of pending requests */
-       struct rb_root sort_list;
-       /* if fifo isn't expired, next request to serve */
-       struct request *next_rq;
-       /* requests queued in sort_list */
-       int queued[2];
-       /* currently allocated requests */
-       int allocated[2];
-       /* fifo list of requests in sort_list */
-       struct list_head fifo;
-
-       unsigned long slice_end;
-       long slice_resid;
-       unsigned int slice_dispatch;
-
-       /* pending metadata requests */
-       int meta_pending;
-       /* number of requests that are on the dispatch list or inside driver */
-       int dispatched;
-
-       /* io prio of this group */
-       unsigned short ioprio, org_ioprio;
-       unsigned short ioprio_class, org_ioprio_class;
-
-       pid_t pid;
+       /*
+        * Fallback dummy cfqq for extreme OOM conditions
+        */
+       struct cfq_queue oom_cfqq;
 };
 
 enum cfqq_state_flags {
@@ -1641,6 +1646,26 @@ static void cfq_ioc_set_ioprio(struct io_context *ioc)
        ioc->ioprio_changed = 0;
 }
 
+static void cfq_init_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+                         pid_t pid, int is_sync)
+{
+       RB_CLEAR_NODE(&cfqq->rb_node);
+       RB_CLEAR_NODE(&cfqq->p_node);
+       INIT_LIST_HEAD(&cfqq->fifo);
+
+       atomic_set(&cfqq->ref, 0);
+       cfqq->cfqd = cfqd;
+
+       cfq_mark_cfqq_prio_changed(cfqq);
+
+       if (is_sync) {
+               if (!cfq_class_idle(cfqq))
+                       cfq_mark_cfqq_idle_window(cfqq);
+               cfq_mark_cfqq_sync(cfqq);
+       }
+       cfqq->pid = pid;
+}
+
 static struct cfq_queue *
 cfq_find_alloc_queue(struct cfq_data *cfqd, int is_sync,
                     struct io_context *ioc, gfp_t gfp_mask)
@@ -1653,56 +1678,40 @@ retry:
        /* cic always exists here */
        cfqq = cic_to_cfqq(cic, is_sync);
 
-       if (!cfqq) {
+       /*
+        * Always try a new alloc if we fell back to the OOM cfqq
+        * originally, since it should just be a temporary situation.
+        */
+       if (!cfqq || cfqq == &cfqd->oom_cfqq) {
+               cfqq = NULL;
                if (new_cfqq) {
                        cfqq = new_cfqq;
                        new_cfqq = NULL;
                } else if (gfp_mask & __GFP_WAIT) {
-                       /*
-                        * Inform the allocator of the fact that we will
-                        * just repeat this allocation if it fails, to allow
-                        * the allocator to do whatever it needs to attempt to
-                        * free memory.
-                        */
                        spin_unlock_irq(cfqd->queue->queue_lock);
                        new_cfqq = kmem_cache_alloc_node(cfq_pool,
-                                       gfp_mask | __GFP_NOFAIL | __GFP_ZERO,
+                                       gfp_mask | __GFP_ZERO,
                                        cfqd->queue->node);
                        spin_lock_irq(cfqd->queue->queue_lock);
-                       goto retry;
+                       if (new_cfqq)
+                               goto retry;
                } else {
                        cfqq = kmem_cache_alloc_node(cfq_pool,
                                        gfp_mask | __GFP_ZERO,
                                        cfqd->queue->node);
-                       if (!cfqq)
-                               goto out;
                }
 
-               RB_CLEAR_NODE(&cfqq->rb_node);
-               RB_CLEAR_NODE(&cfqq->p_node);
-               INIT_LIST_HEAD(&cfqq->fifo);
-
-               atomic_set(&cfqq->ref, 0);
-               cfqq->cfqd = cfqd;
-
-               cfq_mark_cfqq_prio_changed(cfqq);
-
-               cfq_init_prio_data(cfqq, ioc);
-
-               if (is_sync) {
-                       if (!cfq_class_idle(cfqq))
-                               cfq_mark_cfqq_idle_window(cfqq);
-                       cfq_mark_cfqq_sync(cfqq);
-               }
-               cfqq->pid = current->pid;
-               cfq_log_cfqq(cfqd, cfqq, "alloced");
+               if (cfqq) {
+                       cfq_init_cfqq(cfqd, cfqq, current->pid, is_sync);
+                       cfq_init_prio_data(cfqq, ioc);
+                       cfq_log_cfqq(cfqd, cfqq, "alloced");
+               } else
+                       cfqq = &cfqd->oom_cfqq;
        }
 
        if (new_cfqq)
                kmem_cache_free(cfq_pool, new_cfqq);
 
-out:
-       WARN_ON((gfp_mask & __GFP_WAIT) && !cfqq);
        return cfqq;
 }
 
@@ -1735,11 +1744,8 @@ cfq_get_queue(struct cfq_data *cfqd, int is_sync, struct io_context *ioc,
                cfqq = *async_cfqq;
        }
 
-       if (!cfqq) {
+       if (!cfqq)
                cfqq = cfq_find_alloc_queue(cfqd, is_sync, ioc, gfp_mask);
-               if (!cfqq)
-                       return NULL;
-       }
 
        /*
         * pin the queue now that it's allocated, scheduler exit will prune it
@@ -2305,12 +2311,8 @@ cfq_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask)
                goto queue_fail;
 
        cfqq = cic_to_cfqq(cic, is_sync);
-       if (!cfqq) {
+       if (!cfqq || cfqq == &cfqd->oom_cfqq) {
                cfqq = cfq_get_queue(cfqd, is_sync, cic->ioc, gfp_mask);
-
-               if (!cfqq)
-                       goto queue_fail;
-
                cic_set_cfqq(cic, cfqq, is_sync);
        }
 
@@ -2465,6 +2467,14 @@ static void *cfq_init_queue(struct request_queue *q)
        for (i = 0; i < CFQ_PRIO_LISTS; i++)
                cfqd->prio_trees[i] = RB_ROOT;
 
+       /*
+        * Our fallback cfqq if cfq_find_alloc_queue() runs into OOM issues.
+        * Grab a permanent reference to it, so that the normal code flow
+        * will not attempt to free it.
+        */
+       cfq_init_cfqq(cfqd, &cfqd->oom_cfqq, 1, 0);
+       atomic_inc(&cfqd->oom_cfqq.ref);
+
        INIT_LIST_HEAD(&cfqd->cic_list);
 
        cfqd->queue = q;
diff --git a/block/cmd-filter.c b/block/cmd-filter.c
deleted file mode 100644 (file)
index 572bbc2..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright 2004 Peter M. Jones <pjones@redhat.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.
- *
- * 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 Licens
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
- *
- */
-
-#include <linux/list.h>
-#include <linux/genhd.h>
-#include <linux/spinlock.h>
-#include <linux/capability.h>
-#include <linux/bitops.h>
-#include <linux/blkdev.h>
-
-#include <scsi/scsi.h>
-#include <linux/cdrom.h>
-
-int blk_verify_command(struct blk_cmd_filter *filter,
-                      unsigned char *cmd, fmode_t has_write_perm)
-{
-       /* root can do any command. */
-       if (capable(CAP_SYS_RAWIO))
-               return 0;
-
-       /* if there's no filter set, assume we're filtering everything out */
-       if (!filter)
-               return -EPERM;
-
-       /* Anybody who can open the device can do a read-safe command */
-       if (test_bit(cmd[0], filter->read_ok))
-               return 0;
-
-       /* Write-safe commands require a writable open */
-       if (test_bit(cmd[0], filter->write_ok) && has_write_perm)
-               return 0;
-
-       return -EPERM;
-}
-EXPORT_SYMBOL(blk_verify_command);
-
-#if 0
-/* and now, the sysfs stuff */
-static ssize_t rcf_cmds_show(struct blk_cmd_filter *filter, char *page,
-                            int rw)
-{
-       char *npage = page;
-       unsigned long *okbits;
-       int i;
-
-       if (rw == READ)
-               okbits = filter->read_ok;
-       else
-               okbits = filter->write_ok;
-
-       for (i = 0; i < BLK_SCSI_MAX_CMDS; i++) {
-               if (test_bit(i, okbits)) {
-                       npage += sprintf(npage, "0x%02x", i);
-                       if (i < BLK_SCSI_MAX_CMDS - 1)
-                               sprintf(npage++, " ");
-               }
-       }
-
-       if (npage != page)
-               npage += sprintf(npage, "\n");
-
-       return npage - page;
-}
-
-static ssize_t rcf_readcmds_show(struct blk_cmd_filter *filter, char *page)
-{
-       return rcf_cmds_show(filter, page, READ);
-}
-
-static ssize_t rcf_writecmds_show(struct blk_cmd_filter *filter,
-                                char *page)
-{
-       return rcf_cmds_show(filter, page, WRITE);
-}
-
-static ssize_t rcf_cmds_store(struct blk_cmd_filter *filter,
-                             const char *page, size_t count, int rw)
-{
-       unsigned long okbits[BLK_SCSI_CMD_PER_LONG], *target_okbits;
-       int cmd, set;
-       char *p, *status;
-
-       if (rw == READ) {
-               memcpy(&okbits, filter->read_ok, sizeof(okbits));
-               target_okbits = filter->read_ok;
-       } else {
-               memcpy(&okbits, filter->write_ok, sizeof(okbits));
-               target_okbits = filter->write_ok;
-       }
-
-       while ((p = strsep((char **)&page, " ")) != NULL) {
-               set = 1;
-
-               if (p[0] == '+') {
-                       p++;
-               } else if (p[0] == '-') {
-                       set = 0;
-                       p++;
-               }
-
-               cmd = simple_strtol(p, &status, 16);
-
-               /* either of these cases means invalid input, so do nothing. */
-               if ((status == p) || cmd >= BLK_SCSI_MAX_CMDS)
-                       return -EINVAL;
-
-               if (set)
-                       __set_bit(cmd, okbits);
-               else
-                       __clear_bit(cmd, okbits);
-       }
-
-       memcpy(target_okbits, okbits, sizeof(okbits));
-       return count;
-}
-
-static ssize_t rcf_readcmds_store(struct blk_cmd_filter *filter,
-                                 const char *page, size_t count)
-{
-       return rcf_cmds_store(filter, page, count, READ);
-}
-
-static ssize_t rcf_writecmds_store(struct blk_cmd_filter *filter,
-                                  const char *page, size_t count)
-{
-       return rcf_cmds_store(filter, page, count, WRITE);
-}
-
-struct rcf_sysfs_entry {
-       struct attribute attr;
-       ssize_t (*show)(struct blk_cmd_filter *, char *);
-       ssize_t (*store)(struct blk_cmd_filter *, const char *, size_t);
-};
-
-static struct rcf_sysfs_entry rcf_readcmds_entry = {
-       .attr = { .name = "read_table", .mode = S_IRUGO | S_IWUSR },
-       .show = rcf_readcmds_show,
-       .store = rcf_readcmds_store,
-};
-
-static struct rcf_sysfs_entry rcf_writecmds_entry = {
-       .attr = {.name = "write_table", .mode = S_IRUGO | S_IWUSR },
-       .show = rcf_writecmds_show,
-       .store = rcf_writecmds_store,
-};
-
-static struct attribute *default_attrs[] = {
-       &rcf_readcmds_entry.attr,
-       &rcf_writecmds_entry.attr,
-       NULL,
-};
-
-#define to_rcf(atr) container_of((atr), struct rcf_sysfs_entry, attr)
-
-static ssize_t
-rcf_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
-{
-       struct rcf_sysfs_entry *entry = to_rcf(attr);
-       struct blk_cmd_filter *filter;
-
-       filter = container_of(kobj, struct blk_cmd_filter, kobj);
-       if (entry->show)
-               return entry->show(filter, page);
-
-       return 0;
-}
-
-static ssize_t
-rcf_attr_store(struct kobject *kobj, struct attribute *attr,
-                       const char *page, size_t length)
-{
-       struct rcf_sysfs_entry *entry = to_rcf(attr);
-       struct blk_cmd_filter *filter;
-
-       if (!capable(CAP_SYS_RAWIO))
-               return -EPERM;
-
-       if (!entry->store)
-               return -EINVAL;
-
-       filter = container_of(kobj, struct blk_cmd_filter, kobj);
-       return entry->store(filter, page, length);
-}
-
-static struct sysfs_ops rcf_sysfs_ops = {
-       .show = rcf_attr_show,
-       .store = rcf_attr_store,
-};
-
-static struct kobj_type rcf_ktype = {
-       .sysfs_ops = &rcf_sysfs_ops,
-       .default_attrs = default_attrs,
-};
-
-int blk_register_filter(struct gendisk *disk)
-{
-       int ret;
-       struct blk_cmd_filter *filter = &disk->queue->cmd_filter;
-
-       ret = kobject_init_and_add(&filter->kobj, &rcf_ktype,
-                                  &disk_to_dev(disk)->kobj,
-                                  "%s", "cmd_filter");
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-EXPORT_SYMBOL(blk_register_filter);
-
-void blk_unregister_filter(struct gendisk *disk)
-{
-       struct blk_cmd_filter *filter = &disk->queue->cmd_filter;
-
-       kobject_put(&filter->kobj);
-}
-EXPORT_SYMBOL(blk_unregister_filter);
-#endif
index ca861927ba41b2dfc9ff80c139f6c8cc162fc251..2d511f9105e16abcf93cad6ac849ad9996661a32 100644 (file)
@@ -100,6 +100,19 @@ int elv_rq_merge_ok(struct request *rq, struct bio *bio)
        if (bio_integrity(bio) != blk_integrity_rq(rq))
                return 0;
 
+       /*
+        * Don't merge if failfast settings don't match.
+        *
+        * FIXME: The negation in front of each condition is necessary
+        * because bio and request flags use different bit positions
+        * and the accessors return those bits directly.  This
+        * ugliness will soon go away.
+        */
+       if (!bio_failfast_dev(bio)       != !blk_failfast_dev(rq)       ||
+           !bio_failfast_transport(bio) != !blk_failfast_transport(rq) ||
+           !bio_failfast_driver(bio)    != !blk_failfast_driver(rq))
+               return 0;
+
        if (!elv_iosched_allow_merge(rq, bio))
                return 0;
 
index 5f8e798ede4ee6d7c479bce1ee36f5488b717cc9..e5b10017a50b121a9288d6d0354bfe9ebb15e499 100644 (file)
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsi_cmnd.h>
 
+struct blk_cmd_filter {
+       unsigned long read_ok[BLK_SCSI_CMD_PER_LONG];
+       unsigned long write_ok[BLK_SCSI_CMD_PER_LONG];
+} blk_default_cmd_filter;
+
 /* Command group 3 is reserved and should never be used.  */
 const unsigned char scsi_command_size_tbl[8] =
 {
@@ -105,7 +110,7 @@ static int sg_emulated_host(struct request_queue *q, int __user *p)
        return put_user(1, p);
 }
 
-void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter)
+static void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter)
 {
        /* Basic read-only commands */
        __set_bit(TEST_UNIT_READY, filter->read_ok);
@@ -187,14 +192,37 @@ void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter)
        __set_bit(GPCMD_SET_STREAMING, filter->write_ok);
        __set_bit(GPCMD_SET_READ_AHEAD, filter->write_ok);
 }
-EXPORT_SYMBOL_GPL(blk_set_cmd_filter_defaults);
+
+int blk_verify_command(unsigned char *cmd, fmode_t has_write_perm)
+{
+       struct blk_cmd_filter *filter = &blk_default_cmd_filter;
+
+       /* root can do any command. */
+       if (capable(CAP_SYS_RAWIO))
+               return 0;
+
+       /* if there's no filter set, assume we're filtering everything out */
+       if (!filter)
+               return -EPERM;
+
+       /* Anybody who can open the device can do a read-safe command */
+       if (test_bit(cmd[0], filter->read_ok))
+               return 0;
+
+       /* Write-safe commands require a writable open */
+       if (test_bit(cmd[0], filter->write_ok) && has_write_perm)
+               return 0;
+
+       return -EPERM;
+}
+EXPORT_SYMBOL(blk_verify_command);
 
 static int blk_fill_sghdr_rq(struct request_queue *q, struct request *rq,
                             struct sg_io_hdr *hdr, fmode_t mode)
 {
        if (copy_from_user(rq->cmd, hdr->cmdp, hdr->cmd_len))
                return -EFAULT;
-       if (blk_verify_command(&q->cmd_filter, rq->cmd, mode & FMODE_WRITE))
+       if (blk_verify_command(rq->cmd, mode & FMODE_WRITE))
                return -EPERM;
 
        /*
@@ -427,7 +455,7 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
        if (in_len && copy_from_user(buffer, sic->data + cmdlen, in_len))
                goto error;
 
-       err = blk_verify_command(&q->cmd_filter, rq->cmd, mode & FMODE_WRITE);
+       err = blk_verify_command(rq->cmd, mode & FMODE_WRITE);
        if (err)
                goto error;
 
@@ -645,5 +673,11 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod
        blk_put_queue(q);
        return err;
 }
-
 EXPORT_SYMBOL(scsi_cmd_ioctl);
+
+int __init blk_scsi_ioctl_init(void)
+{
+       blk_set_cmd_filter_defaults(&blk_default_cmd_filter);
+       return 0;
+}
+fs_initcall(blk_scsi_ioctl_init);
index 56c62e2858d56a9eee11b9167fe8362a71a7c6c1..df0863d56995d7ca02c1e9492d3ab74de164ab14 100644 (file)
@@ -692,7 +692,7 @@ out:
 }
 EXPORT_SYMBOL_GPL(crypto_enqueue_request);
 
-struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
+void *__crypto_dequeue_request(struct crypto_queue *queue, unsigned int offset)
 {
        struct list_head *request;
 
@@ -707,7 +707,14 @@ struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
        request = queue->list.next;
        list_del(request);
 
-       return list_entry(request, struct crypto_async_request, list);
+       return (char *)list_entry(request, struct crypto_async_request, list) -
+              offset;
+}
+EXPORT_SYMBOL_GPL(__crypto_dequeue_request);
+
+struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
+{
+       return __crypto_dequeue_request(queue, 0);
 }
 EXPORT_SYMBOL_GPL(crypto_dequeue_request);
 
index 95fe2c8d6c516ea0325b9287df8775adb542cee7..90dd3f8bd283171ca725d75f7daae52fd0089ab1 100644 (file)
@@ -300,7 +300,7 @@ EXPORT_SYMBOL_GPL(async_xor_zero_sum);
 
 static int __init async_xor_init(void)
 {
-       #ifdef CONFIG_DMA_ENGINE
+       #ifdef CONFIG_ASYNC_TX_DMA
        /* To conserve stack space the input src_list (array of page pointers)
         * is reused to hold the array of dma addresses passed to the driver.
         * This conversion is only possible when dma_addr_t is less than the
index 7a0f4aa4fa1e355919301ccfb2bd82e4fac6e21b..9a62224cc27816b039d116cc1732acad7080fdb2 100644 (file)
@@ -38,6 +38,9 @@
 
 #define _COMPONENT             ACPI_MEMORY_DEVICE_COMPONENT
 
+#undef PREFIX
+#define        PREFIX          "ACPI:memory_hp:"
+
 ACPI_MODULE_NAME("acpi_memhotplug");
 MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
 MODULE_DESCRIPTION("Hotplug Mem Driver");
@@ -153,6 +156,7 @@ acpi_memory_get_device(acpi_handle handle,
        acpi_handle phandle;
        struct acpi_device *device = NULL;
        struct acpi_device *pdevice = NULL;
+       int result;
 
 
        if (!acpi_bus_get_device(handle, &device) && device)
@@ -165,9 +169,9 @@ acpi_memory_get_device(acpi_handle handle,
        }
 
        /* Get the parent device */
-       status = acpi_bus_get_device(phandle, &pdevice);
-       if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status, "Cannot get acpi bus device"));
+       result = acpi_bus_get_device(phandle, &pdevice);
+       if (result) {
+               printk(KERN_WARNING PREFIX "Cannot get acpi bus device");
                return -EINVAL;
        }
 
@@ -175,9 +179,9 @@ acpi_memory_get_device(acpi_handle handle,
         * Now add the notified device.  This creates the acpi_device
         * and invokes .add function
         */
-       status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
-       if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status, "Cannot add acpi bus"));
+       result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
+       if (result) {
+               printk(KERN_WARNING PREFIX "Cannot add acpi bus");
                return -EINVAL;
        }
 
@@ -238,7 +242,12 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
                        num_enabled++;
                        continue;
                }
-
+               /*
+                * If the memory block size is zero, please ignore it.
+                * Don't try to do the following memory hotplug flowchart.
+                */
+               if (!info->length)
+                       continue;
                if (node < 0)
                        node = memory_add_physaddr_to_nid(info->start_addr);
 
@@ -253,8 +262,15 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
                mem_device->state = MEMORY_INVALID_STATE;
                return -EINVAL;
        }
-
-       return result;
+       /*
+        * Sometimes the memory device will contain several memory blocks.
+        * When one memory block is hot-added to the system memory, it will
+        * be regarded as a success.
+        * Otherwise if the last memory block can't be hot-added to the system
+        * memory, it will be failure and the memory device can't be bound with
+        * driver.
+        */
+       return 0;
 }
 
 static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
index 544dcf834922cb6c324bc3faa44cdd83fb657f75..eb6f038b03d9f23d8479fe1a2caa40bab2ee2cb3 100644 (file)
@@ -97,6 +97,7 @@
 #define AOPOBJ_OBJECT_INITIALIZED   0x08
 #define AOPOBJ_SETUP_COMPLETE       0x10
 #define AOPOBJ_SINGLE_DATUM         0x20
+#define AOPOBJ_INVALID              0x40       /* Used if host OS won't allow an op_region address */
 
 /******************************************************************************
  *
index 584d766e6f124248c1b496731df225fd94fa0099..b79978f7bc7172f5ca7e3d60a8fa380576dd009d 100644 (file)
@@ -397,6 +397,30 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
        status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
                                           extra_desc->extra.aml_length,
                                           extra_desc->extra.aml_start);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       /* Validate the region address/length via the host OS */
+
+       status = acpi_os_validate_address(obj_desc->region.space_id,
+                                         obj_desc->region.address,
+                                         (acpi_size) obj_desc->region.length,
+                                         acpi_ut_get_node_name(node));
+
+       if (ACPI_FAILURE(status)) {
+               /*
+                * Invalid address/length. We will emit an error message and mark
+                * the region as invalid, so that it will cause an additional error if
+                * it is ever used. Then return AE_OK.
+                */
+               ACPI_EXCEPTION((AE_INFO, status,
+                               "During address validation of OpRegion [%4.4s]",
+                               node->name.ascii));
+               obj_desc->common.flags |= AOPOBJ_INVALID;
+               status = AE_OK;
+       }
+
        return_ACPI_STATUS(status);
 }
 
index d4075b8210217ecc5c503b54b4831aabe7ad83c2..6687be167f5f67c6d6b30c5c6b24d3cfd19a7346 100644 (file)
@@ -113,6 +113,12 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
                }
        }
 
+       /* Exit if Address/Length have been disallowed by the host OS */
+
+       if (rgn_desc->common.flags & AOPOBJ_INVALID) {
+               return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
+       }
+
        /*
         * Exit now for SMBus address space, it has a non-linear address space
         * and the request cannot be directly validated
index 67340cc70142209d1aa97ae360b21587cefc321b..257706e7734f786dbe8e8d760283ef2751859838 100644 (file)
@@ -70,6 +70,12 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
 
        ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc);
 
+       /* If Source and Target are the same, just return */
+
+       if (source_desc == target_desc) {
+               return_ACPI_STATUS(AE_OK);
+       }
+
        /* We know that source_desc is a buffer by now */
 
        buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer);
@@ -161,6 +167,12 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc,
 
        ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc);
 
+       /* If Source and Target are the same, just return */
+
+       if (source_desc == target_desc) {
+               return_ACPI_STATUS(AE_OK);
+       }
+
        /* We know that source_desc is a string by now */
 
        buffer = ACPI_CAST_PTR(u8, source_desc->string.pointer);
index 71670719d61a6fec442792189fa0beac85e0324d..5691f165a9527f209c7fcac6febbd73cae43bb65 100644 (file)
@@ -189,11 +189,36 @@ acpi_status __init acpi_os_initialize(void)
        return AE_OK;
 }
 
+static void bind_to_cpu0(struct work_struct *work)
+{
+       set_cpus_allowed(current, cpumask_of_cpu(0));
+       kfree(work);
+}
+
+static void bind_workqueue(struct workqueue_struct *wq)
+{
+       struct work_struct *work;
+
+       work = kzalloc(sizeof(struct work_struct), GFP_KERNEL);
+       INIT_WORK(work, bind_to_cpu0);
+       queue_work(wq, work);
+}
+
 acpi_status acpi_os_initialize1(void)
 {
+       /*
+        * On some machines, a software-initiated SMI causes corruption unless
+        * the SMI runs on CPU 0.  An SMI can be initiated by any AML, but
+        * typically it's done in GPE-related methods that are run via
+        * workqueues, so we can avoid the known corruption cases by binding
+        * the workqueues to CPU 0.
+        */
        kacpid_wq = create_singlethread_workqueue("kacpid");
+       bind_workqueue(kacpid_wq);
        kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify");
+       bind_workqueue(kacpi_notify_wq);
        kacpi_hotplug_wq = create_singlethread_workqueue("kacpi_hotplug");
+       bind_workqueue(kacpi_hotplug_wq);
        BUG_ON(!kacpid_wq);
        BUG_ON(!kacpi_notify_wq);
        BUG_ON(!kacpi_hotplug_wq);
index 8a5bf3b356faa2d60c40f0c1f6aef6279d9d57c8..55b5b90c2a44288f786d266a7cc5810b215ba227 100644 (file)
@@ -395,7 +395,7 @@ struct pci_dev *acpi_get_pci_dev(acpi_handle handle)
                fn  = adr & 0xffff;
 
                pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn));
-               if (hnd == handle)
+               if (!pdev || hnd == handle)
                        break;
 
                pbus = pdev->subordinate;
index 84e0f3c0744270b4c8474f92239b64255a27985b..2cc4b3033872979bd7a1fbeeae055ca077aba227 100644 (file)
@@ -1151,6 +1151,9 @@ static int __init acpi_processor_init(void)
 {
        int result = 0;
 
+       if (acpi_disabled)
+               return 0;
+
        memset(&errata, 0, sizeof(errata));
 
 #ifdef CONFIG_SMP
@@ -1197,6 +1200,9 @@ out_proc:
 
 static void __exit acpi_processor_exit(void)
 {
+       if (acpi_disabled)
+               return;
+
        acpi_processor_ppc_exit();
 
        acpi_thermal_cpufreq_exit();
index 0efa59e7e3afd16095fa538f333f11f37ca7a9d4..66393d5c4c7c9ccff78ea22f4635f6e1a14694f7 100644 (file)
@@ -162,8 +162,9 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr,
                pr->power.timer_broadcast_on_state = state;
 }
 
-static void lapic_timer_propagate_broadcast(struct acpi_processor *pr)
+static void lapic_timer_propagate_broadcast(void *arg)
 {
+       struct acpi_processor *pr = (struct acpi_processor *) arg;
        unsigned long reason;
 
        reason = pr->power.timer_broadcast_on_state < INT_MAX ?
@@ -635,7 +636,8 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
                working++;
        }
 
-       lapic_timer_propagate_broadcast(pr);
+       smp_call_function_single(pr->id, lapic_timer_propagate_broadcast,
+                                pr, 1);
 
        return (working);
 }
index 39838c66603265bd188f398b07fdd494a0699589..31adda1099e0d451f68ef399b8f8c0f5832f21c5 100644 (file)
@@ -66,7 +66,7 @@ static int acpi_processor_apply_limit(struct acpi_processor *pr)
                if (pr->limit.thermal.tx > tx)
                        tx = pr->limit.thermal.tx;
 
-               result = acpi_processor_set_throttling(pr, tx);
+               result = acpi_processor_set_throttling(pr, tx, false);
                if (result)
                        goto end;
        }
@@ -421,12 +421,12 @@ processor_set_cur_state(struct thermal_cooling_device *cdev,
 
        if (state <= max_pstate) {
                if (pr->flags.throttling && pr->throttling.state)
-                       result = acpi_processor_set_throttling(pr, 0);
+                       result = acpi_processor_set_throttling(pr, 0, false);
                cpufreq_set_cur_state(pr->id, state);
        } else {
                cpufreq_set_cur_state(pr->id, max_pstate);
                result = acpi_processor_set_throttling(pr,
-                               state - max_pstate);
+                               state - max_pstate, false);
        }
        return result;
 }
index 227543789ba91db984862f52040fc18d1a7758e9..ae39797aab55cc860debf1a749a1cf858edd9b64 100644 (file)
@@ -62,7 +62,8 @@ struct throttling_tstate {
 #define THROTTLING_POSTCHANGE      (2)
 
 static int acpi_processor_get_throttling(struct acpi_processor *pr);
-int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
+int acpi_processor_set_throttling(struct acpi_processor *pr,
+                                               int state, bool force);
 
 static int acpi_processor_update_tsd_coord(void)
 {
@@ -361,7 +362,7 @@ int acpi_processor_tstate_has_changed(struct acpi_processor *pr)
                 */
                target_state = throttling_limit;
        }
-       return acpi_processor_set_throttling(pr, target_state);
+       return acpi_processor_set_throttling(pr, target_state, false);
 }
 
 /*
@@ -839,10 +840,10 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
        if (ret >= 0) {
                state = acpi_get_throttling_state(pr, value);
                if (state == -1) {
-                       ACPI_WARNING((AE_INFO,
-                               "Invalid throttling state, reset"));
+                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                               "Invalid throttling state, reset\n"));
                        state = 0;
-                       ret = acpi_processor_set_throttling(pr, state);
+                       ret = acpi_processor_set_throttling(pr, state, true);
                        if (ret)
                                return ret;
                }
@@ -915,7 +916,7 @@ static int acpi_processor_get_fadt_info(struct acpi_processor *pr)
 }
 
 static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr,
-                                             int state)
+                                             int state, bool force)
 {
        u32 value = 0;
        u32 duty_mask = 0;
@@ -930,7 +931,7 @@ static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr,
        if (!pr->flags.throttling)
                return -ENODEV;
 
-       if (state == pr->throttling.state)
+       if (!force && (state == pr->throttling.state))
                return 0;
 
        if (state < pr->throttling_platform_limit)
@@ -988,7 +989,7 @@ static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr,
 }
 
 static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
-                                            int state)
+                                            int state, bool force)
 {
        int ret;
        acpi_integer value;
@@ -1002,7 +1003,7 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
        if (!pr->flags.throttling)
                return -ENODEV;
 
-       if (state == pr->throttling.state)
+       if (!force && (state == pr->throttling.state))
                return 0;
 
        if (state < pr->throttling_platform_limit)
@@ -1018,7 +1019,8 @@ static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
        return 0;
 }
 
-int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
+int acpi_processor_set_throttling(struct acpi_processor *pr,
+                                               int state, bool force)
 {
        cpumask_var_t saved_mask;
        int ret = 0;
@@ -1070,7 +1072,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
                /* FIXME: use work_on_cpu() */
                set_cpus_allowed_ptr(current, cpumask_of(pr->id));
                ret = p_throttling->acpi_processor_set_throttling(pr,
-                                               t_state.target_state);
+                                               t_state.target_state, force);
        } else {
                /*
                 * When the T-state coordination is SW_ALL or HW_ALL,
@@ -1103,7 +1105,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state)
                        set_cpus_allowed_ptr(current, cpumask_of(i));
                        ret = match_pr->throttling.
                                acpi_processor_set_throttling(
-                               match_pr, t_state.target_state);
+                               match_pr, t_state.target_state, force);
                }
        }
        /*
@@ -1201,7 +1203,7 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Disabling throttling (was T%d)\n",
                                  pr->throttling.state));
-               result = acpi_processor_set_throttling(pr, 0);
+               result = acpi_processor_set_throttling(pr, 0, false);
                if (result)
                        goto end;
        }
@@ -1307,7 +1309,7 @@ static ssize_t acpi_processor_write_throttling(struct file *file,
        if (strcmp(tmpbuf, charp) != 0)
                return -EINVAL;
 
-       result = acpi_processor_set_throttling(pr, state_val);
+       result = acpi_processor_set_throttling(pr, state_val, false);
        if (result)
                return result;
 
index 01574a06653482a080e21973e44e535824666876..42159a28f4332f8dace6c4089c98ebbc86683209 100644 (file)
@@ -397,6 +397,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
                },
        },
        {
+       .callback = init_set_sci_en_on_resume,
+       .ident = "Hewlett-Packard HP G7000 Notebook PC",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP G7000 Notebook PC"),
+               },
+       },
+       {
        .callback = init_old_suspend_ordering,
        .ident = "Panasonic CF51-2L",
        .matches = {
index 0944daec064ff325b00d1823c81ae3dda649247e..9c61ab2177cf11a558f67877cff45709c3698a06 100644 (file)
@@ -121,7 +121,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
        table_attr->attr.size = 0;
        table_attr->attr.read = acpi_table_show;
        table_attr->attr.attr.name = table_attr->name;
-       table_attr->attr.attr.mode = 0444;
+       table_attr->attr.attr.mode = 0400;
 
        return;
 }
index 8851315ce858a2e2eb1e4ffd2d2b6b695fa8bfb8..60ea984c84a02c651b606d6d42aa4b3610c21882 100644 (file)
@@ -2004,8 +2004,11 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
        status = acpi_remove_notify_handler(device->dev->handle,
                                            ACPI_DEVICE_NOTIFY,
                                            acpi_video_device_notify);
-       sysfs_remove_link(&device->backlight->dev.kobj, "device");
-       backlight_device_unregister(device->backlight);
+       if (device->backlight) {
+               sysfs_remove_link(&device->backlight->dev.kobj, "device");
+               backlight_device_unregister(device->backlight);
+               device->backlight = NULL;
+       }
        if (device->cdev) {
                sysfs_remove_link(&device->dev->dev.kobj,
                                  "thermal_cooling");
index 3d763fdf99b7d2409f8dbf425822ace5f1063cea..246650673010594d08c139551da1973318f78685 100644 (file)
@@ -207,6 +207,16 @@ int amba_device_register(struct amba_device *dev, struct resource *parent)
        void __iomem *tmp;
        int i, ret;
 
+       device_initialize(&dev->dev);
+
+       /*
+        * Copy from device_add
+        */
+       if (dev->dev.init_name) {
+               dev_set_name(&dev->dev, "%s", dev->dev.init_name);
+               dev->dev.init_name = NULL;
+       }
+
        dev->dev.release = amba_device_release;
        dev->dev.bus = &amba_bustype;
        dev->dev.dma_mask = &dev->dma_mask;
@@ -240,7 +250,7 @@ int amba_device_register(struct amba_device *dev, struct resource *parent)
                goto err_release;
        }
 
-       ret = device_register(&dev->dev);
+       ret = device_add(&dev->dev);
        if (ret)
                goto err_release;
 
index 15a23031833f46e921957c48578723caf9b2446e..fe3eba5d6b3ef93633cbe3dfc76827d986ed04cf 100644 (file)
@@ -219,6 +219,8 @@ enum {
        AHCI_HFLAG_SECT255              = (1 << 8), /* max 255 sectors */
        AHCI_HFLAG_YES_NCQ              = (1 << 9), /* force NCQ cap on */
        AHCI_HFLAG_NO_SUSPEND           = (1 << 10), /* don't suspend */
+       AHCI_HFLAG_SRST_TOUT_IS_OFFLINE = (1 << 11), /* treat SRST timeout as
+                                                       link offline */
 
        /* ap->flags bits */
 
@@ -513,11 +515,16 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
        { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
        { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
+       { PCI_VDEVICE(INTEL, 0x3a22), board_ahci }, /* ICH10 */
        { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
+       { PCI_VDEVICE(INTEL, 0x3b22), board_ahci }, /* PCH AHCI */
+       { PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
        { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
        { PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
+       { PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */
        { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
        { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
+       { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
 
        /* JMicron 360/1/3/5/6, match class to avoid IDE function */
        { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -1658,6 +1665,7 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
                             int (*check_ready)(struct ata_link *link))
 {
        struct ata_port *ap = link->ap;
+       struct ahci_host_priv *hpriv = ap->host->private_data;
        const char *reason = NULL;
        unsigned long now, msecs;
        struct ata_taskfile tf;
@@ -1696,12 +1704,21 @@ static int ahci_do_softreset(struct ata_link *link, unsigned int *class,
 
        /* wait for link to become ready */
        rc = ata_wait_after_reset(link, deadline, check_ready);
-       /* link occupied, -ENODEV too is an error */
-       if (rc) {
+       if (rc == -EBUSY && hpriv->flags & AHCI_HFLAG_SRST_TOUT_IS_OFFLINE) {
+               /*
+                * Workaround for cases where link online status can't
+                * be trusted.  Treat device readiness timeout as link
+                * offline.
+                */
+               ata_link_printk(link, KERN_INFO,
+                               "device not ready, treating as offline\n");
+               *class = ATA_DEV_NONE;
+       } else if (rc) {
+               /* link occupied, -ENODEV too is an error */
                reason = "device not ready";
                goto fail;
-       }
-       *class = ahci_dev_classify(ap);
+       } else
+               *class = ahci_dev_classify(ap);
 
        DPRINTK("EXIT, class=%u\n", *class);
        return 0;
@@ -1768,7 +1785,8 @@ static int ahci_sb600_softreset(struct ata_link *link, unsigned int *class,
                irq_sts = readl(port_mmio + PORT_IRQ_STAT);
                if (irq_sts & PORT_IRQ_BAD_PMP) {
                        ata_link_printk(link, KERN_WARNING,
-                                       "failed due to HW bug, retry pmp=0\n");
+                                       "applying SB600 PMP SRST workaround "
+                                       "and retrying\n");
                        rc = ahci_do_softreset(link, class, 0, deadline,
                                               ahci_check_ready);
                }
@@ -2721,6 +2739,56 @@ static bool ahci_broken_suspend(struct pci_dev *pdev)
        return !ver || strcmp(ver, dmi->driver_data) < 0;
 }
 
+static bool ahci_broken_online(struct pci_dev *pdev)
+{
+#define ENCODE_BUSDEVFN(bus, slot, func)                       \
+       (void *)(unsigned long)(((bus) << 8) | PCI_DEVFN((slot), (func)))
+       static const struct dmi_system_id sysids[] = {
+               /*
+                * There are several gigabyte boards which use
+                * SIMG5723s configured as hardware RAID.  Certain
+                * 5723 firmware revisions shipped there keep the link
+                * online but fail to answer properly to SRST or
+                * IDENTIFY when no device is attached downstream
+                * causing libata to retry quite a few times leading
+                * to excessive detection delay.
+                *
+                * As these firmwares respond to the second reset try
+                * with invalid device signature, considering unknown
+                * sig as offline works around the problem acceptably.
+                */
+               {
+                       .ident = "EP45-DQ6",
+                       .matches = {
+                               DMI_MATCH(DMI_BOARD_VENDOR,
+                                         "Gigabyte Technology Co., Ltd."),
+                               DMI_MATCH(DMI_BOARD_NAME, "EP45-DQ6"),
+                       },
+                       .driver_data = ENCODE_BUSDEVFN(0x0a, 0x00, 0),
+               },
+               {
+                       .ident = "EP45-DS5",
+                       .matches = {
+                               DMI_MATCH(DMI_BOARD_VENDOR,
+                                         "Gigabyte Technology Co., Ltd."),
+                               DMI_MATCH(DMI_BOARD_NAME, "EP45-DS5"),
+                       },
+                       .driver_data = ENCODE_BUSDEVFN(0x03, 0x00, 0),
+               },
+               { }     /* terminate list */
+       };
+#undef ENCODE_BUSDEVFN
+       const struct dmi_system_id *dmi = dmi_first_match(sysids);
+       unsigned int val;
+
+       if (!dmi)
+               return false;
+
+       val = (unsigned long)dmi->driver_data;
+
+       return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
+}
+
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int printed_version;
@@ -2836,6 +2904,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                           "BIOS update required for suspend/resume\n");
        }
 
+       if (ahci_broken_online(pdev)) {
+               hpriv->flags |= AHCI_HFLAG_SRST_TOUT_IS_OFFLINE;
+               dev_info(&pdev->dev,
+                        "online status unreliable, applying workaround\n");
+       }
+
        /* CAP.NP sometimes indicate the index of the last enabled
         * port, at other times, that of the last possible port, so
         * determining the maximum port number requires looking at
index d0a14cf2bd741240296122e5da4b83a81b496c08..9ac4e378992ef60d71634121379b91479c8660f2 100644 (file)
@@ -596,9 +596,12 @@ static const struct ich_laptop ich_laptop[] = {
        { 0x27DF, 0x0005, 0x0280 },     /* ICH7 on Acer 5602WLMi */
        { 0x27DF, 0x1025, 0x0102 },     /* ICH7 on Acer 5602aWLMi */
        { 0x27DF, 0x1025, 0x0110 },     /* ICH7 on Acer 3682WLMi */
+       { 0x27DF, 0x1028, 0x02b0 },     /* ICH7 on unknown Dell */
        { 0x27DF, 0x1043, 0x1267 },     /* ICH7 on Asus W5F */
        { 0x27DF, 0x103C, 0x30A1 },     /* ICH7 on HP Compaq nc2400 */
+       { 0x27DF, 0x103C, 0x361a },     /* ICH7 on unkown HP  */
        { 0x27DF, 0x1071, 0xD221 },     /* ICH7 on Hercules EC-900 */
+       { 0x27DF, 0x152D, 0x0778 },     /* ICH7 on unknown Intel */
        { 0x24CA, 0x1025, 0x0061 },     /* ICH4 on ACER Aspire 2023WLMi */
        { 0x24CA, 0x1025, 0x003d },     /* ICH4 on ACER TM290 */
        { 0x266F, 0x1025, 0x0066 },     /* ICH6 on ACER Aspire 1694WLMi */
@@ -661,6 +664,8 @@ static int piix_pata_prereset(struct ata_link *link, unsigned long deadline)
        return ata_sff_prereset(link, deadline);
 }
 
+static DEFINE_SPINLOCK(piix_lock);
+
 /**
  *     piix_set_piomode - Initialize host controller PATA PIO timings
  *     @ap: Port whose timings we are configuring
@@ -674,8 +679,9 @@ static int piix_pata_prereset(struct ata_link *link, unsigned long deadline)
 
 static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
-       unsigned int pio        = adev->pio_mode - XFER_PIO_0;
        struct pci_dev *dev     = to_pci_dev(ap->host->dev);
+       unsigned long flags;
+       unsigned int pio        = adev->pio_mode - XFER_PIO_0;
        unsigned int is_slave   = (adev->devno != 0);
        unsigned int master_port= ap->port_no ? 0x42 : 0x40;
        unsigned int slave_port = 0x44;
@@ -705,6 +711,8 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
        if (adev->class == ATA_DEV_ATA)
                control |= 4;   /* PPE enable */
 
+       spin_lock_irqsave(&piix_lock, flags);
+
        /* PIO configuration clears DTE unconditionally.  It will be
         * programmed in set_dmamode which is guaranteed to be called
         * after set_piomode if any DMA mode is available.
@@ -744,6 +752,8 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
                udma_enable &= ~(1 << (2 * ap->port_no + adev->devno));
                pci_write_config_byte(dev, 0x48, udma_enable);
        }
+
+       spin_unlock_irqrestore(&piix_lock, flags);
 }
 
 /**
@@ -761,6 +771,7 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
 static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, int isich)
 {
        struct pci_dev *dev     = to_pci_dev(ap->host->dev);
+       unsigned long flags;
        u8 master_port          = ap->port_no ? 0x42 : 0x40;
        u16 master_data;
        u8 speed                = adev->dma_mode;
@@ -774,6 +785,8 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in
                            { 2, 1 },
                            { 2, 3 }, };
 
+       spin_lock_irqsave(&piix_lock, flags);
+
        pci_read_config_word(dev, master_port, &master_data);
        if (ap->udma_mask)
                pci_read_config_byte(dev, 0x48, &udma_enable);
@@ -864,6 +877,8 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in
        /* Don't scribble on 0x48 if the controller does not support UDMA */
        if (ap->udma_mask)
                pci_write_config_byte(dev, 0x48, udma_enable);
+
+       spin_unlock_irqrestore(&piix_lock, flags);
 }
 
 /**
index 045a486a09eae25a16174a7c697e52796dcbc503..072ba5ea138f8363a4b108091d0295353792e09a 100644 (file)
@@ -1515,6 +1515,7 @@ static int ata_hpa_resize(struct ata_device *dev)
 
                return rc;
        }
+       dev->n_native_sectors = native_sectors;
 
        /* nothing to do? */
        if (native_sectors <= sectors || !ata_ignore_hpa) {
@@ -3392,17 +3393,27 @@ int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel)
 
 static int ata_dev_set_mode(struct ata_device *dev)
 {
+       struct ata_port *ap = dev->link->ap;
        struct ata_eh_context *ehc = &dev->link->eh_context;
+       const bool nosetxfer = dev->horkage & ATA_HORKAGE_NOSETXFER;
        const char *dev_err_whine = "";
        int ign_dev_err = 0;
-       unsigned int err_mask;
+       unsigned int err_mask = 0;
        int rc;
 
        dev->flags &= ~ATA_DFLAG_PIO;
        if (dev->xfer_shift == ATA_SHIFT_PIO)
                dev->flags |= ATA_DFLAG_PIO;
 
-       err_mask = ata_dev_set_xfermode(dev);
+       if (nosetxfer && ap->flags & ATA_FLAG_SATA && ata_id_is_sata(dev->id))
+               dev_err_whine = " (SET_XFERMODE skipped)";
+       else {
+               if (nosetxfer)
+                       ata_dev_printk(dev, KERN_WARNING,
+                                      "NOSETXFER but PATA detected - can't "
+                                      "skip SETXFER, might malfunction\n");
+               err_mask = ata_dev_set_xfermode(dev);
+       }
 
        if (err_mask & ~AC_ERR_DEV)
                goto fail;
@@ -4089,6 +4100,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
                       unsigned int readid_flags)
 {
        u64 n_sectors = dev->n_sectors;
+       u64 n_native_sectors = dev->n_native_sectors;
        int rc;
 
        if (!ata_dev_enabled(dev))
@@ -4118,16 +4130,30 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
        /* verify n_sectors hasn't changed */
        if (dev->class == ATA_DEV_ATA && n_sectors &&
            dev->n_sectors != n_sectors) {
-               ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch "
+               ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch "
                               "%llu != %llu\n",
                               (unsigned long long)n_sectors,
                               (unsigned long long)dev->n_sectors);
-
-               /* restore original n_sectors */
-               dev->n_sectors = n_sectors;
-
-               rc = -ENODEV;
-               goto fail;
+               /*
+                * Something could have caused HPA to be unlocked
+                * involuntarily.  If n_native_sectors hasn't changed
+                * and the new size matches it, keep the device.
+                */
+               if (dev->n_native_sectors == n_native_sectors &&
+                   dev->n_sectors > n_sectors &&
+                   dev->n_sectors == n_native_sectors) {
+                       ata_dev_printk(dev, KERN_WARNING,
+                                      "new n_sectors matches native, probably "
+                                      "late HPA unlock, continuing\n");
+                       /* keep using the old n_sectors */
+                       dev->n_sectors = n_sectors;
+               } else {
+                       /* restore original n_[native]_sectors and fail */
+                       dev->n_native_sectors = n_native_sectors;
+                       dev->n_sectors = n_sectors;
+                       rc = -ENODEV;
+                       goto fail;
+               }
        }
 
        return 0;
@@ -4276,6 +4302,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "WDC WD2500JD-00HBB0", "WD-WMAL71490727", ATA_HORKAGE_BROKEN_HPA },
        { "MAXTOR 6L080L4",     "A93.0500",     ATA_HORKAGE_BROKEN_HPA },
 
+       /* this one allows HPA unlocking but fails IOs on the area */
+       { "OCZ-VERTEX",             "1.30",     ATA_HORKAGE_BROKEN_HPA },
+
        /* Devices which report 1 sector over size HPA */
        { "ST340823A",          NULL,           ATA_HORKAGE_HPA_SIZE, },
        { "ST320413A",          NULL,           ATA_HORKAGE_HPA_SIZE, },
@@ -4297,6 +4326,12 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        /* Devices which aren't very happy with higher link speeds */
        { "WD My Book",                 NULL,   ATA_HORKAGE_1_5_GBPS, },
 
+       /*
+        * Devices which choke on SETXFER.  Applies only if both the
+        * device and controller are SATA.
+        */
+       { "PIONEER DVD-RW  DVRTD08",    "1.00", ATA_HORKAGE_NOSETXFER },
+
        /* End Marker */
        { }
 };
index fa22f94ca4150247b39a0e26fa7541d4cbee4ba4..79711b64054bde8d3d5815fc09aeca08ad3bf00d 100644 (file)
@@ -2327,7 +2327,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
        struct ata_port *ap = link->ap;
        struct ata_link *slave = ap->slave_link;
        struct ata_eh_context *ehc = &link->eh_context;
-       struct ata_eh_context *sehc = &slave->eh_context;
+       struct ata_eh_context *sehc = slave ? &slave->eh_context : NULL;
        unsigned int *classes = ehc->classes;
        unsigned int lflags = link->flags;
        int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
@@ -2517,6 +2517,10 @@ int ata_eh_reset(struct ata_link *link, int classify,
 
                        ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
                        rc = ata_do_reset(link, reset, classes, deadline, true);
+                       if (rc) {
+                               failed_link = link;
+                               goto fail;
+                       }
                }
        } else {
                if (verbose)
index 4b27617be26da7ecfadd5ac53476237348559310..41c94b1ae4930b4a44e56a57e3e6dde6cd832e3b 100644 (file)
@@ -26,9 +26,7 @@
 #include <linux/platform_device.h>
 #include <linux/ata_platform.h>
 
-#include <mach/at91sam9260_matrix.h>
 #include <mach/at91sam9_smc.h>
-#include <mach/at91sam9260.h>
 #include <mach/board.h>
 #include <mach/gpio.h>
 
@@ -44,65 +42,62 @@ struct at91_ide_info {
        unsigned long mode;
        unsigned int cs;
 
+       struct clk *mck;
+
        void __iomem *ide_addr;
        void __iomem *alt_addr;
 };
 
-const struct ata_timing initial_timing =
+static const struct ata_timing initial_timing =
        {XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0};
 
-static unsigned int calc_mck_cycles(unsigned int ns, unsigned int mck_hz)
+static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz)
 {
        unsigned long mul;
 
-    /*
-     * cycles = x [nsec] * f [Hz] / 10^9 [ns in sec] =
-     *     x * (f / 1_000_000_000) =
-     *     x * ((f * 65536) / 1_000_000_000) / 65536 =
-     *     x * (((f / 10_000) * 65536) / 100_000) / 65536 =
-     */
+       /*
+       * cycles = x [nsec] * f [Hz] / 10^9 [ns in sec] =
+       *     x * (f / 1_000_000_000) =
+       *     x * ((f * 65536) / 1_000_000_000) / 65536 =
+       *     x * (((f / 10_000) * 65536) / 100_000) / 65536 =
+       */
 
-    mul = (mck_hz / 10000) << 16;
-    mul /= 100000;
+       mul = (mck_hz / 10000) << 16;
+       mul /= 100000;
 
-    return (ns * mul + 65536) >> 16;    /* rounding */
+       return (ns * mul + 65536) >> 16;    /* rounding */
 }
 
 static void set_smc_mode(struct at91_ide_info *info)
 {
-    at91_sys_write(AT91_SMC_MODE(info->cs), info->mode);
-    return;
+       at91_sys_write(AT91_SMC_MODE(info->cs), info->mode);
+       return;
 }
 
 static void set_smc_timing(struct device *dev,
                struct at91_ide_info *info, const struct ata_timing *ata)
 {
-       int read_cycle, write_cycle, active, recover;
-       int nrd_setup, nrd_pulse, nrd_recover;
-       int nwe_setup, nwe_pulse;
+       unsigned long read_cycle, write_cycle, active, recover;
+       unsigned long nrd_setup, nrd_pulse, nrd_recover;
+       unsigned long nwe_setup, nwe_pulse;
 
-       int ncs_write_setup, ncs_write_pulse;
-       int ncs_read_setup, ncs_read_pulse;
+       unsigned long ncs_write_setup, ncs_write_pulse;
+       unsigned long ncs_read_setup, ncs_read_pulse;
 
-       unsigned int mck_hz;
-       struct clk *mck;
+       unsigned long mck_hz;
 
        read_cycle  = ata->cyc8b;
        nrd_setup   = ata->setup;
        nrd_pulse   = ata->act8b;
        nrd_recover = ata->rec8b;
 
-       mck = clk_get(NULL, "mck");
-       BUG_ON(IS_ERR(mck));
-       mck_hz = clk_get_rate(mck);
+       mck_hz = clk_get_rate(info->mck);
 
        read_cycle  = calc_mck_cycles(read_cycle, mck_hz);
        nrd_setup   = calc_mck_cycles(nrd_setup, mck_hz);
        nrd_pulse   = calc_mck_cycles(nrd_pulse, mck_hz);
        nrd_recover = calc_mck_cycles(nrd_recover, mck_hz);
 
-       clk_put(mck);
-
        active  = nrd_setup + nrd_pulse;
        recover = read_cycle - active;
 
@@ -121,13 +116,13 @@ static void set_smc_timing(struct device *dev,
        ncs_write_setup = ncs_read_setup;
        ncs_write_pulse = ncs_read_pulse;
 
-       dev_dbg(dev, "ATA timings: nrd_setup = %d nrd_pulse = %d nrd_cycle = %d\n",
+       dev_dbg(dev, "ATA timings: nrd_setup = %lu nrd_pulse = %lu nrd_cycle = %lu\n",
                        nrd_setup, nrd_pulse, read_cycle);
-       dev_dbg(dev, "ATA timings: nwe_setup = %d nwe_pulse = %d nwe_cycle = %d\n",
+       dev_dbg(dev, "ATA timings: nwe_setup = %lu nwe_pulse = %lu nwe_cycle = %lu\n",
                        nwe_setup, nwe_pulse, write_cycle);
-       dev_dbg(dev, "ATA timings: ncs_read_setup = %d ncs_read_pulse = %d\n",
+       dev_dbg(dev, "ATA timings: ncs_read_setup = %lu ncs_read_pulse = %lu\n",
                        ncs_read_setup, ncs_read_pulse);
-       dev_dbg(dev, "ATA timings: ncs_write_setup = %d ncs_write_pulse = %d\n",
+       dev_dbg(dev, "ATA timings: ncs_write_setup = %lu ncs_write_pulse = %lu\n",
                        ncs_write_setup, ncs_write_pulse);
 
        at91_sys_write(AT91_SMC_SETUP(info->cs),
@@ -217,6 +212,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
        struct resource *mem_res;
        struct ata_host *host;
        struct ata_port *ap;
+
        int irq_flags = 0;
        int irq = 0;
        int ret;
@@ -254,13 +250,20 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
                ata_port_desc(ap, "no IRQ, using PIO polling");
        }
 
-       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
 
        if (!info) {
                dev_err(dev, "failed to allocate memory for private data\n");
                return -ENOMEM;
        }
 
+       info->mck = clk_get(NULL, "mck");
+
+       if (IS_ERR(info->mck)) {
+               dev_err(dev, "failed to get access to mck clock\n");
+               return -ENODEV;
+       }
+
        info->cs    = board->chipselect;
        info->mode  = AT91_SMC_READMODE | AT91_SMC_WRITEMODE |
                AT91_SMC_EXNWMODE_READY | AT91_SMC_BAT_SELECT |
@@ -272,7 +275,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
        if (!info->ide_addr) {
                dev_err(dev, "failed to map IO base\n");
                ret = -ENOMEM;
-               goto err_ide_ioremap;
+               goto err_put;
        }
 
        info->alt_addr = devm_ioremap(dev,
@@ -281,7 +284,7 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
        if (!info->alt_addr) {
                dev_err(dev, "failed to map CTL base\n");
                ret = -ENOMEM;
-               goto err_alt_ioremap;
+               goto err_put;
        }
 
        ap->ioaddr.cmd_addr = info->ide_addr;
@@ -300,33 +303,27 @@ static int __devinit pata_at91_probe(struct platform_device *pdev)
                        irq ? ata_sff_interrupt : NULL,
                        irq_flags, &pata_at91_sht);
 
-err_alt_ioremap:
-       devm_iounmap(dev, info->ide_addr);
-
-err_ide_ioremap:
-       kfree(info);
-
+err_put:
+       clk_put(info->mck);
        return ret;
 }
 
 static int __devexit pata_at91_remove(struct platform_device *pdev)
 {
        struct ata_host *host = dev_get_drvdata(&pdev->dev);
-       struct at91_ide_info *info = host->private_data;
-       struct device *dev = &pdev->dev;
+       struct at91_ide_info *info;
 
        if (!host)
                return 0;
+       info = host->private_data;
 
        ata_host_detach(host);
 
        if (!info)
                return 0;
 
-       devm_iounmap(dev, info->ide_addr);
-       devm_iounmap(dev, info->alt_addr);
+       clk_put(info->mck);
 
-       kfree(info);
        return 0;
 }
 
index bec0b8ade66d846c43fcbcc7328daec82cb4925c..45915566e4e9e63caecd553fdb1ec1739c5582af 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * pata_atiixp.c       - ATI PATA for new ATA layer
  *                       (C) 2005 Red Hat Inc
+ *                       (C) 2009 Bartlomiej Zolnierkiewicz
  *
  * Based on
  *
@@ -61,20 +62,19 @@ static void atiixp_set_pio_timing(struct ata_port *ap, struct ata_device *adev,
 
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        int dn = 2 * ap->port_no + adev->devno;
-
-       /* Check this is correct - the order is odd in both drivers */
        int timing_shift = (16 * ap->port_no) + 8 * (adev->devno ^ 1);
-       u16 pio_mode_data, pio_timing_data;
+       u32 pio_timing_data;
+       u16 pio_mode_data;
 
        pci_read_config_word(pdev, ATIIXP_IDE_PIO_MODE, &pio_mode_data);
        pio_mode_data &= ~(0x7 << (4 * dn));
        pio_mode_data |= pio << (4 * dn);
        pci_write_config_word(pdev, ATIIXP_IDE_PIO_MODE, pio_mode_data);
 
-       pci_read_config_word(pdev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
+       pci_read_config_dword(pdev, ATIIXP_IDE_PIO_TIMING, &pio_timing_data);
        pio_timing_data &= ~(0xFF << timing_shift);
        pio_timing_data |= (pio_timings[pio] << timing_shift);
-       pci_write_config_word(pdev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
+       pci_write_config_dword(pdev, ATIIXP_IDE_PIO_TIMING, pio_timing_data);
 }
 
 /**
@@ -119,16 +119,17 @@ static void atiixp_set_dmamode(struct ata_port *ap, struct ata_device *adev)
                udma_mode_data |= dma << (4 * dn);
                pci_write_config_word(pdev, ATIIXP_IDE_UDMA_MODE, udma_mode_data);
        } else {
-               u16 mwdma_timing_data;
-               /* Check this is correct - the order is odd in both drivers */
                int timing_shift = (16 * ap->port_no) + 8 * (adev->devno ^ 1);
+               u32 mwdma_timing_data;
 
                dma -= XFER_MW_DMA_0;
 
-               pci_read_config_word(pdev, ATIIXP_IDE_MWDMA_TIMING, &mwdma_timing_data);
+               pci_read_config_dword(pdev, ATIIXP_IDE_MWDMA_TIMING,
+                                     &mwdma_timing_data);
                mwdma_timing_data &= ~(0xFF << timing_shift);
                mwdma_timing_data |= (mwdma_timings[dma] << timing_shift);
-               pci_write_config_word(pdev, ATIIXP_IDE_MWDMA_TIMING, mwdma_timing_data);
+               pci_write_config_dword(pdev, ATIIXP_IDE_MWDMA_TIMING,
+                                      mwdma_timing_data);
        }
        /*
         *      We must now look at the PIO mode situation. We may need to
index 8d9343accf3ca2bf937ab358fe1afdcd99224100..abdd19fe990a36172c5364dee588c1045bd65a2d 100644 (file)
@@ -653,7 +653,8 @@ static irqreturn_t octeon_cf_interrupt(int irq, void *dev_instance)
 
                ap = host->ports[i];
                ocd = ap->dev->platform_data;
-               if (!ap || (ap->flags & ATA_FLAG_DISABLED))
+
+               if (ap->flags & ATA_FLAG_DISABLED)
                        continue;
 
                ocd = ap->dev->platform_data;
index f4d009ed50aceb10b04e49b6ec9a9c7f1dff6cf6..dc99e26f8e5ba8c5d1a5635de6816d2a868a44bb 100644 (file)
@@ -411,6 +411,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {
        PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
        PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
        PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
+       PCMCIA_DEVICE_PROD_ID12("CNF   ", "CD-ROM", 0x46d7db81, 0x66536591),
        PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
        PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
        PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
index 23714aefb8256d742c56858b9a57e9614ecfb8c1..c19417e02208f3c500c269fcdf5b8846ff19464b 100644 (file)
@@ -2514,7 +2514,7 @@ static void mv_unexpected_intr(struct ata_port *ap, int edma_was_enabled)
        char *when = "idle";
 
        ata_ehi_clear_desc(ehi);
-       if (!ap || (ap->flags & ATA_FLAG_DISABLED)) {
+       if (ap->flags & ATA_FLAG_DISABLED) {
                when = "disabled";
        } else if (edma_was_enabled) {
                when = "EDMA enabled";
index b2d11f300c39045a8ce645949409fde0dc1a971c..86a40582999ce0f80364e2bb5e0995970b6f906e 100644 (file)
@@ -602,6 +602,7 @@ MODULE_VERSION(DRV_VERSION);
 
 static int adma_enabled;
 static int swncq_enabled = 1;
+static int msi_enabled;
 
 static void nv_adma_register_mode(struct ata_port *ap)
 {
@@ -2459,6 +2460,11 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        } else if (type == SWNCQ)
                nv_swncq_host_init(host);
 
+       if (msi_enabled) {
+               dev_printk(KERN_NOTICE, &pdev->dev, "Using MSI\n");
+               pci_enable_msi(pdev);
+       }
+
        pci_set_master(pdev);
        return ata_host_activate(host, pdev->irq, ipriv->irq_handler,
                                 IRQF_SHARED, ipriv->sht);
@@ -2558,4 +2564,6 @@ module_param_named(adma, adma_enabled, bool, 0444);
 MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: false)");
 module_param_named(swncq, swncq_enabled, bool, 0444);
 MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)");
+module_param_named(msi, msi_enabled, bool, 0444);
+MODULE_PARM_DESC(msi, "Enable use of MSI (Default: false)");
 
index 030ec079b184ec592cae99164a91fcca8b5b9075..35bd5cc7f2854b04654039ef4025f6ccfff4a739 100644 (file)
@@ -532,7 +532,7 @@ static irqreturn_t sil_interrupt(int irq, void *dev_instance)
                struct ata_port *ap = host->ports[i];
                u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2);
 
-               if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED))
+               if (unlikely(ap->flags & ATA_FLAG_DISABLED))
                        continue;
 
                /* turn off SATA_IRQ if not supported */
index e8beb8e5b6264232dbfc0ea2dc7ae95d76f5af64..05dd307e8f024038bfe6e9d762e3dff1dd6281ee 100644 (file)
@@ -428,6 +428,9 @@ int devres_release_all(struct device *dev)
 {
        unsigned long flags;
 
+       /* Looks like an uninitialized device structure */
+       if (WARN_ON(dev->devres_head.next == NULL))
+               return -ENODEV;
        spin_lock_irqsave(&dev->devres_lock, flags);
        return release_nodes(dev, dev->devres_head.next, &dev->devres_head,
                             flags);
index ddeb819c8f878a3cf07c18ed9d6d2c3ffe082e46..7376367bcb8053dec4951945f916d47c882fd59a 100644 (file)
@@ -180,7 +180,6 @@ static ssize_t firmware_loading_store(struct device *dev,
                                goto err;
                        }
                        /* Pages will be freed by vfree() */
-                       fw_priv->pages = NULL;
                        fw_priv->page_array_size = 0;
                        fw_priv->nr_pages = 0;
                        complete(&fw_priv->completion);
@@ -217,8 +216,10 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr,
                ret_count = -ENODEV;
                goto out;
        }
-       if (offset > fw->size)
-               return 0;
+       if (offset > fw->size) {
+               ret_count = 0;
+               goto out;
+       }
        if (count > fw->size - offset)
                count = fw->size - offset;
 
@@ -357,7 +358,7 @@ static void fw_dev_release(struct device *dev)
        kfree(fw_priv->pages);
        kfree(fw_priv->fw_id);
        kfree(fw_priv);
-       put_device(dev);
+       kfree(dev);
 
        module_put(THIS_MODULE);
 }
@@ -408,13 +409,11 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
        if (retval) {
                dev_err(device, "%s: device_register failed\n", __func__);
                put_device(f_dev);
-               goto error_kfree_fw_id;
+               return retval;
        }
        *dev_p = f_dev;
        return 0;
 
-error_kfree_fw_id:
-       kfree(fw_priv->fw_id);
 error_kfree:
        kfree(f_dev);
        kfree(fw_priv);
index 81cb01bfc356294865a4e04721d77d5a9c64ffff..456594bd97bc5f13f9189854a73b84dfef157bd8 100644 (file)
@@ -483,9 +483,6 @@ int platform_driver_register(struct platform_driver *drv)
                drv->driver.remove = platform_drv_remove;
        if (drv->shutdown)
                drv->driver.shutdown = platform_drv_shutdown;
-       if (drv->suspend || drv->resume)
-               pr_warning("Platform driver '%s' needs updating - please use "
-                       "dev_pm_ops\n", drv->driver.name);
 
        return driver_register(&drv->driver);
 }
index fae725458981793649bf3e339a20394ac9859448..58a3e572f2c903ff81bfe75a51730257c49daf37 100644 (file)
@@ -762,6 +762,7 @@ static int dpm_prepare(pm_message_t state)
                        dev->power.status = DPM_ON;
                        if (error == -EAGAIN) {
                                put_device(dev);
+                               error = 0;
                                continue;
                        }
                        printk(KERN_ERR "PM: Failed to prepare device %s "
index 79a9ae5238acc1b9fa06a2fed1ed70d2440a9416..0d903909af7e5366126baaa049d35c5ea26fe6b5 100644 (file)
@@ -275,9 +275,9 @@ int sysdev_register(struct sys_device *sysdev)
                                drv->add(sysdev);
                }
                mutex_unlock(&sysdev_drivers_lock);
+               kobject_uevent(&sysdev->kobj, KOBJ_ADD);
        }
 
-       kobject_uevent(&sysdev->kobj, KOBJ_ADD);
        return error;
 }
 
index 668dc234b8e22d5b09950950914398d6f1f61766..1e6b7c14f697c58b7ad5f551e6f947d2fe7719a2 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/proc_fs.h>
 #include <linux/reboot.h>
 #include <linux/spinlock.h>
index bb72ada9f074588e49796267b59600f848a615be..1d886e079c588e70951965b7a67192b962967c16 100644 (file)
@@ -298,6 +298,22 @@ config BLK_DEV_NBD
 
          If unsure, say N.
 
+config BLK_DEV_OSD
+       tristate "OSD object-as-blkdev support"
+       depends on SCSI_OSD_ULD
+       ---help---
+         Saying Y or M here will allow the exporting of a single SCSI
+         OSD (object-based storage) object as a Linux block device.
+
+         For example, if you create a 2G object on an OSD device,
+         you can then use this module to present that 2G object as
+         a Linux block device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called osdblk.
+
+         If unsure, say N.
+
 config BLK_DEV_SX8
        tristate "Promise SATA SX8 support"
        depends on PCI
index 7755a5e2a85e3b5a7ffcfe1544ce507df050764d..cdaa3f8fddf03f324bfe72b92b2ad884e5e1af0a 100644 (file)
@@ -23,6 +23,7 @@ obj-$(CONFIG_XILINX_SYSACE)   += xsysace.o
 obj-$(CONFIG_CDROM_PKTCDVD)    += pktcdvd.o
 obj-$(CONFIG_MG_DISK)          += mg_disk.o
 obj-$(CONFIG_SUNVDC)           += sunvdc.o
+obj-$(CONFIG_BLK_DEV_OSD)      += osdblk.o
 
 obj-$(CONFIG_BLK_DEV_UMEM)     += umem.o
 obj-$(CONFIG_BLK_DEV_NBD)      += nbd.o
index 9c6e5b0fe894f9e6af94a50b87a2ec2b2f04a470..2f07b7c99a95b5046b121572f956c1048dc29894 100644 (file)
@@ -1645,7 +1645,7 @@ static int __init fd_probe_drives(void)
 {
        int drive,drives,nomem;
 
-       printk(KERN_INFO "FD: probing units\n" KERN_INFO "found ");
+       printk(KERN_INFO "FD: probing units\nfound ");
        drives=0;
        nomem=0;
        for(drive=0;drive<FD_MAX_UNITS;drive++) {
index 5e41e6dd657b9a7326ba1347346c8147c428f3c2..db195abad69889e4d499bde162ff5e818601f3b2 100644 (file)
@@ -155,7 +155,7 @@ struct aoedev {
        u16 fw_ver;             /* version of blade's firmware */
        struct work_struct work;/* disk create work struct */
        struct gendisk *gd;
-       struct request_queue blkq;
+       struct request_queue *blkq;
        struct hd_geometry geo; 
        sector_t ssize;
        struct timer_list timer;
index 2307a271bdc99e91b5c410083383a0595c4c08d0..1e15889c4b9819f837076c1b17df34fc8ef881c2 100644 (file)
@@ -264,9 +264,12 @@ aoeblk_gdalloc(void *vp)
                goto err_disk;
        }
 
-       blk_queue_make_request(&d->blkq, aoeblk_make_request);
-       if (bdi_init(&d->blkq.backing_dev_info))
+       d->blkq = blk_alloc_queue(GFP_KERNEL);
+       if (!d->blkq)
                goto err_mempool;
+       blk_queue_make_request(d->blkq, aoeblk_make_request);
+       if (bdi_init(&d->blkq->backing_dev_info))
+               goto err_blkq;
        spin_lock_irqsave(&d->lock, flags);
        gd->major = AOE_MAJOR;
        gd->first_minor = d->sysminor * AOE_PARTITIONS;
@@ -276,7 +279,7 @@ aoeblk_gdalloc(void *vp)
        snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d",
                d->aoemajor, d->aoeminor);
 
-       gd->queue = &d->blkq;
+       gd->queue = d->blkq;
        d->gd = gd;
        d->flags &= ~DEVFL_GDALLOC;
        d->flags |= DEVFL_UP;
@@ -287,6 +290,9 @@ aoeblk_gdalloc(void *vp)
        aoedisk_add_sysfs(d);
        return;
 
+err_blkq:
+       blk_cleanup_queue(d->blkq);
+       d->blkq = NULL;
 err_mempool:
        mempool_destroy(d->bufpool);
 err_disk:
index eeea477d96016596ccd729a6f75d37d5e3d30a0e..fa67027789aab80ca8c11deccad4e2d3ec225697 100644 (file)
@@ -113,6 +113,7 @@ aoedev_freedev(struct aoedev *d)
        if (d->bufpool)
                mempool_destroy(d->bufpool);
        skbpoolfree(d);
+       blk_cleanup_queue(d->blkq);
        kfree(d);
 }
 
index f5e7180d7f47d050ed0e39a37ad748054658b52b..3ff02941b3dd40c57ca9a2cc56d7442c5cd538cb 100644 (file)
@@ -1627,7 +1627,7 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode,
                                drive, dtp->blocks, dtp->spt, dtp->stretch);
 
                /* sanity check */
-               if (!dtp || setprm.track != dtp->blocks/dtp->spt/2 ||
+               if (setprm.track != dtp->blocks/dtp->spt/2 ||
                    setprm.head != 2) {
                        redo_fd_request();
                        return -EINVAL;
index c7a527c08a0980d542c1fffbd30687bbc95289d0..a52cc7fe45ea12d4e3d7742615ed9904013e0f10 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/major.h>
 #include <linux/fs.h>
@@ -226,8 +227,18 @@ static inline void addQ(struct hlist_head *list, CommandList_struct *c)
 
 static inline void removeQ(CommandList_struct *c)
 {
-       if (WARN_ON(hlist_unhashed(&c->list)))
+       /*
+        * After kexec/dump some commands might still
+        * be in flight, which the firmware will try
+        * to complete. Resetting the firmware doesn't work
+        * with old fw revisions, so we have to mark
+        * them off as 'stale' to prevent the driver from
+        * falling over.
+        */
+       if (WARN_ON(hlist_unhashed(&c->list))) {
+               c->cmd_type = CMD_MSG_STALE;
                return;
+       }
 
        hlist_del_init(&c->list);
 }
@@ -4246,7 +4257,8 @@ static void fail_all_cmds(unsigned long ctlr)
        while (!hlist_empty(&h->cmpQ)) {
                c = hlist_entry(h->cmpQ.first, CommandList_struct, list);
                removeQ(c);
-               c->err_info->CommandStatus = CMD_HARDWARE_ERR;
+               if (c->cmd_type != CMD_MSG_STALE)
+                       c->err_info->CommandStatus = CMD_HARDWARE_ERR;
                if (c->cmd_type == CMD_RWREQ) {
                        complete_command(h, c, 0);
                } else if (c->cmd_type == CMD_IOCTL_PEND)
index cd665b00c7c5b333176e160102fc25f5b6f998e5..dbaed1ea0da3c9c2ba71993dfec116d291a87770 100644 (file)
@@ -274,6 +274,7 @@ typedef struct _ErrorInfo_struct {
 #define CMD_SCSI       0x03
 #define CMD_MSG_DONE   0x04
 #define CMD_MSG_TIMEOUT 0x05
+#define CMD_MSG_STALE  0xff
 
 /* This structure needs to be divisible by 8 for new
  * indexing method.
index 862b40c90181b008f91f22aef61e69e87c681123..91b753013780f8a1bcb113159970abde34f4e127 100644 (file)
@@ -3327,7 +3327,10 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                mutex_lock(&open_lock);
-               LOCK_FDC(drive, 1);
+               if (lock_fdc(drive, 1)) {
+                       mutex_unlock(&open_lock);
+                       return -EINTR;
+               }
                floppy_type[type] = *g;
                floppy_type[type].name = "user format";
                for (cnt = type << 2; cnt < (type << 2) + 4; cnt++)
index 801f4ab83302556e9b48f1ddf139201a05e8c304..5757188cd1fb33393e830adf89313857146ce752 100644 (file)
@@ -61,7 +61,6 @@
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/swap.h>
 #include <linux/slab.h>
 #include <linux/loop.h>
index f703f54782469e2ae9491cbd6d6dd89708fb8a55..6d7fbaa922486dc2731ccb50480a1c2184718ea6 100644 (file)
@@ -36,7 +36,6 @@
 
 /* Register offsets */
 #define MG_BUFF_OFFSET                 0x8000
-#define MG_STORAGE_BUFFER_SIZE         0x200
 #define MG_REG_OFFSET                  0xC000
 #define MG_REG_FEATURE                 (MG_REG_OFFSET + 2)     /* write case */
 #define MG_REG_ERROR                   (MG_REG_OFFSET + 2)     /* read case */
@@ -219,6 +218,16 @@ static unsigned int mg_wait(struct mg_host *host, u32 expect, u32 msec)
        host->error = MG_ERR_NONE;
        expire = jiffies + msecs_to_jiffies(msec);
 
+       /* These 2 times dummy status read prevents reading invalid
+        * status. A very little time (3 times of mflash operating clk)
+        * is required for busy bit is set. Use dummy read instead of
+        * busy wait, because mflash's PLL is machine dependent.
+        */
+       if (prv_data->use_polling) {
+               status = inb((unsigned long)host->dev_base + MG_REG_STATUS);
+               status = inb((unsigned long)host->dev_base + MG_REG_STATUS);
+       }
+
        status = inb((unsigned long)host->dev_base + MG_REG_STATUS);
 
        do {
@@ -245,8 +254,6 @@ static unsigned int mg_wait(struct mg_host *host, u32 expect, u32 msec)
                        mg_dump_status("not ready", status, host);
                        return MG_ERR_INV_STAT;
                }
-               if (prv_data->use_polling)
-                       msleep(1);
 
                status = inb((unsigned long)host->dev_base + MG_REG_STATUS);
        } while (time_before(cur_jiffies, expire));
@@ -469,9 +476,18 @@ static unsigned int mg_out(struct mg_host *host,
        return MG_ERR_NONE;
 }
 
+static void mg_read_one(struct mg_host *host, struct request *req)
+{
+       u16 *buff = (u16 *)req->buffer;
+       u32 i;
+
+       for (i = 0; i < MG_SECTOR_SIZE >> 1; i++)
+               *buff++ = inw((unsigned long)host->dev_base + MG_BUFF_OFFSET +
+                             (i << 1));
+}
+
 static void mg_read(struct request *req)
 {
-       u32 j;
        struct mg_host *host = req->rq_disk->private_data;
 
        if (mg_out(host, blk_rq_pos(req), blk_rq_sectors(req),
@@ -482,49 +498,65 @@ static void mg_read(struct request *req)
               blk_rq_sectors(req), blk_rq_pos(req), req->buffer);
 
        do {
-               u16 *buff = (u16 *)req->buffer;
-
                if (mg_wait(host, ATA_DRQ,
                            MG_TMAX_WAIT_RD_DRQ) != MG_ERR_NONE) {
                        mg_bad_rw_intr(host);
                        return;
                }
-               for (j = 0; j < MG_SECTOR_SIZE >> 1; j++)
-                       *buff++ = inw((unsigned long)host->dev_base +
-                                     MG_BUFF_OFFSET + (j << 1));
+
+               mg_read_one(host, req);
 
                outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base +
                                MG_REG_COMMAND);
        } while (mg_end_request(host, 0, MG_SECTOR_SIZE));
 }
 
+static void mg_write_one(struct mg_host *host, struct request *req)
+{
+       u16 *buff = (u16 *)req->buffer;
+       u32 i;
+
+       for (i = 0; i < MG_SECTOR_SIZE >> 1; i++)
+               outw(*buff++, (unsigned long)host->dev_base + MG_BUFF_OFFSET +
+                    (i << 1));
+}
+
 static void mg_write(struct request *req)
 {
-       u32 j;
        struct mg_host *host = req->rq_disk->private_data;
+       unsigned int rem = blk_rq_sectors(req);
 
-       if (mg_out(host, blk_rq_pos(req), blk_rq_sectors(req),
+       if (mg_out(host, blk_rq_pos(req), rem,
                   MG_CMD_WR, NULL) != MG_ERR_NONE) {
                mg_bad_rw_intr(host);
                return;
        }
 
        MG_DBG("requested %d sects (from %ld), buffer=0x%p\n",
-              blk_rq_sectors(req), blk_rq_pos(req), req->buffer);
+              rem, blk_rq_pos(req), req->buffer);
+
+       if (mg_wait(host, ATA_DRQ,
+                   MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) {
+               mg_bad_rw_intr(host);
+               return;
+       }
 
        do {
-               u16 *buff = (u16 *)req->buffer;
+               mg_write_one(host, req);
 
-       if (mg_wait(host, ATA_DRQ, MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) {
+               outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base +
+                               MG_REG_COMMAND);
+
+               rem--;
+               if (rem > 1 && mg_wait(host, ATA_DRQ,
+                                       MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) {
+                       mg_bad_rw_intr(host);
+                       return;
+               } else if (mg_wait(host, MG_STAT_READY,
+                                       MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) {
                        mg_bad_rw_intr(host);
                        return;
                }
-               for (j = 0; j < MG_SECTOR_SIZE >> 1; j++)
-                       outw(*buff++, (unsigned long)host->dev_base +
-                                     MG_BUFF_OFFSET + (j << 1));
-
-               outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base +
-                               MG_REG_COMMAND);
        } while (mg_end_request(host, 0, MG_SECTOR_SIZE));
 }
 
@@ -532,7 +564,6 @@ static void mg_read_intr(struct mg_host *host)
 {
        struct request *req = host->req;
        u32 i;
-       u16 *buff;
 
        /* check status */
        do {
@@ -550,13 +581,7 @@ static void mg_read_intr(struct mg_host *host)
        return;
 
 ok_to_read:
-       /* get current segment of request */
-       buff = (u16 *)req->buffer;
-
-       /* read 1 sector */
-       for (i = 0; i < MG_SECTOR_SIZE >> 1; i++)
-               *buff++ = inw((unsigned long)host->dev_base + MG_BUFF_OFFSET +
-                             (i << 1));
+       mg_read_one(host, req);
 
        MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n",
               blk_rq_pos(req), blk_rq_sectors(req) - 1, req->buffer);
@@ -575,8 +600,7 @@ ok_to_read:
 static void mg_write_intr(struct mg_host *host)
 {
        struct request *req = host->req;
-       u32 i, j;
-       u16 *buff;
+       u32 i;
        bool rem;
 
        /* check status */
@@ -597,12 +621,7 @@ static void mg_write_intr(struct mg_host *host)
 ok_to_write:
        if ((rem = mg_end_request(host, 0, MG_SECTOR_SIZE))) {
                /* write 1 sector and set handler if remains */
-               buff = (u16 *)req->buffer;
-               for (j = 0; j < MG_STORAGE_BUFFER_SIZE >> 1; j++) {
-                       outw(*buff, (unsigned long)host->dev_base +
-                                       MG_BUFF_OFFSET + (j << 1));
-                       buff++;
-               }
+               mg_write_one(host, req);
                MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n",
                       blk_rq_pos(req), blk_rq_sectors(req), req->buffer);
                host->mg_do_intr = mg_write_intr;
@@ -667,9 +686,6 @@ static unsigned int mg_issue_req(struct request *req,
                unsigned int sect_num,
                unsigned int sect_cnt)
 {
-       u16 *buff;
-       u32 i;
-
        switch (rq_data_dir(req)) {
        case READ:
                if (mg_out(host, sect_num, sect_cnt, MG_CMD_RD, &mg_read_intr)
@@ -693,12 +709,7 @@ static unsigned int mg_issue_req(struct request *req,
                        mg_bad_rw_intr(host);
                        return host->error;
                }
-               buff = (u16 *)req->buffer;
-               for (i = 0; i < MG_SECTOR_SIZE >> 1; i++) {
-                       outw(*buff, (unsigned long)host->dev_base +
-                                       MG_BUFF_OFFSET + (i << 1));
-                       buff++;
-               }
+               mg_write_one(host, req);
                mod_timer(&host->timer, jiffies + 3 * HZ);
                outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base +
                                MG_REG_COMMAND);
diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c
new file mode 100644 (file)
index 0000000..13c1aee
--- /dev/null
@@ -0,0 +1,701 @@
+
+/*
+   osdblk.c -- Export a single SCSI OSD object as a Linux block device
+
+
+   Copyright 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+   Instructions for use
+   --------------------
+
+   1) Map a Linux block device to an existing OSD object.
+
+      In this example, we will use partition id 1234, object id 5678,
+      OSD device /dev/osd1.
+
+      $ echo "1234 5678 /dev/osd1" > /sys/class/osdblk/add
+
+
+   2) List all active blkdev<->object mappings.
+
+      In this example, we have performed step #1 twice, creating two blkdevs,
+      mapped to two separate OSD objects.
+
+      $ cat /sys/class/osdblk/list
+      0 174 1234 5678 /dev/osd1
+      1 179 1994 897123 /dev/osd0
+
+      The columns, in order, are:
+      - blkdev unique id
+      - blkdev assigned major
+      - OSD object partition id
+      - OSD object id
+      - OSD device
+
+
+   3) Remove an active blkdev<->object mapping.
+
+      In this example, we remove the mapping with blkdev unique id 1.
+
+      $ echo 1 > /sys/class/osdblk/remove
+
+
+   NOTE:  The actual creation and deletion of OSD objects is outside the scope
+   of this driver.
+
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_attributes.h>
+#include <scsi/osd_sec.h>
+#include <scsi/scsi_device.h>
+
+#define DRV_NAME "osdblk"
+#define PFX DRV_NAME ": "
+
+/* #define _OSDBLK_DEBUG */
+#ifdef _OSDBLK_DEBUG
+#define OSDBLK_DEBUG(fmt, a...) \
+       printk(KERN_NOTICE "osdblk @%s:%d: " fmt, __func__, __LINE__, ##a)
+#else
+#define OSDBLK_DEBUG(fmt, a...) \
+       do { if (0) printk(fmt, ##a); } while (0)
+#endif
+
+MODULE_AUTHOR("Jeff Garzik <jeff@garzik.org>");
+MODULE_DESCRIPTION("block device inside an OSD object osdblk.ko");
+MODULE_LICENSE("GPL");
+
+struct osdblk_device;
+
+enum {
+       OSDBLK_MINORS_PER_MAJOR = 256,          /* max minors per blkdev */
+       OSDBLK_MAX_REQ          = 32,           /* max parallel requests */
+       OSDBLK_OP_TIMEOUT       = 4 * 60,       /* sync OSD req timeout */
+};
+
+struct osdblk_request {
+       struct request          *rq;            /* blk layer request */
+       struct bio              *bio;           /* cloned bio */
+       struct osdblk_device    *osdev;         /* associated blkdev */
+};
+
+struct osdblk_device {
+       int                     id;             /* blkdev unique id */
+
+       int                     major;          /* blkdev assigned major */
+       struct gendisk          *disk;          /* blkdev's gendisk and rq */
+       struct request_queue    *q;
+
+       struct osd_dev          *osd;           /* associated OSD */
+
+       char                    name[32];       /* blkdev name, e.g. osdblk34 */
+
+       spinlock_t              lock;           /* queue lock */
+
+       struct osd_obj_id       obj;            /* OSD partition, obj id */
+       uint8_t                 obj_cred[OSD_CAP_LEN]; /* OSD cred */
+
+       struct osdblk_request   req[OSDBLK_MAX_REQ]; /* request table */
+
+       struct list_head        node;
+
+       char                    osd_path[0];    /* OSD device path */
+};
+
+static struct class *class_osdblk;             /* /sys/class/osdblk */
+static DEFINE_MUTEX(ctl_mutex);        /* Serialize open/close/setup/teardown */
+static LIST_HEAD(osdblkdev_list);
+
+static struct block_device_operations osdblk_bd_ops = {
+       .owner          = THIS_MODULE,
+};
+
+static const struct osd_attr g_attr_logical_length = ATTR_DEF(
+       OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8);
+
+static void osdblk_make_credential(u8 cred_a[OSD_CAP_LEN],
+                                  const struct osd_obj_id *obj)
+{
+       osd_sec_init_nosec_doall_caps(cred_a, obj, false, true);
+}
+
+/* copied from exofs; move to libosd? */
+/*
+ * Perform a synchronous OSD operation.  copied from exofs; move to libosd?
+ */
+static int osd_sync_op(struct osd_request *or, int timeout, uint8_t *credential)
+{
+       int ret;
+
+       or->timeout = timeout;
+       ret = osd_finalize_request(or, 0, credential, NULL);
+       if (ret)
+               return ret;
+
+       ret = osd_execute_request(or);
+
+       /* osd_req_decode_sense(or, ret); */
+       return ret;
+}
+
+/*
+ * Perform an asynchronous OSD operation.  copied from exofs; move to libosd?
+ */
+static int osd_async_op(struct osd_request *or, osd_req_done_fn *async_done,
+                  void *caller_context, u8 *cred)
+{
+       int ret;
+
+       ret = osd_finalize_request(or, 0, cred, NULL);
+       if (ret)
+               return ret;
+
+       ret = osd_execute_request_async(or, async_done, caller_context);
+
+       return ret;
+}
+
+/* copied from exofs; move to libosd? */
+static int extract_attr_from_req(struct osd_request *or, struct osd_attr *attr)
+{
+       struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */
+       void *iter = NULL;
+       int nelem;
+
+       do {
+               nelem = 1;
+               osd_req_decode_get_attr_list(or, &cur_attr, &nelem, &iter);
+               if ((cur_attr.attr_page == attr->attr_page) &&
+                   (cur_attr.attr_id == attr->attr_id)) {
+                       attr->len = cur_attr.len;
+                       attr->val_ptr = cur_attr.val_ptr;
+                       return 0;
+               }
+       } while (iter);
+
+       return -EIO;
+}
+
+static int osdblk_get_obj_size(struct osdblk_device *osdev, u64 *size_out)
+{
+       struct osd_request *or;
+       struct osd_attr attr;
+       int ret;
+
+       /* start request */
+       or = osd_start_request(osdev->osd, GFP_KERNEL);
+       if (!or)
+               return -ENOMEM;
+
+       /* create a get-attributes(length) request */
+       osd_req_get_attributes(or, &osdev->obj);
+
+       osd_req_add_get_attr_list(or, &g_attr_logical_length, 1);
+
+       /* execute op synchronously */
+       ret = osd_sync_op(or, OSDBLK_OP_TIMEOUT, osdev->obj_cred);
+       if (ret)
+               goto out;
+
+       /* extract length from returned attribute info */
+       attr = g_attr_logical_length;
+       ret = extract_attr_from_req(or, &attr);
+       if (ret)
+               goto out;
+
+       *size_out = get_unaligned_be64(attr.val_ptr);
+
+out:
+       osd_end_request(or);
+       return ret;
+
+}
+
+static void osdblk_osd_complete(struct osd_request *or, void *private)
+{
+       struct osdblk_request *orq = private;
+       struct osd_sense_info osi;
+       int ret = osd_req_decode_sense(or, &osi);
+
+       if (ret) {
+               ret = -EIO;
+               OSDBLK_DEBUG("osdblk_osd_complete with err=%d\n", ret);
+       }
+
+       /* complete OSD request */
+       osd_end_request(or);
+
+       /* complete request passed to osdblk by block layer */
+       __blk_end_request_all(orq->rq, ret);
+}
+
+static void bio_chain_put(struct bio *chain)
+{
+       struct bio *tmp;
+
+       while (chain) {
+               tmp = chain;
+               chain = chain->bi_next;
+
+               bio_put(tmp);
+       }
+}
+
+static struct bio *bio_chain_clone(struct bio *old_chain, gfp_t gfpmask)
+{
+       struct bio *tmp, *new_chain = NULL, *tail = NULL;
+
+       while (old_chain) {
+               tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs);
+               if (!tmp)
+                       goto err_out;
+
+               __bio_clone(tmp, old_chain);
+               tmp->bi_bdev = NULL;
+               gfpmask &= ~__GFP_WAIT;
+               tmp->bi_next = NULL;
+
+               if (!new_chain)
+                       new_chain = tail = tmp;
+               else {
+                       tail->bi_next = tmp;
+                       tail = tmp;
+               }
+
+               old_chain = old_chain->bi_next;
+       }
+
+       return new_chain;
+
+err_out:
+       OSDBLK_DEBUG("bio_chain_clone with err\n");
+       bio_chain_put(new_chain);
+       return NULL;
+}
+
+static void osdblk_rq_fn(struct request_queue *q)
+{
+       struct osdblk_device *osdev = q->queuedata;
+
+       while (1) {
+               struct request *rq;
+               struct osdblk_request *orq;
+               struct osd_request *or;
+               struct bio *bio;
+               bool do_write, do_flush;
+
+               /* peek at request from block layer */
+               rq = blk_fetch_request(q);
+               if (!rq)
+                       break;
+
+               /* filter out block requests we don't understand */
+               if (!blk_fs_request(rq) && !blk_barrier_rq(rq)) {
+                       blk_end_request_all(rq, 0);
+                       continue;
+               }
+
+               /* deduce our operation (read, write, flush) */
+               /* I wish the block layer simplified cmd_type/cmd_flags/cmd[]
+                * into a clearly defined set of RPC commands:
+                * read, write, flush, scsi command, power mgmt req,
+                * driver-specific, etc.
+                */
+
+               do_flush = (rq->special == (void *) 0xdeadbeefUL);
+               do_write = (rq_data_dir(rq) == WRITE);
+
+               if (!do_flush) { /* osd_flush does not use a bio */
+                       /* a bio clone to be passed down to OSD request */
+                       bio = bio_chain_clone(rq->bio, GFP_ATOMIC);
+                       if (!bio)
+                               break;
+               } else
+                       bio = NULL;
+
+               /* alloc internal OSD request, for OSD command execution */
+               or = osd_start_request(osdev->osd, GFP_ATOMIC);
+               if (!or) {
+                       bio_chain_put(bio);
+                       OSDBLK_DEBUG("osd_start_request with err\n");
+                       break;
+               }
+
+               orq = &osdev->req[rq->tag];
+               orq->rq = rq;
+               orq->bio = bio;
+               orq->osdev = osdev;
+
+               /* init OSD command: flush, write or read */
+               if (do_flush)
+                       osd_req_flush_object(or, &osdev->obj,
+                                            OSD_CDB_FLUSH_ALL, 0, 0);
+               else if (do_write)
+                       osd_req_write(or, &osdev->obj, blk_rq_pos(rq) * 512ULL,
+                                     bio, blk_rq_bytes(rq));
+               else
+                       osd_req_read(or, &osdev->obj, blk_rq_pos(rq) * 512ULL,
+                                    bio, blk_rq_bytes(rq));
+
+               OSDBLK_DEBUG("%s 0x%x bytes at 0x%llx\n",
+                       do_flush ? "flush" : do_write ?
+                               "write" : "read", blk_rq_bytes(rq),
+                       blk_rq_pos(rq) * 512ULL);
+
+               /* begin OSD command execution */
+               if (osd_async_op(or, osdblk_osd_complete, orq,
+                                osdev->obj_cred)) {
+                       osd_end_request(or);
+                       blk_requeue_request(q, rq);
+                       bio_chain_put(bio);
+                       OSDBLK_DEBUG("osd_execute_request_async with err\n");
+                       break;
+               }
+
+               /* remove the special 'flush' marker, now that the command
+                * is executing
+                */
+               rq->special = NULL;
+       }
+}
+
+static void osdblk_prepare_flush(struct request_queue *q, struct request *rq)
+{
+       /* add driver-specific marker, to indicate that this request
+        * is a flush command
+        */
+       rq->special = (void *) 0xdeadbeefUL;
+}
+
+static void osdblk_free_disk(struct osdblk_device *osdev)
+{
+       struct gendisk *disk = osdev->disk;
+
+       if (!disk)
+               return;
+
+       if (disk->flags & GENHD_FL_UP)
+               del_gendisk(disk);
+       if (disk->queue)
+               blk_cleanup_queue(disk->queue);
+       put_disk(disk);
+}
+
+static int osdblk_init_disk(struct osdblk_device *osdev)
+{
+       struct gendisk *disk;
+       struct request_queue *q;
+       int rc;
+       u64 obj_size = 0;
+
+       /* contact OSD, request size info about the object being mapped */
+       rc = osdblk_get_obj_size(osdev, &obj_size);
+       if (rc)
+               return rc;
+
+       /* create gendisk info */
+       disk = alloc_disk(OSDBLK_MINORS_PER_MAJOR);
+       if (!disk)
+               return -ENOMEM;
+
+       sprintf(disk->disk_name, DRV_NAME "%d", osdev->id);
+       disk->major = osdev->major;
+       disk->first_minor = 0;
+       disk->fops = &osdblk_bd_ops;
+       disk->private_data = osdev;
+
+       /* init rq */
+       q = blk_init_queue(osdblk_rq_fn, &osdev->lock);
+       if (!q) {
+               put_disk(disk);
+               return -ENOMEM;
+       }
+
+       /* switch queue to TCQ mode; allocate tag map */
+       rc = blk_queue_init_tags(q, OSDBLK_MAX_REQ, NULL);
+       if (rc) {
+               blk_cleanup_queue(q);
+               put_disk(disk);
+               return rc;
+       }
+
+       /* Set our limits to the lower device limits, because osdblk cannot
+        * sleep when allocating a lower-request and therefore cannot be
+        * bouncing.
+        */
+       blk_queue_stack_limits(q, osd_request_queue(osdev->osd));
+
+       blk_queue_prep_rq(q, blk_queue_start_tag);
+       blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, osdblk_prepare_flush);
+
+       disk->queue = q;
+
+       q->queuedata = osdev;
+
+       osdev->disk = disk;
+       osdev->q = q;
+
+       /* finally, announce the disk to the world */
+       set_capacity(disk, obj_size / 512ULL);
+       add_disk(disk);
+
+       printk(KERN_INFO "%s: Added of size 0x%llx\n",
+               disk->disk_name, (unsigned long long)obj_size);
+
+       return 0;
+}
+
+/********************************************************************
+ * /sys/class/osdblk/
+ *                   add       map OSD object to blkdev
+ *                   remove    unmap OSD object
+ *                   list      show mappings
+ *******************************************************************/
+
+static void class_osdblk_release(struct class *cls)
+{
+       kfree(cls);
+}
+
+static ssize_t class_osdblk_list(struct class *c, char *data)
+{
+       int n = 0;
+       struct list_head *tmp;
+
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+       list_for_each(tmp, &osdblkdev_list) {
+               struct osdblk_device *osdev;
+
+               osdev = list_entry(tmp, struct osdblk_device, node);
+
+               n += sprintf(data+n, "%d %d %llu %llu %s\n",
+                       osdev->id,
+                       osdev->major,
+                       osdev->obj.partition,
+                       osdev->obj.id,
+                       osdev->osd_path);
+       }
+
+       mutex_unlock(&ctl_mutex);
+       return n;
+}
+
+static ssize_t class_osdblk_add(struct class *c, const char *buf, size_t count)
+{
+       struct osdblk_device *osdev;
+       ssize_t rc;
+       int irc, new_id = 0;
+       struct list_head *tmp;
+
+       if (!try_module_get(THIS_MODULE))
+               return -ENODEV;
+
+       /* new osdblk_device object */
+       osdev = kzalloc(sizeof(*osdev) + strlen(buf) + 1, GFP_KERNEL);
+       if (!osdev) {
+               rc = -ENOMEM;
+               goto err_out_mod;
+       }
+
+       /* static osdblk_device initialization */
+       spin_lock_init(&osdev->lock);
+       INIT_LIST_HEAD(&osdev->node);
+
+       /* generate unique id: find highest unique id, add one */
+
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+       list_for_each(tmp, &osdblkdev_list) {
+               struct osdblk_device *osdev;
+
+               osdev = list_entry(tmp, struct osdblk_device, node);
+               if (osdev->id > new_id)
+                       new_id = osdev->id + 1;
+       }
+
+       osdev->id = new_id;
+
+       /* add to global list */
+       list_add_tail(&osdev->node, &osdblkdev_list);
+
+       mutex_unlock(&ctl_mutex);
+
+       /* parse add command */
+       if (sscanf(buf, "%llu %llu %s", &osdev->obj.partition, &osdev->obj.id,
+                  osdev->osd_path) != 3) {
+               rc = -EINVAL;
+               goto err_out_slot;
+       }
+
+       /* initialize rest of new object */
+       sprintf(osdev->name, DRV_NAME "%d", osdev->id);
+
+       /* contact requested OSD */
+       osdev->osd = osduld_path_lookup(osdev->osd_path);
+       if (IS_ERR(osdev->osd)) {
+               rc = PTR_ERR(osdev->osd);
+               goto err_out_slot;
+       }
+
+       /* build OSD credential */
+       osdblk_make_credential(osdev->obj_cred, &osdev->obj);
+
+       /* register our block device */
+       irc = register_blkdev(0, osdev->name);
+       if (irc < 0) {
+               rc = irc;
+               goto err_out_osd;
+       }
+
+       osdev->major = irc;
+
+       /* set up and announce blkdev mapping */
+       rc = osdblk_init_disk(osdev);
+       if (rc)
+               goto err_out_blkdev;
+
+       return count;
+
+err_out_blkdev:
+       unregister_blkdev(osdev->major, osdev->name);
+err_out_osd:
+       osduld_put_device(osdev->osd);
+err_out_slot:
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+       list_del_init(&osdev->node);
+       mutex_unlock(&ctl_mutex);
+
+       kfree(osdev);
+err_out_mod:
+       OSDBLK_DEBUG("Error adding device %s\n", buf);
+       module_put(THIS_MODULE);
+       return rc;
+}
+
+static ssize_t class_osdblk_remove(struct class *c, const char *buf,
+                                       size_t count)
+{
+       struct osdblk_device *osdev = NULL;
+       int target_id, rc;
+       unsigned long ul;
+       struct list_head *tmp;
+
+       rc = strict_strtoul(buf, 10, &ul);
+       if (rc)
+               return rc;
+
+       /* convert to int; abort if we lost anything in the conversion */
+       target_id = (int) ul;
+       if (target_id != ul)
+               return -EINVAL;
+
+       /* remove object from list immediately */
+       mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+       list_for_each(tmp, &osdblkdev_list) {
+               osdev = list_entry(tmp, struct osdblk_device, node);
+               if (osdev->id == target_id) {
+                       list_del_init(&osdev->node);
+                       break;
+               }
+               osdev = NULL;
+       }
+
+       mutex_unlock(&ctl_mutex);
+
+       if (!osdev)
+               return -ENOENT;
+
+       /* clean up and free blkdev and associated OSD connection */
+       osdblk_free_disk(osdev);
+       unregister_blkdev(osdev->major, osdev->name);
+       osduld_put_device(osdev->osd);
+       kfree(osdev);
+
+       /* release module ref */
+       module_put(THIS_MODULE);
+
+       return count;
+}
+
+static struct class_attribute class_osdblk_attrs[] = {
+       __ATTR(add,     0200, NULL, class_osdblk_add),
+       __ATTR(remove,  0200, NULL, class_osdblk_remove),
+       __ATTR(list,    0444, class_osdblk_list, NULL),
+       __ATTR_NULL
+};
+
+static int osdblk_sysfs_init(void)
+{
+       int ret = 0;
+
+       /*
+        * create control files in sysfs
+        * /sys/class/osdblk/...
+        */
+       class_osdblk = kzalloc(sizeof(*class_osdblk), GFP_KERNEL);
+       if (!class_osdblk)
+               return -ENOMEM;
+
+       class_osdblk->name = DRV_NAME;
+       class_osdblk->owner = THIS_MODULE;
+       class_osdblk->class_release = class_osdblk_release;
+       class_osdblk->class_attrs = class_osdblk_attrs;
+
+       ret = class_register(class_osdblk);
+       if (ret) {
+               kfree(class_osdblk);
+               class_osdblk = NULL;
+               printk(PFX "failed to create class osdblk\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static void osdblk_sysfs_cleanup(void)
+{
+       if (class_osdblk)
+               class_destroy(class_osdblk);
+       class_osdblk = NULL;
+}
+
+static int __init osdblk_init(void)
+{
+       int rc;
+
+       rc = osdblk_sysfs_init();
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+static void __exit osdblk_exit(void)
+{
+       osdblk_sysfs_cleanup();
+}
+
+module_init(osdblk_init);
+module_exit(osdblk_exit);
+
index 83650e00632d80b6837678355fbac3c50c6d9a94..99a506f619b71bcadac21608b5969931441e05cf 100644 (file)
@@ -1372,8 +1372,10 @@ try_next_bio:
        wakeup = (pd->write_congestion_on > 0
                        && pd->bio_queue_size <= pd->write_congestion_off);
        spin_unlock(&pd->lock);
-       if (wakeup)
-               clear_bdi_congested(&pd->disk->queue->backing_dev_info, WRITE);
+       if (wakeup) {
+               clear_bdi_congested(&pd->disk->queue->backing_dev_info,
+                                       BLK_RW_ASYNC);
+       }
 
        pkt->sleep_time = max(PACKET_WAIT_TIME, 1);
        pkt_set_state(pkt, PACKET_WAITING_STATE);
@@ -2592,10 +2594,10 @@ static int pkt_make_request(struct request_queue *q, struct bio *bio)
        spin_lock(&pd->lock);
        if (pd->write_congestion_on > 0
            && pd->bio_queue_size >= pd->write_congestion_on) {
-               set_bdi_congested(&q->backing_dev_info, WRITE);
+               set_bdi_congested(&q->backing_dev_info, BLK_RW_ASYNC);
                do {
                        spin_unlock(&pd->lock);
-                       congestion_wait(WRITE, HZ);
+                       congestion_wait(BLK_RW_ASYNC, HZ);
                        spin_lock(&pd->lock);
                } while(pd->bio_queue_size > pd->write_congestion_off);
        }
index 43db3ea15b54936da4502526602c117876bd67fc..aa1a3d5a3e2bc3f202bb695da2624f4d8cfd03b5 100644 (file)
@@ -213,7 +213,7 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
         * Only allow the generic SCSI ioctls if the host can support it.
         */
        if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI))
-               return -ENOIOCTLCMD;
+               return -ENOTTY;
 
        return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
 }
@@ -360,6 +360,9 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
        blk_queue_max_phys_segments(vblk->disk->queue, vblk->sg_elems-2);
        blk_queue_max_hw_segments(vblk->disk->queue, vblk->sg_elems-2);
 
+       /* No need to bounce any requests */
+       blk_queue_bounce_limit(vblk->disk->queue, BLK_BOUNCE_ANY);
+
        /* No real sector limit. */
        blk_queue_max_sectors(vblk->disk->queue, -1U);
 
@@ -424,7 +427,12 @@ static unsigned int features[] = {
        VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY
 };
 
-static struct virtio_driver virtio_blk = {
+/*
+ * virtio_blk causes spurious section mismatch warning by
+ * simultaneously referring to a __devinit and a __devexit function.
+ * Use __refdata to avoid this warning.
+ */
+static struct virtio_driver __refdata virtio_blk = {
        .feature_table = features,
        .feature_table_size = ARRAY_SIZE(features),
        .driver.name =  KBUILD_MODNAME,
index f08491a3a813b84e83df249196636c8829466cf7..b20abe102a2b774d66cc4505508762bbed86b8d0 100644 (file)
@@ -390,9 +390,10 @@ static inline void ace_dump_mem(void *base, int len)
 
 static void ace_dump_regs(struct ace_device *ace)
 {
-       dev_info(ace->dev, "    ctrl:  %.8x  seccnt/cmd: %.4x      ver:%.4x\n"
-                KERN_INFO "    status:%.8x  mpu_lba:%.8x  busmode:%4x\n"
-                KERN_INFO "    error: %.8x  cfg_lba:%.8x  fatstat:%.4x\n",
+       dev_info(ace->dev,
+                "    ctrl:  %.8x  seccnt/cmd: %.4x      ver:%.4x\n"
+                "    status:%.8x  mpu_lba:%.8x  busmode:%4x\n"
+                "    error: %.8x  cfg_lba:%.8x  fatstat:%.4x\n",
                 ace_in32(ace, ACE_CTRL),
                 ace_in(ace, ACE_SECCNTCMD),
                 ace_in(ace, ACE_VERSION),
index 4575171e5beb1bd754e0fe0ba11600b0fce4ea3f..b2590409f25efb1911dc8e87a4d88c2dc0b3d719 100644 (file)
@@ -374,7 +374,7 @@ err:
 static void __exit z2_exit(void)
 {
     int i, j;
-    blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), 256);
+    blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), Z2MINOR_COUNT);
     unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
     del_gendisk(z2ram_gendisk);
     put_disk(z2ram_gendisk);
index 1df9dda2e377d8415366ae43fb1c44e57e2ed9d2..d5cde6d86f891a2c01a47cdfbdbe43772e6de86d 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
index 0bd01f49cfd8bc76baf500b7d903ffbe8b40de96..6a06913b01d30151065471350ec492e7df79a6a3 100644 (file)
@@ -1029,10 +1029,6 @@ config CS5535_GPIO
 
          If compiled as a module, it will be called cs5535_gpio.
 
-config GPIO_VR41XX
-       tristate "NEC VR4100 series General-purpose I/O Unit support"
-       depends on CPU_VR41XX
-
 config RAW_DRIVER
        tristate "RAW driver (/dev/raw/rawN)"
        depends on BLOCK
index 189efcff08ce246a58900ab15a7cacd487c37724..66f779ad4f4c05297409c5eefadcf92d0a3903f1 100644 (file)
@@ -95,7 +95,6 @@ obj-$(CONFIG_SCx200_GPIO)     += scx200_gpio.o
 obj-$(CONFIG_PC8736x_GPIO)     += pc8736x_gpio.o
 obj-$(CONFIG_NSC_GPIO)         += nsc_gpio.o
 obj-$(CONFIG_CS5535_GPIO)      += cs5535_gpio.o
-obj-$(CONFIG_GPIO_VR41XX)      += vr41xx_giu.o
 obj-$(CONFIG_GPIO_TB0219)      += tb0219.o
 obj-$(CONFIG_TELCLOCK)         += tlclk.o
 
index 8c9d50db5c3a7913fba96958a4a1a433cde90330..c58557790585dfe6a0d56dba70fabb3764a3e2c6 100644 (file)
@@ -49,6 +49,7 @@
 #define PCI_DEVICE_ID_INTEL_IGDNG_D_HB     0x0040
 #define PCI_DEVICE_ID_INTEL_IGDNG_D_IG     0x0042
 #define PCI_DEVICE_ID_INTEL_IGDNG_M_HB     0x0044
+#define PCI_DEVICE_ID_INTEL_IGDNG_MA_HB            0x0062
 #define PCI_DEVICE_ID_INTEL_IGDNG_M_IG     0x0046
 
 /* cover 915 and 945 variants */
@@ -81,7 +82,8 @@
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \
                agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_D_HB || \
-               agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_M_HB)
+               agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_M_HB || \
+               agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MA_HB)
 
 extern int agp_memory_reserved;
 
@@ -1216,6 +1218,7 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
        case PCI_DEVICE_ID_INTEL_G41_HB:
        case PCI_DEVICE_ID_INTEL_IGDNG_D_HB:
        case PCI_DEVICE_ID_INTEL_IGDNG_M_HB:
+       case PCI_DEVICE_ID_INTEL_IGDNG_MA_HB:
                *gtt_offset = *gtt_size = MB(2);
                break;
        default:
@@ -2195,6 +2198,8 @@ static const struct intel_driver_description {
            "IGDNG/D", NULL, &intel_i965_driver },
        { PCI_DEVICE_ID_INTEL_IGDNG_M_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0,
            "IGDNG/M", NULL, &intel_i965_driver },
+       { PCI_DEVICE_ID_INTEL_IGDNG_MA_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0,
+           "IGDNG/MA", NULL, &intel_i965_driver },
        { 0, 0, 0, NULL, NULL, NULL }
 };
 
@@ -2398,6 +2403,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
        ID(PCI_DEVICE_ID_INTEL_G41_HB),
        ID(PCI_DEVICE_ID_INTEL_IGDNG_D_HB),
        ID(PCI_DEVICE_ID_INTEL_IGDNG_M_HB),
+       ID(PCI_DEVICE_ID_INTEL_IGDNG_MA_HB),
        { }
 };
 
index f4bb43fb8016192f244b1d3225672075df0d20dd..e077701ae3d91ab2af0c40d3e99e3f0480610f5f 100644 (file)
@@ -225,7 +225,7 @@ static const struct agp_bridge_driver parisc_agp_driver = {
        .configure              = parisc_agp_configure,
        .fetch_size             = parisc_agp_fetch_size,
        .tlb_flush              = parisc_agp_tlbflush,
-       .mask_memory            = parisc_agp_mask_memory,
+       .mask_memory            = parisc_agp_page_mask_memory,
        .masks                  = parisc_agp_masks,
        .agp_enable             = parisc_agp_enable,
        .cache_flush            = global_cache_flush,
index 72429b6b2fa831e8ce925145398acfbb7aa66170..6c32fbf071648931374bfc6fa699d6ba37a523f1 100644 (file)
@@ -81,6 +81,7 @@ static char *serial_version = "4.30";
 #include <linux/mm.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
 
index 140ea10ecb886e276c8a6ba53d112cdf06d96499..c02db01f736ea46bc536190910a2f4a9e336bfbb 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/cdev.h>
 #include <linux/list.h>
 #include <linux/mm.h>
+#include <asm/pgtable.h>
 #include <asm/io.h>
 
 /*
@@ -75,12 +76,13 @@ static struct class *bsr_class;
 static int bsr_major;
 
 enum {
-       BSR_8   = 0,
-       BSR_16  = 1,
-       BSR_64  = 2,
-       BSR_128 = 3,
-       BSR_UNKNOWN = 4,
-       BSR_MAX = 5,
+       BSR_8    = 0,
+       BSR_16   = 1,
+       BSR_64   = 2,
+       BSR_128  = 3,
+       BSR_4096 = 4,
+       BSR_UNKNOWN = 5,
+       BSR_MAX  = 6,
 };
 
 static unsigned bsr_types[BSR_MAX];
@@ -117,15 +119,22 @@ static int bsr_mmap(struct file *filp, struct vm_area_struct *vma)
 {
        unsigned long size   = vma->vm_end - vma->vm_start;
        struct bsr_dev *dev = filp->private_data;
+       int ret;
 
-       if (size > dev->bsr_len || (size & (PAGE_SIZE-1)))
-               return -EINVAL;
-
-       vma->vm_flags |= (VM_IO | VM_DONTEXPAND);
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
-       if (io_remap_pfn_range(vma, vma->vm_start, dev->bsr_addr >> PAGE_SHIFT,
-                              size, vma->vm_page_prot))
+       /* check for the case of a small BSR device and map one 4k page for it*/
+       if (dev->bsr_len < PAGE_SIZE && size == PAGE_SIZE)
+               ret = remap_4k_pfn(vma, vma->vm_start, dev->bsr_addr >> 12,
+                                  vma->vm_page_prot);
+       else if (size <= dev->bsr_len)
+               ret = io_remap_pfn_range(vma, vma->vm_start,
+                                        dev->bsr_addr >> PAGE_SHIFT,
+                                        size, vma->vm_page_prot);
+       else
+               return -EINVAL;
+
+       if (ret)
                return -EAGAIN;
 
        return 0;
@@ -205,6 +214,11 @@ static int bsr_add_node(struct device_node *bn)
                cur->bsr_stride = bsr_stride[i];
                cur->bsr_dev    = MKDEV(bsr_major, i + total_bsr_devs);
 
+               /* if we have a bsr_len of > 4k and less then PAGE_SIZE (64k pages) */
+               /* we can only map 4k of it, so only advertise the 4k in sysfs */
+               if (cur->bsr_len > 4096 && cur->bsr_len < PAGE_SIZE)
+                       cur->bsr_len = 4096;
+
                switch(cur->bsr_bytes) {
                case 8:
                        cur->bsr_type = BSR_8;
@@ -218,9 +232,11 @@ static int bsr_add_node(struct device_node *bn)
                case 128:
                        cur->bsr_type = BSR_128;
                        break;
+               case 4096:
+                       cur->bsr_type = BSR_4096;
+                       break;
                default:
                        cur->bsr_type = BSR_UNKNOWN;
-                       printk(KERN_INFO "unknown BSR size %d\n",cur->bsr_bytes);
                }
 
                cur->bsr_num = bsr_types[cur->bsr_type];
index f3366d3f06cfe404cdfe94b6d3393c55b7b05886..2dafc2da06488f631b1b6937b287440d8a1417bd 100644 (file)
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
+#include <linux/smp_lock.h>
 #include <linux/major.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
index abef1f7d84fefb03ef23ffc90417d173aea7ceef..ff647ca1c4895d9f08049ea840496b86b40fbf28 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/uaccess.h>
index 94e7e3c8c05ad3f0720aaae3d6df588eebd2d50b..d97779ef72cb2846dabe8487ebf4cc0b4c7c6bf3 100644 (file)
@@ -552,7 +552,7 @@ static int hvc_chars_in_buffer(struct tty_struct *tty)
        struct hvc_struct *hp = tty->driver_data;
 
        if (!hp)
-               return -1;
+               return 0;
        return hp->n_outbuf;
 }
 
index 5dcbe603eca2eae981e70077d1cddfc7616ab0a9..91b53eb1c053bff15349b80d6b949abb71ad4fb8 100644 (file)
@@ -305,10 +305,11 @@ static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw,
             (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))
            == BIOS_CNTL_LOCK_ENABLE_MASK) {
                static __initdata /*const*/ char warning[] =
-                       KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n"
-                       KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n"
-                       KERN_WARNING PFX "you are certain that your system has a functional\n"
-                       KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n";
+                       KERN_WARNING
+PFX "Firmware space is locked read-only. If you can't or\n"
+PFX "don't want to disable this in firmware setup, and if\n"
+PFX "you are certain that your system has a functional\n"
+PFX "RNG, try using the 'no_fwh_detect' option.\n";
 
                if (no_fwh_detect)
                        return -ENODEV;
index 4159292e35cf4e570fa6c0322bbe26b339ef9569..4f1f4cd670dac7dcd252d088ee2760d2977df1f3 100644 (file)
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include <linux/serial.h>
+#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
@@ -1478,10 +1479,10 @@ static int __devinit load_firmware(struct pci_dev *pdev,
                status = inw(base + 0x4);
                if (status != 0) {
                        dev_warn(&pdev->dev, "Card%d rejected load header:\n"
-                               KERN_WARNING "Address:0x%x\n"
-                               KERN_WARNING "Count:0x%x\n"
-                               KERN_WARNING "Status:0x%x\n",
-                               index + 1, frame->addr, frame->count, status);
+                                "Address:0x%x\n"
+                                "Count:0x%x\n"
+                                "Status:0x%x\n",
+                                index + 1, frame->addr, frame->count, status);
                        goto errrelfw;
                }
                outsw(base, frame->data, word_count);
@@ -1526,10 +1527,10 @@ static int __devinit load_firmware(struct pci_dev *pdev,
                status = inw(base + 0x4);
                if (status != 0) {
                        dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
-                               KERN_WARNING "Address:0x%x\n"
-                               KERN_WARNING "Count:0x%x\n"
-                               KERN_WARNING "Status: 0x%x\n",
-                               index + 1, frame->addr, frame->count, status);
+                                "Address:0x%x\n"
+                                "Count:0x%x\n"
+                                "Status: 0x%x\n",
+                                index + 1, frame->addr, frame->count, status);
                        goto errrelfw;
                }
 
index 0c999f5bb3db6df69e0062609e9f82d1c0ee8955..ab2f3349c5c4cc9dc13e3021307a3ede3ddf9a92 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
index 65b6ff2442c6df4edfd839b37752ded8340df9c9..dd0083bbb64addaea9b286ac8d5a914a474625ea 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/major.h>
+#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
index 52d953eb30c3d6872eb6e4d3b3710ba7578e272c..dbf8d52f31d02d743b0436abcc871104bdf7e588 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
index 1c43c8cdee259f18d3ffbf0e063be81dc5c2f3f2..c68118efad844940e7977f4e30afa5f3c694977d 100644 (file)
@@ -97,6 +97,7 @@
 #include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/errno.h>
+#include <linux/smp_lock.h>
 #include <linux/string.h>      /* used in new tty drivers */
 #include <linux/signal.h>      /* used in new tty drivers */
 #include <linux/if.h>
index 2e99158ebb8a6e7922a1ac0c0f97c0a06b49f338..6934025a1ac10d5e094c0b9df10ec88ff0f40468 100644 (file)
@@ -58,6 +58,7 @@
 #include <linux/ioport.h>
 #include <linux/in.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/tty.h>
 #include <linux/errno.h>
 #include <linux/string.h>      /* used in new tty drivers */
index 94a5d5020abcec935e08d6bc74180a249ea58423..4e28b35024ece708161ec948f37b926fc8455c1b 100644 (file)
@@ -300,8 +300,7 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
                        if (space < 2)
                                return -1;
                        tty->canon_column = tty->column = 0;
-                       tty_put_char(tty, '\r');
-                       tty_put_char(tty, c);
+                       tty->ops->write(tty, "\r\n", 2);
                        return 2;
                }
                tty->canon_column = tty->column;
@@ -1331,9 +1330,6 @@ handle_newline:
 
 static void n_tty_write_wakeup(struct tty_struct *tty)
 {
-       /* Write out any echoed characters that are still pending */
-       process_echoes(tty);
-
        if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags))
                kill_fasync(&tty->fasync, SIGIO, POLL_OUT);
 }
@@ -1586,6 +1582,7 @@ static int n_tty_open(struct tty_struct *tty)
 
 static inline int input_available_p(struct tty_struct *tty, int amt)
 {
+       tty_flush_to_ldisc(tty);
        if (tty->icanon) {
                if (tty->canon_data)
                        return 1;
index 574f1c79b6e637ededd5a4708651bc7902aea960..ec58d8c387ff2303f67db428622f68b7eff76057 100644 (file)
@@ -828,7 +828,7 @@ static int receive_data(enum port_type index, struct nozomi *dc)
        struct port *port = &dc->port[index];
        void __iomem *addr = port->dl_addr[port->toggle_dl];
        struct tty_struct *tty = tty_port_tty_get(&port->port);
-       int i;
+       int i, ret;
 
        if (unlikely(!tty)) {
                DBG1("tty not open for port: %d?", index);
@@ -844,12 +844,14 @@ static int receive_data(enum port_type index, struct nozomi *dc)
 
                /* disable interrupt in downlink... */
                disable_transmit_dl(index, dc);
-               return 0;
+               ret = 0;
+               goto put;
        }
 
        if (unlikely(size == 0)) {
                dev_err(&dc->pdev->dev, "size == 0?\n");
-               return 1;
+               ret = 1;
+               goto put;
        }
 
        tty_buffer_request_room(tty, size);
@@ -871,8 +873,10 @@ static int receive_data(enum port_type index, struct nozomi *dc)
        }
 
        set_bit(index, &dc->flip);
+       ret = 1;
+put:
        tty_kref_put(tty);
-       return 1;
+       return ret;
 }
 
 /* Debug for interrupts */
@@ -1862,16 +1866,14 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty)
 {
        struct port *port = tty->driver_data;
        struct nozomi *dc = get_dc_by_tty(tty);
-       s32 rval;
+       s32 rval = 0;
 
        if (unlikely(!dc || !port)) {
-               rval = -ENODEV;
                goto exit_in_buffer;
        }
 
        if (unlikely(!port->port.count)) {
                dev_err(&dc->pdev->dev, "No tty open?\n");
-               rval = -ENODEV;
                goto exit_in_buffer;
        }
 
index 569f2f7743a78ddc80f4e7714c6456506b8a4995..674b3ab3587d505458fbdb802fc0a7cbcdf7d2eb 100644 (file)
@@ -320,10 +320,10 @@ static int ipw_chars_in_buffer(struct tty_struct *linux_tty)
        struct ipw_tty *tty = linux_tty->driver_data;
 
        if (!tty)
-               return -ENODEV;
+               return 0;
 
        if (!tty->open_count)
-               return -EINVAL;
+               return 0;
 
        return tty->tx_bytes_queued;
 }
index daebe1ba43d42ad0f3a4053cea80e6c411e8968a..b33d6688e9109a31bb27a6b297a73a8e69c5989d 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/major.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/sysctl.h>
 #include <linux/device.h>
 #include <linux/uaccess.h>
@@ -75,114 +76,82 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
  */
 static void pty_unthrottle(struct tty_struct *tty)
 {
-       struct tty_struct *o_tty = tty->link;
-
-       if (!o_tty)
-               return;
-
-       tty_wakeup(o_tty);
+       tty_wakeup(tty->link);
        set_bit(TTY_THROTTLED, &tty->flags);
 }
 
-/*
- * WSH 05/24/97: modified to
- *   (1) use space in tty->flip instead of a shared temp buffer
- *      The flip buffers aren't being used for a pty, so there's lots
- *      of space available.  The buffer is protected by a per-pty
- *      semaphore that should almost never come under contention.
- *   (2) avoid redundant copying for cases where count >> receive_room
- * N.B. Calls from user space may now return an error code instead of
- * a count.
+/**
+ *     pty_space       -       report space left for writing
+ *     @to: tty we are writing into
  *
- * FIXME: Our pty_write method is called with our ldisc lock held but
- * not our partners. We can't just wait on the other one blindly without
- * risking deadlocks. At some point when everything has settled down we need
- * to look into making pty_write at least able to sleep over an ldisc change.
+ *     The tty buffers allow 64K but we sneak a peak and clip at 8K this
+ *     allows a lot of overspill room for echo and other fun messes to
+ *     be handled properly
+ */
+
+static int pty_space(struct tty_struct *to)
+{
+       int n = 8192 - to->buf.memory_used;
+       if (n < 0)
+               return 0;
+       return n;
+}
+
+/**
+ *     pty_write               -       write to a pty
+ *     @tty: the tty we write from
+ *     @buf: kernel buffer of data
+ *     @count: bytes to write
  *
- * The return on no ldisc is a bit counter intuitive but the logic works
- * like this. During an ldisc change the other end will flush its buffers. We
- * thus return the full length which is identical to the case where we had
- * proper locking and happened to queue the bytes just before the flush during
- * the ldisc change.
+ *     Our "hardware" write method. Data is coming from the ldisc which
+ *     may be in a non sleeping state. We simply throw this at the other
+ *     end of the link as if we were an IRQ handler receiving stuff for
+ *     the other side of the pty/tty pair.
  */
-static int pty_write(struct tty_struct *tty, const unsigned char *buf,
-                                                               int count)
+
+static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c)
 {
        struct tty_struct *to = tty->link;
-       struct tty_ldisc *ld;
-       int c = count;
 
-       if (!to || tty->stopped)
+       if (tty->stopped)
                return 0;
-       ld = tty_ldisc_ref(to);
-
-       if (ld) {
-               c = to->receive_room;
-               if (c > count)
-                       c = count;
-               ld->ops->receive_buf(to, buf, NULL, c);
-               tty_ldisc_deref(ld);
+
+       if (c > 0) {
+               /* Stuff the data into the input queue of the other end */
+               c = tty_insert_flip_string(to, buf, c);
+               /* And shovel */
+               tty_flip_buffer_push(to);
+               tty_wakeup(tty);
        }
        return c;
 }
 
+/**
+ *     pty_write_room  -       write space
+ *     @tty: tty we are writing from
+ *
+ *     Report how many bytes the ldisc can send into the queue for
+ *     the other device.
+ */
+
 static int pty_write_room(struct tty_struct *tty)
 {
-       struct tty_struct *to = tty->link;
-
-       if (!to || tty->stopped)
+       if (tty->stopped)
                return 0;
-
-       return to->receive_room;
+       return pty_space(tty->link);
 }
 
-/*
- *     WSH 05/24/97:  Modified for asymmetric MASTER/SLAVE behavior
- *     The chars_in_buffer() value is used by the ldisc select() function
- *     to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256).
- *     The pty driver chars_in_buffer() Master/Slave must behave differently:
- *
- *      The Master side needs to allow typed-ahead commands to accumulate
- *      while being canonicalized, so we report "our buffer" as empty until
- *     some threshold is reached, and then report the count. (Any count >
- *     WAKEUP_CHARS is regarded by select() as "full".)  To avoid deadlock
- *     the count returned must be 0 if no canonical data is available to be
- *     read. (The N_TTY ldisc.chars_in_buffer now knows this.)
+/**
+ *     pty_chars_in_buffer     -       characters currently in our tx queue
+ *     @tty: our tty
  *
- *     The Slave side passes all characters in raw mode to the Master side's
- *     buffer where they can be read immediately, so in this case we can
- *     return the true count in the buffer.
+ *     Report how much we have in the transmit queue. As everything is
+ *     instantly at the other end this is easy to implement.
  */
+
 static int pty_chars_in_buffer(struct tty_struct *tty)
 {
-       struct tty_struct *to = tty->link;
-       struct tty_ldisc *ld;
-       int count = 0;
-
-       /* We should get the line discipline lock for "tty->link" */
-       if (!to)
-               return 0;
-       /* We cannot take a sleeping reference here without deadlocking with
-          an ldisc change - but it doesn't really matter */
-       ld = tty_ldisc_ref(to);
-       if (ld == NULL)
-               return 0;
-
-       /* The ldisc must report 0 if no characters available to be read */
-       if (ld->ops->chars_in_buffer)
-               count = ld->ops->chars_in_buffer(to);
-
-       tty_ldisc_deref(ld);
-
-       if (tty->driver->subtype == PTY_TYPE_SLAVE)
-               return count;
-
-       /* Master side driver ... if the other side's read buffer is less than
-        * half full, return 0 to allow writers to proceed; otherwise return
-        * the count.  This leaves a comfortable margin to avoid overflow,
-        * and still allows half a buffer's worth of typed-ahead commands.
-        */
-       return (count < N_TTY_BUF_SIZE/2) ? 0 : count;
+       return 0;
 }
 
 /* Set the lock flag on a pty */
@@ -202,20 +171,10 @@ static void pty_flush_buffer(struct tty_struct *tty)
 {
        struct tty_struct *to = tty->link;
        unsigned long flags;
-       struct tty_ldisc *ld;
 
        if (!to)
                return;
-       ld = tty_ldisc_ref(to);
-
-       /* The other end is changing discipline */
-       if (!ld)
-               return;
-
-       if (ld->ops->flush_buffer)
-               to->ldisc->ops->flush_buffer(to);
-       tty_ldisc_deref(ld);
-
+       /* tty_buffer_flush(to); FIXME */
        if (to->packet) {
                spin_lock_irqsave(&tty->ctrl_lock, flags);
                tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
index ce81da5b2da9a20079cf46fe64eddcac546b1474..d58c2eb07f07aaad25a568095ccaab7d3e53f686 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/miscdevice.h>
 #include <linux/init.h>
 
index 217660451237a79c7cd186d38697bad07f9dbcf8..171711acf5cd33736ebb74d69a6f02983b15bdb3 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/tty_flip.h>
+#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
 
index 63d5b628477a72bbffb6cb8696a0a4b615ef5725..0e29a23ec4c50be1f2d74b492c91785a8feae2b3 100644 (file)
@@ -73,6 +73,7 @@
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
+#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
index f1f24f0ee26f4281392925b0d86b4ad4a5e897af..51e7a46787bea72aa23e93535e4d9ce636b63448 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/interrupt.h>
 #include <linux/serial.h>
 #include <linux/serialP.h>
+#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
index e72be4190a442a6378cca9a68a306b3421dcb06c..268e17f9ec3f50c4586607bb0dd59e76442f3bee 100644 (file)
@@ -87,6 +87,7 @@
 #include <linux/tty_flip.h>
 #include <linux/mm.h>
 #include <linux/serial.h>
+#include <linux/smp_lock.h>
 #include <linux/fcntl.h>
 #include <linux/major.h>
 #include <linux/delay.h>
@@ -1808,10 +1809,10 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file,
                if (clear & TIOCM_DTR)
                        port->MSVR &= ~MSVR_DTR;
        }
-       spin_lock_irqsave(&bp->lock, flags);
+       spin_lock(&bp->lock);
        sx_out(bp, CD186x_CAR, port_No(port));
        sx_out(bp, CD186x_MSVR, port->MSVR);
-       spin_unlock_irqrestore(&bp->lock, flags);
+       spin_unlock(&bp->lock);
        spin_unlock_irqrestore(&port->lock, flags);
        func_exit();
        return 0;
@@ -1832,11 +1833,11 @@ static int sx_send_break(struct tty_struct *tty, int length)
        port->break_length = SPECIALIX_TPS / HZ * length;
        port->COR2 |= COR2_ETC;
        port->IER  |= IER_TXRDY;
-       spin_lock_irqsave(&bp->lock, flags);
+       spin_lock(&bp->lock);
        sx_out(bp, CD186x_CAR, port_No(port));
        sx_out(bp, CD186x_COR2, port->COR2);
        sx_out(bp, CD186x_IER, port->IER);
-       spin_unlock_irqrestore(&bp->lock, flags);
+       spin_unlock(&bp->lock);
        spin_unlock_irqrestore(&port->lock, flags);
        sx_wait_CCR(bp);
        spin_lock_irqsave(&bp->lock, flags);
@@ -2022,9 +2023,9 @@ static void sx_unthrottle(struct tty_struct *tty)
        if (sx_crtscts(tty))
                port->MSVR |= MSVR_DTR;
        /* Else clause: see remark in "sx_throttle"... */
-       spin_lock_irqsave(&bp->lock, flags);
+       spin_lock(&bp->lock);
        sx_out(bp, CD186x_CAR, port_No(port));
-       spin_unlock_irqrestore(&bp->lock, flags);
+       spin_unlock(&bp->lock);
        if (I_IXOFF(tty)) {
                spin_unlock_irqrestore(&port->lock, flags);
                sx_wait_CCR(bp);
@@ -2034,9 +2035,9 @@ static void sx_unthrottle(struct tty_struct *tty)
                sx_wait_CCR(bp);
                spin_lock_irqsave(&port->lock, flags);
        }
-       spin_lock_irqsave(&bp->lock, flags);
+       spin_lock(&bp->lock);
        sx_out(bp, CD186x_MSVR, port->MSVR);
-       spin_unlock_irqrestore(&bp->lock, flags);
+       spin_unlock(&bp->lock);
        spin_unlock_irqrestore(&port->lock, flags);
 
        func_exit();
@@ -2060,10 +2061,10 @@ static void sx_stop(struct tty_struct *tty)
 
        spin_lock_irqsave(&port->lock, flags);
        port->IER &= ~IER_TXRDY;
-       spin_lock_irqsave(&bp->lock, flags);
+       spin_lock(&bp->lock);
        sx_out(bp, CD186x_CAR, port_No(port));
        sx_out(bp, CD186x_IER, port->IER);
-       spin_unlock_irqrestore(&bp->lock, flags);
+       spin_unlock(&bp->lock);
        spin_unlock_irqrestore(&port->lock, flags);
 
        func_exit();
@@ -2088,10 +2089,10 @@ static void sx_start(struct tty_struct *tty)
        spin_lock_irqsave(&port->lock, flags);
        if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
                port->IER |= IER_TXRDY;
-               spin_lock_irqsave(&bp->lock, flags);
+               spin_lock(&bp->lock);
                sx_out(bp, CD186x_CAR, port_No(port));
                sx_out(bp, CD186x_IER, port->IER);
-               spin_unlock_irqrestore(&bp->lock, flags);
+               spin_unlock(&bp->lock);
        }
        spin_unlock_irqrestore(&port->lock, flags);
 
index 518f2a25d91ec6b1a208c6fe233c505a7395aa47..a81ec4fcf6ff4480b9473587d5424b09cb74510e 100644 (file)
 #include <linux/eisa.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/miscdevice.h>
 #include <linux/bitops.h>
index afded3a2379c592082e85e373236addce5d9fcd3..813552f14884427ea785b1ac0e2bec080c704a6a 100644 (file)
@@ -81,6 +81,7 @@
 #include <linux/mm.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/vmalloc.h>
index a2e67e6df3a1406697e3482c93689e314bfe0f12..91f20a92fddf2f9afb76dc10b7ab1d86a150954f 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/mm.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/netdevice.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
index 6f727e3c53ade1028d21cf11f364bdcc2fafbed9..8d4a2a8a0a7001ad314fa282c589229ea53d8804 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/mm.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/netdevice.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
index 0db35857e4d85e11dcd343117777b610e025be10..5d7a02f63e1c66e539702acc31eac13b4f9ef7fe 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/spinlock.h>
 #include <linux/vt_kern.h>
 #include <linux/workqueue.h>
-#include <linux/kexec.h>
 #include <linux/hrtimer.h>
 #include <linux/oom.h>
 
@@ -124,9 +123,12 @@ static struct sysrq_key_op sysrq_unraw_op = {
 static void sysrq_handle_crash(int key, struct tty_struct *tty)
 {
        char *killer = NULL;
+
+       panic_on_oops = 1;      /* force panic */
+       wmb();
        *killer = 1;
 }
-static struct sysrq_key_op sysrq_crashdump_op = {
+static struct sysrq_key_op sysrq_crash_op = {
        .handler        = sysrq_handle_crash,
        .help_msg       = "Crash",
        .action_msg     = "Trigger a crash",
@@ -401,7 +403,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
         */
        NULL,                           /* a */
        &sysrq_reboot_op,               /* b */
-       &sysrq_crashdump_op,            /* c & ibm_emac driver debug */
+       &sysrq_crash_op,                /* c & ibm_emac driver debug */
        &sysrq_showlocks_op,            /* d */
        &sysrq_term_op,                 /* e */
        &sysrq_moom_op,                 /* f */
index 6062b62800fd2d97e01a640fedaf655983b6997d..b3ec9b10e29208e5272f2f00593d6cf9421503c1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for TANBAC TB0219 base board.
  *
- *  Copyright (C) 2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -28,7 +28,7 @@
 #include <asm/vr41xx/giu.h>
 #include <asm/vr41xx/tb0219.h>
 
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
 MODULE_DESCRIPTION("TANBAC TB0219 base board driver");
 MODULE_LICENSE("GPL");
 
index ccdd828adcef2711e2ed91a7c52f38b1a6dca844..b0603b2e56844e38e1e4082eaf20ed115d78b07e 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/poll.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 
 #include "tpm.h"
 
index 810ee25d66a48fa5042c84b7f4cf47f0a870ef4e..3108991c5c8b60f312742ca4eaeb37e4c812ad4c 100644 (file)
@@ -461,6 +461,19 @@ static void flush_to_ldisc(struct work_struct *work)
        tty_ldisc_deref(disc);
 }
 
+/**
+ *     tty_flush_to_ldisc
+ *     @tty: tty to push
+ *
+ *     Push the terminal flip buffers to the line discipline.
+ *
+ *     Must not be called from IRQ context.
+ */
+void tty_flush_to_ldisc(struct tty_struct *tty)
+{
+       flush_to_ldisc(&tty->buf.work.work);
+}
+
 /**
  *     tty_flip_buffer_push    -       terminal
  *     @tty: tty to push
index b24f6c6a1ea317c1ccf399eaf2842f281175d70d..ad6ba4ed280853bce299b8bf6aab4d3d53b7c68e 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/module.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
index a19e935847b0a14e9740184e32d6e099efc26955..e48af9f79219a0dec76315724eeeaaae3a4102d6 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/device.h>
 #include <linux/wait.h>
 #include <linux/bitops.h>
@@ -49,6 +48,41 @@ static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
 /* Line disc dispatch table */
 static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
 
+static inline struct tty_ldisc *get_ldisc(struct tty_ldisc *ld)
+{
+       if (ld)
+               atomic_inc(&ld->users);
+       return ld;
+}
+
+static void put_ldisc(struct tty_ldisc *ld)
+{
+       unsigned long flags;
+
+       if (WARN_ON_ONCE(!ld))
+               return;
+
+       /*
+        * If this is the last user, free the ldisc, and
+        * release the ldisc ops.
+        *
+        * We really want an "atomic_dec_and_lock_irqsave()",
+        * but we don't have it, so this does it by hand.
+        */
+       local_irq_save(flags);
+       if (atomic_dec_and_lock(&ld->users, &tty_ldisc_lock)) {
+               struct tty_ldisc_ops *ldo = ld->ops;
+
+               ldo->refcount--;
+               module_put(ldo->owner);
+               spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+               kfree(ld);
+               return;
+       }
+       local_irq_restore(flags);
+}
+
 /**
  *     tty_register_ldisc      -       install a line discipline
  *     @disc: ldisc number
@@ -143,7 +177,7 @@ static struct tty_ldisc *tty_ldisc_try_get(int disc)
                        /* lock it */
                        ldops->refcount++;
                        ld->ops = ldops;
-                       ld->refcount = 0;
+                       atomic_set(&ld->users, 1);
                        err = 0;
                }
        }
@@ -182,35 +216,6 @@ static struct tty_ldisc *tty_ldisc_get(int disc)
        return ld;
 }
 
-/**
- *     tty_ldisc_put           -       drop ldisc reference
- *     @ld: ldisc
- *
- *     Drop a reference to a line discipline. Manage refcounts and
- *     module usage counts. Free the ldisc once the recount hits zero.
- *
- *     Locking:
- *             takes tty_ldisc_lock to guard against ldisc races
- */
-
-static void tty_ldisc_put(struct tty_ldisc *ld)
-{
-       unsigned long flags;
-       int disc = ld->ops->num;
-       struct tty_ldisc_ops *ldo;
-
-       BUG_ON(disc < N_TTY || disc >= NR_LDISCS);
-
-       spin_lock_irqsave(&tty_ldisc_lock, flags);
-       ldo = tty_ldiscs[disc];
-       BUG_ON(ldo->refcount == 0);
-       ldo->refcount--;
-       module_put(ldo->owner);
-       spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-       WARN_ON(ld->refcount);
-       kfree(ld);
-}
-
 static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
 {
        return (*pos < NR_LDISCS) ? pos : NULL;
@@ -235,7 +240,7 @@ static int tty_ldiscs_seq_show(struct seq_file *m, void *v)
        if (IS_ERR(ld))
                return 0;
        seq_printf(m, "%-10s %2d\n", ld->ops->name ? ld->ops->name : "???", i);
-       tty_ldisc_put(ld);
+       put_ldisc(ld);
        return 0;
 }
 
@@ -289,20 +294,17 @@ static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
  *     Locking: takes tty_ldisc_lock
  */
 
-static int tty_ldisc_try(struct tty_struct *tty)
+static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty)
 {
        unsigned long flags;
        struct tty_ldisc *ld;
-       int ret = 0;
 
        spin_lock_irqsave(&tty_ldisc_lock, flags);
-       ld = tty->ldisc;
-       if (test_bit(TTY_LDISC, &tty->flags)) {
-               ld->refcount++;
-               ret = 1;
-       }
+       ld = NULL;
+       if (test_bit(TTY_LDISC, &tty->flags))
+               ld = get_ldisc(tty->ldisc);
        spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-       return ret;
+       return ld;
 }
 
 /**
@@ -323,10 +325,11 @@ static int tty_ldisc_try(struct tty_struct *tty)
 
 struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
 {
+       struct tty_ldisc *ld;
+
        /* wait_event is a macro */
-       wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
-       WARN_ON(tty->ldisc->refcount == 0);
-       return tty->ldisc;
+       wait_event(tty_ldisc_wait, (ld = tty_ldisc_try(tty)) != NULL);
+       return ld;
 }
 EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
 
@@ -343,9 +346,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
 
 struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
 {
-       if (tty_ldisc_try(tty))
-               return tty->ldisc;
-       return NULL;
+       return tty_ldisc_try(tty);
 }
 EXPORT_SYMBOL_GPL(tty_ldisc_ref);
 
@@ -361,21 +362,15 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref);
 
 void tty_ldisc_deref(struct tty_ldisc *ld)
 {
-       unsigned long flags;
-
-       BUG_ON(ld == NULL);
-
-       spin_lock_irqsave(&tty_ldisc_lock, flags);
-       if (ld->refcount == 0)
-               printk(KERN_ERR "tty_ldisc_deref: no references.\n");
-       else
-               ld->refcount--;
-       if (ld->refcount == 0)
-               wake_up(&tty_ldisc_wait);
-       spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+       put_ldisc(ld);
 }
 EXPORT_SYMBOL_GPL(tty_ldisc_deref);
 
+static inline void tty_ldisc_put(struct tty_ldisc *ld)
+{
+       put_ldisc(ld);
+}
+
 /**
  *     tty_ldisc_enable        -       allow ldisc use
  *     @tty: terminal to activate ldisc on
@@ -513,8 +508,9 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
  *     be obtained while the delayed work queue halt ensures that no more
  *     data is fed to the ldisc.
  *
- *     In order to wait for any existing references to complete see
- *     tty_ldisc_wait_idle.
+ *     You need to do a 'flush_scheduled_work()' (outside the ldisc_mutex)
+ *     in order to make sure any currently executing ldisc work is also
+ *     flushed.
  */
 
 static int tty_ldisc_halt(struct tty_struct *tty)
@@ -523,31 +519,6 @@ static int tty_ldisc_halt(struct tty_struct *tty)
        return cancel_delayed_work(&tty->buf.work);
 }
 
-/**
- *     tty_ldisc_wait_idle     -       wait for the ldisc to become idle
- *     @tty: tty to wait for
- *
- *     Wait for the line discipline to become idle. The discipline must
- *     have been halted for this to guarantee it remains idle.
- *
- *     tty_ldisc_lock protects the ref counts currently.
- */
-
-static int tty_ldisc_wait_idle(struct tty_struct *tty)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&tty_ldisc_lock, flags);
-       while (tty->ldisc->refcount) {
-               spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-               if (wait_event_timeout(tty_ldisc_wait,
-                               tty->ldisc->refcount == 0, 5 * HZ) == 0)
-                       return -EBUSY;
-               spin_lock_irqsave(&tty_ldisc_lock, flags);
-       }
-       spin_unlock_irqrestore(&tty_ldisc_lock, flags);
-       return 0;
-}
-
 /**
  *     tty_set_ldisc           -       set line discipline
  *     @tty: the terminal to set
@@ -643,14 +614,6 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 
        flush_scheduled_work();
 
-       /* Let any existing reference holders finish */
-       retval = tty_ldisc_wait_idle(tty);
-       if (retval < 0) {
-               clear_bit(TTY_LDISC_CHANGING, &tty->flags);
-               tty_ldisc_put(new_ldisc);
-               return retval;
-       }
-
        mutex_lock(&tty->ldisc_mutex);
        if (test_bit(TTY_HUPPED, &tty->flags)) {
                /* We were raced by the hangup method. It will have stomped
@@ -791,17 +754,22 @@ void tty_ldisc_hangup(struct tty_struct *tty)
         * N_TTY.
         */
        if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
-               /* Avoid racing set_ldisc */
-               mutex_lock(&tty->ldisc_mutex);
-               /* Switch back to N_TTY */
+               /* Make sure the old ldisc is quiescent */
                tty_ldisc_halt(tty);
-               tty_ldisc_wait_idle(tty);
-               tty_ldisc_reinit(tty);
-               /* At this point we have a closed ldisc and we want to
-                  reopen it. We could defer this to the next open but
-                  it means auditing a lot of other paths so this is a FIXME */
-               WARN_ON(tty_ldisc_open(tty, tty->ldisc));
-               tty_ldisc_enable(tty);
+               flush_scheduled_work();
+
+               /* Avoid racing set_ldisc or tty_ldisc_release */
+               mutex_lock(&tty->ldisc_mutex);
+               if (tty->ldisc) {       /* Not yet closed */
+                       /* Switch back to N_TTY */
+                       tty_ldisc_reinit(tty);
+                       /* At this point we have a closed ldisc and we want to
+                          reopen it. We could defer this to the next open but
+                          it means auditing a lot of other paths so this is
+                          a FIXME */
+                       WARN_ON(tty_ldisc_open(tty, tty->ldisc));
+                       tty_ldisc_enable(tty);
+               }
                mutex_unlock(&tty->ldisc_mutex);
                tty_reset_termios(tty);
        }
@@ -858,24 +826,25 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
        tty_ldisc_halt(tty);
        flush_scheduled_work();
 
+       mutex_lock(&tty->ldisc_mutex);
        /*
-        * Wait for any short term users (we know they are just driver
-        * side waiters as the file is closing so user count on the file
-        * side is zero.
+        * Now kill off the ldisc
         */
+       tty_ldisc_close(tty, tty->ldisc);
+       tty_ldisc_put(tty->ldisc);
+       /* Force an oops if we mess this up */
+       tty->ldisc = NULL;
 
-       tty_ldisc_wait_idle(tty);
-
-       /*
-        * Shutdown the current line discipline, and reset it to N_TTY.
-        *
-        * FIXME: this MUST get fixed for the new reflocking
-        */
+       /* Ensure the next open requests the N_TTY ldisc */
+       tty_set_termios_ldisc(tty, N_TTY);
+       mutex_unlock(&tty->ldisc_mutex);
 
-       tty_ldisc_reinit(tty);
        /* This will need doing differently if we need to lock */
        if (o_tty)
                tty_ldisc_release(o_tty, NULL);
+
+       /* And the memory resources remaining (buffers, termios) will be
+          disposed of when the kref hits zero */
 }
 
 /**
index 4e862a75f7ff213bd62022e852a9d485b65adbbf..9769b1149f7602cf9c2c7ea1a3eab70bfad9b0a0 100644 (file)
@@ -267,7 +267,7 @@ int tty_port_block_til_ready(struct tty_port *port,
        if (retval == 0)
                port->flags |= ASYNC_NORMAL_ACTIVE;
        spin_unlock_irqrestore(&port->lock, flags);
-       return 0;
+       return retval;
        
 }
 EXPORT_SYMBOL(tty_port_block_til_ready);
index d94d25c12aa87ccacfe12d72ea5e72d4f3f4f93c..c1791a63d99d40c2e1dbe7a4fba6e1f8cfba8c16 100644 (file)
@@ -495,11 +495,15 @@ void vcs_remove_sysfs(int index)
 
 int __init vcs_init(void)
 {
+       unsigned int i;
+
        if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
                panic("unable to get major %d for vcs device", VCS_MAJOR);
        vc_class = class_create(THIS_MODULE, "vc");
 
        device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
        device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+       for (i = 0; i < MIN_NR_CONSOLES; i++)
+               vcs_make_sysfs(i);
        return 0;
 }
index d9113b4c76e370bad289b19558958448846a6064..404f4c1ee43145c5429f6639f0454e5a59818f3f 100644 (file)
@@ -89,6 +89,7 @@
 #include <linux/mutex.h>
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
+#include <linux/smp_lock.h>
 #include <linux/tiocl.h>
 #include <linux/kbd_kern.h>
 #include <linux/consolemap.h>
@@ -769,14 +770,12 @@ int vc_allocate(unsigned int currcons)    /* return 0 on success */
            visual_init(vc, currcons, 1);
            if (!*vc->vc_uni_pagedir_loc)
                con_set_default_unimap(vc);
-           if (!vc->vc_kmalloced)
-               vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
+           vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
            if (!vc->vc_screenbuf) {
                kfree(vc);
                vc_cons[currcons].d = NULL;
                return -ENOMEM;
            }
-           vc->vc_kmalloced = 1;
            vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
            vcs_make_sysfs(currcons);
            atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, &param);
@@ -912,10 +911,8 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
        if (new_scr_end > new_origin)
                scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
                            new_scr_end - new_origin);
-       if (vc->vc_kmalloced)
-               kfree(vc->vc_screenbuf);
+       kfree(vc->vc_screenbuf);
        vc->vc_screenbuf = newscreen;
-       vc->vc_kmalloced = 1;
        vc->vc_screenbuf_size = new_screen_size;
        set_origin(vc);
 
@@ -994,8 +991,7 @@ void vc_deallocate(unsigned int currcons)
                vc->vc_sw->con_deinit(vc);
                put_pid(vc->vt_pid);
                module_put(vc->vc_sw->owner);
-               if (vc->vc_kmalloced)
-                       kfree(vc->vc_screenbuf);
+               kfree(vc->vc_screenbuf);
                if (currcons >= MIN_NR_CONSOLES)
                        kfree(vc);
                vc_cons[currcons].d = NULL;
@@ -2880,7 +2876,6 @@ static int __init con_init(void)
                INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
                visual_init(vc, currcons, 1);
                vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
-               vc->vc_kmalloced = 0;
                vc_init(vc, vc->vc_rows, vc->vc_cols,
                        currcons || !vc->vc_sw->con_save_screen);
        }
index 7539bed0f7e07ec315e9dff21a3a0914161afee6..95189f288f8ccffcab9204c9fbeec0cd1357e3a4 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/console.h>
 #include <linux/consolemap.h>
 #include <linux/signal.h>
+#include <linux/smp_lock.h>
 #include <linux/timex.h>
 
 #include <asm/io.h>
index 2964f5f4a7ef3348104044f008992d22b08b55b1..6b3e0c2f33e2b193838fbecc0dda72aa9f0db5ef 100644 (file)
@@ -40,6 +40,7 @@ struct sh_cmt_priv {
        struct platform_device *pdev;
 
        unsigned long flags;
+       unsigned long flags_suspend;
        unsigned long match_value;
        unsigned long next_match_value;
        unsigned long max_match_value;
@@ -667,11 +668,38 @@ static int __devexit sh_cmt_remove(struct platform_device *pdev)
        return -EBUSY; /* cannot unregister clockevent and clocksource */
 }
 
+static int sh_cmt_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct sh_cmt_priv *p = platform_get_drvdata(pdev);
+
+       /* save flag state and stop CMT channel */
+       p->flags_suspend = p->flags;
+       sh_cmt_stop(p, p->flags);
+       return 0;
+}
+
+static int sh_cmt_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct sh_cmt_priv *p = platform_get_drvdata(pdev);
+
+       /* start CMT channel from saved state */
+       sh_cmt_start(p, p->flags_suspend);
+       return 0;
+}
+
+static struct dev_pm_ops sh_cmt_dev_pm_ops = {
+       .suspend = sh_cmt_suspend,
+       .resume = sh_cmt_resume,
+};
+
 static struct platform_driver sh_cmt_device_driver = {
        .probe          = sh_cmt_probe,
        .remove         = __devexit_p(sh_cmt_remove),
        .driver         = {
                .name   = "sh_cmt",
+               .pm     = &sh_cmt_dev_pm_ops,
        }
 };
 
index 9ffb05f4095d7598c6b8fc8e37bc55cae96ae2b6..93c2322feab79e8e119d0b51949ac0b1bc42135d 100644 (file)
@@ -161,7 +161,7 @@ static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta,
        if (periodic)
                sh_tmu_write(p, TCOR, delta);
        else
-               sh_tmu_write(p, TCOR, 0);
+               sh_tmu_write(p, TCOR, 0xffffffff);
 
        sh_tmu_write(p, TCNT, delta);
 
index c769ef269fb5833e96b3ac32ece432c4ce1de564..408c2af25d5097c93f41c6fc519bbfbcae0f230f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     cn_queue.c
  *
- * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
index fd336c5a9057a8da729ebd2d3961cbb7b6a4c271..08b2500f21ec1757cd57472326843642e0a2460f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     connector.c
  *
- * 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * 2004+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -33,7 +33,7 @@
 #include <net/sock.h>
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
 MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
 
 static u32 cn_idx = CN_IDX_CONNECTOR;
index 6e2ec0b189489803ebaa55ecb4ae094bd2a1fdf0..2968ed6a9c4997003591a9ebc33546e19d6deb0b 100644 (file)
@@ -761,6 +761,10 @@ static struct kobj_type ktype_cpufreq = {
  * cpufreq_add_dev - add a CPU device
  *
  * Adds the cpufreq interface for a CPU device.
+ *
+ * The Oracle says: try running cpufreq registration/unregistration concurrently
+ * with with cpu hotplugging and all hell will break loose. Tried to clean this
+ * mess up, but more thorough testing is needed. - Mathieu
  */
 static int cpufreq_add_dev(struct sys_device *sys_dev)
 {
@@ -772,9 +776,6 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
        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;
@@ -804,15 +805,12 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
                goto nomem_out;
        }
        if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL)) {
-               kfree(policy);
                ret = -ENOMEM;
-               goto nomem_out;
+               goto err_free_policy;
        }
        if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) {
-               free_cpumask_var(policy->cpus);
-               kfree(policy);
                ret = -ENOMEM;
-               goto nomem_out;
+               goto err_free_cpumask;
        }
 
        policy->cpu = cpu;
@@ -820,7 +818,8 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
 
        /* Initially set CPU itself as the policy_cpu */
        per_cpu(policy_cpu, cpu) = cpu;
-       lock_policy_rwsem_write(cpu);
+       ret = (lock_policy_rwsem_write(cpu) < 0);
+       WARN_ON(ret);
 
        init_completion(&policy->kobj_unregister);
        INIT_WORK(&policy->update, handle_update);
@@ -833,7 +832,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
        ret = cpufreq_driver->init(policy);
        if (ret) {
                dprintk("initialization failed\n");
-               goto err_out;
+               goto err_unlock_policy;
        }
        policy->user_policy.min = policy->min;
        policy->user_policy.max = policy->max;
@@ -852,21 +851,31 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
 #endif
 
        for_each_cpu(j, policy->cpus) {
+               struct cpufreq_policy *managed_policy;
+
                if (cpu == j)
                        continue;
 
                /* Check for existing affected CPUs.
                 * They may not be aware of it due to CPU Hotplug.
+                * cpufreq_cpu_put is called when the device is removed
+                * in __cpufreq_remove_dev()
                 */
-               managed_policy = cpufreq_cpu_get(j);            /* FIXME: Where is this released?  What about error paths? */
+               managed_policy = cpufreq_cpu_get(j);
                if (unlikely(managed_policy)) {
 
                        /* Set proper policy_cpu */
                        unlock_policy_rwsem_write(cpu);
                        per_cpu(policy_cpu, cpu) = managed_policy->cpu;
 
-                       if (lock_policy_rwsem_write(cpu) < 0)
-                               goto err_out_driver_exit;
+                       if (lock_policy_rwsem_write(cpu) < 0) {
+                               /* Should not go through policy unlock path */
+                               if (cpufreq_driver->exit)
+                                       cpufreq_driver->exit(policy);
+                               ret = -EBUSY;
+                               cpufreq_cpu_put(managed_policy);
+                               goto err_free_cpumask;
+                       }
 
                        spin_lock_irqsave(&cpufreq_driver_lock, flags);
                        cpumask_copy(managed_policy->cpus, policy->cpus);
@@ -878,11 +887,13 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
                                                &managed_policy->kobj,
                                                "cpufreq");
                        if (ret)
-                               goto err_out_driver_exit;
-
-                       cpufreq_debug_enable_ratelimit();
-                       ret = 0;
-                       goto err_out_driver_exit; /* call driver->exit() */
+                               cpufreq_cpu_put(managed_policy);
+                       /*
+                        * Success. We only needed to be added to the mask.
+                        * Call driver->exit() because only the cpu parent of
+                        * the kobj needed to call init().
+                        */
+                       goto out_driver_exit; /* call driver->exit() */
                }
        }
 #endif
@@ -892,29 +903,31 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
        ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj,
                                   "cpufreq");
        if (ret)
-               goto err_out_driver_exit;
+               goto out_driver_exit;
 
        /* set up files for this cpu device */
        drv_attr = cpufreq_driver->attr;
        while ((drv_attr) && (*drv_attr)) {
                ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
                if (ret)
-                       goto err_out_driver_exit;
+                       goto err_out_kobj_put;
                drv_attr++;
        }
        if (cpufreq_driver->get) {
                ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
                if (ret)
-                       goto err_out_driver_exit;
+                       goto err_out_kobj_put;
        }
        if (cpufreq_driver->target) {
                ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
                if (ret)
-                       goto err_out_driver_exit;
+                       goto err_out_kobj_put;
        }
 
        spin_lock_irqsave(&cpufreq_driver_lock, flags);
        for_each_cpu(j, policy->cpus) {
+               if (!cpu_online(j))
+                       continue;
                per_cpu(cpufreq_cpu_data, j) = policy;
                per_cpu(policy_cpu, j) = policy->cpu;
        }
@@ -922,18 +935,22 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
 
        /* symlink affected CPUs */
        for_each_cpu(j, policy->cpus) {
+               struct cpufreq_policy *managed_policy;
+
                if (j == cpu)
                        continue;
                if (!cpu_online(j))
                        continue;
 
                dprintk("CPU %u already managed, adding link\n", j);
-               cpufreq_cpu_get(cpu);
+               managed_policy = cpufreq_cpu_get(cpu);
                cpu_sys_dev = get_cpu_sysdev(j);
                ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
                                        "cpufreq");
-               if (ret)
+               if (ret) {
+                       cpufreq_cpu_put(managed_policy);
                        goto err_out_unregister;
+               }
        }
 
        policy->governor = NULL; /* to assure that the starting sequence is
@@ -965,17 +982,20 @@ err_out_unregister:
                per_cpu(cpufreq_cpu_data, j) = NULL;
        spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
+err_out_kobj_put:
        kobject_put(&policy->kobj);
        wait_for_completion(&policy->kobj_unregister);
 
-err_out_driver_exit:
+out_driver_exit:
        if (cpufreq_driver->exit)
                cpufreq_driver->exit(policy);
 
-err_out:
+err_unlock_policy:
        unlock_policy_rwsem_write(cpu);
+err_free_cpumask:
+       free_cpumask_var(policy->cpus);
+err_free_policy:
        kfree(policy);
-
 nomem_out:
        module_put(cpufreq_driver->owner);
 module_out:
@@ -1070,8 +1090,6 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
        spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 #endif
 
-       unlock_policy_rwsem_write(cpu);
-
        if (cpufreq_driver->target)
                __cpufreq_governor(data, CPUFREQ_GOV_STOP);
 
@@ -1088,6 +1106,8 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
        if (cpufreq_driver->exit)
                cpufreq_driver->exit(data);
 
+       unlock_policy_rwsem_write(cpu);
+
        free_cpumask_var(data->related_cpus);
        free_cpumask_var(data->cpus);
        kfree(data);
@@ -1228,9 +1248,9 @@ EXPORT_SYMBOL(cpufreq_get);
 
 static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg)
 {
-       int cpu = sysdev->id;
        int ret = 0;
-       unsigned int cur_freq = 0;
+
+       int cpu = sysdev->id;
        struct cpufreq_policy *cpu_policy;
 
        dprintk("suspending cpu %u\n", cpu);
@@ -1253,42 +1273,9 @@ static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg)
 
        if (cpufreq_driver->suspend) {
                ret = cpufreq_driver->suspend(cpu_policy, pmsg);
-               if (ret) {
+               if (ret)
                        printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
                                        "step on CPU %u\n", cpu_policy->cpu);
-                       goto out;
-               }
-       }
-
-       if (cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)
-               goto out;
-
-       if (cpufreq_driver->get)
-               cur_freq = cpufreq_driver->get(cpu_policy->cpu);
-
-       if (!cur_freq || !cpu_policy->cur) {
-               printk(KERN_ERR "cpufreq: suspend failed to assert current "
-                      "frequency is what timing core thinks it is.\n");
-               goto out;
-       }
-
-       if (unlikely(cur_freq != cpu_policy->cur)) {
-               struct cpufreq_freqs freqs;
-
-               if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN))
-                       dprintk("Warning: CPU frequency is %u, "
-                              "cpufreq assumed %u kHz.\n",
-                              cur_freq, cpu_policy->cur);
-
-               freqs.cpu = cpu;
-               freqs.old = cpu_policy->cur;
-               freqs.new = cur_freq;
-
-               srcu_notifier_call_chain(&cpufreq_transition_notifier_list,
-                                   CPUFREQ_SUSPENDCHANGE, &freqs);
-               adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs);
-
-               cpu_policy->cur = cur_freq;
        }
 
 out:
@@ -1300,14 +1287,17 @@ out:
  *     cpufreq_resume -  restore proper CPU frequency handling after resume
  *
  *     1.) resume CPUfreq hardware support (cpufreq_driver->resume())
- *     2.) if ->target and !CPUFREQ_CONST_LOOPS: verify we're in sync
- *     3.) schedule call cpufreq_update_policy() ASAP as interrupts are
- *         restored.
+ *     2.) schedule call cpufreq_update_policy() ASAP as interrupts are
+ *         restored. It will verify that the current freq is in sync with
+ *         what we believe it to be. This is a bit later than when it
+ *         should be, but nonethteless it's better than calling
+ *         cpufreq_driver->get() here which might re-enable interrupts...
  */
 static int cpufreq_resume(struct sys_device *sysdev)
 {
-       int cpu = sysdev->id;
        int ret = 0;
+
+       int cpu = sysdev->id;
        struct cpufreq_policy *cpu_policy;
 
        dprintk("resuming cpu %u\n", cpu);
@@ -1337,42 +1327,8 @@ static int cpufreq_resume(struct sys_device *sysdev)
                }
        }
 
-       if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
-               unsigned int cur_freq = 0;
-
-               if (cpufreq_driver->get)
-                       cur_freq = cpufreq_driver->get(cpu_policy->cpu);
-
-               if (!cur_freq || !cpu_policy->cur) {
-                       printk(KERN_ERR "cpufreq: resume failed to assert "
-                                       "current frequency is what timing core "
-                                       "thinks it is.\n");
-                       goto out;
-               }
-
-               if (unlikely(cur_freq != cpu_policy->cur)) {
-                       struct cpufreq_freqs freqs;
-
-                       if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN))
-                               dprintk("Warning: CPU frequency "
-                                      "is %u, cpufreq assumed %u kHz.\n",
-                                      cur_freq, cpu_policy->cur);
-
-                       freqs.cpu = cpu;
-                       freqs.old = cpu_policy->cur;
-                       freqs.new = cur_freq;
-
-                       srcu_notifier_call_chain(
-                                       &cpufreq_transition_notifier_list,
-                                       CPUFREQ_RESUMECHANGE, &freqs);
-                       adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs);
-
-                       cpu_policy->cur = cur_freq;
-               }
-       }
-
-out:
        schedule_work(&cpu_policy->update);
+
 fail:
        cpufreq_cpu_put(cpu_policy);
        return ret;
index 7fc58af748b49b8ba4bf18e71dd1302fa6590c7d..bdea7e2f94baa9c6f3743a1bdefc84ba44376822 100644 (file)
@@ -64,21 +64,20 @@ struct cpu_dbs_info_s {
        unsigned int requested_freq;
        int cpu;
        unsigned int enable:1;
+       /*
+        * percpu mutex that serializes governor limit change with
+        * do_dbs_timer invocation. We do not want do_dbs_timer to run
+        * when user is changing the governor or limits.
+        */
+       struct mutex timer_mutex;
 };
 static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
 
 static unsigned int dbs_enable;        /* number of CPUs using this policy */
 
 /*
- * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug
- * lock and dbs_mutex. cpu_hotplug lock should always be held before
- * dbs_mutex. If any function that can potentially take cpu_hotplug lock
- * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then
- * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock
- * is recursive for the same process. -Venki
- * DEADLOCK ALERT! (2) : do_dbs_timer() must not take the dbs_mutex, because it
- * would deadlock with cancel_delayed_work_sync(), which is needed for proper
- * raceless workqueue teardown.
+ * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on
+ * different CPUs. It protects dbs_enable in governor start/stop.
  */
 static DEFINE_MUTEX(dbs_mutex);
 
@@ -488,18 +487,12 @@ static void do_dbs_timer(struct work_struct *work)
 
        delay -= jiffies % delay;
 
-       if (lock_policy_rwsem_write(cpu) < 0)
-               return;
-
-       if (!dbs_info->enable) {
-               unlock_policy_rwsem_write(cpu);
-               return;
-       }
+       mutex_lock(&dbs_info->timer_mutex);
 
        dbs_check_cpu(dbs_info);
 
        queue_delayed_work_on(cpu, kconservative_wq, &dbs_info->work, delay);
-       unlock_policy_rwsem_write(cpu);
+       mutex_unlock(&dbs_info->timer_mutex);
 }
 
 static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
@@ -535,9 +528,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                if ((!cpu_online(cpu)) || (!policy->cur))
                        return -EINVAL;
 
-               if (this_dbs_info->enable) /* Already enabled */
-                       break;
-
                mutex_lock(&dbs_mutex);
 
                rc = sysfs_create_group(&policy->kobj, &dbs_attr_group);
@@ -561,6 +551,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                this_dbs_info->down_skip = 0;
                this_dbs_info->requested_freq = policy->cur;
 
+               mutex_init(&this_dbs_info->timer_mutex);
                dbs_enable++;
                /*
                 * Start the timerschedule work, when this governor
@@ -590,17 +581,19 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                                        &dbs_cpufreq_notifier_block,
                                        CPUFREQ_TRANSITION_NOTIFIER);
                }
-               dbs_timer_init(this_dbs_info);
-
                mutex_unlock(&dbs_mutex);
 
+               dbs_timer_init(this_dbs_info);
+
                break;
 
        case CPUFREQ_GOV_STOP:
-               mutex_lock(&dbs_mutex);
                dbs_timer_exit(this_dbs_info);
+
+               mutex_lock(&dbs_mutex);
                sysfs_remove_group(&policy->kobj, &dbs_attr_group);
                dbs_enable--;
+               mutex_destroy(&this_dbs_info->timer_mutex);
 
                /*
                 * Stop the timerschedule work, when this governor
@@ -616,7 +609,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                break;
 
        case CPUFREQ_GOV_LIMITS:
-               mutex_lock(&dbs_mutex);
+               mutex_lock(&this_dbs_info->timer_mutex);
                if (policy->max < this_dbs_info->cur_policy->cur)
                        __cpufreq_driver_target(
                                        this_dbs_info->cur_policy,
@@ -625,7 +618,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                        __cpufreq_driver_target(
                                        this_dbs_info->cur_policy,
                                        policy->min, CPUFREQ_RELATION_L);
-               mutex_unlock(&dbs_mutex);
+               mutex_unlock(&this_dbs_info->timer_mutex);
 
                break;
        }
index 1911d1729353fe3bdc621ae76896fbabd0a31c5e..d6ba14276bb1b0fda545cfab00367403d9b17408 100644 (file)
@@ -70,23 +70,21 @@ struct cpu_dbs_info_s {
        unsigned int freq_lo_jiffies;
        unsigned int freq_hi_jiffies;
        int cpu;
-       unsigned int enable:1,
-               sample_type:1;
+       unsigned int sample_type:1;
+       /*
+        * percpu mutex that serializes governor limit change with
+        * do_dbs_timer invocation. We do not want do_dbs_timer to run
+        * when user is changing the governor or limits.
+        */
+       struct mutex timer_mutex;
 };
 static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
 
 static unsigned int dbs_enable;        /* number of CPUs using this policy */
 
 /*
- * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug
- * lock and dbs_mutex. cpu_hotplug lock should always be held before
- * dbs_mutex. If any function that can potentially take cpu_hotplug lock
- * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then
- * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock
- * is recursive for the same process. -Venki
- * DEADLOCK ALERT! (2) : do_dbs_timer() must not take the dbs_mutex, because it
- * would deadlock with cancel_delayed_work_sync(), which is needed for proper
- * raceless workqueue teardown.
+ * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on
+ * different CPUs. It protects dbs_enable in governor start/stop.
  */
 static DEFINE_MUTEX(dbs_mutex);
 
@@ -192,13 +190,18 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
        return freq_hi;
 }
 
+static void ondemand_powersave_bias_init_cpu(int cpu)
+{
+       struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu);
+       dbs_info->freq_table = cpufreq_frequency_get_table(cpu);
+       dbs_info->freq_lo = 0;
+}
+
 static void ondemand_powersave_bias_init(void)
 {
        int i;
        for_each_online_cpu(i) {
-               struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, i);
-               dbs_info->freq_table = cpufreq_frequency_get_table(i);
-               dbs_info->freq_lo = 0;
+               ondemand_powersave_bias_init_cpu(i);
        }
 }
 
@@ -240,12 +243,10 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
        unsigned int input;
        int ret;
        ret = sscanf(buf, "%u", &input);
+       if (ret != 1)
+               return -EINVAL;
 
        mutex_lock(&dbs_mutex);
-       if (ret != 1) {
-               mutex_unlock(&dbs_mutex);
-               return -EINVAL;
-       }
        dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate);
        mutex_unlock(&dbs_mutex);
 
@@ -259,13 +260,12 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
        int ret;
        ret = sscanf(buf, "%u", &input);
 
-       mutex_lock(&dbs_mutex);
        if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
                        input < MIN_FREQUENCY_UP_THRESHOLD) {
-               mutex_unlock(&dbs_mutex);
                return -EINVAL;
        }
 
+       mutex_lock(&dbs_mutex);
        dbs_tuners_ins.up_threshold = input;
        mutex_unlock(&dbs_mutex);
 
@@ -363,9 +363,6 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
        struct cpufreq_policy *policy;
        unsigned int j;
 
-       if (!this_dbs_info->enable)
-               return;
-
        this_dbs_info->freq_lo = 0;
        policy = this_dbs_info->cur_policy;
 
@@ -493,14 +490,7 @@ static void do_dbs_timer(struct work_struct *work)
        int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
 
        delay -= jiffies % delay;
-
-       if (lock_policy_rwsem_write(cpu) < 0)
-               return;
-
-       if (!dbs_info->enable) {
-               unlock_policy_rwsem_write(cpu);
-               return;
-       }
+       mutex_lock(&dbs_info->timer_mutex);
 
        /* Common NORMAL_SAMPLE setup */
        dbs_info->sample_type = DBS_NORMAL_SAMPLE;
@@ -517,7 +507,7 @@ static void do_dbs_timer(struct work_struct *work)
                        dbs_info->freq_lo, CPUFREQ_RELATION_H);
        }
        queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
-       unlock_policy_rwsem_write(cpu);
+       mutex_unlock(&dbs_info->timer_mutex);
 }
 
 static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
@@ -526,8 +516,6 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
        int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
        delay -= jiffies % delay;
 
-       dbs_info->enable = 1;
-       ondemand_powersave_bias_init();
        dbs_info->sample_type = DBS_NORMAL_SAMPLE;
        INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer);
        queue_delayed_work_on(dbs_info->cpu, kondemand_wq, &dbs_info->work,
@@ -536,7 +524,6 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
 
 static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
 {
-       dbs_info->enable = 0;
        cancel_delayed_work_sync(&dbs_info->work);
 }
 
@@ -555,19 +542,15 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                if ((!cpu_online(cpu)) || (!policy->cur))
                        return -EINVAL;
 
-               if (this_dbs_info->enable) /* Already enabled */
-                       break;
-
                mutex_lock(&dbs_mutex);
-               dbs_enable++;
 
                rc = sysfs_create_group(&policy->kobj, &dbs_attr_group);
                if (rc) {
-                       dbs_enable--;
                        mutex_unlock(&dbs_mutex);
                        return rc;
                }
 
+               dbs_enable++;
                for_each_cpu(j, policy->cpus) {
                        struct cpu_dbs_info_s *j_dbs_info;
                        j_dbs_info = &per_cpu(cpu_dbs_info, j);
@@ -581,6 +564,8 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                        }
                }
                this_dbs_info->cpu = cpu;
+               ondemand_powersave_bias_init_cpu(cpu);
+               mutex_init(&this_dbs_info->timer_mutex);
                /*
                 * Start the timerschedule work, when this governor
                 * is used for first time
@@ -598,29 +583,31 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                                max(min_sampling_rate,
                                    latency * LATENCY_MULTIPLIER);
                }
-               dbs_timer_init(this_dbs_info);
-
                mutex_unlock(&dbs_mutex);
+
+               dbs_timer_init(this_dbs_info);
                break;
 
        case CPUFREQ_GOV_STOP:
-               mutex_lock(&dbs_mutex);
                dbs_timer_exit(this_dbs_info);
+
+               mutex_lock(&dbs_mutex);
                sysfs_remove_group(&policy->kobj, &dbs_attr_group);
+               mutex_destroy(&this_dbs_info->timer_mutex);
                dbs_enable--;
                mutex_unlock(&dbs_mutex);
 
                break;
 
        case CPUFREQ_GOV_LIMITS:
-               mutex_lock(&dbs_mutex);
+               mutex_lock(&this_dbs_info->timer_mutex);
                if (policy->max < this_dbs_info->cur_policy->cur)
                        __cpufreq_driver_target(this_dbs_info->cur_policy,
                                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);
-               mutex_unlock(&dbs_mutex);
+               mutex_unlock(&this_dbs_info->timer_mutex);
                break;
        }
        return 0;
index 070357aaedbcacfd0a2f2bb42e8e7587eeb1e3f1..81e1020fb5148a75677aec191e974c554031d03f 100644 (file)
@@ -4,7 +4,7 @@
 
 menuconfig DMADEVICES
        bool "DMA Engine support"
-       depends on !HIGHMEM64G && HAS_DMA
+       depends on HAS_DMA
        help
          DMA engines can do asynchronous data transfers without
          involving the host CPU.  Currently, this framework can be
@@ -46,6 +46,14 @@ config DW_DMAC
          Support the Synopsys DesignWare AHB DMA controller.  This
          can be integrated in chips such as the Atmel AT32ap7000.
 
+config AT_HDMAC
+       tristate "Atmel AHB DMA support"
+       depends on ARCH_AT91SAM9RL
+       select DMA_ENGINE
+       help
+         Support the Atmel AHB DMA controller.  This can be integrated in
+         chips such as the Atmel AT91SAM9RL.
+
 config FSL_DMA
        tristate "Freescale Elo and Elo Plus DMA support"
        depends on FSL_SOC
@@ -108,7 +116,7 @@ config NET_DMA
 
 config ASYNC_TX_DMA
        bool "Async_tx: Offload support for the async_tx api"
-       depends on DMA_ENGINE
+       depends on DMA_ENGINE && !HIGHMEM64G
        help
          This allows the async_tx api to take advantage of offload engines for
          memcpy, memset, xor, and raid6 p+q operations.  If your platform has
index a0b6564800c4871f967bbe7d5cf401ea59fd6314..40e1e008357192b1aced8b1abab5a86460c78352 100644 (file)
@@ -7,5 +7,6 @@ obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
 obj-$(CONFIG_FSL_DMA) += fsldma.o
 obj-$(CONFIG_MV_XOR) += mv_xor.o
 obj-$(CONFIG_DW_DMAC) += dw_dmac.o
+obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
 obj-$(CONFIG_MX3_IPU) += ipu/
 obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
new file mode 100644 (file)
index 0000000..9a1e5fb
--- /dev/null
@@ -0,0 +1,1213 @@
+/*
+ * Driver for the Atmel AHB DMA Controller (aka HDMA or DMAC on AT91 systems)
+ *
+ * Copyright (C) 2008 Atmel 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 supports the Atmel AHB DMA Controller,
+ *
+ * The driver has currently been tested with the Atmel AT91SAM9RL
+ * and AT91SAM9G45 series.
+ */
+
+#include <linux/clk.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "at_hdmac_regs.h"
+
+/*
+ * Glossary
+ * --------
+ *
+ * at_hdmac            : Name of the ATmel AHB DMA Controller
+ * at_dma_ / atdma     : ATmel DMA controller entity related
+ * atc_        / atchan        : ATmel DMA Channel entity related
+ */
+
+#define        ATC_DEFAULT_CFG         (ATC_FIFOCFG_HALFFIFO)
+#define        ATC_DEFAULT_CTRLA       (0)
+#define        ATC_DEFAULT_CTRLB       (ATC_SIF(0)     \
+                               |ATC_DIF(1))
+
+/*
+ * Initial number of descriptors to allocate for each channel. This could
+ * be increased during dma usage.
+ */
+static unsigned int init_nr_desc_per_channel = 64;
+module_param(init_nr_desc_per_channel, uint, 0644);
+MODULE_PARM_DESC(init_nr_desc_per_channel,
+                "initial descriptors per channel (default: 64)");
+
+
+/* prototypes */
+static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx);
+
+
+/*----------------------------------------------------------------------*/
+
+static struct at_desc *atc_first_active(struct at_dma_chan *atchan)
+{
+       return list_first_entry(&atchan->active_list,
+                               struct at_desc, desc_node);
+}
+
+static struct at_desc *atc_first_queued(struct at_dma_chan *atchan)
+{
+       return list_first_entry(&atchan->queue,
+                               struct at_desc, desc_node);
+}
+
+/**
+ * atc_alloc_descriptor - allocate and return an initilized descriptor
+ * @chan: the channel to allocate descriptors for
+ * @gfp_flags: GFP allocation flags
+ *
+ * Note: The ack-bit is positioned in the descriptor flag at creation time
+ *       to make initial allocation more convenient. This bit will be cleared
+ *       and control will be given to client at usage time (during
+ *       preparation functions).
+ */
+static struct at_desc *atc_alloc_descriptor(struct dma_chan *chan,
+                                           gfp_t gfp_flags)
+{
+       struct at_desc  *desc = NULL;
+       struct at_dma   *atdma = to_at_dma(chan->device);
+       dma_addr_t phys;
+
+       desc = dma_pool_alloc(atdma->dma_desc_pool, gfp_flags, &phys);
+       if (desc) {
+               memset(desc, 0, sizeof(struct at_desc));
+               dma_async_tx_descriptor_init(&desc->txd, chan);
+               /* txd.flags will be overwritten in prep functions */
+               desc->txd.flags = DMA_CTRL_ACK;
+               desc->txd.tx_submit = atc_tx_submit;
+               desc->txd.phys = phys;
+       }
+
+       return desc;
+}
+
+/**
+ * atc_desc_get - get a unsused descriptor from free_list
+ * @atchan: channel we want a new descriptor for
+ */
+static struct at_desc *atc_desc_get(struct at_dma_chan *atchan)
+{
+       struct at_desc *desc, *_desc;
+       struct at_desc *ret = NULL;
+       unsigned int i = 0;
+       LIST_HEAD(tmp_list);
+
+       spin_lock_bh(&atchan->lock);
+       list_for_each_entry_safe(desc, _desc, &atchan->free_list, desc_node) {
+               i++;
+               if (async_tx_test_ack(&desc->txd)) {
+                       list_del(&desc->desc_node);
+                       ret = desc;
+                       break;
+               }
+               dev_dbg(chan2dev(&atchan->chan_common),
+                               "desc %p not ACKed\n", desc);
+       }
+       spin_unlock_bh(&atchan->lock);
+       dev_vdbg(chan2dev(&atchan->chan_common),
+               "scanned %u descriptors on freelist\n", i);
+
+       /* no more descriptor available in initial pool: create one more */
+       if (!ret) {
+               ret = atc_alloc_descriptor(&atchan->chan_common, GFP_ATOMIC);
+               if (ret) {
+                       spin_lock_bh(&atchan->lock);
+                       atchan->descs_allocated++;
+                       spin_unlock_bh(&atchan->lock);
+               } else {
+                       dev_err(chan2dev(&atchan->chan_common),
+                                       "not enough descriptors available\n");
+               }
+       }
+
+       return ret;
+}
+
+/**
+ * atc_desc_put - move a descriptor, including any children, to the free list
+ * @atchan: channel we work on
+ * @desc: descriptor, at the head of a chain, to move to free list
+ */
+static void atc_desc_put(struct at_dma_chan *atchan, struct at_desc *desc)
+{
+       if (desc) {
+               struct at_desc *child;
+
+               spin_lock_bh(&atchan->lock);
+               list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+                       dev_vdbg(chan2dev(&atchan->chan_common),
+                                       "moving child desc %p to freelist\n",
+                                       child);
+               list_splice_init(&desc->txd.tx_list, &atchan->free_list);
+               dev_vdbg(chan2dev(&atchan->chan_common),
+                        "moving desc %p to freelist\n", desc);
+               list_add(&desc->desc_node, &atchan->free_list);
+               spin_unlock_bh(&atchan->lock);
+       }
+}
+
+/**
+ * atc_assign_cookie - compute and assign new cookie
+ * @atchan: channel we work on
+ * @desc: descriptor to asign cookie for
+ *
+ * Called with atchan->lock held and bh disabled
+ */
+static dma_cookie_t
+atc_assign_cookie(struct at_dma_chan *atchan, struct at_desc *desc)
+{
+       dma_cookie_t cookie = atchan->chan_common.cookie;
+
+       if (++cookie < 0)
+               cookie = 1;
+
+       atchan->chan_common.cookie = cookie;
+       desc->txd.cookie = cookie;
+
+       return cookie;
+}
+
+/**
+ * atc_dostart - starts the DMA engine for real
+ * @atchan: the channel we want to start
+ * @first: first descriptor in the list we want to begin with
+ *
+ * Called with atchan->lock held and bh disabled
+ */
+static void atc_dostart(struct at_dma_chan *atchan, struct at_desc *first)
+{
+       struct at_dma   *atdma = to_at_dma(atchan->chan_common.device);
+
+       /* ASSERT:  channel is idle */
+       if (atc_chan_is_enabled(atchan)) {
+               dev_err(chan2dev(&atchan->chan_common),
+                       "BUG: Attempted to start non-idle channel\n");
+               dev_err(chan2dev(&atchan->chan_common),
+                       "  channel: s0x%x d0x%x ctrl0x%x:0x%x l0x%x\n",
+                       channel_readl(atchan, SADDR),
+                       channel_readl(atchan, DADDR),
+                       channel_readl(atchan, CTRLA),
+                       channel_readl(atchan, CTRLB),
+                       channel_readl(atchan, DSCR));
+
+               /* The tasklet will hopefully advance the queue... */
+               return;
+       }
+
+       vdbg_dump_regs(atchan);
+
+       /* clear any pending interrupt */
+       while (dma_readl(atdma, EBCISR))
+               cpu_relax();
+
+       channel_writel(atchan, SADDR, 0);
+       channel_writel(atchan, DADDR, 0);
+       channel_writel(atchan, CTRLA, 0);
+       channel_writel(atchan, CTRLB, 0);
+       channel_writel(atchan, DSCR, first->txd.phys);
+       dma_writel(atdma, CHER, atchan->mask);
+
+       vdbg_dump_regs(atchan);
+}
+
+/**
+ * atc_chain_complete - finish work for one transaction chain
+ * @atchan: channel we work on
+ * @desc: descriptor at the head of the chain we want do complete
+ *
+ * Called with atchan->lock held and bh disabled */
+static void
+atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
+{
+       dma_async_tx_callback           callback;
+       void                            *param;
+       struct dma_async_tx_descriptor  *txd = &desc->txd;
+
+       dev_vdbg(chan2dev(&atchan->chan_common),
+               "descriptor %u complete\n", txd->cookie);
+
+       atchan->completed_cookie = txd->cookie;
+       callback = txd->callback;
+       param = txd->callback_param;
+
+       /* move children to free_list */
+       list_splice_init(&txd->tx_list, &atchan->free_list);
+       /* move myself to free_list */
+       list_move(&desc->desc_node, &atchan->free_list);
+
+       /* unmap dma addresses */
+       if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+               if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE)
+                       dma_unmap_single(chan2parent(&atchan->chan_common),
+                                       desc->lli.daddr,
+                                       desc->len, DMA_FROM_DEVICE);
+               else
+                       dma_unmap_page(chan2parent(&atchan->chan_common),
+                                       desc->lli.daddr,
+                                       desc->len, DMA_FROM_DEVICE);
+       }
+       if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+               if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE)
+                       dma_unmap_single(chan2parent(&atchan->chan_common),
+                                       desc->lli.saddr,
+                                       desc->len, DMA_TO_DEVICE);
+               else
+                       dma_unmap_page(chan2parent(&atchan->chan_common),
+                                       desc->lli.saddr,
+                                       desc->len, DMA_TO_DEVICE);
+       }
+
+       /*
+        * The API requires that no submissions are done from a
+        * callback, so we don't need to drop the lock here
+        */
+       if (callback)
+               callback(param);
+
+       dma_run_dependencies(txd);
+}
+
+/**
+ * atc_complete_all - finish work for all transactions
+ * @atchan: channel to complete transactions for
+ *
+ * Eventually submit queued descriptors if any
+ *
+ * Assume channel is idle while calling this function
+ * Called with atchan->lock held and bh disabled
+ */
+static void atc_complete_all(struct at_dma_chan *atchan)
+{
+       struct at_desc *desc, *_desc;
+       LIST_HEAD(list);
+
+       dev_vdbg(chan2dev(&atchan->chan_common), "complete all\n");
+
+       BUG_ON(atc_chan_is_enabled(atchan));
+
+       /*
+        * Submit queued descriptors ASAP, i.e. before we go through
+        * the completed ones.
+        */
+       if (!list_empty(&atchan->queue))
+               atc_dostart(atchan, atc_first_queued(atchan));
+       /* empty active_list now it is completed */
+       list_splice_init(&atchan->active_list, &list);
+       /* empty queue list by moving descriptors (if any) to active_list */
+       list_splice_init(&atchan->queue, &atchan->active_list);
+
+       list_for_each_entry_safe(desc, _desc, &list, desc_node)
+               atc_chain_complete(atchan, desc);
+}
+
+/**
+ * atc_cleanup_descriptors - cleanup up finished descriptors in active_list
+ * @atchan: channel to be cleaned up
+ *
+ * Called with atchan->lock held and bh disabled
+ */
+static void atc_cleanup_descriptors(struct at_dma_chan *atchan)
+{
+       struct at_desc  *desc, *_desc;
+       struct at_desc  *child;
+
+       dev_vdbg(chan2dev(&atchan->chan_common), "cleanup descriptors\n");
+
+       list_for_each_entry_safe(desc, _desc, &atchan->active_list, desc_node) {
+               if (!(desc->lli.ctrla & ATC_DONE))
+                       /* This one is currently in progress */
+                       return;
+
+               list_for_each_entry(child, &desc->txd.tx_list, desc_node)
+                       if (!(child->lli.ctrla & ATC_DONE))
+                               /* Currently in progress */
+                               return;
+
+               /*
+                * No descriptors so far seem to be in progress, i.e.
+                * this chain must be done.
+                */
+               atc_chain_complete(atchan, desc);
+       }
+}
+
+/**
+ * atc_advance_work - at the end of a transaction, move forward
+ * @atchan: channel where the transaction ended
+ *
+ * Called with atchan->lock held and bh disabled
+ */
+static void atc_advance_work(struct at_dma_chan *atchan)
+{
+       dev_vdbg(chan2dev(&atchan->chan_common), "advance_work\n");
+
+       if (list_empty(&atchan->active_list) ||
+           list_is_singular(&atchan->active_list)) {
+               atc_complete_all(atchan);
+       } else {
+               atc_chain_complete(atchan, atc_first_active(atchan));
+               /* advance work */
+               atc_dostart(atchan, atc_first_active(atchan));
+       }
+}
+
+
+/**
+ * atc_handle_error - handle errors reported by DMA controller
+ * @atchan: channel where error occurs
+ *
+ * Called with atchan->lock held and bh disabled
+ */
+static void atc_handle_error(struct at_dma_chan *atchan)
+{
+       struct at_desc *bad_desc;
+       struct at_desc *child;
+
+       /*
+        * The descriptor currently at the head of the active list is
+        * broked. Since we don't have any way to report errors, we'll
+        * just have to scream loudly and try to carry on.
+        */
+       bad_desc = atc_first_active(atchan);
+       list_del_init(&bad_desc->desc_node);
+
+       /* As we are stopped, take advantage to push queued descriptors
+        * in active_list */
+       list_splice_init(&atchan->queue, atchan->active_list.prev);
+
+       /* Try to restart the controller */
+       if (!list_empty(&atchan->active_list))
+               atc_dostart(atchan, atc_first_active(atchan));
+
+       /*
+        * KERN_CRITICAL may seem harsh, but since this only happens
+        * when someone submits a bad physical address in a
+        * descriptor, we should consider ourselves lucky that the
+        * controller flagged an error instead of scribbling over
+        * random memory locations.
+        */
+       dev_crit(chan2dev(&atchan->chan_common),
+                       "Bad descriptor submitted for DMA!\n");
+       dev_crit(chan2dev(&atchan->chan_common),
+                       "  cookie: %d\n", bad_desc->txd.cookie);
+       atc_dump_lli(atchan, &bad_desc->lli);
+       list_for_each_entry(child, &bad_desc->txd.tx_list, desc_node)
+               atc_dump_lli(atchan, &child->lli);
+
+       /* Pretend the descriptor completed successfully */
+       atc_chain_complete(atchan, bad_desc);
+}
+
+
+/*--  IRQ & Tasklet  ---------------------------------------------------*/
+
+static void atc_tasklet(unsigned long data)
+{
+       struct at_dma_chan *atchan = (struct at_dma_chan *)data;
+
+       /* Channel cannot be enabled here */
+       if (atc_chan_is_enabled(atchan)) {
+               dev_err(chan2dev(&atchan->chan_common),
+                       "BUG: channel enabled in tasklet\n");
+               return;
+       }
+
+       spin_lock(&atchan->lock);
+       if (test_and_clear_bit(0, &atchan->error_status))
+               atc_handle_error(atchan);
+       else
+               atc_advance_work(atchan);
+
+       spin_unlock(&atchan->lock);
+}
+
+static irqreturn_t at_dma_interrupt(int irq, void *dev_id)
+{
+       struct at_dma           *atdma = (struct at_dma *)dev_id;
+       struct at_dma_chan      *atchan;
+       int                     i;
+       u32                     status, pending, imr;
+       int                     ret = IRQ_NONE;
+
+       do {
+               imr = dma_readl(atdma, EBCIMR);
+               status = dma_readl(atdma, EBCISR);
+               pending = status & imr;
+
+               if (!pending)
+                       break;
+
+               dev_vdbg(atdma->dma_common.dev,
+                       "interrupt: status = 0x%08x, 0x%08x, 0x%08x\n",
+                        status, imr, pending);
+
+               for (i = 0; i < atdma->dma_common.chancnt; i++) {
+                       atchan = &atdma->chan[i];
+                       if (pending & (AT_DMA_CBTC(i) | AT_DMA_ERR(i))) {
+                               if (pending & AT_DMA_ERR(i)) {
+                                       /* Disable channel on AHB error */
+                                       dma_writel(atdma, CHDR, atchan->mask);
+                                       /* Give information to tasklet */
+                                       set_bit(0, &atchan->error_status);
+                               }
+                               tasklet_schedule(&atchan->tasklet);
+                               ret = IRQ_HANDLED;
+                       }
+               }
+
+       } while (pending);
+
+       return ret;
+}
+
+
+/*--  DMA Engine API  --------------------------------------------------*/
+
+/**
+ * atc_tx_submit - set the prepared descriptor(s) to be executed by the engine
+ * @desc: descriptor at the head of the transaction chain
+ *
+ * Queue chain if DMA engine is working already
+ *
+ * Cookie increment and adding to active_list or queue must be atomic
+ */
+static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+       struct at_desc          *desc = txd_to_at_desc(tx);
+       struct at_dma_chan      *atchan = to_at_dma_chan(tx->chan);
+       dma_cookie_t            cookie;
+
+       spin_lock_bh(&atchan->lock);
+       cookie = atc_assign_cookie(atchan, desc);
+
+       if (list_empty(&atchan->active_list)) {
+               dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n",
+                               desc->txd.cookie);
+               atc_dostart(atchan, desc);
+               list_add_tail(&desc->desc_node, &atchan->active_list);
+       } else {
+               dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n",
+                               desc->txd.cookie);
+               list_add_tail(&desc->desc_node, &atchan->queue);
+       }
+
+       spin_unlock_bh(&atchan->lock);
+
+       return cookie;
+}
+
+/**
+ * atc_prep_dma_memcpy - prepare a memcpy operation
+ * @chan: the channel to prepare operation on
+ * @dest: operation virtual destination address
+ * @src: operation virtual source address
+ * @len: operation length
+ * @flags: tx descriptor status flags
+ */
+static struct dma_async_tx_descriptor *
+atc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+               size_t len, unsigned long flags)
+{
+       struct at_dma_chan      *atchan = to_at_dma_chan(chan);
+       struct at_desc          *desc = NULL;
+       struct at_desc          *first = NULL;
+       struct at_desc          *prev = NULL;
+       size_t                  xfer_count;
+       size_t                  offset;
+       unsigned int            src_width;
+       unsigned int            dst_width;
+       u32                     ctrla;
+       u32                     ctrlb;
+
+       dev_vdbg(chan2dev(chan), "prep_dma_memcpy: d0x%x s0x%x l0x%zx f0x%lx\n",
+                       dest, src, len, flags);
+
+       if (unlikely(!len)) {
+               dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n");
+               return NULL;
+       }
+
+       ctrla =   ATC_DEFAULT_CTRLA;
+       ctrlb =   ATC_DEFAULT_CTRLB
+               | ATC_SRC_ADDR_MODE_INCR
+               | ATC_DST_ADDR_MODE_INCR
+               | ATC_FC_MEM2MEM;
+
+       /*
+        * We can be a lot more clever here, but this should take care
+        * of the most common optimization.
+        */
+       if (!((src | dest  | len) & 3)) {
+               ctrla |= ATC_SRC_WIDTH_WORD | ATC_DST_WIDTH_WORD;
+               src_width = dst_width = 2;
+       } else if (!((src | dest | len) & 1)) {
+               ctrla |= ATC_SRC_WIDTH_HALFWORD | ATC_DST_WIDTH_HALFWORD;
+               src_width = dst_width = 1;
+       } else {
+               ctrla |= ATC_SRC_WIDTH_BYTE | ATC_DST_WIDTH_BYTE;
+               src_width = dst_width = 0;
+       }
+
+       for (offset = 0; offset < len; offset += xfer_count << src_width) {
+               xfer_count = min_t(size_t, (len - offset) >> src_width,
+                               ATC_BTSIZE_MAX);
+
+               desc = atc_desc_get(atchan);
+               if (!desc)
+                       goto err_desc_get;
+
+               desc->lli.saddr = src + offset;
+               desc->lli.daddr = dest + offset;
+               desc->lli.ctrla = ctrla | xfer_count;
+               desc->lli.ctrlb = ctrlb;
+
+               desc->txd.cookie = 0;
+               async_tx_ack(&desc->txd);
+
+               if (!first) {
+                       first = desc;
+               } else {
+                       /* inform the HW lli about chaining */
+                       prev->lli.dscr = desc->txd.phys;
+                       /* insert the link descriptor to the LD ring */
+                       list_add_tail(&desc->desc_node,
+                                       &first->txd.tx_list);
+               }
+               prev = desc;
+       }
+
+       /* First descriptor of the chain embedds additional information */
+       first->txd.cookie = -EBUSY;
+       first->len = len;
+
+       /* set end-of-link to the last link descriptor of list*/
+       set_desc_eol(desc);
+
+       desc->txd.flags = flags; /* client is in control of this ack */
+
+       return &first->txd;
+
+err_desc_get:
+       atc_desc_put(atchan, first);
+       return NULL;
+}
+
+
+/**
+ * atc_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction
+ * @chan: DMA channel
+ * @sgl: scatterlist to transfer to/from
+ * @sg_len: number of entries in @scatterlist
+ * @direction: DMA direction
+ * @flags: tx descriptor status flags
+ */
+static struct dma_async_tx_descriptor *
+atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+               unsigned int sg_len, enum dma_data_direction direction,
+               unsigned long flags)
+{
+       struct at_dma_chan      *atchan = to_at_dma_chan(chan);
+       struct at_dma_slave     *atslave = chan->private;
+       struct at_desc          *first = NULL;
+       struct at_desc          *prev = NULL;
+       u32                     ctrla;
+       u32                     ctrlb;
+       dma_addr_t              reg;
+       unsigned int            reg_width;
+       unsigned int            mem_width;
+       unsigned int            i;
+       struct scatterlist      *sg;
+       size_t                  total_len = 0;
+
+       dev_vdbg(chan2dev(chan), "prep_slave_sg: %s f0x%lx\n",
+                       direction == DMA_TO_DEVICE ? "TO DEVICE" : "FROM DEVICE",
+                       flags);
+
+       if (unlikely(!atslave || !sg_len)) {
+               dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n");
+               return NULL;
+       }
+
+       reg_width = atslave->reg_width;
+
+       sg_len = dma_map_sg(chan2parent(chan), sgl, sg_len, direction);
+
+       ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla;
+       ctrlb = ATC_DEFAULT_CTRLB | ATC_IEN;
+
+       switch (direction) {
+       case DMA_TO_DEVICE:
+               ctrla |=  ATC_DST_WIDTH(reg_width);
+               ctrlb |=  ATC_DST_ADDR_MODE_FIXED
+                       | ATC_SRC_ADDR_MODE_INCR
+                       | ATC_FC_MEM2PER;
+               reg = atslave->tx_reg;
+               for_each_sg(sgl, sg, sg_len, i) {
+                       struct at_desc  *desc;
+                       u32             len;
+                       u32             mem;
+
+                       desc = atc_desc_get(atchan);
+                       if (!desc)
+                               goto err_desc_get;
+
+                       mem = sg_phys(sg);
+                       len = sg_dma_len(sg);
+                       mem_width = 2;
+                       if (unlikely(mem & 3 || len & 3))
+                               mem_width = 0;
+
+                       desc->lli.saddr = mem;
+                       desc->lli.daddr = reg;
+                       desc->lli.ctrla = ctrla
+                                       | ATC_SRC_WIDTH(mem_width)
+                                       | len >> mem_width;
+                       desc->lli.ctrlb = ctrlb;
+
+                       if (!first) {
+                               first = desc;
+                       } else {
+                               /* inform the HW lli about chaining */
+                               prev->lli.dscr = desc->txd.phys;
+                               /* insert the link descriptor to the LD ring */
+                               list_add_tail(&desc->desc_node,
+                                               &first->txd.tx_list);
+                       }
+                       prev = desc;
+                       total_len += len;
+               }
+               break;
+       case DMA_FROM_DEVICE:
+               ctrla |=  ATC_SRC_WIDTH(reg_width);
+               ctrlb |=  ATC_DST_ADDR_MODE_INCR
+                       | ATC_SRC_ADDR_MODE_FIXED
+                       | ATC_FC_PER2MEM;
+
+               reg = atslave->rx_reg;
+               for_each_sg(sgl, sg, sg_len, i) {
+                       struct at_desc  *desc;
+                       u32             len;
+                       u32             mem;
+
+                       desc = atc_desc_get(atchan);
+                       if (!desc)
+                               goto err_desc_get;
+
+                       mem = sg_phys(sg);
+                       len = sg_dma_len(sg);
+                       mem_width = 2;
+                       if (unlikely(mem & 3 || len & 3))
+                               mem_width = 0;
+
+                       desc->lli.saddr = reg;
+                       desc->lli.daddr = mem;
+                       desc->lli.ctrla = ctrla
+                                       | ATC_DST_WIDTH(mem_width)
+                                       | len >> mem_width;
+                       desc->lli.ctrlb = ctrlb;
+
+                       if (!first) {
+                               first = desc;
+                       } else {
+                               /* inform the HW lli about chaining */
+                               prev->lli.dscr = desc->txd.phys;
+                               /* insert the link descriptor to the LD ring */
+                               list_add_tail(&desc->desc_node,
+                                               &first->txd.tx_list);
+                       }
+                       prev = desc;
+                       total_len += len;
+               }
+               break;
+       default:
+               return NULL;
+       }
+
+       /* set end-of-link to the last link descriptor of list*/
+       set_desc_eol(prev);
+
+       /* First descriptor of the chain embedds additional information */
+       first->txd.cookie = -EBUSY;
+       first->len = total_len;
+
+       /* last link descriptor of list is responsible of flags */
+       prev->txd.flags = flags; /* client is in control of this ack */
+
+       return &first->txd;
+
+err_desc_get:
+       dev_err(chan2dev(chan), "not enough descriptors available\n");
+       atc_desc_put(atchan, first);
+       return NULL;
+}
+
+static void atc_terminate_all(struct dma_chan *chan)
+{
+       struct at_dma_chan      *atchan = to_at_dma_chan(chan);
+       struct at_dma           *atdma = to_at_dma(chan->device);
+       struct at_desc          *desc, *_desc;
+       LIST_HEAD(list);
+
+       /*
+        * This is only called when something went wrong elsewhere, so
+        * we don't really care about the data. Just disable the
+        * channel. We still have to poll the channel enable bit due
+        * to AHB/HSB limitations.
+        */
+       spin_lock_bh(&atchan->lock);
+
+       dma_writel(atdma, CHDR, atchan->mask);
+
+       /* confirm that this channel is disabled */
+       while (dma_readl(atdma, CHSR) & atchan->mask)
+               cpu_relax();
+
+       /* active_list entries will end up before queued entries */
+       list_splice_init(&atchan->queue, &list);
+       list_splice_init(&atchan->active_list, &list);
+
+       spin_unlock_bh(&atchan->lock);
+
+       /* Flush all pending and queued descriptors */
+       list_for_each_entry_safe(desc, _desc, &list, desc_node)
+               atc_chain_complete(atchan, desc);
+}
+
+/**
+ * atc_is_tx_complete - poll for transaction completion
+ * @chan: DMA channel
+ * @cookie: transaction identifier to check status of
+ * @done: if not %NULL, updated with last completed transaction
+ * @used: if not %NULL, updated with last used transaction
+ *
+ * If @done and @used are passed in, upon return they reflect the driver
+ * internal state and can be used with dma_async_is_complete() to check
+ * the status of multiple cookies without re-checking hardware state.
+ */
+static enum dma_status
+atc_is_tx_complete(struct dma_chan *chan,
+               dma_cookie_t cookie,
+               dma_cookie_t *done, dma_cookie_t *used)
+{
+       struct at_dma_chan      *atchan = to_at_dma_chan(chan);
+       dma_cookie_t            last_used;
+       dma_cookie_t            last_complete;
+       enum dma_status         ret;
+
+       dev_vdbg(chan2dev(chan), "is_tx_complete: %d (d%d, u%d)\n",
+                       cookie, done ? *done : 0, used ? *used : 0);
+
+       spin_lock_bh(atchan->lock);
+
+       last_complete = atchan->completed_cookie;
+       last_used = chan->cookie;
+
+       ret = dma_async_is_complete(cookie, last_complete, last_used);
+       if (ret != DMA_SUCCESS) {
+               atc_cleanup_descriptors(atchan);
+
+               last_complete = atchan->completed_cookie;
+               last_used = chan->cookie;
+
+               ret = dma_async_is_complete(cookie, last_complete, last_used);
+       }
+
+       spin_unlock_bh(atchan->lock);
+
+       if (done)
+               *done = last_complete;
+       if (used)
+               *used = last_used;
+
+       return ret;
+}
+
+/**
+ * atc_issue_pending - try to finish work
+ * @chan: target DMA channel
+ */
+static void atc_issue_pending(struct dma_chan *chan)
+{
+       struct at_dma_chan      *atchan = to_at_dma_chan(chan);
+
+       dev_vdbg(chan2dev(chan), "issue_pending\n");
+
+       if (!atc_chan_is_enabled(atchan)) {
+               spin_lock_bh(&atchan->lock);
+               atc_advance_work(atchan);
+               spin_unlock_bh(&atchan->lock);
+       }
+}
+
+/**
+ * atc_alloc_chan_resources - allocate resources for DMA channel
+ * @chan: allocate descriptor resources for this channel
+ * @client: current client requesting the channel be ready for requests
+ *
+ * return - the number of allocated descriptors
+ */
+static int atc_alloc_chan_resources(struct dma_chan *chan)
+{
+       struct at_dma_chan      *atchan = to_at_dma_chan(chan);
+       struct at_dma           *atdma = to_at_dma(chan->device);
+       struct at_desc          *desc;
+       struct at_dma_slave     *atslave;
+       int                     i;
+       u32                     cfg;
+       LIST_HEAD(tmp_list);
+
+       dev_vdbg(chan2dev(chan), "alloc_chan_resources\n");
+
+       /* ASSERT:  channel is idle */
+       if (atc_chan_is_enabled(atchan)) {
+               dev_dbg(chan2dev(chan), "DMA channel not idle ?\n");
+               return -EIO;
+       }
+
+       cfg = ATC_DEFAULT_CFG;
+
+       atslave = chan->private;
+       if (atslave) {
+               /*
+                * We need controller-specific data to set up slave
+                * transfers.
+                */
+               BUG_ON(!atslave->dma_dev || atslave->dma_dev != atdma->dma_common.dev);
+
+               /* if cfg configuration specified take it instad of default */
+               if (atslave->cfg)
+                       cfg = atslave->cfg;
+       }
+
+       /* have we already been set up?
+        * reconfigure channel but no need to reallocate descriptors */
+       if (!list_empty(&atchan->free_list))
+               return atchan->descs_allocated;
+
+       /* Allocate initial pool of descriptors */
+       for (i = 0; i < init_nr_desc_per_channel; i++) {
+               desc = atc_alloc_descriptor(chan, GFP_KERNEL);
+               if (!desc) {
+                       dev_err(atdma->dma_common.dev,
+                               "Only %d initial descriptors\n", i);
+                       break;
+               }
+               list_add_tail(&desc->desc_node, &tmp_list);
+       }
+
+       spin_lock_bh(&atchan->lock);
+       atchan->descs_allocated = i;
+       list_splice(&tmp_list, &atchan->free_list);
+       atchan->completed_cookie = chan->cookie = 1;
+       spin_unlock_bh(&atchan->lock);
+
+       /* channel parameters */
+       channel_writel(atchan, CFG, cfg);
+
+       dev_dbg(chan2dev(chan),
+               "alloc_chan_resources: allocated %d descriptors\n",
+               atchan->descs_allocated);
+
+       return atchan->descs_allocated;
+}
+
+/**
+ * atc_free_chan_resources - free all channel resources
+ * @chan: DMA channel
+ */
+static void atc_free_chan_resources(struct dma_chan *chan)
+{
+       struct at_dma_chan      *atchan = to_at_dma_chan(chan);
+       struct at_dma           *atdma = to_at_dma(chan->device);
+       struct at_desc          *desc, *_desc;
+       LIST_HEAD(list);
+
+       dev_dbg(chan2dev(chan), "free_chan_resources: (descs allocated=%u)\n",
+               atchan->descs_allocated);
+
+       /* ASSERT:  channel is idle */
+       BUG_ON(!list_empty(&atchan->active_list));
+       BUG_ON(!list_empty(&atchan->queue));
+       BUG_ON(atc_chan_is_enabled(atchan));
+
+       list_for_each_entry_safe(desc, _desc, &atchan->free_list, desc_node) {
+               dev_vdbg(chan2dev(chan), "  freeing descriptor %p\n", desc);
+               list_del(&desc->desc_node);
+               /* free link descriptor */
+               dma_pool_free(atdma->dma_desc_pool, desc, desc->txd.phys);
+       }
+       list_splice_init(&atchan->free_list, &list);
+       atchan->descs_allocated = 0;
+
+       dev_vdbg(chan2dev(chan), "free_chan_resources: done\n");
+}
+
+
+/*--  Module Management  -----------------------------------------------*/
+
+/**
+ * at_dma_off - disable DMA controller
+ * @atdma: the Atmel HDAMC device
+ */
+static void at_dma_off(struct at_dma *atdma)
+{
+       dma_writel(atdma, EN, 0);
+
+       /* disable all interrupts */
+       dma_writel(atdma, EBCIDR, -1L);
+
+       /* confirm that all channels are disabled */
+       while (dma_readl(atdma, CHSR) & atdma->all_chan_mask)
+               cpu_relax();
+}
+
+static int __init at_dma_probe(struct platform_device *pdev)
+{
+       struct at_dma_platform_data *pdata;
+       struct resource         *io;
+       struct at_dma           *atdma;
+       size_t                  size;
+       int                     irq;
+       int                     err;
+       int                     i;
+
+       /* get DMA Controller parameters from platform */
+       pdata = pdev->dev.platform_data;
+       if (!pdata || pdata->nr_channels > AT_DMA_MAX_NR_CHANNELS)
+               return -EINVAL;
+
+       io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!io)
+               return -EINVAL;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
+
+       size = sizeof(struct at_dma);
+       size += pdata->nr_channels * sizeof(struct at_dma_chan);
+       atdma = kzalloc(size, GFP_KERNEL);
+       if (!atdma)
+               return -ENOMEM;
+
+       /* discover transaction capabilites from the platform data */
+       atdma->dma_common.cap_mask = pdata->cap_mask;
+       atdma->all_chan_mask = (1 << pdata->nr_channels) - 1;
+
+       size = io->end - io->start + 1;
+       if (!request_mem_region(io->start, size, pdev->dev.driver->name)) {
+               err = -EBUSY;
+               goto err_kfree;
+       }
+
+       atdma->regs = ioremap(io->start, size);
+       if (!atdma->regs) {
+               err = -ENOMEM;
+               goto err_release_r;
+       }
+
+       atdma->clk = clk_get(&pdev->dev, "dma_clk");
+       if (IS_ERR(atdma->clk)) {
+               err = PTR_ERR(atdma->clk);
+               goto err_clk;
+       }
+       clk_enable(atdma->clk);
+
+       /* force dma off, just in case */
+       at_dma_off(atdma);
+
+       err = request_irq(irq, at_dma_interrupt, 0, "at_hdmac", atdma);
+       if (err)
+               goto err_irq;
+
+       platform_set_drvdata(pdev, atdma);
+
+       /* create a pool of consistent memory blocks for hardware descriptors */
+       atdma->dma_desc_pool = dma_pool_create("at_hdmac_desc_pool",
+                       &pdev->dev, sizeof(struct at_desc),
+                       4 /* word alignment */, 0);
+       if (!atdma->dma_desc_pool) {
+               dev_err(&pdev->dev, "No memory for descriptors dma pool\n");
+               err = -ENOMEM;
+               goto err_pool_create;
+       }
+
+       /* clear any pending interrupt */
+       while (dma_readl(atdma, EBCISR))
+               cpu_relax();
+
+       /* initialize channels related values */
+       INIT_LIST_HEAD(&atdma->dma_common.channels);
+       for (i = 0; i < pdata->nr_channels; i++, atdma->dma_common.chancnt++) {
+               struct at_dma_chan      *atchan = &atdma->chan[i];
+
+               atchan->chan_common.device = &atdma->dma_common;
+               atchan->chan_common.cookie = atchan->completed_cookie = 1;
+               atchan->chan_common.chan_id = i;
+               list_add_tail(&atchan->chan_common.device_node,
+                               &atdma->dma_common.channels);
+
+               atchan->ch_regs = atdma->regs + ch_regs(i);
+               spin_lock_init(&atchan->lock);
+               atchan->mask = 1 << i;
+
+               INIT_LIST_HEAD(&atchan->active_list);
+               INIT_LIST_HEAD(&atchan->queue);
+               INIT_LIST_HEAD(&atchan->free_list);
+
+               tasklet_init(&atchan->tasklet, atc_tasklet,
+                               (unsigned long)atchan);
+               atc_enable_irq(atchan);
+       }
+
+       /* set base routines */
+       atdma->dma_common.device_alloc_chan_resources = atc_alloc_chan_resources;
+       atdma->dma_common.device_free_chan_resources = atc_free_chan_resources;
+       atdma->dma_common.device_is_tx_complete = atc_is_tx_complete;
+       atdma->dma_common.device_issue_pending = atc_issue_pending;
+       atdma->dma_common.dev = &pdev->dev;
+
+       /* set prep routines based on capability */
+       if (dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask))
+               atdma->dma_common.device_prep_dma_memcpy = atc_prep_dma_memcpy;
+
+       if (dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)) {
+               atdma->dma_common.device_prep_slave_sg = atc_prep_slave_sg;
+               atdma->dma_common.device_terminate_all = atc_terminate_all;
+       }
+
+       dma_writel(atdma, EN, AT_DMA_ENABLE);
+
+       dev_info(&pdev->dev, "Atmel AHB DMA Controller ( %s%s), %d channels\n",
+         dma_has_cap(DMA_MEMCPY, atdma->dma_common.cap_mask) ? "cpy " : "",
+         dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)  ? "slave " : "",
+         atdma->dma_common.chancnt);
+
+       dma_async_device_register(&atdma->dma_common);
+
+       return 0;
+
+err_pool_create:
+       platform_set_drvdata(pdev, NULL);
+       free_irq(platform_get_irq(pdev, 0), atdma);
+err_irq:
+       clk_disable(atdma->clk);
+       clk_put(atdma->clk);
+err_clk:
+       iounmap(atdma->regs);
+       atdma->regs = NULL;
+err_release_r:
+       release_mem_region(io->start, size);
+err_kfree:
+       kfree(atdma);
+       return err;
+}
+
+static int __exit at_dma_remove(struct platform_device *pdev)
+{
+       struct at_dma           *atdma = platform_get_drvdata(pdev);
+       struct dma_chan         *chan, *_chan;
+       struct resource         *io;
+
+       at_dma_off(atdma);
+       dma_async_device_unregister(&atdma->dma_common);
+
+       dma_pool_destroy(atdma->dma_desc_pool);
+       platform_set_drvdata(pdev, NULL);
+       free_irq(platform_get_irq(pdev, 0), atdma);
+
+       list_for_each_entry_safe(chan, _chan, &atdma->dma_common.channels,
+                       device_node) {
+               struct at_dma_chan      *atchan = to_at_dma_chan(chan);
+
+               /* Disable interrupts */
+               atc_disable_irq(atchan);
+               tasklet_disable(&atchan->tasklet);
+
+               tasklet_kill(&atchan->tasklet);
+               list_del(&chan->device_node);
+       }
+
+       clk_disable(atdma->clk);
+       clk_put(atdma->clk);
+
+       iounmap(atdma->regs);
+       atdma->regs = NULL;
+
+       io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(io->start, io->end - io->start + 1);
+
+       kfree(atdma);
+
+       return 0;
+}
+
+static void at_dma_shutdown(struct platform_device *pdev)
+{
+       struct at_dma   *atdma = platform_get_drvdata(pdev);
+
+       at_dma_off(platform_get_drvdata(pdev));
+       clk_disable(atdma->clk);
+}
+
+static int at_dma_suspend_late(struct platform_device *pdev, pm_message_t mesg)
+{
+       struct at_dma   *atdma = platform_get_drvdata(pdev);
+
+       at_dma_off(platform_get_drvdata(pdev));
+       clk_disable(atdma->clk);
+       return 0;
+}
+
+static int at_dma_resume_early(struct platform_device *pdev)
+{
+       struct at_dma   *atdma = platform_get_drvdata(pdev);
+
+       clk_enable(atdma->clk);
+       dma_writel(atdma, EN, AT_DMA_ENABLE);
+       return 0;
+
+}
+
+static struct platform_driver at_dma_driver = {
+       .remove         = __exit_p(at_dma_remove),
+       .shutdown       = at_dma_shutdown,
+       .suspend_late   = at_dma_suspend_late,
+       .resume_early   = at_dma_resume_early,
+       .driver = {
+               .name   = "at_hdmac",
+       },
+};
+
+static int __init at_dma_init(void)
+{
+       return platform_driver_probe(&at_dma_driver, at_dma_probe);
+}
+module_init(at_dma_init);
+
+static void __exit at_dma_exit(void)
+{
+       platform_driver_unregister(&at_dma_driver);
+}
+module_exit(at_dma_exit);
+
+MODULE_DESCRIPTION("Atmel AHB DMA Controller driver");
+MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:at_hdmac");
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
new file mode 100644 (file)
index 0000000..4c972af
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * Header file for the Atmel AHB DMA Controller driver
+ *
+ * Copyright (C) 2008 Atmel 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.
+ */
+#ifndef AT_HDMAC_REGS_H
+#define        AT_HDMAC_REGS_H
+
+#include <mach/at_hdmac.h>
+
+#define        AT_DMA_MAX_NR_CHANNELS  8
+
+
+#define        AT_DMA_GCFG     0x00    /* Global Configuration Register */
+#define                AT_DMA_IF_BIGEND(i)     (0x1 << (i))    /* AHB-Lite Interface i in Big-endian mode */
+#define                AT_DMA_ARB_CFG  (0x1 << 4)      /* Arbiter mode. */
+#define                        AT_DMA_ARB_CFG_FIXED            (0x0 << 4)
+#define                        AT_DMA_ARB_CFG_ROUND_ROBIN      (0x1 << 4)
+
+#define        AT_DMA_EN       0x04    /* Controller Enable Register */
+#define                AT_DMA_ENABLE   (0x1 << 0)
+
+#define        AT_DMA_SREQ     0x08    /* Software Single Request Register */
+#define                AT_DMA_SSREQ(x) (0x1 << ((x) << 1))             /* Request a source single transfer on channel x */
+#define                AT_DMA_DSREQ(x) (0x1 << (1 + ((x) << 1)))       /* Request a destination single transfer on channel x */
+
+#define        AT_DMA_CREQ     0x0C    /* Software Chunk Transfer Request Register */
+#define                AT_DMA_SCREQ(x) (0x1 << ((x) << 1))             /* Request a source chunk transfer on channel x */
+#define                AT_DMA_DCREQ(x) (0x1 << (1 + ((x) << 1)))       /* Request a destination chunk transfer on channel x */
+
+#define        AT_DMA_LAST     0x10    /* Software Last Transfer Flag Register */
+#define                AT_DMA_SLAST(x) (0x1 << ((x) << 1))             /* This src rq is last tx of buffer on channel x */
+#define                AT_DMA_DLAST(x) (0x1 << (1 + ((x) << 1)))       /* This dst rq is last tx of buffer on channel x */
+
+#define        AT_DMA_SYNC     0x14    /* Request Synchronization Register */
+#define                AT_DMA_SYR(h)   (0x1 << (h))                    /* Synchronize handshake line h */
+
+/* Error, Chained Buffer transfer completed and Buffer transfer completed Interrupt registers */
+#define        AT_DMA_EBCIER   0x18    /* Enable register */
+#define        AT_DMA_EBCIDR   0x1C    /* Disable register */
+#define        AT_DMA_EBCIMR   0x20    /* Mask Register */
+#define        AT_DMA_EBCISR   0x24    /* Status Register */
+#define                AT_DMA_CBTC_OFFSET      8
+#define                AT_DMA_ERR_OFFSET       16
+#define                AT_DMA_BTC(x)   (0x1 << (x))
+#define                AT_DMA_CBTC(x)  (0x1 << (AT_DMA_CBTC_OFFSET + (x)))
+#define                AT_DMA_ERR(x)   (0x1 << (AT_DMA_ERR_OFFSET + (x)))
+
+#define        AT_DMA_CHER     0x28    /* Channel Handler Enable Register */
+#define                AT_DMA_ENA(x)   (0x1 << (x))
+#define                AT_DMA_SUSP(x)  (0x1 << ( 8 + (x)))
+#define                AT_DMA_KEEP(x)  (0x1 << (24 + (x)))
+
+#define        AT_DMA_CHDR     0x2C    /* Channel Handler Disable Register */
+#define                AT_DMA_DIS(x)   (0x1 << (x))
+#define                AT_DMA_RES(x)   (0x1 << ( 8 + (x)))
+
+#define        AT_DMA_CHSR     0x30    /* Channel Handler Status Register */
+#define                AT_DMA_EMPT(x)  (0x1 << (16 + (x)))
+#define                AT_DMA_STAL(x)  (0x1 << (24 + (x)))
+
+
+#define        AT_DMA_CH_REGS_BASE     0x3C    /* Channel registers base address */
+#define        ch_regs(x)      (AT_DMA_CH_REGS_BASE + (x) * 0x28) /* Channel x base addr */
+
+/* Hardware register offset for each channel */
+#define        ATC_SADDR_OFFSET        0x00    /* Source Address Register */
+#define        ATC_DADDR_OFFSET        0x04    /* Destination Address Register */
+#define        ATC_DSCR_OFFSET         0x08    /* Descriptor Address Register */
+#define        ATC_CTRLA_OFFSET        0x0C    /* Control A Register */
+#define        ATC_CTRLB_OFFSET        0x10    /* Control B Register */
+#define        ATC_CFG_OFFSET          0x14    /* Configuration Register */
+#define        ATC_SPIP_OFFSET         0x18    /* Src PIP Configuration Register */
+#define        ATC_DPIP_OFFSET         0x1C    /* Dst PIP Configuration Register */
+
+
+/* Bitfield definitions */
+
+/* Bitfields in DSCR */
+#define        ATC_DSCR_IF(i)          (0x3 & (i))     /* Dsc feched via AHB-Lite Interface i */
+
+/* Bitfields in CTRLA */
+#define        ATC_BTSIZE_MAX          0xFFFFUL        /* Maximum Buffer Transfer Size */
+#define        ATC_BTSIZE(x)           (ATC_BTSIZE_MAX & (x)) /* Buffer Transfer Size */
+/* Chunck Tranfer size definitions are in at_hdmac.h */
+#define        ATC_SRC_WIDTH_MASK      (0x3 << 24)     /* Source Single Transfer Size */
+#define                ATC_SRC_WIDTH(x)        ((x) << 24)
+#define                ATC_SRC_WIDTH_BYTE      (0x0 << 24)
+#define                ATC_SRC_WIDTH_HALFWORD  (0x1 << 24)
+#define                ATC_SRC_WIDTH_WORD      (0x2 << 24)
+#define        ATC_DST_WIDTH_MASK      (0x3 << 28)     /* Destination Single Transfer Size */
+#define                ATC_DST_WIDTH(x)        ((x) << 28)
+#define                ATC_DST_WIDTH_BYTE      (0x0 << 28)
+#define                ATC_DST_WIDTH_HALFWORD  (0x1 << 28)
+#define                ATC_DST_WIDTH_WORD      (0x2 << 28)
+#define        ATC_DONE                (0x1 << 31)     /* Tx Done (only written back in descriptor) */
+
+/* Bitfields in CTRLB */
+#define        ATC_SIF(i)              (0x3 & (i))     /* Src tx done via AHB-Lite Interface i */
+#define        ATC_DIF(i)              ((0x3 & (i)) <<  4)     /* Dst tx done via AHB-Lite Interface i */
+#define        ATC_SRC_PIP             (0x1 <<  8)     /* Source Picture-in-Picture enabled */
+#define        ATC_DST_PIP             (0x1 << 12)     /* Destination Picture-in-Picture enabled */
+#define        ATC_SRC_DSCR_DIS        (0x1 << 16)     /* Src Descriptor fetch disable */
+#define        ATC_DST_DSCR_DIS        (0x1 << 20)     /* Dst Descriptor fetch disable */
+#define        ATC_FC_MASK             (0x7 << 21)     /* Choose Flow Controller */
+#define                ATC_FC_MEM2MEM          (0x0 << 21)     /* Mem-to-Mem (DMA) */
+#define                ATC_FC_MEM2PER          (0x1 << 21)     /* Mem-to-Periph (DMA) */
+#define                ATC_FC_PER2MEM          (0x2 << 21)     /* Periph-to-Mem (DMA) */
+#define                ATC_FC_PER2PER          (0x3 << 21)     /* Periph-to-Periph (DMA) */
+#define                ATC_FC_PER2MEM_PER      (0x4 << 21)     /* Periph-to-Mem (Peripheral) */
+#define                ATC_FC_MEM2PER_PER      (0x5 << 21)     /* Mem-to-Periph (Peripheral) */
+#define                ATC_FC_PER2PER_SRCPER   (0x6 << 21)     /* Periph-to-Periph (Src Peripheral) */
+#define                ATC_FC_PER2PER_DSTPER   (0x7 << 21)     /* Periph-to-Periph (Dst Peripheral) */
+#define        ATC_SRC_ADDR_MODE_MASK  (0x3 << 24)
+#define                ATC_SRC_ADDR_MODE_INCR  (0x0 << 24)     /* Incrementing Mode */
+#define                ATC_SRC_ADDR_MODE_DECR  (0x1 << 24)     /* Decrementing Mode */
+#define                ATC_SRC_ADDR_MODE_FIXED (0x2 << 24)     /* Fixed Mode */
+#define        ATC_DST_ADDR_MODE_MASK  (0x3 << 28)
+#define                ATC_DST_ADDR_MODE_INCR  (0x0 << 28)     /* Incrementing Mode */
+#define                ATC_DST_ADDR_MODE_DECR  (0x1 << 28)     /* Decrementing Mode */
+#define                ATC_DST_ADDR_MODE_FIXED (0x2 << 28)     /* Fixed Mode */
+#define        ATC_IEN                 (0x1 << 30)     /* BTC interrupt enable (active low) */
+#define        ATC_AUTO                (0x1 << 31)     /* Auto multiple buffer tx enable */
+
+/* Bitfields in CFG */
+/* are in at_hdmac.h */
+
+/* Bitfields in SPIP */
+#define        ATC_SPIP_HOLE(x)        (0xFFFFU & (x))
+#define        ATC_SPIP_BOUNDARY(x)    ((0x3FF & (x)) << 16)
+
+/* Bitfields in DPIP */
+#define        ATC_DPIP_HOLE(x)        (0xFFFFU & (x))
+#define        ATC_DPIP_BOUNDARY(x)    ((0x3FF & (x)) << 16)
+
+
+/*--  descriptors  -----------------------------------------------------*/
+
+/* LLI == Linked List Item; aka DMA buffer descriptor */
+struct at_lli {
+       /* values that are not changed by hardware */
+       dma_addr_t      saddr;
+       dma_addr_t      daddr;
+       /* value that may get written back: */
+       u32             ctrla;
+       /* more values that are not changed by hardware */
+       u32             ctrlb;
+       dma_addr_t      dscr;   /* chain to next lli */
+};
+
+/**
+ * struct at_desc - software descriptor
+ * @at_lli: hardware lli structure
+ * @txd: support for the async_tx api
+ * @desc_node: node on the channed descriptors list
+ * @len: total transaction bytecount
+ */
+struct at_desc {
+       /* FIRST values the hardware uses */
+       struct at_lli                   lli;
+
+       /* THEN values for driver housekeeping */
+       struct dma_async_tx_descriptor  txd;
+       struct list_head                desc_node;
+       size_t                          len;
+};
+
+static inline struct at_desc *
+txd_to_at_desc(struct dma_async_tx_descriptor *txd)
+{
+       return container_of(txd, struct at_desc, txd);
+}
+
+
+/*--  Channels  --------------------------------------------------------*/
+
+/**
+ * struct at_dma_chan - internal representation of an Atmel HDMAC channel
+ * @chan_common: common dmaengine channel object members
+ * @device: parent device
+ * @ch_regs: memory mapped register base
+ * @mask: channel index in a mask
+ * @error_status: transmit error status information from irq handler
+ *                to tasklet (use atomic operations)
+ * @tasklet: bottom half to finish transaction work
+ * @lock: serializes enqueue/dequeue operations to descriptors lists
+ * @completed_cookie: identifier for the most recently completed operation
+ * @active_list: list of descriptors dmaengine is being running on
+ * @queue: list of descriptors ready to be submitted to engine
+ * @free_list: list of descriptors usable by the channel
+ * @descs_allocated: records the actual size of the descriptor pool
+ */
+struct at_dma_chan {
+       struct dma_chan         chan_common;
+       struct at_dma           *device;
+       void __iomem            *ch_regs;
+       u8                      mask;
+       unsigned long           error_status;
+       struct tasklet_struct   tasklet;
+
+       spinlock_t              lock;
+
+       /* these other elements are all protected by lock */
+       dma_cookie_t            completed_cookie;
+       struct list_head        active_list;
+       struct list_head        queue;
+       struct list_head        free_list;
+       unsigned int            descs_allocated;
+};
+
+#define        channel_readl(atchan, name) \
+       __raw_readl((atchan)->ch_regs + ATC_##name##_OFFSET)
+
+#define        channel_writel(atchan, name, val) \
+       __raw_writel((val), (atchan)->ch_regs + ATC_##name##_OFFSET)
+
+static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
+{
+       return container_of(dchan, struct at_dma_chan, chan_common);
+}
+
+
+/*--  Controller  ------------------------------------------------------*/
+
+/**
+ * struct at_dma - internal representation of an Atmel HDMA Controller
+ * @chan_common: common dmaengine dma_device object members
+ * @ch_regs: memory mapped register base
+ * @clk: dma controller clock
+ * @all_chan_mask: all channels availlable in a mask
+ * @dma_desc_pool: base of DMA descriptor region (DMA address)
+ * @chan: channels table to store at_dma_chan structures
+ */
+struct at_dma {
+       struct dma_device       dma_common;
+       void __iomem            *regs;
+       struct clk              *clk;
+
+       u8                      all_chan_mask;
+
+       struct dma_pool         *dma_desc_pool;
+       /* AT THE END channels table */
+       struct at_dma_chan      chan[0];
+};
+
+#define        dma_readl(atdma, name) \
+       __raw_readl((atdma)->regs + AT_DMA_##name)
+#define        dma_writel(atdma, name, val) \
+       __raw_writel((val), (atdma)->regs + AT_DMA_##name)
+
+static inline struct at_dma *to_at_dma(struct dma_device *ddev)
+{
+       return container_of(ddev, struct at_dma, dma_common);
+}
+
+
+/*--  Helper functions  ------------------------------------------------*/
+
+static struct device *chan2dev(struct dma_chan *chan)
+{
+       return &chan->dev->device;
+}
+static struct device *chan2parent(struct dma_chan *chan)
+{
+       return chan->dev->device.parent;
+}
+
+#if defined(VERBOSE_DEBUG)
+static void vdbg_dump_regs(struct at_dma_chan *atchan)
+{
+       struct at_dma   *atdma = to_at_dma(atchan->chan_common.device);
+
+       dev_err(chan2dev(&atchan->chan_common),
+               "  channel %d : imr = 0x%x, chsr = 0x%x\n",
+               atchan->chan_common.chan_id,
+               dma_readl(atdma, EBCIMR),
+               dma_readl(atdma, CHSR));
+
+       dev_err(chan2dev(&atchan->chan_common),
+               "  channel: s0x%x d0x%x ctrl0x%x:0x%x cfg0x%x l0x%x\n",
+               channel_readl(atchan, SADDR),
+               channel_readl(atchan, DADDR),
+               channel_readl(atchan, CTRLA),
+               channel_readl(atchan, CTRLB),
+               channel_readl(atchan, CFG),
+               channel_readl(atchan, DSCR));
+}
+#else
+static void vdbg_dump_regs(struct at_dma_chan *atchan) {}
+#endif
+
+static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli)
+{
+       dev_printk(KERN_CRIT, chan2dev(&atchan->chan_common),
+                       "  desc: s0x%x d0x%x ctrl0x%x:0x%x l0x%x\n",
+                       lli->saddr, lli->daddr,
+                       lli->ctrla, lli->ctrlb, lli->dscr);
+}
+
+
+static void atc_setup_irq(struct at_dma_chan *atchan, int on)
+{
+       struct at_dma   *atdma = to_at_dma(atchan->chan_common.device);
+       u32             ebci;
+
+       /* enable interrupts on buffer chain completion & error */
+       ebci =    AT_DMA_CBTC(atchan->chan_common.chan_id)
+               | AT_DMA_ERR(atchan->chan_common.chan_id);
+       if (on)
+               dma_writel(atdma, EBCIER, ebci);
+       else
+               dma_writel(atdma, EBCIDR, ebci);
+}
+
+static inline void atc_enable_irq(struct at_dma_chan *atchan)
+{
+       atc_setup_irq(atchan, 1);
+}
+
+static inline void atc_disable_irq(struct at_dma_chan *atchan)
+{
+       atc_setup_irq(atchan, 0);
+}
+
+
+/**
+ * atc_chan_is_enabled - test if given channel is enabled
+ * @atchan: channel we want to test status
+ */
+static inline int atc_chan_is_enabled(struct at_dma_chan *atchan)
+{
+       struct at_dma   *atdma = to_at_dma(atchan->chan_common.device);
+
+       return !!(dma_readl(atdma, CHSR) & atchan->mask);
+}
+
+
+/**
+ * set_desc_eol - set end-of-link to descriptor so it will end transfer
+ * @desc: descriptor, signle or at the end of a chain, to end chain on
+ */
+static void set_desc_eol(struct at_desc *desc)
+{
+       desc->lli.ctrlb |= ATC_SRC_DSCR_DIS | ATC_DST_DSCR_DIS;
+       desc->lli.dscr = 0;
+}
+
+#endif /* AT_HDMAC_REGS_H */
index fb7da5141e96b2052fae826f816909c2598035d9..d93017fc7872d1f0fe3904ff85870ff8aee1156a 100644 (file)
@@ -38,6 +38,11 @@ module_param(max_channels, uint, S_IRUGO);
 MODULE_PARM_DESC(max_channels,
                "Maximum number of channels to use (default: all)");
 
+static unsigned int iterations;
+module_param(iterations, uint, S_IRUGO);
+MODULE_PARM_DESC(iterations,
+               "Iterations before stopping test (default: infinite)");
+
 static unsigned int xor_sources = 3;
 module_param(xor_sources, uint, S_IRUGO);
 MODULE_PARM_DESC(xor_sources,
@@ -114,7 +119,7 @@ static void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len)
                        buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
                for ( ; i < start + len; i++)
                        buf[i] = PATTERN_SRC | PATTERN_COPY
-                               | (~i & PATTERN_COUNT_MASK);;
+                               | (~i & PATTERN_COUNT_MASK);
                for ( ; i < test_buf_size; i++)
                        buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
                buf++;
@@ -270,7 +275,8 @@ static int dmatest_func(void *data)
 
        flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT;
 
-       while (!kthread_should_stop()) {
+       while (!kthread_should_stop()
+              && !(iterations && total_tests >= iterations)) {
                struct dma_device *dev = chan->device;
                struct dma_async_tx_descriptor *tx = NULL;
                dma_addr_t dma_srcs[src_cnt];
@@ -416,6 +422,13 @@ err_srcbuf:
 err_srcs:
        pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
                        thread_name, total_tests, failed_tests, ret);
+
+       if (iterations > 0)
+               while (!kthread_should_stop()) {
+                       DECLARE_WAIT_QUEUE_HEAD(wait_dmatest_exit);
+                       interruptible_sleep_on(&wait_dmatest_exit);
+               }
+
        return ret;
 }
 
@@ -495,11 +508,11 @@ static int dmatest_add_channel(struct dma_chan *chan)
 
        if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
                cnt = dmatest_add_threads(dtc, DMA_MEMCPY);
-               thread_count += cnt > 0 ?: 0;
+               thread_count += cnt > 0 ? cnt : 0;
        }
        if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
                cnt = dmatest_add_threads(dtc, DMA_XOR);
-               thread_count += cnt > 0 ?: 0;
+               thread_count += cnt > 0 ? cnt : 0;
        }
 
        pr_info("dmatest: Started %u threads using %s\n",
index f18d1bde04397178dfd4a88f263c77546449c381..ef87a89841450e0f35f1a35f4753b0207abc0300 100644 (file)
  *   also fit for MPC8560, MPC8555, MPC8548, MPC8641, and etc.
  *   The support for MPC8349 DMA contorller is also added.
  *
+ * This driver instructs the DMA controller to issue the PCI Read Multiple
+ * command for PCI read operations, instead of using the default PCI Read Line
+ * command. Please be aware that this setting may result in read pre-fetching
+ * on some platforms.
+ *
  * This 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
@@ -49,9 +54,10 @@ static void dma_init(struct fsl_dma_chan *fsl_chan)
        case FSL_DMA_IP_83XX:
                /* Set the channel to below modes:
                 * EOTIE - End-of-transfer interrupt enable
+                * PRC_RM - PCI read multiple
                 */
-               DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, FSL_DMA_MR_EOTIE,
-                               32);
+               DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, FSL_DMA_MR_EOTIE
+                               | FSL_DMA_MR_PRC_RM, 32);
                break;
        }
 
@@ -136,15 +142,16 @@ static int dma_is_idle(struct fsl_dma_chan *fsl_chan)
 
 static void dma_start(struct fsl_dma_chan *fsl_chan)
 {
-       u32 mr_set = 0;;
+       u32 mr_set = 0;
 
        if (fsl_chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
                DMA_OUT(fsl_chan, &fsl_chan->reg_base->bcr, 0, 32);
                mr_set |= FSL_DMA_MR_EMP_EN;
-       } else
+       } else if ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
                DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr,
                        DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32)
                                & ~FSL_DMA_MR_EMP_EN, 32);
+       }
 
        if (fsl_chan->feature & FSL_DMA_CHAN_START_EXT)
                mr_set |= FSL_DMA_MR_EMS_EN;
@@ -871,9 +878,9 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev,
 
        switch (new_fsl_chan->feature & FSL_DMA_IP_MASK) {
        case FSL_DMA_IP_85XX:
-               new_fsl_chan->toggle_ext_start = fsl_chan_toggle_ext_start;
                new_fsl_chan->toggle_ext_pause = fsl_chan_toggle_ext_pause;
        case FSL_DMA_IP_83XX:
+               new_fsl_chan->toggle_ext_start = fsl_chan_toggle_ext_start;
                new_fsl_chan->set_src_loop_size = fsl_chan_set_src_loop_size;
                new_fsl_chan->set_dest_loop_size = fsl_chan_set_dest_loop_size;
        }
index 4f21a512d84852cf2074084ffc8f7035228a2fe7..dc7f26865797cc12ef6610296a83919107c5ad84 100644 (file)
@@ -38,6 +38,7 @@
 
 /* Special MR definition for MPC8349 */
 #define FSL_DMA_MR_EOTIE       0x00000080
+#define FSL_DMA_MR_PRC_RM      0x00000800
 
 #define FSL_DMA_SR_CH          0x00000020
 #define FSL_DMA_SR_PE          0x00000010
index ddab94f512247d600a1488a44d27a832f8ee9d3c..3f23eabe09f2076cc05ddc1805129615d1dde6bc 100644 (file)
@@ -1176,7 +1176,7 @@ static int __devinit mv_xor_probe(struct platform_device *pdev)
        if (dma_has_cap(DMA_MEMSET, dma_dev->cap_mask))
                dma_dev->device_prep_dma_memset = mv_xor_prep_dma_memset;
        if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
-               dma_dev->max_xor = 8;                  ;
+               dma_dev->max_xor = 8;
                dma_dev->device_prep_dma_xor = mv_xor_prep_dma_xor;
        }
 
index c36bf40568cf8e7de0aacaa5ce7219650cec5a26..e2a10bcba7a14d511ada5eada69cc329a81ab36c 100644 (file)
@@ -754,13 +754,13 @@ static void amd64_cpu_display_info(struct amd64_pvt *pvt)
 static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt)
 {
        int bit;
-       enum dev_type edac_cap = EDAC_NONE;
+       enum dev_type edac_cap = EDAC_FLAG_NONE;
 
        bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= OPTERON_CPU_REV_F)
                ? 19
                : 17;
 
-       if (pvt->dclr0 >> BIT(bit))
+       if (pvt->dclr0 & BIT(bit))
                edac_cap = EDAC_FLAG_SECDED;
 
        return edac_cap;
@@ -868,6 +868,8 @@ static void amd64_read_dbam_reg(struct amd64_pvt *pvt)
                        goto err_reg;
        }
 
+       return;
+
 err_reg:
        debugf0("Error reading F2x%03x.\n", reg);
 }
@@ -970,7 +972,7 @@ static void amd64_read_dct_base_mask(struct amd64_pvt *pvt)
        }
 
        for (cs = 0; cs < pvt->num_dcsm; cs++) {
-               reg = K8_DCSB0 + (cs * 4);
+               reg = K8_DCSM0 + (cs * 4);
                err = pci_read_config_dword(pvt->dram_f2_ctl, reg,
                                        &pvt->dcsm0[cs]);
                if (unlikely(err))
@@ -1269,7 +1271,7 @@ static int f10_early_channel_count(struct amd64_pvt *pvt)
        if (channels == 0)
                channels = 1;
 
-       debugf0("DIMM count= %d\n", channels);
+       debugf0("MCT channel count: %d\n", channels);
 
        return channels;
 
@@ -2634,6 +2636,8 @@ static void amd64_read_mc_registers(struct amd64_pvt *pvt)
 
        amd64_dump_misc_regs(pvt);
 
+       return;
+
 err_reg:
        debugf0("Reading an MC register failed\n");
 
@@ -2966,12 +2970,20 @@ static int amd64_check_ecc_enabled(struct amd64_pvt *pvt)
                                "    Use of the override can cause "
                                "unknown side effects.\n");
                        ret = -ENODEV;
-               }
+               } else
+                       /*
+                        * enable further driver loading if ECC enable is
+                        * overridden.
+                        */
+                       ret = 0;
        } else {
                amd64_printk(KERN_INFO,
                        "ECC is enabled by BIOS, Proceeding "
                        "with EDAC module initialization\n");
 
+               /* Signal good ECC status */
+               ret = 0;
+
                /* CLEAR the override, since BIOS controlled it */
                ecc_enable_override = 0;
        }
@@ -3006,7 +3018,6 @@ static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci)
 
        mci->mtype_cap          = MEM_FLAG_DDR2 | MEM_FLAG_RDDR2;
        mci->edac_ctl_cap       = EDAC_FLAG_NONE;
-       mci->edac_cap           = EDAC_FLAG_NONE;
 
        if (pvt->nbcap & K8_NBCAP_SECDED)
                mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
@@ -3052,7 +3063,7 @@ static int amd64_probe_one_instance(struct pci_dev *dram_f2_ctl,
        if (!pvt)
                goto err_exit;
 
-       pvt->mc_node_id = get_mc_node_id_from_pdev(dram_f2_ctl);
+       pvt->mc_node_id = get_node_id(dram_f2_ctl);
 
        pvt->dram_f2_ctl        = dram_f2_ctl;
        pvt->ext_model          = boot_cpu_data.x86_model >> 4;
@@ -3179,8 +3190,7 @@ static int __devinit amd64_init_one_instance(struct pci_dev *pdev,
 {
        int ret = 0;
 
-       debugf0("(MC node=%d,mc_type='%s')\n",
-               get_mc_node_id_from_pdev(pdev),
+       debugf0("(MC node=%d,mc_type='%s')\n", get_node_id(pdev),
                get_amd_family_name(mc_type->driver_data));
 
        ret = pci_enable_device(pdev);
@@ -3319,15 +3329,17 @@ static int __init amd64_edac_init(void)
 
                err = amd64_init_2nd_stage(pvt_lookup[nb]);
                if (err)
-                       goto err_exit;
+                       goto err_2nd_stage;
        }
 
        amd64_setup_pci_device();
 
        return 0;
 
+err_2nd_stage:
+       debugf0("2nd stage failed\n");
+
 err_exit:
-       debugf0("'finish_setup' stage failed\n");
        pci_unregister_driver(&amd64_pci_driver);
 
        return err;
index a159957e167b158e85ca3ebbced142d6690e2d53..ba73015af8e48d22307b3e9e22e47474a48cc3fa 100644 (file)
@@ -444,7 +444,7 @@ enum {
 #define K8_MSR_MC4ADDR                 0x0412
 
 /* AMD sets the first MC device at device ID 0x18. */
-static inline int get_mc_node_id_from_pdev(struct pci_dev *pdev)
+static inline int get_node_id(struct pci_dev *pdev)
 {
        return PCI_SLOT(pdev->devfn) - 0x18;
 }
index 3493c6bdb8206b7f712c00cf07b355974bdd27a2..871c13b4c1489587a91a12a9503aa73ff6dd1670 100644 (file)
@@ -150,6 +150,8 @@ enum mem_type {
        MEM_FB_DDR2,            /* fully buffered DDR2 */
        MEM_RDDR2,              /* Registered DDR2 RAM */
        MEM_XDR,                /* Rambus XDR */
+       MEM_DDR3,               /* DDR3 RAM */
+       MEM_RDDR3,              /* Registered DDR3 RAM */
 };
 
 #define MEM_FLAG_EMPTY         BIT(MEM_EMPTY)
@@ -167,6 +169,8 @@ enum mem_type {
 #define MEM_FLAG_FB_DDR2        BIT(MEM_FB_DDR2)
 #define MEM_FLAG_RDDR2          BIT(MEM_RDDR2)
 #define MEM_FLAG_XDR            BIT(MEM_XDR)
+#define MEM_FLAG_DDR3           BIT(MEM_DDR3)
+#define MEM_FLAG_RDDR3          BIT(MEM_RDDR3)
 
 /* chipset Error Detection and Correction capabilities and mode */
 enum edac_type {
index ad218fe4942dfcf258273ee22f56776f3a0b23c2..e1d4ce0834813b79ba347c8f78baeaa6616f8b4e 100644 (file)
@@ -94,7 +94,9 @@ static const char *mem_types[] = {
        [MEM_DDR2] = "Unbuffered-DDR2",
        [MEM_FB_DDR2] = "FullyBuffered-DDR2",
        [MEM_RDDR2] = "Registered-DDR2",
-       [MEM_XDR] = "XDR"
+       [MEM_XDR] = "XDR",
+       [MEM_DDR3] = "Unbuffered-DDR3",
+       [MEM_RDDR3] = "Registered-DDR3"
 };
 
 static const char *dev_types[] = {
index 7c8c2d72916f60f0ade44a323a7f01cc644e0d21..3f2ccfc6407c298be7be4260e5b09512590e0dfe 100644 (file)
@@ -757,6 +757,9 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci)
                case DSC_SDTYPE_DDR2:
                        mtype = MEM_RDDR2;
                        break;
+               case DSC_SDTYPE_DDR3:
+                       mtype = MEM_RDDR3;
+                       break;
                default:
                        mtype = MEM_UNKNOWN;
                        break;
@@ -769,6 +772,9 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci)
                case DSC_SDTYPE_DDR2:
                        mtype = MEM_DDR2;
                        break;
+               case DSC_SDTYPE_DDR3:
+                       mtype = MEM_DDR3;
+                       break;
                default:
                        mtype = MEM_UNKNOWN;
                        break;
index 135b3539a030d4cee2eca42217564bbf4b050476..52432ee7c4b98bf96a10e605116e04c00131481e 100644 (file)
@@ -53,6 +53,7 @@
 
 #define DSC_SDTYPE_DDR         0x02000000
 #define DSC_SDTYPE_DDR2                0x03000000
+#define DSC_SDTYPE_DDR3                0x07000000
 #define DSC_X32_EN     0x00000020
 
 /* Err_Int_En */
index 2406c2ce2844a235d181bb0c43be47fcd96dcd34..d4ec6059317604e40aae2e705b50f636dc26c4b9 100644 (file)
@@ -30,7 +30,7 @@
 /* Intel X38 register addresses - device 0 function 0 - DRAM Controller */
 
 #define X38_MCHBAR_LOW 0x48    /* MCH Memory Mapped Register BAR */
-#define X38_MCHBAR_HIGH        0x4b
+#define X38_MCHBAR_HIGH        0x4c
 #define X38_MCHBAR_MASK        0xfffffc000ULL  /* bits 35:14 */
 #define X38_MMR_WINDOW_SIZE    16384
 
index 543fccac81bb953aa38c60cebb764374602e2d4d..f74edae5cb4cfce68726102cca77711865003bc5 100644 (file)
@@ -196,8 +196,8 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation)
 {
        int channel, bandwidth = 0;
 
-       fw_iso_resource_manage(card, generation, 1ULL << 31,
-                              &channel, &bandwidth, true);
+       fw_iso_resource_manage(card, generation, 1ULL << 31, &channel,
+                              &bandwidth, true, card->bm_transaction_data);
        if (channel == 31) {
                card->broadcast_channel_allocated = true;
                device_for_each_child(card->device, (void *)(long)generation,
@@ -230,7 +230,6 @@ static void fw_card_bm_work(struct work_struct *work)
        bool do_reset = false;
        bool root_device_is_running;
        bool root_device_is_cmc;
-       __be32 lock_data[2];
 
        spin_lock_irqsave(&card->lock, flags);
 
@@ -273,22 +272,23 @@ static void fw_card_bm_work(struct work_struct *work)
                        goto pick_me;
                }
 
-               lock_data[0] = cpu_to_be32(0x3f);
-               lock_data[1] = cpu_to_be32(local_id);
+               card->bm_transaction_data[0] = cpu_to_be32(0x3f);
+               card->bm_transaction_data[1] = cpu_to_be32(local_id);
 
                spin_unlock_irqrestore(&card->lock, flags);
 
                rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
                                irm_id, generation, SCODE_100,
                                CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
-                               lock_data, sizeof(lock_data));
+                               card->bm_transaction_data,
+                               sizeof(card->bm_transaction_data));
 
                if (rcode == RCODE_GENERATION)
                        /* Another bus reset, BM work has been rescheduled. */
                        goto out;
 
                if (rcode == RCODE_COMPLETE &&
-                   lock_data[0] != cpu_to_be32(0x3f)) {
+                   card->bm_transaction_data[0] != cpu_to_be32(0x3f)) {
 
                        /* Somebody else is BM.  Only act as IRM. */
                        if (local_id == irm_id)
index d1d30c615b0f191c7fb33a313e64bfd37b2835d5..ced186d7e9a9d16552fcf3d73a95203303a8251a 100644 (file)
@@ -125,6 +125,7 @@ struct iso_resource {
        int generation;
        u64 channels;
        s32 bandwidth;
+       __be32 transaction_data[2];
        struct iso_resource_event *e_alloc, *e_dealloc;
 };
 
@@ -1049,7 +1050,8 @@ static void iso_resource_work(struct work_struct *work)
                        r->channels, &channel, &bandwidth,
                        todo == ISO_RES_ALLOC ||
                        todo == ISO_RES_REALLOC ||
-                       todo == ISO_RES_ALLOC_ONCE);
+                       todo == ISO_RES_ALLOC_ONCE,
+                       r->transaction_data);
        /*
         * Is this generation outdated already?  As long as this resource sticks
         * in the idr, it will be scheduled again for a newer generation or at
index 166f19c6d38d6dd86930751a9aefbac0ddb819cb..1c0b504a42f3068e852fa1b7423ee5c37bfb0abd 100644 (file)
@@ -177,9 +177,8 @@ EXPORT_SYMBOL(fw_iso_context_stop);
  */
 
 static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
-                           int bandwidth, bool allocate)
+                           int bandwidth, bool allocate, __be32 data[2])
 {
-       __be32 data[2];
        int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0;
 
        /*
@@ -197,7 +196,7 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
                switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
                                irm_id, generation, SCODE_100,
                                CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE,
-                               data, sizeof(data))) {
+                               data, 8)) {
                case RCODE_GENERATION:
                        /* A generation change frees all bandwidth. */
                        return allocate ? -EAGAIN : bandwidth;
@@ -215,9 +214,9 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
 }
 
 static int manage_channel(struct fw_card *card, int irm_id, int generation,
-                         u32 channels_mask, u64 offset, bool allocate)
+               u32 channels_mask, u64 offset, bool allocate, __be32 data[2])
 {
-       __be32 data[2], c, all, old;
+       __be32 c, all, old;
        int i, retry = 5;
 
        old = all = allocate ? cpu_to_be32(~0) : 0;
@@ -234,7 +233,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation,
                data[1] = old ^ c;
                switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
                                           irm_id, generation, SCODE_100,
-                                          offset, data, sizeof(data))) {
+                                          offset, data, 8)) {
                case RCODE_GENERATION:
                        /* A generation change frees all channels. */
                        return allocate ? -EAGAIN : i;
@@ -260,7 +259,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation,
 }
 
 static void deallocate_channel(struct fw_card *card, int irm_id,
-                              int generation, int channel)
+                              int generation, int channel, __be32 buffer[2])
 {
        u32 mask;
        u64 offset;
@@ -269,7 +268,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id,
        offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI :
                                CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO;
 
-       manage_channel(card, irm_id, generation, mask, offset, false);
+       manage_channel(card, irm_id, generation, mask, offset, false, buffer);
 }
 
 /**
@@ -298,7 +297,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id,
  */
 void fw_iso_resource_manage(struct fw_card *card, int generation,
                            u64 channels_mask, int *channel, int *bandwidth,
-                           bool allocate)
+                           bool allocate, __be32 buffer[2])
 {
        u32 channels_hi = channels_mask;        /* channels 31...0 */
        u32 channels_lo = channels_mask >> 32;  /* channels 63...32 */
@@ -310,10 +309,12 @@ void fw_iso_resource_manage(struct fw_card *card, int generation,
 
        if (channels_hi)
                c = manage_channel(card, irm_id, generation, channels_hi,
-                   CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, allocate);
+                               CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI,
+                               allocate, buffer);
        if (channels_lo && c < 0) {
                c = manage_channel(card, irm_id, generation, channels_lo,
-                   CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, allocate);
+                               CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO,
+                               allocate, buffer);
                if (c >= 0)
                        c += 32;
        }
@@ -325,12 +326,13 @@ void fw_iso_resource_manage(struct fw_card *card, int generation,
        if (*bandwidth == 0)
                return;
 
-       ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate);
+       ret = manage_bandwidth(card, irm_id, generation, *bandwidth,
+                              allocate, buffer);
        if (ret < 0)
                *bandwidth = 0;
 
        if (allocate && ret < 0 && c >= 0) {
-               deallocate_channel(card, irm_id, generation, c);
+               deallocate_channel(card, irm_id, generation, c, buffer);
                *channel = ret;
        }
 }
index c3cfc647e5e30dae6edfa9e38fae365d416184d3..6052816be353e899b540394afa05747f7dc1d2c0 100644 (file)
@@ -120,7 +120,8 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event);
 
 int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma);
 void fw_iso_resource_manage(struct fw_card *card, int generation,
-               u64 channels_mask, int *channel, int *bandwidth, bool allocate);
+                           u64 channels_mask, int *channel, int *bandwidth,
+                           bool allocate, __be32 buffer[2]);
 
 
 /* -topology */
index ecddd11b797a366d105763656dd4eda2c2273add..76b321bb73f9419aa52c826a944047388d53cd0a 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
+#include <linux/pci_ids.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
 
@@ -2372,6 +2373,9 @@ static void ohci_pmac_off(struct pci_dev *dev)
 #define ohci_pmac_off(dev)
 #endif /* CONFIG_PPC_PMAC */
 
+#define PCI_VENDOR_ID_AGERE            PCI_VENDOR_ID_ATT
+#define PCI_DEVICE_ID_AGERE_FW643      0x5901
+
 static int __devinit pci_probe(struct pci_dev *dev,
                               const struct pci_device_id *ent)
 {
@@ -2422,6 +2426,16 @@ static int __devinit pci_probe(struct pci_dev *dev,
        version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
        ohci->use_dualbuffer = version >= OHCI_VERSION_1_1;
 
+       /* dual-buffer mode is broken if more than one IR context is active */
+       if (dev->vendor == PCI_VENDOR_ID_AGERE &&
+           dev->device == PCI_DEVICE_ID_AGERE_FW643)
+               ohci->use_dualbuffer = false;
+
+       /* dual-buffer mode is broken */
+       if (dev->vendor == PCI_VENDOR_ID_RICOH &&
+           dev->device == PCI_DEVICE_ID_RICOH_R5C832)
+               ohci->use_dualbuffer = false;
+
 /* x86-32 currently doesn't use highmem for dma_alloc_coherent */
 #if !defined(CONFIG_X86_32)
        /* dual-buffer mode is broken with descriptor addresses above 2G */
index 24c45635376a746ba9ae3e69ef53cfa7da1ab514..e5df822a8130ca99730a009c75cf3ea454bfccab 100644 (file)
@@ -200,6 +200,12 @@ static struct fw_device *target_device(struct sbp2_target *tgt)
 #define SBP2_RETRY_LIMIT               0xf             /* 15 retries */
 #define SBP2_CYCLE_LIMIT               (0xc8 << 12)    /* 200 125us cycles */
 
+/*
+ * There is no transport protocol limit to the CDB length,  but we implement
+ * a fixed length only.  16 bytes is enough for disks larger than 2 TB.
+ */
+#define SBP2_MAX_CDB_SIZE              16
+
 /*
  * The default maximum s/g segment size of a FireWire controller is
  * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
@@ -312,7 +318,7 @@ struct sbp2_command_orb {
                struct sbp2_pointer next;
                struct sbp2_pointer data_descriptor;
                __be32 misc;
-               u8 command_block[12];
+               u8 command_block[SBP2_MAX_CDB_SIZE];
        } request;
        struct scsi_cmnd *cmd;
        scsi_done_fn_t done;
@@ -450,12 +456,12 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request,
        }
        spin_unlock_irqrestore(&card->lock, flags);
 
-       if (&orb->link != &lu->orb_list)
+       if (&orb->link != &lu->orb_list) {
                orb->callback(orb, &status);
-       else
+               kref_put(&orb->kref, free_orb);
+       } else {
                fw_error("status write for unknown orb\n");
-
-       kref_put(&orb->kref, free_orb);
+       }
 
        fw_send_response(card, request, RCODE_COMPLETE);
 }
@@ -1146,6 +1152,8 @@ static int sbp2_probe(struct device *dev)
        if (fw_device_enable_phys_dma(device) < 0)
                goto fail_shost_put;
 
+       shost->max_cmd_len = SBP2_MAX_CDB_SIZE;
+
        if (scsi_add_host(shost, &unit->device) < 0)
                goto fail_shost_put;
 
index 3582c39f97258ee7f9a95612816fa0f1c83bc467..96dda81c922855ecb564a232df184a5896f6ec99 100644 (file)
@@ -79,6 +79,12 @@ config GPIO_XILINX
        help
          Say yes here to support the Xilinx FPGA GPIO device
 
+config GPIO_VR41XX
+       tristate "NEC VR4100 series General-purpose I/O Uint support"
+       depends on CPU_VR41XX
+       help
+         Say yes here to support the NEC VR4100 series General-purpose I/O Uint
+
 comment "I2C GPIO expanders:"
 
 config GPIO_MAX732X
index ef90203e8f3c77df4c2f1b9cbe1433f50ce2b92a..9244c6fcd8be3e60a211609160c0f320726df594 100644 (file)
@@ -13,3 +13,4 @@ obj-$(CONFIG_GPIO_PL061)      += pl061.o
 obj-$(CONFIG_GPIO_TWL4030)     += twl4030-gpio.o
 obj-$(CONFIG_GPIO_XILINX)      += xilinx_gpio.o
 obj-$(CONFIG_GPIO_BT8XX)       += bt8xxgpio.o
+obj-$(CONFIG_GPIO_VR41XX)      += vr41xx_giu.o
index aa8e7cb020d93bf2e3d9b24a1a75bb1e0d8850aa..4ee4c8367a3f988144c7a721399a5d14306be50e 100644 (file)
@@ -109,6 +109,16 @@ static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
        writeb(!!value << offset, chip->base + (1 << (offset + 2)));
 }
 
+static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+       struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+
+       if (chip->irq_base == (unsigned) -1)
+               return -EINVAL;
+
+       return chip->irq_base + offset;
+}
+
 /*
  * PL061 GPIO IRQ
  */
@@ -200,7 +210,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
        desc->chip->ack(irq);
        list_for_each(ptr, chip_list) {
                unsigned long pending;
-               int gpio;
+               int offset;
 
                chip = list_entry(ptr, struct pl061_gpio, list);
                pending = readb(chip->base + GPIOMIS);
@@ -209,8 +219,8 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
                if (pending == 0)
                        continue;
 
-               for_each_bit(gpio, &pending, PL061_GPIO_NR)
-                       generic_handle_irq(gpio_to_irq(gpio));
+               for_each_bit(offset, &pending, PL061_GPIO_NR)
+                       generic_handle_irq(pl061_to_irq(&chip->gc, offset));
        }
        desc->chip->unmask(irq);
 }
@@ -221,7 +231,7 @@ static int __init pl061_probe(struct amba_device *dev, struct amba_id *id)
        struct pl061_gpio *chip;
        struct list_head *chip_list;
        int ret, irq, i;
-       static unsigned long init_irq[BITS_TO_LONGS(NR_IRQS)];
+       static DECLARE_BITMAP(init_irq, NR_IRQS);
 
        pdata = dev->dev.platform_data;
        if (pdata == NULL)
@@ -251,6 +261,7 @@ static int __init pl061_probe(struct amba_device *dev, struct amba_id *id)
        chip->gc.direction_output = pl061_direction_output;
        chip->gc.get = pl061_get_value;
        chip->gc.set = pl061_set_value;
+       chip->gc.to_irq = pl061_to_irq;
        chip->gc.base = pdata->gpio_base;
        chip->gc.ngpio = PL061_GPIO_NR;
        chip->gc.label = dev_name(&dev->dev);
@@ -280,6 +291,7 @@ static int __init pl061_probe(struct amba_device *dev, struct amba_id *id)
        if (!test_and_set_bit(irq, init_irq)) { /* list initialized? */
                chip_list = kmalloc(sizeof(*chip_list), GFP_KERNEL);
                if (chip_list == NULL) {
+                       clear_bit(irq, init_irq);
                        ret = -ENOMEM;
                        goto iounmap;
                }
similarity index 66%
rename from drivers/char/vr41xx_giu.c
rename to drivers/gpio/vr41xx_giu.c
index 54c837288d19453ff2baf3756d28b8cbc5b1092e..b16c9a8c03f5d10e5a2f691653fef4604ec5915d 100644 (file)
@@ -2,8 +2,8 @@
  *  Driver for NEC VR4100 series General-purpose I/O Unit.
  *
  *  Copyright (C) 2002 MontaVista Software Inc.
- *     Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2003-2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *     Author: Yoichi Yuasa <source@mvista.com>
+ *  Copyright (C) 2003-2009  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  */
 #include <linux/errno.h>
 #include <linux/fs.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
-#include <asm/io.h>
 #include <asm/vr41xx/giu.h>
 #include <asm/vr41xx/irq.h>
 #include <asm/vr41xx/vr41xx.h>
 
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
 MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
 MODULE_LICENSE("GPL");
 
-static int major;      /* default is dynamic major device number */
-module_param(major, int, 0);
-MODULE_PARM_DESC(major, "Major device number");
-
 #define GIUIOSELL      0x00
 #define GIUIOSELH      0x02
 #define GIUPIODL       0x04
@@ -76,9 +72,13 @@ MODULE_PARM_DESC(major, "Major device number");
 #define GPIO_HAS_OUTPUT_ENABLE         0x0002
 #define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
 
-static spinlock_t giu_lock;
+enum {
+       GPIO_INPUT,
+       GPIO_OUTPUT,
+};
+
+static DEFINE_SPINLOCK(giu_lock);
 static unsigned long giu_flags;
-static unsigned int giu_nr_pins;
 
 static void __iomem *giu_base;
 
@@ -89,9 +89,9 @@ static void __iomem *giu_base;
 #define GIUINT_HIGH_OFFSET     16
 #define GIUINT_HIGH_MAX                32
 
-static inline uint16_t giu_set(uint16_t offset, uint16_t set)
+static inline u16 giu_set(u16 offset, u16 set)
 {
-       uint16_t data;
+       u16 data;
 
        data = giu_read(offset);
        data |= set;
@@ -100,9 +100,9 @@ static inline uint16_t giu_set(uint16_t offset, uint16_t set)
        return data;
 }
 
-static inline uint16_t giu_clear(uint16_t offset, uint16_t clear)
+static inline u16 giu_clear(u16 offset, u16 clear)
 {
-       uint16_t data;
+       u16 data;
 
        data = giu_read(offset);
        data &= ~clear;
@@ -145,7 +145,8 @@ static struct irq_chip giuint_low_irq_chip = {
 
 static void ack_giuint_high(unsigned int irq)
 {
-       giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+       giu_write(GIUINTSTATH,
+                 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
 }
 
 static void mask_giuint_high(unsigned int irq)
@@ -177,7 +178,7 @@ static struct irq_chip giuint_high_irq_chip = {
 
 static int giu_get_irq(unsigned int irq)
 {
-       uint16_t pendl, pendh, maskl, maskh;
+       u16 pendl, pendh, maskl, maskh;
        int i;
 
        pendl = giu_read(GIUINTSTATL);
@@ -208,14 +209,15 @@ static int giu_get_irq(unsigned int irq)
        return -EINVAL;
 }
 
-void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal)
+void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger,
+                           irq_signal_t signal)
 {
-       uint16_t mask;
+       u16 mask;
 
        if (pin < GIUINT_HIGH_OFFSET) {
                mask = 1 << pin;
                if (trigger != IRQ_TRIGGER_LEVEL) {
-                       giu_set(GIUINTTYPL, mask);
+                       giu_set(GIUINTTYPL, mask);
                        if (signal == IRQ_SIGNAL_HOLD)
                                giu_set(GIUINTHTSELL, mask);
                        else
@@ -237,14 +239,14 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_
                                }
                        }
                        set_irq_chip_and_handler(GIU_IRQ(pin),
-                                                &giuint_low_irq_chip,
-                                                handle_edge_irq);
+                                                &giuint_low_irq_chip,
+                                                handle_edge_irq);
                } else {
                        giu_clear(GIUINTTYPL, mask);
                        giu_clear(GIUINTHTSELL, mask);
                        set_irq_chip_and_handler(GIU_IRQ(pin),
-                                                &giuint_low_irq_chip,
-                                                handle_level_irq);
+                                                &giuint_low_irq_chip,
+                                                handle_level_irq);
                }
                giu_write(GIUINTSTATL, mask);
        } else if (pin < GIUINT_HIGH_MAX) {
@@ -272,14 +274,14 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_
                                }
                        }
                        set_irq_chip_and_handler(GIU_IRQ(pin),
-                                                &giuint_high_irq_chip,
-                                                handle_edge_irq);
+                                                &giuint_high_irq_chip,
+                                                handle_edge_irq);
                } else {
                        giu_clear(GIUINTTYPH, mask);
                        giu_clear(GIUINTHTSELH, mask);
                        set_irq_chip_and_handler(GIU_IRQ(pin),
-                                                &giuint_high_irq_chip,
-                                                handle_level_irq);
+                                                &giuint_high_irq_chip,
+                                                handle_level_irq);
                }
                giu_write(GIUINTSTATH, mask);
        }
@@ -288,7 +290,7 @@ EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
 
 void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
 {
-       uint16_t mask;
+       u16 mask;
 
        if (pin < GIUINT_HIGH_OFFSET) {
                mask = 1 << pin;
@@ -308,89 +310,24 @@ void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
 }
 EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
 
-gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
-{
-       uint16_t reg, mask;
-
-       if (pin >= giu_nr_pins)
-               return GPIO_DATA_INVAL;
-
-       if (pin < 16) {
-               reg = giu_read(GIUPIODL);
-               mask = (uint16_t)1 << pin;
-       } else if (pin < 32) {
-               reg = giu_read(GIUPIODH);
-               mask = (uint16_t)1 << (pin - 16);
-       } else if (pin < 48) {
-               reg = giu_read(GIUPODATL);
-               mask = (uint16_t)1 << (pin - 32);
-       } else {
-               reg = giu_read(GIUPODATH);
-               mask = (uint16_t)1 << (pin - 48);
-       }
-
-       if (reg & mask)
-               return GPIO_DATA_HIGH;
-
-       return GPIO_DATA_LOW;
-}
-EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);
-
-int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
-{
-       uint16_t offset, mask, reg;
-       unsigned long flags;
-
-       if (pin >= giu_nr_pins)
-               return -EINVAL;
-
-       if (pin < 16) {
-               offset = GIUPIODL;
-               mask = (uint16_t)1 << pin;
-       } else if (pin < 32) {
-               offset = GIUPIODH;
-               mask = (uint16_t)1 << (pin - 16);
-       } else if (pin < 48) {
-               offset = GIUPODATL;
-               mask = (uint16_t)1 << (pin - 32);
-       } else {
-               offset = GIUPODATH;
-               mask = (uint16_t)1 << (pin - 48);
-       }
-
-       spin_lock_irqsave(&giu_lock, flags);
-
-       reg = giu_read(offset);
-       if (data == GPIO_DATA_HIGH)
-               reg |= mask;
-       else
-               reg &= ~mask;
-       giu_write(offset, reg);
-
-       spin_unlock_irqrestore(&giu_lock, flags);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);
-
-int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
+static int giu_set_direction(struct gpio_chip *chip, unsigned pin, int dir)
 {
-       uint16_t offset, mask, reg;
+       u16 offset, mask, reg;
        unsigned long flags;
 
-       if (pin >= giu_nr_pins)
+       if (pin >= chip->ngpio)
                return -EINVAL;
 
        if (pin < 16) {
                offset = GIUIOSELL;
-               mask = (uint16_t)1 << pin;
+               mask = 1 << pin;
        } else if (pin < 32) {
                offset = GIUIOSELH;
-               mask = (uint16_t)1 << (pin - 16);
+               mask = 1 << (pin - 16);
        } else {
                if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
                        offset = GIUPODATEN;
-                       mask = (uint16_t)1 << (pin - 32);
+                       mask = 1 << (pin - 32);
                } else {
                        switch (pin) {
                        case 48:
@@ -420,11 +357,10 @@ int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);
 
 int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
 {
-       uint16_t reg, mask;
+       u16 reg, mask;
        unsigned long flags;
 
        if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
@@ -433,7 +369,7 @@ int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
        if (pin >= 15)
                return -EINVAL;
 
-       mask = (uint16_t)1 << pin;
+       mask = 1 << pin;
 
        spin_lock_irqsave(&giu_lock, flags);
 
@@ -460,146 +396,125 @@ int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
 }
 EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
 
-static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
-                         loff_t *ppos)
+static int vr41xx_gpio_get(struct gpio_chip *chip, unsigned pin)
 {
-       unsigned int pin;
-       char value = '0';
+       u16 reg, mask;
 
-       pin = iminor(file->f_path.dentry->d_inode);
-       if (pin >= giu_nr_pins)
-               return -EBADF;
-
-       if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH)
-               value = '1';
+       if (pin >= chip->ngpio)
+               return -EINVAL;
 
-       if (len <= 0)
-               return -EFAULT;
+       if (pin < 16) {
+               reg = giu_read(GIUPIODL);
+               mask = 1 << pin;
+       } else if (pin < 32) {
+               reg = giu_read(GIUPIODH);
+               mask = 1 << (pin - 16);
+       } else if (pin < 48) {
+               reg = giu_read(GIUPODATL);
+               mask = 1 << (pin - 32);
+       } else {
+               reg = giu_read(GIUPODATH);
+               mask = 1 << (pin - 48);
+       }
 
-       if (put_user(value, buf))
-               return -EFAULT;
+       if (reg & mask)
+               return 1;
 
-       return 1;
+       return 0;
 }
 
-static ssize_t gpio_write(struct file *file, const char __user *data,
-                          size_t len, loff_t *ppos)
+static void vr41xx_gpio_set(struct gpio_chip *chip, unsigned pin,
+                           int value)
 {
-       unsigned int pin;
-       size_t i;
-       char c;
-       int retval = 0;
-
-       pin = iminor(file->f_path.dentry->d_inode);
-       if (pin >= giu_nr_pins)
-               return -EBADF;
-
-       for (i = 0; i < len; i++) {
-               if (get_user(c, data + i))
-                       return -EFAULT;
-
-               switch (c) {
-               case '0':
-                       retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW);
-                       break;
-               case '1':
-                       retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH);
-                       break;
-               case 'D':
-                       printk(KERN_INFO "GPIO%d: pull down\n", pin);
-                       retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN);
-                       break;
-               case 'd':
-                       printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
-                       retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
-                       break;
-               case 'I':
-                       printk(KERN_INFO "GPIO%d: input\n", pin);
-                       retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT);
-                       break;
-               case 'O':
-                       printk(KERN_INFO "GPIO%d: output\n", pin);
-                       retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT);
-                       break;
-               case 'o':
-                       printk(KERN_INFO "GPIO%d: output disable\n", pin);
-                       retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE);
-                       break;
-               case 'P':
-                       printk(KERN_INFO "GPIO%d: pull up\n", pin);
-                       retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP);
-                       break;
-               case 'p':
-                       printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
-                       retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
-                       break;
-               default:
-                       break;
-               }
+       u16 offset, mask, reg;
+       unsigned long flags;
+
+       if (pin >= chip->ngpio)
+               return;
 
-               if (retval < 0)
-                       break;
+       if (pin < 16) {
+               offset = GIUPIODL;
+               mask = 1 << pin;
+       } else if (pin < 32) {
+               offset = GIUPIODH;
+               mask = 1 << (pin - 16);
+       } else if (pin < 48) {
+               offset = GIUPODATL;
+               mask = 1 << (pin - 32);
+       } else {
+               offset = GIUPODATH;
+               mask = 1 << (pin - 48);
        }
 
-       return i;
+       spin_lock_irqsave(&giu_lock, flags);
+
+       reg = giu_read(offset);
+       if (value)
+               reg |= mask;
+       else
+               reg &= ~mask;
+       giu_write(offset, reg);
+
+       spin_unlock_irqrestore(&giu_lock, flags);
 }
 
-static int gpio_open(struct inode *inode, struct file *file)
+
+static int vr41xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 {
-       unsigned int pin;
+       return giu_set_direction(chip, offset, GPIO_INPUT);
+}
 
-       cycle_kernel_lock();
-       pin = iminor(inode);
-       if (pin >= giu_nr_pins)
-               return -EBADF;
+static int vr41xx_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                               int value)
+{
+       vr41xx_gpio_set(chip, offset, value);
 
-       return nonseekable_open(inode, file);
+       return giu_set_direction(chip, offset, GPIO_OUTPUT);
 }
 
-static int gpio_release(struct inode *inode, struct file *file)
+static int vr41xx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
-       unsigned int pin;
-
-       pin = iminor(inode);
-       if (pin >= giu_nr_pins)
-               return -EBADF;
+       if (offset >= chip->ngpio)
+               return -EINVAL;
 
-       return 0;
+       return GIU_IRQ_BASE + offset;
 }
 
-static const struct file_operations gpio_fops = {
-       .owner          = THIS_MODULE,
-       .read           = gpio_read,
-       .write          = gpio_write,
-       .open           = gpio_open,
-       .release        = gpio_release,
+static struct gpio_chip vr41xx_gpio_chip = {
+       .label                  = "vr41xx",
+       .owner                  = THIS_MODULE,
+       .direction_input        = vr41xx_gpio_direction_input,
+       .get                    = vr41xx_gpio_get,
+       .direction_output       = vr41xx_gpio_direction_output,
+       .set                    = vr41xx_gpio_set,
+       .to_irq                 = vr41xx_gpio_to_irq,
 };
 
-static int __devinit giu_probe(struct platform_device *dev)
+static int __devinit giu_probe(struct platform_device *pdev)
 {
        struct resource *res;
        unsigned int trigger, i, pin;
        struct irq_chip *chip;
        int irq, retval;
 
-       switch (dev->id) {
+       switch (pdev->id) {
        case GPIO_50PINS_PULLUPDOWN:
                giu_flags = GPIO_HAS_PULLUPDOWN_IO;
-               giu_nr_pins = 50;
+               vr41xx_gpio_chip.ngpio = 50;
                break;
        case GPIO_36PINS:
-               giu_nr_pins = 36;
+               vr41xx_gpio_chip.ngpio = 36;
                break;
        case GPIO_48PINS_EDGE_SELECT:
                giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
-               giu_nr_pins = 48;
+               vr41xx_gpio_chip.ngpio = 48;
                break;
        default:
-               printk(KERN_ERR "GIU: unknown ID %d\n", dev->id);
+               dev_err(&pdev->dev, "GIU: unknown ID %d\n", pdev->id);
                return -ENODEV;
        }
 
-       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
                return -EBUSY;
 
@@ -607,19 +522,9 @@ static int __devinit giu_probe(struct platform_device *dev)
        if (!giu_base)
                return -ENOMEM;
 
-       retval = register_chrdev(major, "GIU", &gpio_fops);
-       if (retval < 0) {
-               iounmap(giu_base);
-               giu_base = NULL;
-               return retval;
-       }
-
-       if (major == 0) {
-               major = retval;
-               printk(KERN_INFO "GIU: major number %d\n", major);
-       }
+       vr41xx_gpio_chip.dev = &pdev->dev;
 
-       spin_lock_init(&giu_lock);
+       retval = gpiochip_add(&vr41xx_gpio_chip);
 
        giu_write(GIUINTENL, 0);
        giu_write(GIUINTENH, 0);
@@ -640,14 +545,14 @@ static int __devinit giu_probe(struct platform_device *dev)
 
        }
 
-       irq = platform_get_irq(dev, 0);
+       irq = platform_get_irq(pdev, 0);
        if (irq < 0 || irq >= nr_irqs)
                return -EBUSY;
 
        return cascade_irq(irq, giu_get_irq);
 }
 
-static int __devexit giu_remove(struct platform_device *dev)
+static int __devexit giu_remove(struct platform_device *pdev)
 {
        if (giu_base) {
                iounmap(giu_base);
index c961fe415aef83bfecda56873b59431601674bce..39b393d38bb3e6f9a7ba3c016265f213858ed612 100644 (file)
@@ -81,6 +81,7 @@ config DRM_I830
 
 config DRM_I915
        tristate "i915 driver"
+       depends on AGP_INTEL
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
index 4e89ab08b7b8d9eecf6fccc6e16901f5e41f4ed9..fe23f29f7cba8bc7fb3e88450b07c2b8537a7913 100644 (file)
@@ -16,6 +16,7 @@ drm-y       :=        drm_auth.o drm_bufs.o drm_cache.o \
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 
 obj-$(CONFIG_DRM)      += drm.o
+obj-$(CONFIG_DRM_TTM)  += ttm/
 obj-$(CONFIG_DRM_TDFX) += tdfx/
 obj-$(CONFIG_DRM_R128) += r128/
 obj-$(CONFIG_DRM_RADEON)+= radeon/
@@ -26,4 +27,3 @@ obj-$(CONFIG_DRM_I915)  += i915/
 obj-$(CONFIG_DRM_SIS)   += sis/
 obj-$(CONFIG_DRM_SAVAGE)+= savage/
 obj-$(CONFIG_DRM_VIA)  +=via/
-obj-$(CONFIG_DRM_TTM)  += ttm/
index 8fab7890a363e6109a540bf5a98b08e9dae8fd1d..2f631c75f704214ef6227e07581efb409b46753d 100644 (file)
@@ -257,31 +257,6 @@ void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type)
 }
 EXPORT_SYMBOL(drm_mode_object_find);
 
-/**
- * drm_crtc_from_fb - find the CRTC structure associated with an fb
- * @dev: DRM device
- * @fb: framebuffer in question
- *
- * LOCKING:
- * Caller must hold mode_config lock.
- *
- * Find CRTC in the mode_config structure that matches @fb.
- *
- * RETURNS:
- * Pointer to the CRTC or NULL if it wasn't found.
- */
-struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev,
-                                 struct drm_framebuffer *fb)
-{
-       struct drm_crtc *crtc;
-
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               if (crtc->fb == fb)
-                       return crtc;
-       }
-       return NULL;
-}
-
 /**
  * drm_framebuffer_init - initialize a framebuffer
  * @dev: DRM device
@@ -328,11 +303,20 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
 {
        struct drm_device *dev = fb->dev;
        struct drm_crtc *crtc;
+       struct drm_mode_set set;
+       int ret;
 
        /* remove from any CRTC */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               if (crtc->fb == fb)
-                       crtc->fb = NULL;
+               if (crtc->fb == fb) {
+                       /* should turn off the crtc */
+                       memset(&set, 0, sizeof(struct drm_mode_set));
+                       set.crtc = crtc;
+                       set.fb = NULL;
+                       ret = crtc->funcs->set_config(&set);
+                       if (ret)
+                               DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
+               }
        }
 
        drm_mode_object_put(dev, &fb->base);
@@ -1461,7 +1445,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
                goto out;
        }
 
-       if (crtc_req->count_connectors > 0 && !mode && !fb) {
+       if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
                DRM_DEBUG("Count connectors is %d but no mode or fb set\n",
                          crtc_req->count_connectors);
                ret = -EINVAL;
@@ -1511,7 +1495,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
        set.mode = mode;
        set.connectors = connector_set;
        set.num_connectors = crtc_req->count_connectors;
-       set.fb =fb;
+       set.fb = fb;
        ret = crtc->funcs->set_config(&set);
 
 out:
index a6f73f1e99d9b839e369861c5b24e4f17279b8aa..6aaa2cb23365765ed594ec8b717734aaccca399a 100644 (file)
@@ -706,8 +706,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
        struct drm_encoder **save_encoders, *new_encoder;
        struct drm_framebuffer *old_fb = NULL;
        bool save_enabled;
-       bool mode_changed = false;
-       bool fb_changed = false;
+       bool mode_changed = false; /* if true do a full mode set */
+       bool fb_changed = false; /* if true and !mode_changed just do a flip */
        struct drm_connector *connector;
        int count = 0, ro, fail = 0;
        struct drm_crtc_helper_funcs *crtc_funcs;
@@ -758,6 +758,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                if (set->crtc->fb == NULL) {
                        DRM_DEBUG("crtc has no fb, full mode set\n");
                        mode_changed = true;
+               } else if (set->fb == NULL) {
+                       mode_changed = true;
                } else if ((set->fb->bits_per_pixel !=
                         set->crtc->fb->bits_per_pixel) ||
                         set->fb->depth != set->crtc->fb->depth)
@@ -1090,6 +1092,8 @@ int drm_helper_resume_force_mode(struct drm_device *dev)
                if (ret == false)
                        DRM_ERROR("failed to set mode on crtc %p\n", crtc);
        }
+       /* disable the unused connectors while restoring the modesetting */
+       drm_helper_disable_unused_functions(dev);
        return 0;
 }
 EXPORT_SYMBOL(drm_helper_resume_force_mode);
index 2960b6d73456d65b672ad4a7b715976113002859..9903f270e4409c8239add50adc2a3db80ca56623 100644 (file)
@@ -101,6 +101,10 @@ int drm_debugfs_create_files(struct drm_info_list *files, int count,
                        continue;
 
                tmp = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
+               if (tmp == NULL) {
+                       ret = -1;
+                       goto fail;
+               }
                ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO,
                                          root, tmp, &drm_debugfs_fops);
                if (!ent) {
index 7d0835226f6edece18d91ebd1c5cfa95de5b1546..7f2728bbc16c7078e7e249d54f68743c228d4f55 100644 (file)
@@ -294,10 +294,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
        unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo;
        unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo;
        unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo;
-       unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 8 | pt->hsync_offset_lo;
-       unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 6 | pt->hsync_pulse_width_lo;
-       unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) | (pt->vsync_offset_pulse_width_lo & 0xf);
-       unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) >> 2 | pt->vsync_offset_pulse_width_lo >> 4;
+       unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo;
+       unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo;
+       unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4;
+       unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf);
 
        /* ignore tiny modes */
        if (hactive < 64 || vactive < 64)
@@ -347,8 +347,8 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
        mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
                DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
 
-       mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf) << 8;
-       mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
+       mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
+       mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8;
 
        if (quirks & EDID_QUIRK_DETAILED_IN_CM) {
                mode->width_mm *= 10;
@@ -502,12 +502,40 @@ static int add_detailed_info(struct drm_connector *connector,
                struct detailed_non_pixel *data = &timing->data.other_data;
                struct drm_display_mode *newmode;
 
-               /* EDID up to and including 1.2 may put monitor info here */
-               if (edid->version == 1 && edid->revision < 3)
-                       continue;
-
-               /* Detailed mode timing */
-               if (timing->pixel_clock) {
+               /* X server check is version 1.1 or higher */
+               if (edid->version == 1 && edid->revision >= 1 &&
+                   !timing->pixel_clock) {
+                       /* Other timing or info */
+                       switch (data->type) {
+                       case EDID_DETAIL_MONITOR_SERIAL:
+                               break;
+                       case EDID_DETAIL_MONITOR_STRING:
+                               break;
+                       case EDID_DETAIL_MONITOR_RANGE:
+                               /* Get monitor range data */
+                               break;
+                       case EDID_DETAIL_MONITOR_NAME:
+                               break;
+                       case EDID_DETAIL_MONITOR_CPDATA:
+                               break;
+                       case EDID_DETAIL_STD_MODES:
+                               /* Five modes per detailed section */
+                               for (j = 0; j < 5; i++) {
+                                       struct std_timing *std;
+                                       struct drm_display_mode *newmode;
+
+                                       std = &data->data.timings[j];
+                                       newmode = drm_mode_std(dev, std);
+                                       if (newmode) {
+                                               drm_mode_probed_add(connector, newmode);
+                                               modes++;
+                                       }
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+               } else {
                        newmode = drm_mode_detailed(dev, edid, timing, quirks);
                        if (!newmode)
                                continue;
@@ -518,38 +546,6 @@ static int add_detailed_info(struct drm_connector *connector,
                        drm_mode_probed_add(connector, newmode);
 
                        modes++;
-                       continue;
-               }
-
-               /* Other timing or info */
-               switch (data->type) {
-               case EDID_DETAIL_MONITOR_SERIAL:
-                       break;
-               case EDID_DETAIL_MONITOR_STRING:
-                       break;
-               case EDID_DETAIL_MONITOR_RANGE:
-                       /* Get monitor range data */
-                       break;
-               case EDID_DETAIL_MONITOR_NAME:
-                       break;
-               case EDID_DETAIL_MONITOR_CPDATA:
-                       break;
-               case EDID_DETAIL_STD_MODES:
-                       /* Five modes per detailed section */
-                       for (j = 0; j < 5; i++) {
-                               struct std_timing *std;
-                               struct drm_display_mode *newmode;
-
-                               std = &data->data.timings[j];
-                               newmode = drm_mode_std(dev, std);
-                               if (newmode) {
-                                       drm_mode_probed_add(connector, newmode);
-                                       modes++;
-                               }
-                       }
-                       break;
-               default:
-                       break;
                }
        }
 
index 8104ecaea26fbe7170d4c85b41ee0a96e6a0bec4..ffe8f4394d50d71f96411200d9d4d90907bd5f2c 100644 (file)
@@ -134,26 +134,29 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
        BUG_ON((size & (PAGE_SIZE - 1)) != 0);
 
        obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+       if (!obj)
+               goto free;
 
        obj->dev = dev;
        obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
-       if (IS_ERR(obj->filp)) {
-               kfree(obj);
-               return NULL;
-       }
+       if (IS_ERR(obj->filp))
+               goto free;
 
        kref_init(&obj->refcount);
        kref_init(&obj->handlecount);
        obj->size = size;
        if (dev->driver->gem_init_object != NULL &&
            dev->driver->gem_init_object(obj) != 0) {
-               fput(obj->filp);
-               kfree(obj);
-               return NULL;
+               goto fput;
        }
        atomic_inc(&dev->object_count);
        atomic_add(obj->size, &dev->object_memory);
        return obj;
+fput:
+       fput(obj->filp);
+free:
+       kfree(obj);
+       return NULL;
 }
 EXPORT_SYMBOL(drm_gem_object_alloc);
 
index b4a3dbcebe9b415d8e27f8ef1c0a8c88a17e6f7f..f85aaf21e7839b65f821d903a556ef38661cc6e8 100644 (file)
@@ -566,7 +566,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
 
        ret = drm_vblank_get(dev, crtc);
        if (ret) {
-               DRM_ERROR("failed to acquire vblank counter, %d\n", ret);
+               DRM_DEBUG("failed to acquire vblank counter, %d\n", ret);
                return ret;
        }
        seq = drm_vblank_count(dev, crtc);
index 54f492a488a93c68387bc388a6579c92edb7f988..7914097b09c61b5cad674dfdf7c98dc485fd82f2 100644 (file)
@@ -566,6 +566,8 @@ void drm_mode_connector_list_update(struct drm_connector *connector)
                                found_it = 1;
                                /* if equal delete the probed mode */
                                mode->status = pmode->status;
+                               /* Merge type bits together */
+                               mode->type |= pmode->type;
                                list_del(&pmode->head);
                                drm_mode_destroy(connector->dev, pmode);
                                break;
index 155a5bbce680ac4187f297699644a29317a188e6..55bb8a82d6127cb5d1ec3bea675e0001de593122 100644 (file)
@@ -489,7 +489,7 @@ int drm_put_minor(struct drm_minor **minor_p)
  */
 void drm_put_dev(struct drm_device *dev)
 {
-       struct drm_driver *driver = dev->driver;
+       struct drm_driver *driver;
        struct drm_map_list *r_list, *list_temp;
 
        DRM_DEBUG("\n");
@@ -498,6 +498,7 @@ void drm_put_dev(struct drm_device *dev)
                DRM_ERROR("cleanup called no dev\n");
                return;
        }
+       driver = dev->driver;
 
        drm_vblank_cleanup(dev);
 
index 85ec31b3ff00a09f1d18b0a9b66cd31b68d8ba21..f7a615b80c706a3094bb94f5f9981f1a0e5016ae 100644 (file)
 #define to_drm_minor(d) container_of(d, struct drm_minor, kdev)
 #define to_drm_connector(d) container_of(d, struct drm_connector, kdev)
 
+static struct device_type drm_sysfs_device_minor = {
+       .name = "drm_minor"
+};
+
 /**
- * drm_sysfs_suspend - DRM class suspend hook
+ * drm_class_suspend - DRM class suspend hook
  * @dev: Linux device to suspend
  * @state: power state to enter
  *
  * Just figures out what the actual struct drm_device associated with
  * @dev is and calls its suspend hook, if present.
  */
-static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
+static int drm_class_suspend(struct device *dev, pm_message_t state)
 {
-       struct drm_minor *drm_minor = to_drm_minor(dev);
-       struct drm_device *drm_dev = drm_minor->dev;
-
-       if (drm_minor->type == DRM_MINOR_LEGACY &&
-           !drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
-           drm_dev->driver->suspend)
-               return drm_dev->driver->suspend(drm_dev, state);
-
+       if (dev->type == &drm_sysfs_device_minor) {
+               struct drm_minor *drm_minor = to_drm_minor(dev);
+               struct drm_device *drm_dev = drm_minor->dev;
+
+               if (drm_minor->type == DRM_MINOR_LEGACY &&
+                   !drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
+                   drm_dev->driver->suspend)
+                       return drm_dev->driver->suspend(drm_dev, state);
+       }
        return 0;
 }
 
 /**
- * drm_sysfs_resume - DRM class resume hook
+ * drm_class_resume - DRM class resume hook
  * @dev: Linux device to resume
  *
  * Just figures out what the actual struct drm_device associated with
  * @dev is and calls its resume hook, if present.
  */
-static int drm_sysfs_resume(struct device *dev)
+static int drm_class_resume(struct device *dev)
 {
-       struct drm_minor *drm_minor = to_drm_minor(dev);
-       struct drm_device *drm_dev = drm_minor->dev;
-
-       if (drm_minor->type == DRM_MINOR_LEGACY &&
-           !drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
-           drm_dev->driver->resume)
-               return drm_dev->driver->resume(drm_dev);
-
+       if (dev->type == &drm_sysfs_device_minor) {
+               struct drm_minor *drm_minor = to_drm_minor(dev);
+               struct drm_device *drm_dev = drm_minor->dev;
+
+               if (drm_minor->type == DRM_MINOR_LEGACY &&
+                   !drm_core_check_feature(drm_dev, DRIVER_MODESET) &&
+                   drm_dev->driver->resume)
+                       return drm_dev->driver->resume(drm_dev);
+       }
        return 0;
 }
 
@@ -99,8 +105,8 @@ struct class *drm_sysfs_create(struct module *owner, char *name)
                goto err_out;
        }
 
-       class->suspend = drm_sysfs_suspend;
-       class->resume = drm_sysfs_resume;
+       class->suspend = drm_class_suspend;
+       class->resume = drm_class_resume;
 
        err = class_create_file(class, &class_attr_version);
        if (err)
@@ -480,6 +486,7 @@ int drm_sysfs_device_add(struct drm_minor *minor)
        minor->kdev.class = drm_class;
        minor->kdev.release = drm_sysfs_device_release;
        minor->kdev.devt = minor->device;
+       minor->kdev.type = &drm_sysfs_device_minor;
        if (minor->type == DRM_MINOR_CONTROL)
                minor_str = "controlD%d";
         else if (minor->type == DRM_MINOR_RENDER)
index 51c5a050aa730ee2b1f841d2a413c6e77c31833d..30d6b99fb302908d4aaadd03edef03ba1266f733 100644 (file)
@@ -13,6 +13,8 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \
          intel_crt.o \
          intel_lvds.o \
          intel_bios.o \
+         intel_dp.o \
+         intel_dp_i2c.o \
          intel_hdmi.o \
          intel_sdvo.o \
          intel_modes.o \
index e747ac42fe3a9b117ca8e99235fccad7d925a40d..288fc50627e2de2f795854b2ec965a3ebc19a8c5 100644 (file)
@@ -37,7 +37,7 @@ struct intel_dvo_device {
        /* GPIO register used for i2c bus to control this device */
        u32 gpio;
        int slave_addr;
-       struct intel_i2c_chan *i2c_bus;
+       struct i2c_adapter *i2c_bus;
 
        const struct intel_dvo_dev_ops *dev_ops;
        void *dev_priv;
@@ -52,7 +52,7 @@ struct intel_dvo_dev_ops {
         * Returns NULL if the device does not exist.
         */
        bool (*init)(struct intel_dvo_device *dvo,
-                    struct intel_i2c_chan *i2cbus);
+                    struct i2c_adapter *i2cbus);
 
        /*
         * Called to allow the output a chance to create properties after the
index 03d4b4973b02e1c30262efd0a0061ca84198f05f..621815b531dbba427b87e1290589a7de6a94fd6b 100644 (file)
@@ -176,19 +176,20 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, int mode);
 
 static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val)
 {
-       struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+       struct i2c_adapter *adapter = dvo->i2c_bus;
+       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        u8 out_buf[2];
        u8 in_buf[2];
 
        struct i2c_msg msgs[] = {
                {
-                       .addr = i2cbus->slave_addr,
+                       .addr = dvo->slave_addr,
                        .flags = 0,
                        .len = 1,
                        .buf = out_buf,
                },
                {
-                       .addr = i2cbus->slave_addr,
+                       .addr = dvo->slave_addr,
                        .flags = I2C_M_RD,
                        .len = 1,
                        .buf = in_buf,
@@ -208,10 +209,11 @@ static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val)
 
 static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val)
 {
-       struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+       struct i2c_adapter *adapter = dvo->i2c_bus;
+       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        uint8_t out_buf[2];
        struct i2c_msg msg = {
-               .addr = i2cbus->slave_addr,
+               .addr = dvo->slave_addr,
                .flags = 0,
                .len = 2,
                .buf = out_buf,
@@ -228,8 +230,9 @@ static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val)
 
 /** Probes for a CH7017 on the given bus and slave address. */
 static bool ch7017_init(struct intel_dvo_device *dvo,
-                       struct intel_i2c_chan *i2cbus)
+                       struct i2c_adapter *adapter)
 {
+       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        struct ch7017_priv *priv;
        uint8_t val;
 
@@ -237,8 +240,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo,
        if (priv == NULL)
                return false;
 
-       dvo->i2c_bus = i2cbus;
-       dvo->i2c_bus->slave_addr = dvo->slave_addr;
+       dvo->i2c_bus = adapter;
        dvo->dev_priv = priv;
 
        if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val))
@@ -248,7 +250,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo,
            val != CH7018_DEVICE_ID_VALUE &&
            val != CH7019_DEVICE_ID_VALUE) {
                DRM_DEBUG("ch701x not detected, got %d: from %s Slave %d.\n",
-                         val, i2cbus->adapter.name,i2cbus->slave_addr);
+                         val, i2cbus->adapter.name,dvo->slave_addr);
                goto fail;
        }
 
index d2fd95dbd034b948d180a95129b09817da8314da..a9b8962896801ffe674bafe06685e9e40f846036 100644 (file)
@@ -123,19 +123,20 @@ static char *ch7xxx_get_id(uint8_t vid)
 static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 {
        struct ch7xxx_priv *ch7xxx= dvo->dev_priv;
-       struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+       struct i2c_adapter *adapter = dvo->i2c_bus;
+       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        u8 out_buf[2];
        u8 in_buf[2];
 
        struct i2c_msg msgs[] = {
                {
-                       .addr = i2cbus->slave_addr,
+                       .addr = dvo->slave_addr,
                        .flags = 0,
                        .len = 1,
                        .buf = out_buf,
                },
                {
-                       .addr = i2cbus->slave_addr,
+                       .addr = dvo->slave_addr,
                        .flags = I2C_M_RD,
                        .len = 1,
                        .buf = in_buf,
@@ -152,7 +153,7 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 
        if (!ch7xxx->quiet) {
                DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
-                         addr, i2cbus->adapter.name, i2cbus->slave_addr);
+                         addr, i2cbus->adapter.name, dvo->slave_addr);
        }
        return false;
 }
@@ -161,10 +162,11 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 {
        struct ch7xxx_priv *ch7xxx = dvo->dev_priv;
-       struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+       struct i2c_adapter *adapter = dvo->i2c_bus;
+       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        uint8_t out_buf[2];
        struct i2c_msg msg = {
-               .addr = i2cbus->slave_addr,
+               .addr = dvo->slave_addr,
                .flags = 0,
                .len = 2,
                .buf = out_buf,
@@ -178,14 +180,14 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 
        if (!ch7xxx->quiet) {
                DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
-                         addr, i2cbus->adapter.name, i2cbus->slave_addr);
+                         addr, i2cbus->adapter.name, dvo->slave_addr);
        }
 
        return false;
 }
 
 static bool ch7xxx_init(struct intel_dvo_device *dvo,
-                       struct intel_i2c_chan *i2cbus)
+                       struct i2c_adapter *adapter)
 {
        /* this will detect the CH7xxx chip on the specified i2c bus */
        struct ch7xxx_priv *ch7xxx;
@@ -196,8 +198,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo,
        if (ch7xxx == NULL)
                return false;
 
-       dvo->i2c_bus = i2cbus;
-       dvo->i2c_bus->slave_addr = dvo->slave_addr;
+       dvo->i2c_bus = adapter;
        dvo->dev_priv = ch7xxx;
        ch7xxx->quiet = true;
 
@@ -207,7 +208,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo,
        name = ch7xxx_get_id(vendor);
        if (!name) {
                DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n",
-                         vendor, i2cbus->adapter.name, i2cbus->slave_addr);
+                         vendor, adapter->name, dvo->slave_addr);
                goto out;
        }
 
@@ -217,7 +218,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo,
 
        if (device != CH7xxx_DID) {
                DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n",
-                         vendor, i2cbus->adapter.name, i2cbus->slave_addr);
+                         vendor, adapter->name, dvo->slave_addr);
                goto out;
        }
 
index 0c8d375e8e378e523c46ca62bf5ab6564a803b16..aa176f9921fe2c772ade093f67d970647b175f34 100644 (file)
@@ -169,13 +169,14 @@ static void ivch_dump_regs(struct intel_dvo_device *dvo);
 static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
 {
        struct ivch_priv *priv = dvo->dev_priv;
-       struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+       struct i2c_adapter *adapter = dvo->i2c_bus;
+       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        u8 out_buf[1];
        u8 in_buf[2];
 
        struct i2c_msg msgs[] = {
                {
-                       .addr = i2cbus->slave_addr,
+                       .addr = dvo->slave_addr,
                        .flags = I2C_M_RD,
                        .len = 0,
                },
@@ -186,7 +187,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
                        .buf = out_buf,
                },
                {
-                       .addr = i2cbus->slave_addr,
+                       .addr = dvo->slave_addr,
                        .flags = I2C_M_RD | I2C_M_NOSTART,
                        .len = 2,
                        .buf = in_buf,
@@ -202,7 +203,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
 
        if (!priv->quiet) {
                DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
-                         addr, i2cbus->adapter.name, i2cbus->slave_addr);
+                         addr, i2cbus->adapter.name, dvo->slave_addr);
        }
        return false;
 }
@@ -211,10 +212,11 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data)
 static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data)
 {
        struct ivch_priv *priv = dvo->dev_priv;
-       struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+       struct i2c_adapter *adapter = dvo->i2c_bus;
+       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        u8 out_buf[3];
        struct i2c_msg msg = {
-               .addr = i2cbus->slave_addr,
+               .addr = dvo->slave_addr,
                .flags = 0,
                .len = 3,
                .buf = out_buf,
@@ -229,7 +231,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data)
 
        if (!priv->quiet) {
                DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
-                         addr, i2cbus->adapter.name, i2cbus->slave_addr);
+                         addr, i2cbus->adapter.name, dvo->slave_addr);
        }
 
        return false;
@@ -237,7 +239,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data)
 
 /** Probes the given bus and slave address for an ivch */
 static bool ivch_init(struct intel_dvo_device *dvo,
-                     struct intel_i2c_chan *i2cbus)
+                     struct i2c_adapter *adapter)
 {
        struct ivch_priv *priv;
        uint16_t temp;
@@ -246,8 +248,7 @@ static bool ivch_init(struct intel_dvo_device *dvo,
        if (priv == NULL)
                return false;
 
-       dvo->i2c_bus = i2cbus;
-       dvo->i2c_bus->slave_addr = dvo->slave_addr;
+       dvo->i2c_bus = adapter;
        dvo->dev_priv = priv;
        priv->quiet = true;
 
index 033a4bb070b2ac7b89660183ae4ade657531d613..e1c1f7341e5cff60a15fb568e7a0dd322782ef91 100644 (file)
@@ -76,19 +76,20 @@ struct sil164_priv {
 static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 {
        struct sil164_priv *sil = dvo->dev_priv;
-       struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+       struct i2c_adapter *adapter = dvo->i2c_bus;
+       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        u8 out_buf[2];
        u8 in_buf[2];
 
        struct i2c_msg msgs[] = {
                {
-                       .addr = i2cbus->slave_addr,
+                       .addr = dvo->slave_addr,
                        .flags = 0,
                        .len = 1,
                        .buf = out_buf,
                },
                {
-                       .addr = i2cbus->slave_addr,
+                       .addr = dvo->slave_addr,
                        .flags = I2C_M_RD,
                        .len = 1,
                        .buf = in_buf,
@@ -105,7 +106,7 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 
        if (!sil->quiet) {
                DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
-                         addr, i2cbus->adapter.name, i2cbus->slave_addr);
+                         addr, i2cbus->adapter.name, dvo->slave_addr);
        }
        return false;
 }
@@ -113,10 +114,11 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 {
        struct sil164_priv *sil= dvo->dev_priv;
-       struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+       struct i2c_adapter *adapter = dvo->i2c_bus;
+       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        uint8_t out_buf[2];
        struct i2c_msg msg = {
-               .addr = i2cbus->slave_addr,
+               .addr = dvo->slave_addr,
                .flags = 0,
                .len = 2,
                .buf = out_buf,
@@ -130,7 +132,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 
        if (!sil->quiet) {
                DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
-                         addr, i2cbus->adapter.name, i2cbus->slave_addr);
+                         addr, i2cbus->adapter.name, dvo->slave_addr);
        }
 
        return false;
@@ -138,7 +140,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 
 /* Silicon Image 164 driver for chip on i2c bus */
 static bool sil164_init(struct intel_dvo_device *dvo,
-                       struct intel_i2c_chan *i2cbus)
+                       struct i2c_adapter *adapter)
 {
        /* this will detect the SIL164 chip on the specified i2c bus */
        struct sil164_priv *sil;
@@ -148,8 +150,7 @@ static bool sil164_init(struct intel_dvo_device *dvo,
        if (sil == NULL)
                return false;
 
-       dvo->i2c_bus = i2cbus;
-       dvo->i2c_bus->slave_addr = dvo->slave_addr;
+       dvo->i2c_bus = adapter;
        dvo->dev_priv = sil;
        sil->quiet = true;
 
@@ -158,7 +159,7 @@ static bool sil164_init(struct intel_dvo_device *dvo,
 
        if (ch != (SIL164_VID & 0xff)) {
                DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n",
-                         ch, i2cbus->adapter.name, i2cbus->slave_addr);
+                         ch, adapter->name, dvo->slave_addr);
                goto out;
        }
 
@@ -167,7 +168,7 @@ static bool sil164_init(struct intel_dvo_device *dvo,
 
        if (ch != (SIL164_DID & 0xff)) {
                DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n",
-                         ch, i2cbus->adapter.name, i2cbus->slave_addr);
+                         ch, adapter->name, dvo->slave_addr);
                goto out;
        }
        sil->quiet = false;
index 207fda806ebf87a212141353e44c88b3caa456b3..9ecc907384ec339d312ca31c5ea26a2a0636aedf 100644 (file)
@@ -101,19 +101,20 @@ struct tfp410_priv {
 static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 {
        struct tfp410_priv *tfp = dvo->dev_priv;
-       struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+       struct i2c_adapter *adapter = dvo->i2c_bus;
+       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        u8 out_buf[2];
        u8 in_buf[2];
 
        struct i2c_msg msgs[] = {
                {
-                       .addr = i2cbus->slave_addr,
+                       .addr = dvo->slave_addr,
                        .flags = 0,
                        .len = 1,
                        .buf = out_buf,
                },
                {
-                       .addr = i2cbus->slave_addr,
+                       .addr = dvo->slave_addr,
                        .flags = I2C_M_RD,
                        .len = 1,
                        .buf = in_buf,
@@ -130,7 +131,7 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 
        if (!tfp->quiet) {
                DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n",
-                         addr, i2cbus->adapter.name, i2cbus->slave_addr);
+                         addr, i2cbus->adapter.name, dvo->slave_addr);
        }
        return false;
 }
@@ -138,10 +139,11 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
 static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 {
        struct tfp410_priv *tfp = dvo->dev_priv;
-       struct intel_i2c_chan *i2cbus = dvo->i2c_bus;
+       struct i2c_adapter *adapter = dvo->i2c_bus;
+       struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter);
        uint8_t out_buf[2];
        struct i2c_msg msg = {
-               .addr = i2cbus->slave_addr,
+               .addr = dvo->slave_addr,
                .flags = 0,
                .len = 2,
                .buf = out_buf,
@@ -155,7 +157,7 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
 
        if (!tfp->quiet) {
                DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n",
-                         addr, i2cbus->adapter.name, i2cbus->slave_addr);
+                         addr, i2cbus->adapter.name, dvo->slave_addr);
        }
 
        return false;
@@ -174,7 +176,7 @@ static int tfp410_getid(struct intel_dvo_device *dvo, int addr)
 
 /* Ti TFP410 driver for chip on i2c bus */
 static bool tfp410_init(struct intel_dvo_device *dvo,
-                       struct intel_i2c_chan *i2cbus)
+                       struct i2c_adapter *adapter)
 {
        /* this will detect the tfp410 chip on the specified i2c bus */
        struct tfp410_priv *tfp;
@@ -184,20 +186,19 @@ static bool tfp410_init(struct intel_dvo_device *dvo,
        if (tfp == NULL)
                return false;
 
-       dvo->i2c_bus = i2cbus;
-       dvo->i2c_bus->slave_addr = dvo->slave_addr;
+       dvo->i2c_bus = adapter;
        dvo->dev_priv = tfp;
        tfp->quiet = true;
 
        if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) {
                DRM_DEBUG("tfp410 not detected got VID %X: from %s Slave %d.\n",
-                         id, i2cbus->adapter.name, i2cbus->slave_addr);
+                         id, adapter->name, dvo->slave_addr);
                goto out;
        }
 
        if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) {
                DRM_DEBUG("tfp410 not detected got DID %X: from %s Slave %d.\n",
-                         id, i2cbus->adapter.name, i2cbus->slave_addr);
+                         id, adapter->name, dvo->slave_addr);
                goto out;
        }
        tfp->quiet = false;
index f112c769d5334148683040deef54a3dde80382f8..50d1f782768cc99ffc1e3a844f74a4c7898fcfed 100644 (file)
@@ -846,7 +846,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
                return 0;
        }
 
-       printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr);
+       DRM_DEBUG("set status page addr 0x%08x\n", (u32)hws->addr);
 
        dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12);
 
@@ -885,8 +885,8 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
  * some RAM for the framebuffer at early boot.  This code figures out
  * how much was set aside so we can use it for our own purposes.
  */
-static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size,
-                         unsigned long *preallocated_size)
+static int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size,
+                         uint32_t *preallocated_size)
 {
        struct pci_dev *bridge_dev;
        u16 tmp = 0;
@@ -984,10 +984,11 @@ static int i915_probe_agp(struct drm_device *dev, unsigned long *aperture_size,
        return 0;
 }
 
-static int i915_load_modeset_init(struct drm_device *dev)
+static int i915_load_modeset_init(struct drm_device *dev,
+                                 unsigned long prealloc_size,
+                                 unsigned long agp_size)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned long agp_size, prealloc_size;
        int fb_bar = IS_I9XX(dev) ? 2 : 0;
        int ret = 0;
 
@@ -1002,10 +1003,6 @@ static int i915_load_modeset_init(struct drm_device *dev)
        if (IS_I965G(dev) || IS_G33(dev))
                dev_priv->cursor_needs_physical = false;
 
-       ret = i915_probe_agp(dev, &agp_size, &prealloc_size);
-       if (ret)
-               goto out;
-
        /* Basic memrange allocator for stolen space (aka vram) */
        drm_mm_init(&dev_priv->vram, 0, prealloc_size);
 
@@ -1082,6 +1079,44 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
        master->driver_priv = NULL;
 }
 
+static void i915_get_mem_freq(struct drm_device *dev)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       u32 tmp;
+
+       if (!IS_IGD(dev))
+               return;
+
+       tmp = I915_READ(CLKCFG);
+
+       switch (tmp & CLKCFG_FSB_MASK) {
+       case CLKCFG_FSB_533:
+               dev_priv->fsb_freq = 533; /* 133*4 */
+               break;
+       case CLKCFG_FSB_800:
+               dev_priv->fsb_freq = 800; /* 200*4 */
+               break;
+       case CLKCFG_FSB_667:
+               dev_priv->fsb_freq =  667; /* 167*4 */
+               break;
+       case CLKCFG_FSB_400:
+               dev_priv->fsb_freq = 400; /* 100*4 */
+               break;
+       }
+
+       switch (tmp & CLKCFG_MEM_MASK) {
+       case CLKCFG_MEM_533:
+               dev_priv->mem_freq = 533;
+               break;
+       case CLKCFG_MEM_667:
+               dev_priv->mem_freq = 667;
+               break;
+       case CLKCFG_MEM_800:
+               dev_priv->mem_freq = 800;
+               break;
+       }
+}
+
 /**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
@@ -1098,6 +1133,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        struct drm_i915_private *dev_priv = dev->dev_private;
        resource_size_t base, size;
        int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1;
+       uint32_t agp_size, prealloc_size;
 
        /* i915 has 4 more counters */
        dev->counters += 4;
@@ -1146,9 +1182,29 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                         "performance may suffer.\n");
        }
 
+       ret = i915_probe_agp(dev, &agp_size, &prealloc_size);
+       if (ret)
+               goto out_iomapfree;
+
+       dev_priv->wq = create_workqueue("i915");
+       if (dev_priv->wq == NULL) {
+               DRM_ERROR("Failed to create our workqueue.\n");
+               ret = -ENOMEM;
+               goto out_iomapfree;
+       }
+
        /* enable GEM by default */
        dev_priv->has_gem = 1;
 
+       if (prealloc_size > agp_size * 3 / 4) {
+               DRM_ERROR("Detected broken video BIOS with %d/%dkB of video "
+                         "memory stolen.\n",
+                         prealloc_size / 1024, agp_size / 1024);
+               DRM_ERROR("Disabling GEM. (try reducing stolen memory or "
+                         "updating the BIOS to fix).\n");
+               dev_priv->has_gem = 0;
+       }
+
        dev->driver->get_vblank_counter = i915_get_vblank_counter;
        dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
        if (IS_G4X(dev) || IS_IGDNG(dev)) {
@@ -1162,9 +1218,11 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        if (!I915_NEED_GFX_HWS(dev)) {
                ret = i915_init_phys_hws(dev);
                if (ret != 0)
-                       goto out_iomapfree;
+                       goto out_workqueue_free;
        }
 
+       i915_get_mem_freq(dev);
+
        /* On the 945G/GM, the chipset reports the MSI capability on the
         * integrated graphics even though the support isn't actually there
         * according to the published specs.  It doesn't appear to function
@@ -1180,6 +1238,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                pci_enable_msi(dev->pdev);
 
        spin_lock_init(&dev_priv->user_irq_lock);
+       spin_lock_init(&dev_priv->error_lock);
        dev_priv->user_irq_refcount = 0;
 
        ret = drm_vblank_init(dev, I915_NUM_PIPE);
@@ -1190,10 +1249,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        }
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               ret = i915_load_modeset_init(dev);
+               ret = i915_load_modeset_init(dev, prealloc_size, agp_size);
                if (ret < 0) {
                        DRM_ERROR("failed to init modeset\n");
-                       goto out_rmmap;
+                       goto out_workqueue_free;
                }
        }
 
@@ -1204,6 +1263,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
        return 0;
 
+out_workqueue_free:
+       destroy_workqueue(dev_priv->wq);
 out_iomapfree:
        io_mapping_free(dev_priv->mm.gtt_mapping);
 out_rmmap:
@@ -1217,6 +1278,8 @@ int i915_driver_unload(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       destroy_workqueue(dev_priv->wq);
+
        io_mapping_free(dev_priv->mm.gtt_mapping);
        if (dev_priv->mm.gtt_mtrr >= 0) {
                mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base,
index 98560e1e899a83171ddd2ef041e1d76df191e37d..fc4b68aa2d056e9c8b9256860c38b4ac2175f529 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "drm_pciids.h"
 #include <linux/console.h>
+#include "drm_crtc_helper.h"
 
 static unsigned int i915_modeset = -1;
 module_param_named(modeset, i915_modeset, int, 0400);
@@ -57,8 +58,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        if (!dev || !dev_priv) {
-               printk(KERN_ERR "dev: %p, dev_priv: %p\n", dev, dev_priv);
-               printk(KERN_ERR "DRM not initialized, aborting suspend.\n");
+               DRM_ERROR("dev: %p, dev_priv: %p\n", dev, dev_priv);
+               DRM_ERROR("DRM not initialized, aborting suspend.\n");
                return -ENODEV;
        }
 
@@ -67,8 +68,6 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
 
        pci_save_state(dev->pdev);
 
-       i915_save_state(dev);
-
        /* If KMS is active, we do the leavevt stuff here */
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
                if (i915_gem_idle(dev))
@@ -77,6 +76,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
                drm_irq_uninstall(dev);
        }
 
+       i915_save_state(dev);
+
        intel_opregion_free(dev, 1);
 
        if (state.event == PM_EVENT_SUSPEND) {
@@ -115,6 +116,10 @@ static int i915_resume(struct drm_device *dev)
 
                drm_irq_install(dev);
        }
+       if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+               /* Resume the modeset for every activated CRTC */
+               drm_helper_resume_force_mode(dev);
+       }
 
        return ret;
 }
index 7a84f04e8439c1ea2f68acce4520f0d4665490f7..5b4f87e556218e0574fb3a57f3e084fbaaa7a251 100644 (file)
@@ -133,6 +133,22 @@ struct sdvo_device_mapping {
        u8 initialized;
 };
 
+struct drm_i915_error_state {
+       u32 eir;
+       u32 pgtbl_er;
+       u32 pipeastat;
+       u32 pipebstat;
+       u32 ipeir;
+       u32 ipehr;
+       u32 instdone;
+       u32 acthd;
+       u32 instpm;
+       u32 instps;
+       u32 instdone1;
+       u32 seqno;
+       struct timeval time;
+};
+
 typedef struct drm_i915_private {
        struct drm_device *dev;
 
@@ -203,12 +219,21 @@ typedef struct drm_i915_private {
        unsigned int lvds_vbt:1;
        unsigned int int_crt_support:1;
        unsigned int lvds_use_ssc:1;
+       unsigned int edp_support:1;
        int lvds_ssc_freq;
 
+       int crt_ddc_bus; /* -1 = unknown, else GPIO to use for CRT DDC */
        struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
        int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
        int num_fence_regs; /* 8 on pre-965, 16 otherwise */
 
+       unsigned int fsb_freq, mem_freq;
+
+       spinlock_t error_lock;
+       struct drm_i915_error_state *first_error;
+       struct work_struct error_work;
+       struct workqueue_struct *wq;
+
        /* Register state */
        u8 saveLBB;
        u32 saveDSPACNTR;
@@ -306,6 +331,17 @@ typedef struct drm_i915_private {
        u32 saveCURBPOS;
        u32 saveCURBBASE;
        u32 saveCURSIZE;
+       u32 saveDP_B;
+       u32 saveDP_C;
+       u32 saveDP_D;
+       u32 savePIPEA_GMCH_DATA_M;
+       u32 savePIPEB_GMCH_DATA_M;
+       u32 savePIPEA_GMCH_DATA_N;
+       u32 savePIPEB_GMCH_DATA_N;
+       u32 savePIPEA_DP_LINK_M;
+       u32 savePIPEB_DP_LINK_M;
+       u32 savePIPEA_DP_LINK_N;
+       u32 savePIPEB_DP_LINK_N;
 
        struct {
                struct drm_mm gtt_space;
@@ -349,6 +385,9 @@ typedef struct drm_i915_private {
                 */
                struct list_head inactive_list;
 
+               /** LRU list of objects with fence regs on them. */
+               struct list_head fence_list;
+
                /**
                 * List of breadcrumbs associated with GPU requests currently
                 * outstanding.
@@ -416,6 +455,9 @@ struct drm_i915_gem_object {
        /** This object's place on the active/flushing/inactive lists */
        struct list_head list;
 
+       /** This object's place on the fenced object LRU */
+       struct list_head fence_list;
+
        /**
         * This is set if the object is on the active or flushing lists
         * (has pending rendering), and is not set if it's on inactive (ready
@@ -457,9 +499,6 @@ struct drm_i915_gem_object {
         */
        int fence_reg;
 
-       /** Boolean whether this object has a valid gtt offset. */
-       int gtt_bound;
-
        /** How many users have pinned this object in GTT space */
        int pin_count;
 
@@ -644,6 +683,7 @@ void i915_gem_free_object(struct drm_gem_object *obj);
 int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment);
 void i915_gem_object_unpin(struct drm_gem_object *obj);
 int i915_gem_object_unbind(struct drm_gem_object *obj);
+void i915_gem_release_mmap(struct drm_gem_object *obj);
 void i915_gem_lastclose(struct drm_device *dev);
 uint32_t i915_get_gem_seqno(struct drm_device *dev);
 int i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
@@ -857,7 +897,11 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \
                                                      IS_I915GM(dev)))
 #define SUPPORTS_INTEGRATED_HDMI(dev)  (IS_G4X(dev) || IS_IGDNG(dev))
+#define SUPPORTS_INTEGRATED_DP(dev)    (IS_G4X(dev) || IS_IGDNG(dev))
+#define SUPPORTS_EDP(dev)              (IS_IGDNG_M(dev))
 #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev))
+/* dsparb controlled by hw only */
+#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IGDNG(dev))
 
 #define PRIMARY_RINGBUFFER_SIZE         (128*1024)
 
index fd2b8bdffe3f416b7a7869051ff44b954e03ada7..80e5ba490dc28c8a15c4619865f4872f82a6625e 100644 (file)
@@ -978,6 +978,7 @@ int
 i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
                          struct drm_file *file_priv)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_set_domain *args = data;
        struct drm_gem_object *obj;
        uint32_t read_domains = args->read_domains;
@@ -1006,12 +1007,22 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
 
        mutex_lock(&dev->struct_mutex);
 #if WATCH_BUF
-       DRM_INFO("set_domain_ioctl %p(%d), %08x %08x\n",
+       DRM_INFO("set_domain_ioctl %p(%zd), %08x %08x\n",
                 obj, obj->size, read_domains, write_domain);
 #endif
        if (read_domains & I915_GEM_DOMAIN_GTT) {
+               struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
                ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
 
+               /* Update the LRU on the fence for the CPU access that's
+                * about to occur.
+                */
+               if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
+                       list_move_tail(&obj_priv->fence_list,
+                                      &dev_priv->mm.fence_list);
+               }
+
                /* Silently promote "you're not bound, there was nothing to do"
                 * to success, since the client was just asking us to
                 * make sure everything was done.
@@ -1050,7 +1061,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
        }
 
 #if WATCH_BUF
-       DRM_INFO("%s: sw_finish %d (%p %d)\n",
+       DRM_INFO("%s: sw_finish %d (%p %zd)\n",
                 __func__, args->handle, obj, obj->size);
 #endif
        obj_priv = obj->driver_private;
@@ -1155,8 +1166,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        }
 
        /* Need a new fence register? */
-       if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
-           obj_priv->tiling_mode != I915_TILING_NONE) {
+       if (obj_priv->tiling_mode != I915_TILING_NONE) {
                ret = i915_gem_object_get_fence_reg(obj);
                if (ret) {
                        mutex_unlock(&dev->struct_mutex);
@@ -1252,6 +1262,31 @@ out_free_list:
        return ret;
 }
 
+/**
+ * i915_gem_release_mmap - remove physical page mappings
+ * @obj: obj in question
+ *
+ * Preserve the reservation of the mmaping with the DRM core code, but
+ * relinquish ownership of the pages back to the system.
+ *
+ * It is vital that we remove the page mapping if we have mapped a tiled
+ * object through the GTT and then lose the fence register due to
+ * resource pressure. Similarly if the object has been moved out of the
+ * aperture, than pages mapped into userspace must be revoked. Removing the
+ * mapping will then trigger a page fault on the next user access, allowing
+ * fixup by i915_gem_fault().
+ */
+void
+i915_gem_release_mmap(struct drm_gem_object *obj)
+{
+       struct drm_device *dev = obj->dev;
+       struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+       if (dev->dev_mapping)
+               unmap_mapping_range(dev->dev_mapping,
+                                   obj_priv->mmap_offset, obj->size, 1);
+}
+
 static void
 i915_gem_free_mmap_offset(struct drm_gem_object *obj)
 {
@@ -1545,7 +1580,7 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
        }
 
        if (was_empty && !dev_priv->mm.suspended)
-               schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
+               queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
        return seqno;
 }
 
@@ -1694,7 +1729,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
        i915_gem_retire_requests(dev);
        if (!dev_priv->mm.suspended &&
            !list_empty(&dev_priv->mm.request_list))
-               schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
+               queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
        mutex_unlock(&dev->struct_mutex);
 }
 
@@ -1861,7 +1896,6 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
 {
        struct drm_device *dev = obj->dev;
        struct drm_i915_gem_object *obj_priv = obj->driver_private;
-       loff_t offset;
        int ret = 0;
 
 #if WATCH_BUF
@@ -1898,9 +1932,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
        BUG_ON(obj_priv->active);
 
        /* blow away mappings if mapped through GTT */
-       offset = ((loff_t) obj->map_list.hash.key) << PAGE_SHIFT;
-       if (dev->dev_mapping)
-               unmap_mapping_range(dev->dev_mapping, offset, obj->size, 1);
+       i915_gem_release_mmap(obj);
 
        if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
                i915_gem_clear_fence_reg(obj);
@@ -2186,6 +2218,12 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
        struct drm_i915_gem_object *old_obj_priv = NULL;
        int i, ret, avail;
 
+       /* Just update our place in the LRU if our fence is getting used. */
+       if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
+               list_move_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list);
+               return 0;
+       }
+
        switch (obj_priv->tiling_mode) {
        case I915_TILING_NONE:
                WARN(1, "allocating a fence for non-tiled object?\n");
@@ -2207,7 +2245,6 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
        }
 
        /* First try to find a free reg */
-try_again:
        avail = 0;
        for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
                reg = &dev_priv->fence_regs[i];
@@ -2221,67 +2258,62 @@ try_again:
 
        /* None available, try to steal one or wait for a user to finish */
        if (i == dev_priv->num_fence_regs) {
-               uint32_t seqno = dev_priv->mm.next_gem_seqno;
-               loff_t offset;
+               struct drm_gem_object *old_obj = NULL;
 
                if (avail == 0)
                        return -ENOSPC;
 
-               for (i = dev_priv->fence_reg_start;
-                    i < dev_priv->num_fence_regs; i++) {
-                       uint32_t this_seqno;
-
-                       reg = &dev_priv->fence_regs[i];
-                       old_obj_priv = reg->obj->driver_private;
+               list_for_each_entry(old_obj_priv, &dev_priv->mm.fence_list,
+                                   fence_list) {
+                       old_obj = old_obj_priv->obj;
 
                        if (old_obj_priv->pin_count)
                                continue;
 
+                       /* Take a reference, as otherwise the wait_rendering
+                        * below may cause the object to get freed out from
+                        * under us.
+                        */
+                       drm_gem_object_reference(old_obj);
+
                        /* i915 uses fences for GPU access to tiled buffers */
                        if (IS_I965G(dev) || !old_obj_priv->active)
                                break;
 
-                       /* find the seqno of the first available fence */
-                       this_seqno = old_obj_priv->last_rendering_seqno;
-                       if (this_seqno != 0 &&
-                           reg->obj->write_domain == 0 &&
-                           i915_seqno_passed(seqno, this_seqno))
-                               seqno = this_seqno;
-               }
-
-               /*
-                * Now things get ugly... we have to wait for one of the
-                * objects to finish before trying again.
-                */
-               if (i == dev_priv->num_fence_regs) {
-                       if (seqno == dev_priv->mm.next_gem_seqno) {
-                               i915_gem_flush(dev,
-                                              I915_GEM_GPU_DOMAINS,
-                                              I915_GEM_GPU_DOMAINS);
-                               seqno = i915_add_request(dev, NULL,
-                                                        I915_GEM_GPU_DOMAINS);
-                               if (seqno == 0)
-                                       return -ENOMEM;
+                       /* This brings the object to the head of the LRU if it
+                        * had been written to.  The only way this should
+                        * result in us waiting longer than the expected
+                        * optimal amount of time is if there was a
+                        * fence-using buffer later that was read-only.
+                        */
+                       i915_gem_object_flush_gpu_write_domain(old_obj);
+                       ret = i915_gem_object_wait_rendering(old_obj);
+                       if (ret != 0) {
+                               drm_gem_object_unreference(old_obj);
+                               return ret;
                        }
 
-                       ret = i915_wait_request(dev, seqno);
-                       if (ret)
-                               return ret;
-                       goto try_again;
+                       break;
                }
 
                /*
                 * Zap this virtual mapping so we can set up a fence again
                 * for this object next time we need it.
                 */
-               offset = ((loff_t) reg->obj->map_list.hash.key) << PAGE_SHIFT;
-               if (dev->dev_mapping)
-                       unmap_mapping_range(dev->dev_mapping, offset,
-                                           reg->obj->size, 1);
+               i915_gem_release_mmap(old_obj);
+
+               i = old_obj_priv->fence_reg;
+               reg = &dev_priv->fence_regs[i];
+
                old_obj_priv->fence_reg = I915_FENCE_REG_NONE;
+               list_del_init(&old_obj_priv->fence_list);
+
+               drm_gem_object_unreference(old_obj);
        }
 
        obj_priv->fence_reg = i;
+       list_add_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list);
+
        reg->obj = obj;
 
        if (IS_I965G(dev))
@@ -2324,6 +2356,7 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
 
        dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL;
        obj_priv->fence_reg = I915_FENCE_REG_NONE;
+       list_del_init(&obj_priv->fence_list);
 }
 
 /**
@@ -2423,7 +2456,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
        }
 
 #if WATCH_BUF
-       DRM_INFO("Binding object of size %d at 0x%08x\n",
+       DRM_INFO("Binding object of size %zd at 0x%08x\n",
                 obj->size, obj_priv->gtt_offset);
 #endif
        ret = i915_gem_object_get_pages(obj);
@@ -3577,9 +3610,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
         * Pre-965 chips need a fence register set up in order to
         * properly handle tiled surfaces.
         */
-       if (!IS_I965G(dev) &&
-           obj_priv->fence_reg == I915_FENCE_REG_NONE &&
-           obj_priv->tiling_mode != I915_TILING_NONE) {
+       if (!IS_I965G(dev) && obj_priv->tiling_mode != I915_TILING_NONE) {
                ret = i915_gem_object_get_fence_reg(obj);
                if (ret != 0) {
                        if (ret != -EBUSY && ret != -ERESTARTSYS)
@@ -3788,6 +3819,7 @@ int i915_gem_init_object(struct drm_gem_object *obj)
        obj_priv->obj = obj;
        obj_priv->fence_reg = I915_FENCE_REG_NONE;
        INIT_LIST_HEAD(&obj_priv->list);
+       INIT_LIST_HEAD(&obj_priv->fence_list);
 
        return 0;
 }
@@ -4200,15 +4232,11 @@ int
 i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
                       struct drm_file *file_priv)
 {
-       int ret;
-
        if (drm_core_check_feature(dev, DRIVER_MODESET))
                return 0;
 
-       ret = i915_gem_idle(dev);
        drm_irq_uninstall(dev);
-
-       return ret;
+       return i915_gem_idle(dev);
 }
 
 void
@@ -4227,6 +4255,7 @@ i915_gem_lastclose(struct drm_device *dev)
 void
 i915_gem_load(struct drm_device *dev)
 {
+       int i;
        drm_i915_private_t *dev_priv = dev->dev_private;
 
        spin_lock_init(&dev_priv->mm.active_list_lock);
@@ -4234,6 +4263,7 @@ i915_gem_load(struct drm_device *dev)
        INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
        INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
        INIT_LIST_HEAD(&dev_priv->mm.request_list);
+       INIT_LIST_HEAD(&dev_priv->mm.fence_list);
        INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
                          i915_gem_retire_work_handler);
        dev_priv->mm.next_gem_seqno = 1;
@@ -4246,6 +4276,18 @@ i915_gem_load(struct drm_device *dev)
        else
                dev_priv->num_fence_regs = 8;
 
+       /* Initialize fence registers to zero */
+       if (IS_I965G(dev)) {
+               for (i = 0; i < 16; i++)
+                       I915_WRITE64(FENCE_REG_965_0 + (i * 8), 0);
+       } else {
+               for (i = 0; i < 8; i++)
+                       I915_WRITE(FENCE_REG_830_0 + (i * 4), 0);
+               if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
+                       for (i = 0; i < 8; i++)
+                               I915_WRITE(FENCE_REG_945_8 + (i * 4), 0);
+       }
+
        i915_gem_detect_bit_6_swizzle(dev);
 }
 
index 8d0b943e2c5aced503603a5848e291ea0a0c9694..e602614bd3f89a9cbbb7f53c6503e93814272a18 100644 (file)
@@ -87,7 +87,7 @@ i915_gem_dump_object(struct drm_gem_object *obj, int len,
                        chunk_len = page_len - chunk;
                        if (chunk_len > 128)
                                chunk_len = 128;
-                       i915_gem_dump_page(obj_priv->page_list[page],
+                       i915_gem_dump_page(obj_priv->pages[page],
                                           chunk, chunk + chunk_len,
                                           obj_priv->gtt_offset +
                                           page * PAGE_SIZE,
@@ -143,7 +143,7 @@ i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle)
        uint32_t *backing_map = NULL;
        int bad_count = 0;
 
-       DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %dkb):\n",
+       DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %zdkb):\n",
                 __func__, obj, obj_priv->gtt_offset, handle,
                 obj->size / 1024);
 
@@ -157,7 +157,7 @@ i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle)
        for (page = 0; page < obj->size / PAGE_SIZE; page++) {
                int i;
 
-               backing_map = kmap_atomic(obj_priv->page_list[page], KM_USER0);
+               backing_map = kmap_atomic(obj_priv->pages[page], KM_USER0);
 
                if (backing_map == NULL) {
                        DRM_ERROR("failed to map backing page\n");
index 28146e405e87404cf5177100ee2c467d8e5238e1..cb3b97405fbfdd3735b91a9a60ec5108bc83c40b 100644 (file)
@@ -75,11 +75,10 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
        case ACTIVE_LIST:
                seq_printf(m, "Active:\n");
                lock = &dev_priv->mm.active_list_lock;
-               spin_lock(lock);
                head = &dev_priv->mm.active_list;
                break;
        case INACTIVE_LIST:
-               seq_printf(m, "Inctive:\n");
+               seq_printf(m, "Inactive:\n");
                head = &dev_priv->mm.inactive_list;
                break;
        case FLUSHING_LIST:
@@ -91,6 +90,8 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
                return 0;
        }
 
+       if (lock)
+               spin_lock(lock);
        list_for_each_entry(obj_priv, head, list)
        {
                struct drm_gem_object *obj = obj_priv->obj;
@@ -104,7 +105,10 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
                if (obj->name)
                        seq_printf(m, " (name: %d)", obj->name);
                if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
-                       seq_printf(m, " (fence: %d)\n", obj_priv->fence_reg);
+                       seq_printf(m, " (fence: %d)", obj_priv->fence_reg);
+               if (obj_priv->gtt_space != NULL)
+                       seq_printf(m, " (gtt_offset: %08x)", obj_priv->gtt_offset);
+
                seq_printf(m, "\n");
        }
 
@@ -323,6 +327,41 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
        return 0;
 }
 
+static int i915_error_state(struct seq_file *m, void *unused)
+{
+       struct drm_info_node *node = (struct drm_info_node *) m->private;
+       struct drm_device *dev = node->minor->dev;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       struct drm_i915_error_state *error;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev_priv->error_lock, flags);
+       if (!dev_priv->first_error) {
+               seq_printf(m, "no error state collected\n");
+               goto out;
+       }
+
+       error = dev_priv->first_error;
+
+       seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
+                  error->time.tv_usec);
+       seq_printf(m, "EIR: 0x%08x\n", error->eir);
+       seq_printf(m, "  PGTBL_ER: 0x%08x\n", error->pgtbl_er);
+       seq_printf(m, "  INSTPM: 0x%08x\n", error->instpm);
+       seq_printf(m, "  IPEIR: 0x%08x\n", error->ipeir);
+       seq_printf(m, "  IPEHR: 0x%08x\n", error->ipehr);
+       seq_printf(m, "  INSTDONE: 0x%08x\n", error->instdone);
+       seq_printf(m, "  ACTHD: 0x%08x\n", error->acthd);
+       if (IS_I965G(dev)) {
+               seq_printf(m, "  INSTPS: 0x%08x\n", error->instps);
+               seq_printf(m, "  INSTDONE1: 0x%08x\n", error->instdone1);
+       }
+
+out:
+       spin_unlock_irqrestore(&dev_priv->error_lock, flags);
+
+       return 0;
+}
 
 static struct drm_info_list i915_gem_debugfs_list[] = {
        {"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
@@ -336,6 +375,7 @@ static struct drm_info_list i915_gem_debugfs_list[] = {
        {"i915_ringbuffer_data", i915_ringbuffer_data, 0},
        {"i915_ringbuffer_info", i915_ringbuffer_info, 0},
        {"i915_batchbuffers", i915_batchbuffer_info, 0},
+       {"i915_error_state", i915_error_state, 0},
 };
 #define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list)
 
index 5c1ceec49f5b6daf499cb9a984cc3aabaea1bb2c..a2d527b22ec4f7ba837d9787f11585cf141cf844 100644 (file)
@@ -114,11 +114,13 @@ intel_alloc_mchbar_resource(struct drm_device *dev)
        mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
 
        /* If ACPI doesn't have it, assume we need to allocate it ourselves */
+#ifdef CONFIG_PNP
        if (mchbar_addr &&
            pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) {
                ret = 0;
                goto out_put;
        }
+#endif
 
        /* Get some space for it */
        ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res,
@@ -519,6 +521,12 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
                        goto err;
                }
 
+               /* If we've changed tiling, GTT-mappings of the object
+                * need to re-fault to ensure that the correct fence register
+                * setup is in place.
+                */
+               i915_gem_release_mmap(obj);
+
                obj_priv->tiling_mode = args->tiling_mode;
                obj_priv->stride = args->stride;
        }
index b86b7b7130c603beca04456ccca0abc4c5bbfbcc..7ebc84c2881e23547ffb7099294f58995dea1bfe 100644 (file)
@@ -26,6 +26,7 @@
  *
  */
 
+#include <linux/sysrq.h>
 #include "drmP.h"
 #include "drm.h"
 #include "i915_drm.h"
  * we leave them always unmasked in IMR and then control enabling them through
  * PIPESTAT alone.
  */
-#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \
-                                  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |  \
-                                  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
+#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT |                \
+                                  I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
+                                  I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | \
+                                  I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
 
 /** Interrupts that we mask and unmask at runtime. */
 #define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
@@ -188,7 +190,7 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
        low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
 
        if (!i915_pipe_enabled(dev, pipe)) {
-               DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
+               DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe);
                return 0;
        }
 
@@ -217,7 +219,7 @@ u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
        int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45;
 
        if (!i915_pipe_enabled(dev, pipe)) {
-               DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
+               DRM_DEBUG("trying to get vblank count for disabled pipe %d\n", pipe);
                return 0;
        }
 
@@ -232,7 +234,17 @@ static void i915_hotplug_work_func(struct work_struct *work)
        drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
                                                    hotplug_work);
        struct drm_device *dev = dev_priv->dev;
-
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct drm_connector *connector;
+
+       if (mode_config->num_connector) {
+               list_for_each_entry(connector, &mode_config->connector_list, head) {
+                       struct intel_output *intel_output = to_intel_output(connector);
+       
+                       if (intel_output->hot_plug)
+                               (*intel_output->hot_plug) (intel_output);
+               }
+       }
        /* Just fire off a uevent and let userspace tell us what to do */
        drm_sysfs_hotplug_event(dev);
 }
@@ -278,6 +290,201 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev)
        return ret;
 }
 
+/**
+ * i915_error_work_func - do process context error handling work
+ * @work: work struct
+ *
+ * Fire an error uevent so userspace can see that a hang or error
+ * was detected.
+ */
+static void i915_error_work_func(struct work_struct *work)
+{
+       drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
+                                                   error_work);
+       struct drm_device *dev = dev_priv->dev;
+       char *event_string = "ERROR=1";
+       char *envp[] = { event_string, NULL };
+
+       DRM_DEBUG("generating error event\n");
+
+       kobject_uevent_env(&dev->primary->kdev.kobj, KOBJ_CHANGE, envp);
+}
+
+/**
+ * i915_capture_error_state - capture an error record for later analysis
+ * @dev: drm device
+ *
+ * Should be called when an error is detected (either a hang or an error
+ * interrupt) to capture error state from the time of the error.  Fills
+ * out a structure which becomes available in debugfs for user level tools
+ * to pick up.
+ */
+static void i915_capture_error_state(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_i915_error_state *error;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev_priv->error_lock, flags);
+       if (dev_priv->first_error)
+               goto out;
+
+       error = kmalloc(sizeof(*error), GFP_ATOMIC);
+       if (!error) {
+               DRM_DEBUG("out ot memory, not capturing error state\n");
+               goto out;
+       }
+
+       error->eir = I915_READ(EIR);
+       error->pgtbl_er = I915_READ(PGTBL_ER);
+       error->pipeastat = I915_READ(PIPEASTAT);
+       error->pipebstat = I915_READ(PIPEBSTAT);
+       error->instpm = I915_READ(INSTPM);
+       if (!IS_I965G(dev)) {
+               error->ipeir = I915_READ(IPEIR);
+               error->ipehr = I915_READ(IPEHR);
+               error->instdone = I915_READ(INSTDONE);
+               error->acthd = I915_READ(ACTHD);
+       } else {
+               error->ipeir = I915_READ(IPEIR_I965);
+               error->ipehr = I915_READ(IPEHR_I965);
+               error->instdone = I915_READ(INSTDONE_I965);
+               error->instps = I915_READ(INSTPS);
+               error->instdone1 = I915_READ(INSTDONE1);
+               error->acthd = I915_READ(ACTHD_I965);
+       }
+
+       do_gettimeofday(&error->time);
+
+       dev_priv->first_error = error;
+
+out:
+       spin_unlock_irqrestore(&dev_priv->error_lock, flags);
+}
+
+/**
+ * i915_handle_error - handle an error interrupt
+ * @dev: drm device
+ *
+ * Do some basic checking of regsiter state at error interrupt time and
+ * dump it to the syslog.  Also call i915_capture_error_state() to make
+ * sure we get a record and make it available in debugfs.  Fire a uevent
+ * so userspace knows something bad happened (should trigger collection
+ * of a ring dump etc.).
+ */
+static void i915_handle_error(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 eir = I915_READ(EIR);
+       u32 pipea_stats = I915_READ(PIPEASTAT);
+       u32 pipeb_stats = I915_READ(PIPEBSTAT);
+
+       i915_capture_error_state(dev);
+
+       printk(KERN_ERR "render error detected, EIR: 0x%08x\n",
+              eir);
+
+       if (IS_G4X(dev)) {
+               if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) {
+                       u32 ipeir = I915_READ(IPEIR_I965);
+
+                       printk(KERN_ERR "  IPEIR: 0x%08x\n",
+                              I915_READ(IPEIR_I965));
+                       printk(KERN_ERR "  IPEHR: 0x%08x\n",
+                              I915_READ(IPEHR_I965));
+                       printk(KERN_ERR "  INSTDONE: 0x%08x\n",
+                              I915_READ(INSTDONE_I965));
+                       printk(KERN_ERR "  INSTPS: 0x%08x\n",
+                              I915_READ(INSTPS));
+                       printk(KERN_ERR "  INSTDONE1: 0x%08x\n",
+                              I915_READ(INSTDONE1));
+                       printk(KERN_ERR "  ACTHD: 0x%08x\n",
+                              I915_READ(ACTHD_I965));
+                       I915_WRITE(IPEIR_I965, ipeir);
+                       (void)I915_READ(IPEIR_I965);
+               }
+               if (eir & GM45_ERROR_PAGE_TABLE) {
+                       u32 pgtbl_err = I915_READ(PGTBL_ER);
+                       printk(KERN_ERR "page table error\n");
+                       printk(KERN_ERR "  PGTBL_ER: 0x%08x\n",
+                              pgtbl_err);
+                       I915_WRITE(PGTBL_ER, pgtbl_err);
+                       (void)I915_READ(PGTBL_ER);
+               }
+       }
+
+       if (IS_I9XX(dev)) {
+               if (eir & I915_ERROR_PAGE_TABLE) {
+                       u32 pgtbl_err = I915_READ(PGTBL_ER);
+                       printk(KERN_ERR "page table error\n");
+                       printk(KERN_ERR "  PGTBL_ER: 0x%08x\n",
+                              pgtbl_err);
+                       I915_WRITE(PGTBL_ER, pgtbl_err);
+                       (void)I915_READ(PGTBL_ER);
+               }
+       }
+
+       if (eir & I915_ERROR_MEMORY_REFRESH) {
+               printk(KERN_ERR "memory refresh error\n");
+               printk(KERN_ERR "PIPEASTAT: 0x%08x\n",
+                      pipea_stats);
+               printk(KERN_ERR "PIPEBSTAT: 0x%08x\n",
+                      pipeb_stats);
+               /* pipestat has already been acked */
+       }
+       if (eir & I915_ERROR_INSTRUCTION) {
+               printk(KERN_ERR "instruction error\n");
+               printk(KERN_ERR "  INSTPM: 0x%08x\n",
+                      I915_READ(INSTPM));
+               if (!IS_I965G(dev)) {
+                       u32 ipeir = I915_READ(IPEIR);
+
+                       printk(KERN_ERR "  IPEIR: 0x%08x\n",
+                              I915_READ(IPEIR));
+                       printk(KERN_ERR "  IPEHR: 0x%08x\n",
+                              I915_READ(IPEHR));
+                       printk(KERN_ERR "  INSTDONE: 0x%08x\n",
+                              I915_READ(INSTDONE));
+                       printk(KERN_ERR "  ACTHD: 0x%08x\n",
+                              I915_READ(ACTHD));
+                       I915_WRITE(IPEIR, ipeir);
+                       (void)I915_READ(IPEIR);
+               } else {
+                       u32 ipeir = I915_READ(IPEIR_I965);
+
+                       printk(KERN_ERR "  IPEIR: 0x%08x\n",
+                              I915_READ(IPEIR_I965));
+                       printk(KERN_ERR "  IPEHR: 0x%08x\n",
+                              I915_READ(IPEHR_I965));
+                       printk(KERN_ERR "  INSTDONE: 0x%08x\n",
+                              I915_READ(INSTDONE_I965));
+                       printk(KERN_ERR "  INSTPS: 0x%08x\n",
+                              I915_READ(INSTPS));
+                       printk(KERN_ERR "  INSTDONE1: 0x%08x\n",
+                              I915_READ(INSTDONE1));
+                       printk(KERN_ERR "  ACTHD: 0x%08x\n",
+                              I915_READ(ACTHD_I965));
+                       I915_WRITE(IPEIR_I965, ipeir);
+                       (void)I915_READ(IPEIR_I965);
+               }
+       }
+
+       I915_WRITE(EIR, eir);
+       (void)I915_READ(EIR);
+       eir = I915_READ(EIR);
+       if (eir) {
+               /*
+                * some errors might have become stuck,
+                * mask them.
+                */
+               DRM_ERROR("EIR stuck: 0x%08x, masking\n", eir);
+               I915_WRITE(EMR, I915_READ(EMR) | eir);
+               I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
+       }
+
+       queue_work(dev_priv->wq, &dev_priv->error_work);
+}
+
 irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
@@ -319,15 +526,22 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
                pipea_stats = I915_READ(PIPEASTAT);
                pipeb_stats = I915_READ(PIPEBSTAT);
 
+               if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
+                       i915_handle_error(dev);
+
                /*
                 * Clear the PIPE(A|B)STAT regs before the IIR
                 */
                if (pipea_stats & 0x8000ffff) {
+                       if (pipea_stats &  PIPE_FIFO_UNDERRUN_STATUS)
+                               DRM_DEBUG("pipe a underrun\n");
                        I915_WRITE(PIPEASTAT, pipea_stats);
                        irq_received = 1;
                }
 
                if (pipeb_stats & 0x8000ffff) {
+                       if (pipeb_stats &  PIPE_FIFO_UNDERRUN_STATUS)
+                               DRM_DEBUG("pipe b underrun\n");
                        I915_WRITE(PIPEBSTAT, pipeb_stats);
                        irq_received = 1;
                }
@@ -346,7 +560,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
                        DRM_DEBUG("hotplug event received, stat 0x%08x\n",
                                  hotplug_status);
                        if (hotplug_status & dev_priv->hotplug_supported_mask)
-                               schedule_work(&dev_priv->hotplug_work);
+                               queue_work(dev_priv->wq,
+                                          &dev_priv->hotplug_work);
 
                        I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
                        I915_READ(PORT_HOTPLUG_STAT);
@@ -699,6 +914,7 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
        atomic_set(&dev_priv->irq_received, 0);
 
        INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
+       INIT_WORK(&dev_priv->error_work, i915_error_work_func);
 
        if (IS_IGDNG(dev)) {
                igdng_irq_preinstall(dev);
@@ -722,6 +938,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
 {
        drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
        u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
+       u32 error_mask;
 
        DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
 
@@ -758,6 +975,21 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
                i915_enable_irq(dev_priv, I915_DISPLAY_PORT_INTERRUPT);
        }
 
+       /*
+        * Enable some error detection, note the instruction error mask
+        * bit is reserved, so we leave it masked.
+        */
+       if (IS_G4X(dev)) {
+               error_mask = ~(GM45_ERROR_PAGE_TABLE |
+                              GM45_ERROR_MEM_PRIV |
+                              GM45_ERROR_CP_PRIV |
+                              I915_ERROR_MEMORY_REFRESH);
+       } else {
+               error_mask = ~(I915_ERROR_PAGE_TABLE |
+                              I915_ERROR_MEMORY_REFRESH);
+       }
+       I915_WRITE(EMR, error_mask);
+
        /* Disable pipe interrupt enables, clear pending pipe status */
        I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
        I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
index f6237a0b1133c0429cc27a2a0c26282bd6051b8c..2955083aa4719edc6cccdfdacb9b6c5487baf190 100644 (file)
 /*
  * Instruction and interrupt control regs
  */
+#define PGTBL_ER       0x02024
 #define PRB0_TAIL      0x02030
 #define PRB0_HEAD      0x02034
 #define PRB0_START     0x02038
 #define PRB1_HEAD      0x02044 /* 915+ only */
 #define PRB1_START     0x02048 /* 915+ only */
 #define PRB1_CTL       0x0204c /* 915+ only */
+#define IPEIR_I965     0x02064
+#define IPEHR_I965     0x02068
+#define INSTDONE_I965  0x0206c
+#define INSTPS         0x02070 /* 965+ only */
+#define INSTDONE1      0x0207c /* 965+ only */
 #define ACTHD_I965     0x02074
 #define HWS_PGA                0x02080
 #define HWS_ADDRESS_MASK       0xfffff000
 #define HWS_START_ADDRESS_SHIFT        4
 #define IPEIR          0x02088
+#define IPEHR          0x0208c
+#define INSTDONE       0x02090
 #define NOPID          0x02094
 #define HWSTAM         0x02098
 #define SCPD0          0x0209c /* 915+ only */
 #define EIR            0x020b0
 #define EMR            0x020b4
 #define ESR            0x020b8
+#define   GM45_ERROR_PAGE_TABLE                                (1<<5)
+#define   GM45_ERROR_MEM_PRIV                          (1<<4)
+#define   I915_ERROR_PAGE_TABLE                                (1<<4)
+#define   GM45_ERROR_CP_PRIV                           (1<<3)
+#define   I915_ERROR_MEMORY_REFRESH                    (1<<1)
+#define   I915_ERROR_INSTRUCTION                       (1<<0)
 #define INSTPM         0x020c0
 #define ACTHD          0x020c8
 #define FW_BLC         0x020d8
+#define FW_BLC2                0x020dc
 #define FW_BLC_SELF    0x020e0 /* 915+ only */
+#define   FW_BLC_SELF_EN (1<<15)
+#define MM_BURST_LENGTH     0x00700000
+#define MM_FIFO_WATERMARK   0x0001F000
+#define LM_BURST_LENGTH     0x00000700
+#define LM_FIFO_WATERMARK   0x0000001F
 #define MI_ARB_STATE   0x020e4 /* 915+ only */
 #define CACHE_MODE_0   0x02120 /* 915+ only */
 #define   CM0_MASK_SHIFT          16
 #define C0DRB3                 0x10206
 #define C1DRB3                 0x10606
 
+/* Clocking configuration register */
+#define CLKCFG                 0x10c00
+#define CLKCFG_FSB_400                                 (5 << 0)        /* hrawclk 100 */
+#define CLKCFG_FSB_533                                 (1 << 0)        /* hrawclk 133 */
+#define CLKCFG_FSB_667                                 (3 << 0)        /* hrawclk 166 */
+#define CLKCFG_FSB_800                                 (2 << 0)        /* hrawclk 200 */
+#define CLKCFG_FSB_1067                                        (6 << 0)        /* hrawclk 266 */
+#define CLKCFG_FSB_1333                                        (7 << 0)        /* hrawclk 333 */
+/* Note, below two are guess */
+#define CLKCFG_FSB_1600                                        (4 << 0)        /* hrawclk 400 */
+#define CLKCFG_FSB_1600_ALT                            (0 << 0)        /* hrawclk 400 */
+#define CLKCFG_FSB_MASK                                        (7 << 0)
+#define CLKCFG_MEM_533                                 (1 << 4)
+#define CLKCFG_MEM_667                                 (2 << 4)
+#define CLKCFG_MEM_800                                 (3 << 4)
+#define CLKCFG_MEM_MASK                                        (7 << 4)
+
 /** GM965 GM45 render standby register */
 #define MCHBAR_RENDER_STANDBY  0x111B8
 
 #define   HORIZ_INTERP_MASK    (3 << 6)
 #define   HORIZ_AUTO_SCALE     (1 << 5)
 #define   PANEL_8TO6_DITHER_ENABLE (1 << 3)
+#define   PFIT_FILTER_FUZZY    (0 << 24)
+#define   PFIT_SCALING_AUTO    (0 << 26)
+#define   PFIT_SCALING_PROGRAMMED (1 << 26)
+#define   PFIT_SCALING_PILLAR  (2 << 26)
+#define   PFIT_SCALING_LETTER  (3 << 26)
 #define PFIT_PGM_RATIOS        0x61234
 #define   PFIT_VERT_SCALE_MASK                 0xfff00000
 #define   PFIT_HORIZ_SCALE_MASK                        0x0000fff0
+/* Pre-965 */
+#define                PFIT_VERT_SCALE_SHIFT           20
+#define                PFIT_VERT_SCALE_MASK            0xfff00000
+#define                PFIT_HORIZ_SCALE_SHIFT          4
+#define                PFIT_HORIZ_SCALE_MASK           0x0000fff0
+/* 965+ */
+#define                PFIT_VERT_SCALE_SHIFT_965       16
+#define                PFIT_VERT_SCALE_MASK_965        0x1fff0000
+#define                PFIT_HORIZ_SCALE_SHIFT_965      0
+#define                PFIT_HORIZ_SCALE_MASK_965       0x00001fff
+
 #define PFIT_AUTO_RATIOS 0x61238
 
 /* Backlight control */
 #define TV_V_CHROMA_42         0x684a8
 
 /* Display Port */
+#define DP_A                           0x64000 /* eDP */
 #define DP_B                           0x64100
 #define DP_C                           0x64200
 #define DP_D                           0x64300
 /* Mystic DPCD version 1.1 special mode */
 #define   DP_ENHANCED_FRAMING          (1 << 18)
 
+/* eDP */
+#define   DP_PLL_FREQ_270MHZ           (0 << 16)
+#define   DP_PLL_FREQ_160MHZ           (1 << 16)
+#define   DP_PLL_FREQ_MASK             (3 << 16)
+
 /** locked once port is enabled */
 #define   DP_PORT_REVERSAL             (1 << 15)
 
+/* eDP */
+#define   DP_PLL_ENABLE                        (1 << 14)
+
 /** sends the clock on lane 15 of the PEG for debug */
 #define   DP_CLOCK_OUTPUT_ENABLE       (1 << 13)
 
 #define   DP_SCRAMBLING_DISABLE                (1 << 12)
+#define   DP_SCRAMBLING_DISABLE_IGDNG  (1 << 7)
 
 /** limit RGB values to avoid confusing TVs */
 #define   DP_COLOR_RANGE_16_235                (1 << 8)
  * is 20 bytes in each direction, hence the 5 fixed
  * data registers
  */
+#define DPA_AUX_CH_CTL                 0x64010
+#define DPA_AUX_CH_DATA1               0x64014
+#define DPA_AUX_CH_DATA2               0x64018
+#define DPA_AUX_CH_DATA3               0x6401c
+#define DPA_AUX_CH_DATA4               0x64020
+#define DPA_AUX_CH_DATA5               0x64024
+
 #define DPB_AUX_CH_CTL                 0x64110
 #define DPB_AUX_CH_DATA1               0x64114
 #define DPB_AUX_CH_DATA2               0x64118
 #define   DSPARB_CSTART_SHIFT  7
 #define   DSPARB_BSTART_MASK   (0x7f)
 #define   DSPARB_BSTART_SHIFT  0
+#define   DSPARB_BEND_SHIFT    9 /* on 855 */
+#define   DSPARB_AEND_SHIFT    0
+
+#define DSPFW1                 0x70034
+#define DSPFW2                 0x70038
+#define DSPFW3                 0x7003c
+#define   IGD_SELF_REFRESH_EN  (1<<30)
+
+/* FIFO watermark sizes etc */
+#define I915_FIFO_LINE_SIZE    64
+#define I830_FIFO_LINE_SIZE    32
+#define I945_FIFO_SIZE         127 /* 945 & 965 */
+#define I915_FIFO_SIZE         95
+#define I855GM_FIFO_SIZE       127 /* In cachelines */
+#define I830_FIFO_SIZE         95
+#define I915_MAX_WM            0x3f
+
+#define IGD_DISPLAY_FIFO       512 /* in 64byte unit */
+#define IGD_FIFO_LINE_SIZE     64
+#define IGD_MAX_WM             0x1ff
+#define IGD_DFT_WM             0x3f
+#define IGD_DFT_HPLLOFF_WM     0
+#define IGD_GUARD_WM           10
+#define IGD_CURSOR_FIFO                64
+#define IGD_CURSOR_MAX_WM      0x3f
+#define IGD_CURSOR_DFT_WM      0
+#define IGD_CURSOR_GUARD_WM    5
+
 /*
  * The two pipe frame counter registers are not synchronized, so
  * reading a stable value is somewhat tricky. The following code
 #define PFA_CTL_1               0x68080
 #define PFB_CTL_1               0x68880
 #define  PF_ENABLE              (1<<31)
+#define PFA_WIN_SZ             0x68074
+#define PFB_WIN_SZ             0x68874
 
 /* legacy palette */
 #define LGC_PALETTE_A           0x4a000
 #define PCH_PP_OFF_DELAYS      0xc720c
 #define PCH_PP_DIVISOR         0xc7210
 
+#define PCH_DP_B               0xe4100
+#define PCH_DPB_AUX_CH_CTL     0xe4110
+#define PCH_DPB_AUX_CH_DATA1   0xe4114
+#define PCH_DPB_AUX_CH_DATA2   0xe4118
+#define PCH_DPB_AUX_CH_DATA3   0xe411c
+#define PCH_DPB_AUX_CH_DATA4   0xe4120
+#define PCH_DPB_AUX_CH_DATA5   0xe4124
+
+#define PCH_DP_C               0xe4200
+#define PCH_DPC_AUX_CH_CTL     0xe4210
+#define PCH_DPC_AUX_CH_DATA1   0xe4214
+#define PCH_DPC_AUX_CH_DATA2   0xe4218
+#define PCH_DPC_AUX_CH_DATA3   0xe421c
+#define PCH_DPC_AUX_CH_DATA4   0xe4220
+#define PCH_DPC_AUX_CH_DATA5   0xe4224
+
+#define PCH_DP_D               0xe4300
+#define PCH_DPD_AUX_CH_CTL     0xe4310
+#define PCH_DPD_AUX_CH_DATA1   0xe4314
+#define PCH_DPD_AUX_CH_DATA2   0xe4318
+#define PCH_DPD_AUX_CH_DATA3   0xe431c
+#define PCH_DPD_AUX_CH_DATA4   0xe4320
+#define PCH_DPD_AUX_CH_DATA5   0xe4324
+
 #endif /* _I915_REG_H_ */
index a98e2831ed31787ee6985fb058bdc3d32725367c..1d04e1904ac69c7be338897a71d25900e44927d1 100644 (file)
@@ -222,23 +222,12 @@ static void i915_restore_vga(struct drm_device *dev)
        I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
 }
 
-int i915_save_state(struct drm_device *dev)
+static void i915_save_modeset_reg(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int i;
-
-       pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
-
-       /* Render Standby */
-       if (IS_I965G(dev) && IS_MOBILE(dev))
-               dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
-
-       /* Hardware status page */
-       dev_priv->saveHWS = I915_READ(HWS_PGA);
-
-       /* Display arbitration control */
-       dev_priv->saveDSPARB = I915_READ(DSPARB);
 
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return;
        /* Pipe & plane A info */
        dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
        dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
@@ -294,7 +283,122 @@ int i915_save_state(struct drm_device *dev)
        }
        i915_save_palette(dev, PIPE_B);
        dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
+       return;
+}
+static void i915_restore_modeset_reg(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               return;
+
+       /* Pipe & plane A info */
+       /* Prime the clock */
+       if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
+               I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
+                          ~DPLL_VCO_ENABLE);
+               DRM_UDELAY(150);
+       }
+       I915_WRITE(FPA0, dev_priv->saveFPA0);
+       I915_WRITE(FPA1, dev_priv->saveFPA1);
+       /* Actually enable it */
+       I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
+       DRM_UDELAY(150);
+       if (IS_I965G(dev))
+               I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
+       DRM_UDELAY(150);
+
+       /* Restore mode */
+       I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
+       I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
+       I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
+       I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
+       I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
+       I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
+       I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
+
+       /* Restore plane info */
+       I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
+       I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
+       I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
+       I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
+       I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
+       if (IS_I965G(dev)) {
+               I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
+               I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
+       }
+
+       I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
+
+       i915_restore_palette(dev, PIPE_A);
+       /* Enable the plane */
+       I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
+       I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
+
+       /* Pipe & plane B info */
+       if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
+               I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
+                          ~DPLL_VCO_ENABLE);
+               DRM_UDELAY(150);
+       }
+       I915_WRITE(FPB0, dev_priv->saveFPB0);
+       I915_WRITE(FPB1, dev_priv->saveFPB1);
+       /* Actually enable it */
+       I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
+       DRM_UDELAY(150);
+       if (IS_I965G(dev))
+               I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
+       DRM_UDELAY(150);
+
+       /* Restore mode */
+       I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
+       I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
+       I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
+       I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
+       I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
+       I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
+       I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
+
+       /* Restore plane info */
+       I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
+       I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
+       I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
+       I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
+       I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
+       if (IS_I965G(dev)) {
+               I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
+               I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
+       }
+
+       I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
+
+       i915_restore_palette(dev, PIPE_B);
+       /* Enable the plane */
+       I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
+       I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
 
+       return;
+}
+int i915_save_state(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int i;
+
+       pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
+
+       /* Render Standby */
+       if (IS_I965G(dev) && IS_MOBILE(dev))
+               dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
+
+       /* Hardware status page */
+       dev_priv->saveHWS = I915_READ(HWS_PGA);
+
+       /* Display arbitration control */
+       dev_priv->saveDSPARB = I915_READ(DSPARB);
+
+       /* This is only meaningful in non-KMS mode */
+       /* Don't save them in KMS mode */
+       i915_save_modeset_reg(dev);
        /* Cursor state */
        dev_priv->saveCURACNTR = I915_READ(CURACNTR);
        dev_priv->saveCURAPOS = I915_READ(CURAPOS);
@@ -322,6 +426,20 @@ int i915_save_state(struct drm_device *dev)
        dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
        dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR);
 
+       /* Display Port state */
+       if (SUPPORTS_INTEGRATED_DP(dev)) {
+               dev_priv->saveDP_B = I915_READ(DP_B);
+               dev_priv->saveDP_C = I915_READ(DP_C);
+               dev_priv->saveDP_D = I915_READ(DP_D);
+               dev_priv->savePIPEA_GMCH_DATA_M = I915_READ(PIPEA_GMCH_DATA_M);
+               dev_priv->savePIPEB_GMCH_DATA_M = I915_READ(PIPEB_GMCH_DATA_M);
+               dev_priv->savePIPEA_GMCH_DATA_N = I915_READ(PIPEA_GMCH_DATA_N);
+               dev_priv->savePIPEB_GMCH_DATA_N = I915_READ(PIPEB_GMCH_DATA_N);
+               dev_priv->savePIPEA_DP_LINK_M = I915_READ(PIPEA_DP_LINK_M);
+               dev_priv->savePIPEB_DP_LINK_M = I915_READ(PIPEB_DP_LINK_M);
+               dev_priv->savePIPEA_DP_LINK_N = I915_READ(PIPEA_DP_LINK_N);
+               dev_priv->savePIPEB_DP_LINK_N = I915_READ(PIPEB_DP_LINK_N);
+       }
        /* FIXME: save TV & SDVO state */
 
        /* FBC state */
@@ -404,92 +522,21 @@ int i915_restore_state(struct drm_device *dev)
                        for (i = 0; i < 8; i++)
                                I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]);
        }
-
-       /* Pipe & plane A info */
-       /* Prime the clock */
-       if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
-               I915_WRITE(DPLL_A, dev_priv->saveDPLL_A &
-                          ~DPLL_VCO_ENABLE);
-               DRM_UDELAY(150);
+       
+       /* Display port ratios (must be done before clock is set) */
+       if (SUPPORTS_INTEGRATED_DP(dev)) {
+               I915_WRITE(PIPEA_GMCH_DATA_M, dev_priv->savePIPEA_GMCH_DATA_M);
+               I915_WRITE(PIPEB_GMCH_DATA_M, dev_priv->savePIPEB_GMCH_DATA_M);
+               I915_WRITE(PIPEA_GMCH_DATA_N, dev_priv->savePIPEA_GMCH_DATA_N);
+               I915_WRITE(PIPEB_GMCH_DATA_N, dev_priv->savePIPEB_GMCH_DATA_N);
+               I915_WRITE(PIPEA_DP_LINK_M, dev_priv->savePIPEA_DP_LINK_M);
+               I915_WRITE(PIPEB_DP_LINK_M, dev_priv->savePIPEB_DP_LINK_M);
+               I915_WRITE(PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N);
+               I915_WRITE(PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N);
        }
-       I915_WRITE(FPA0, dev_priv->saveFPA0);
-       I915_WRITE(FPA1, dev_priv->saveFPA1);
-       /* Actually enable it */
-       I915_WRITE(DPLL_A, dev_priv->saveDPLL_A);
-       DRM_UDELAY(150);
-       if (IS_I965G(dev))
-               I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
-       DRM_UDELAY(150);
-
-       /* Restore mode */
-       I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
-       I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
-       I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
-       I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
-       I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
-       I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
-       I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
-
-       /* Restore plane info */
-       I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
-       I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
-       I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
-       I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
-       I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
-       if (IS_I965G(dev)) {
-               I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
-               I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
-       }
-
-       I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
-
-       i915_restore_palette(dev, PIPE_A);
-       /* Enable the plane */
-       I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
-       I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
-
-       /* Pipe & plane B info */
-       if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
-               I915_WRITE(DPLL_B, dev_priv->saveDPLL_B &
-                          ~DPLL_VCO_ENABLE);
-               DRM_UDELAY(150);
-       }
-       I915_WRITE(FPB0, dev_priv->saveFPB0);
-       I915_WRITE(FPB1, dev_priv->saveFPB1);
-       /* Actually enable it */
-       I915_WRITE(DPLL_B, dev_priv->saveDPLL_B);
-       DRM_UDELAY(150);
-       if (IS_I965G(dev))
-               I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
-       DRM_UDELAY(150);
-
-       /* Restore mode */
-       I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
-       I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
-       I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
-       I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
-       I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
-       I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
-       I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
-
-       /* Restore plane info */
-       I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
-       I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
-       I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
-       I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
-       I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
-       if (IS_I965G(dev)) {
-               I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
-               I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
-       }
-
-       I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
-
-       i915_restore_palette(dev, PIPE_B);
-       /* Enable the plane */
-       I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
-       I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
-
+       /* This is only meaningful in non-KMS mode */
+       /* Don't restore them in KMS mode */
+       i915_restore_modeset_reg(dev);
        /* Cursor state */
        I915_WRITE(CURAPOS, dev_priv->saveCURAPOS);
        I915_WRITE(CURACNTR, dev_priv->saveCURACNTR);
@@ -518,6 +565,12 @@ int i915_restore_state(struct drm_device *dev)
        I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR);
        I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL);
 
+       /* Display Port state */
+       if (SUPPORTS_INTEGRATED_DP(dev)) {
+               I915_WRITE(DP_B, dev_priv->saveDP_B);
+               I915_WRITE(DP_C, dev_priv->saveDP_C);
+               I915_WRITE(DP_D, dev_priv->saveDP_D);
+       }
        /* FIXME: restore TV & SDVO state */
 
        /* FBC info */
@@ -545,7 +598,7 @@ int i915_restore_state(struct drm_device *dev)
 
        for (i = 0; i < 16; i++) {
                I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
-               I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
+               I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i]);
        }
        for (i = 0; i < 3; i++)
                I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
index cdd126d068a7283577caf5338ffc5d6d8fe786f0..f806fcc54e09d3ad5a6e262b92530d6900a8afb6 100644 (file)
@@ -59,6 +59,16 @@ find_section(struct bdb_header *bdb, int section_id)
        return NULL;
 }
 
+static u16
+get_blocksize(void *p)
+{
+       u16 *block_ptr, block_size;
+
+       block_ptr = (u16 *)((char *)p - 2);
+       block_size = *block_ptr;
+       return block_size;
+}
+
 static void
 fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
                        struct lvds_dvo_timing *dvo_timing)
@@ -99,9 +109,11 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 {
        struct bdb_lvds_options *lvds_options;
        struct bdb_lvds_lfp_data *lvds_lfp_data;
+       struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
        struct bdb_lvds_lfp_data_entry *entry;
        struct lvds_dvo_timing *dvo_timing;
        struct drm_display_mode *panel_fixed_mode;
+       int lfp_data_size, dvo_timing_offset;
 
        /* Defaults if we can't find VBT info */
        dev_priv->lvds_dither = 0;
@@ -119,10 +131,27 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
        if (!lvds_lfp_data)
                return;
 
+       lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
+       if (!lvds_lfp_data_ptrs)
+               return;
+
        dev_priv->lvds_vbt = 1;
 
-       entry = &lvds_lfp_data->data[lvds_options->panel_type];
-       dvo_timing = &entry->dvo_timing;
+       lfp_data_size = lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset -
+               lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset;
+       entry = (struct bdb_lvds_lfp_data_entry *)
+               ((uint8_t *)lvds_lfp_data->data + (lfp_data_size *
+                                                  lvds_options->panel_type));
+       dvo_timing_offset = lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -
+               lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;
+
+       /*
+        * the size of fp_timing varies on the different platform.
+        * So calculate the DVO timing relative offset in LVDS data
+        * entry to get the DVO timing entry
+        */
+       dvo_timing = (struct lvds_dvo_timing *)
+                       ((unsigned char *)entry + dvo_timing_offset);
 
        panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
 
@@ -185,10 +214,47 @@ parse_general_features(struct drm_i915_private *dev_priv,
                dev_priv->lvds_use_ssc = general->enable_ssc;
 
                if (dev_priv->lvds_use_ssc) {
-                 if (IS_I855(dev_priv->dev))
-                   dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48;
-                 else
-                   dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96;
+                       if (IS_I85X(dev_priv->dev))
+                               dev_priv->lvds_ssc_freq =
+                                       general->ssc_freq ? 66 : 48;
+                       else
+                               dev_priv->lvds_ssc_freq =
+                                       general->ssc_freq ? 100 : 96;
+               }
+       }
+}
+
+static void
+parse_general_definitions(struct drm_i915_private *dev_priv,
+                         struct bdb_header *bdb)
+{
+       struct bdb_general_definitions *general;
+       const int crt_bus_map_table[] = {
+               GPIOB,
+               GPIOA,
+               GPIOC,
+               GPIOD,
+               GPIOE,
+               GPIOF,
+       };
+
+       /* Set sensible defaults in case we can't find the general block
+          or it is the wrong chipset */
+       dev_priv->crt_ddc_bus = -1;
+
+       general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+       if (general) {
+               u16 block_size = get_blocksize(general);
+               if (block_size >= sizeof(*general)) {
+                       int bus_pin = general->crt_ddc_gmbus_pin;
+                       DRM_DEBUG("crt_ddc_bus_pin: %d\n", bus_pin);
+                       if ((bus_pin >= 1) && (bus_pin <= 6)) {
+                               dev_priv->crt_ddc_bus =
+                                       crt_bus_map_table[bus_pin-1];
+                       }
+               } else {
+                       DRM_DEBUG("BDB_GD too small (%d). Invalid.\n",
+                                 block_size);
                }
        }
 }
@@ -201,7 +267,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
        struct bdb_general_definitions *p_defs;
        struct child_device_config *p_child;
        int i, child_device_num, count;
-       u16     block_size, *block_ptr;
+       u16     block_size;
 
        p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
        if (!p_defs) {
@@ -219,8 +285,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
                return;
        }
        /* get the block size of general definitions */
-       block_ptr = (u16 *)((char *)p_defs - 2);
-       block_size = *block_ptr;
+       block_size = get_blocksize(p_defs);
        /* get the number of child device */
        child_device_num = (block_size - sizeof(*p_defs)) /
                                sizeof(*p_child);
@@ -275,6 +340,25 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
        }
        return;
 }
+
+static void
+parse_driver_features(struct drm_i915_private *dev_priv,
+                      struct bdb_header *bdb)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct bdb_driver_features *driver;
+
+       /* set default for chips without eDP */
+       if (!SUPPORTS_EDP(dev)) {
+               dev_priv->edp_support = 0;
+               return;
+       }
+
+       driver = find_section(bdb, BDB_DRIVER_FEATURES);
+       if (driver && driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
+               dev_priv->edp_support = 1;
+}
+
 /**
  * intel_init_bios - initialize VBIOS settings & find VBT
  * @dev: DRM device
@@ -322,9 +406,12 @@ intel_init_bios(struct drm_device *dev)
 
        /* Grab useful general definitions */
        parse_general_features(dev_priv, bdb);
+       parse_general_definitions(dev_priv, bdb);
        parse_lfp_panel_data(dev_priv, bdb);
        parse_sdvo_panel_data(dev_priv, bdb);
        parse_sdvo_device_mapping(dev_priv, bdb);
+       parse_driver_features(dev_priv, bdb);
+
        pci_unmap_rom(pdev, bios);
 
        return 0;
index fe72e1c225d8ab1085a752f3ccbf6d298c44fca3..0f8e5f69ac7a315eb8eb8c4b9f377a87cc8e5f6c 100644 (file)
@@ -381,6 +381,51 @@ struct bdb_sdvo_lvds_options {
 } __attribute__((packed));
 
 
+#define BDB_DRIVER_FEATURE_NO_LVDS             0
+#define BDB_DRIVER_FEATURE_INT_LVDS            1
+#define BDB_DRIVER_FEATURE_SDVO_LVDS           2
+#define BDB_DRIVER_FEATURE_EDP                 3
+
+struct bdb_driver_features {
+       u8 boot_dev_algorithm:1;
+       u8 block_display_switch:1;
+       u8 allow_display_switch:1;
+       u8 hotplug_dvo:1;
+       u8 dual_view_zoom:1;
+       u8 int15h_hook:1;
+       u8 sprite_in_clone:1;
+       u8 primary_lfp_id:1;
+
+       u16 boot_mode_x;
+       u16 boot_mode_y;
+       u8 boot_mode_bpp;
+       u8 boot_mode_refresh;
+
+       u16 enable_lfp_primary:1;
+       u16 selective_mode_pruning:1;
+       u16 dual_frequency:1;
+       u16 render_clock_freq:1; /* 0: high freq; 1: low freq */
+       u16 nt_clone_support:1;
+       u16 power_scheme_ui:1; /* 0: CUI; 1: 3rd party */
+       u16 sprite_display_assign:1; /* 0: secondary; 1: primary */
+       u16 cui_aspect_scaling:1;
+       u16 preserve_aspect_ratio:1;
+       u16 sdvo_device_power_down:1;
+       u16 crt_hotplug:1;
+       u16 lvds_config:2;
+       u16 tv_hotplug:1;
+       u16 hdmi_config:2;
+
+       u8 static_display:1;
+       u8 reserved2:7;
+       u16 legacy_crt_max_x;
+       u16 legacy_crt_max_y;
+       u8 legacy_crt_max_refresh;
+
+       u8 hdmi_termination;
+       u8 custom_vbt_version;
+} __attribute__((packed));
+
 bool intel_init_bios(struct drm_device *dev);
 
 /*
index 6de97fc66029ed2f28707649f65dfd19ea87d042..590f81c8f59482b6e702d8b8191211e79cd8987b 100644 (file)
@@ -46,7 +46,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
 
        temp = I915_READ(reg);
        temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
-       temp |= ADPA_DAC_ENABLE;
+       temp &= ~ADPA_DAC_ENABLE;
 
        switch(mode) {
        case DRM_MODE_DPMS_ON:
@@ -156,6 +156,9 @@ static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector)
 
        temp = adpa = I915_READ(PCH_ADPA);
 
+       adpa &= ~ADPA_DAC_ENABLE;
+       I915_WRITE(PCH_ADPA, adpa);
+
        adpa &= ~ADPA_CRT_HOTPLUG_MASK;
 
        adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 |
@@ -169,13 +172,14 @@ static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector)
        DRM_DEBUG("pch crt adpa 0x%x", adpa);
        I915_WRITE(PCH_ADPA, adpa);
 
-       /* This might not be needed as not specified in spec...*/
-       udelay(1000);
+       while ((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) != 0)
+               ;
 
        /* Check the status to see if both blue and green are on now */
        adpa = I915_READ(PCH_ADPA);
-       if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) ==
-                       ADPA_CRT_HOTPLUG_MONITOR_COLOR)
+       adpa &= ADPA_CRT_HOTPLUG_MONITOR_MASK;
+       if ((adpa == ADPA_CRT_HOTPLUG_MONITOR_COLOR) ||
+               (adpa == ADPA_CRT_HOTPLUG_MONITOR_MONO))
                ret = true;
        else
                ret = false;
@@ -428,8 +432,34 @@ static void intel_crt_destroy(struct drm_connector *connector)
 
 static int intel_crt_get_modes(struct drm_connector *connector)
 {
+       int ret;
        struct intel_output *intel_output = to_intel_output(connector);
-       return intel_ddc_get_modes(intel_output);
+       struct i2c_adapter *ddcbus;
+       struct drm_device *dev = connector->dev;
+
+
+       ret = intel_ddc_get_modes(intel_output);
+       if (ret || !IS_G4X(dev))
+               goto end;
+
+       ddcbus = intel_output->ddc_bus;
+       /* Try to probe digital port for output in DVI-I -> VGA mode. */
+       intel_output->ddc_bus =
+               intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D");
+
+       if (!intel_output->ddc_bus) {
+               intel_output->ddc_bus = ddcbus;
+               dev_printk(KERN_ERR, &connector->dev->pdev->dev,
+                          "DDC bus registration failed for CRTDDC_D.\n");
+               goto end;
+       }
+       /* Try to get modes by GPIOD port */
+       ret = intel_ddc_get_modes(intel_output);
+       intel_i2c_destroy(ddcbus);
+
+end:
+       return ret;
+
 }
 
 static int intel_crt_set_property(struct drm_connector *connector,
@@ -478,6 +508,7 @@ void intel_crt_init(struct drm_device *dev)
 {
        struct drm_connector *connector;
        struct intel_output *intel_output;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        u32 i2c_reg;
 
        intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
@@ -497,8 +528,12 @@ void intel_crt_init(struct drm_device *dev)
        /* Set up the DDC bus. */
        if (IS_IGDNG(dev))
                i2c_reg = PCH_GPIOA;
-       else
+       else {
                i2c_reg = GPIOA;
+               /* Use VBT information for CRT DDC if available */
+               if (dev_priv->crt_ddc_bus != -1)
+                       i2c_reg = dev_priv->crt_ddc_bus;
+       }
        intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A");
        if (!intel_output->ddc_bus) {
                dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
@@ -507,6 +542,10 @@ void intel_crt_init(struct drm_device *dev)
        }
 
        intel_output->type = INTEL_OUTPUT_ANALOG;
+       intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+                                  (1 << INTEL_ANALOG_CLONE_BIT) |
+                                  (1 << INTEL_SDVO_LVDS_CLONE_BIT);
+       intel_output->crtc_mask = (1 << 0) | (1 << 1);
        connector->interlace_allowed = 0;
        connector->doublescan_allowed = 0;
 
index 3e1c7816211904391c1b65a43a7aace7726db5fc..748ed50c55ca9c67683dcbdca233f6fb4aaa6e41 100644 (file)
  */
 
 #include <linux/i2c.h>
+#include <linux/kernel.h>
 #include "drmP.h"
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
+#include "intel_dp.h"
 
 #include "drm_crtc_helper.h"
 
+#define HAS_eDP (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
+
 bool intel_pipe_has_type (struct drm_crtc *crtc, int type);
+static void intel_update_watermarks(struct drm_device *dev);
 
 typedef struct {
     /* given values */
@@ -85,7 +90,7 @@ struct intel_limit {
 #define I8XX_P2_SLOW                 4
 #define I8XX_P2_FAST                 2
 #define I8XX_P2_LVDS_SLOW            14
-#define I8XX_P2_LVDS_FAST            14 /* No fast option */
+#define I8XX_P2_LVDS_FAST            7
 #define I8XX_P2_SLOW_LIMIT      165000
 
 #define I9XX_DOT_MIN             20000
@@ -127,19 +132,6 @@ struct intel_limit {
 #define I9XX_P2_LVDS_FAST                    7
 #define I9XX_P2_LVDS_SLOW_LIMIT                 112000
 
-#define INTEL_LIMIT_I8XX_DVO_DAC    0
-#define INTEL_LIMIT_I8XX_LVDS      1
-#define INTEL_LIMIT_I9XX_SDVO_DAC   2
-#define INTEL_LIMIT_I9XX_LVDS      3
-#define INTEL_LIMIT_G4X_SDVO       4
-#define INTEL_LIMIT_G4X_HDMI_DAC   5
-#define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS   6
-#define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS   7
-#define INTEL_LIMIT_IGD_SDVO_DAC    8
-#define INTEL_LIMIT_IGD_LVDS       9
-#define INTEL_LIMIT_IGDNG_SDVO_DAC  10
-#define INTEL_LIMIT_IGDNG_LVDS     11
-
 /*The parameter is for SDVO on G4x platform*/
 #define G4X_DOT_SDVO_MIN           25000
 #define G4X_DOT_SDVO_MAX           270000
@@ -218,6 +210,25 @@ struct intel_limit {
 #define G4X_P2_DUAL_CHANNEL_LVDS_FAST           7
 #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT          0
 
+/*The parameter is for DISPLAY PORT on G4x platform*/
+#define G4X_DOT_DISPLAY_PORT_MIN           161670
+#define G4X_DOT_DISPLAY_PORT_MAX           227000
+#define G4X_N_DISPLAY_PORT_MIN             1
+#define G4X_N_DISPLAY_PORT_MAX             2
+#define G4X_M_DISPLAY_PORT_MIN             97
+#define G4X_M_DISPLAY_PORT_MAX             108
+#define G4X_M1_DISPLAY_PORT_MIN            0x10
+#define G4X_M1_DISPLAY_PORT_MAX            0x12
+#define G4X_M2_DISPLAY_PORT_MIN            0x05
+#define G4X_M2_DISPLAY_PORT_MAX            0x06
+#define G4X_P_DISPLAY_PORT_MIN             10
+#define G4X_P_DISPLAY_PORT_MAX             20
+#define G4X_P1_DISPLAY_PORT_MIN            1
+#define G4X_P1_DISPLAY_PORT_MAX            2
+#define G4X_P2_DISPLAY_PORT_SLOW           10
+#define G4X_P2_DISPLAY_PORT_FAST           10
+#define G4X_P2_DISPLAY_PORT_LIMIT          0
+
 /* IGDNG */
 /* as we calculate clock using (register_value + 2) for
    N/M1/M2, so here the range value for them is (actual_value-2).
@@ -256,8 +267,14 @@ static bool
 intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
                        int target, int refclk, intel_clock_t *best_clock);
 
-static const intel_limit_t intel_limits[] = {
-    { /* INTEL_LIMIT_I8XX_DVO_DAC */
+static bool
+intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc,
+                     int target, int refclk, intel_clock_t *best_clock);
+static bool
+intel_find_pll_igdng_dp(const intel_limit_t *, struct drm_crtc *crtc,
+                     int target, int refclk, intel_clock_t *best_clock);
+
+static const intel_limit_t intel_limits_i8xx_dvo = {
         .dot = { .min = I8XX_DOT_MIN,          .max = I8XX_DOT_MAX },
         .vco = { .min = I8XX_VCO_MIN,          .max = I8XX_VCO_MAX },
         .n   = { .min = I8XX_N_MIN,            .max = I8XX_N_MAX },
@@ -269,8 +286,9 @@ static const intel_limit_t intel_limits[] = {
        .p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
                 .p2_slow = I8XX_P2_SLOW,       .p2_fast = I8XX_P2_FAST },
        .find_pll = intel_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_I8XX_LVDS */
+};
+
+static const intel_limit_t intel_limits_i8xx_lvds = {
         .dot = { .min = I8XX_DOT_MIN,          .max = I8XX_DOT_MAX },
         .vco = { .min = I8XX_VCO_MIN,          .max = I8XX_VCO_MAX },
         .n   = { .min = I8XX_N_MIN,            .max = I8XX_N_MAX },
@@ -282,8 +300,9 @@ static const intel_limit_t intel_limits[] = {
        .p2  = { .dot_limit = I8XX_P2_SLOW_LIMIT,
                 .p2_slow = I8XX_P2_LVDS_SLOW,  .p2_fast = I8XX_P2_LVDS_FAST },
        .find_pll = intel_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_I9XX_SDVO_DAC */
+};
+       
+static const intel_limit_t intel_limits_i9xx_sdvo = {
         .dot = { .min = I9XX_DOT_MIN,          .max = I9XX_DOT_MAX },
         .vco = { .min = I9XX_VCO_MIN,          .max = I9XX_VCO_MAX },
         .n   = { .min = I9XX_N_MIN,            .max = I9XX_N_MAX },
@@ -295,8 +314,9 @@ static const intel_limit_t intel_limits[] = {
        .p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
                 .p2_slow = I9XX_P2_SDVO_DAC_SLOW,      .p2_fast = I9XX_P2_SDVO_DAC_FAST },
        .find_pll = intel_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_I9XX_LVDS */
+};
+
+static const intel_limit_t intel_limits_i9xx_lvds = {
         .dot = { .min = I9XX_DOT_MIN,          .max = I9XX_DOT_MAX },
         .vco = { .min = I9XX_VCO_MIN,          .max = I9XX_VCO_MAX },
         .n   = { .min = I9XX_N_MIN,            .max = I9XX_N_MAX },
@@ -311,9 +331,10 @@ static const intel_limit_t intel_limits[] = {
        .p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
                 .p2_slow = I9XX_P2_LVDS_SLOW,  .p2_fast = I9XX_P2_LVDS_FAST },
        .find_pll = intel_find_best_PLL,
-    },
+};
+
     /* below parameter and function is for G4X Chipset Family*/
-    { /* INTEL_LIMIT_G4X_SDVO */
+static const intel_limit_t intel_limits_g4x_sdvo = {
        .dot = { .min = G4X_DOT_SDVO_MIN,       .max = G4X_DOT_SDVO_MAX },
        .vco = { .min = G4X_VCO_MIN,            .max = G4X_VCO_MAX},
        .n   = { .min = G4X_N_SDVO_MIN,         .max = G4X_N_SDVO_MAX },
@@ -327,8 +348,9 @@ static const intel_limit_t intel_limits[] = {
                 .p2_fast = G4X_P2_SDVO_FAST
        },
        .find_pll = intel_g4x_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_G4X_HDMI_DAC */
+};
+
+static const intel_limit_t intel_limits_g4x_hdmi = {
        .dot = { .min = G4X_DOT_HDMI_DAC_MIN,   .max = G4X_DOT_HDMI_DAC_MAX },
        .vco = { .min = G4X_VCO_MIN,            .max = G4X_VCO_MAX},
        .n   = { .min = G4X_N_HDMI_DAC_MIN,     .max = G4X_N_HDMI_DAC_MAX },
@@ -342,8 +364,9 @@ static const intel_limit_t intel_limits[] = {
                 .p2_fast = G4X_P2_HDMI_DAC_FAST
        },
        .find_pll = intel_g4x_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS */
+};
+
+static const intel_limit_t intel_limits_g4x_single_channel_lvds = {
        .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN,
                 .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX },
        .vco = { .min = G4X_VCO_MIN,
@@ -365,8 +388,9 @@ static const intel_limit_t intel_limits[] = {
                 .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST
        },
        .find_pll = intel_g4x_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS */
+};
+
+static const intel_limit_t intel_limits_g4x_dual_channel_lvds = {
        .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN,
                 .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX },
        .vco = { .min = G4X_VCO_MIN,
@@ -388,8 +412,32 @@ static const intel_limit_t intel_limits[] = {
                 .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST
        },
        .find_pll = intel_g4x_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_IGD_SDVO */
+};
+
+static const intel_limit_t intel_limits_g4x_display_port = {
+        .dot = { .min = G4X_DOT_DISPLAY_PORT_MIN,
+                 .max = G4X_DOT_DISPLAY_PORT_MAX },
+        .vco = { .min = G4X_VCO_MIN,
+                 .max = G4X_VCO_MAX},
+        .n   = { .min = G4X_N_DISPLAY_PORT_MIN,
+                 .max = G4X_N_DISPLAY_PORT_MAX },
+        .m   = { .min = G4X_M_DISPLAY_PORT_MIN,
+                 .max = G4X_M_DISPLAY_PORT_MAX },
+        .m1  = { .min = G4X_M1_DISPLAY_PORT_MIN,
+                 .max = G4X_M1_DISPLAY_PORT_MAX },
+        .m2  = { .min = G4X_M2_DISPLAY_PORT_MIN,
+                 .max = G4X_M2_DISPLAY_PORT_MAX },
+        .p   = { .min = G4X_P_DISPLAY_PORT_MIN,
+                 .max = G4X_P_DISPLAY_PORT_MAX },
+        .p1  = { .min = G4X_P1_DISPLAY_PORT_MIN,
+                 .max = G4X_P1_DISPLAY_PORT_MAX},
+        .p2  = { .dot_limit = G4X_P2_DISPLAY_PORT_LIMIT,
+                 .p2_slow = G4X_P2_DISPLAY_PORT_SLOW,
+                 .p2_fast = G4X_P2_DISPLAY_PORT_FAST },
+        .find_pll = intel_find_pll_g4x_dp,
+};
+
+static const intel_limit_t intel_limits_igd_sdvo = {
         .dot = { .min = I9XX_DOT_MIN,          .max = I9XX_DOT_MAX},
         .vco = { .min = IGD_VCO_MIN,           .max = IGD_VCO_MAX },
         .n   = { .min = IGD_N_MIN,             .max = IGD_N_MAX },
@@ -401,8 +449,9 @@ static const intel_limit_t intel_limits[] = {
        .p2  = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
                 .p2_slow = I9XX_P2_SDVO_DAC_SLOW,      .p2_fast = I9XX_P2_SDVO_DAC_FAST },
        .find_pll = intel_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_IGD_LVDS */
+};
+
+static const intel_limit_t intel_limits_igd_lvds = {
         .dot = { .min = I9XX_DOT_MIN,          .max = I9XX_DOT_MAX },
         .vco = { .min = IGD_VCO_MIN,           .max = IGD_VCO_MAX },
         .n   = { .min = IGD_N_MIN,             .max = IGD_N_MAX },
@@ -415,8 +464,9 @@ static const intel_limit_t intel_limits[] = {
        .p2  = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
                 .p2_slow = I9XX_P2_LVDS_SLOW,  .p2_fast = I9XX_P2_LVDS_SLOW },
        .find_pll = intel_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_IGDNG_SDVO_DAC */
+};
+
+static const intel_limit_t intel_limits_igdng_sdvo = {
        .dot = { .min = IGDNG_DOT_MIN,          .max = IGDNG_DOT_MAX },
        .vco = { .min = IGDNG_VCO_MIN,          .max = IGDNG_VCO_MAX },
        .n   = { .min = IGDNG_N_MIN,            .max = IGDNG_N_MAX },
@@ -429,8 +479,9 @@ static const intel_limit_t intel_limits[] = {
                 .p2_slow = IGDNG_P2_SDVO_DAC_SLOW,
                 .p2_fast = IGDNG_P2_SDVO_DAC_FAST },
        .find_pll = intel_igdng_find_best_PLL,
-    },
-    { /* INTEL_LIMIT_IGDNG_LVDS */
+};
+
+static const intel_limit_t intel_limits_igdng_lvds = {
        .dot = { .min = IGDNG_DOT_MIN,          .max = IGDNG_DOT_MAX },
        .vco = { .min = IGDNG_VCO_MIN,          .max = IGDNG_VCO_MAX },
        .n   = { .min = IGDNG_N_MIN,            .max = IGDNG_N_MAX },
@@ -443,16 +494,15 @@ static const intel_limit_t intel_limits[] = {
                 .p2_slow = IGDNG_P2_LVDS_SLOW,
                 .p2_fast = IGDNG_P2_LVDS_FAST },
        .find_pll = intel_igdng_find_best_PLL,
-    },
 };
 
 static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc)
 {
        const intel_limit_t *limit;
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
-               limit = &intel_limits[INTEL_LIMIT_IGDNG_LVDS];
+               limit = &intel_limits_igdng_lvds;
        else
-               limit = &intel_limits[INTEL_LIMIT_IGDNG_SDVO_DAC];
+               limit = &intel_limits_igdng_sdvo;
 
        return limit;
 }
@@ -467,19 +517,19 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)
                if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
                    LVDS_CLKB_POWER_UP)
                        /* LVDS with dual channel */
-                       limit = &intel_limits
-                                       [INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS];
+                       limit = &intel_limits_g4x_dual_channel_lvds;
                else
                        /* LVDS with dual channel */
-                       limit = &intel_limits
-                                       [INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS];
+                       limit = &intel_limits_g4x_single_channel_lvds;
        } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) ||
                   intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) {
-               limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC];
+               limit = &intel_limits_g4x_hdmi;
        } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) {
-               limit = &intel_limits[INTEL_LIMIT_G4X_SDVO];
+               limit = &intel_limits_g4x_sdvo;
+       } else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+               limit = &intel_limits_g4x_display_port;
        } else /* The option is for other outputs */
-               limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
+               limit = &intel_limits_i9xx_sdvo;
 
        return limit;
 }
@@ -495,19 +545,19 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
                limit = intel_g4x_limit(crtc);
        } else if (IS_I9XX(dev) && !IS_IGD(dev)) {
                if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
-                       limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS];
+                       limit = &intel_limits_i9xx_lvds;
                else
-                       limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
+                       limit = &intel_limits_i9xx_sdvo;
        } else if (IS_IGD(dev)) {
                if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
-                       limit = &intel_limits[INTEL_LIMIT_IGD_LVDS];
+                       limit = &intel_limits_igd_lvds;
                else
-                       limit = &intel_limits[INTEL_LIMIT_IGD_SDVO_DAC];
+                       limit = &intel_limits_igd_sdvo;
        } else {
                if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
-                       limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS];
+                       limit = &intel_limits_i8xx_lvds;
                else
-                       limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC];
+                       limit = &intel_limits_i8xx_dvo;
        }
        return limit;
 }
@@ -553,6 +603,23 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
     return false;
 }
 
+struct drm_connector *
+intel_pipe_get_output (struct drm_crtc *crtc)
+{
+    struct drm_device *dev = crtc->dev;
+    struct drm_mode_config *mode_config = &dev->mode_config;
+    struct drm_connector *l_entry, *ret = NULL;
+
+    list_for_each_entry(l_entry, &mode_config->connector_list, head) {
+           if (l_entry->encoder &&
+               l_entry->encoder->crtc == crtc) {
+                   ret = l_entry;
+                   break;
+           }
+    }
+    return ret;
+}
+
 #define INTELPllInvalid(s)   do { /* DRM_DEBUG(s); */ return false; } while (0)
 /**
  * Returns whether the given set of divisors are valid for a given refclk with
@@ -599,8 +666,8 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
        intel_clock_t clock;
        int err = target;
 
-       if (IS_I9XX(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
-           (I915_READ(LVDS) & LVDS_PORT_EN) != 0) {
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+           (I915_READ(LVDS)) != 0) {
                /*
                 * For LVDS, if the panel is on, just rely on its current
                 * settings for dual-channel.  We haven't figured out how to
@@ -706,6 +773,30 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
        return found;
 }
 
+static bool
+intel_find_pll_igdng_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
+                     int target, int refclk, intel_clock_t *best_clock)
+{
+       struct drm_device *dev = crtc->dev;
+       intel_clock_t clock;
+       if (target < 200000) {
+               clock.n = 1;
+               clock.p1 = 2;
+               clock.p2 = 10;
+               clock.m1 = 12;
+               clock.m2 = 9;
+       } else {
+               clock.n = 2;
+               clock.p1 = 1;
+               clock.p2 = 10;
+               clock.m1 = 14;
+               clock.m2 = 8;
+       }
+       intel_clock(dev, refclk, &clock);
+       memcpy(best_clock, &clock, sizeof(intel_clock_t));
+       return true;
+}
+
 static bool
 intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
                        int target, int refclk, intel_clock_t *best_clock)
@@ -718,6 +809,14 @@ intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
        int err_most = 47;
        found = false;
 
+       /* eDP has only 2 clock choice, no n/m/p setting */
+       if (HAS_eDP)
+               return true;
+
+       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
+               return intel_find_pll_igdng_dp(limit, crtc, target,
+                                              refclk, best_clock);
+
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
                if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
                    LVDS_CLKB_POWER_UP)
@@ -764,6 +863,32 @@ out:
        return found;
 }
 
+/* DisplayPort has only two frequencies, 162MHz and 270MHz */
+static bool
+intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
+                     int target, int refclk, intel_clock_t *best_clock)
+{
+    intel_clock_t clock;
+    if (target < 200000) {
+       clock.p1 = 2;
+       clock.p2 = 10;
+       clock.n = 2;
+       clock.m1 = 23;
+       clock.m2 = 8;
+    } else {
+       clock.p1 = 1;
+       clock.p2 = 10;
+       clock.n = 1;
+       clock.m1 = 14;
+       clock.m2 = 2;
+    }
+    clock.m = 5 * (clock.m1 + 2) + (clock.m2 + 2);
+    clock.p = (clock.p1 * clock.p2);
+    clock.dot = 96000 * clock.m / (clock.n + 2) / clock.p;
+    memcpy(best_clock, &clock, sizeof(intel_clock_t));
+    return true;
+}
+
 void
 intel_wait_for_vblank(struct drm_device *dev)
 {
@@ -927,13 +1052,97 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        return 0;
 }
 
+/* Disable the VGA plane that we never use */
+static void i915_disable_vga (struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u8 sr1;
+       u32 vga_reg;
+
+       if (IS_IGDNG(dev))
+               vga_reg = CPU_VGACNTRL;
+       else
+               vga_reg = VGACNTRL;
+
+       if (I915_READ(vga_reg) & VGA_DISP_DISABLE)
+               return;
+
+       I915_WRITE8(VGA_SR_INDEX, 1);
+       sr1 = I915_READ8(VGA_SR_DATA);
+       I915_WRITE8(VGA_SR_DATA, sr1 | (1 << 5));
+       udelay(100);
+
+       I915_WRITE(vga_reg, VGA_DISP_DISABLE);
+}
+
+static void igdng_disable_pll_edp (struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 dpa_ctl;
+
+       DRM_DEBUG("\n");
+       dpa_ctl = I915_READ(DP_A);
+       dpa_ctl &= ~DP_PLL_ENABLE;
+       I915_WRITE(DP_A, dpa_ctl);
+}
+
+static void igdng_enable_pll_edp (struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 dpa_ctl;
+
+       dpa_ctl = I915_READ(DP_A);
+       dpa_ctl |= DP_PLL_ENABLE;
+       I915_WRITE(DP_A, dpa_ctl);
+       udelay(200);
+}
+
+
+static void igdng_set_pll_edp (struct drm_crtc *crtc, int clock)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 dpa_ctl;
+
+       DRM_DEBUG("eDP PLL enable for clock %d\n", clock);
+       dpa_ctl = I915_READ(DP_A);
+       dpa_ctl &= ~DP_PLL_FREQ_MASK;
+
+       if (clock < 200000) {
+               u32 temp;
+               dpa_ctl |= DP_PLL_FREQ_160MHZ;
+               /* workaround for 160Mhz:
+                  1) program 0x4600c bits 15:0 = 0x8124
+                  2) program 0x46010 bit 0 = 1
+                  3) program 0x46034 bit 24 = 1
+                  4) program 0x64000 bit 14 = 1
+                  */
+               temp = I915_READ(0x4600c);
+               temp &= 0xffff0000;
+               I915_WRITE(0x4600c, temp | 0x8124);
+
+               temp = I915_READ(0x46010);
+               I915_WRITE(0x46010, temp | 1);
+
+               temp = I915_READ(0x46034);
+               I915_WRITE(0x46034, temp | (1 << 24));
+       } else {
+               dpa_ctl |= DP_PLL_FREQ_270MHZ;
+       }
+       I915_WRITE(DP_A, dpa_ctl);
+
+       udelay(500);
+}
+
 static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       int plane = intel_crtc->pipe;
+       int plane = intel_crtc->plane;
        int pch_dpll_reg = (pipe == 0) ? PCH_DPLL_A : PCH_DPLL_B;
        int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
        int dspcntr_reg = (plane == 0) ? DSPACNTR : DSPBCNTR;
@@ -944,6 +1153,7 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
        int fdi_rx_imr_reg = (pipe == 0) ? FDI_RXA_IMR : FDI_RXB_IMR;
        int transconf_reg = (pipe == 0) ? TRANSACONF : TRANSBCONF;
        int pf_ctl_reg = (pipe == 0) ? PFA_CTL_1 : PFB_CTL_1;
+       int pf_win_size = (pipe == 0) ? PFA_WIN_SZ : PFB_WIN_SZ;
        int cpu_htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
        int cpu_hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
        int cpu_hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
@@ -957,7 +1167,7 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
        int trans_vblank_reg = (pipe == 0) ? TRANS_VBLANK_A : TRANS_VBLANK_B;
        int trans_vsync_reg = (pipe == 0) ? TRANS_VSYNC_A : TRANS_VSYNC_B;
        u32 temp;
-       int tries = 5, j;
+       int tries = 5, j, n;
 
        /* XXX: When our outputs are all unaware of DPMS modes other than off
         * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
@@ -967,27 +1177,32 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
                DRM_DEBUG("crtc %d dpms on\n", pipe);
-               /* enable PCH DPLL */
-               temp = I915_READ(pch_dpll_reg);
-               if ((temp & DPLL_VCO_ENABLE) == 0) {
-                       I915_WRITE(pch_dpll_reg, temp | DPLL_VCO_ENABLE);
-                       I915_READ(pch_dpll_reg);
-               }
-
-               /* enable PCH FDI RX PLL, wait warmup plus DMI latency */
-               temp = I915_READ(fdi_rx_reg);
-               I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE |
-                               FDI_SEL_PCDCLK |
-                               FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */
-               I915_READ(fdi_rx_reg);
-               udelay(200);
+               if (HAS_eDP) {
+                       /* enable eDP PLL */
+                       igdng_enable_pll_edp(crtc);
+               } else {
+                       /* enable PCH DPLL */
+                       temp = I915_READ(pch_dpll_reg);
+                       if ((temp & DPLL_VCO_ENABLE) == 0) {
+                               I915_WRITE(pch_dpll_reg, temp | DPLL_VCO_ENABLE);
+                               I915_READ(pch_dpll_reg);
+                       }
 
-               /* Enable CPU FDI TX PLL, always on for IGDNG */
-               temp = I915_READ(fdi_tx_reg);
-               if ((temp & FDI_TX_PLL_ENABLE) == 0) {
-                       I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE);
-                       I915_READ(fdi_tx_reg);
-                       udelay(100);
+                       /* enable PCH FDI RX PLL, wait warmup plus DMI latency */
+                       temp = I915_READ(fdi_rx_reg);
+                       I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE |
+                                       FDI_SEL_PCDCLK |
+                                       FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */
+                       I915_READ(fdi_rx_reg);
+                       udelay(200);
+
+                       /* Enable CPU FDI TX PLL, always on for IGDNG */
+                       temp = I915_READ(fdi_tx_reg);
+                       if ((temp & FDI_TX_PLL_ENABLE) == 0) {
+                               I915_WRITE(fdi_tx_reg, temp | FDI_TX_PLL_ENABLE);
+                               I915_READ(fdi_tx_reg);
+                               udelay(100);
+                       }
                }
 
                /* Enable CPU pipe */
@@ -1006,122 +1221,126 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
                        I915_WRITE(dspbase_reg, I915_READ(dspbase_reg));
                }
 
-               /* enable CPU FDI TX and PCH FDI RX */
-               temp = I915_READ(fdi_tx_reg);
-               temp |= FDI_TX_ENABLE;
-               temp |= FDI_DP_PORT_WIDTH_X4; /* default */
-               temp &= ~FDI_LINK_TRAIN_NONE;
-               temp |= FDI_LINK_TRAIN_PATTERN_1;
-               I915_WRITE(fdi_tx_reg, temp);
-               I915_READ(fdi_tx_reg);
+               if (!HAS_eDP) {
+                       /* enable CPU FDI TX and PCH FDI RX */
+                       temp = I915_READ(fdi_tx_reg);
+                       temp |= FDI_TX_ENABLE;
+                       temp |= FDI_DP_PORT_WIDTH_X4; /* default */
+                       temp &= ~FDI_LINK_TRAIN_NONE;
+                       temp |= FDI_LINK_TRAIN_PATTERN_1;
+                       I915_WRITE(fdi_tx_reg, temp);
+                       I915_READ(fdi_tx_reg);
 
-               temp = I915_READ(fdi_rx_reg);
-               temp &= ~FDI_LINK_TRAIN_NONE;
-               temp |= FDI_LINK_TRAIN_PATTERN_1;
-               I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE);
-               I915_READ(fdi_rx_reg);
+                       temp = I915_READ(fdi_rx_reg);
+                       temp &= ~FDI_LINK_TRAIN_NONE;
+                       temp |= FDI_LINK_TRAIN_PATTERN_1;
+                       I915_WRITE(fdi_rx_reg, temp | FDI_RX_ENABLE);
+                       I915_READ(fdi_rx_reg);
 
-               udelay(150);
+                       udelay(150);
 
-               /* Train FDI. */
-               /* umask FDI RX Interrupt symbol_lock and bit_lock bit
-                  for train result */
-               temp = I915_READ(fdi_rx_imr_reg);
-               temp &= ~FDI_RX_SYMBOL_LOCK;
-               temp &= ~FDI_RX_BIT_LOCK;
-               I915_WRITE(fdi_rx_imr_reg, temp);
-               I915_READ(fdi_rx_imr_reg);
-               udelay(150);
+                       /* Train FDI. */
+                       /* umask FDI RX Interrupt symbol_lock and bit_lock bit
+                          for train result */
+                       temp = I915_READ(fdi_rx_imr_reg);
+                       temp &= ~FDI_RX_SYMBOL_LOCK;
+                       temp &= ~FDI_RX_BIT_LOCK;
+                       I915_WRITE(fdi_rx_imr_reg, temp);
+                       I915_READ(fdi_rx_imr_reg);
+                       udelay(150);
 
-               temp = I915_READ(fdi_rx_iir_reg);
-               DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
+                       temp = I915_READ(fdi_rx_iir_reg);
+                       DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
 
-               if ((temp & FDI_RX_BIT_LOCK) == 0) {
-                       for (j = 0; j < tries; j++) {
-                               temp = I915_READ(fdi_rx_iir_reg);
-                               DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
-                               if (temp & FDI_RX_BIT_LOCK)
-                                       break;
-                               udelay(200);
-                       }
-                       if (j != tries)
+                       if ((temp & FDI_RX_BIT_LOCK) == 0) {
+                               for (j = 0; j < tries; j++) {
+                                       temp = I915_READ(fdi_rx_iir_reg);
+                                       DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
+                                       if (temp & FDI_RX_BIT_LOCK)
+                                               break;
+                                       udelay(200);
+                               }
+                               if (j != tries)
+                                       I915_WRITE(fdi_rx_iir_reg,
+                                                       temp | FDI_RX_BIT_LOCK);
+                               else
+                                       DRM_DEBUG("train 1 fail\n");
+                       } else {
                                I915_WRITE(fdi_rx_iir_reg,
                                                temp | FDI_RX_BIT_LOCK);
-                       else
-                               DRM_DEBUG("train 1 fail\n");
-               } else {
-                       I915_WRITE(fdi_rx_iir_reg,
-                                       temp | FDI_RX_BIT_LOCK);
-                       DRM_DEBUG("train 1 ok 2!\n");
-               }
-               temp = I915_READ(fdi_tx_reg);
-               temp &= ~FDI_LINK_TRAIN_NONE;
-               temp |= FDI_LINK_TRAIN_PATTERN_2;
-               I915_WRITE(fdi_tx_reg, temp);
-
-               temp = I915_READ(fdi_rx_reg);
-               temp &= ~FDI_LINK_TRAIN_NONE;
-               temp |= FDI_LINK_TRAIN_PATTERN_2;
-               I915_WRITE(fdi_rx_reg, temp);
+                               DRM_DEBUG("train 1 ok 2!\n");
+                       }
+                       temp = I915_READ(fdi_tx_reg);
+                       temp &= ~FDI_LINK_TRAIN_NONE;
+                       temp |= FDI_LINK_TRAIN_PATTERN_2;
+                       I915_WRITE(fdi_tx_reg, temp);
+
+                       temp = I915_READ(fdi_rx_reg);
+                       temp &= ~FDI_LINK_TRAIN_NONE;
+                       temp |= FDI_LINK_TRAIN_PATTERN_2;
+                       I915_WRITE(fdi_rx_reg, temp);
 
-               udelay(150);
+                       udelay(150);
 
-               temp = I915_READ(fdi_rx_iir_reg);
-               DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
+                       temp = I915_READ(fdi_rx_iir_reg);
+                       DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
 
-               if ((temp & FDI_RX_SYMBOL_LOCK) == 0) {
-                       for (j = 0; j < tries; j++) {
-                               temp = I915_READ(fdi_rx_iir_reg);
-                               DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
-                               if (temp & FDI_RX_SYMBOL_LOCK)
-                                       break;
-                               udelay(200);
-                       }
-                       if (j != tries) {
+                       if ((temp & FDI_RX_SYMBOL_LOCK) == 0) {
+                               for (j = 0; j < tries; j++) {
+                                       temp = I915_READ(fdi_rx_iir_reg);
+                                       DRM_DEBUG("FDI_RX_IIR 0x%x\n", temp);
+                                       if (temp & FDI_RX_SYMBOL_LOCK)
+                                               break;
+                                       udelay(200);
+                               }
+                               if (j != tries) {
+                                       I915_WRITE(fdi_rx_iir_reg,
+                                                       temp | FDI_RX_SYMBOL_LOCK);
+                                       DRM_DEBUG("train 2 ok 1!\n");
+                               } else
+                                       DRM_DEBUG("train 2 fail\n");
+                       } else {
                                I915_WRITE(fdi_rx_iir_reg,
                                                temp | FDI_RX_SYMBOL_LOCK);
-                               DRM_DEBUG("train 2 ok 1!\n");
-                       } else
-                               DRM_DEBUG("train 2 fail\n");
-               } else {
-                       I915_WRITE(fdi_rx_iir_reg, temp | FDI_RX_SYMBOL_LOCK);
-                       DRM_DEBUG("train 2 ok 2!\n");
-               }
-               DRM_DEBUG("train done\n");
+                               DRM_DEBUG("train 2 ok 2!\n");
+                       }
+                       DRM_DEBUG("train done\n");
 
-               /* set transcoder timing */
-               I915_WRITE(trans_htot_reg, I915_READ(cpu_htot_reg));
-               I915_WRITE(trans_hblank_reg, I915_READ(cpu_hblank_reg));
-               I915_WRITE(trans_hsync_reg, I915_READ(cpu_hsync_reg));
+                       /* set transcoder timing */
+                       I915_WRITE(trans_htot_reg, I915_READ(cpu_htot_reg));
+                       I915_WRITE(trans_hblank_reg, I915_READ(cpu_hblank_reg));
+                       I915_WRITE(trans_hsync_reg, I915_READ(cpu_hsync_reg));
 
-               I915_WRITE(trans_vtot_reg, I915_READ(cpu_vtot_reg));
-               I915_WRITE(trans_vblank_reg, I915_READ(cpu_vblank_reg));
-               I915_WRITE(trans_vsync_reg, I915_READ(cpu_vsync_reg));
+                       I915_WRITE(trans_vtot_reg, I915_READ(cpu_vtot_reg));
+                       I915_WRITE(trans_vblank_reg, I915_READ(cpu_vblank_reg));
+                       I915_WRITE(trans_vsync_reg, I915_READ(cpu_vsync_reg));
 
-               /* enable PCH transcoder */
-               temp = I915_READ(transconf_reg);
-               I915_WRITE(transconf_reg, temp | TRANS_ENABLE);
-               I915_READ(transconf_reg);
+                       /* enable PCH transcoder */
+                       temp = I915_READ(transconf_reg);
+                       I915_WRITE(transconf_reg, temp | TRANS_ENABLE);
+                       I915_READ(transconf_reg);
 
-               while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0)
-                       ;
+                       while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) == 0)
+                               ;
 
-               /* enable normal */
+                       /* enable normal */
 
-               temp = I915_READ(fdi_tx_reg);
-               temp &= ~FDI_LINK_TRAIN_NONE;
-               I915_WRITE(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE |
-                               FDI_TX_ENHANCE_FRAME_ENABLE);
-               I915_READ(fdi_tx_reg);
+                       temp = I915_READ(fdi_tx_reg);
+                       temp &= ~FDI_LINK_TRAIN_NONE;
+                       I915_WRITE(fdi_tx_reg, temp | FDI_LINK_TRAIN_NONE |
+                                       FDI_TX_ENHANCE_FRAME_ENABLE);
+                       I915_READ(fdi_tx_reg);
 
-               temp = I915_READ(fdi_rx_reg);
-               temp &= ~FDI_LINK_TRAIN_NONE;
-               I915_WRITE(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE |
-                               FDI_RX_ENHANCE_FRAME_ENABLE);
-               I915_READ(fdi_rx_reg);
+                       temp = I915_READ(fdi_rx_reg);
+                       temp &= ~FDI_LINK_TRAIN_NONE;
+                       I915_WRITE(fdi_rx_reg, temp | FDI_LINK_TRAIN_NONE |
+                                       FDI_RX_ENHANCE_FRAME_ENABLE);
+                       I915_READ(fdi_rx_reg);
 
-               /* wait one idle pattern time */
-               udelay(100);
+                       /* wait one idle pattern time */
+                       udelay(100);
+
+               }
 
                intel_crtc_load_lut(crtc);
 
@@ -1129,8 +1348,7 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
        case DRM_MODE_DPMS_OFF:
                DRM_DEBUG("crtc %d dpms off\n", pipe);
 
-               /* Disable the VGA plane that we never use */
-               I915_WRITE(CPU_VGACNTRL, VGA_DISP_DISABLE);
+               i915_disable_vga(dev);
 
                /* Disable display plane */
                temp = I915_READ(dspcntr_reg);
@@ -1146,17 +1364,23 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
                if ((temp & PIPEACONF_ENABLE) != 0) {
                        I915_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
                        I915_READ(pipeconf_reg);
+                       n = 0;
                        /* wait for cpu pipe off, pipe state */
-                       while ((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) != 0)
-                               ;
+                       while ((I915_READ(pipeconf_reg) & I965_PIPECONF_ACTIVE) != 0) {
+                               n++;
+                               if (n < 60) {
+                                       udelay(500);
+                                       continue;
+                               } else {
+                                       DRM_DEBUG("pipe %d off delay\n", pipe);
+                                       break;
+                               }
+                       }
                } else
                        DRM_DEBUG("crtc %d is disabled\n", pipe);
 
-               /* IGDNG-A : disable cpu panel fitter ? */
-               temp = I915_READ(pf_ctl_reg);
-               if ((temp & PF_ENABLE) != 0) {
-                       I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
-                       I915_READ(pf_ctl_reg);
+               if (HAS_eDP) {
+                       igdng_disable_pll_edp(crtc);
                }
 
                /* disable CPU FDI tx and PCH FDI rx */
@@ -1168,6 +1392,8 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
                I915_WRITE(fdi_rx_reg, temp & ~FDI_RX_ENABLE);
                I915_READ(fdi_rx_reg);
 
+               udelay(100);
+
                /* still set train pattern 1 */
                temp = I915_READ(fdi_tx_reg);
                temp &= ~FDI_LINK_TRAIN_NONE;
@@ -1179,14 +1405,25 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
                temp |= FDI_LINK_TRAIN_PATTERN_1;
                I915_WRITE(fdi_rx_reg, temp);
 
+               udelay(100);
+
                /* disable PCH transcoder */
                temp = I915_READ(transconf_reg);
                if ((temp & TRANS_ENABLE) != 0) {
                        I915_WRITE(transconf_reg, temp & ~TRANS_ENABLE);
                        I915_READ(transconf_reg);
+                       n = 0;
                        /* wait for PCH transcoder off, transcoder state */
-                       while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) != 0)
-                               ;
+                       while ((I915_READ(transconf_reg) & TRANS_STATE_ENABLE) != 0) {
+                               n++;
+                               if (n < 60) {
+                                       udelay(500);
+                                       continue;
+                               } else {
+                                       DRM_DEBUG("transcoder %d off delay\n", pipe);
+                                       break;
+                               }
+                       }
                }
 
                /* disable PCH DPLL */
@@ -1204,6 +1441,22 @@ static void igdng_crtc_dpms(struct drm_crtc *crtc, int mode)
                        I915_READ(fdi_rx_reg);
                }
 
+               /* Disable CPU FDI TX PLL */
+               temp = I915_READ(fdi_tx_reg);
+               if ((temp & FDI_TX_PLL_ENABLE) != 0) {
+                       I915_WRITE(fdi_tx_reg, temp & ~FDI_TX_PLL_ENABLE);
+                       I915_READ(fdi_tx_reg);
+                       udelay(100);
+               }
+
+               /* Disable PF */
+               temp = I915_READ(pf_ctl_reg);
+               if ((temp & PF_ENABLE) != 0) {
+                       I915_WRITE(pf_ctl_reg, temp & ~PF_ENABLE);
+                       I915_READ(pf_ctl_reg);
+               }
+               I915_WRITE(pf_win_size, 0);
+
                /* Wait for the clocks to turn off. */
                udelay(150);
                break;
@@ -1263,13 +1516,15 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
 
                /* Give the overlay scaler a chance to enable if it's on this pipe */
                //intel_crtc_dpms_video(crtc, true); TODO
+               intel_update_watermarks(dev);
        break;
        case DRM_MODE_DPMS_OFF:
+               intel_update_watermarks(dev);
                /* Give the overlay scaler a chance to disable if it's on this pipe */
                //intel_crtc_dpms_video(crtc, FALSE); TODO
 
                /* Disable the VGA plane that we never use */
-               I915_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+               i915_disable_vga(dev);
 
                /* Disable display plane */
                temp = I915_READ(dspcntr_reg);
@@ -1443,7 +1698,6 @@ static int intel_get_core_clock_speed(struct drm_device *dev)
        return 0; /* Silence gcc warning */
 }
 
-
 /**
  * Return the pipe currently connected to the panel fitter,
  * or -1 if the panel fitter is not present or not in use
@@ -1502,7 +1756,7 @@ igdng_compute_m_n(int bytes_per_pixel, int nlanes,
 
        temp = (u64) DATA_N * pixel_clock;
        temp = div_u64(temp, link_clock);
-       m_n->gmch_m = (temp * bytes_per_pixel) / nlanes;
+       m_n->gmch_m = div_u64(temp * bytes_per_pixel, nlanes);
        m_n->gmch_n = DATA_N;
        fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
 
@@ -1513,6 +1767,478 @@ igdng_compute_m_n(int bytes_per_pixel, int nlanes,
 }
 
 
+struct intel_watermark_params {
+       unsigned long fifo_size;
+       unsigned long max_wm;
+       unsigned long default_wm;
+       unsigned long guard_size;
+       unsigned long cacheline_size;
+};
+
+/* IGD has different values for various configs */
+static struct intel_watermark_params igd_display_wm = {
+       IGD_DISPLAY_FIFO,
+       IGD_MAX_WM,
+       IGD_DFT_WM,
+       IGD_GUARD_WM,
+       IGD_FIFO_LINE_SIZE
+};
+static struct intel_watermark_params igd_display_hplloff_wm = {
+       IGD_DISPLAY_FIFO,
+       IGD_MAX_WM,
+       IGD_DFT_HPLLOFF_WM,
+       IGD_GUARD_WM,
+       IGD_FIFO_LINE_SIZE
+};
+static struct intel_watermark_params igd_cursor_wm = {
+       IGD_CURSOR_FIFO,
+       IGD_CURSOR_MAX_WM,
+       IGD_CURSOR_DFT_WM,
+       IGD_CURSOR_GUARD_WM,
+       IGD_FIFO_LINE_SIZE,
+};
+static struct intel_watermark_params igd_cursor_hplloff_wm = {
+       IGD_CURSOR_FIFO,
+       IGD_CURSOR_MAX_WM,
+       IGD_CURSOR_DFT_WM,
+       IGD_CURSOR_GUARD_WM,
+       IGD_FIFO_LINE_SIZE
+};
+static struct intel_watermark_params i945_wm_info = {
+       I945_FIFO_SIZE,
+       I915_MAX_WM,
+       1,
+       2,
+       I915_FIFO_LINE_SIZE
+};
+static struct intel_watermark_params i915_wm_info = {
+       I915_FIFO_SIZE,
+       I915_MAX_WM,
+       1,
+       2,
+       I915_FIFO_LINE_SIZE
+};
+static struct intel_watermark_params i855_wm_info = {
+       I855GM_FIFO_SIZE,
+       I915_MAX_WM,
+       1,
+       2,
+       I830_FIFO_LINE_SIZE
+};
+static struct intel_watermark_params i830_wm_info = {
+       I830_FIFO_SIZE,
+       I915_MAX_WM,
+       1,
+       2,
+       I830_FIFO_LINE_SIZE
+};
+
+/**
+ * intel_calculate_wm - calculate watermark level
+ * @clock_in_khz: pixel clock
+ * @wm: chip FIFO params
+ * @pixel_size: display pixel size
+ * @latency_ns: memory latency for the platform
+ *
+ * Calculate the watermark level (the level at which the display plane will
+ * start fetching from memory again).  Each chip has a different display
+ * FIFO size and allocation, so the caller needs to figure that out and pass
+ * in the correct intel_watermark_params structure.
+ *
+ * As the pixel clock runs, the FIFO will be drained at a rate that depends
+ * on the pixel size.  When it reaches the watermark level, it'll start
+ * fetching FIFO line sized based chunks from memory until the FIFO fills
+ * past the watermark point.  If the FIFO drains completely, a FIFO underrun
+ * will occur, and a display engine hang could result.
+ */
+static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
+                                       struct intel_watermark_params *wm,
+                                       int pixel_size,
+                                       unsigned long latency_ns)
+{
+       long entries_required, wm_size;
+
+       entries_required = (clock_in_khz * pixel_size * latency_ns) / 1000000;
+       entries_required /= wm->cacheline_size;
+
+       DRM_DEBUG("FIFO entries required for mode: %d\n", entries_required);
+
+       wm_size = wm->fifo_size - (entries_required + wm->guard_size);
+
+       DRM_DEBUG("FIFO watermark level: %d\n", wm_size);
+
+       /* Don't promote wm_size to unsigned... */
+       if (wm_size > (long)wm->max_wm)
+               wm_size = wm->max_wm;
+       if (wm_size <= 0)
+               wm_size = wm->default_wm;
+       return wm_size;
+}
+
+struct cxsr_latency {
+       int is_desktop;
+       unsigned long fsb_freq;
+       unsigned long mem_freq;
+       unsigned long display_sr;
+       unsigned long display_hpll_disable;
+       unsigned long cursor_sr;
+       unsigned long cursor_hpll_disable;
+};
+
+static struct cxsr_latency cxsr_latency_table[] = {
+       {1, 800, 400, 3382, 33382, 3983, 33983},    /* DDR2-400 SC */
+       {1, 800, 667, 3354, 33354, 3807, 33807},    /* DDR2-667 SC */
+       {1, 800, 800, 3347, 33347, 3763, 33763},    /* DDR2-800 SC */
+
+       {1, 667, 400, 3400, 33400, 4021, 34021},    /* DDR2-400 SC */
+       {1, 667, 667, 3372, 33372, 3845, 33845},    /* DDR2-667 SC */
+       {1, 667, 800, 3386, 33386, 3822, 33822},    /* DDR2-800 SC */
+
+       {1, 400, 400, 3472, 33472, 4173, 34173},    /* DDR2-400 SC */
+       {1, 400, 667, 3443, 33443, 3996, 33996},    /* DDR2-667 SC */
+       {1, 400, 800, 3430, 33430, 3946, 33946},    /* DDR2-800 SC */
+
+       {0, 800, 400, 3438, 33438, 4065, 34065},    /* DDR2-400 SC */
+       {0, 800, 667, 3410, 33410, 3889, 33889},    /* DDR2-667 SC */
+       {0, 800, 800, 3403, 33403, 3845, 33845},    /* DDR2-800 SC */
+
+       {0, 667, 400, 3456, 33456, 4103, 34106},    /* DDR2-400 SC */
+       {0, 667, 667, 3428, 33428, 3927, 33927},    /* DDR2-667 SC */
+       {0, 667, 800, 3443, 33443, 3905, 33905},    /* DDR2-800 SC */
+
+       {0, 400, 400, 3528, 33528, 4255, 34255},    /* DDR2-400 SC */
+       {0, 400, 667, 3500, 33500, 4079, 34079},    /* DDR2-667 SC */
+       {0, 400, 800, 3487, 33487, 4029, 34029},    /* DDR2-800 SC */
+};
+
+static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb,
+                                                  int mem)
+{
+       int i;
+       struct cxsr_latency *latency;
+
+       if (fsb == 0 || mem == 0)
+               return NULL;
+
+       for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) {
+               latency = &cxsr_latency_table[i];
+               if (is_desktop == latency->is_desktop &&
+                       fsb == latency->fsb_freq && mem == latency->mem_freq)
+                       break;
+       }
+       if (i >= ARRAY_SIZE(cxsr_latency_table)) {
+               DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n");
+               return NULL;
+       }
+       return latency;
+}
+
+static void igd_disable_cxsr(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 reg;
+
+       /* deactivate cxsr */
+       reg = I915_READ(DSPFW3);
+       reg &= ~(IGD_SELF_REFRESH_EN);
+       I915_WRITE(DSPFW3, reg);
+       DRM_INFO("Big FIFO is disabled\n");
+}
+
+static void igd_enable_cxsr(struct drm_device *dev, unsigned long clock,
+                           int pixel_size)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 reg;
+       unsigned long wm;
+       struct cxsr_latency *latency;
+
+       latency = intel_get_cxsr_latency(IS_IGDG(dev), dev_priv->fsb_freq,
+               dev_priv->mem_freq);
+       if (!latency) {
+               DRM_DEBUG("Unknown FSB/MEM found, disable CxSR\n");
+               igd_disable_cxsr(dev);
+               return;
+       }
+
+       /* Display SR */
+       wm = intel_calculate_wm(clock, &igd_display_wm, pixel_size,
+                               latency->display_sr);
+       reg = I915_READ(DSPFW1);
+       reg &= 0x7fffff;
+       reg |= wm << 23;
+       I915_WRITE(DSPFW1, reg);
+       DRM_DEBUG("DSPFW1 register is %x\n", reg);
+
+       /* cursor SR */
+       wm = intel_calculate_wm(clock, &igd_cursor_wm, pixel_size,
+                               latency->cursor_sr);
+       reg = I915_READ(DSPFW3);
+       reg &= ~(0x3f << 24);
+       reg |= (wm & 0x3f) << 24;
+       I915_WRITE(DSPFW3, reg);
+
+       /* Display HPLL off SR */
+       wm = intel_calculate_wm(clock, &igd_display_hplloff_wm,
+               latency->display_hpll_disable, I915_FIFO_LINE_SIZE);
+       reg = I915_READ(DSPFW3);
+       reg &= 0xfffffe00;
+       reg |= wm & 0x1ff;
+       I915_WRITE(DSPFW3, reg);
+
+       /* cursor HPLL off SR */
+       wm = intel_calculate_wm(clock, &igd_cursor_hplloff_wm, pixel_size,
+                               latency->cursor_hpll_disable);
+       reg = I915_READ(DSPFW3);
+       reg &= ~(0x3f << 16);
+       reg |= (wm & 0x3f) << 16;
+       I915_WRITE(DSPFW3, reg);
+       DRM_DEBUG("DSPFW3 register is %x\n", reg);
+
+       /* activate cxsr */
+       reg = I915_READ(DSPFW3);
+       reg |= IGD_SELF_REFRESH_EN;
+       I915_WRITE(DSPFW3, reg);
+
+       DRM_INFO("Big FIFO is enabled\n");
+
+       return;
+}
+
+/*
+ * Latency for FIFO fetches is dependent on several factors:
+ *   - memory configuration (speed, channels)
+ *   - chipset
+ *   - current MCH state
+ * It can be fairly high in some situations, so here we assume a fairly
+ * pessimal value.  It's a tradeoff between extra memory fetches (if we
+ * set this value too high, the FIFO will fetch frequently to stay full)
+ * and power consumption (set it too low to save power and we might see
+ * FIFO underruns and display "flicker").
+ *
+ * A value of 5us seems to be a good balance; safe for very low end
+ * platforms but not overly aggressive on lower latency configs.
+ */
+const static int latency_ns = 5000;
+
+static int intel_get_fifo_size(struct drm_device *dev, int plane)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t dsparb = I915_READ(DSPARB);
+       int size;
+
+       if (IS_I9XX(dev)) {
+               if (plane == 0)
+                       size = dsparb & 0x7f;
+               else
+                       size = ((dsparb >> DSPARB_CSTART_SHIFT) & 0x7f) -
+                               (dsparb & 0x7f);
+       } else if (IS_I85X(dev)) {
+               if (plane == 0)
+                       size = dsparb & 0x1ff;
+               else
+                       size = ((dsparb >> DSPARB_BEND_SHIFT) & 0x1ff) -
+                               (dsparb & 0x1ff);
+               size >>= 1; /* Convert to cachelines */
+       } else if (IS_845G(dev)) {
+               size = dsparb & 0x7f;
+               size >>= 2; /* Convert to cachelines */
+       } else {
+               size = dsparb & 0x7f;
+               size >>= 1; /* Convert to cachelines */
+       }
+
+       DRM_DEBUG("FIFO size - (0x%08x) %s: %d\n", dsparb, plane ? "B" : "A",
+                 size);
+
+       return size;
+}
+
+static void i965_update_wm(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("Setting FIFO watermarks - A: 8, B: 8, C: 8, SR 8\n");
+
+       /* 965 has limitations... */
+       I915_WRITE(DSPFW1, (8 << 16) | (8 << 8) | (8 << 0));
+       I915_WRITE(DSPFW2, (8 << 8) | (8 << 0));
+}
+
+static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
+                          int planeb_clock, int sr_hdisplay, int pixel_size)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t fwater_lo;
+       uint32_t fwater_hi;
+       int total_size, cacheline_size, cwm, srwm = 1;
+       int planea_wm, planeb_wm;
+       struct intel_watermark_params planea_params, planeb_params;
+       unsigned long line_time_us;
+       int sr_clock, sr_entries = 0;
+
+       /* Create copies of the base settings for each pipe */
+       if (IS_I965GM(dev) || IS_I945GM(dev))
+               planea_params = planeb_params = i945_wm_info;
+       else if (IS_I9XX(dev))
+               planea_params = planeb_params = i915_wm_info;
+       else
+               planea_params = planeb_params = i855_wm_info;
+
+       /* Grab a couple of global values before we overwrite them */
+       total_size = planea_params.fifo_size;
+       cacheline_size = planea_params.cacheline_size;
+
+       /* Update per-plane FIFO sizes */
+       planea_params.fifo_size = intel_get_fifo_size(dev, 0);
+       planeb_params.fifo_size = intel_get_fifo_size(dev, 1);
+
+       planea_wm = intel_calculate_wm(planea_clock, &planea_params,
+                                      pixel_size, latency_ns);
+       planeb_wm = intel_calculate_wm(planeb_clock, &planeb_params,
+                                      pixel_size, latency_ns);
+       DRM_DEBUG("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
+
+       /*
+        * Overlay gets an aggressive default since video jitter is bad.
+        */
+       cwm = 2;
+
+       /* Calc sr entries for one plane configs */
+       if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
+               /* self-refresh has much higher latency */
+               const static int sr_latency_ns = 6000;
+
+               sr_clock = planea_clock ? planea_clock : planeb_clock;
+               line_time_us = ((sr_hdisplay * 1000) / sr_clock);
+
+               /* Use ns/us then divide to preserve precision */
+               sr_entries = (((sr_latency_ns / line_time_us) + 1) *
+                             pixel_size * sr_hdisplay) / 1000;
+               sr_entries = roundup(sr_entries / cacheline_size, 1);
+               DRM_DEBUG("self-refresh entries: %d\n", sr_entries);
+               srwm = total_size - sr_entries;
+               if (srwm < 0)
+                       srwm = 1;
+               if (IS_I9XX(dev))
+                       I915_WRITE(FW_BLC_SELF, (srwm & 0x3f));
+       }
+
+       DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
+                 planea_wm, planeb_wm, cwm, srwm);
+
+       fwater_lo = ((planeb_wm & 0x3f) << 16) | (planea_wm & 0x3f);
+       fwater_hi = (cwm & 0x1f);
+
+       /* Set request length to 8 cachelines per fetch */
+       fwater_lo = fwater_lo | (1 << 24) | (1 << 8);
+       fwater_hi = fwater_hi | (1 << 8);
+
+       I915_WRITE(FW_BLC, fwater_lo);
+       I915_WRITE(FW_BLC2, fwater_hi);
+}
+
+static void i830_update_wm(struct drm_device *dev, int planea_clock,
+                          int pixel_size)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t fwater_lo = I915_READ(FW_BLC) & ~0xfff;
+       int planea_wm;
+
+       i830_wm_info.fifo_size = intel_get_fifo_size(dev, 0);
+
+       planea_wm = intel_calculate_wm(planea_clock, &i830_wm_info,
+                                      pixel_size, latency_ns);
+       fwater_lo |= (3<<8) | planea_wm;
+
+       DRM_DEBUG("Setting FIFO watermarks - A: %d\n", planea_wm);
+
+       I915_WRITE(FW_BLC, fwater_lo);
+}
+
+/**
+ * intel_update_watermarks - update FIFO watermark values based on current modes
+ *
+ * Calculate watermark values for the various WM regs based on current mode
+ * and plane configuration.
+ *
+ * There are several cases to deal with here:
+ *   - normal (i.e. non-self-refresh)
+ *   - self-refresh (SR) mode
+ *   - lines are large relative to FIFO size (buffer can hold up to 2)
+ *   - lines are small relative to FIFO size (buffer can hold more than 2
+ *     lines), so need to account for TLB latency
+ *
+ *   The normal calculation is:
+ *     watermark = dotclock * bytes per pixel * latency
+ *   where latency is platform & configuration dependent (we assume pessimal
+ *   values here).
+ *
+ *   The SR calculation is:
+ *     watermark = (trunc(latency/line time)+1) * surface width *
+ *       bytes per pixel
+ *   where
+ *     line time = htotal / dotclock
+ *   and latency is assumed to be high, as above.
+ *
+ * The final value programmed to the register should always be rounded up,
+ * and include an extra 2 entries to account for clock crossings.
+ *
+ * We don't use the sprite, so we can ignore that.  And on Crestline we have
+ * to set the non-SR watermarks to 8.
+  */
+static void intel_update_watermarks(struct drm_device *dev)
+{
+       struct drm_crtc *crtc;
+       struct intel_crtc *intel_crtc;
+       int sr_hdisplay = 0;
+       unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0;
+       int enabled = 0, pixel_size = 0;
+
+       if (DSPARB_HWCONTROL(dev))
+               return;
+
+       /* Get the clock config from both planes */
+       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+               intel_crtc = to_intel_crtc(crtc);
+               if (crtc->enabled) {
+                       enabled++;
+                       if (intel_crtc->plane == 0) {
+                               DRM_DEBUG("plane A (pipe %d) clock: %d\n",
+                                         intel_crtc->pipe, crtc->mode.clock);
+                               planea_clock = crtc->mode.clock;
+                       } else {
+                               DRM_DEBUG("plane B (pipe %d) clock: %d\n",
+                                         intel_crtc->pipe, crtc->mode.clock);
+                               planeb_clock = crtc->mode.clock;
+                       }
+                       sr_hdisplay = crtc->mode.hdisplay;
+                       sr_clock = crtc->mode.clock;
+                       if (crtc->fb)
+                               pixel_size = crtc->fb->bits_per_pixel / 8;
+                       else
+                               pixel_size = 4; /* by default */
+               }
+       }
+
+       if (enabled <= 0)
+               return;
+
+       /* Single plane configs can enable self refresh */
+       if (enabled == 1 && IS_IGD(dev))
+               igd_enable_cxsr(dev, sr_clock, pixel_size);
+       else if (IS_IGD(dev))
+               igd_disable_cxsr(dev);
+
+       if (IS_I965G(dev))
+               i965_update_wm(dev);
+       else if (IS_I9XX(dev) || IS_MOBILE(dev))
+               i9xx_update_wm(dev, planea_clock, planeb_clock, sr_hdisplay,
+                              pixel_size);
+       else
+               i830_update_wm(dev, planea_clock, pixel_size);
+}
+
 static int intel_crtc_mode_set(struct drm_crtc *crtc,
                               struct drm_display_mode *mode,
                               struct drm_display_mode *adjusted_mode,
@@ -1541,7 +2267,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
        intel_clock_t clock;
        u32 dpll = 0, fp = 0, dspcntr, pipeconf;
        bool ok, is_sdvo = false, is_dvo = false;
-       bool is_crt = false, is_lvds = false, is_tv = false;
+       bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;
+       bool is_edp = false;
        struct drm_mode_config *mode_config = &dev->mode_config;
        struct drm_connector *connector;
        const intel_limit_t *limit;
@@ -1557,6 +2284,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
        int lvds_reg = LVDS;
        u32 temp;
        int sdvo_pixel_multiply;
+       int target_clock;
 
        drm_vblank_pre_modeset(dev, pipe);
 
@@ -1585,6 +2313,12 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                case INTEL_OUTPUT_ANALOG:
                        is_crt = true;
                        break;
+               case INTEL_OUTPUT_DISPLAYPORT:
+                       is_dp = true;
+                       break;
+               case INTEL_OUTPUT_EDP:
+                       is_edp = true;
+                       break;
                }
 
                num_outputs++;
@@ -1600,6 +2334,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
        } else {
                refclk = 48000;
        }
+       
 
        /*
         * Returns a set of divisors for the desired target clock with the given
@@ -1635,11 +2370,29 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
        }
 
        /* FDI link */
-       if (IS_IGDNG(dev))
-               igdng_compute_m_n(3, 4, /* lane num 4 */
-                               adjusted_mode->clock,
-                               270000, /* lane clock */
-                               &m_n);
+       if (IS_IGDNG(dev)) {
+               int lane, link_bw;
+               /* eDP doesn't require FDI link, so just set DP M/N
+                  according to current link config */
+               if (is_edp) {
+                       struct drm_connector *edp;
+                       target_clock = mode->clock;
+                       edp = intel_pipe_get_output(crtc);
+                       intel_edp_link_config(to_intel_output(edp),
+                                       &lane, &link_bw);
+               } else {
+                       /* DP over FDI requires target mode clock
+                          instead of link clock */
+                       if (is_dp)
+                               target_clock = mode->clock;
+                       else
+                               target_clock = adjusted_mode->clock;
+                       lane = 4;
+                       link_bw = 270000;
+               }
+               igdng_compute_m_n(3, lane, target_clock,
+                                 link_bw, &m_n);
+       }
 
        if (IS_IGD(dev))
                fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
@@ -1657,11 +2410,13 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                if (is_sdvo) {
                        dpll |= DPLL_DVO_HIGH_SPEED;
                        sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
-                       if (IS_I945G(dev) || IS_I945GM(dev))
+                       if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
                                dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
                        else if (IS_IGDNG(dev))
                                dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT;
                }
+               if (is_dp)
+                       dpll |= DPLL_DVO_HIGH_SPEED;
 
                /* compute bitmask from p1 value */
                if (IS_IGD(dev))
@@ -1758,29 +2513,15 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                dpll_reg = pch_dpll_reg;
        }
 
-       if (dpll & DPLL_VCO_ENABLE) {
+       if (is_edp) {
+               igdng_disable_pll_edp(crtc);
+       } else if ((dpll & DPLL_VCO_ENABLE)) {
                I915_WRITE(fp_reg, fp);
                I915_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
                I915_READ(dpll_reg);
                udelay(150);
        }
 
-       if (IS_IGDNG(dev)) {
-               /* enable PCH clock reference source */
-               /* XXX need to change the setting for other outputs */
-               u32 temp;
-               temp = I915_READ(PCH_DREF_CONTROL);
-               temp &= ~DREF_NONSPREAD_SOURCE_MASK;
-               temp |= DREF_NONSPREAD_CK505_ENABLE;
-               temp &= ~DREF_SSC_SOURCE_MASK;
-               temp |= DREF_SSC_SOURCE_ENABLE;
-               temp &= ~DREF_SSC1_ENABLE;
-               /* if no eDP, disable source output to CPU */
-               temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
-               temp |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
-               I915_WRITE(PCH_DREF_CONTROL, temp);
-       }
-
        /* The LVDS pin pair needs to be on before the DPLLs are enabled.
         * This is an exception to the general rule that mode_set doesn't turn
         * things on.
@@ -1809,24 +2550,28 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                I915_WRITE(lvds_reg, lvds);
                I915_READ(lvds_reg);
        }
+       if (is_dp)
+               intel_dp_set_m_n(crtc, mode, adjusted_mode);
 
-       I915_WRITE(fp_reg, fp);
-       I915_WRITE(dpll_reg, dpll);
-       I915_READ(dpll_reg);
-       /* Wait for the clocks to stabilize. */
-       udelay(150);
-
-       if (IS_I965G(dev) && !IS_IGDNG(dev)) {
-               sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
-               I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
-                          ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
-       } else {
-               /* write it again -- the BIOS does, after all */
+       if (!is_edp) {
+               I915_WRITE(fp_reg, fp);
                I915_WRITE(dpll_reg, dpll);
+               I915_READ(dpll_reg);
+               /* Wait for the clocks to stabilize. */
+               udelay(150);
+
+               if (IS_I965G(dev) && !IS_IGDNG(dev)) {
+                       sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
+                       I915_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
+                                       ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
+               } else {
+                       /* write it again -- the BIOS does, after all */
+                       I915_WRITE(dpll_reg, dpll);
+               }
+               I915_READ(dpll_reg);
+               /* Wait for the clocks to stabilize. */
+               udelay(150);
        }
-       I915_READ(dpll_reg);
-       /* Wait for the clocks to stabilize. */
-       udelay(150);
 
        I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
                   ((adjusted_mode->crtc_htotal - 1) << 16));
@@ -1856,10 +2601,14 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                I915_WRITE(link_m1_reg, m_n.link_m);
                I915_WRITE(link_n1_reg, m_n.link_n);
 
-                /* enable FDI RX PLL too */
-               temp = I915_READ(fdi_rx_reg);
-               I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);
-               udelay(200);
+               if (is_edp) {
+                       igdng_set_pll_edp(crtc, adjusted_mode->clock);
+               } else {
+                       /* enable FDI RX PLL too */
+                       temp = I915_READ(fdi_rx_reg);
+                       I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);
+                       udelay(200);
+               }
        }
 
        I915_WRITE(pipeconf_reg, pipeconf);
@@ -1871,6 +2620,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
        /* Flush the plane changes */
        ret = intel_pipe_set_base(crtc, x, y, old_fb);
+
+       intel_update_watermarks(dev);
+
        drm_vblank_post_modeset(dev, pipe);
 
        return ret;
@@ -2359,6 +3111,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 
        drm_mode_crtc_set_gamma_size(&intel_crtc->base, 256);
        intel_crtc->pipe = pipe;
+       intel_crtc->plane = pipe;
        for (i = 0; i < 256; i++) {
                intel_crtc->lut_r[i] = i;
                intel_crtc->lut_g[i] = i;
@@ -2431,7 +3184,7 @@ static int intel_connector_clones(struct drm_device *dev, int type_mask)
 
         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                struct intel_output *intel_output = to_intel_output(connector);
-               if (type_mask & (1 << intel_output->type))
+               if (type_mask & intel_output->clone_mask)
                        index_mask |= (1 << entry);
                entry++;
        }
@@ -2453,12 +3206,17 @@ static void intel_setup_outputs(struct drm_device *dev)
        if (IS_IGDNG(dev)) {
                int found;
 
+               if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED))
+                       intel_dp_init(dev, DP_A);
+
                if (I915_READ(HDMIB) & PORT_DETECTED) {
                        /* check SDVOB */
                        /* found = intel_sdvo_init(dev, HDMIB); */
                        found = 0;
                        if (!found)
                                intel_hdmi_init(dev, HDMIB);
+                       if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
+                               intel_dp_init(dev, PCH_DP_B);
                }
 
                if (I915_READ(HDMIC) & PORT_DETECTED)
@@ -2467,27 +3225,39 @@ static void intel_setup_outputs(struct drm_device *dev)
                if (I915_READ(HDMID) & PORT_DETECTED)
                        intel_hdmi_init(dev, HDMID);
 
+               if (I915_READ(PCH_DP_C) & DP_DETECTED)
+                       intel_dp_init(dev, PCH_DP_C);
+
+               if (I915_READ(PCH_DP_D) & DP_DETECTED)
+                       intel_dp_init(dev, PCH_DP_D);
+
        } else if (IS_I9XX(dev)) {
-               int found;
-               u32 reg;
+               bool found = false;
 
                if (I915_READ(SDVOB) & SDVO_DETECTED) {
                        found = intel_sdvo_init(dev, SDVOB);
                        if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
                                intel_hdmi_init(dev, SDVOB);
+
+                       if (!found && SUPPORTS_INTEGRATED_DP(dev))
+                               intel_dp_init(dev, DP_B);
                }
 
                /* Before G4X SDVOC doesn't have its own detect register */
-               if (IS_G4X(dev))
-                       reg = SDVOC;
-               else
-                       reg = SDVOB;
 
-               if (I915_READ(reg) & SDVO_DETECTED) {
+               if (I915_READ(SDVOB) & SDVO_DETECTED)
                        found = intel_sdvo_init(dev, SDVOC);
-                       if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
+
+               if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) {
+
+                       if (SUPPORTS_INTEGRATED_HDMI(dev))
                                intel_hdmi_init(dev, SDVOC);
+                       if (SUPPORTS_INTEGRATED_DP(dev))
+                               intel_dp_init(dev, DP_C);
                }
+
+               if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED))
+                       intel_dp_init(dev, DP_D);
        } else
                intel_dvo_init(dev);
 
@@ -2497,42 +3267,10 @@ static void intel_setup_outputs(struct drm_device *dev)
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                struct intel_output *intel_output = to_intel_output(connector);
                struct drm_encoder *encoder = &intel_output->enc;
-               int crtc_mask = 0, clone_mask = 0;
 
-               /* valid crtcs */
-               switch(intel_output->type) {
-               case INTEL_OUTPUT_HDMI:
-                       crtc_mask = ((1 << 0)|
-                                    (1 << 1));
-                       clone_mask = ((1 << INTEL_OUTPUT_HDMI));
-                       break;
-               case INTEL_OUTPUT_DVO:
-               case INTEL_OUTPUT_SDVO:
-                       crtc_mask = ((1 << 0)|
-                                    (1 << 1));
-                       clone_mask = ((1 << INTEL_OUTPUT_ANALOG) |
-                                     (1 << INTEL_OUTPUT_DVO) |
-                                     (1 << INTEL_OUTPUT_SDVO));
-                       break;
-               case INTEL_OUTPUT_ANALOG:
-                       crtc_mask = ((1 << 0)|
-                                    (1 << 1));
-                       clone_mask = ((1 << INTEL_OUTPUT_ANALOG) |
-                                     (1 << INTEL_OUTPUT_DVO) |
-                                     (1 << INTEL_OUTPUT_SDVO));
-                       break;
-               case INTEL_OUTPUT_LVDS:
-                       crtc_mask = (1 << 1);
-                       clone_mask = (1 << INTEL_OUTPUT_LVDS);
-                       break;
-               case INTEL_OUTPUT_TVOUT:
-                       crtc_mask = ((1 << 0) |
-                                    (1 << 1));
-                       clone_mask = (1 << INTEL_OUTPUT_TVOUT);
-                       break;
-               }
-               encoder->possible_crtcs = crtc_mask;
-               encoder->possible_clones = intel_connector_clones(dev, clone_mask);
+               encoder->possible_crtcs = intel_output->crtc_mask;
+               encoder->possible_clones = intel_connector_clones(dev,
+                                               intel_output->clone_mask);
        }
 }
 
@@ -2639,6 +3377,9 @@ void intel_modeset_init(struct drm_device *dev)
        if (IS_I965G(dev)) {
                dev->mode_config.max_width = 8192;
                dev->mode_config.max_height = 8192;
+       } else if (IS_I9XX(dev)) {
+               dev->mode_config.max_width = 4096;
+               dev->mode_config.max_height = 4096;
        } else {
                dev->mode_config.max_width = 2048;
                dev->mode_config.max_height = 2048;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
new file mode 100644 (file)
index 0000000..2b914d7
--- /dev/null
@@ -0,0 +1,1330 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Authors:
+ *    Keith Packard <keithp@keithp.com>
+ *
+ */
+
+#include <linux/i2c.h>
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+#include "intel_drv.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+#include "intel_dp.h"
+
+#define DP_LINK_STATUS_SIZE    6
+#define DP_LINK_CHECK_TIMEOUT  (10 * 1000)
+
+#define DP_LINK_CONFIGURATION_SIZE     9
+
+#define IS_eDP(i) ((i)->type == INTEL_OUTPUT_EDP)
+
+struct intel_dp_priv {
+       uint32_t output_reg;
+       uint32_t DP;
+       uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
+       uint32_t save_DP;
+       uint8_t  save_link_configuration[DP_LINK_CONFIGURATION_SIZE];
+       bool has_audio;
+       int dpms_mode;
+       uint8_t link_bw;
+       uint8_t lane_count;
+       uint8_t dpcd[4];
+       struct intel_output *intel_output;
+       struct i2c_adapter adapter;
+       struct i2c_algo_dp_aux_data algo;
+};
+
+static void
+intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
+                   uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]);
+
+static void
+intel_dp_link_down(struct intel_output *intel_output, uint32_t DP);
+
+void
+intel_edp_link_config (struct intel_output *intel_output,
+               int *lane_num, int *link_bw)
+{
+       struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+
+       *lane_num = dp_priv->lane_count;
+       if (dp_priv->link_bw == DP_LINK_BW_1_62)
+               *link_bw = 162000;
+       else if (dp_priv->link_bw == DP_LINK_BW_2_7)
+               *link_bw = 270000;
+}
+
+static int
+intel_dp_max_lane_count(struct intel_output *intel_output)
+{
+       struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+       int max_lane_count = 4;
+
+       if (dp_priv->dpcd[0] >= 0x11) {
+               max_lane_count = dp_priv->dpcd[2] & 0x1f;
+               switch (max_lane_count) {
+               case 1: case 2: case 4:
+                       break;
+               default:
+                       max_lane_count = 4;
+               }
+       }
+       return max_lane_count;
+}
+
+static int
+intel_dp_max_link_bw(struct intel_output *intel_output)
+{
+       struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+       int max_link_bw = dp_priv->dpcd[1];
+
+       switch (max_link_bw) {
+       case DP_LINK_BW_1_62:
+       case DP_LINK_BW_2_7:
+               break;
+       default:
+               max_link_bw = DP_LINK_BW_1_62;
+               break;
+       }
+       return max_link_bw;
+}
+
+static int
+intel_dp_link_clock(uint8_t link_bw)
+{
+       if (link_bw == DP_LINK_BW_2_7)
+               return 270000;
+       else
+               return 162000;
+}
+
+/* I think this is a fiction */
+static int
+intel_dp_link_required(int pixel_clock)
+{
+       return pixel_clock * 3;
+}
+
+static int
+intel_dp_mode_valid(struct drm_connector *connector,
+                   struct drm_display_mode *mode)
+{
+       struct intel_output *intel_output = to_intel_output(connector);
+       int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output));
+       int max_lanes = intel_dp_max_lane_count(intel_output);
+
+       if (intel_dp_link_required(mode->clock) > max_link_clock * max_lanes)
+               return MODE_CLOCK_HIGH;
+
+       if (mode->clock < 10000)
+               return MODE_CLOCK_LOW;
+
+       return MODE_OK;
+}
+
+static uint32_t
+pack_aux(uint8_t *src, int src_bytes)
+{
+       int     i;
+       uint32_t v = 0;
+
+       if (src_bytes > 4)
+               src_bytes = 4;
+       for (i = 0; i < src_bytes; i++)
+               v |= ((uint32_t) src[i]) << ((3-i) * 8);
+       return v;
+}
+
+static void
+unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes)
+{
+       int i;
+       if (dst_bytes > 4)
+               dst_bytes = 4;
+       for (i = 0; i < dst_bytes; i++)
+               dst[i] = src >> ((3-i) * 8);
+}
+
+/* hrawclock is 1/4 the FSB frequency */
+static int
+intel_hrawclk(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t clkcfg;
+
+       clkcfg = I915_READ(CLKCFG);
+       switch (clkcfg & CLKCFG_FSB_MASK) {
+       case CLKCFG_FSB_400:
+               return 100;
+       case CLKCFG_FSB_533:
+               return 133;
+       case CLKCFG_FSB_667:
+               return 166;
+       case CLKCFG_FSB_800:
+               return 200;
+       case CLKCFG_FSB_1067:
+               return 266;
+       case CLKCFG_FSB_1333:
+               return 333;
+       /* these two are just a guess; one of them might be right */
+       case CLKCFG_FSB_1600:
+       case CLKCFG_FSB_1600_ALT:
+               return 400;
+       default:
+               return 133;
+       }
+}
+
+static int
+intel_dp_aux_ch(struct intel_output *intel_output,
+               uint8_t *send, int send_bytes,
+               uint8_t *recv, int recv_size)
+{
+       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       uint32_t output_reg = dp_priv->output_reg;
+       struct drm_device *dev = intel_output->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t ch_ctl = output_reg + 0x10;
+       uint32_t ch_data = ch_ctl + 4;
+       int i;
+       int recv_bytes;
+       uint32_t ctl;
+       uint32_t status;
+       uint32_t aux_clock_divider;
+       int try;
+
+       /* The clock divider is based off the hrawclk,
+        * and would like to run at 2MHz. So, take the
+        * hrawclk value and divide by 2 and use that
+        */
+       if (IS_eDP(intel_output))
+               aux_clock_divider = 225; /* eDP input clock at 450Mhz */
+       else if (IS_IGDNG(dev))
+               aux_clock_divider = 62; /* IGDNG: input clock fixed at 125Mhz */
+       else
+               aux_clock_divider = intel_hrawclk(dev) / 2;
+
+       /* Must try at least 3 times according to DP spec */
+       for (try = 0; try < 5; try++) {
+               /* Load the send data into the aux channel data registers */
+               for (i = 0; i < send_bytes; i += 4) {
+                       uint32_t    d = pack_aux(send + i, send_bytes - i);;
+       
+                       I915_WRITE(ch_data + i, d);
+               }
+       
+               ctl = (DP_AUX_CH_CTL_SEND_BUSY |
+                      DP_AUX_CH_CTL_TIME_OUT_400us |
+                      (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+                      (5 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
+                      (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) |
+                      DP_AUX_CH_CTL_DONE |
+                      DP_AUX_CH_CTL_TIME_OUT_ERROR |
+                      DP_AUX_CH_CTL_RECEIVE_ERROR);
+       
+               /* Send the command and wait for it to complete */
+               I915_WRITE(ch_ctl, ctl);
+               (void) I915_READ(ch_ctl);
+               for (;;) {
+                       udelay(100);
+                       status = I915_READ(ch_ctl);
+                       if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
+                               break;
+               }
+       
+               /* Clear done status and any errors */
+               I915_WRITE(ch_ctl, (status |
+                               DP_AUX_CH_CTL_DONE |
+                               DP_AUX_CH_CTL_TIME_OUT_ERROR |
+                               DP_AUX_CH_CTL_RECEIVE_ERROR));
+               (void) I915_READ(ch_ctl);
+               if ((status & DP_AUX_CH_CTL_TIME_OUT_ERROR) == 0)
+                       break;
+       }
+
+       if ((status & DP_AUX_CH_CTL_DONE) == 0) {
+               DRM_ERROR("dp_aux_ch not done status 0x%08x\n", status);
+               return -EBUSY;
+       }
+
+       /* Check for timeout or receive error.
+        * Timeouts occur when the sink is not connected
+        */
+       if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
+               DRM_ERROR("dp_aux_ch receive error status 0x%08x\n", status);
+               return -EIO;
+       }
+
+       /* Timeouts occur when the device isn't connected, so they're
+        * "normal" -- don't fill the kernel log with these */
+       if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
+               DRM_DEBUG("dp_aux_ch timeout status 0x%08x\n", status);
+               return -ETIMEDOUT;
+       }
+
+       /* Unload any bytes sent back from the other side */
+       recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
+                     DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
+
+       if (recv_bytes > recv_size)
+               recv_bytes = recv_size;
+       
+       for (i = 0; i < recv_bytes; i += 4) {
+               uint32_t    d = I915_READ(ch_data + i);
+
+               unpack_aux(d, recv + i, recv_bytes - i);
+       }
+
+       return recv_bytes;
+}
+
+/* Write data to the aux channel in native mode */
+static int
+intel_dp_aux_native_write(struct intel_output *intel_output,
+                         uint16_t address, uint8_t *send, int send_bytes)
+{
+       int ret;
+       uint8_t msg[20];
+       int msg_bytes;
+       uint8_t ack;
+
+       if (send_bytes > 16)
+               return -1;
+       msg[0] = AUX_NATIVE_WRITE << 4;
+       msg[1] = address >> 8;
+       msg[2] = address & 0xff;
+       msg[3] = send_bytes - 1;
+       memcpy(&msg[4], send, send_bytes);
+       msg_bytes = send_bytes + 4;
+       for (;;) {
+               ret = intel_dp_aux_ch(intel_output, msg, msg_bytes, &ack, 1);
+               if (ret < 0)
+                       return ret;
+               if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
+                       break;
+               else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+                       udelay(100);
+               else
+                       return -EIO;
+       }
+       return send_bytes;
+}
+
+/* Write a single byte to the aux channel in native mode */
+static int
+intel_dp_aux_native_write_1(struct intel_output *intel_output,
+                           uint16_t address, uint8_t byte)
+{
+       return intel_dp_aux_native_write(intel_output, address, &byte, 1);
+}
+
+/* read bytes from a native aux channel */
+static int
+intel_dp_aux_native_read(struct intel_output *intel_output,
+                        uint16_t address, uint8_t *recv, int recv_bytes)
+{
+       uint8_t msg[4];
+       int msg_bytes;
+       uint8_t reply[20];
+       int reply_bytes;
+       uint8_t ack;
+       int ret;
+
+       msg[0] = AUX_NATIVE_READ << 4;
+       msg[1] = address >> 8;
+       msg[2] = address & 0xff;
+       msg[3] = recv_bytes - 1;
+
+       msg_bytes = 4;
+       reply_bytes = recv_bytes + 1;
+
+       for (;;) {
+               ret = intel_dp_aux_ch(intel_output, msg, msg_bytes,
+                                     reply, reply_bytes);
+               if (ret == 0)
+                       return -EPROTO;
+               if (ret < 0)
+                       return ret;
+               ack = reply[0];
+               if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) {
+                       memcpy(recv, reply + 1, ret - 1);
+                       return ret - 1;
+               }
+               else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+                       udelay(100);
+               else
+                       return -EIO;
+       }
+}
+
+static int
+intel_dp_i2c_aux_ch(struct i2c_adapter *adapter,
+                   uint8_t *send, int send_bytes,
+                   uint8_t *recv, int recv_bytes)
+{
+       struct intel_dp_priv *dp_priv = container_of(adapter,
+                                                    struct intel_dp_priv,
+                                                    adapter);
+       struct intel_output *intel_output = dp_priv->intel_output;
+
+       return intel_dp_aux_ch(intel_output,
+                              send, send_bytes, recv, recv_bytes);
+}
+
+static int
+intel_dp_i2c_init(struct intel_output *intel_output, const char *name)
+{
+       struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+
+       DRM_ERROR("i2c_init %s\n", name);
+       dp_priv->algo.running = false;
+       dp_priv->algo.address = 0;
+       dp_priv->algo.aux_ch = intel_dp_i2c_aux_ch;
+
+       memset(&dp_priv->adapter, '\0', sizeof (dp_priv->adapter));
+       dp_priv->adapter.owner = THIS_MODULE;
+       dp_priv->adapter.class = I2C_CLASS_DDC;
+       strncpy (dp_priv->adapter.name, name, sizeof(dp_priv->adapter.name) - 1);
+       dp_priv->adapter.name[sizeof(dp_priv->adapter.name) - 1] = '\0';
+       dp_priv->adapter.algo_data = &dp_priv->algo;
+       dp_priv->adapter.dev.parent = &intel_output->base.kdev;
+       
+       return i2c_dp_aux_add_bus(&dp_priv->adapter);
+}
+
+static bool
+intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
+                   struct drm_display_mode *adjusted_mode)
+{
+       struct intel_output *intel_output = enc_to_intel_output(encoder);
+       struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+       int lane_count, clock;
+       int max_lane_count = intel_dp_max_lane_count(intel_output);
+       int max_clock = intel_dp_max_link_bw(intel_output) == DP_LINK_BW_2_7 ? 1 : 0;
+       static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
+
+       for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
+               for (clock = 0; clock <= max_clock; clock++) {
+                       int link_avail = intel_dp_link_clock(bws[clock]) * lane_count;
+
+                       if (intel_dp_link_required(mode->clock) <= link_avail) {
+                               dp_priv->link_bw = bws[clock];
+                               dp_priv->lane_count = lane_count;
+                               adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
+                               DRM_DEBUG("Display port link bw %02x lane count %d clock %d\n",
+                                      dp_priv->link_bw, dp_priv->lane_count,
+                                      adjusted_mode->clock);
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+
+struct intel_dp_m_n {
+       uint32_t        tu;
+       uint32_t        gmch_m;
+       uint32_t        gmch_n;
+       uint32_t        link_m;
+       uint32_t        link_n;
+};
+
+static void
+intel_reduce_ratio(uint32_t *num, uint32_t *den)
+{
+       while (*num > 0xffffff || *den > 0xffffff) {
+               *num >>= 1;
+               *den >>= 1;
+       }
+}
+
+static void
+intel_dp_compute_m_n(int bytes_per_pixel,
+                    int nlanes,
+                    int pixel_clock,
+                    int link_clock,
+                    struct intel_dp_m_n *m_n)
+{
+       m_n->tu = 64;
+       m_n->gmch_m = pixel_clock * bytes_per_pixel;
+       m_n->gmch_n = link_clock * nlanes;
+       intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
+       m_n->link_m = pixel_clock;
+       m_n->link_n = link_clock;
+       intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
+}
+
+void
+intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
+                struct drm_display_mode *adjusted_mode)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_mode_config *mode_config = &dev->mode_config;
+       struct drm_connector *connector;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int lane_count = 4;
+       struct intel_dp_m_n m_n;
+
+       /*
+        * Find the lane count in the intel_output private
+        */
+       list_for_each_entry(connector, &mode_config->connector_list, head) {
+               struct intel_output *intel_output = to_intel_output(connector);
+               struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+               if (!connector->encoder || connector->encoder->crtc != crtc)
+                       continue;
+
+               if (intel_output->type == INTEL_OUTPUT_DISPLAYPORT) {
+                       lane_count = dp_priv->lane_count;
+                       break;
+               }
+       }
+
+       /*
+        * Compute the GMCH and Link ratios. The '3' here is
+        * the number of bytes_per_pixel post-LUT, which we always
+        * set up for 8-bits of R/G/B, or 3 bytes total.
+        */
+       intel_dp_compute_m_n(3, lane_count,
+                            mode->clock, adjusted_mode->clock, &m_n);
+
+       if (IS_IGDNG(dev)) {
+               if (intel_crtc->pipe == 0) {
+                       I915_WRITE(TRANSA_DATA_M1,
+                                  ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+                                  m_n.gmch_m);
+                       I915_WRITE(TRANSA_DATA_N1, m_n.gmch_n);
+                       I915_WRITE(TRANSA_DP_LINK_M1, m_n.link_m);
+                       I915_WRITE(TRANSA_DP_LINK_N1, m_n.link_n);
+               } else {
+                       I915_WRITE(TRANSB_DATA_M1,
+                                  ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+                                  m_n.gmch_m);
+                       I915_WRITE(TRANSB_DATA_N1, m_n.gmch_n);
+                       I915_WRITE(TRANSB_DP_LINK_M1, m_n.link_m);
+                       I915_WRITE(TRANSB_DP_LINK_N1, m_n.link_n);
+               }
+       } else {
+               if (intel_crtc->pipe == 0) {
+                       I915_WRITE(PIPEA_GMCH_DATA_M,
+                                  ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+                                  m_n.gmch_m);
+                       I915_WRITE(PIPEA_GMCH_DATA_N,
+                                  m_n.gmch_n);
+                       I915_WRITE(PIPEA_DP_LINK_M, m_n.link_m);
+                       I915_WRITE(PIPEA_DP_LINK_N, m_n.link_n);
+               } else {
+                       I915_WRITE(PIPEB_GMCH_DATA_M,
+                                  ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+                                  m_n.gmch_m);
+                       I915_WRITE(PIPEB_GMCH_DATA_N,
+                                       m_n.gmch_n);
+                       I915_WRITE(PIPEB_DP_LINK_M, m_n.link_m);
+                       I915_WRITE(PIPEB_DP_LINK_N, m_n.link_n);
+               }
+       }
+}
+
+static void
+intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
+                 struct drm_display_mode *adjusted_mode)
+{
+       struct intel_output *intel_output = enc_to_intel_output(encoder);
+       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       struct drm_crtc *crtc = intel_output->enc.crtc;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+       dp_priv->DP = (DP_LINK_TRAIN_OFF |
+                       DP_VOLTAGE_0_4 |
+                       DP_PRE_EMPHASIS_0 |
+                       DP_SYNC_VS_HIGH |
+                       DP_SYNC_HS_HIGH);
+
+       switch (dp_priv->lane_count) {
+       case 1:
+               dp_priv->DP |= DP_PORT_WIDTH_1;
+               break;
+       case 2:
+               dp_priv->DP |= DP_PORT_WIDTH_2;
+               break;
+       case 4:
+               dp_priv->DP |= DP_PORT_WIDTH_4;
+               break;
+       }
+       if (dp_priv->has_audio)
+               dp_priv->DP |= DP_AUDIO_OUTPUT_ENABLE;
+
+       memset(dp_priv->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
+       dp_priv->link_configuration[0] = dp_priv->link_bw;
+       dp_priv->link_configuration[1] = dp_priv->lane_count;
+
+       /*
+        * Check for DPCD version > 1.1,
+        * enable enahanced frame stuff in that case
+        */
+       if (dp_priv->dpcd[0] >= 0x11) {
+               dp_priv->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+               dp_priv->DP |= DP_ENHANCED_FRAMING;
+       }
+
+       if (intel_crtc->pipe == 1)
+               dp_priv->DP |= DP_PIPEB_SELECT;
+
+       if (IS_eDP(intel_output)) {
+               /* don't miss out required setting for eDP */
+               dp_priv->DP |= DP_PLL_ENABLE;
+               if (adjusted_mode->clock < 200000)
+                       dp_priv->DP |= DP_PLL_FREQ_160MHZ;
+               else
+                       dp_priv->DP |= DP_PLL_FREQ_270MHZ;
+       }
+}
+
+static void igdng_edp_backlight_on (struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 pp;
+
+       DRM_DEBUG("\n");
+       pp = I915_READ(PCH_PP_CONTROL);
+       pp |= EDP_BLC_ENABLE;
+       I915_WRITE(PCH_PP_CONTROL, pp);
+}
+
+static void igdng_edp_backlight_off (struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 pp;
+
+       DRM_DEBUG("\n");
+       pp = I915_READ(PCH_PP_CONTROL);
+       pp &= ~EDP_BLC_ENABLE;
+       I915_WRITE(PCH_PP_CONTROL, pp);
+}
+
+static void
+intel_dp_dpms(struct drm_encoder *encoder, int mode)
+{
+       struct intel_output *intel_output = enc_to_intel_output(encoder);
+       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       struct drm_device *dev = intel_output->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       uint32_t dp_reg = I915_READ(dp_priv->output_reg);
+
+       if (mode != DRM_MODE_DPMS_ON) {
+               if (dp_reg & DP_PORT_EN) {
+                       intel_dp_link_down(intel_output, dp_priv->DP);
+                       if (IS_eDP(intel_output))
+                               igdng_edp_backlight_off(dev);
+               }
+       } else {
+               if (!(dp_reg & DP_PORT_EN)) {
+                       intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration);
+                       if (IS_eDP(intel_output))
+                               igdng_edp_backlight_on(dev);
+               }
+       }
+       dp_priv->dpms_mode = mode;
+}
+
+/*
+ * Fetch AUX CH registers 0x202 - 0x207 which contain
+ * link status information
+ */
+static bool
+intel_dp_get_link_status(struct intel_output *intel_output,
+                        uint8_t link_status[DP_LINK_STATUS_SIZE])
+{
+       int ret;
+
+       ret = intel_dp_aux_native_read(intel_output,
+                                      DP_LANE0_1_STATUS,
+                                      link_status, DP_LINK_STATUS_SIZE);
+       if (ret != DP_LINK_STATUS_SIZE)
+               return false;
+       return true;
+}
+
+static uint8_t
+intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
+                    int r)
+{
+       return link_status[r - DP_LANE0_1_STATUS];
+}
+
+static void
+intel_dp_save(struct drm_connector *connector)
+{
+       struct intel_output *intel_output = to_intel_output(connector);
+       struct drm_device *dev = intel_output->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+       dp_priv->save_DP = I915_READ(dp_priv->output_reg);
+       intel_dp_aux_native_read(intel_output, DP_LINK_BW_SET,
+                                dp_priv->save_link_configuration,
+                                sizeof (dp_priv->save_link_configuration));
+}
+
+static uint8_t
+intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
+                                int lane)
+{
+       int         i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+       int         s = ((lane & 1) ?
+                        DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
+                        DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
+       uint8_t l = intel_dp_link_status(link_status, i);
+
+       return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
+}
+
+static uint8_t
+intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE],
+                                     int lane)
+{
+       int         i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+       int         s = ((lane & 1) ?
+                        DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
+                        DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
+       uint8_t l = intel_dp_link_status(link_status, i);
+
+       return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
+}
+
+
+#if 0
+static char    *voltage_names[] = {
+       "0.4V", "0.6V", "0.8V", "1.2V"
+};
+static char    *pre_emph_names[] = {
+       "0dB", "3.5dB", "6dB", "9.5dB"
+};
+static char    *link_train_names[] = {
+       "pattern 1", "pattern 2", "idle", "off"
+};
+#endif
+
+/*
+ * These are source-specific values; current Intel hardware supports
+ * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
+ */
+#define I830_DP_VOLTAGE_MAX        DP_TRAIN_VOLTAGE_SWING_800
+
+static uint8_t
+intel_dp_pre_emphasis_max(uint8_t voltage_swing)
+{
+       switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+       case DP_TRAIN_VOLTAGE_SWING_400:
+               return DP_TRAIN_PRE_EMPHASIS_6;
+       case DP_TRAIN_VOLTAGE_SWING_600:
+               return DP_TRAIN_PRE_EMPHASIS_6;
+       case DP_TRAIN_VOLTAGE_SWING_800:
+               return DP_TRAIN_PRE_EMPHASIS_3_5;
+       case DP_TRAIN_VOLTAGE_SWING_1200:
+       default:
+               return DP_TRAIN_PRE_EMPHASIS_0;
+       }
+}
+
+static void
+intel_get_adjust_train(struct intel_output *intel_output,
+                      uint8_t link_status[DP_LINK_STATUS_SIZE],
+                      int lane_count,
+                      uint8_t train_set[4])
+{
+       uint8_t v = 0;
+       uint8_t p = 0;
+       int lane;
+
+       for (lane = 0; lane < lane_count; lane++) {
+               uint8_t this_v = intel_get_adjust_request_voltage(link_status, lane);
+               uint8_t this_p = intel_get_adjust_request_pre_emphasis(link_status, lane);
+
+               if (this_v > v)
+                       v = this_v;
+               if (this_p > p)
+                       p = this_p;
+       }
+
+       if (v >= I830_DP_VOLTAGE_MAX)
+               v = I830_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED;
+
+       if (p >= intel_dp_pre_emphasis_max(v))
+               p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+       for (lane = 0; lane < 4; lane++)
+               train_set[lane] = v | p;
+}
+
+static uint32_t
+intel_dp_signal_levels(uint8_t train_set, int lane_count)
+{
+       uint32_t        signal_levels = 0;
+
+       switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) {
+       case DP_TRAIN_VOLTAGE_SWING_400:
+       default:
+               signal_levels |= DP_VOLTAGE_0_4;
+               break;
+       case DP_TRAIN_VOLTAGE_SWING_600:
+               signal_levels |= DP_VOLTAGE_0_6;
+               break;
+       case DP_TRAIN_VOLTAGE_SWING_800:
+               signal_levels |= DP_VOLTAGE_0_8;
+               break;
+       case DP_TRAIN_VOLTAGE_SWING_1200:
+               signal_levels |= DP_VOLTAGE_1_2;
+               break;
+       }
+       switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
+       case DP_TRAIN_PRE_EMPHASIS_0:
+       default:
+               signal_levels |= DP_PRE_EMPHASIS_0;
+               break;
+       case DP_TRAIN_PRE_EMPHASIS_3_5:
+               signal_levels |= DP_PRE_EMPHASIS_3_5;
+               break;
+       case DP_TRAIN_PRE_EMPHASIS_6:
+               signal_levels |= DP_PRE_EMPHASIS_6;
+               break;
+       case DP_TRAIN_PRE_EMPHASIS_9_5:
+               signal_levels |= DP_PRE_EMPHASIS_9_5;
+               break;
+       }
+       return signal_levels;
+}
+
+static uint8_t
+intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
+                     int lane)
+{
+       int i = DP_LANE0_1_STATUS + (lane >> 1);
+       int s = (lane & 1) * 4;
+       uint8_t l = intel_dp_link_status(link_status, i);
+
+       return (l >> s) & 0xf;
+}
+
+/* Check for clock recovery is done on all channels */
+static bool
+intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
+{
+       int lane;
+       uint8_t lane_status;
+
+       for (lane = 0; lane < lane_count; lane++) {
+               lane_status = intel_get_lane_status(link_status, lane);
+               if ((lane_status & DP_LANE_CR_DONE) == 0)
+                       return false;
+       }
+       return true;
+}
+
+/* Check to see if channel eq is done on all channels */
+#define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\
+                        DP_LANE_CHANNEL_EQ_DONE|\
+                        DP_LANE_SYMBOL_LOCKED)
+static bool
+intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
+{
+       uint8_t lane_align;
+       uint8_t lane_status;
+       int lane;
+
+       lane_align = intel_dp_link_status(link_status,
+                                         DP_LANE_ALIGN_STATUS_UPDATED);
+       if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
+               return false;
+       for (lane = 0; lane < lane_count; lane++) {
+               lane_status = intel_get_lane_status(link_status, lane);
+               if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
+                       return false;
+       }
+       return true;
+}
+
+static bool
+intel_dp_set_link_train(struct intel_output *intel_output,
+                       uint32_t dp_reg_value,
+                       uint8_t dp_train_pat,
+                       uint8_t train_set[4],
+                       bool first)
+{
+       struct drm_device *dev = intel_output->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       int ret;
+
+       I915_WRITE(dp_priv->output_reg, dp_reg_value);
+       POSTING_READ(dp_priv->output_reg);
+       if (first)
+               intel_wait_for_vblank(dev);
+
+       intel_dp_aux_native_write_1(intel_output,
+                                   DP_TRAINING_PATTERN_SET,
+                                   dp_train_pat);
+
+       ret = intel_dp_aux_native_write(intel_output,
+                                       DP_TRAINING_LANE0_SET, train_set, 4);
+       if (ret != 4)
+               return false;
+
+       return true;
+}
+
+static void
+intel_dp_link_train(struct intel_output *intel_output, uint32_t DP,
+                   uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE])
+{
+       struct drm_device *dev = intel_output->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       uint8_t train_set[4];
+       uint8_t link_status[DP_LINK_STATUS_SIZE];
+       int i;
+       uint8_t voltage;
+       bool clock_recovery = false;
+       bool channel_eq = false;
+       bool first = true;
+       int tries;
+
+       /* Write the link configuration data */
+       intel_dp_aux_native_write(intel_output, 0x100,
+                                 link_configuration, DP_LINK_CONFIGURATION_SIZE);
+
+       DP |= DP_PORT_EN;
+       DP &= ~DP_LINK_TRAIN_MASK;
+       memset(train_set, 0, 4);
+       voltage = 0xff;
+       tries = 0;
+       clock_recovery = false;
+       for (;;) {
+               /* Use train_set[0] to set the voltage and pre emphasis values */
+               uint32_t    signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
+               DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
+
+               if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_1,
+                                            DP_TRAINING_PATTERN_1, train_set, first))
+                       break;
+               first = false;
+               /* Set training pattern 1 */
+
+               udelay(100);
+               if (!intel_dp_get_link_status(intel_output, link_status))
+                       break;
+
+               if (intel_clock_recovery_ok(link_status, dp_priv->lane_count)) {
+                       clock_recovery = true;
+                       break;
+               }
+
+               /* Check to see if we've tried the max voltage */
+               for (i = 0; i < dp_priv->lane_count; i++)
+                       if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
+                               break;
+               if (i == dp_priv->lane_count)
+                       break;
+
+               /* Check to see if we've tried the same voltage 5 times */
+               if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
+                       ++tries;
+                       if (tries == 5)
+                               break;
+               } else
+                       tries = 0;
+               voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+
+               /* Compute new train_set as requested by target */
+               intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set);
+       }
+
+       /* channel equalization */
+       tries = 0;
+       channel_eq = false;
+       for (;;) {
+               /* Use train_set[0] to set the voltage and pre emphasis values */
+               uint32_t    signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count);
+               DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
+
+               /* channel eq pattern */
+               if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_2,
+                                            DP_TRAINING_PATTERN_2, train_set,
+                                            false))
+                       break;
+
+               udelay(400);
+               if (!intel_dp_get_link_status(intel_output, link_status))
+                       break;
+
+               if (intel_channel_eq_ok(link_status, dp_priv->lane_count)) {
+                       channel_eq = true;
+                       break;
+               }
+
+               /* Try 5 times */
+               if (tries > 5)
+                       break;
+
+               /* Compute new train_set as requested by target */
+               intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set);
+               ++tries;
+       }
+
+       I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_OFF);
+       POSTING_READ(dp_priv->output_reg);
+       intel_dp_aux_native_write_1(intel_output,
+                                   DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE);
+}
+
+static void
+intel_dp_link_down(struct intel_output *intel_output, uint32_t DP)
+{
+       struct drm_device *dev = intel_output->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+       DRM_DEBUG("\n");
+
+       if (IS_eDP(intel_output)) {
+               DP &= ~DP_PLL_ENABLE;
+               I915_WRITE(dp_priv->output_reg, DP);
+               POSTING_READ(dp_priv->output_reg);
+               udelay(100);
+       }
+
+       DP &= ~DP_LINK_TRAIN_MASK;
+       I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
+       POSTING_READ(dp_priv->output_reg);
+
+       udelay(17000);
+
+       if (IS_eDP(intel_output))
+               DP |= DP_LINK_TRAIN_OFF;
+       I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN);
+       POSTING_READ(dp_priv->output_reg);
+}
+
+static void
+intel_dp_restore(struct drm_connector *connector)
+{
+       struct intel_output *intel_output = to_intel_output(connector);
+       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+       if (dp_priv->save_DP & DP_PORT_EN)
+               intel_dp_link_train(intel_output, dp_priv->save_DP, dp_priv->save_link_configuration);
+       else
+               intel_dp_link_down(intel_output,  dp_priv->save_DP);
+}
+
+/*
+ * According to DP spec
+ * 5.1.2:
+ *  1. Read DPCD
+ *  2. Configure link according to Receiver Capabilities
+ *  3. Use Link Training from 2.5.3.3 and 3.5.1.3
+ *  4. Check link status on receipt of hot-plug interrupt
+ */
+
+static void
+intel_dp_check_link_status(struct intel_output *intel_output)
+{
+       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       uint8_t link_status[DP_LINK_STATUS_SIZE];
+
+       if (!intel_output->enc.crtc)
+               return;
+
+       if (!intel_dp_get_link_status(intel_output, link_status)) {
+               intel_dp_link_down(intel_output, dp_priv->DP);
+               return;
+       }
+
+       if (!intel_channel_eq_ok(link_status, dp_priv->lane_count))
+               intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration);
+}
+
+static enum drm_connector_status
+igdng_dp_detect(struct drm_connector *connector)
+{
+       struct intel_output *intel_output = to_intel_output(connector);
+       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       enum drm_connector_status status;
+
+       status = connector_status_disconnected;
+       if (intel_dp_aux_native_read(intel_output,
+                                    0x000, dp_priv->dpcd,
+                                    sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd))
+       {
+               if (dp_priv->dpcd[0] != 0)
+                       status = connector_status_connected;
+       }
+       return status;
+}
+
+/**
+ * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
+ *
+ * \return true if DP port is connected.
+ * \return false if DP port is disconnected.
+ */
+static enum drm_connector_status
+intel_dp_detect(struct drm_connector *connector)
+{
+       struct intel_output *intel_output = to_intel_output(connector);
+       struct drm_device *dev = intel_output->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+       uint32_t temp, bit;
+       enum drm_connector_status status;
+
+       dp_priv->has_audio = false;
+
+       if (IS_IGDNG(dev))
+               return igdng_dp_detect(connector);
+
+       temp = I915_READ(PORT_HOTPLUG_EN);
+
+       I915_WRITE(PORT_HOTPLUG_EN,
+              temp |
+              DPB_HOTPLUG_INT_EN |
+              DPC_HOTPLUG_INT_EN |
+              DPD_HOTPLUG_INT_EN);
+
+       POSTING_READ(PORT_HOTPLUG_EN);
+
+       switch (dp_priv->output_reg) {
+       case DP_B:
+               bit = DPB_HOTPLUG_INT_STATUS;
+               break;
+       case DP_C:
+               bit = DPC_HOTPLUG_INT_STATUS;
+               break;
+       case DP_D:
+               bit = DPD_HOTPLUG_INT_STATUS;
+               break;
+       default:
+               return connector_status_unknown;
+       }
+
+       temp = I915_READ(PORT_HOTPLUG_STAT);
+
+       if ((temp & bit) == 0)
+               return connector_status_disconnected;
+
+       status = connector_status_disconnected;
+       if (intel_dp_aux_native_read(intel_output,
+                                    0x000, dp_priv->dpcd,
+                                    sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd))
+       {
+               if (dp_priv->dpcd[0] != 0)
+                       status = connector_status_connected;
+       }
+       return status;
+}
+
+static int intel_dp_get_modes(struct drm_connector *connector)
+{
+       struct intel_output *intel_output = to_intel_output(connector);
+       struct drm_device *dev = intel_output->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret;
+
+       /* We should parse the EDID data and find out if it has an audio sink
+        */
+
+       ret = intel_ddc_get_modes(intel_output);
+       if (ret)
+               return ret;
+
+       /* if eDP has no EDID, try to use fixed panel mode from VBT */
+       if (IS_eDP(intel_output)) {
+               if (dev_priv->panel_fixed_mode != NULL) {
+                       struct drm_display_mode *mode;
+                       mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
+                       drm_mode_probed_add(connector, mode);
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static void
+intel_dp_destroy (struct drm_connector *connector)
+{
+       struct intel_output *intel_output = to_intel_output(connector);
+
+       if (intel_output->i2c_bus)
+               intel_i2c_destroy(intel_output->i2c_bus);
+       drm_sysfs_connector_remove(connector);
+       drm_connector_cleanup(connector);
+       kfree(intel_output);
+}
+
+static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
+       .dpms = intel_dp_dpms,
+       .mode_fixup = intel_dp_mode_fixup,
+       .prepare = intel_encoder_prepare,
+       .mode_set = intel_dp_mode_set,
+       .commit = intel_encoder_commit,
+};
+
+static const struct drm_connector_funcs intel_dp_connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .save = intel_dp_save,
+       .restore = intel_dp_restore,
+       .detect = intel_dp_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = intel_dp_destroy,
+};
+
+static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = {
+       .get_modes = intel_dp_get_modes,
+       .mode_valid = intel_dp_mode_valid,
+       .best_encoder = intel_best_encoder,
+};
+
+static void intel_dp_enc_destroy(struct drm_encoder *encoder)
+{
+       drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs intel_dp_enc_funcs = {
+       .destroy = intel_dp_enc_destroy,
+};
+
+void
+intel_dp_hot_plug(struct intel_output *intel_output)
+{
+       struct intel_dp_priv *dp_priv = intel_output->dev_priv;
+
+       if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON)
+               intel_dp_check_link_status(intel_output);
+}
+
+void
+intel_dp_init(struct drm_device *dev, int output_reg)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_connector *connector;
+       struct intel_output *intel_output;
+       struct intel_dp_priv *dp_priv;
+       const char *name = NULL;
+
+       intel_output = kcalloc(sizeof(struct intel_output) + 
+                              sizeof(struct intel_dp_priv), 1, GFP_KERNEL);
+       if (!intel_output)
+               return;
+
+       dp_priv = (struct intel_dp_priv *)(intel_output + 1);
+
+       connector = &intel_output->base;
+       drm_connector_init(dev, connector, &intel_dp_connector_funcs,
+                          DRM_MODE_CONNECTOR_DisplayPort);
+       drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
+
+       if (output_reg == DP_A)
+               intel_output->type = INTEL_OUTPUT_EDP;
+       else
+               intel_output->type = INTEL_OUTPUT_DISPLAYPORT;
+
+       if (output_reg == DP_B)
+               intel_output->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
+       else if (output_reg == DP_C)
+               intel_output->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
+       else if (output_reg == DP_D)
+               intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
+
+       if (IS_eDP(intel_output)) {
+               intel_output->crtc_mask = (1 << 1);
+               intel_output->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
+       } else
+               intel_output->crtc_mask = (1 << 0) | (1 << 1);
+       connector->interlace_allowed = true;
+       connector->doublescan_allowed = 0;
+
+       dp_priv->intel_output = intel_output;
+       dp_priv->output_reg = output_reg;
+       dp_priv->has_audio = false;
+       dp_priv->dpms_mode = DRM_MODE_DPMS_ON;
+       intel_output->dev_priv = dp_priv;
+
+       drm_encoder_init(dev, &intel_output->enc, &intel_dp_enc_funcs,
+                        DRM_MODE_ENCODER_TMDS);
+       drm_encoder_helper_add(&intel_output->enc, &intel_dp_helper_funcs);
+
+       drm_mode_connector_attach_encoder(&intel_output->base,
+                                         &intel_output->enc);
+       drm_sysfs_connector_add(connector);
+
+       /* Set up the DDC bus. */
+       switch (output_reg) {
+               case DP_A:
+                       name = "DPDDC-A";
+                       break;
+               case DP_B:
+               case PCH_DP_B:
+                       name = "DPDDC-B";
+                       break;
+               case DP_C:
+               case PCH_DP_C:
+                       name = "DPDDC-C";
+                       break;
+               case DP_D:
+               case PCH_DP_D:
+                       name = "DPDDC-D";
+                       break;
+       }
+
+       intel_dp_i2c_init(intel_output, name);
+
+       intel_output->ddc_bus = &dp_priv->adapter;
+       intel_output->hot_plug = intel_dp_hot_plug;
+
+       if (output_reg == DP_A) {
+               /* initialize panel mode from VBT if available for eDP */
+               if (dev_priv->lfp_lvds_vbt_mode) {
+                       dev_priv->panel_fixed_mode =
+                               drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
+                       if (dev_priv->panel_fixed_mode) {
+                               dev_priv->panel_fixed_mode->type |=
+                                       DRM_MODE_TYPE_PREFERRED;
+                       }
+               }
+       }
+
+       /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
+        * 0xd.  Failure to do so will result in spurious interrupts being
+        * generated on the port when a cable is not attached.
+        */
+       if (IS_G4X(dev) && !IS_GM45(dev)) {
+               u32 temp = I915_READ(PEG_BAND_GAP_DATA);
+               I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
+       }
+}
diff --git a/drivers/gpu/drm/i915/intel_dp.h b/drivers/gpu/drm/i915/intel_dp.h
new file mode 100644 (file)
index 0000000..2b38054
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2008 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _INTEL_DP_H_
+#define _INTEL_DP_H_
+
+/* From the VESA DisplayPort spec */
+
+#define AUX_NATIVE_WRITE       0x8
+#define AUX_NATIVE_READ                0x9
+#define AUX_I2C_WRITE          0x0
+#define AUX_I2C_READ           0x1
+#define AUX_I2C_STATUS         0x2
+#define AUX_I2C_MOT            0x4
+
+#define AUX_NATIVE_REPLY_ACK   (0x0 << 4)
+#define AUX_NATIVE_REPLY_NACK  (0x1 << 4)
+#define AUX_NATIVE_REPLY_DEFER (0x2 << 4)
+#define AUX_NATIVE_REPLY_MASK  (0x3 << 4)
+
+#define AUX_I2C_REPLY_ACK      (0x0 << 6)
+#define AUX_I2C_REPLY_NACK     (0x1 << 6)
+#define AUX_I2C_REPLY_DEFER    (0x2 << 6)
+#define AUX_I2C_REPLY_MASK     (0x3 << 6)
+
+/* AUX CH addresses */
+#define        DP_LINK_BW_SET          0x100
+# define DP_LINK_BW_1_62                   0x06
+# define DP_LINK_BW_2_7                            0x0a
+
+#define DP_LANE_COUNT_SET      0x101
+# define DP_LANE_COUNT_MASK                0x0f
+# define DP_LANE_COUNT_ENHANCED_FRAME_EN    (1 << 7)
+
+#define DP_TRAINING_PATTERN_SET        0x102
+
+# define DP_TRAINING_PATTERN_DISABLE       0
+# define DP_TRAINING_PATTERN_1             1
+# define DP_TRAINING_PATTERN_2             2
+# define DP_TRAINING_PATTERN_MASK          0x3
+
+# define DP_LINK_QUAL_PATTERN_DISABLE      (0 << 2)
+# define DP_LINK_QUAL_PATTERN_D10_2        (1 << 2)
+# define DP_LINK_QUAL_PATTERN_ERROR_RATE    (2 << 2)
+# define DP_LINK_QUAL_PATTERN_PRBS7        (3 << 2)
+# define DP_LINK_QUAL_PATTERN_MASK         (3 << 2)
+
+# define DP_RECOVERED_CLOCK_OUT_EN         (1 << 4)
+# define DP_LINK_SCRAMBLING_DISABLE        (1 << 5)
+
+# define DP_SYMBOL_ERROR_COUNT_BOTH        (0 << 6)
+# define DP_SYMBOL_ERROR_COUNT_DISPARITY    (1 << 6)
+# define DP_SYMBOL_ERROR_COUNT_SYMBOL      (2 << 6)
+# define DP_SYMBOL_ERROR_COUNT_MASK        (3 << 6)
+
+#define DP_TRAINING_LANE0_SET              0x103
+#define DP_TRAINING_LANE1_SET              0x104
+#define DP_TRAINING_LANE2_SET              0x105
+#define DP_TRAINING_LANE3_SET              0x106
+
+# define DP_TRAIN_VOLTAGE_SWING_MASK       0x3
+# define DP_TRAIN_VOLTAGE_SWING_SHIFT      0
+# define DP_TRAIN_MAX_SWING_REACHED        (1 << 2)
+# define DP_TRAIN_VOLTAGE_SWING_400        (0 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_600        (1 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_800        (2 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_1200       (3 << 0)
+
+# define DP_TRAIN_PRE_EMPHASIS_MASK        (3 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_0           (0 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_3_5         (1 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_6           (2 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_9_5         (3 << 3)
+
+# define DP_TRAIN_PRE_EMPHASIS_SHIFT       3
+# define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED  (1 << 5)
+
+#define DP_DOWNSPREAD_CTRL                 0x107
+# define DP_SPREAD_AMP_0_5                 (1 << 4)
+
+#define DP_MAIN_LINK_CHANNEL_CODING_SET            0x108
+# define DP_SET_ANSI_8B10B                 (1 << 0)
+
+#define DP_LANE0_1_STATUS                  0x202
+#define DP_LANE2_3_STATUS                  0x203
+
+# define DP_LANE_CR_DONE                   (1 << 0)
+# define DP_LANE_CHANNEL_EQ_DONE           (1 << 1)
+# define DP_LANE_SYMBOL_LOCKED             (1 << 2)
+
+#define DP_LANE_ALIGN_STATUS_UPDATED       0x204
+
+#define DP_INTERLANE_ALIGN_DONE                    (1 << 0)
+#define DP_DOWNSTREAM_PORT_STATUS_CHANGED   (1 << 6)
+#define DP_LINK_STATUS_UPDATED             (1 << 7)
+
+#define DP_SINK_STATUS                     0x205
+
+#define DP_RECEIVE_PORT_0_STATUS           (1 << 0)
+#define DP_RECEIVE_PORT_1_STATUS           (1 << 1)
+
+#define DP_ADJUST_REQUEST_LANE0_1          0x206
+#define DP_ADJUST_REQUEST_LANE2_3          0x207
+
+#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK  0x03
+#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0
+#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK   0x0c
+#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT  2
+#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK  0x30
+#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4
+#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK   0xc0
+#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT  6
+
+struct i2c_algo_dp_aux_data {
+       bool running;
+       u16 address;
+       int (*aux_ch) (struct i2c_adapter *adapter,
+                      uint8_t *send, int send_bytes,
+                      uint8_t *recv, int recv_bytes);
+};
+
+int
+i2c_dp_aux_add_bus(struct i2c_adapter *adapter);
+
+#endif /* _INTEL_DP_H_ */
diff --git a/drivers/gpu/drm/i915/intel_dp_i2c.c b/drivers/gpu/drm/i915/intel_dp_i2c.c
new file mode 100644 (file)
index 0000000..a63b6f5
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright © 2009 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/i2c.h>
+#include "intel_dp.h"
+#include "drmP.h"
+
+/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
+
+#define MODE_I2C_START 1
+#define MODE_I2C_WRITE 2
+#define MODE_I2C_READ  4
+#define MODE_I2C_STOP  8
+
+static int
+i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
+                           uint8_t write_byte, uint8_t *read_byte)
+{
+       struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+       uint16_t address = algo_data->address;
+       uint8_t msg[5];
+       uint8_t reply[2];
+       int msg_bytes;
+       int reply_bytes;
+       int ret;
+
+       /* Set up the command byte */
+       if (mode & MODE_I2C_READ)
+               msg[0] = AUX_I2C_READ << 4;
+       else
+               msg[0] = AUX_I2C_WRITE << 4;
+
+       if (!(mode & MODE_I2C_STOP))
+               msg[0] |= AUX_I2C_MOT << 4;
+
+       msg[1] = address >> 8;
+       msg[2] = address;
+
+       switch (mode) {
+       case MODE_I2C_WRITE:
+               msg[3] = 0;
+               msg[4] = write_byte;
+               msg_bytes = 5;
+               reply_bytes = 1;
+               break;
+       case MODE_I2C_READ:
+               msg[3] = 0;
+               msg_bytes = 4;
+               reply_bytes = 2;
+               break;
+       default:
+               msg_bytes = 3;
+               reply_bytes = 1;
+               break;
+       }
+
+       for (;;) {
+               ret = (*algo_data->aux_ch)(adapter,
+                                          msg, msg_bytes,
+                                          reply, reply_bytes);
+               if (ret < 0) {
+                       DRM_DEBUG("aux_ch failed %d\n", ret);
+                       return ret;
+               }
+               switch (reply[0] & AUX_I2C_REPLY_MASK) {
+               case AUX_I2C_REPLY_ACK:
+                       if (mode == MODE_I2C_READ) {
+                               *read_byte = reply[1];
+                       }
+                       return reply_bytes - 1;
+               case AUX_I2C_REPLY_NACK:
+                       DRM_DEBUG("aux_ch nack\n");
+                       return -EREMOTEIO;
+               case AUX_I2C_REPLY_DEFER:
+                       DRM_DEBUG("aux_ch defer\n");
+                       udelay(100);
+                       break;
+               default:
+                       DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]);
+                       return -EREMOTEIO;
+               }
+       }
+}
+
+/*
+ * I2C over AUX CH
+ */
+
+/*
+ * Send the address. If the I2C link is running, this 'restarts'
+ * the connection with the new address, this is used for doing
+ * a write followed by a read (as needed for DDC)
+ */
+static int
+i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
+{
+       struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+       int mode = MODE_I2C_START;
+       int ret;
+
+       if (reading)
+               mode |= MODE_I2C_READ;
+       else
+               mode |= MODE_I2C_WRITE;
+       algo_data->address = address;
+       algo_data->running = true;
+       ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
+       return ret;
+}
+
+/*
+ * Stop the I2C transaction. This closes out the link, sending
+ * a bare address packet with the MOT bit turned off
+ */
+static void
+i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
+{
+       struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+       int mode = MODE_I2C_STOP;
+
+       if (reading)
+               mode |= MODE_I2C_READ;
+       else
+               mode |= MODE_I2C_WRITE;
+       if (algo_data->running) {
+               (void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
+               algo_data->running = false;
+       }
+}
+
+/*
+ * Write a single byte to the current I2C address, the
+ * the I2C link must be running or this returns -EIO
+ */
+static int
+i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
+{
+       struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+       int ret;
+
+       if (!algo_data->running)
+               return -EIO;
+
+       ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
+       return ret;
+}
+
+/*
+ * Read a single byte from the current I2C address, the
+ * I2C link must be running or this returns -EIO
+ */
+static int
+i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
+{
+       struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+       int ret;
+
+       if (!algo_data->running)
+               return -EIO;
+
+       ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
+       return ret;
+}
+
+static int
+i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
+                    struct i2c_msg *msgs,
+                    int num)
+{
+       int ret = 0;
+       bool reading = false;
+       int m;
+       int b;
+
+       for (m = 0; m < num; m++) {
+               u16 len = msgs[m].len;
+               u8 *buf = msgs[m].buf;
+               reading = (msgs[m].flags & I2C_M_RD) != 0;
+               ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
+               if (ret < 0)
+                       break;
+               if (reading) {
+                       for (b = 0; b < len; b++) {
+                               ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
+                               if (ret < 0)
+                                       break;
+                       }
+               } else {
+                       for (b = 0; b < len; b++) {
+                               ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
+                               if (ret < 0)
+                                       break;
+                       }
+               }
+               if (ret < 0)
+                       break;
+       }
+       if (ret >= 0)
+               ret = num;
+       i2c_algo_dp_aux_stop(adapter, reading);
+       DRM_DEBUG("dp_aux_xfer return %d\n", ret);
+       return ret;
+}
+
+static u32
+i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+              I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+              I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+              I2C_FUNC_10BIT_ADDR;
+}
+
+static const struct i2c_algorithm i2c_dp_aux_algo = {
+       .master_xfer    = i2c_algo_dp_aux_xfer,
+       .functionality  = i2c_algo_dp_aux_functionality,
+};
+
+static void
+i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
+{
+       (void) i2c_algo_dp_aux_address(adapter, 0, false);
+       (void) i2c_algo_dp_aux_stop(adapter, false);
+                                          
+}
+
+static int
+i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
+{
+       adapter->algo = &i2c_dp_aux_algo;
+       adapter->retries = 3;
+       i2c_dp_aux_reset_bus(adapter);
+       return 0;
+}
+
+int
+i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
+{
+       int error;
+       
+       error = i2c_dp_aux_prepare_bus(adapter);
+       if (error)
+               return error;
+       error = i2c_add_adapter(adapter);
+       return error;
+}
+EXPORT_SYMBOL(i2c_dp_aux_add_bus);
index cd4b9c5f715e82e9abb4981945009aee09b2e9da..26a6227c15fe7c0f20f9f93594ba93254b7b3301 100644 (file)
 #define INTEL_OUTPUT_LVDS 4
 #define INTEL_OUTPUT_TVOUT 5
 #define INTEL_OUTPUT_HDMI 6
+#define INTEL_OUTPUT_DISPLAYPORT 7
+#define INTEL_OUTPUT_EDP 8
+
+/* Intel Pipe Clone Bit */
+#define INTEL_HDMIB_CLONE_BIT 1
+#define INTEL_HDMIC_CLONE_BIT 2
+#define INTEL_HDMID_CLONE_BIT 3
+#define INTEL_HDMIE_CLONE_BIT 4
+#define INTEL_HDMIF_CLONE_BIT 5
+#define INTEL_SDVO_NON_TV_CLONE_BIT 6
+#define INTEL_SDVO_TV_CLONE_BIT 7
+#define INTEL_SDVO_LVDS_CLONE_BIT 8
+#define INTEL_ANALOG_CLONE_BIT 9
+#define INTEL_TV_CLONE_BIT 10
+#define INTEL_DP_B_CLONE_BIT 11
+#define INTEL_DP_C_CLONE_BIT 12
+#define INTEL_DP_D_CLONE_BIT 13
+#define INTEL_LVDS_CLONE_BIT 14
+#define INTEL_DVO_TMDS_CLONE_BIT 15
+#define INTEL_DVO_LVDS_CLONE_BIT 16
+#define INTEL_EDP_CLONE_BIT 17
 
 #define INTEL_DVO_CHIP_NONE 0
 #define INTEL_DVO_CHIP_LVDS 1
@@ -65,7 +86,6 @@ struct intel_i2c_chan {
        u32 reg; /* GPIO reg */
        struct i2c_adapter adapter;
        struct i2c_algo_bit_data algo;
-        u8 slave_addr;
 };
 
 struct intel_framebuffer {
@@ -79,11 +99,14 @@ struct intel_output {
 
        struct drm_encoder enc;
        int type;
-       struct intel_i2c_chan *i2c_bus; /* for control functions */
-       struct intel_i2c_chan *ddc_bus; /* for DDC only stuff */
+       struct i2c_adapter *i2c_bus;
+       struct i2c_adapter *ddc_bus;
        bool load_detect_temp;
        bool needs_tv_clock;
        void *dev_priv;
+       void (*hot_plug)(struct intel_output *);
+       int crtc_mask;
+       int clone_mask;
 };
 
 struct intel_crtc {
@@ -104,9 +127,9 @@ struct intel_crtc {
 #define enc_to_intel_output(x) container_of(x, struct intel_output, enc)
 #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
 
-struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
-                                       const char *name);
-void intel_i2c_destroy(struct intel_i2c_chan *chan);
+struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
+                                    const char *name);
+void intel_i2c_destroy(struct i2c_adapter *adapter);
 int intel_ddc_get_modes(struct intel_output *intel_output);
 extern bool intel_ddc_probe(struct intel_output *intel_output);
 void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
@@ -116,6 +139,12 @@ extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
 extern void intel_dvo_init(struct drm_device *dev);
 extern void intel_tv_init(struct drm_device *dev);
 extern void intel_lvds_init(struct drm_device *dev);
+extern void intel_dp_init(struct drm_device *dev, int dp_reg);
+void
+intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
+                struct drm_display_mode *adjusted_mode);
+extern void intel_edp_link_config (struct intel_output *, int *, int *);
+
 
 extern void intel_crtc_load_lut(struct drm_crtc *crtc);
 extern void intel_encoder_prepare (struct drm_encoder *encoder);
index 1ee3007d6ec04e062e8d18fd482047687b1ea026..a4d2606de778c3d419713c3d8552290d828826c0 100644 (file)
@@ -384,10 +384,9 @@ void intel_dvo_init(struct drm_device *dev)
 {
        struct intel_output *intel_output;
        struct intel_dvo_device *dvo;
-       struct intel_i2c_chan *i2cbus = NULL;
+       struct i2c_adapter *i2cbus = NULL;
        int ret = 0;
        int i;
-       int gpio_inited = 0;
        int encoder_type = DRM_MODE_ENCODER_NONE;
        intel_output = kzalloc (sizeof(struct intel_output), GFP_KERNEL);
        if (!intel_output)
@@ -420,14 +419,11 @@ void intel_dvo_init(struct drm_device *dev)
                 * It appears that everything is on GPIOE except for panels
                 * on i830 laptops, which are on GPIOB (DVOA).
                 */
-               if (gpio_inited != gpio) {
-                       if (i2cbus != NULL)
-                               intel_i2c_destroy(i2cbus);
-                       if (!(i2cbus = intel_i2c_create(dev, gpio,
-                               gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) {
-                               continue;
-                       }
-                       gpio_inited = gpio;
+               if (i2cbus != NULL)
+                       intel_i2c_destroy(i2cbus);
+               if (!(i2cbus = intel_i2c_create(dev, gpio,
+                       gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) {
+                       continue;
                }
 
                if (dvo->dev_ops!= NULL)
@@ -439,14 +435,20 @@ void intel_dvo_init(struct drm_device *dev)
                        continue;
 
                intel_output->type = INTEL_OUTPUT_DVO;
+               intel_output->crtc_mask = (1 << 0) | (1 << 1);
                switch (dvo->type) {
                case INTEL_DVO_CHIP_TMDS:
+                       intel_output->clone_mask =
+                               (1 << INTEL_DVO_TMDS_CLONE_BIT) |
+                               (1 << INTEL_ANALOG_CLONE_BIT);
                        drm_connector_init(dev, connector,
                                           &intel_dvo_connector_funcs,
                                           DRM_MODE_CONNECTOR_DVII);
                        encoder_type = DRM_MODE_ENCODER_TMDS;
                        break;
                case INTEL_DVO_CHIP_LVDS:
+                       intel_output->clone_mask =
+                               (1 << INTEL_DVO_LVDS_CLONE_BIT);
                        drm_connector_init(dev, connector,
                                           &intel_dvo_connector_funcs,
                                           DRM_MODE_CONNECTOR_LVDS);
index 1af7d68e380756f3f785551cb9c8a4c38da8604a..1d30802e773e383492c03aeabb99e6a3ddd623f2 100644 (file)
@@ -453,7 +453,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
        size = ALIGN(size, PAGE_SIZE);
        fbo = drm_gem_object_alloc(dev, size);
        if (!fbo) {
-               printk(KERN_ERR "failed to allocate framebuffer\n");
+               DRM_ERROR("failed to allocate framebuffer\n");
                ret = -ENOMEM;
                goto out;
        }
@@ -610,8 +610,8 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
        par->dev = dev;
 
        /* To allow resizeing without swapping buffers */
-       printk("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width,
-              intel_fb->base.height, obj_priv->gtt_offset, fbo);
+       DRM_DEBUG("allocated %dx%d fb: 0x%08x, bo %p\n", intel_fb->base.width,
+                 intel_fb->base.height, obj_priv->gtt_offset, fbo);
 
        mutex_unlock(&dev->struct_mutex);
        return 0;
@@ -698,13 +698,13 @@ static int intelfb_multi_fb_probe_crtc(struct drm_device *dev, struct drm_crtc *
        } else
                intelfb_set_par(info);
 
-       printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+       DRM_INFO("fb%d: %s frame buffer device\n", info->node,
               info->fix.id);
 
        /* Switch back to kernel console on panic */
        kernelfb_mode = *modeset;
        atomic_notifier_chain_register(&panic_notifier_list, &paniced);
-       printk(KERN_INFO "registered panic notifier\n");
+       DRM_DEBUG("registered panic notifier\n");
 
        return 0;
 }
@@ -852,13 +852,13 @@ static int intelfb_single_fb_probe(struct drm_device *dev)
        } else
                intelfb_set_par(info);
 
-       printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+       DRM_INFO("fb%d: %s frame buffer device\n", info->node,
               info->fix.id);
 
        /* Switch back to kernel console on panic */
        kernelfb_mode = *modeset;
        atomic_notifier_chain_register(&panic_notifier_list, &paniced);
-       printk(KERN_INFO "registered panic notifier\n");
+       DRM_DEBUG("registered panic notifier\n");
 
        return 0;
 }
@@ -872,8 +872,8 @@ void intelfb_restore(void)
 {
        int ret;
        if ((ret = drm_crtc_helper_set_config(&kernelfb_mode)) != 0) {
-               printk(KERN_ERR "Failed to restore crtc configuration: %d\n",
-                      ret);
+               DRM_ERROR("Failed to restore crtc configuration: %d\n",
+                         ret);
        }
 }
 
index 4ea2a651b92c43079a4c3185a829e241822ca488..fa304e136010b0cef680590adbfc606b1776dcfa 100644 (file)
@@ -31,6 +31,7 @@
 #include "drmP.h"
 #include "drm.h"
 #include "drm_crtc.h"
+#include "drm_edid.h"
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
@@ -56,8 +57,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
        sdvox = SDVO_ENCODING_HDMI |
                SDVO_BORDER_ENABLE |
                SDVO_VSYNC_ACTIVE_HIGH |
-               SDVO_HSYNC_ACTIVE_HIGH |
-               SDVO_NULL_PACKETS_DURING_VSYNC;
+               SDVO_HSYNC_ACTIVE_HIGH;
 
        if (hdmi_priv->has_hdmi_sink)
                sdvox |= SDVO_AUDIO_ENABLE;
@@ -129,83 +129,28 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
        return true;
 }
 
-static void
-intel_hdmi_sink_detect(struct drm_connector *connector)
-{
-       struct intel_output *intel_output = to_intel_output(connector);
-       struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
-       struct edid *edid = NULL;
-
-       edid = drm_get_edid(&intel_output->base,
-                           &intel_output->ddc_bus->adapter);
-       if (edid != NULL) {
-               hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
-               kfree(edid);
-               intel_output->base.display_info.raw_edid = NULL;
-       }
-}
-
-static enum drm_connector_status
-igdng_hdmi_detect(struct drm_connector *connector)
-{
-       struct intel_output *intel_output = to_intel_output(connector);
-       struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
-
-       /* FIXME hotplug detect */
-
-       hdmi_priv->has_hdmi_sink = false;
-       intel_hdmi_sink_detect(connector);
-       if (hdmi_priv->has_hdmi_sink)
-               return connector_status_connected;
-       else
-               return connector_status_disconnected;
-}
-
 static enum drm_connector_status
 intel_hdmi_detect(struct drm_connector *connector)
 {
-       struct drm_device *dev = connector->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_output *intel_output = to_intel_output(connector);
        struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
-       u32 temp, bit;
-
-       if (IS_IGDNG(dev))
-               return igdng_hdmi_detect(connector);
-
-       temp = I915_READ(PORT_HOTPLUG_EN);
-
-       switch (hdmi_priv->sdvox_reg) {
-       case SDVOB:
-               temp |= HDMIB_HOTPLUG_INT_EN;
-               break;
-       case SDVOC:
-               temp |= HDMIC_HOTPLUG_INT_EN;
-               break;
-       default:
-               return connector_status_unknown;
-       }
-
-       I915_WRITE(PORT_HOTPLUG_EN, temp);
+       struct edid *edid = NULL;
+       enum drm_connector_status status = connector_status_disconnected;
 
-       POSTING_READ(PORT_HOTPLUG_EN);
+       hdmi_priv->has_hdmi_sink = false;
+       edid = drm_get_edid(&intel_output->base,
+                           intel_output->ddc_bus);
 
-       switch (hdmi_priv->sdvox_reg) {
-       case SDVOB:
-               bit = HDMIB_HOTPLUG_INT_STATUS;
-               break;
-       case SDVOC:
-               bit = HDMIC_HOTPLUG_INT_STATUS;
-               break;
-       default:
-               return connector_status_unknown;
+       if (edid) {
+               if (edid->input & DRM_EDID_INPUT_DIGITAL) {
+                       status = connector_status_connected;
+                       hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
+               }
+               intel_output->base.display_info.raw_edid = NULL;
+               kfree(edid);
        }
 
-       if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) {
-               intel_hdmi_sink_detect(connector);
-               return connector_status_connected;
-       } else
-               return connector_status_disconnected;
+       return status;
 }
 
 static int intel_hdmi_get_modes(struct drm_connector *connector)
@@ -285,22 +230,28 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 
        connector->interlace_allowed = 0;
        connector->doublescan_allowed = 0;
+       intel_output->crtc_mask = (1 << 0) | (1 << 1);
 
        /* Set up the DDC bus. */
-       if (sdvox_reg == SDVOB)
+       if (sdvox_reg == SDVOB) {
+               intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB");
-       else if (sdvox_reg == SDVOC)
+       } else if (sdvox_reg == SDVOC) {
+               intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC");
-       else if (sdvox_reg == HDMIB)
+       } else if (sdvox_reg == HDMIB) {
+               intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE,
                                                                "HDMIB");
-       else if (sdvox_reg == HDMIC)
+       } else if (sdvox_reg == HDMIC) {
+               intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD,
                                                                "HDMIC");
-       else if (sdvox_reg == HDMID)
+       } else if (sdvox_reg == HDMID) {
+               intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
                intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF,
                                                                "HDMID");
-
+       }
        if (!intel_output->ddc_bus)
                goto err_connector;
 
index f7061f68d050c817c86ef1adf4d4bab336d01b59..62b8bead7652cdeed3f12d6680a64d5659da6889 100644 (file)
@@ -124,6 +124,7 @@ static void set_data(void *data, int state_high)
  * @output: driver specific output device
  * @reg: GPIO reg to use
  * @name: name for this bus
+ * @slave_addr: slave address (if fixed)
  *
  * Creates and registers a new i2c bus with the Linux i2c layer, for use
  * in output probing and control (e.g. DDC or SDVO control functions).
@@ -139,8 +140,8 @@ static void set_data(void *data, int state_high)
  *   %GPIOH
  * see PRM for details on how these different busses are used.
  */
-struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
-                                       const char *name)
+struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
+                                    const char *name)
 {
        struct intel_i2c_chan *chan;
 
@@ -174,7 +175,7 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
        intel_i2c_quirk_set(dev, false);
        udelay(20);
 
-       return chan;
+       return &chan->adapter;
 
 out_free:
        kfree(chan);
@@ -187,11 +188,16 @@ out_free:
  *
  * Unregister the adapter from the i2c layer, then free the structure.
  */
-void intel_i2c_destroy(struct intel_i2c_chan *chan)
+void intel_i2c_destroy(struct i2c_adapter *adapter)
 {
-       if (!chan)
+       struct intel_i2c_chan *chan;
+
+       if (!adapter)
                return;
 
+       chan = container_of(adapter,
+                           struct intel_i2c_chan,
+                           adapter);
        i2c_del_adapter(&chan->adapter);
        kfree(chan);
 }
index f073ed8432e8fb9547d272653b51315a3bc90de3..8df02ef892617ed7a47b8ab9d88665b675cbb046 100644 (file)
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
+#include <linux/acpi.h>
 
 #define I915_LVDS "i915_lvds"
 
+/*
+ * the following four scaling options are defined.
+ * #define DRM_MODE_SCALE_NON_GPU      0
+ * #define DRM_MODE_SCALE_FULLSCREEN   1
+ * #define DRM_MODE_SCALE_NO_SCALE     2
+ * #define DRM_MODE_SCALE_ASPECT       3
+ */
+
+/* Private structure for the integrated LVDS support */
+struct intel_lvds_priv {
+       int fitting_mode;
+       u32 pfit_control;
+       u32 pfit_pgm_ratios;
+};
+
 /**
  * Sets the backlight level.
  *
@@ -213,26 +229,45 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
                                  struct drm_display_mode *mode,
                                  struct drm_display_mode *adjusted_mode)
 {
+       /*
+        * float point operation is not supported . So the PANEL_RATIO_FACTOR
+        * is defined, which can avoid the float point computation when
+        * calculating the panel ratio.
+        */
+#define PANEL_RATIO_FACTOR 8192
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
        struct drm_encoder *tmp_encoder;
+       struct intel_output *intel_output = enc_to_intel_output(encoder);
+       struct intel_lvds_priv *lvds_priv = intel_output->dev_priv;
+       u32 pfit_control = 0, pfit_pgm_ratios = 0;
+       int left_border = 0, right_border = 0, top_border = 0;
+       int bottom_border = 0;
+       bool border = 0;
+       int panel_ratio, desired_ratio, vert_scale, horiz_scale;
+       int horiz_ratio, vert_ratio;
+       u32 hsync_width, vsync_width;
+       u32 hblank_width, vblank_width;
+       u32 hsync_pos, vsync_pos;
 
        /* Should never happen!! */
        if (!IS_I965G(dev) && intel_crtc->pipe == 0) {
-               printk(KERN_ERR "Can't support LVDS on pipe A\n");
+               DRM_ERROR("Can't support LVDS on pipe A\n");
                return false;
        }
 
        /* Should never happen!! */
        list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, head) {
                if (tmp_encoder != encoder && tmp_encoder->crtc == encoder->crtc) {
-                       printk(KERN_ERR "Can't enable LVDS and another "
+                       DRM_ERROR("Can't enable LVDS and another "
                               "encoder on the same pipe\n");
                        return false;
                }
        }
-
+       /* If we don't have a panel mode, there is nothing we can do */
+       if (dev_priv->panel_fixed_mode == NULL)
+               return true;
        /*
         * If we have timings from the BIOS for the panel, put them in
         * to the adjusted mode.  The CRTC will be set up for this mode,
@@ -256,6 +291,243 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
                drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
        }
 
+       /* Make sure pre-965s set dither correctly */
+       if (!IS_I965G(dev)) {
+               if (dev_priv->panel_wants_dither || dev_priv->lvds_dither)
+                       pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+       }
+
+       /* Native modes don't need fitting */
+       if (adjusted_mode->hdisplay == mode->hdisplay &&
+                       adjusted_mode->vdisplay == mode->vdisplay) {
+               pfit_pgm_ratios = 0;
+               border = 0;
+               goto out;
+       }
+
+       /* 965+ wants fuzzy fitting */
+       if (IS_I965G(dev))
+               pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) |
+                                       PFIT_FILTER_FUZZY;
+
+       hsync_width = adjusted_mode->crtc_hsync_end -
+                                       adjusted_mode->crtc_hsync_start;
+       vsync_width = adjusted_mode->crtc_vsync_end -
+                                       adjusted_mode->crtc_vsync_start;
+       hblank_width = adjusted_mode->crtc_hblank_end -
+                                       adjusted_mode->crtc_hblank_start;
+       vblank_width = adjusted_mode->crtc_vblank_end -
+                                       adjusted_mode->crtc_vblank_start;
+       /*
+        * Deal with panel fitting options. Figure out how to stretch the
+        * image based on its aspect ratio & the current panel fitting mode.
+        */
+       panel_ratio = adjusted_mode->hdisplay * PANEL_RATIO_FACTOR /
+                               adjusted_mode->vdisplay;
+       desired_ratio = mode->hdisplay * PANEL_RATIO_FACTOR /
+                               mode->vdisplay;
+       /*
+        * Enable automatic panel scaling for non-native modes so that they fill
+        * the screen.  Should be enabled before the pipe is enabled, according
+        * to register description and PRM.
+        * Change the value here to see the borders for debugging
+        */
+       I915_WRITE(BCLRPAT_A, 0);
+       I915_WRITE(BCLRPAT_B, 0);
+
+       switch (lvds_priv->fitting_mode) {
+       case DRM_MODE_SCALE_NO_SCALE:
+               /*
+                * For centered modes, we have to calculate border widths &
+                * heights and modify the values programmed into the CRTC.
+                */
+               left_border = (adjusted_mode->hdisplay - mode->hdisplay) / 2;
+               right_border = left_border;
+               if (mode->hdisplay & 1)
+                       right_border++;
+               top_border = (adjusted_mode->vdisplay - mode->vdisplay) / 2;
+               bottom_border = top_border;
+               if (mode->vdisplay & 1)
+                       bottom_border++;
+               /* Set active & border values */
+               adjusted_mode->crtc_hdisplay = mode->hdisplay;
+               /* Keep the boder be even */
+               if (right_border & 1)
+                       right_border++;
+               /* use the border directly instead of border minuse one */
+               adjusted_mode->crtc_hblank_start = mode->hdisplay +
+                                               right_border;
+               /* keep the blank width constant */
+               adjusted_mode->crtc_hblank_end =
+                       adjusted_mode->crtc_hblank_start + hblank_width;
+               /* get the hsync pos relative to hblank start */
+               hsync_pos = (hblank_width - hsync_width) / 2;
+               /* keep the hsync pos be even */
+               if (hsync_pos & 1)
+                       hsync_pos++;
+               adjusted_mode->crtc_hsync_start =
+                               adjusted_mode->crtc_hblank_start + hsync_pos;
+               /* keep the hsync width constant */
+               adjusted_mode->crtc_hsync_end =
+                               adjusted_mode->crtc_hsync_start + hsync_width;
+               adjusted_mode->crtc_vdisplay = mode->vdisplay;
+               /* use the border instead of border minus one */
+               adjusted_mode->crtc_vblank_start = mode->vdisplay +
+                                               bottom_border;
+               /* keep the vblank width constant */
+               adjusted_mode->crtc_vblank_end =
+                               adjusted_mode->crtc_vblank_start + vblank_width;
+               /* get the vsync start postion relative to vblank start */
+               vsync_pos = (vblank_width - vsync_width) / 2;
+               adjusted_mode->crtc_vsync_start =
+                               adjusted_mode->crtc_vblank_start + vsync_pos;
+               /* keep the vsync width constant */
+               adjusted_mode->crtc_vsync_end =
+                               adjusted_mode->crtc_vblank_start + vsync_width;
+               border = 1;
+               break;
+       case DRM_MODE_SCALE_ASPECT:
+               /* Scale but preserve the spect ratio */
+               pfit_control |= PFIT_ENABLE;
+               if (IS_I965G(dev)) {
+                       /* 965+ is easy, it does everything in hw */
+                       if (panel_ratio > desired_ratio)
+                               pfit_control |= PFIT_SCALING_PILLAR;
+                       else if (panel_ratio < desired_ratio)
+                               pfit_control |= PFIT_SCALING_LETTER;
+                       else
+                               pfit_control |= PFIT_SCALING_AUTO;
+               } else {
+                       /*
+                        * For earlier chips we have to calculate the scaling
+                        * ratio by hand and program it into the
+                        * PFIT_PGM_RATIO register
+                        */
+                       u32 horiz_bits, vert_bits, bits = 12;
+                       horiz_ratio = mode->hdisplay * PANEL_RATIO_FACTOR/
+                                               adjusted_mode->hdisplay;
+                       vert_ratio = mode->vdisplay * PANEL_RATIO_FACTOR/
+                                               adjusted_mode->vdisplay;
+                       horiz_scale = adjusted_mode->hdisplay *
+                                       PANEL_RATIO_FACTOR / mode->hdisplay;
+                       vert_scale = adjusted_mode->vdisplay *
+                                       PANEL_RATIO_FACTOR / mode->vdisplay;
+
+                       /* retain aspect ratio */
+                       if (panel_ratio > desired_ratio) { /* Pillar */
+                               u32 scaled_width;
+                               scaled_width = mode->hdisplay * vert_scale /
+                                               PANEL_RATIO_FACTOR;
+                               horiz_ratio = vert_ratio;
+                               pfit_control |= (VERT_AUTO_SCALE |
+                                                VERT_INTERP_BILINEAR |
+                                                HORIZ_INTERP_BILINEAR);
+                               /* Pillar will have left/right borders */
+                               left_border = (adjusted_mode->hdisplay -
+                                               scaled_width) / 2;
+                               right_border = left_border;
+                               if (mode->hdisplay & 1) /* odd resolutions */
+                                       right_border++;
+                               /* keep the border be even */
+                               if (right_border & 1)
+                                       right_border++;
+                               adjusted_mode->crtc_hdisplay = scaled_width;
+                               /* use border instead of border minus one */
+                               adjusted_mode->crtc_hblank_start =
+                                       scaled_width + right_border;
+                               /* keep the hblank width constant */
+                               adjusted_mode->crtc_hblank_end =
+                                       adjusted_mode->crtc_hblank_start +
+                                                       hblank_width;
+                               /*
+                                * get the hsync start pos relative to
+                                * hblank start
+                                */
+                               hsync_pos = (hblank_width - hsync_width) / 2;
+                               /* keep the hsync_pos be even */
+                               if (hsync_pos & 1)
+                                       hsync_pos++;
+                               adjusted_mode->crtc_hsync_start =
+                                       adjusted_mode->crtc_hblank_start +
+                                                       hsync_pos;
+                               /* keept hsync width constant */
+                               adjusted_mode->crtc_hsync_end =
+                                       adjusted_mode->crtc_hsync_start +
+                                                       hsync_width;
+                               border = 1;
+                       } else if (panel_ratio < desired_ratio) { /* letter */
+                               u32 scaled_height = mode->vdisplay *
+                                       horiz_scale / PANEL_RATIO_FACTOR;
+                               vert_ratio = horiz_ratio;
+                               pfit_control |= (HORIZ_AUTO_SCALE |
+                                                VERT_INTERP_BILINEAR |
+                                                HORIZ_INTERP_BILINEAR);
+                               /* Letterbox will have top/bottom border */
+                               top_border = (adjusted_mode->vdisplay -
+                                       scaled_height) / 2;
+                               bottom_border = top_border;
+                               if (mode->vdisplay & 1)
+                                       bottom_border++;
+                               adjusted_mode->crtc_vdisplay = scaled_height;
+                               /* use border instead of border minus one */
+                               adjusted_mode->crtc_vblank_start =
+                                       scaled_height + bottom_border;
+                               /* keep the vblank width constant */
+                               adjusted_mode->crtc_vblank_end =
+                                       adjusted_mode->crtc_vblank_start +
+                                                       vblank_width;
+                               /*
+                                * get the vsync start pos relative to
+                                * vblank start
+                                */
+                               vsync_pos = (vblank_width - vsync_width) / 2;
+                               adjusted_mode->crtc_vsync_start =
+                                       adjusted_mode->crtc_vblank_start +
+                                                       vsync_pos;
+                               /* keep the vsync width constant */
+                               adjusted_mode->crtc_vsync_end =
+                                       adjusted_mode->crtc_vsync_start +
+                                                       vsync_width;
+                               border = 1;
+                       } else {
+                       /* Aspects match, Let hw scale both directions */
+                               pfit_control |= (VERT_AUTO_SCALE |
+                                                HORIZ_AUTO_SCALE |
+                                                VERT_INTERP_BILINEAR |
+                                                HORIZ_INTERP_BILINEAR);
+                       }
+                       horiz_bits = (1 << bits) * horiz_ratio /
+                                       PANEL_RATIO_FACTOR;
+                       vert_bits = (1 << bits) * vert_ratio /
+                                       PANEL_RATIO_FACTOR;
+                       pfit_pgm_ratios =
+                               ((vert_bits << PFIT_VERT_SCALE_SHIFT) &
+                                               PFIT_VERT_SCALE_MASK) |
+                               ((horiz_bits << PFIT_HORIZ_SCALE_SHIFT) &
+                                               PFIT_HORIZ_SCALE_MASK);
+               }
+               break;
+
+       case DRM_MODE_SCALE_FULLSCREEN:
+               /*
+                * Full scaling, even if it changes the aspect ratio.
+                * Fortunately this is all done for us in hw.
+                */
+               pfit_control |= PFIT_ENABLE;
+               if (IS_I965G(dev))
+                       pfit_control |= PFIT_SCALING_AUTO;
+               else
+                       pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
+                                        VERT_INTERP_BILINEAR |
+                                        HORIZ_INTERP_BILINEAR);
+               break;
+       default:
+               break;
+       }
+
+out:
+       lvds_priv->pfit_control = pfit_control;
+       lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios;
        /*
         * XXX: It would be nice to support lower refresh rates on the
         * panels to reduce power consumption, and perhaps match the
@@ -301,8 +573,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
 {
        struct drm_device *dev = encoder->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
-       u32 pfit_control;
+       struct intel_output *intel_output = enc_to_intel_output(encoder);
+       struct intel_lvds_priv *lvds_priv = intel_output->dev_priv;
 
        /*
         * The LVDS pin pair will already have been turned on in the
@@ -319,22 +591,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
         * screen.  Should be enabled before the pipe is enabled, according to
         * register description and PRM.
         */
-       if (mode->hdisplay != adjusted_mode->hdisplay ||
-           mode->vdisplay != adjusted_mode->vdisplay)
-               pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
-                               HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
-                               HORIZ_INTERP_BILINEAR);
-       else
-               pfit_control = 0;
-
-       if (!IS_I965G(dev)) {
-               if (dev_priv->panel_wants_dither || dev_priv->lvds_dither)
-                       pfit_control |= PANEL_8TO6_DITHER_ENABLE;
-       }
-       else
-               pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT;
-
-       I915_WRITE(PFIT_CONTROL, pfit_control);
+       I915_WRITE(PFIT_PGM_RATIOS, lvds_priv->pfit_pgm_ratios);
+       I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control);
 }
 
 /**
@@ -406,6 +664,34 @@ static int intel_lvds_set_property(struct drm_connector *connector,
                                   struct drm_property *property,
                                   uint64_t value)
 {
+       struct drm_device *dev = connector->dev;
+       struct intel_output *intel_output =
+                       to_intel_output(connector);
+
+       if (property == dev->mode_config.scaling_mode_property &&
+                               connector->encoder) {
+               struct drm_crtc *crtc = connector->encoder->crtc;
+               struct intel_lvds_priv *lvds_priv = intel_output->dev_priv;
+               if (value == DRM_MODE_SCALE_NON_GPU) {
+                       DRM_DEBUG_KMS(I915_LVDS,
+                                       "non_GPU property is unsupported\n");
+                       return 0;
+               }
+               if (lvds_priv->fitting_mode == value) {
+                       /* the LVDS scaling property is not changed */
+                       return 0;
+               }
+               lvds_priv->fitting_mode = value;
+               if (crtc && crtc->enabled) {
+                       /*
+                        * If the CRTC is enabled, the display will be changed
+                        * according to the new panel fitting mode.
+                        */
+                       drm_crtc_helper_set_mode(crtc, &crtc->mode,
+                               crtc->x, crtc->y, crtc->fb);
+               }
+       }
+
        return 0;
 }
 
@@ -456,7 +742,7 @@ static const struct dmi_system_id intel_no_lvds[] = {
                .callback = intel_no_lvds_dmi_callback,
                .ident = "Apple Mac Mini (Core series)",
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
                },
        },
@@ -464,7 +750,7 @@ static const struct dmi_system_id intel_no_lvds[] = {
                .callback = intel_no_lvds_dmi_callback,
                .ident = "Apple Mac Mini (Core 2 series)",
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"),
                },
        },
@@ -492,6 +778,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "i965GMx-IF"),
                },
        },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "AOpen Mini PC MP915",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
+                       DMI_MATCH(DMI_BOARD_NAME, "i915GMx-F"),
+               },
+       },
        {
                .callback = intel_no_lvds_dmi_callback,
                .ident = "Aopen i945GTt-VFA",
@@ -503,6 +797,65 @@ static const struct dmi_system_id intel_no_lvds[] = {
        { }     /* terminating entry */
 };
 
+#ifdef CONFIG_ACPI
+/*
+ * check_lid_device -- check whether @handle is an ACPI LID device.
+ * @handle: ACPI device handle
+ * @level : depth in the ACPI namespace tree
+ * @context: the number of LID device when we find the device
+ * @rv: a return value to fill if desired (Not use)
+ */
+static acpi_status
+check_lid_device(acpi_handle handle, u32 level, void *context,
+                       void **return_value)
+{
+       struct acpi_device *acpi_dev;
+       int *lid_present = context;
+
+       acpi_dev = NULL;
+       /* Get the acpi device for device handle */
+       if (acpi_bus_get_device(handle, &acpi_dev) || !acpi_dev) {
+               /* If there is no ACPI device for handle, return */
+               return AE_OK;
+       }
+
+       if (!strncmp(acpi_device_hid(acpi_dev), "PNP0C0D", 7))
+               *lid_present = 1;
+
+       return AE_OK;
+}
+
+/**
+ * check whether there exists the ACPI LID device by enumerating the ACPI
+ * device tree.
+ */
+static int intel_lid_present(void)
+{
+       int lid_present = 0;
+
+       if (acpi_disabled) {
+               /* If ACPI is disabled, there is no ACPI device tree to
+                * check, so assume the LID device would have been present.
+                */
+               return 1;
+       }
+
+       acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+                               ACPI_UINT32_MAX,
+                               check_lid_device, &lid_present, NULL);
+
+       return lid_present;
+}
+#else
+static int intel_lid_present(void)
+{
+       /* In the absence of ACPI built in, assume that the LID device would
+        * have been present.
+        */
+       return 1;
+}
+#endif
+
 /**
  * intel_lvds_init - setup LVDS connectors on this device
  * @dev: drm device
@@ -518,6 +871,7 @@ void intel_lvds_init(struct drm_device *dev)
        struct drm_encoder *encoder;
        struct drm_display_mode *scan; /* *modes, *bios_mode; */
        struct drm_crtc *crtc;
+       struct intel_lvds_priv *lvds_priv;
        u32 lvds;
        int pipe, gpio = GPIOC;
 
@@ -525,13 +879,28 @@ void intel_lvds_init(struct drm_device *dev)
        if (dmi_check_system(intel_no_lvds))
                return;
 
+       /* Assume that any device without an ACPI LID device also doesn't
+        * have an integrated LVDS.  We would be better off parsing the BIOS
+        * to get a reliable indicator, but that code isn't written yet.
+        *
+        * In the case of all-in-one desktops using LVDS that we've seen,
+        * they're using SDVO LVDS.
+        */
+       if (!intel_lid_present())
+               return;
+
        if (IS_IGDNG(dev)) {
                if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
                        return;
+               if (dev_priv->edp_support) {
+                       DRM_DEBUG("disable LVDS for eDP support\n");
+                       return;
+               }
                gpio = PCH_GPIOC;
        }
 
-       intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
+       intel_output = kzalloc(sizeof(struct intel_output) +
+                               sizeof(struct intel_lvds_priv), GFP_KERNEL);
        if (!intel_output) {
                return;
        }
@@ -547,13 +916,26 @@ void intel_lvds_init(struct drm_device *dev)
        drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
        intel_output->type = INTEL_OUTPUT_LVDS;
 
+       intel_output->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
+       intel_output->crtc_mask = (1 << 1);
        drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
        drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
        connector->display_info.subpixel_order = SubPixelHorizontalRGB;
        connector->interlace_allowed = false;
        connector->doublescan_allowed = false;
 
+       lvds_priv = (struct intel_lvds_priv *)(intel_output + 1);
+       intel_output->dev_priv = lvds_priv;
+       /* create the scaling mode property */
+       drm_mode_create_scaling_mode_property(dev);
+       /*
+        * the initial panel fitting mode will be FULL_SCREEN.
+        */
 
+       drm_connector_attach_property(&intel_output->base,
+                                     dev->mode_config.scaling_mode_property,
+                                     DRM_MODE_SCALE_FULLSCREEN);
+       lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN;
        /*
         * LVDS discovery:
         * 1) check for EDID on DDC
@@ -649,5 +1031,5 @@ failed:
        if (intel_output->ddc_bus)
                intel_i2c_destroy(intel_output->ddc_bus);
        drm_connector_cleanup(connector);
-       kfree(connector);
+       kfree(intel_output);
 }
index e0910fefce8713d232ec131d39edad62e91c2058..67e2f4632a2451fd77200e0f9810a18c83afca1d 100644 (file)
@@ -53,10 +53,9 @@ bool intel_ddc_probe(struct intel_output *intel_output)
                }
        };
 
-       intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true);
-       ret = i2c_transfer(&intel_output->ddc_bus->adapter, msgs, 2);
-       intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false);
-
+       intel_i2c_quirk_set(intel_output->base.dev, true);
+       ret = i2c_transfer(intel_output->ddc_bus, msgs, 2);
+       intel_i2c_quirk_set(intel_output->base.dev, false);
        if (ret == 2)
                return true;
 
@@ -74,10 +73,9 @@ int intel_ddc_get_modes(struct intel_output *intel_output)
        struct edid *edid;
        int ret = 0;
 
-       intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true);
-       edid = drm_get_edid(&intel_output->base,
-                           &intel_output->ddc_bus->adapter);
-       intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false);
+       intel_i2c_quirk_set(intel_output->base.dev, true);
+       edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus);
+       intel_i2c_quirk_set(intel_output->base.dev, false);
        if (edid) {
                drm_mode_connector_update_edid_property(&intel_output->base,
                                                        edid);
index 9a00adb3a50896033302bb70b6d715de72408dce..d3b74ba62b4a07bb1702eca5e62f28dcea017ade 100644 (file)
@@ -31,6 +31,7 @@
 #include "drm.h"
 #include "drm_crtc.h"
 #include "intel_drv.h"
+#include "drm_edid.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
 #include "intel_sdvo_regs.h"
@@ -38,8 +39,7 @@
 #undef SDVO_DEBUG
 #define I915_SDVO      "i915_sdvo"
 struct intel_sdvo_priv {
-       struct intel_i2c_chan *i2c_bus;
-       int slaveaddr;
+       u8 slave_addr;
 
        /* Register for the SDVO device: SDVOB or SDVOC */
        int output_device;
@@ -56,6 +56,12 @@ struct intel_sdvo_priv {
        /* Pixel clock limitations reported by the SDVO device, in kHz */
        int pixel_clock_min, pixel_clock_max;
 
+       /*
+       * For multiple function SDVO device,
+       * this is for current attached outputs.
+       */
+       uint16_t attached_output;
+
        /**
         * This is set if we're going to treat the device as TV-out.
         *
@@ -69,11 +75,22 @@ struct intel_sdvo_priv {
         * This is set if we treat the device as HDMI, instead of DVI.
         */
        bool is_hdmi;
+
        /**
         * This is set if we detect output of sdvo device as LVDS.
         */
        bool is_lvds;
 
+       /**
+        * This is sdvo flags for input timing.
+        */
+       uint8_t sdvo_flags;
+
+       /**
+        * This is sdvo fixed pannel mode pointer
+        */
+       struct drm_display_mode *sdvo_lvds_fixed_mode;
+
        /**
         * Returned SDTV resolutions allowed for the current format, if the
         * device reported it.
@@ -104,6 +121,9 @@ struct intel_sdvo_priv {
        u32 save_SDVOX;
 };
 
+static bool
+intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags);
+
 /**
  * Writes the SDVOB or SDVOC with the given value, but always writes both
  * SDVOB and SDVOC to work around apparent hardware issues (according to
@@ -146,13 +166,13 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr,
 
        struct i2c_msg msgs[] = {
                {
-                       .addr = sdvo_priv->i2c_bus->slave_addr,
+                       .addr = sdvo_priv->slave_addr >> 1,
                        .flags = 0,
                        .len = 1,
                        .buf = out_buf,
                },
                {
-                       .addr = sdvo_priv->i2c_bus->slave_addr,
+                       .addr = sdvo_priv->slave_addr >> 1,
                        .flags = I2C_M_RD,
                        .len = 1,
                        .buf = buf,
@@ -162,7 +182,7 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr,
        out_buf[0] = addr;
        out_buf[1] = 0;
 
-       if ((ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2)) == 2)
+       if ((ret = i2c_transfer(intel_output->i2c_bus, msgs, 2)) == 2)
        {
                *ch = buf[0];
                return true;
@@ -175,10 +195,11 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr,
 static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr,
                                  u8 ch)
 {
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
        u8 out_buf[2];
        struct i2c_msg msgs[] = {
                {
-                       .addr = intel_output->i2c_bus->slave_addr,
+                       .addr = sdvo_priv->slave_addr >> 1,
                        .flags = 0,
                        .len = 2,
                        .buf = out_buf,
@@ -188,7 +209,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr,
        out_buf[0] = addr;
        out_buf[1] = ch;
 
-       if (i2c_transfer(&intel_output->i2c_bus->adapter, msgs, 1) == 1)
+       if (i2c_transfer(intel_output->i2c_bus, msgs, 1) == 1)
        {
                return true;
        }
@@ -592,6 +613,7 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output,
                                         uint16_t height)
 {
        struct intel_sdvo_preferred_input_timing_args args;
+       struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
        uint8_t status;
 
        memset(&args, 0, sizeof(args));
@@ -599,7 +621,12 @@ intel_sdvo_create_preferred_input_timing(struct intel_output *output,
        args.width = width;
        args.height = height;
        args.interlace = 0;
-       args.scaled = 0;
+
+       if (sdvo_priv->is_lvds &&
+          (sdvo_priv->sdvo_lvds_fixed_mode->hdisplay != width ||
+           sdvo_priv->sdvo_lvds_fixed_mode->vdisplay != height))
+               args.scaled = 1;
+
        intel_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING,
                             &args, sizeof(args));
        status = intel_sdvo_read_response(output, NULL, 0);
@@ -944,12 +971,7 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
        struct intel_output *output = enc_to_intel_output(encoder);
        struct intel_sdvo_priv *dev_priv = output->dev_priv;
 
-       if (!dev_priv->is_tv) {
-               /* Make the CRTC code factor in the SDVO pixel multiplier.  The
-                * SDVO device will be told of the multiplier during mode_set.
-                */
-               adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode);
-       } else {
+       if (dev_priv->is_tv) {
                struct intel_sdvo_dtd output_dtd;
                bool success;
 
@@ -980,6 +1002,47 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
                        intel_sdvo_get_preferred_input_timing(output,
                                                             &input_dtd);
                        intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
+                       dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags;
+
+                       drm_mode_set_crtcinfo(adjusted_mode, 0);
+
+                       mode->clock = adjusted_mode->clock;
+
+                       adjusted_mode->clock *=
+                               intel_sdvo_get_pixel_multiplier(mode);
+               } else {
+                       return false;
+               }
+       } else if (dev_priv->is_lvds) {
+               struct intel_sdvo_dtd output_dtd;
+               bool success;
+
+               drm_mode_set_crtcinfo(dev_priv->sdvo_lvds_fixed_mode, 0);
+               /* Set output timings */
+               intel_sdvo_get_dtd_from_mode(&output_dtd,
+                               dev_priv->sdvo_lvds_fixed_mode);
+
+               intel_sdvo_set_target_output(output,
+                                            dev_priv->controlled_output);
+               intel_sdvo_set_output_timing(output, &output_dtd);
+
+               /* Set the input timing to the screen. Assume always input 0. */
+               intel_sdvo_set_target_input(output, true, false);
+
+
+               success = intel_sdvo_create_preferred_input_timing(
+                               output,
+                               mode->clock / 10,
+                               mode->hdisplay,
+                               mode->vdisplay);
+
+               if (success) {
+                       struct intel_sdvo_dtd input_dtd;
+
+                       intel_sdvo_get_preferred_input_timing(output,
+                                                            &input_dtd);
+                       intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
+                       dev_priv->sdvo_flags = input_dtd.part2.sdvo_flags;
 
                        drm_mode_set_crtcinfo(adjusted_mode, 0);
 
@@ -990,6 +1053,12 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
                } else {
                        return false;
                }
+
+       } else {
+               /* Make the CRTC code factor in the SDVO pixel multiplier.  The
+                * SDVO device will be told of the multiplier during mode_set.
+                */
+               adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode);
        }
        return true;
 }
@@ -1033,15 +1102,16 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
 
        /* We have tried to get input timing in mode_fixup, and filled into
           adjusted_mode */
-       if (sdvo_priv->is_tv)
+       if (sdvo_priv->is_tv || sdvo_priv->is_lvds) {
                intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
-       else
+               input_dtd.part2.sdvo_flags = sdvo_priv->sdvo_flags;
+       } else
                intel_sdvo_get_dtd_from_mode(&input_dtd, mode);
 
        /* If it's a TV, we already set the output timing in mode_fixup.
         * Otherwise, the output timing is equal to the input timing.
         */
-       if (!sdvo_priv->is_tv) {
+       if (!sdvo_priv->is_tv && !sdvo_priv->is_lvds) {
                /* Set the output timing to the screen */
                intel_sdvo_set_target_output(output,
                                             sdvo_priv->controlled_output);
@@ -1116,6 +1186,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
                sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
        }
 
+       if (sdvo_priv->sdvo_flags & SDVO_NEED_TO_STALL)
+               sdvox |= SDVO_STALL_SELECT;
        intel_sdvo_write_sdvox(output, sdvox);
 }
 
@@ -1276,6 +1348,17 @@ static int intel_sdvo_mode_valid(struct drm_connector *connector,
        if (sdvo_priv->pixel_clock_max < mode->clock)
                return MODE_CLOCK_HIGH;
 
+       if (sdvo_priv->is_lvds == true) {
+               if (sdvo_priv->sdvo_lvds_fixed_mode == NULL)
+                       return MODE_PANEL;
+
+               if (mode->hdisplay > sdvo_priv->sdvo_lvds_fixed_mode->hdisplay)
+                       return MODE_PANEL;
+
+               if (mode->vdisplay > sdvo_priv->sdvo_lvds_fixed_mode->vdisplay)
+                       return MODE_PANEL;
+       }
+
        return MODE_OK;
 }
 
@@ -1362,42 +1445,96 @@ void intel_sdvo_set_hotplug(struct drm_connector *connector, int on)
        intel_sdvo_read_response(intel_output, &response, 2);
 }
 
-static void
-intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
+static bool
+intel_sdvo_multifunc_encoder(struct intel_output *intel_output)
+{
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+       int caps = 0;
+
+       if (sdvo_priv->caps.output_flags &
+               (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
+               caps++;
+       if (sdvo_priv->caps.output_flags &
+               (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1))
+               caps++;
+       if (sdvo_priv->caps.output_flags &
+               (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID1))
+               caps++;
+       if (sdvo_priv->caps.output_flags &
+               (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_CVBS1))
+               caps++;
+       if (sdvo_priv->caps.output_flags &
+               (SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_YPRPB1))
+               caps++;
+
+       if (sdvo_priv->caps.output_flags &
+               (SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1))
+               caps++;
+
+       if (sdvo_priv->caps.output_flags &
+               (SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1))
+               caps++;
+
+       return (caps > 1);
+}
+
+enum drm_connector_status
+intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
 {
        struct intel_output *intel_output = to_intel_output(connector);
        struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+       enum drm_connector_status status = connector_status_connected;
        struct edid *edid = NULL;
 
-       intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus);
        edid = drm_get_edid(&intel_output->base,
-                           &intel_output->ddc_bus->adapter);
+                           intel_output->ddc_bus);
        if (edid != NULL) {
-               sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid);
+               /* Don't report the output as connected if it's a DVI-I
+                * connector with a non-digital EDID coming out.
+                */
+               if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) {
+                       if (edid->input & DRM_EDID_INPUT_DIGITAL)
+                               sdvo_priv->is_hdmi =
+                                       drm_detect_hdmi_monitor(edid);
+                       else
+                               status = connector_status_disconnected;
+               }
+
                kfree(edid);
                intel_output->base.display_info.raw_edid = NULL;
-       }
+
+       } else if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
+               status = connector_status_disconnected;
+
+       return status;
 }
 
 static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector)
 {
-       u8 response[2];
+       uint16_t response;
        u8 status;
        struct intel_output *intel_output = to_intel_output(connector);
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
 
        intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
        status = intel_sdvo_read_response(intel_output, &response, 2);
 
-       DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]);
+       DRM_DEBUG("SDVO response %d %d\n", response & 0xff, response >> 8);
 
        if (status != SDVO_CMD_STATUS_SUCCESS)
                return connector_status_unknown;
 
-       if ((response[0] != 0) || (response[1] != 0)) {
-               intel_sdvo_hdmi_sink_detect(connector);
-               return connector_status_connected;
-       } else
+       if (response == 0)
                return connector_status_disconnected;
+
+       if (intel_sdvo_multifunc_encoder(intel_output) &&
+               sdvo_priv->attached_output != response) {
+               if (sdvo_priv->controlled_output != response &&
+                       intel_sdvo_output_setup(intel_output, response) != true)
+                       return connector_status_unknown;
+               sdvo_priv->attached_output = response;
+       }
+       return intel_sdvo_hdmi_sink_detect(connector, response);
 }
 
 static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
@@ -1549,23 +1686,21 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
 static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
 {
        struct intel_output *intel_output = to_intel_output(connector);
-       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
        struct drm_i915_private *dev_priv = connector->dev->dev_private;
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+       struct drm_display_mode *newmode;
 
        /*
         * Attempt to get the mode list from DDC.
         * Assume that the preferred modes are
         * arranged in priority order.
         */
-       /* set the bus switch and get the modes */
-       intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus);
        intel_ddc_get_modes(intel_output);
        if (list_empty(&connector->probed_modes) == false)
-               return;
+               goto end;
 
        /* Fetch modes from VBT */
        if (dev_priv->sdvo_lvds_vbt_mode != NULL) {
-               struct drm_display_mode *newmode;
                newmode = drm_mode_duplicate(connector->dev,
                                             dev_priv->sdvo_lvds_vbt_mode);
                if (newmode != NULL) {
@@ -1575,6 +1710,16 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
                        drm_mode_probed_add(connector, newmode);
                }
        }
+
+end:
+       list_for_each_entry(newmode, &connector->probed_modes, head) {
+               if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
+                       sdvo_priv->sdvo_lvds_fixed_mode =
+                               drm_mode_duplicate(connector->dev, newmode);
+                       break;
+               }
+       }
+
 }
 
 static int intel_sdvo_get_modes(struct drm_connector *connector)
@@ -1597,14 +1742,20 @@ static int intel_sdvo_get_modes(struct drm_connector *connector)
 static void intel_sdvo_destroy(struct drm_connector *connector)
 {
        struct intel_output *intel_output = to_intel_output(connector);
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
 
        if (intel_output->i2c_bus)
                intel_i2c_destroy(intel_output->i2c_bus);
        if (intel_output->ddc_bus)
                intel_i2c_destroy(intel_output->ddc_bus);
 
+       if (sdvo_priv->sdvo_lvds_fixed_mode != NULL)
+               drm_mode_destroy(connector->dev,
+                                sdvo_priv->sdvo_lvds_fixed_mode);
+
        drm_sysfs_connector_remove(connector);
        drm_connector_cleanup(connector);
+
        kfree(intel_output);
 }
 
@@ -1709,7 +1860,7 @@ intel_sdvo_chan_to_intel_output(struct intel_i2c_chan *chan)
 
        list_for_each_entry(connector,
                        &dev->mode_config.connector_list, head) {
-               if (to_intel_output(connector)->ddc_bus == chan) {
+               if (to_intel_output(connector)->ddc_bus == &chan->adapter) {
                        intel_output = to_intel_output(connector);
                        break;
                }
@@ -1723,7 +1874,7 @@ static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap,
        struct intel_output *intel_output;
        struct intel_sdvo_priv *sdvo_priv;
        struct i2c_algo_bit_data *algo_data;
-       struct i2c_algorithm *algo;
+       const struct i2c_algorithm *algo;
 
        algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data;
        intel_output =
@@ -1733,7 +1884,7 @@ static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap,
                return -EINVAL;
 
        sdvo_priv = intel_output->dev_priv;
-       algo = (struct i2c_algorithm *)intel_output->i2c_bus->adapter.algo;
+       algo = intel_output->i2c_bus->algo;
 
        intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus);
        return algo->master_xfer(i2c_adap, msgs, num);
@@ -1780,18 +1931,112 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, int output_device)
                return 0x72;
 }
 
+static bool
+intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)
+{
+       struct drm_connector *connector = &intel_output->base;
+       struct drm_encoder *encoder = &intel_output->enc;
+       struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
+       bool ret = true, registered = false;
+
+       sdvo_priv->is_tv = false;
+       intel_output->needs_tv_clock = false;
+       sdvo_priv->is_lvds = false;
+
+       if (device_is_registered(&connector->kdev)) {
+               drm_sysfs_connector_remove(connector);
+               registered = true;
+       }
+
+       if (flags &
+           (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) {
+               if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
+                       sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS0;
+               else
+                       sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS1;
+
+               encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
+               connector->connector_type = DRM_MODE_CONNECTOR_DVID;
+
+               if (intel_sdvo_get_supp_encode(intel_output,
+                                              &sdvo_priv->encode) &&
+                   intel_sdvo_get_digital_encoding_mode(intel_output) &&
+                   sdvo_priv->is_hdmi) {
+                       /* enable hdmi encoding mode if supported */
+                       intel_sdvo_set_encode(intel_output, SDVO_ENCODE_HDMI);
+                       intel_sdvo_set_colorimetry(intel_output,
+                                                  SDVO_COLORIMETRY_RGB256);
+                       connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
+                       intel_output->clone_mask =
+                                       (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+                                       (1 << INTEL_ANALOG_CLONE_BIT);
+               }
+       } else if (flags & SDVO_OUTPUT_SVID0) {
+
+               sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0;
+               encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
+               connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
+               sdvo_priv->is_tv = true;
+               intel_output->needs_tv_clock = true;
+               intel_output->clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
+       } else if (flags & SDVO_OUTPUT_RGB0) {
+
+               sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0;
+               encoder->encoder_type = DRM_MODE_ENCODER_DAC;
+               connector->connector_type = DRM_MODE_CONNECTOR_VGA;
+               intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
+                                       (1 << INTEL_ANALOG_CLONE_BIT);
+       } else if (flags & SDVO_OUTPUT_RGB1) {
+
+               sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1;
+               encoder->encoder_type = DRM_MODE_ENCODER_DAC;
+               connector->connector_type = DRM_MODE_CONNECTOR_VGA;
+       } else if (flags & SDVO_OUTPUT_LVDS0) {
+
+               sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0;
+               encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
+               connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
+               sdvo_priv->is_lvds = true;
+               intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
+                                       (1 << INTEL_SDVO_LVDS_CLONE_BIT);
+       } else if (flags & SDVO_OUTPUT_LVDS1) {
+
+               sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1;
+               encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
+               connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
+               sdvo_priv->is_lvds = true;
+               intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) |
+                                       (1 << INTEL_SDVO_LVDS_CLONE_BIT);
+       } else {
+
+               unsigned char bytes[2];
+
+               sdvo_priv->controlled_output = 0;
+               memcpy(bytes, &sdvo_priv->caps.output_flags, 2);
+               DRM_DEBUG_KMS(I915_SDVO,
+                               "%s: Unknown SDVO output type (0x%02x%02x)\n",
+                                 SDVO_NAME(sdvo_priv),
+                                 bytes[0], bytes[1]);
+               ret = false;
+       }
+       intel_output->crtc_mask = (1 << 0) | (1 << 1);
+
+       if (ret && registered)
+               ret = drm_sysfs_connector_add(connector) == 0 ? true : false;
+
+
+       return ret;
+
+}
+
 bool intel_sdvo_init(struct drm_device *dev, int output_device)
 {
        struct drm_connector *connector;
        struct intel_output *intel_output;
        struct intel_sdvo_priv *sdvo_priv;
-       struct intel_i2c_chan *i2cbus = NULL;
-       struct intel_i2c_chan *ddcbus = NULL;
-       int connector_type;
+
        u8 ch[0x40];
        int i;
-       int encoder_type, output_id;
-       u8 slave_addr;
 
        intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL);
        if (!intel_output) {
@@ -1799,29 +2044,24 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
        }
 
        sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1);
+       sdvo_priv->output_device = output_device;
+
+       intel_output->dev_priv = sdvo_priv;
        intel_output->type = INTEL_OUTPUT_SDVO;
 
        /* setup the DDC bus. */
        if (output_device == SDVOB)
-               i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB");
+               intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB");
        else
-               i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC");
+               intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC");
 
-       if (!i2cbus)
+       if (!intel_output->i2c_bus)
                goto err_inteloutput;
 
-       slave_addr = intel_sdvo_get_slave_addr(dev, output_device);
-       sdvo_priv->i2c_bus = i2cbus;
+       sdvo_priv->slave_addr = intel_sdvo_get_slave_addr(dev, output_device);
 
-       if (output_device == SDVOB) {
-               output_id = 1;
-       } else {
-               output_id = 2;
-       }
-       sdvo_priv->i2c_bus->slave_addr = slave_addr >> 1;
-       sdvo_priv->output_device = output_device;
-       intel_output->i2c_bus = i2cbus;
-       intel_output->dev_priv = sdvo_priv;
+       /* Save the bit-banging i2c functionality for use by the DDC wrapper */
+       intel_sdvo_i2c_bit_algo.functionality = intel_output->i2c_bus->algo->functionality;
 
        /* Read the regs to test if we can talk to the device */
        for (i = 0; i < 0x40; i++) {
@@ -1835,101 +2075,39 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
 
        /* setup the DDC bus. */
        if (output_device == SDVOB)
-               ddcbus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
+               intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS");
        else
-               ddcbus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
+               intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS");
 
-       if (ddcbus == NULL)
+       if (intel_output->ddc_bus == NULL)
                goto err_i2c;
 
-       intel_sdvo_i2c_bit_algo.functionality =
-               intel_output->i2c_bus->adapter.algo->functionality;
-       ddcbus->adapter.algo = &intel_sdvo_i2c_bit_algo;
-       intel_output->ddc_bus = ddcbus;
+       /* Wrap with our custom algo which switches to DDC mode */
+       intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo;
 
        /* In defaut case sdvo lvds is false */
-       sdvo_priv->is_lvds = false;
        intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps);
 
-       if (sdvo_priv->caps.output_flags &
-           (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) {
-               if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
-                       sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS0;
-               else
-                       sdvo_priv->controlled_output = SDVO_OUTPUT_TMDS1;
-
-               encoder_type = DRM_MODE_ENCODER_TMDS;
-               connector_type = DRM_MODE_CONNECTOR_DVID;
-
-               if (intel_sdvo_get_supp_encode(intel_output,
-                                              &sdvo_priv->encode) &&
-                   intel_sdvo_get_digital_encoding_mode(intel_output) &&
-                   sdvo_priv->is_hdmi) {
-                       /* enable hdmi encoding mode if supported */
-                       intel_sdvo_set_encode(intel_output, SDVO_ENCODE_HDMI);
-                       intel_sdvo_set_colorimetry(intel_output,
-                                                  SDVO_COLORIMETRY_RGB256);
-                       connector_type = DRM_MODE_CONNECTOR_HDMIA;
-               }
-       }
-       else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_SVID0)
-       {
-               sdvo_priv->controlled_output = SDVO_OUTPUT_SVID0;
-               encoder_type = DRM_MODE_ENCODER_TVDAC;
-               connector_type = DRM_MODE_CONNECTOR_SVIDEO;
-               sdvo_priv->is_tv = true;
-               intel_output->needs_tv_clock = true;
-       }
-       else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0)
-       {
-               sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0;
-               encoder_type = DRM_MODE_ENCODER_DAC;
-               connector_type = DRM_MODE_CONNECTOR_VGA;
-       }
-       else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1)
-       {
-               sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1;
-               encoder_type = DRM_MODE_ENCODER_DAC;
-               connector_type = DRM_MODE_CONNECTOR_VGA;
-       }
-       else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_LVDS0)
-       {
-               sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS0;
-               encoder_type = DRM_MODE_ENCODER_LVDS;
-               connector_type = DRM_MODE_CONNECTOR_LVDS;
-               sdvo_priv->is_lvds = true;
-       }
-       else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_LVDS1)
-       {
-               sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1;
-               encoder_type = DRM_MODE_ENCODER_LVDS;
-               connector_type = DRM_MODE_CONNECTOR_LVDS;
-               sdvo_priv->is_lvds = true;
-       }
-       else
-       {
-               unsigned char bytes[2];
-
-               sdvo_priv->controlled_output = 0;
-               memcpy (bytes, &sdvo_priv->caps.output_flags, 2);
-               DRM_DEBUG_KMS(I915_SDVO,
-                               "%s: Unknown SDVO output type (0x%02x%02x)\n",
-                                 SDVO_NAME(sdvo_priv),
-                                 bytes[0], bytes[1]);
-               encoder_type = DRM_MODE_ENCODER_NONE;
-               connector_type = DRM_MODE_CONNECTOR_Unknown;
+       if (intel_sdvo_output_setup(intel_output,
+                                   sdvo_priv->caps.output_flags) != true) {
+               DRM_DEBUG("SDVO output failed to setup on SDVO%c\n",
+                         output_device == SDVOB ? 'B' : 'C');
                goto err_i2c;
        }
 
+
        connector = &intel_output->base;
        drm_connector_init(dev, connector, &intel_sdvo_connector_funcs,
-                          connector_type);
+                          connector->connector_type);
+
        drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs);
        connector->interlace_allowed = 0;
        connector->doublescan_allowed = 0;
        connector->display_info.subpixel_order = SubPixelHorizontalRGB;
 
-       drm_encoder_init(dev, &intel_output->enc, &intel_sdvo_enc_funcs, encoder_type);
+       drm_encoder_init(dev, &intel_output->enc,
+                       &intel_sdvo_enc_funcs, intel_output->enc.encoder_type);
+
        drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs);
 
        drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
@@ -1965,9 +2143,10 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
        return true;
 
 err_i2c:
-       if (ddcbus != NULL)
+       if (intel_output->ddc_bus != NULL)
                intel_i2c_destroy(intel_output->ddc_bus);
-       intel_i2c_destroy(intel_output->i2c_bus);
+       if (intel_output->i2c_bus != NULL)
+               intel_i2c_destroy(intel_output->i2c_bus);
 err_inteloutput:
        kfree(intel_output);
 
index 193938b7d7f9ea3cce94188fb733a15990282040..ba5cdf8ae40bea4ab9d5b416fd5c3e10ac43facb 100644 (file)
@@ -715,6 +715,7 @@ struct intel_sdvo_enhancements_arg {
   #define SDVO_HBUF_TX_ONCE    (2 << 6)
   #define SDVO_HBUF_TX_VSYNC   (3 << 6)
 #define SDVO_CMD_GET_AUDIO_TX_INFO     0x9c
+#define SDVO_NEED_TO_STALL  (1 << 7)
 
 struct intel_sdvo_encode{
     u8 dvi_rev;
index ea68992e441607b9356e7d93c4463782bfeae200..5b1c9e9fdba04b89044b5131b00477c66b230c41 100644 (file)
@@ -1383,34 +1383,31 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output)
        /*
         * Detect TV by polling)
         */
-       if (intel_output->load_detect_temp) {
-               /* TV not currently running, prod it with destructive detect */
-               save_tv_dac = tv_dac;
-               tv_ctl = I915_READ(TV_CTL);
-               save_tv_ctl = tv_ctl;
-               tv_ctl &= ~TV_ENC_ENABLE;
-               tv_ctl &= ~TV_TEST_MODE_MASK;
-               tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
-               tv_dac &= ~TVDAC_SENSE_MASK;
-               tv_dac &= ~DAC_A_MASK;
-               tv_dac &= ~DAC_B_MASK;
-               tv_dac &= ~DAC_C_MASK;
-               tv_dac |= (TVDAC_STATE_CHG_EN |
-                          TVDAC_A_SENSE_CTL |
-                          TVDAC_B_SENSE_CTL |
-                          TVDAC_C_SENSE_CTL |
-                          DAC_CTL_OVERRIDE |
-                          DAC_A_0_7_V |
-                          DAC_B_0_7_V |
-                          DAC_C_0_7_V);
-               I915_WRITE(TV_CTL, tv_ctl);
-               I915_WRITE(TV_DAC, tv_dac);
-               intel_wait_for_vblank(dev);
-               tv_dac = I915_READ(TV_DAC);
-               I915_WRITE(TV_DAC, save_tv_dac);
-               I915_WRITE(TV_CTL, save_tv_ctl);
-               intel_wait_for_vblank(dev);
-       }
+       save_tv_dac = tv_dac;
+       tv_ctl = I915_READ(TV_CTL);
+       save_tv_ctl = tv_ctl;
+       tv_ctl &= ~TV_ENC_ENABLE;
+       tv_ctl &= ~TV_TEST_MODE_MASK;
+       tv_ctl |= TV_TEST_MODE_MONITOR_DETECT;
+       tv_dac &= ~TVDAC_SENSE_MASK;
+       tv_dac &= ~DAC_A_MASK;
+       tv_dac &= ~DAC_B_MASK;
+       tv_dac &= ~DAC_C_MASK;
+       tv_dac |= (TVDAC_STATE_CHG_EN |
+                  TVDAC_A_SENSE_CTL |
+                  TVDAC_B_SENSE_CTL |
+                  TVDAC_C_SENSE_CTL |
+                  DAC_CTL_OVERRIDE |
+                  DAC_A_0_7_V |
+                  DAC_B_0_7_V |
+                  DAC_C_0_7_V);
+       I915_WRITE(TV_CTL, tv_ctl);
+       I915_WRITE(TV_DAC, tv_dac);
+       intel_wait_for_vblank(dev);
+       tv_dac = I915_READ(TV_DAC);
+       I915_WRITE(TV_DAC, save_tv_dac);
+       I915_WRITE(TV_CTL, save_tv_ctl);
+       intel_wait_for_vblank(dev);
        /*
         *  A B C
         *  0 1 1 Composite
@@ -1493,6 +1490,27 @@ static struct input_res {
        {"1920x1080", 1920, 1080},
 };
 
+/*
+ * Chose preferred mode  according to line number of TV format
+ */
+static void
+intel_tv_chose_preferred_modes(struct drm_connector *connector,
+                              struct drm_display_mode *mode_ptr)
+{
+       struct intel_output *intel_output = to_intel_output(connector);
+       const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
+
+       if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480)
+               mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
+       else if (tv_mode->nbr_end > 480) {
+               if (tv_mode->progressive == true && tv_mode->nbr_end < 720) {
+                       if (mode_ptr->vdisplay == 720)
+                               mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
+               } else if (mode_ptr->vdisplay == 1080)
+                               mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
+       }
+}
+
 /**
  * Stub get_modes function.
  *
@@ -1547,6 +1565,7 @@ intel_tv_get_modes(struct drm_connector *connector)
                mode_ptr->clock = (int) tmp;
 
                mode_ptr->type = DRM_MODE_TYPE_DRIVER;
+               intel_tv_chose_preferred_modes(connector, mode_ptr);
                drm_mode_probed_add(connector, mode_ptr);
                count++;
        }
@@ -1699,6 +1718,7 @@ intel_tv_init(struct drm_device *dev)
        if (!intel_output) {
                return;
        }
+
        connector = &intel_output->base;
 
        drm_connector_init(dev, connector, &intel_tv_connector_funcs,
@@ -1710,6 +1730,8 @@ intel_tv_init(struct drm_device *dev)
        drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
        tv_priv = (struct intel_tv_priv *)(intel_output + 1);
        intel_output->type = INTEL_OUTPUT_TVOUT;
+       intel_output->crtc_mask = (1 << 0) | (1 << 1);
+       intel_output->clone_mask = (1 << INTEL_TV_CLONE_BIT);
        intel_output->enc.possible_crtcs = ((1 << 0) | (1 << 1));
        intel_output->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
        intel_output->dev_priv = tv_priv;
index 5fae1e074b4b7fd8565f9c4e2f75202305f4ddb6..013d38059943e13b0b930a1638e7452d705ce9ca 100644 (file)
@@ -13,7 +13,8 @@ radeon-$(CONFIG_DRM_RADEON_KMS) += radeon_device.o radeon_kms.o \
        radeon_encoders.o radeon_display.o radeon_cursor.o radeon_i2c.o \
        radeon_clocks.o radeon_fb.o radeon_gem.o radeon_ring.o radeon_irq_kms.o \
        radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
-       rs400.o rs600.o rs690.o rv515.o r520.o r600.o rs780.o rv770.o
+       rs400.o rs600.o rs690.o rv515.o r520.o r600.o rs780.o rv770.o \
+       radeon_test.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 
index c0080cc9bf8d9a816390cfb0ebd5451e2d66cdbf..74d034f77c6bacc6d9ac4047c13243090280e666 100644 (file)
 #include "atom.h"
 #include "atom-bits.h"
 
+static void atombios_overscan_setup(struct drm_crtc *crtc,
+                                   struct drm_display_mode *mode,
+                                   struct drm_display_mode *adjusted_mode)
+{
+       struct drm_device *dev = crtc->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+       SET_CRTC_OVERSCAN_PS_ALLOCATION args;
+       int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
+       int a1, a2;
+
+       memset(&args, 0, sizeof(args));
+
+       args.usOverscanRight = 0;
+       args.usOverscanLeft = 0;
+       args.usOverscanBottom = 0;
+       args.usOverscanTop = 0;
+       args.ucCRTC = radeon_crtc->crtc_id;
+
+       switch (radeon_crtc->rmx_type) {
+       case RMX_CENTER:
+               args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
+               args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
+               args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
+               args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
+               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+               break;
+       case RMX_ASPECT:
+               a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay;
+               a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay;
+
+               if (a1 > a2) {
+                       args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
+                       args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
+               } else if (a2 > a1) {
+                       args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
+                       args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
+               }
+               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+               break;
+       case RMX_FULL:
+       default:
+               args.usOverscanRight = 0;
+               args.usOverscanLeft = 0;
+               args.usOverscanBottom = 0;
+               args.usOverscanTop = 0;
+               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+               break;
+       }
+}
+
+static void atombios_scaler_setup(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+       ENABLE_SCALER_PS_ALLOCATION args;
+       int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
+       /* fixme - fill in enc_priv for atom dac */
+       enum radeon_tv_std tv_std = TV_STD_NTSC;
+
+       if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)
+               return;
+
+       memset(&args, 0, sizeof(args));
+
+       args.ucScaler = radeon_crtc->crtc_id;
+
+       if (radeon_crtc->devices & (ATOM_DEVICE_TV_SUPPORT)) {
+               switch (tv_std) {
+               case TV_STD_NTSC:
+               default:
+                       args.ucTVStandard = ATOM_TV_NTSC;
+                       break;
+               case TV_STD_PAL:
+                       args.ucTVStandard = ATOM_TV_PAL;
+                       break;
+               case TV_STD_PAL_M:
+                       args.ucTVStandard = ATOM_TV_PALM;
+                       break;
+               case TV_STD_PAL_60:
+                       args.ucTVStandard = ATOM_TV_PAL60;
+                       break;
+               case TV_STD_NTSC_J:
+                       args.ucTVStandard = ATOM_TV_NTSCJ;
+                       break;
+               case TV_STD_SCART_PAL:
+                       args.ucTVStandard = ATOM_TV_PAL; /* ??? */
+                       break;
+               case TV_STD_SECAM:
+                       args.ucTVStandard = ATOM_TV_SECAM;
+                       break;
+               case TV_STD_PAL_CN:
+                       args.ucTVStandard = ATOM_TV_PALCN;
+                       break;
+               }
+               args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
+       } else if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT)) {
+               args.ucTVStandard = ATOM_TV_CV;
+               args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
+       } else {
+               switch (radeon_crtc->rmx_type) {
+               case RMX_FULL:
+                       args.ucEnable = ATOM_SCALER_EXPANSION;
+                       break;
+               case RMX_CENTER:
+                       args.ucEnable = ATOM_SCALER_CENTER;
+                       break;
+               case RMX_ASPECT:
+                       args.ucEnable = ATOM_SCALER_EXPANSION;
+                       break;
+               default:
+                       if (ASIC_IS_AVIVO(rdev))
+                               args.ucEnable = ATOM_SCALER_DISABLE;
+                       else
+                               args.ucEnable = ATOM_SCALER_CENTER;
+                       break;
+               }
+       }
+       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+       if (radeon_crtc->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)
+           && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) {
+               atom_rv515_force_tv_scaler(rdev);
+       }
+}
+
 static void atombios_lock_crtc(struct drm_crtc *crtc, int lock)
 {
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -203,6 +329,12 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
        if (ASIC_IS_AVIVO(rdev)) {
                uint32_t ss_cntl;
 
+               if ((rdev->family == CHIP_RS600) ||
+                   (rdev->family == CHIP_RS690) ||
+                   (rdev->family == CHIP_RS740))
+                       pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
+                                     RADEON_PLL_PREFER_CLOSEST_LOWER);
+
                if (ASIC_IS_DCE32(rdev) && mode->clock > 200000)        /* range limits??? */
                        pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
                else
@@ -321,7 +453,7 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
        struct drm_gem_object *obj;
        struct drm_radeon_gem_object *obj_priv;
        uint64_t fb_location;
-       uint32_t fb_format, fb_pitch_pixels;
+       uint32_t fb_format, fb_pitch_pixels, tiling_flags;
 
        if (!crtc->fb)
                return -EINVAL;
@@ -358,7 +490,14 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
                return -EINVAL;
        }
 
-       /* TODO tiling */
+       radeon_object_get_tiling_flags(obj->driver_private,
+                                      &tiling_flags, NULL);
+       if (tiling_flags & RADEON_TILING_MACRO)
+               fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
+
+       if (tiling_flags & RADEON_TILING_MICRO)
+               fb_format |= AVIVO_D1GRPH_TILED;
+
        if (radeon_crtc->crtc_id == 0)
                WREG32(AVIVO_D1VGA_CONTROL, 0);
        else
@@ -509,6 +648,9 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc,
                radeon_crtc_set_base(crtc, x, y, old_fb);
                radeon_legacy_atom_set_surface(crtc);
        }
+       atombios_overscan_setup(crtc, mode, adjusted_mode);
+       atombios_scaler_setup(crtc);
+       radeon_bandwidth_update(rdev);
        return 0;
 }
 
@@ -516,6 +658,8 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
                                     struct drm_display_mode *mode,
                                     struct drm_display_mode *adjusted_mode)
 {
+       if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
+               return false;
        return true;
 }
 
@@ -548,148 +692,3 @@ void radeon_atombios_init_crtc(struct drm_device *dev,
                    AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
        drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
 }
-
-void radeon_init_disp_bw_avivo(struct drm_device *dev,
-                              struct drm_display_mode *mode1,
-                              uint32_t pixel_bytes1,
-                              struct drm_display_mode *mode2,
-                              uint32_t pixel_bytes2)
-{
-       struct radeon_device *rdev = dev->dev_private;
-       fixed20_12 min_mem_eff;
-       fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff;
-       fixed20_12 sclk_ff, mclk_ff;
-       uint32_t dc_lb_memory_split, temp;
-
-       min_mem_eff.full = rfixed_const_8(0);
-       if (rdev->disp_priority == 2) {
-               uint32_t mc_init_misc_lat_timer = 0;
-               if (rdev->family == CHIP_RV515)
-                       mc_init_misc_lat_timer =
-                           RREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER);
-               else if (rdev->family == CHIP_RS690)
-                       mc_init_misc_lat_timer =
-                           RREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER);
-
-               mc_init_misc_lat_timer &=
-                   ~(R300_MC_DISP1R_INIT_LAT_MASK <<
-                     R300_MC_DISP1R_INIT_LAT_SHIFT);
-               mc_init_misc_lat_timer &=
-                   ~(R300_MC_DISP0R_INIT_LAT_MASK <<
-                     R300_MC_DISP0R_INIT_LAT_SHIFT);
-
-               if (mode2)
-                       mc_init_misc_lat_timer |=
-                           (1 << R300_MC_DISP1R_INIT_LAT_SHIFT);
-               if (mode1)
-                       mc_init_misc_lat_timer |=
-                           (1 << R300_MC_DISP0R_INIT_LAT_SHIFT);
-
-               if (rdev->family == CHIP_RV515)
-                       WREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER,
-                                 mc_init_misc_lat_timer);
-               else if (rdev->family == CHIP_RS690)
-                       WREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER,
-                                 mc_init_misc_lat_timer);
-       }
-
-       /*
-        * determine is there is enough bw for current mode
-        */
-       temp_ff.full = rfixed_const(100);
-       mclk_ff.full = rfixed_const(rdev->clock.default_mclk);
-       mclk_ff.full = rfixed_div(mclk_ff, temp_ff);
-       sclk_ff.full = rfixed_const(rdev->clock.default_sclk);
-       sclk_ff.full = rfixed_div(sclk_ff, temp_ff);
-
-       temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1);
-       temp_ff.full = rfixed_const(temp);
-       mem_bw.full = rfixed_mul(mclk_ff, temp_ff);
-       mem_bw.full = rfixed_mul(mem_bw, min_mem_eff);
-
-       pix_clk.full = 0;
-       pix_clk2.full = 0;
-       peak_disp_bw.full = 0;
-       if (mode1) {
-               temp_ff.full = rfixed_const(1000);
-               pix_clk.full = rfixed_const(mode1->clock);      /* convert to fixed point */
-               pix_clk.full = rfixed_div(pix_clk, temp_ff);
-               temp_ff.full = rfixed_const(pixel_bytes1);
-               peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff);
-       }
-       if (mode2) {
-               temp_ff.full = rfixed_const(1000);
-               pix_clk2.full = rfixed_const(mode2->clock);     /* convert to fixed point */
-               pix_clk2.full = rfixed_div(pix_clk2, temp_ff);
-               temp_ff.full = rfixed_const(pixel_bytes2);
-               peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff);
-       }
-
-       if (peak_disp_bw.full >= mem_bw.full) {
-               DRM_ERROR
-                   ("You may not have enough display bandwidth for current mode\n"
-                    "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
-               printk("peak disp bw %d, mem_bw %d\n",
-                      rfixed_trunc(peak_disp_bw), rfixed_trunc(mem_bw));
-       }
-
-       /*
-        * Line Buffer Setup
-        * There is a single line buffer shared by both display controllers.
-        * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display
-        * controllers.  The paritioning can either be done manually or via one of four
-        * preset allocations specified in bits 1:0:
-        * 0 - line buffer is divided in half and shared between each display controller
-        * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
-        * 2 - D1 gets the whole buffer
-        * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
-        * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode.
-        * In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits
-        * 14:4; D2 allocation follows D1.
-        */
-
-       /* is auto or manual better ? */
-       dc_lb_memory_split =
-           RREG32(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK;
-       dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
-#if 1
-       /* auto */
-       if (mode1 && mode2) {
-               if (mode1->hdisplay > mode2->hdisplay) {
-                       if (mode1->hdisplay > 2560)
-                               dc_lb_memory_split |=
-                                   AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
-                       else
-                               dc_lb_memory_split |=
-                                   AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
-               } else if (mode2->hdisplay > mode1->hdisplay) {
-                       if (mode2->hdisplay > 2560)
-                               dc_lb_memory_split |=
-                                   AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
-                       else
-                               dc_lb_memory_split |=
-                                   AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
-               } else
-                       dc_lb_memory_split |=
-                           AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
-       } else if (mode1) {
-               dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY;
-       } else if (mode2) {
-               dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
-       }
-#else
-       /* manual */
-       dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
-       dc_lb_memory_split &=
-           ~(AVIVO_DC_LB_DISP1_END_ADR_MASK <<
-             AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
-       if (mode1) {
-               dc_lb_memory_split |=
-                   ((((mode1->hdisplay / 2) + 64) & AVIVO_DC_LB_DISP1_END_ADR_MASK)
-                    << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
-       } else if (mode2) {
-               dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
-       }
-#endif
-       WREG32(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split);
-}
index c550932a108fb65f8cb5be0abf9dc9e98421cd38..68e728e8be4d3cda06ca678a5c363fd95a94eb84 100644 (file)
@@ -110,7 +110,7 @@ int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
        if (i < 0 || i > rdev->gart.num_gpu_pages) {
                return -EINVAL;
        }
-       rdev->gart.table.ram.ptr[i] = cpu_to_le32((uint32_t)addr);
+       rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr));
        return 0;
 }
 
@@ -173,8 +173,12 @@ void r100_mc_setup(struct radeon_device *rdev)
                DRM_ERROR("Failed to register debugfs file for R100 MC !\n");
        }
        /* Write VRAM size in case we are limiting it */
-       WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
-       tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
+       WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
+       /* Novell bug 204882 for RN50/M6/M7 with 8/16/32MB VRAM,
+        * if the aperture is 64MB but we have 32MB VRAM
+        * we report only 32MB VRAM but we have to set MC_FB_LOCATION
+        * to 64MB, otherwise the gpu accidentially dies */
+       tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
        tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16);
        tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16);
        WREG32(RADEON_MC_FB_LOCATION, tmp);
@@ -215,7 +219,6 @@ int r100_mc_init(struct radeon_device *rdev)
        r100_pci_gart_disable(rdev);
 
        /* Setup GPU memory space */
-       rdev->mc.vram_location = 0xFFFFFFFFUL;
        rdev->mc.gtt_location = 0xFFFFFFFFUL;
        if (rdev->flags & RADEON_IS_AGP) {
                r = radeon_agp_init(rdev);
@@ -250,6 +253,72 @@ void r100_mc_fini(struct radeon_device *rdev)
 }
 
 
+/*
+ * Interrupts
+ */
+int r100_irq_set(struct radeon_device *rdev)
+{
+       uint32_t tmp = 0;
+
+       if (rdev->irq.sw_int) {
+               tmp |= RADEON_SW_INT_ENABLE;
+       }
+       if (rdev->irq.crtc_vblank_int[0]) {
+               tmp |= RADEON_CRTC_VBLANK_MASK;
+       }
+       if (rdev->irq.crtc_vblank_int[1]) {
+               tmp |= RADEON_CRTC2_VBLANK_MASK;
+       }
+       WREG32(RADEON_GEN_INT_CNTL, tmp);
+       return 0;
+}
+
+static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
+{
+       uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
+       uint32_t irq_mask = RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT |
+               RADEON_CRTC2_VBLANK_STAT;
+
+       if (irqs) {
+               WREG32(RADEON_GEN_INT_STATUS, irqs);
+       }
+       return irqs & irq_mask;
+}
+
+int r100_irq_process(struct radeon_device *rdev)
+{
+       uint32_t status;
+
+       status = r100_irq_ack(rdev);
+       if (!status) {
+               return IRQ_NONE;
+       }
+       while (status) {
+               /* SW interrupt */
+               if (status & RADEON_SW_INT_TEST) {
+                       radeon_fence_process(rdev);
+               }
+               /* Vertical blank interrupts */
+               if (status & RADEON_CRTC_VBLANK_STAT) {
+                       drm_handle_vblank(rdev->ddev, 0);
+               }
+               if (status & RADEON_CRTC2_VBLANK_STAT) {
+                       drm_handle_vblank(rdev->ddev, 1);
+               }
+               status = r100_irq_ack(rdev);
+       }
+       return IRQ_HANDLED;
+}
+
+u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc)
+{
+       if (crtc == 0)
+               return RREG32(RADEON_CRTC_CRNT_FRAME);
+       else
+               return RREG32(RADEON_CRTC2_CRNT_FRAME);
+}
+
+
 /*
  * Fence emission
  */
@@ -719,13 +788,14 @@ int r100_cs_packet_parse(struct radeon_cs_parser *p,
                         unsigned idx)
 {
        struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
-       uint32_t header = ib_chunk->kdata[idx];
+       uint32_t header;
 
        if (idx >= ib_chunk->length_dw) {
                DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
                          idx, ib_chunk->length_dw);
                return -EINVAL;
        }
+       header = ib_chunk->kdata[idx];
        pkt->idx = idx;
        pkt->type = CP_PACKET_GET_TYPE(header);
        pkt->count = CP_PACKET_GET_COUNT(header);
@@ -752,6 +822,102 @@ int r100_cs_packet_parse(struct radeon_cs_parser *p,
        return 0;
 }
 
+/**
+ * r100_cs_packet_next_vline() - parse userspace VLINE packet
+ * @parser:            parser structure holding parsing context.
+ *
+ * Userspace sends a special sequence for VLINE waits.
+ * PACKET0 - VLINE_START_END + value
+ * PACKET0 - WAIT_UNTIL +_value
+ * RELOC (P3) - crtc_id in reloc.
+ *
+ * This function parses this and relocates the VLINE START END
+ * and WAIT UNTIL packets to the correct crtc.
+ * It also detects a switched off crtc and nulls out the
+ * wait in that case.
+ */
+int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
+{
+       struct radeon_cs_chunk *ib_chunk;
+       struct drm_mode_object *obj;
+       struct drm_crtc *crtc;
+       struct radeon_crtc *radeon_crtc;
+       struct radeon_cs_packet p3reloc, waitreloc;
+       int crtc_id;
+       int r;
+       uint32_t header, h_idx, reg;
+
+       ib_chunk = &p->chunks[p->chunk_ib_idx];
+
+       /* parse the wait until */
+       r = r100_cs_packet_parse(p, &waitreloc, p->idx);
+       if (r)
+               return r;
+
+       /* check its a wait until and only 1 count */
+       if (waitreloc.reg != RADEON_WAIT_UNTIL ||
+           waitreloc.count != 0) {
+               DRM_ERROR("vline wait had illegal wait until segment\n");
+               r = -EINVAL;
+               return r;
+       }
+
+       if (ib_chunk->kdata[waitreloc.idx + 1] != RADEON_WAIT_CRTC_VLINE) {
+               DRM_ERROR("vline wait had illegal wait until\n");
+               r = -EINVAL;
+               return r;
+       }
+
+       /* jump over the NOP */
+       r = r100_cs_packet_parse(p, &p3reloc, p->idx);
+       if (r)
+               return r;
+
+       h_idx = p->idx - 2;
+       p->idx += waitreloc.count;
+       p->idx += p3reloc.count;
+
+       header = ib_chunk->kdata[h_idx];
+       crtc_id = ib_chunk->kdata[h_idx + 5];
+       reg = ib_chunk->kdata[h_idx] >> 2;
+       mutex_lock(&p->rdev->ddev->mode_config.mutex);
+       obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
+       if (!obj) {
+               DRM_ERROR("cannot find crtc %d\n", crtc_id);
+               r = -EINVAL;
+               goto out;
+       }
+       crtc = obj_to_crtc(obj);
+       radeon_crtc = to_radeon_crtc(crtc);
+       crtc_id = radeon_crtc->crtc_id;
+
+       if (!crtc->enabled) {
+               /* if the CRTC isn't enabled - we need to nop out the wait until */
+               ib_chunk->kdata[h_idx + 2] = PACKET2(0);
+               ib_chunk->kdata[h_idx + 3] = PACKET2(0);
+       } else if (crtc_id == 1) {
+               switch (reg) {
+               case AVIVO_D1MODE_VLINE_START_END:
+                       header &= R300_CP_PACKET0_REG_MASK;
+                       header |= AVIVO_D2MODE_VLINE_START_END >> 2;
+                       break;
+               case RADEON_CRTC_GUI_TRIG_VLINE:
+                       header &= R300_CP_PACKET0_REG_MASK;
+                       header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2;
+                       break;
+               default:
+                       DRM_ERROR("unknown crtc reloc\n");
+                       r = -EINVAL;
+                       goto out;
+               }
+               ib_chunk->kdata[h_idx] = header;
+               ib_chunk->kdata[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1;
+       }
+out:
+       mutex_unlock(&p->rdev->ddev->mode_config.mutex);
+       return r;
+}
+
 /**
  * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3
  * @parser:            parser structure holding parsing context.
@@ -814,6 +980,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
        unsigned idx;
        bool onereg;
        int r;
+       u32 tile_flags = 0;
 
        ib = p->ib->ptr;
        ib_chunk = &p->chunks[p->chunk_ib_idx];
@@ -825,6 +992,15 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
        }
        for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
                switch (reg) {
+               case RADEON_CRTC_GUI_TRIG_VLINE:
+                       r = r100_cs_packet_parse_vline(p);
+                       if (r) {
+                               DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+                                               idx, reg);
+                               r100_cs_dump_packet(p, pkt);
+                               return r;
+                       }
+                       break;
                /* FIXME: only allow PACKET3 blit? easier to check for out of
                 * range access */
                case RADEON_DST_PITCH_OFFSET:
@@ -838,7 +1014,20 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                        }
                        tmp = ib_chunk->kdata[idx] & 0x003fffff;
                        tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
-                       ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp;
+
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                               tile_flags |= RADEON_DST_TILE_MACRO;
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+                               if (reg == RADEON_SRC_PITCH_OFFSET) {
+                                       DRM_ERROR("Cannot src blit from microtiled surface\n");
+                                       r100_cs_dump_packet(p, pkt);
+                                       return -EINVAL;
+                               }
+                               tile_flags |= RADEON_DST_TILE_MICRO;
+                       }
+
+                       tmp |= tile_flags;
+                       ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp;
                        break;
                case RADEON_RB3D_DEPTHOFFSET:
                case RADEON_RB3D_COLOROFFSET:
@@ -869,6 +1058,40 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
                case R300_TX_OFFSET_0+52:
                case R300_TX_OFFSET_0+56:
                case R300_TX_OFFSET_0+60:
+                       /* rn50 has no 3D engine so fail on any 3d setup */
+                       if (ASIC_IS_RN50(p->rdev)) {
+                               DRM_ERROR("attempt to use RN50 3D engine failed\n");
+                               return -EINVAL;
+                       }
+                       r = r100_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+                                         idx, reg);
+                               r100_cs_dump_packet(p, pkt);
+                               return r;
+                       }
+                       ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+                       break;
+               case R300_RB3D_COLORPITCH0:
+               case RADEON_RB3D_COLORPITCH:
+                       r = r100_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+                                         idx, reg);
+                               r100_cs_dump_packet(p, pkt);
+                               return r;
+                       }
+
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                               tile_flags |= RADEON_COLOR_TILE_ENABLE;
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                               tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
+
+                       tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
+                       tmp |= tile_flags;
+                       ib[idx] = tmp;
+                       break;
+               case RADEON_RB3D_ZPASS_ADDR:
                        r = r100_cs_packet_next_reloc(p, &reloc);
                        if (r) {
                                DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
@@ -1256,29 +1479,100 @@ static void r100_vram_get_type(struct radeon_device *rdev)
        }
 }
 
-void r100_vram_info(struct radeon_device *rdev)
+static u32 r100_get_accessible_vram(struct radeon_device *rdev)
 {
-       r100_vram_get_type(rdev);
+       u32 aper_size;
+       u8 byte;
+
+       aper_size = RREG32(RADEON_CONFIG_APER_SIZE);
+
+       /* Set HDP_APER_CNTL only on cards that are known not to be broken,
+        * that is has the 2nd generation multifunction PCI interface
+        */
+       if (rdev->family == CHIP_RV280 ||
+           rdev->family >= CHIP_RV350) {
+               WREG32_P(RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL,
+                      ~RADEON_HDP_APER_CNTL);
+               DRM_INFO("Generation 2 PCI interface, using max accessible memory\n");
+               return aper_size * 2;
+       }
+
+       /* Older cards have all sorts of funny issues to deal with. First
+        * check if it's a multifunction card by reading the PCI config
+        * header type... Limit those to one aperture size
+        */
+       pci_read_config_byte(rdev->pdev, 0xe, &byte);
+       if (byte & 0x80) {
+               DRM_INFO("Generation 1 PCI interface in multifunction mode\n");
+               DRM_INFO("Limiting VRAM to one aperture\n");
+               return aper_size;
+       }
+
+       /* Single function older card. We read HDP_APER_CNTL to see how the BIOS
+        * have set it up. We don't write this as it's broken on some ASICs but
+        * we expect the BIOS to have done the right thing (might be too optimistic...)
+        */
+       if (RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL)
+               return aper_size * 2;
+       return aper_size;
+}
+
+void r100_vram_init_sizes(struct radeon_device *rdev)
+{
+       u64 config_aper_size;
+       u32 accessible;
+
+       config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE);
 
        if (rdev->flags & RADEON_IS_IGP) {
                uint32_t tom;
                /* read NB_TOM to get the amount of ram stolen for the GPU */
                tom = RREG32(RADEON_NB_TOM);
-               rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16);
-               WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
+               rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16);
+               /* for IGPs we need to keep VRAM where it was put by the BIOS */
+               rdev->mc.vram_location = (tom & 0xffff) << 16;
+               WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
+               rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
        } else {
-               rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
+               rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
                /* Some production boards of m6 will report 0
                 * if it's 8 MB
                 */
-               if (rdev->mc.vram_size == 0) {
-                       rdev->mc.vram_size = 8192 * 1024;
-                       WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
+               if (rdev->mc.real_vram_size == 0) {
+                       rdev->mc.real_vram_size = 8192 * 1024;
+                       WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
                }
+               /* let driver place VRAM */
+               rdev->mc.vram_location = 0xFFFFFFFFUL;
+                /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - 
+                 * Novell bug 204882 + along with lots of ubuntu ones */
+               if (config_aper_size > rdev->mc.real_vram_size)
+                       rdev->mc.mc_vram_size = config_aper_size;
+               else
+                       rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
        }
 
+       /* work out accessible VRAM */
+       accessible = r100_get_accessible_vram(rdev);
+
        rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
        rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+
+       if (accessible > rdev->mc.aper_size)
+               accessible = rdev->mc.aper_size;
+
+       if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
+               rdev->mc.mc_vram_size = rdev->mc.aper_size;
+
+       if (rdev->mc.real_vram_size > rdev->mc.aper_size)
+               rdev->mc.real_vram_size = rdev->mc.aper_size;
+}
+
+void r100_vram_info(struct radeon_device *rdev)
+{
+       r100_vram_get_type(rdev);
+
+       r100_vram_init_sizes(rdev);
 }
 
 
@@ -1338,26 +1632,6 @@ void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
        r100_pll_errata_after_data(rdev);
 }
 
-uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
-{
-       if (reg < 0x10000)
-               return readl(((void __iomem *)rdev->rmmio) + reg);
-       else {
-               writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
-               return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
-       }
-}
-
-void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
-{
-       if (reg < 0x10000)
-               writel(v, ((void __iomem *)rdev->rmmio) + reg);
-       else {
-               writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
-               writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
-       }
-}
-
 int r100_init(struct radeon_device *rdev)
 {
        return 0;
@@ -1533,3 +1807,530 @@ int r100_debugfs_mc_info_init(struct radeon_device *rdev)
        return 0;
 #endif
 }
+
+int r100_set_surface_reg(struct radeon_device *rdev, int reg,
+                        uint32_t tiling_flags, uint32_t pitch,
+                        uint32_t offset, uint32_t obj_size)
+{
+       int surf_index = reg * 16;
+       int flags = 0;
+
+       /* r100/r200 divide by 16 */
+       if (rdev->family < CHIP_R300)
+               flags = pitch / 16;
+       else
+               flags = pitch / 8;
+
+       if (rdev->family <= CHIP_RS200) {
+               if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
+                                == (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
+                       flags |= RADEON_SURF_TILE_COLOR_BOTH;
+               if (tiling_flags & RADEON_TILING_MACRO)
+                       flags |= RADEON_SURF_TILE_COLOR_MACRO;
+       } else if (rdev->family <= CHIP_RV280) {
+               if (tiling_flags & (RADEON_TILING_MACRO))
+                       flags |= R200_SURF_TILE_COLOR_MACRO;
+               if (tiling_flags & RADEON_TILING_MICRO)
+                       flags |= R200_SURF_TILE_COLOR_MICRO;
+       } else {
+               if (tiling_flags & RADEON_TILING_MACRO)
+                       flags |= R300_SURF_TILE_MACRO;
+               if (tiling_flags & RADEON_TILING_MICRO)
+                       flags |= R300_SURF_TILE_MICRO;
+       }
+
+       DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1);
+       WREG32(RADEON_SURFACE0_INFO + surf_index, flags);
+       WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset);
+       WREG32(RADEON_SURFACE0_UPPER_BOUND + surf_index, offset + obj_size - 1);
+       return 0;
+}
+
+void r100_clear_surface_reg(struct radeon_device *rdev, int reg)
+{
+       int surf_index = reg * 16;
+       WREG32(RADEON_SURFACE0_INFO + surf_index, 0);
+}
+
+void r100_bandwidth_update(struct radeon_device *rdev)
+{
+       fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff;
+       fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff;
+       fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff;
+       uint32_t temp, data, mem_trcd, mem_trp, mem_tras;
+       fixed20_12 memtcas_ff[8] = {
+               fixed_init(1),
+               fixed_init(2),
+               fixed_init(3),
+               fixed_init(0),
+               fixed_init_half(1),
+               fixed_init_half(2),
+               fixed_init(0),
+       };
+       fixed20_12 memtcas_rs480_ff[8] = {
+               fixed_init(0),
+               fixed_init(1),
+               fixed_init(2),
+               fixed_init(3),
+               fixed_init(0),
+               fixed_init_half(1),
+               fixed_init_half(2),
+               fixed_init_half(3),
+       };
+       fixed20_12 memtcas2_ff[8] = {
+               fixed_init(0),
+               fixed_init(1),
+               fixed_init(2),
+               fixed_init(3),
+               fixed_init(4),
+               fixed_init(5),
+               fixed_init(6),
+               fixed_init(7),
+       };
+       fixed20_12 memtrbs[8] = {
+               fixed_init(1),
+               fixed_init_half(1),
+               fixed_init(2),
+               fixed_init_half(2),
+               fixed_init(3),
+               fixed_init_half(3),
+               fixed_init(4),
+               fixed_init_half(4)
+       };
+       fixed20_12 memtrbs_r4xx[8] = {
+               fixed_init(4),
+               fixed_init(5),
+               fixed_init(6),
+               fixed_init(7),
+               fixed_init(8),
+               fixed_init(9),
+               fixed_init(10),
+               fixed_init(11)
+       };
+       fixed20_12 min_mem_eff;
+       fixed20_12 mc_latency_sclk, mc_latency_mclk, k1;
+       fixed20_12 cur_latency_mclk, cur_latency_sclk;
+       fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate,
+               disp_drain_rate2, read_return_rate;
+       fixed20_12 time_disp1_drop_priority;
+       int c;
+       int cur_size = 16;       /* in octawords */
+       int critical_point = 0, critical_point2;
+/*     uint32_t read_return_rate, time_disp1_drop_priority; */
+       int stop_req, max_stop_req;
+       struct drm_display_mode *mode1 = NULL;
+       struct drm_display_mode *mode2 = NULL;
+       uint32_t pixel_bytes1 = 0;
+       uint32_t pixel_bytes2 = 0;
+
+       if (rdev->mode_info.crtcs[0]->base.enabled) {
+               mode1 = &rdev->mode_info.crtcs[0]->base.mode;
+               pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8;
+       }
+       if (rdev->mode_info.crtcs[1]->base.enabled) {
+               mode2 = &rdev->mode_info.crtcs[1]->base.mode;
+               pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8;
+       }
+
+       min_mem_eff.full = rfixed_const_8(0);
+       /* get modes */
+       if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) {
+               uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER);
+               mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT);
+               mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT);
+               /* check crtc enables */
+               if (mode2)
+                       mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT);
+               if (mode1)
+                       mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT);
+               WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
+       }
+
+       /*
+        * determine is there is enough bw for current mode
+        */
+       mclk_ff.full = rfixed_const(rdev->clock.default_mclk);
+       temp_ff.full = rfixed_const(100);
+       mclk_ff.full = rfixed_div(mclk_ff, temp_ff);
+       sclk_ff.full = rfixed_const(rdev->clock.default_sclk);
+       sclk_ff.full = rfixed_div(sclk_ff, temp_ff);
+
+       temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1);
+       temp_ff.full = rfixed_const(temp);
+       mem_bw.full = rfixed_mul(mclk_ff, temp_ff);
+
+       pix_clk.full = 0;
+       pix_clk2.full = 0;
+       peak_disp_bw.full = 0;
+       if (mode1) {
+               temp_ff.full = rfixed_const(1000);
+               pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */
+               pix_clk.full = rfixed_div(pix_clk, temp_ff);
+               temp_ff.full = rfixed_const(pixel_bytes1);
+               peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff);
+       }
+       if (mode2) {
+               temp_ff.full = rfixed_const(1000);
+               pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */
+               pix_clk2.full = rfixed_div(pix_clk2, temp_ff);
+               temp_ff.full = rfixed_const(pixel_bytes2);
+               peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff);
+       }
+
+       mem_bw.full = rfixed_mul(mem_bw, min_mem_eff);
+       if (peak_disp_bw.full >= mem_bw.full) {
+               DRM_ERROR("You may not have enough display bandwidth for current mode\n"
+                         "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
+       }
+
+       /*  Get values from the EXT_MEM_CNTL register...converting its contents. */
+       temp = RREG32(RADEON_MEM_TIMING_CNTL);
+       if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */
+               mem_trcd = ((temp >> 2) & 0x3) + 1;
+               mem_trp  = ((temp & 0x3)) + 1;
+               mem_tras = ((temp & 0x70) >> 4) + 1;
+       } else if (rdev->family == CHIP_R300 ||
+                  rdev->family == CHIP_R350) { /* r300, r350 */
+               mem_trcd = (temp & 0x7) + 1;
+               mem_trp = ((temp >> 8) & 0x7) + 1;
+               mem_tras = ((temp >> 11) & 0xf) + 4;
+       } else if (rdev->family == CHIP_RV350 ||
+                  rdev->family <= CHIP_RV380) {
+               /* rv3x0 */
+               mem_trcd = (temp & 0x7) + 3;
+               mem_trp = ((temp >> 8) & 0x7) + 3;
+               mem_tras = ((temp >> 11) & 0xf) + 6;
+       } else if (rdev->family == CHIP_R420 ||
+                  rdev->family == CHIP_R423 ||
+                  rdev->family == CHIP_RV410) {
+               /* r4xx */
+               mem_trcd = (temp & 0xf) + 3;
+               if (mem_trcd > 15)
+                       mem_trcd = 15;
+               mem_trp = ((temp >> 8) & 0xf) + 3;
+               if (mem_trp > 15)
+                       mem_trp = 15;
+               mem_tras = ((temp >> 12) & 0x1f) + 6;
+               if (mem_tras > 31)
+                       mem_tras = 31;
+       } else { /* RV200, R200 */
+               mem_trcd = (temp & 0x7) + 1;
+               mem_trp = ((temp >> 8) & 0x7) + 1;
+               mem_tras = ((temp >> 12) & 0xf) + 4;
+       }
+       /* convert to FF */
+       trcd_ff.full = rfixed_const(mem_trcd);
+       trp_ff.full = rfixed_const(mem_trp);
+       tras_ff.full = rfixed_const(mem_tras);
+
+       /* Get values from the MEM_SDRAM_MODE_REG register...converting its */
+       temp = RREG32(RADEON_MEM_SDRAM_MODE_REG);
+       data = (temp & (7 << 20)) >> 20;
+       if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) {
+               if (rdev->family == CHIP_RS480) /* don't think rs400 */
+                       tcas_ff = memtcas_rs480_ff[data];
+               else
+                       tcas_ff = memtcas_ff[data];
+       } else
+               tcas_ff = memtcas2_ff[data];
+
+       if (rdev->family == CHIP_RS400 ||
+           rdev->family == CHIP_RS480) {
+               /* extra cas latency stored in bits 23-25 0-4 clocks */
+               data = (temp >> 23) & 0x7;
+               if (data < 5)
+                       tcas_ff.full += rfixed_const(data);
+       }
+
+       if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) {
+               /* on the R300, Tcas is included in Trbs.
+                */
+               temp = RREG32(RADEON_MEM_CNTL);
+               data = (R300_MEM_NUM_CHANNELS_MASK & temp);
+               if (data == 1) {
+                       if (R300_MEM_USE_CD_CH_ONLY & temp) {
+                               temp = RREG32(R300_MC_IND_INDEX);
+                               temp &= ~R300_MC_IND_ADDR_MASK;
+                               temp |= R300_MC_READ_CNTL_CD_mcind;
+                               WREG32(R300_MC_IND_INDEX, temp);
+                               temp = RREG32(R300_MC_IND_DATA);
+                               data = (R300_MEM_RBS_POSITION_C_MASK & temp);
+                       } else {
+                               temp = RREG32(R300_MC_READ_CNTL_AB);
+                               data = (R300_MEM_RBS_POSITION_A_MASK & temp);
+                       }
+               } else {
+                       temp = RREG32(R300_MC_READ_CNTL_AB);
+                       data = (R300_MEM_RBS_POSITION_A_MASK & temp);
+               }
+               if (rdev->family == CHIP_RV410 ||
+                   rdev->family == CHIP_R420 ||
+                   rdev->family == CHIP_R423)
+                       trbs_ff = memtrbs_r4xx[data];
+               else
+                       trbs_ff = memtrbs[data];
+               tcas_ff.full += trbs_ff.full;
+       }
+
+       sclk_eff_ff.full = sclk_ff.full;
+
+       if (rdev->flags & RADEON_IS_AGP) {
+               fixed20_12 agpmode_ff;
+               agpmode_ff.full = rfixed_const(radeon_agpmode);
+               temp_ff.full = rfixed_const_666(16);
+               sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff);
+       }
+       /* TODO PCIE lanes may affect this - agpmode == 16?? */
+
+       if (ASIC_IS_R300(rdev)) {
+               sclk_delay_ff.full = rfixed_const(250);
+       } else {
+               if ((rdev->family == CHIP_RV100) ||
+                   rdev->flags & RADEON_IS_IGP) {
+                       if (rdev->mc.vram_is_ddr)
+                               sclk_delay_ff.full = rfixed_const(41);
+                       else
+                               sclk_delay_ff.full = rfixed_const(33);
+               } else {
+                       if (rdev->mc.vram_width == 128)
+                               sclk_delay_ff.full = rfixed_const(57);
+                       else
+                               sclk_delay_ff.full = rfixed_const(41);
+               }
+       }
+
+       mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff);
+
+       if (rdev->mc.vram_is_ddr) {
+               if (rdev->mc.vram_width == 32) {
+                       k1.full = rfixed_const(40);
+                       c  = 3;
+               } else {
+                       k1.full = rfixed_const(20);
+                       c  = 1;
+               }
+       } else {
+               k1.full = rfixed_const(40);
+               c  = 3;
+       }
+
+       temp_ff.full = rfixed_const(2);
+       mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff);
+       temp_ff.full = rfixed_const(c);
+       mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff);
+       temp_ff.full = rfixed_const(4);
+       mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff);
+       mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff);
+       mc_latency_mclk.full += k1.full;
+
+       mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff);
+       mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff);
+
+       /*
+         HW cursor time assuming worst case of full size colour cursor.
+       */
+       temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1))));
+       temp_ff.full += trcd_ff.full;
+       if (temp_ff.full < tras_ff.full)
+               temp_ff.full = tras_ff.full;
+       cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff);
+
+       temp_ff.full = rfixed_const(cur_size);
+       cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff);
+       /*
+         Find the total latency for the display data.
+       */
+       disp_latency_overhead.full = rfixed_const(80);
+       disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff);
+       mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full;
+       mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full;
+
+       if (mc_latency_mclk.full > mc_latency_sclk.full)
+               disp_latency.full = mc_latency_mclk.full;
+       else
+               disp_latency.full = mc_latency_sclk.full;
+
+       /* setup Max GRPH_STOP_REQ default value */
+       if (ASIC_IS_RV100(rdev))
+               max_stop_req = 0x5c;
+       else
+               max_stop_req = 0x7c;
+
+       if (mode1) {
+               /*  CRTC1
+                   Set GRPH_BUFFER_CNTL register using h/w defined optimal values.
+                   GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ]
+               */
+               stop_req = mode1->hdisplay * pixel_bytes1 / 16;
+
+               if (stop_req > max_stop_req)
+                       stop_req = max_stop_req;
+
+               /*
+                 Find the drain rate of the display buffer.
+               */
+               temp_ff.full = rfixed_const((16/pixel_bytes1));
+               disp_drain_rate.full = rfixed_div(pix_clk, temp_ff);
+
+               /*
+                 Find the critical point of the display buffer.
+               */
+               crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency);
+               crit_point_ff.full += rfixed_const_half(0);
+
+               critical_point = rfixed_trunc(crit_point_ff);
+
+               if (rdev->disp_priority == 2) {
+                       critical_point = 0;
+               }
+
+               /*
+                 The critical point should never be above max_stop_req-4.  Setting
+                 GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time.
+               */
+               if (max_stop_req - critical_point < 4)
+                       critical_point = 0;
+
+               if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) {
+                       /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/
+                       critical_point = 0x10;
+               }
+
+               temp = RREG32(RADEON_GRPH_BUFFER_CNTL);
+               temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
+               temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
+               temp &= ~(RADEON_GRPH_START_REQ_MASK);
+               if ((rdev->family == CHIP_R350) &&
+                   (stop_req > 0x15)) {
+                       stop_req -= 0x10;
+               }
+               temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
+               temp |= RADEON_GRPH_BUFFER_SIZE;
+               temp &= ~(RADEON_GRPH_CRITICAL_CNTL   |
+                         RADEON_GRPH_CRITICAL_AT_SOF |
+                         RADEON_GRPH_STOP_CNTL);
+               /*
+                 Write the result into the register.
+               */
+               WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
+                                                      (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
+
+#if 0
+               if ((rdev->family == CHIP_RS400) ||
+                   (rdev->family == CHIP_RS480)) {
+                       /* attempt to program RS400 disp regs correctly ??? */
+                       temp = RREG32(RS400_DISP1_REG_CNTL);
+                       temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK |
+                                 RS400_DISP1_STOP_REQ_LEVEL_MASK);
+                       WREG32(RS400_DISP1_REQ_CNTL1, (temp |
+                                                      (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) |
+                                                      (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT)));
+                       temp = RREG32(RS400_DMIF_MEM_CNTL1);
+                       temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK |
+                                 RS400_DISP1_CRITICAL_POINT_STOP_MASK);
+                       WREG32(RS400_DMIF_MEM_CNTL1, (temp |
+                                                     (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) |
+                                                     (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT)));
+               }
+#endif
+
+               DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n",
+                         /*      (unsigned int)info->SavedReg->grph_buffer_cntl, */
+                         (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL));
+       }
+
+       if (mode2) {
+               u32 grph2_cntl;
+               stop_req = mode2->hdisplay * pixel_bytes2 / 16;
+
+               if (stop_req > max_stop_req)
+                       stop_req = max_stop_req;
+
+               /*
+                 Find the drain rate of the display buffer.
+               */
+               temp_ff.full = rfixed_const((16/pixel_bytes2));
+               disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff);
+
+               grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL);
+               grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK);
+               grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
+               grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK);
+               if ((rdev->family == CHIP_R350) &&
+                   (stop_req > 0x15)) {
+                       stop_req -= 0x10;
+               }
+               grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
+               grph2_cntl |= RADEON_GRPH_BUFFER_SIZE;
+               grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL   |
+                         RADEON_GRPH_CRITICAL_AT_SOF |
+                         RADEON_GRPH_STOP_CNTL);
+
+               if ((rdev->family == CHIP_RS100) ||
+                   (rdev->family == CHIP_RS200))
+                       critical_point2 = 0;
+               else {
+                       temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128;
+                       temp_ff.full = rfixed_const(temp);
+                       temp_ff.full = rfixed_mul(mclk_ff, temp_ff);
+                       if (sclk_ff.full < temp_ff.full)
+                               temp_ff.full = sclk_ff.full;
+
+                       read_return_rate.full = temp_ff.full;
+
+                       if (mode1) {
+                               temp_ff.full = read_return_rate.full - disp_drain_rate.full;
+                               time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff);
+                       } else {
+                               time_disp1_drop_priority.full = 0;
+                       }
+                       crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full;
+                       crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2);
+                       crit_point_ff.full += rfixed_const_half(0);
+
+                       critical_point2 = rfixed_trunc(crit_point_ff);
+
+                       if (rdev->disp_priority == 2) {
+                               critical_point2 = 0;
+                       }
+
+                       if (max_stop_req - critical_point2 < 4)
+                               critical_point2 = 0;
+
+               }
+
+               if (critical_point2 == 0 && rdev->family == CHIP_R300) {
+                       /* some R300 cards have problem with this set to 0 */
+                       critical_point2 = 0x10;
+               }
+
+               WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
+                                                 (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
+
+               if ((rdev->family == CHIP_RS400) ||
+                   (rdev->family == CHIP_RS480)) {
+#if 0
+                       /* attempt to program RS400 disp2 regs correctly ??? */
+                       temp = RREG32(RS400_DISP2_REQ_CNTL1);
+                       temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK |
+                                 RS400_DISP2_STOP_REQ_LEVEL_MASK);
+                       WREG32(RS400_DISP2_REQ_CNTL1, (temp |
+                                                      (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) |
+                                                      (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT)));
+                       temp = RREG32(RS400_DISP2_REQ_CNTL2);
+                       temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK |
+                                 RS400_DISP2_CRITICAL_POINT_STOP_MASK);
+                       WREG32(RS400_DISP2_REQ_CNTL2, (temp |
+                                                      (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) |
+                                                      (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT)));
+#endif
+                       WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC);
+                       WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000);
+                       WREG32(RS400_DMIF_MEM_CNTL1,  0x29CA71DC);
+                       WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC);
+               }
+
+               DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n",
+                         (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL));
+       }
+}
index e2ed5bc08170db96113ab9a038556dd42877af72..051bca6e3a4f2981d1f580d7bbc174c43ac586d3 100644 (file)
@@ -30,6 +30,8 @@
 #include "drm.h"
 #include "radeon_reg.h"
 #include "radeon.h"
+#include "radeon_drm.h"
+#include "radeon_share.h"
 
 /* r300,r350,rv350,rv370,rv380 depends on : */
 void r100_hdp_reset(struct radeon_device *rdev);
@@ -44,6 +46,7 @@ int r100_gui_wait_for_idle(struct radeon_device *rdev);
 int r100_cs_packet_parse(struct radeon_cs_parser *p,
                         struct radeon_cs_packet *pkt,
                         unsigned idx);
+int r100_cs_packet_parse_vline(struct radeon_cs_parser *p);
 int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
                              struct radeon_cs_reloc **cs_reloc);
 int r100_cs_parse_packet0(struct radeon_cs_parser *p,
@@ -80,8 +83,8 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev)
                WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp | RADEON_PCIE_TX_GART_INVALIDATE_TLB);
                (void)RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
                WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
-               mb();
        }
+       mb();
 }
 
 int rv370_pcie_gart_enable(struct radeon_device *rdev)
@@ -150,8 +153,13 @@ int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
        if (i < 0 || i > rdev->gart.num_gpu_pages) {
                return -EINVAL;
        }
-       addr = (((u32)addr) >> 8) | ((upper_32_bits(addr) & 0xff) << 4) | 0xC;
-       writel(cpu_to_le32(addr), ((void __iomem *)ptr) + (i * 4));
+       addr = (lower_32_bits(addr) >> 8) |
+              ((upper_32_bits(addr) & 0xff) << 24) |
+              0xc;
+       /* on x86 we want this to be CPU endian, on powerpc
+        * on powerpc without HW swappers, it'll get swapped on way
+        * into VRAM - so no need for cpu_to_le32 on VRAM tables */
+       writel(addr, ((void __iomem *)ptr) + (i * 4));
        return 0;
 }
 
@@ -440,6 +448,7 @@ void r300_gpu_init(struct radeon_device *rdev)
                /* rv350,rv370,rv380 */
                rdev->num_gb_pipes = 1;
        }
+       rdev->num_z_pipes = 1;
        gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
        switch (rdev->num_gb_pipes) {
        case 2:
@@ -478,7 +487,8 @@ void r300_gpu_init(struct radeon_device *rdev)
                printk(KERN_WARNING "Failed to wait MC idle while "
                       "programming pipes. Bad things might happen.\n");
        }
-       DRM_INFO("radeon: %d pipes initialized.\n", rdev->num_gb_pipes);
+       DRM_INFO("radeon: %d quad pipes, %d Z pipes initialized.\n",
+                rdev->num_gb_pipes, rdev->num_z_pipes);
 }
 
 int r300_ga_reset(struct radeon_device *rdev)
@@ -579,34 +589,11 @@ void r300_vram_info(struct radeon_device *rdev)
        } else {
                rdev->mc.vram_width = 64;
        }
-       rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
 
-       rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
-       rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+       r100_vram_init_sizes(rdev);
 }
 
 
-/*
- * Indirect registers accessor
- */
-uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg)
-{
-       uint32_t r;
-
-       WREG8(RADEON_PCIE_INDEX, ((reg) & 0xff));
-       (void)RREG32(RADEON_PCIE_INDEX);
-       r = RREG32(RADEON_PCIE_DATA);
-       return r;
-}
-
-void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
-{
-       WREG8(RADEON_PCIE_INDEX, ((reg) & 0xff));
-       (void)RREG32(RADEON_PCIE_INDEX);
-       WREG32(RADEON_PCIE_DATA, (v));
-       (void)RREG32(RADEON_PCIE_DATA);
-}
-
 /*
  * PCIE Lanes
  */
@@ -970,7 +957,7 @@ static inline void r300_cs_track_clear(struct r300_cs_track *track)
 
 static const unsigned r300_reg_safe_bm[159] = {
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-       0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
@@ -1008,7 +995,7 @@ static const unsigned r300_reg_safe_bm[159] = {
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
        0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x0003FC01, 0xFFFFFFF8, 0xFE800B19,
+       0x0003FC01, 0xFFFFFCF8, 0xFF800B19,
 };
 
 static int r300_packet0_check(struct radeon_cs_parser *p,
@@ -1019,7 +1006,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
        struct radeon_cs_reloc *reloc;
        struct r300_cs_track *track;
        volatile uint32_t *ib;
-       uint32_t tmp;
+       uint32_t tmp, tile_flags = 0;
        unsigned i;
        int r;
 
@@ -1027,6 +1014,16 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
        ib_chunk = &p->chunks[p->chunk_ib_idx];
        track = (struct r300_cs_track*)p->track;
        switch(reg) {
+       case AVIVO_D1MODE_VLINE_START_END:
+       case RADEON_CRTC_GUI_TRIG_VLINE:
+               r = r100_cs_packet_parse_vline(p);
+               if (r) {
+                       DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+                                       idx, reg);
+                       r100_cs_dump_packet(p, pkt);
+                       return r;
+               }
+               break;
        case RADEON_DST_PITCH_OFFSET:
        case RADEON_SRC_PITCH_OFFSET:
                r = r100_cs_packet_next_reloc(p, &reloc);
@@ -1038,7 +1035,19 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                }
                tmp = ib_chunk->kdata[idx] & 0x003fffff;
                tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
-               ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp;
+
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                       tile_flags |= RADEON_DST_TILE_MACRO;
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+                       if (reg == RADEON_SRC_PITCH_OFFSET) {
+                               DRM_ERROR("Cannot src blit from microtiled surface\n");
+                               r100_cs_dump_packet(p, pkt);
+                               return -EINVAL;
+                       }
+                       tile_flags |= RADEON_DST_TILE_MICRO;
+               }
+               tmp |= tile_flags;
+               ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp;
                break;
        case R300_RB3D_COLOROFFSET0:
        case R300_RB3D_COLOROFFSET1:
@@ -1127,6 +1136,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                /* RB3D_COLORPITCH1 */
                /* RB3D_COLORPITCH2 */
                /* RB3D_COLORPITCH3 */
+               r = r100_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+                                 idx, reg);
+                       r100_cs_dump_packet(p, pkt);
+                       return r;
+               }
+
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                       tile_flags |= R300_COLOR_TILE_ENABLE;
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                       tile_flags |= R300_COLOR_MICROTILE_ENABLE;
+
+               tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
+               tmp |= tile_flags;
+               ib[idx] = tmp;
+
                i = (reg - 0x4E38) >> 2;
                track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE;
                switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) {
@@ -1182,6 +1208,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                break;
        case 0x4F24:
                /* ZB_DEPTHPITCH */
+               r = r100_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+                                 idx, reg);
+                       r100_cs_dump_packet(p, pkt);
+                       return r;
+               }
+
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                       tile_flags |= R300_DEPTHMACROTILE_ENABLE;
+               if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                       tile_flags |= R300_DEPTHMICROTILE_TILED;;
+
+               tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
+               tmp |= tile_flags;
+               ib[idx] = tmp;
+
                track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC;
                break;
        case 0x4104:
@@ -1341,6 +1384,21 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                tmp = (ib_chunk->kdata[idx] >> 22) & 0xF;
                track->textures[i].txdepth = tmp;
                break;
+       case R300_ZB_ZPASS_ADDR:
+               r = r100_cs_packet_next_reloc(p, &reloc);
+               if (r) {
+                       DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+                                       idx, reg);
+                       r100_cs_dump_packet(p, pkt);
+                       return r;
+               }
+               ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
+               break;
+       case 0x4be8:
+               /* valid register only on RV530 */
+               if (p->rdev->family == CHIP_RV530)
+                       break;
+               /* fallthrough do not move */
        default:
                printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
                       reg, idx);
index 70f48609515e2c1c69b19e83a7cc5ce6595399f9..4b7afef35a655511a2431682bd77e24fe37838b4 100644 (file)
@@ -27,7 +27,9 @@
 #ifndef _R300_REG_H_
 #define _R300_REG_H_
 
-
+#define R300_SURF_TILE_MACRO (1<<16)
+#define R300_SURF_TILE_MICRO (2<<16)
+#define R300_SURF_TILE_BOTH (3<<16)
 
 
 #define R300_MC_INIT_MISC_LAT_TIMER    0x180
index dea497a979f2083548d491ca9505571696f6ecea..97426a6f370f11695276105dc8906fc10c203c9c 100644 (file)
@@ -165,7 +165,18 @@ void r420_pipes_init(struct radeon_device *rdev)
                printk(KERN_WARNING "Failed to wait GUI idle while "
                       "programming pipes. Bad things might happen.\n");
        }
-       DRM_INFO("radeon: %d pipes initialized.\n", rdev->num_gb_pipes);
+
+       if (rdev->family == CHIP_RV530) {
+               tmp = RREG32(RV530_GB_PIPE_SELECT2);
+               if ((tmp & 3) == 3)
+                       rdev->num_z_pipes = 2;
+               else
+                       rdev->num_z_pipes = 1;
+       } else
+               rdev->num_z_pipes = 1;
+
+       DRM_INFO("radeon: %d quad pipes, %d z pipes initialized.\n",
+                rdev->num_gb_pipes, rdev->num_z_pipes);
 }
 
 void r420_gpu_init(struct radeon_device *rdev)
index 9070a1c2ce238ac2e8534318c6b4fe7a69a96211..e1d5e0331e19095b863d0a613c9a87318ee7d082 100644 (file)
 #define AVIVO_D1CRTC_BLANK_CONTROL                              0x6084
 #define AVIVO_D1CRTC_INTERLACE_CONTROL                          0x6088
 #define AVIVO_D1CRTC_INTERLACE_STATUS                           0x608c
+#define AVIVO_D1CRTC_FRAME_COUNT                                0x60a4
 #define AVIVO_D1CRTC_STEREO_CONTROL                             0x60c4
 
 /* master controls */
 #       define AVIVO_DC_LB_DISP1_END_ADR_SHIFT  4
 #       define AVIVO_DC_LB_DISP1_END_ADR_MASK   0x7ff
 
-#define R500_DxMODE_INT_MASK 0x6540
-#define R500_D1MODE_INT_MASK (1<<0)
-#define R500_D2MODE_INT_MASK (1<<8)
-
 #define AVIVO_D1MODE_DATA_FORMAT                0x6528
 #       define AVIVO_D1MODE_INTERLEAVE_EN       (1 << 0)
 #define AVIVO_D1MODE_DESKTOP_HEIGHT             0x652C
+#define AVIVO_D1MODE_VBLANK_STATUS              0x6534
+#       define AVIVO_VBLANK_ACK                 (1 << 4)
+#define AVIVO_D1MODE_VLINE_START_END            0x6538
+#define AVIVO_DxMODE_INT_MASK                   0x6540
+#       define AVIVO_D1MODE_INT_MASK            (1 << 0)
+#       define AVIVO_D2MODE_INT_MASK            (1 << 8)
 #define AVIVO_D1MODE_VIEWPORT_START             0x6580
 #define AVIVO_D1MODE_VIEWPORT_SIZE              0x6584
 #define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT    0x6588
 #define AVIVO_D2CRTC_BLANK_CONTROL                              0x6884
 #define AVIVO_D2CRTC_INTERLACE_CONTROL                          0x6888
 #define AVIVO_D2CRTC_INTERLACE_STATUS                           0x688c
+#define AVIVO_D2CRTC_FRAME_COUNT                                0x68a4
 #define AVIVO_D2CRTC_STEREO_CONTROL                             0x68c4
 
 #define AVIVO_D2GRPH_ENABLE                                     0x6900
 #define AVIVO_D2CUR_SIZE                        0x6c10
 #define AVIVO_D2CUR_POSITION                    0x6c14
 
+#define AVIVO_D2MODE_VBLANK_STATUS              0x6d34
+#define AVIVO_D2MODE_VLINE_START_END            0x6d38
 #define AVIVO_D2MODE_VIEWPORT_START             0x6d80
 #define AVIVO_D2MODE_VIEWPORT_SIZE              0x6d84
 #define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT    0x6d88
 #      define AVIVO_I2C_EN                                                     (1 << 0)
 #      define AVIVO_I2C_RESET                                          (1 << 8)
 
+#define AVIVO_DISP_INTERRUPT_STATUS                             0x7edc
+#       define AVIVO_D1_VBLANK_INTERRUPT                        (1 << 4)
+#       define AVIVO_D2_VBLANK_INTERRUPT                        (1 << 5)
+
 #endif
index 570a244bd88b6815725129def0a3d8280281a8ed..ebd6b0f7bdff584577a27a1feabbaa66e1cad355 100644 (file)
@@ -28,6 +28,7 @@
 #include "drmP.h"
 #include "radeon_reg.h"
 #include "radeon.h"
+#include "radeon_share.h"
 
 /* r520,rv530,rv560,rv570,r580 depends on : */
 void r100_hdp_reset(struct radeon_device *rdev);
@@ -94,8 +95,8 @@ int r520_mc_init(struct radeon_device *rdev)
                       "programming pipes. Bad things might happen.\n");
        }
        /* Write VRAM size in case we are limiting it */
-       WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
-       tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
+       WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
+       tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
        tmp = REG_SET(R520_MC_FB_TOP, tmp >> 16);
        tmp |= REG_SET(R520_MC_FB_START, rdev->mc.vram_location >> 16);
        WREG32_MC(R520_MC_FB_LOCATION, tmp);
@@ -176,7 +177,6 @@ void r520_gpu_init(struct radeon_device *rdev)
         */
        /* workaround for RV530 */
        if (rdev->family == CHIP_RV530) {
-               WREG32(0x4124, 1);
                WREG32(0x4128, 0xFF);
        }
        r420_pipes_init(rdev);
@@ -226,9 +226,20 @@ static void r520_vram_get_type(struct radeon_device *rdev)
 
 void r520_vram_info(struct radeon_device *rdev)
 {
+       fixed20_12 a;
+
        r520_vram_get_type(rdev);
-       rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
 
-       rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
-       rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+       r100_vram_init_sizes(rdev);
+       /* FIXME: we should enforce default clock in case GPU is not in
+        * default setup
+        */
+       a.full = rfixed_const(100);
+       rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
+       rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+}
+
+void r520_bandwidth_update(struct radeon_device *rdev)
+{
+       rv515_bandwidth_avivo_update(rdev);
 }
index c45559fc97fd2c1e5acf630c751be9d3efeb15f3..538cd907df690607a2bab2e219b6d73cfde69108 100644 (file)
@@ -67,7 +67,7 @@ int r600_mc_init(struct radeon_device *rdev)
                       "programming pipes. Bad things might happen.\n");
        }
 
-       tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
+       tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
        tmp = REG_SET(R600_MC_FB_TOP, tmp >> 24);
        tmp |= REG_SET(R600_MC_FB_BASE, rdev->mc.vram_location >> 24);
        WREG32(R600_MC_VM_FB_LOCATION, tmp);
@@ -140,7 +140,8 @@ void r600_vram_get_type(struct radeon_device *rdev)
 void r600_vram_info(struct radeon_device *rdev)
 {
        r600_vram_get_type(rdev);
-       rdev->mc.vram_size = RREG32(R600_CONFIG_MEMSIZE);
+       rdev->mc.real_vram_size = RREG32(R600_CONFIG_MEMSIZE);
+       rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
 
        /* Could aper size report 0 ? */
        rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
index 146f3570af8e710f689d3f9823981b993a5e3632..20f17908b036d6c59b8435e354787a42295fa0d8 100644 (file)
@@ -384,8 +384,9 @@ static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
                DRM_INFO("Loading RV670 PFP Microcode\n");
                for (i = 0; i < PFP_UCODE_SIZE; i++)
                        RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV670_pfp_microcode[i]);
-       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780)) {
-               DRM_INFO("Loading RS780 CP Microcode\n");
+       } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
+               DRM_INFO("Loading RS780/RS880 CP Microcode\n");
                for (i = 0; i < PM4_UCODE_SIZE; i++) {
                        RADEON_WRITE(R600_CP_ME_RAM_DATA,
                                     RS780_cp_microcode[i][0]);
@@ -396,7 +397,7 @@ static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
                }
 
                RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-               DRM_INFO("Loading RS780 PFP Microcode\n");
+               DRM_INFO("Loading RS780/RS880 PFP Microcode\n");
                for (i = 0; i < PFP_UCODE_SIZE; i++)
                        RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RS780_pfp_microcode[i]);
        }
@@ -783,6 +784,7 @@ static void r600_gfx_init(struct drm_device *dev,
                break;
        case CHIP_RV610:
        case CHIP_RS780:
+       case CHIP_RS880:
        case CHIP_RV620:
                dev_priv->r600_max_pipes = 1;
                dev_priv->r600_max_tile_pipes = 1;
@@ -917,7 +919,8 @@ static void r600_gfx_init(struct drm_device *dev,
            ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630) ||
            ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
            ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780))
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880))
                RADEON_WRITE(R600_DB_DEBUG, R600_PREZ_MUST_WAIT_FOR_POSTZ_DONE);
        else
                RADEON_WRITE(R600_DB_DEBUG, 0);
@@ -935,7 +938,8 @@ static void r600_gfx_init(struct drm_device *dev,
        sq_ms_fifo_sizes = RADEON_READ(R600_SQ_MS_FIFO_SIZES);
        if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
            ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780)) {
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
                sq_ms_fifo_sizes = (R600_CACHE_FIFO_SIZE(0xa) |
                                    R600_FETCH_FIFO_HIWATER(0xa) |
                                    R600_DONE_FIFO_HIWATER(0xe0) |
@@ -978,7 +982,8 @@ static void r600_gfx_init(struct drm_device *dev,
                                            R600_NUM_ES_STACK_ENTRIES(0));
        } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
                   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780)) {
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+                  ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
                /* no vertex cache */
                sq_config &= ~R600_VC_ENABLE;
 
@@ -1035,7 +1040,8 @@ static void r600_gfx_init(struct drm_device *dev,
 
        if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
            ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
-           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780))
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
+           ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880))
                RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_TC_ONLY));
        else
                RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_VC_AND_TC));
@@ -1078,6 +1084,7 @@ static void r600_gfx_init(struct drm_device *dev,
                break;
        case CHIP_RV610:
        case CHIP_RS780:
+       case CHIP_RS880:
        case CHIP_RV620:
                gs_prim_buffer_depth = 32;
                break;
@@ -1123,6 +1130,7 @@ static void r600_gfx_init(struct drm_device *dev,
        switch (dev_priv->flags & RADEON_FAMILY_MASK) {
        case CHIP_RV610:
        case CHIP_RS780:
+       case CHIP_RS880:
        case CHIP_RV620:
                tc_cntl = R600_TC_L2_SIZE(8);
                break;
index d61f2fc61df53e959b083ce5f07aa2a3b6771d27..b519fb2fecbb4ba25df535c61fa15316b5032d6d 100644 (file)
@@ -64,6 +64,7 @@ extern int radeon_agpmode;
 extern int radeon_vram_limit;
 extern int radeon_gart_size;
 extern int radeon_benchmarking;
+extern int radeon_testing;
 extern int radeon_connector_table;
 
 /*
@@ -113,6 +114,7 @@ enum radeon_family {
        CHIP_RV770,
        CHIP_RV730,
        CHIP_RV710,
+       CHIP_RS880,
        CHIP_LAST,
 };
 
@@ -201,6 +203,14 @@ int radeon_fence_wait_last(struct radeon_device *rdev);
 struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
 void radeon_fence_unref(struct radeon_fence **fence);
 
+/*
+ * Tiling registers
+ */
+struct radeon_surface_reg {
+       struct radeon_object *robj;
+};
+
+#define RADEON_GEM_MAX_SURFACES 8
 
 /*
  * Radeon buffer.
@@ -213,6 +223,7 @@ struct radeon_object_list {
        uint64_t                gpu_offset;
        unsigned                rdomain;
        unsigned                wdomain;
+       uint32_t                tiling_flags;
 };
 
 int radeon_object_init(struct radeon_device *rdev);
@@ -231,6 +242,7 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
                      uint64_t *gpu_addr);
 void radeon_object_unpin(struct radeon_object *robj);
 int radeon_object_wait(struct radeon_object *robj);
+int radeon_object_busy_domain(struct radeon_object *robj, uint32_t *cur_placement);
 int radeon_object_evict_vram(struct radeon_device *rdev);
 int radeon_object_mmap(struct radeon_object *robj, uint64_t *offset);
 void radeon_object_force_delete(struct radeon_device *rdev);
@@ -242,8 +254,15 @@ void radeon_object_list_clean(struct list_head *head);
 int radeon_object_fbdev_mmap(struct radeon_object *robj,
                             struct vm_area_struct *vma);
 unsigned long radeon_object_size(struct radeon_object *robj);
-
-
+void radeon_object_clear_surface_reg(struct radeon_object *robj);
+int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved,
+                              bool force_drop);
+void radeon_object_set_tiling_flags(struct radeon_object *robj,
+                                   uint32_t tiling_flags, uint32_t pitch);
+void radeon_object_get_tiling_flags(struct radeon_object *robj, uint32_t *tiling_flags, uint32_t *pitch);
+void radeon_bo_move_notify(struct ttm_buffer_object *bo,
+                          struct ttm_mem_reg *mem);
+void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
 /*
  * GEM objects.
  */
@@ -315,8 +334,11 @@ struct radeon_mc {
        unsigned                gtt_location;
        unsigned                gtt_size;
        unsigned                vram_location;
-       unsigned                vram_size;
+       /* for some chips with <= 32MB we need to lie
+        * about vram size near mc fb location */
+       unsigned                mc_vram_size;
        unsigned                vram_width;
+       unsigned                real_vram_size;
        int                     vram_mtrr;
        bool                    vram_is_ddr;
 };
@@ -474,6 +496,39 @@ struct radeon_wb {
        uint64_t                gpu_addr;
 };
 
+/**
+ * struct radeon_pm - power management datas
+ * @max_bandwidth:      maximum bandwidth the gpu has (MByte/s)
+ * @igp_sideport_mclk:  sideport memory clock Mhz (rs690,rs740,rs780,rs880)
+ * @igp_system_mclk:    system clock Mhz (rs690,rs740,rs780,rs880)
+ * @igp_ht_link_clk:    ht link clock Mhz (rs690,rs740,rs780,rs880)
+ * @igp_ht_link_width:  ht link width in bits (rs690,rs740,rs780,rs880)
+ * @k8_bandwidth:       k8 bandwidth the gpu has (MByte/s) (IGP)
+ * @sideport_bandwidth: sideport bandwidth the gpu has (MByte/s) (IGP)
+ * @ht_bandwidth:       ht bandwidth the gpu has (MByte/s) (IGP)
+ * @core_bandwidth:     core GPU bandwidth the gpu has (MByte/s) (IGP)
+ * @sclk:              GPU clock Mhz (core bandwith depends of this clock)
+ * @needed_bandwidth:   current bandwidth needs
+ *
+ * It keeps track of various data needed to take powermanagement decision.
+ * Bandwith need is used to determine minimun clock of the GPU and memory.
+ * Equation between gpu/memory clock and available bandwidth is hw dependent
+ * (type of memory, bus size, efficiency, ...)
+ */
+struct radeon_pm {
+       fixed20_12              max_bandwidth;
+       fixed20_12              igp_sideport_mclk;
+       fixed20_12              igp_system_mclk;
+       fixed20_12              igp_ht_link_clk;
+       fixed20_12              igp_ht_link_width;
+       fixed20_12              k8_bandwidth;
+       fixed20_12              sideport_bandwidth;
+       fixed20_12              ht_bandwidth;
+       fixed20_12              core_bandwidth;
+       fixed20_12              sclk;
+       fixed20_12              needed_bandwidth;
+};
+
 
 /*
  * Benchmarking
@@ -481,6 +536,12 @@ struct radeon_wb {
 void radeon_benchmark(struct radeon_device *rdev);
 
 
+/*
+ * Testing
+ */
+void radeon_test_moves(struct radeon_device *rdev);
+
+
 /*
  * Debugfs
  */
@@ -514,6 +575,7 @@ struct radeon_asic {
        void (*ring_start)(struct radeon_device *rdev);
        int (*irq_set)(struct radeon_device *rdev);
        int (*irq_process)(struct radeon_device *rdev);
+       u32 (*get_vblank_counter)(struct radeon_device *rdev, int crtc);
        void (*fence_ring_emit)(struct radeon_device *rdev, struct radeon_fence *fence);
        int (*cs_parse)(struct radeon_cs_parser *p);
        int (*copy_blit)(struct radeon_device *rdev,
@@ -535,6 +597,11 @@ struct radeon_asic {
        void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock);
        void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes);
        void (*set_clock_gating)(struct radeon_device *rdev, int enable);
+       int (*set_surface_reg)(struct radeon_device *rdev, int reg,
+                              uint32_t tiling_flags, uint32_t pitch,
+                              uint32_t offset, uint32_t obj_size);
+       int (*clear_surface_reg)(struct radeon_device *rdev, int reg);
+       void (*bandwidth_update)(struct radeon_device *rdev);
 };
 
 union radeon_asic_config {
@@ -566,6 +633,10 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
 int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
                              struct drm_file *filp);
 int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
+int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *filp);
+int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *filp);
 
 
 /*
@@ -584,6 +655,7 @@ struct radeon_device {
        int                             usec_timeout;
        enum radeon_pll_errata          pll_errata;
        int                             num_gb_pipes;
+       int                             num_z_pipes;
        int                             disp_priority;
        /* BIOS */
        uint8_t                         *bios;
@@ -594,17 +666,14 @@ struct radeon_device {
        struct radeon_object            *fbdev_robj;
        struct radeon_framebuffer       *fbdev_rfb;
        /* Register mmio */
-       unsigned long                   rmmio_base;
-       unsigned long                   rmmio_size;
+       resource_size_t                 rmmio_base;
+       resource_size_t                 rmmio_size;
        void                            *rmmio;
-       radeon_rreg_t                   mm_rreg;
-       radeon_wreg_t                   mm_wreg;
        radeon_rreg_t                   mc_rreg;
        radeon_wreg_t                   mc_wreg;
        radeon_rreg_t                   pll_rreg;
        radeon_wreg_t                   pll_wreg;
-       radeon_rreg_t                   pcie_rreg;
-       radeon_wreg_t                   pcie_wreg;
+       uint32_t                        pcie_reg_mask;
        radeon_rreg_t                   pciep_rreg;
        radeon_wreg_t                   pciep_wreg;
        struct radeon_clock             clock;
@@ -619,11 +688,14 @@ struct radeon_device {
        struct radeon_irq               irq;
        struct radeon_asic              *asic;
        struct radeon_gem               gem;
+       struct radeon_pm                pm;
        struct mutex                    cs_mutex;
        struct radeon_wb                wb;
        bool                            gpu_lockup;
        bool                            shutdown;
        bool                            suspend;
+       bool                            need_dma32;
+       struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES];
 };
 
 int radeon_device_init(struct radeon_device *rdev,
@@ -633,22 +705,42 @@ int radeon_device_init(struct radeon_device *rdev,
 void radeon_device_fini(struct radeon_device *rdev);
 int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
 
+static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+       if (reg < 0x10000)
+               return readl(((void __iomem *)rdev->rmmio) + reg);
+       else {
+               writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+               return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+       }
+}
+
+static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+       if (reg < 0x10000)
+               writel(v, ((void __iomem *)rdev->rmmio) + reg);
+       else {
+               writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
+               writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+       }
+}
+
 
 /*
  * Registers read & write functions.
  */
 #define RREG8(reg) readb(((void __iomem *)rdev->rmmio) + (reg))
 #define WREG8(reg, v) writeb(v, ((void __iomem *)rdev->rmmio) + (reg))
-#define RREG32(reg) rdev->mm_rreg(rdev, (reg))
-#define WREG32(reg, v) rdev->mm_wreg(rdev, (reg), (v))
+#define RREG32(reg) r100_mm_rreg(rdev, (reg))
+#define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v))
 #define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
 #define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
 #define RREG32_PLL(reg) rdev->pll_rreg(rdev, (reg))
 #define WREG32_PLL(reg, v) rdev->pll_wreg(rdev, (reg), (v))
 #define RREG32_MC(reg) rdev->mc_rreg(rdev, (reg))
 #define WREG32_MC(reg, v) rdev->mc_wreg(rdev, (reg), (v))
-#define RREG32_PCIE(reg) rdev->pcie_rreg(rdev, (reg))
-#define WREG32_PCIE(reg, v) rdev->pcie_wreg(rdev, (reg), (v))
+#define RREG32_PCIE(reg) rv370_pcie_rreg(rdev, (reg))
+#define WREG32_PCIE(reg, v) rv370_pcie_wreg(rdev, (reg), (v))
 #define WREG32_P(reg, val, mask)                               \
        do {                                                    \
                uint32_t tmp_ = RREG32(reg);                    \
@@ -664,12 +756,32 @@ int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
                WREG32_PLL(reg, tmp_);                          \
        } while (0)
 
+/*
+ * Indirect registers accessor
+ */
+static inline uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg)
+{
+       uint32_t r;
+
+       WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask));
+       r = RREG32(RADEON_PCIE_DATA);
+       return r;
+}
+
+static inline void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+{
+       WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask));
+       WREG32(RADEON_PCIE_DATA, (v));
+}
+
 void r100_pll_errata_after_index(struct radeon_device *rdev);
 
 
 /*
  * ASICs helpers.
  */
+#define ASIC_IS_RN50(rdev) ((rdev->pdev->device == 0x515e) || \
+                           (rdev->pdev->device == 0x5969))
 #define ASIC_IS_RV100(rdev) ((rdev->family == CHIP_RV100) || \
                (rdev->family == CHIP_RV200) || \
                (rdev->family == CHIP_RS100) || \
@@ -788,6 +900,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
 #define radeon_ring_start(rdev) (rdev)->asic->ring_start((rdev))
 #define radeon_irq_set(rdev) (rdev)->asic->irq_set((rdev))
 #define radeon_irq_process(rdev) (rdev)->asic->irq_process((rdev))
+#define radeon_get_vblank_counter(rdev, crtc) (rdev)->asic->get_vblank_counter((rdev), (crtc))
 #define radeon_fence_ring_emit(rdev, fence) (rdev)->asic->fence_ring_emit((rdev), (fence))
 #define radeon_copy_blit(rdev, s, d, np, f) (rdev)->asic->copy_blit((rdev), (s), (d), (np), (f))
 #define radeon_copy_dma(rdev, s, d, np, f) (rdev)->asic->copy_dma((rdev), (s), (d), (np), (f))
@@ -796,5 +909,8 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
 #define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
 #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l))
 #define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e))
+#define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s)))
+#define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r)))
+#define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev))
 
 #endif
index e2e567395df887fe19f85a3cea9b5ebf5cd81423..93d8f88893024088624e007e36ec2bb9b106eeed 100644 (file)
@@ -49,6 +49,7 @@ void r100_vram_info(struct radeon_device *rdev);
 int r100_gpu_reset(struct radeon_device *rdev);
 int r100_mc_init(struct radeon_device *rdev);
 void r100_mc_fini(struct radeon_device *rdev);
+u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc);
 int r100_wb_init(struct radeon_device *rdev);
 void r100_wb_fini(struct radeon_device *rdev);
 int r100_gart_enable(struct radeon_device *rdev);
@@ -71,6 +72,11 @@ int r100_copy_blit(struct radeon_device *rdev,
                   uint64_t dst_offset,
                   unsigned num_pages,
                   struct radeon_fence *fence);
+int r100_set_surface_reg(struct radeon_device *rdev, int reg,
+                        uint32_t tiling_flags, uint32_t pitch,
+                        uint32_t offset, uint32_t obj_size);
+int r100_clear_surface_reg(struct radeon_device *rdev, int reg);
+void r100_bandwidth_update(struct radeon_device *rdev);
 
 static struct radeon_asic r100_asic = {
        .init = &r100_init,
@@ -91,6 +97,7 @@ static struct radeon_asic r100_asic = {
        .ring_start = &r100_ring_start,
        .irq_set = &r100_irq_set,
        .irq_process = &r100_irq_process,
+       .get_vblank_counter = &r100_get_vblank_counter,
        .fence_ring_emit = &r100_fence_ring_emit,
        .cs_parse = &r100_cs_parse,
        .copy_blit = &r100_copy_blit,
@@ -100,6 +107,9 @@ static struct radeon_asic r100_asic = {
        .set_memory_clock = NULL,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &r100_bandwidth_update,
 };
 
 
@@ -128,6 +138,7 @@ int r300_copy_dma(struct radeon_device *rdev,
                  uint64_t dst_offset,
                  unsigned num_pages,
                  struct radeon_fence *fence);
+
 static struct radeon_asic r300_asic = {
        .init = &r300_init,
        .errata = &r300_errata,
@@ -147,6 +158,7 @@ static struct radeon_asic r300_asic = {
        .ring_start = &r300_ring_start,
        .irq_set = &r100_irq_set,
        .irq_process = &r100_irq_process,
+       .get_vblank_counter = &r100_get_vblank_counter,
        .fence_ring_emit = &r300_fence_ring_emit,
        .cs_parse = &r300_cs_parse,
        .copy_blit = &r100_copy_blit,
@@ -156,6 +168,9 @@ static struct radeon_asic r300_asic = {
        .set_memory_clock = NULL,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &r100_bandwidth_update,
 };
 
 /*
@@ -184,6 +199,7 @@ static struct radeon_asic r420_asic = {
        .ring_start = &r300_ring_start,
        .irq_set = &r100_irq_set,
        .irq_process = &r100_irq_process,
+       .get_vblank_counter = &r100_get_vblank_counter,
        .fence_ring_emit = &r300_fence_ring_emit,
        .cs_parse = &r300_cs_parse,
        .copy_blit = &r100_copy_blit,
@@ -193,6 +209,9 @@ static struct radeon_asic r420_asic = {
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_atom_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &r100_bandwidth_update,
 };
 
 
@@ -228,6 +247,7 @@ static struct radeon_asic rs400_asic = {
        .ring_start = &r300_ring_start,
        .irq_set = &r100_irq_set,
        .irq_process = &r100_irq_process,
+       .get_vblank_counter = &r100_get_vblank_counter,
        .fence_ring_emit = &r300_fence_ring_emit,
        .cs_parse = &r300_cs_parse,
        .copy_blit = &r100_copy_blit,
@@ -237,25 +257,32 @@ static struct radeon_asic rs400_asic = {
        .set_memory_clock = NULL,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_legacy_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &r100_bandwidth_update,
 };
 
 
 /*
  * rs600.
  */
+int rs600_init(struct radeon_device *dev);
 void rs600_errata(struct radeon_device *rdev);
 void rs600_vram_info(struct radeon_device *rdev);
 int rs600_mc_init(struct radeon_device *rdev);
 void rs600_mc_fini(struct radeon_device *rdev);
 int rs600_irq_set(struct radeon_device *rdev);
+int rs600_irq_process(struct radeon_device *rdev);
+u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc);
 int rs600_gart_enable(struct radeon_device *rdev);
 void rs600_gart_disable(struct radeon_device *rdev);
 void rs600_gart_tlb_flush(struct radeon_device *rdev);
 int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
 uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg);
 void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+void rs600_bandwidth_update(struct radeon_device *rdev);
 static struct radeon_asic rs600_asic = {
-       .init = &r300_init,
+       .init = &rs600_init,
        .errata = &rs600_errata,
        .vram_info = &rs600_vram_info,
        .gpu_reset = &r300_gpu_reset,
@@ -272,7 +299,8 @@ static struct radeon_asic rs600_asic = {
        .cp_disable = &r100_cp_disable,
        .ring_start = &r300_ring_start,
        .irq_set = &rs600_irq_set,
-       .irq_process = &r100_irq_process,
+       .irq_process = &rs600_irq_process,
+       .get_vblank_counter = &rs600_get_vblank_counter,
        .fence_ring_emit = &r300_fence_ring_emit,
        .cs_parse = &r300_cs_parse,
        .copy_blit = &r100_copy_blit,
@@ -282,6 +310,7 @@ static struct radeon_asic rs600_asic = {
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_atom_set_clock_gating,
+       .bandwidth_update = &rs600_bandwidth_update,
 };
 
 
@@ -294,8 +323,9 @@ int rs690_mc_init(struct radeon_device *rdev);
 void rs690_mc_fini(struct radeon_device *rdev);
 uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg);
 void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+void rs690_bandwidth_update(struct radeon_device *rdev);
 static struct radeon_asic rs690_asic = {
-       .init = &r300_init,
+       .init = &rs600_init,
        .errata = &rs690_errata,
        .vram_info = &rs690_vram_info,
        .gpu_reset = &r300_gpu_reset,
@@ -312,7 +342,8 @@ static struct radeon_asic rs690_asic = {
        .cp_disable = &r100_cp_disable,
        .ring_start = &r300_ring_start,
        .irq_set = &rs600_irq_set,
-       .irq_process = &r100_irq_process,
+       .irq_process = &rs600_irq_process,
+       .get_vblank_counter = &rs600_get_vblank_counter,
        .fence_ring_emit = &r300_fence_ring_emit,
        .cs_parse = &r300_cs_parse,
        .copy_blit = &r100_copy_blit,
@@ -322,6 +353,9 @@ static struct radeon_asic rs690_asic = {
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = NULL,
        .set_clock_gating = &radeon_atom_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &rs690_bandwidth_update,
 };
 
 
@@ -339,6 +373,7 @@ void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 void rv515_ring_start(struct radeon_device *rdev);
 uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
 void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+void rv515_bandwidth_update(struct radeon_device *rdev);
 static struct radeon_asic rv515_asic = {
        .init = &rv515_init,
        .errata = &rv515_errata,
@@ -356,8 +391,9 @@ static struct radeon_asic rv515_asic = {
        .cp_fini = &r100_cp_fini,
        .cp_disable = &r100_cp_disable,
        .ring_start = &rv515_ring_start,
-       .irq_set = &r100_irq_set,
-       .irq_process = &r100_irq_process,
+       .irq_set = &rs600_irq_set,
+       .irq_process = &rs600_irq_process,
+       .get_vblank_counter = &rs600_get_vblank_counter,
        .fence_ring_emit = &r300_fence_ring_emit,
        .cs_parse = &r300_cs_parse,
        .copy_blit = &r100_copy_blit,
@@ -367,6 +403,9 @@ static struct radeon_asic rv515_asic = {
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_atom_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &rv515_bandwidth_update,
 };
 
 
@@ -377,6 +416,7 @@ void r520_errata(struct radeon_device *rdev);
 void r520_vram_info(struct radeon_device *rdev);
 int r520_mc_init(struct radeon_device *rdev);
 void r520_mc_fini(struct radeon_device *rdev);
+void r520_bandwidth_update(struct radeon_device *rdev);
 static struct radeon_asic r520_asic = {
        .init = &rv515_init,
        .errata = &r520_errata,
@@ -394,8 +434,9 @@ static struct radeon_asic r520_asic = {
        .cp_fini = &r100_cp_fini,
        .cp_disable = &r100_cp_disable,
        .ring_start = &rv515_ring_start,
-       .irq_set = &r100_irq_set,
-       .irq_process = &r100_irq_process,
+       .irq_set = &rs600_irq_set,
+       .irq_process = &rs600_irq_process,
+       .get_vblank_counter = &rs600_get_vblank_counter,
        .fence_ring_emit = &r300_fence_ring_emit,
        .cs_parse = &r300_cs_parse,
        .copy_blit = &r100_copy_blit,
@@ -405,6 +446,9 @@ static struct radeon_asic r520_asic = {
        .set_memory_clock = &radeon_atom_set_memory_clock,
        .set_pcie_lanes = &rv370_set_pcie_lanes,
        .set_clock_gating = &radeon_atom_set_clock_gating,
+       .set_surface_reg = r100_set_surface_reg,
+       .clear_surface_reg = r100_clear_surface_reg,
+       .bandwidth_update = &r520_bandwidth_update,
 };
 
 /*
index 1f5a1a4909844c20d6ced2f9ba174ea5130eb278..fcfe5c02d744ab63eb13b085fcde591b35cae1d9 100644 (file)
@@ -103,7 +103,8 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device
 static bool radeon_atom_apply_quirks(struct drm_device *dev,
                                     uint32_t supported_device,
                                     int *connector_type,
-                                    struct radeon_i2c_bus_rec *i2c_bus)
+                                    struct radeon_i2c_bus_rec *i2c_bus,
+                                    uint8_t *line_mux)
 {
 
        /* Asus M2A-VM HDMI board lists the DVI port as HDMI */
@@ -127,8 +128,10 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
        if ((dev->pdev->device == 0x5653) &&
            (dev->pdev->subsystem_vendor == 0x1462) &&
            (dev->pdev->subsystem_device == 0x0291)) {
-               if (*connector_type == DRM_MODE_CONNECTOR_LVDS)
+               if (*connector_type == DRM_MODE_CONNECTOR_LVDS) {
                        i2c_bus->valid = false;
+                       *line_mux = 53;
+               }
        }
 
        /* Funky macbooks */
@@ -526,7 +529,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
 
                if (!radeon_atom_apply_quirks
                    (dev, (1 << i), &bios_connectors[i].connector_type,
-                    &bios_connectors[i].ddc_bus))
+                    &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux))
                        continue;
 
                bios_connectors[i].valid = true;
index c44403a2ca76d1d7558e919f94fa8d7cc1590354..2e938f7496fb0b58f355ae6906489a491309a9c0 100644 (file)
@@ -63,7 +63,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
                if (r) {
                        goto out_cleanup;
                }
-               r = radeon_copy_dma(rdev, saddr, daddr, size >> 14, fence);
+               r = radeon_copy_dma(rdev, saddr, daddr, size / 4096, fence);
                if (r) {
                        goto out_cleanup;
                }
@@ -88,7 +88,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
                if (r) {
                        goto out_cleanup;
                }
-               r = radeon_copy_blit(rdev, saddr, daddr, size >> 14, fence);
+               r = radeon_copy_blit(rdev, saddr, daddr, size / 4096, fence);
                if (r) {
                        goto out_cleanup;
                }
index afc4db280b949419d962aafdd2f5b93ed76328ff..2a027e00762afee4625a065eb9a1ab266a48c46c 100644 (file)
@@ -685,23 +685,15 @@ static const uint32_t default_tvdac_adj[CHIP_LAST] = {
        0x00780000,             /* rs480 */
 };
 
-static struct radeon_encoder_tv_dac
-    *radeon_legacy_get_tv_dac_info_from_table(struct radeon_device *rdev)
+static void radeon_legacy_get_tv_dac_info_from_table(struct radeon_device *rdev,
+                                                    struct radeon_encoder_tv_dac *tv_dac)
 {
-       struct radeon_encoder_tv_dac *tv_dac = NULL;
-
-       tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
-
-       if (!tv_dac)
-               return NULL;
-
        tv_dac->ps2_tvdac_adj = default_tvdac_adj[rdev->family];
        if ((rdev->flags & RADEON_IS_MOBILITY) && (rdev->family == CHIP_RV250))
                tv_dac->ps2_tvdac_adj = 0x00880000;
        tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;
        tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj;
-
-       return tv_dac;
+       return;
 }
 
 struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct
@@ -713,19 +705,18 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct
        uint16_t dac_info;
        uint8_t rev, bg, dac;
        struct radeon_encoder_tv_dac *tv_dac = NULL;
+       int found = 0;
+
+       tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
+       if (!tv_dac)
+               return NULL;
 
        if (rdev->bios == NULL)
-               return radeon_legacy_get_tv_dac_info_from_table(rdev);
+               goto out;
 
        /* first check TV table */
        dac_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
        if (dac_info) {
-               tv_dac =
-                   kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
-
-               if (!tv_dac)
-                       return NULL;
-
                rev = RBIOS8(dac_info + 0x3);
                if (rev > 4) {
                        bg = RBIOS8(dac_info + 0xc) & 0xf;
@@ -739,6 +730,7 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct
                        bg = RBIOS8(dac_info + 0x10) & 0xf;
                        dac = RBIOS8(dac_info + 0x11) & 0xf;
                        tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
+                       found = 1;
                } else if (rev > 1) {
                        bg = RBIOS8(dac_info + 0xc) & 0xf;
                        dac = (RBIOS8(dac_info + 0xc) >> 4) & 0xf;
@@ -751,22 +743,15 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct
                        bg = RBIOS8(dac_info + 0xe) & 0xf;
                        dac = (RBIOS8(dac_info + 0xe) >> 4) & 0xf;
                        tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
+                       found = 1;
                }
-
                tv_dac->tv_std = radeon_combios_get_tv_info(encoder);
-
-       } else {
+       }
+       if (!found) {
                /* then check CRT table */
                dac_info =
                    combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
                if (dac_info) {
-                       tv_dac =
-                           kzalloc(sizeof(struct radeon_encoder_tv_dac),
-                                   GFP_KERNEL);
-
-                       if (!tv_dac)
-                               return NULL;
-
                        rev = RBIOS8(dac_info) & 0x3;
                        if (rev < 2) {
                                bg = RBIOS8(dac_info + 0x3) & 0xf;
@@ -775,6 +760,7 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct
                                    (bg << 16) | (dac << 20);
                                tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;
                                tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj;
+                               found = 1;
                        } else {
                                bg = RBIOS8(dac_info + 0x4) & 0xf;
                                dac = RBIOS8(dac_info + 0x5) & 0xf;
@@ -782,13 +768,17 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct
                                    (bg << 16) | (dac << 20);
                                tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;
                                tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj;
+                               found = 1;
                        }
                } else {
                        DRM_INFO("No TV DAC info found in BIOS\n");
-                       return radeon_legacy_get_tv_dac_info_from_table(rdev);
                }
        }
 
+out:
+       if (!found) /* fallback to defaults */
+               radeon_legacy_get_tv_dac_info_from_table(rdev, tv_dac);
+
        return tv_dac;
 }
 
index d8356827ef17f8f7ae75a09868646c1d39bb4e4e..7a52c461145c6a48d1a7c76f13bf1f43f4513e90 100644 (file)
@@ -406,6 +406,15 @@ static void radeon_init_pipes(drm_radeon_private_t *dev_priv)
 {
        uint32_t gb_tile_config, gb_pipe_sel = 0;
 
+       if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) {
+               uint32_t z_pipe_sel = RADEON_READ(RV530_GB_PIPE_SELECT2);
+               if ((z_pipe_sel & 3) == 3)
+                       dev_priv->num_z_pipes = 2;
+               else
+                       dev_priv->num_z_pipes = 1;
+       } else
+               dev_priv->num_z_pipes = 1;
+
        /* RS4xx/RS6xx/R4xx/R5xx */
        if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) {
                gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT);
index b843f9bdfb14fc6928521fd4e7dc492379f99fa3..a169067efc4e5c3ccc87a57dfd1623d6be514035 100644 (file)
@@ -127,17 +127,23 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                                       sizeof(struct drm_radeon_cs_chunk))) {
                        return -EFAULT;
                }
+               p->chunks[i].length_dw = user_chunk.length_dw;
+               p->chunks[i].kdata = NULL;
                p->chunks[i].chunk_id = user_chunk.chunk_id;
+
                if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) {
                        p->chunk_relocs_idx = i;
                }
                if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_IB) {
                        p->chunk_ib_idx = i;
+                       /* zero length IB isn't useful */
+                       if (p->chunks[i].length_dw == 0)
+                               return -EINVAL;
                }
+
                p->chunks[i].length_dw = user_chunk.length_dw;
                cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data;
 
-               p->chunks[i].kdata = NULL;
                size = p->chunks[i].length_dw * sizeof(uint32_t);
                p->chunks[i].kdata = kzalloc(size, GFP_KERNEL);
                if (p->chunks[i].kdata == NULL) {
index 5232441f119b100077a828d2c13dc965054bfd63..b13c79e38bc020cd6ad41233eaa8968d6f45a6cf 100644 (file)
@@ -111,9 +111,11 @@ static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj,
 
        if (ASIC_IS_AVIVO(rdev))
                WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr);
-       else
+       else {
+               radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr;
                /* offset is from DISP(2)_BASE_ADDRESS */
-               WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, gpu_addr);
+               WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset);
+       }
 }
 
 int radeon_crtc_cursor_set(struct drm_crtc *crtc,
@@ -245,6 +247,9 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
                       (RADEON_CUR_LOCK
                        | ((xorigin ? 0 : x) << 16)
                        | (yorigin ? 0 : y)));
+               /* offset is from DISP(2)_BASE_ADDRESS */
+               WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset +
+                                                                     (yorigin * 256)));
        }
        radeon_lock_cursor(crtc, false);
 
index f30aa7274a54099913d85b7eeede05b1e9daafec..7693f7c67bd3a9ed4740744007cd65ace93936b3 100644 (file)
 #include "radeon_asic.h"
 #include "atom.h"
 
+/*
+ * Clear GPU surface registers.
+ */
+static void radeon_surface_init(struct radeon_device *rdev)
+{
+       /* FIXME: check this out */
+       if (rdev->family < CHIP_R600) {
+               int i;
+
+               for (i = 0; i < 8; i++) {
+                       WREG32(RADEON_SURFACE0_INFO +
+                              i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO),
+                              0);
+               }
+               /* enable surfaces */
+               WREG32(RADEON_SURFACE_CNTL, 0);
+       }
+}
+
 /*
  * GPU scratch registers helpers function.
  */
@@ -102,7 +121,7 @@ int radeon_mc_setup(struct radeon_device *rdev)
        if (rdev->mc.vram_location != 0xFFFFFFFFUL) {
                /* vram location was already setup try to put gtt after
                 * if it fits */
-               tmp = rdev->mc.vram_location + rdev->mc.vram_size;
+               tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size;
                tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1);
                if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) {
                        rdev->mc.gtt_location = tmp;
@@ -117,13 +136,13 @@ int radeon_mc_setup(struct radeon_device *rdev)
        } else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) {
                /* gtt location was already setup try to put vram before
                 * if it fits */
-               if (rdev->mc.vram_size < rdev->mc.gtt_location) {
+               if (rdev->mc.mc_vram_size < rdev->mc.gtt_location) {
                        rdev->mc.vram_location = 0;
                } else {
                        tmp = rdev->mc.gtt_location + rdev->mc.gtt_size;
-                       tmp += (rdev->mc.vram_size - 1);
-                       tmp &= ~(rdev->mc.vram_size - 1);
-                       if ((0xFFFFFFFFUL - tmp) >= rdev->mc.vram_size) {
+                       tmp += (rdev->mc.mc_vram_size - 1);
+                       tmp &= ~(rdev->mc.mc_vram_size - 1);
+                       if ((0xFFFFFFFFUL - tmp) >= rdev->mc.mc_vram_size) {
                                rdev->mc.vram_location = tmp;
                        } else {
                                printk(KERN_ERR "[drm] vram too big to fit "
@@ -133,12 +152,16 @@ int radeon_mc_setup(struct radeon_device *rdev)
                }
        } else {
                rdev->mc.vram_location = 0;
-               rdev->mc.gtt_location = rdev->mc.vram_size;
+               tmp = rdev->mc.mc_vram_size;
+               tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1);
+               rdev->mc.gtt_location = tmp;
        }
-       DRM_INFO("radeon: VRAM %uM\n", rdev->mc.vram_size >> 20);
+       DRM_INFO("radeon: VRAM %uM\n", rdev->mc.real_vram_size >> 20);
        DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n",
                 rdev->mc.vram_location,
-                rdev->mc.vram_location + rdev->mc.vram_size - 1);
+                rdev->mc.vram_location + rdev->mc.mc_vram_size - 1);
+       if (rdev->mc.real_vram_size != rdev->mc.mc_vram_size)
+               DRM_INFO("radeon: VRAM less than aperture workaround enabled\n");
        DRM_INFO("radeon: GTT %uM\n", rdev->mc.gtt_size >> 20);
        DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n",
                 rdev->mc.gtt_location,
@@ -202,25 +225,18 @@ void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 
 void radeon_register_accessor_init(struct radeon_device *rdev)
 {
-       rdev->mm_rreg = &r100_mm_rreg;
-       rdev->mm_wreg = &r100_mm_wreg;
        rdev->mc_rreg = &radeon_invalid_rreg;
        rdev->mc_wreg = &radeon_invalid_wreg;
        rdev->pll_rreg = &radeon_invalid_rreg;
        rdev->pll_wreg = &radeon_invalid_wreg;
-       rdev->pcie_rreg = &radeon_invalid_rreg;
-       rdev->pcie_wreg = &radeon_invalid_wreg;
        rdev->pciep_rreg = &radeon_invalid_rreg;
        rdev->pciep_wreg = &radeon_invalid_wreg;
 
        /* Don't change order as we are overridding accessor. */
        if (rdev->family < CHIP_RV515) {
-               rdev->pcie_rreg = &rv370_pcie_rreg;
-               rdev->pcie_wreg = &rv370_pcie_wreg;
-       }
-       if (rdev->family >= CHIP_RV515) {
-               rdev->pcie_rreg = &rv515_pcie_rreg;
-               rdev->pcie_wreg = &rv515_pcie_wreg;
+               rdev->pcie_reg_mask = 0xff;
+       } else {
+               rdev->pcie_reg_mask = 0x7ff;
        }
        /* FIXME: not sure here */
        if (rdev->family <= CHIP_R580) {
@@ -433,6 +449,7 @@ int radeon_device_init(struct radeon_device *rdev,
                       uint32_t flags)
 {
        int r, ret;
+       int dma_bits;
 
        DRM_INFO("radeon: Initializing kernel modesetting.\n");
        rdev->shutdown = false;
@@ -475,8 +492,20 @@ int radeon_device_init(struct radeon_device *rdev,
                return r;
        }
 
-       /* Report DMA addressing limitation */
-       r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(32));
+       /* set DMA mask + need_dma32 flags.
+        * PCIE - can handle 40-bits.
+        * IGP - can handle 40-bits (in theory)
+        * AGP - generally dma32 is safest
+        * PCI - only dma32
+        */
+       rdev->need_dma32 = false;
+       if (rdev->flags & RADEON_IS_AGP)
+               rdev->need_dma32 = true;
+       if (rdev->flags & RADEON_IS_PCI)
+               rdev->need_dma32 = true;
+
+       dma_bits = rdev->need_dma32 ? 32 : 40;
+       r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
        if (r) {
                printk(KERN_WARNING "radeon: No suitable DMA available.\n");
        }
@@ -496,6 +525,8 @@ int radeon_device_init(struct radeon_device *rdev,
        radeon_errata(rdev);
        /* Initialize scratch registers */
        radeon_scratch_init(rdev);
+       /* Initialize surface registers */
+       radeon_surface_init(rdev);
 
        /* TODO: disable VGA need to use VGA request */
        /* BIOS*/
@@ -527,27 +558,22 @@ int radeon_device_init(struct radeon_device *rdev,
                        radeon_combios_asic_init(rdev->ddev);
                }
        }
+       /* Initialize clocks */
+       r = radeon_clocks_init(rdev);
+       if (r) {
+               return r;
+       }
        /* Get vram informations */
        radeon_vram_info(rdev);
-       /* Device is severly broken if aper size > vram size.
-        * for RN50/M6/M7 - Novell bug 204882 ?
-        */
-       if (rdev->mc.vram_size < rdev->mc.aper_size) {
-               rdev->mc.aper_size = rdev->mc.vram_size;
-       }
+
        /* Add an MTRR for the VRAM */
        rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size,
                                      MTRR_TYPE_WRCOMB, 1);
        DRM_INFO("Detected VRAM RAM=%uM, BAR=%uM\n",
-                rdev->mc.vram_size >> 20,
+                rdev->mc.real_vram_size >> 20,
                 (unsigned)rdev->mc.aper_size >> 20);
        DRM_INFO("RAM width %dbits %cDR\n",
                 rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S');
-       /* Initialize clocks */
-       r = radeon_clocks_init(rdev);
-       if (r) {
-               return r;
-       }
        /* Initialize memory controller (also test AGP) */
        r = radeon_mc_init(rdev);
        if (r) {
@@ -604,12 +630,12 @@ int radeon_device_init(struct radeon_device *rdev,
        if (r) {
                return r;
        }
-       if (rdev->fbdev_rfb && rdev->fbdev_rfb->obj) {
-               rdev->fbdev_robj = rdev->fbdev_rfb->obj->driver_private;
-       }
        if (!ret) {
                DRM_INFO("radeon: kernel modesetting successfully initialized.\n");
        }
+       if (radeon_testing) {
+               radeon_test_moves(rdev);
+       }
        if (radeon_benchmarking) {
                radeon_benchmark(rdev);
        }
index 3efcf1a526be6b58ab9098f11f5db4a031e6ce49..a8fa1bb84cf79b72f51813f06e0ccf66e56c9dc1 100644 (file)
@@ -187,6 +187,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
 
        drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256);
        radeon_crtc->crtc_id = index;
+       rdev->mode_info.crtcs[index] = radeon_crtc;
 
        radeon_crtc->mode_set.crtc = &radeon_crtc->base;
        radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc + 1);
@@ -491,7 +492,11 @@ void radeon_compute_pll(struct radeon_pll *pll,
                                        tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div;
                                        current_freq = radeon_div(tmp, ref_div * post_div);
 
-                                       error = abs(current_freq - freq);
+                                       if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
+                                               error = freq - current_freq;
+                                               error = error < 0 ? 0xffffffff : error;
+                                       } else
+                                               error = abs(current_freq - freq);
                                        vco_diff = abs(vco - best_vco);
 
                                        if ((best_vco == 0 && error < best_error) ||
@@ -657,36 +662,51 @@ void radeon_modeset_fini(struct radeon_device *rdev)
        }
 }
 
-void radeon_init_disp_bandwidth(struct drm_device *dev)
+bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
+                               struct drm_display_mode *mode,
+                               struct drm_display_mode *adjusted_mode)
 {
-       struct radeon_device *rdev = dev->dev_private;
-       struct drm_display_mode *modes[2];
-       int pixel_bytes[2];
-       struct drm_crtc *crtc;
-
-       pixel_bytes[0] = pixel_bytes[1] = 0;
-       modes[0] = modes[1] = NULL;
-
-       list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-               struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct drm_encoder *encoder;
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+       struct radeon_encoder *radeon_encoder;
+       bool first = true;
 
-               if (crtc->enabled && crtc->fb) {
-                       modes[radeon_crtc->crtc_id] = &crtc->mode;
-                       pixel_bytes[radeon_crtc->crtc_id] = crtc->fb->bits_per_pixel / 8;
+       list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+               radeon_encoder = to_radeon_encoder(encoder);
+               if (encoder->crtc != crtc)
+                       continue;
+               if (first) {
+                       radeon_crtc->rmx_type = radeon_encoder->rmx_type;
+                       radeon_crtc->devices = radeon_encoder->devices;
+                       memcpy(&radeon_crtc->native_mode,
+                               &radeon_encoder->native_mode,
+                               sizeof(struct radeon_native_mode));
+                       first = false;
+               } else {
+                       if (radeon_crtc->rmx_type != radeon_encoder->rmx_type) {
+                               /* WARNING: Right now this can't happen but
+                                * in the future we need to check that scaling
+                                * are consistent accross different encoder
+                                * (ie all encoder can work with the same
+                                *  scaling).
+                                */
+                               DRM_ERROR("Scaling not consistent accross encoder.\n");
+                               return false;
+                       }
                }
        }
-
-       if (ASIC_IS_AVIVO(rdev)) {
-               radeon_init_disp_bw_avivo(dev,
-                                         modes[0],
-                                         pixel_bytes[0],
-                                         modes[1],
-                                         pixel_bytes[1]);
+       if (radeon_crtc->rmx_type != RMX_OFF) {
+               fixed20_12 a, b;
+               a.full = rfixed_const(crtc->mode.vdisplay);
+               b.full = rfixed_const(radeon_crtc->native_mode.panel_xres);
+               radeon_crtc->vsc.full = rfixed_div(a, b);
+               a.full = rfixed_const(crtc->mode.hdisplay);
+               b.full = rfixed_const(radeon_crtc->native_mode.panel_yres);
+               radeon_crtc->hsc.full = rfixed_div(a, b);
        } else {
-               radeon_init_disp_bw_legacy(dev,
-                                          modes[0],
-                                          pixel_bytes[0],
-                                          modes[1],
-                                          pixel_bytes[1]);
+               radeon_crtc->vsc.full = rfixed_const(1);
+               radeon_crtc->hsc.full = rfixed_const(1);
        }
+       return true;
 }
index 09c9fb9f621071c864997bdd286b04e0e8a26d99..0bd5879a49571b1aaf4ba07fc9de64128c8b90ab 100644 (file)
@@ -89,6 +89,7 @@ int radeon_agpmode = 0;
 int radeon_vram_limit = 0;
 int radeon_gart_size = 512; /* default gart size */
 int radeon_benchmarking = 0;
+int radeon_testing = 0;
 int radeon_connector_table = 0;
 #endif
 
@@ -117,6 +118,9 @@ module_param_named(gartsize, radeon_gart_size, int, 0600);
 MODULE_PARM_DESC(benchmark, "Run benchmark");
 module_param_named(benchmark, radeon_benchmarking, int, 0444);
 
+MODULE_PARM_DESC(test, "Run tests");
+module_param_named(test, radeon_testing, int, 0444);
+
 MODULE_PARM_DESC(connector_table, "Force connector table");
 module_param_named(connector_table, radeon_connector_table, int, 0444);
 #endif
@@ -314,6 +318,14 @@ static int __init radeon_init(void)
        driver = &driver_old;
        driver->num_ioctls = radeon_max_ioctl;
 #if defined(CONFIG_DRM_RADEON_KMS)
+#ifdef CONFIG_VGA_CONSOLE
+       if (vgacon_text_force() && radeon_modeset == -1) {
+               DRM_INFO("VGACON disable radeon kernel modesetting.\n");
+               driver = &driver_old;
+               driver->driver_features &= ~DRIVER_MODESET;
+               radeon_modeset = 0;
+       }
+#endif
        /* if enabled by default */
        if (radeon_modeset == -1) {
                DRM_INFO("radeon default to kernel modesetting.\n");
@@ -325,17 +337,8 @@ static int __init radeon_init(void)
                driver->driver_features |= DRIVER_MODESET;
                driver->num_ioctls = radeon_max_kms_ioctl;
        }
-
        /* if the vga console setting is enabled still
         * let modprobe override it */
-#ifdef CONFIG_VGA_CONSOLE
-       if (vgacon_text_force() && radeon_modeset == -1) {
-               DRM_INFO("VGACON disable radeon kernel modesetting.\n");
-               driver = &driver_old;
-               driver->driver_features &= ~DRIVER_MODESET;
-               radeon_modeset = 0;
-       }
-#endif
 #endif
        return drm_init(driver);
 }
@@ -345,7 +348,7 @@ static void __exit radeon_exit(void)
        drm_exit(driver);
 }
 
-late_initcall(radeon_init);
+module_init(radeon_init);
 module_exit(radeon_exit);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
index 127d0456f628bf87ed469e5a451347c5d981f5b4..6fa32dac4e978e0857a8de1c8a347e630a1996a3 100644 (file)
  * 1.28- Add support for VBL on CRTC2
  * 1.29- R500 3D cmd buffer support
  * 1.30- Add support for occlusion queries
+ * 1.31- Add support for num Z pipes from GET_PARAM
  */
 #define DRIVER_MAJOR           1
-#define DRIVER_MINOR           30
+#define DRIVER_MINOR           31
 #define DRIVER_PATCHLEVEL      0
 
 /*
@@ -143,6 +144,7 @@ enum radeon_family {
        CHIP_RV635,
        CHIP_RV670,
        CHIP_RS780,
+       CHIP_RS880,
        CHIP_RV770,
        CHIP_RV730,
        CHIP_RV710,
@@ -328,6 +330,7 @@ typedef struct drm_radeon_private {
        resource_size_t fb_aper_offset;
 
        int num_gb_pipes;
+       int num_z_pipes;
        int track_flush;
        drm_local_map_t *mmio;
 
@@ -688,6 +691,7 @@ extern void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pciga
 
 /* pipe config regs */
 #define R400_GB_PIPE_SELECT             0x402c
+#define RV530_GB_PIPE_SELECT2           0x4124
 #define R500_DYN_SCLK_PWMEM_PIPE        0x000d /* PLL */
 #define R300_GB_TILE_CONFIG             0x4018
 #       define R300_ENABLE_TILING       (1 << 0)
index c8ef0d14ffab0190d1e9bb7adce7d6fef619f0f3..0a92706eac191597839972389248788ebebadb54 100644 (file)
@@ -154,7 +154,6 @@ void radeon_rmx_mode_fixup(struct drm_encoder *encoder,
 
        if (mode->hdisplay < native_mode->panel_xres ||
            mode->vdisplay < native_mode->panel_yres) {
-               radeon_encoder->flags |= RADEON_USE_RMX;
                if (ASIC_IS_AVIVO(rdev)) {
                        adjusted_mode->hdisplay = native_mode->panel_xres;
                        adjusted_mode->vdisplay = native_mode->panel_yres;
@@ -197,15 +196,13 @@ void radeon_rmx_mode_fixup(struct drm_encoder *encoder,
        }
 }
 
+
 static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
                                   struct drm_display_mode *mode,
                                   struct drm_display_mode *adjusted_mode)
 {
-
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 
-       radeon_encoder->flags &= ~RADEON_USE_RMX;
-
        drm_mode_set_crtcinfo(adjusted_mode, 0);
 
        if (radeon_encoder->rmx_type != RMX_OFF)
@@ -808,234 +805,6 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action)
 
 }
 
-static void atom_rv515_force_tv_scaler(struct radeon_device *rdev)
-{
-
-       WREG32(0x659C, 0x0);
-       WREG32(0x6594, 0x705);
-       WREG32(0x65A4, 0x10001);
-       WREG32(0x65D8, 0x0);
-       WREG32(0x65B0, 0x0);
-       WREG32(0x65C0, 0x0);
-       WREG32(0x65D4, 0x0);
-       WREG32(0x6578, 0x0);
-       WREG32(0x657C, 0x841880A8);
-       WREG32(0x6578, 0x1);
-       WREG32(0x657C, 0x84208680);
-       WREG32(0x6578, 0x2);
-       WREG32(0x657C, 0xBFF880B0);
-       WREG32(0x6578, 0x100);
-       WREG32(0x657C, 0x83D88088);
-       WREG32(0x6578, 0x101);
-       WREG32(0x657C, 0x84608680);
-       WREG32(0x6578, 0x102);
-       WREG32(0x657C, 0xBFF080D0);
-       WREG32(0x6578, 0x200);
-       WREG32(0x657C, 0x83988068);
-       WREG32(0x6578, 0x201);
-       WREG32(0x657C, 0x84A08680);
-       WREG32(0x6578, 0x202);
-       WREG32(0x657C, 0xBFF080F8);
-       WREG32(0x6578, 0x300);
-       WREG32(0x657C, 0x83588058);
-       WREG32(0x6578, 0x301);
-       WREG32(0x657C, 0x84E08660);
-       WREG32(0x6578, 0x302);
-       WREG32(0x657C, 0xBFF88120);
-       WREG32(0x6578, 0x400);
-       WREG32(0x657C, 0x83188040);
-       WREG32(0x6578, 0x401);
-       WREG32(0x657C, 0x85008660);
-       WREG32(0x6578, 0x402);
-       WREG32(0x657C, 0xBFF88150);
-       WREG32(0x6578, 0x500);
-       WREG32(0x657C, 0x82D88030);
-       WREG32(0x6578, 0x501);
-       WREG32(0x657C, 0x85408640);
-       WREG32(0x6578, 0x502);
-       WREG32(0x657C, 0xBFF88180);
-       WREG32(0x6578, 0x600);
-       WREG32(0x657C, 0x82A08018);
-       WREG32(0x6578, 0x601);
-       WREG32(0x657C, 0x85808620);
-       WREG32(0x6578, 0x602);
-       WREG32(0x657C, 0xBFF081B8);
-       WREG32(0x6578, 0x700);
-       WREG32(0x657C, 0x82608010);
-       WREG32(0x6578, 0x701);
-       WREG32(0x657C, 0x85A08600);
-       WREG32(0x6578, 0x702);
-       WREG32(0x657C, 0x800081F0);
-       WREG32(0x6578, 0x800);
-       WREG32(0x657C, 0x8228BFF8);
-       WREG32(0x6578, 0x801);
-       WREG32(0x657C, 0x85E085E0);
-       WREG32(0x6578, 0x802);
-       WREG32(0x657C, 0xBFF88228);
-       WREG32(0x6578, 0x10000);
-       WREG32(0x657C, 0x82A8BF00);
-       WREG32(0x6578, 0x10001);
-       WREG32(0x657C, 0x82A08CC0);
-       WREG32(0x6578, 0x10002);
-       WREG32(0x657C, 0x8008BEF8);
-       WREG32(0x6578, 0x10100);
-       WREG32(0x657C, 0x81F0BF28);
-       WREG32(0x6578, 0x10101);
-       WREG32(0x657C, 0x83608CA0);
-       WREG32(0x6578, 0x10102);
-       WREG32(0x657C, 0x8018BED0);
-       WREG32(0x6578, 0x10200);
-       WREG32(0x657C, 0x8148BF38);
-       WREG32(0x6578, 0x10201);
-       WREG32(0x657C, 0x84408C80);
-       WREG32(0x6578, 0x10202);
-       WREG32(0x657C, 0x8008BEB8);
-       WREG32(0x6578, 0x10300);
-       WREG32(0x657C, 0x80B0BF78);
-       WREG32(0x6578, 0x10301);
-       WREG32(0x657C, 0x85008C20);
-       WREG32(0x6578, 0x10302);
-       WREG32(0x657C, 0x8020BEA0);
-       WREG32(0x6578, 0x10400);
-       WREG32(0x657C, 0x8028BF90);
-       WREG32(0x6578, 0x10401);
-       WREG32(0x657C, 0x85E08BC0);
-       WREG32(0x6578, 0x10402);
-       WREG32(0x657C, 0x8018BE90);
-       WREG32(0x6578, 0x10500);
-       WREG32(0x657C, 0xBFB8BFB0);
-       WREG32(0x6578, 0x10501);
-       WREG32(0x657C, 0x86C08B40);
-       WREG32(0x6578, 0x10502);
-       WREG32(0x657C, 0x8010BE90);
-       WREG32(0x6578, 0x10600);
-       WREG32(0x657C, 0xBF58BFC8);
-       WREG32(0x6578, 0x10601);
-       WREG32(0x657C, 0x87A08AA0);
-       WREG32(0x6578, 0x10602);
-       WREG32(0x657C, 0x8010BE98);
-       WREG32(0x6578, 0x10700);
-       WREG32(0x657C, 0xBF10BFF0);
-       WREG32(0x6578, 0x10701);
-       WREG32(0x657C, 0x886089E0);
-       WREG32(0x6578, 0x10702);
-       WREG32(0x657C, 0x8018BEB0);
-       WREG32(0x6578, 0x10800);
-       WREG32(0x657C, 0xBED8BFE8);
-       WREG32(0x6578, 0x10801);
-       WREG32(0x657C, 0x89408940);
-       WREG32(0x6578, 0x10802);
-       WREG32(0x657C, 0xBFE8BED8);
-       WREG32(0x6578, 0x20000);
-       WREG32(0x657C, 0x80008000);
-       WREG32(0x6578, 0x20001);
-       WREG32(0x657C, 0x90008000);
-       WREG32(0x6578, 0x20002);
-       WREG32(0x657C, 0x80008000);
-       WREG32(0x6578, 0x20003);
-       WREG32(0x657C, 0x80008000);
-       WREG32(0x6578, 0x20100);
-       WREG32(0x657C, 0x80108000);
-       WREG32(0x6578, 0x20101);
-       WREG32(0x657C, 0x8FE0BF70);
-       WREG32(0x6578, 0x20102);
-       WREG32(0x657C, 0xBFE880C0);
-       WREG32(0x6578, 0x20103);
-       WREG32(0x657C, 0x80008000);
-       WREG32(0x6578, 0x20200);
-       WREG32(0x657C, 0x8018BFF8);
-       WREG32(0x6578, 0x20201);
-       WREG32(0x657C, 0x8F80BF08);
-       WREG32(0x6578, 0x20202);
-       WREG32(0x657C, 0xBFD081A0);
-       WREG32(0x6578, 0x20203);
-       WREG32(0x657C, 0xBFF88000);
-       WREG32(0x6578, 0x20300);
-       WREG32(0x657C, 0x80188000);
-       WREG32(0x6578, 0x20301);
-       WREG32(0x657C, 0x8EE0BEC0);
-       WREG32(0x6578, 0x20302);
-       WREG32(0x657C, 0xBFB082A0);
-       WREG32(0x6578, 0x20303);
-       WREG32(0x657C, 0x80008000);
-       WREG32(0x6578, 0x20400);
-       WREG32(0x657C, 0x80188000);
-       WREG32(0x6578, 0x20401);
-       WREG32(0x657C, 0x8E00BEA0);
-       WREG32(0x6578, 0x20402);
-       WREG32(0x657C, 0xBF8883C0);
-       WREG32(0x6578, 0x20403);
-       WREG32(0x657C, 0x80008000);
-       WREG32(0x6578, 0x20500);
-       WREG32(0x657C, 0x80188000);
-       WREG32(0x6578, 0x20501);
-       WREG32(0x657C, 0x8D00BE90);
-       WREG32(0x6578, 0x20502);
-       WREG32(0x657C, 0xBF588500);
-       WREG32(0x6578, 0x20503);
-       WREG32(0x657C, 0x80008008);
-       WREG32(0x6578, 0x20600);
-       WREG32(0x657C, 0x80188000);
-       WREG32(0x6578, 0x20601);
-       WREG32(0x657C, 0x8BC0BE98);
-       WREG32(0x6578, 0x20602);
-       WREG32(0x657C, 0xBF308660);
-       WREG32(0x6578, 0x20603);
-       WREG32(0x657C, 0x80008008);
-       WREG32(0x6578, 0x20700);
-       WREG32(0x657C, 0x80108000);
-       WREG32(0x6578, 0x20701);
-       WREG32(0x657C, 0x8A80BEB0);
-       WREG32(0x6578, 0x20702);
-       WREG32(0x657C, 0xBF0087C0);
-       WREG32(0x6578, 0x20703);
-       WREG32(0x657C, 0x80008008);
-       WREG32(0x6578, 0x20800);
-       WREG32(0x657C, 0x80108000);
-       WREG32(0x6578, 0x20801);
-       WREG32(0x657C, 0x8920BED0);
-       WREG32(0x6578, 0x20802);
-       WREG32(0x657C, 0xBED08920);
-       WREG32(0x6578, 0x20803);
-       WREG32(0x657C, 0x80008010);
-       WREG32(0x6578, 0x30000);
-       WREG32(0x657C, 0x90008000);
-       WREG32(0x6578, 0x30001);
-       WREG32(0x657C, 0x80008000);
-       WREG32(0x6578, 0x30100);
-       WREG32(0x657C, 0x8FE0BF90);
-       WREG32(0x6578, 0x30101);
-       WREG32(0x657C, 0xBFF880A0);
-       WREG32(0x6578, 0x30200);
-       WREG32(0x657C, 0x8F60BF40);
-       WREG32(0x6578, 0x30201);
-       WREG32(0x657C, 0xBFE88180);
-       WREG32(0x6578, 0x30300);
-       WREG32(0x657C, 0x8EC0BF00);
-       WREG32(0x6578, 0x30301);
-       WREG32(0x657C, 0xBFC88280);
-       WREG32(0x6578, 0x30400);
-       WREG32(0x657C, 0x8DE0BEE0);
-       WREG32(0x6578, 0x30401);
-       WREG32(0x657C, 0xBFA083A0);
-       WREG32(0x6578, 0x30500);
-       WREG32(0x657C, 0x8CE0BED0);
-       WREG32(0x6578, 0x30501);
-       WREG32(0x657C, 0xBF7884E0);
-       WREG32(0x6578, 0x30600);
-       WREG32(0x657C, 0x8BA0BED8);
-       WREG32(0x6578, 0x30601);
-       WREG32(0x657C, 0xBF508640);
-       WREG32(0x6578, 0x30700);
-       WREG32(0x657C, 0x8A60BEE8);
-       WREG32(0x6578, 0x30701);
-       WREG32(0x657C, 0xBF2087A0);
-       WREG32(0x6578, 0x30800);
-       WREG32(0x657C, 0x8900BF00);
-       WREG32(0x6578, 0x30801);
-       WREG32(0x657C, 0xBF008900);
-}
-
 static void
 atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
 {
@@ -1073,129 +842,6 @@ atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
        WREG32(reg, temp);
 }
 
-static void
-atombios_overscan_setup(struct drm_encoder *encoder,
-                       struct drm_display_mode *mode,
-                       struct drm_display_mode *adjusted_mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-       SET_CRTC_OVERSCAN_PS_ALLOCATION args;
-       int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
-
-       memset(&args, 0, sizeof(args));
-
-       args.usOverscanRight = 0;
-       args.usOverscanLeft = 0;
-       args.usOverscanBottom = 0;
-       args.usOverscanTop = 0;
-       args.ucCRTC = radeon_crtc->crtc_id;
-
-       if (radeon_encoder->flags & RADEON_USE_RMX) {
-               if (radeon_encoder->rmx_type == RMX_FULL) {
-                       args.usOverscanRight = 0;
-                       args.usOverscanLeft = 0;
-                       args.usOverscanBottom = 0;
-                       args.usOverscanTop = 0;
-               } else if (radeon_encoder->rmx_type == RMX_CENTER) {
-                       args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
-                       args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
-                       args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
-                       args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
-               } else if (radeon_encoder->rmx_type == RMX_ASPECT) {
-                       int a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay;
-                       int a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay;
-
-                       if (a1 > a2) {
-                               args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
-                               args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
-                       } else if (a2 > a1) {
-                               args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
-                               args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
-                       }
-               }
-       }
-
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-}
-
-static void
-atombios_scaler_setup(struct drm_encoder *encoder)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
-       ENABLE_SCALER_PS_ALLOCATION args;
-       int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
-       /* fixme - fill in enc_priv for atom dac */
-       enum radeon_tv_std tv_std = TV_STD_NTSC;
-
-       if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)
-               return;
-
-       memset(&args, 0, sizeof(args));
-
-       args.ucScaler = radeon_crtc->crtc_id;
-
-       if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) {
-               switch (tv_std) {
-               case TV_STD_NTSC:
-               default:
-                       args.ucTVStandard = ATOM_TV_NTSC;
-                       break;
-               case TV_STD_PAL:
-                       args.ucTVStandard = ATOM_TV_PAL;
-                       break;
-               case TV_STD_PAL_M:
-                       args.ucTVStandard = ATOM_TV_PALM;
-                       break;
-               case TV_STD_PAL_60:
-                       args.ucTVStandard = ATOM_TV_PAL60;
-                       break;
-               case TV_STD_NTSC_J:
-                       args.ucTVStandard = ATOM_TV_NTSCJ;
-                       break;
-               case TV_STD_SCART_PAL:
-                       args.ucTVStandard = ATOM_TV_PAL; /* ??? */
-                       break;
-               case TV_STD_SECAM:
-                       args.ucTVStandard = ATOM_TV_SECAM;
-                       break;
-               case TV_STD_PAL_CN:
-                       args.ucTVStandard = ATOM_TV_PALCN;
-                       break;
-               }
-               args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
-       } else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) {
-               args.ucTVStandard = ATOM_TV_CV;
-               args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
-       } else if (radeon_encoder->flags & RADEON_USE_RMX) {
-               if (radeon_encoder->rmx_type == RMX_FULL)
-                       args.ucEnable = ATOM_SCALER_EXPANSION;
-               else if (radeon_encoder->rmx_type == RMX_CENTER)
-                       args.ucEnable = ATOM_SCALER_CENTER;
-               else if (radeon_encoder->rmx_type == RMX_ASPECT)
-                       args.ucEnable = ATOM_SCALER_EXPANSION;
-       } else {
-               if (ASIC_IS_AVIVO(rdev))
-                       args.ucEnable = ATOM_SCALER_DISABLE;
-               else
-                       args.ucEnable = ATOM_SCALER_CENTER;
-       }
-
-       atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
-
-       if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)
-           && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) {
-               atom_rv515_force_tv_scaler(rdev);
-       }
-
-}
-
 static void
 radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
@@ -1448,8 +1094,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
        radeon_encoder->pixel_clock = adjusted_mode->clock;
 
        radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
-       atombios_overscan_setup(encoder, mode, adjusted_mode);
-       atombios_scaler_setup(encoder);
        atombios_set_encoder_crtc_source(encoder);
 
        if (ASIC_IS_AVIVO(rdev)) {
@@ -1667,6 +1311,7 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su
 
        radeon_encoder->encoder_id = encoder_id;
        radeon_encoder->devices = supported_device;
+       radeon_encoder->rmx_type = RMX_OFF;
 
        switch (radeon_encoder->encoder_id) {
        case ENCODER_OBJECT_ID_INTERNAL_LVDS:
index fa86d398945e237c30e71250627626d9b20bbf74..ec383edf5f38acb3370fb570a5553e792e45604f 100644 (file)
@@ -101,9 +101,10 @@ static int radeonfb_setcolreg(unsigned regno,
                                break;
                        case 24:
                        case 32:
-                               fb->pseudo_palette[regno] = ((red & 0xff00) << 8) |
-                                       (green & 0xff00) |
-                                       ((blue  & 0xff00) >> 8);
+                               fb->pseudo_palette[regno] =
+                                       (((red >> 8) & 0xff) << info->var.red.offset) |
+                                       (((green >> 8) & 0xff) << info->var.green.offset) |
+                                       (((blue >> 8) & 0xff) << info->var.blue.offset);
                                break;
                        }
                }
@@ -154,6 +155,7 @@ static int radeonfb_check_var(struct fb_var_screeninfo *var,
                var->transp.length = 0;
                var->transp.offset = 0;
                break;
+#ifdef __LITTLE_ENDIAN
        case 15:
                var->red.offset = 10;
                var->green.offset = 5;
@@ -194,6 +196,28 @@ static int radeonfb_check_var(struct fb_var_screeninfo *var,
                var->transp.length = 8;
                var->transp.offset = 24;
                break;
+#else
+       case 24:
+               var->red.offset = 8;
+               var->green.offset = 16;
+               var->blue.offset = 24;
+               var->red.length = 8;
+               var->green.length = 8;
+               var->blue.length = 8;
+               var->transp.length = 0;
+               var->transp.offset = 0;
+               break;
+       case 32:
+               var->red.offset = 8;
+               var->green.offset = 16;
+               var->blue.offset = 24;
+               var->red.length = 8;
+               var->green.length = 8;
+               var->blue.length = 8;
+               var->transp.length = 8;
+               var->transp.offset = 0;
+               break;
+#endif
        default:
                return -EINVAL;
        }
@@ -447,10 +471,10 @@ static struct notifier_block paniced = {
        .notifier_call = radeonfb_panic,
 };
 
-static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp)
+static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
 {
        int aligned = width;
-       int align_large = (ASIC_IS_AVIVO(rdev));
+       int align_large = (ASIC_IS_AVIVO(rdev)) || tiled;
        int pitch_mask = 0;
 
        switch (bpp / 8) {
@@ -478,36 +502,42 @@ int radeonfb_create(struct radeon_device *rdev,
 {
        struct fb_info *info;
        struct radeon_fb_device *rfbdev;
-       struct drm_framebuffer *fb;
+       struct drm_framebuffer *fb = NULL;
        struct radeon_framebuffer *rfb;
        struct drm_mode_fb_cmd mode_cmd;
        struct drm_gem_object *gobj = NULL;
        struct radeon_object *robj = NULL;
        struct device *device = &rdev->pdev->dev;
        int size, aligned_size, ret;
+       u64 fb_gpuaddr;
        void *fbptr = NULL;
+       unsigned long tmp;
+       bool fb_tiled = false; /* useful for testing */
 
        mode_cmd.width = surface_width;
        mode_cmd.height = surface_height;
        mode_cmd.bpp = 32;
        /* need to align pitch with crtc limits */
-       mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp) * ((mode_cmd.bpp + 1) / 8);
+       mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8);
        mode_cmd.depth = 24;
 
        size = mode_cmd.pitch * mode_cmd.height;
        aligned_size = ALIGN(size, PAGE_SIZE);
 
        ret = radeon_gem_object_create(rdev, aligned_size, 0,
-                                      RADEON_GEM_DOMAIN_VRAM,
-                                      false, ttm_bo_type_kernel,
-                                      false, &gobj);
+                       RADEON_GEM_DOMAIN_VRAM,
+                       false, ttm_bo_type_kernel,
+                       false, &gobj);
        if (ret) {
-               printk(KERN_ERR "failed to allocate framebuffer\n");
+               printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n",
+                      surface_width, surface_height);
                ret = -ENOMEM;
                goto out;
        }
        robj = gobj->driver_private;
 
+       if (fb_tiled)
+               radeon_object_set_tiling_flags(robj, RADEON_TILING_MACRO|RADEON_TILING_SURFACE, mode_cmd.pitch);
        mutex_lock(&rdev->ddev->struct_mutex);
        fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj);
        if (fb == NULL) {
@@ -515,12 +545,19 @@ int radeonfb_create(struct radeon_device *rdev,
                ret = -ENOMEM;
                goto out_unref;
        }
+       ret = radeon_object_pin(robj, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr);
+       if (ret) {
+               printk(KERN_ERR "failed to pin framebuffer\n");
+               ret = -ENOMEM;
+               goto out_unref;
+       }
 
        list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list);
 
        rfb = to_radeon_framebuffer(fb);
        *rfb_p = rfb;
        rdev->fbdev_rfb = rfb;
+       rdev->fbdev_robj = robj;
 
        info = framebuffer_alloc(sizeof(struct radeon_fb_device), device);
        if (info == NULL) {
@@ -529,11 +566,16 @@ int radeonfb_create(struct radeon_device *rdev,
        }
        rfbdev = info->par;
 
+       if (fb_tiled)
+               radeon_object_check_tiling(robj, 0, 0);
+
        ret = radeon_object_kmap(robj, &fbptr);
        if (ret) {
                goto out_unref;
        }
 
+       memset_io(fbptr, 0, aligned_size);
+
        strcpy(info->fix.id, "radeondrmfb");
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.visual = FB_VISUAL_TRUECOLOR;
@@ -541,13 +583,13 @@ int radeonfb_create(struct radeon_device *rdev,
        info->fix.xpanstep = 1; /* doing it in hw */
        info->fix.ypanstep = 1; /* doing it in hw */
        info->fix.ywrapstep = 0;
-       info->fix.accel = FB_ACCEL_I830;
+       info->fix.accel = FB_ACCEL_NONE;
        info->fix.type_aux = 0;
        info->flags = FBINFO_DEFAULT;
        info->fbops = &radeonfb_ops;
        info->fix.line_length = fb->pitch;
-       info->screen_base = fbptr;
-       info->fix.smem_start = (unsigned long)fbptr;
+       tmp = fb_gpuaddr - rdev->mc.vram_location;
+       info->fix.smem_start = rdev->mc.aper_base + tmp;
        info->fix.smem_len = size;
        info->screen_base = fbptr;
        info->screen_size = size;
@@ -562,8 +604,13 @@ int radeonfb_create(struct radeon_device *rdev,
        info->var.width = -1;
        info->var.xres = fb_width;
        info->var.yres = fb_height;
-       info->fix.mmio_start = pci_resource_start(rdev->pdev, 2);
-       info->fix.mmio_len = pci_resource_len(rdev->pdev, 2);
+
+       /* setup aperture base/size for vesafb takeover */
+       info->aperture_base = rdev->ddev->mode_config.fb_base;
+       info->aperture_size = rdev->mc.real_vram_size;
+
+       info->fix.mmio_start = 0;
+       info->fix.mmio_len = 0;
        info->pixmap.size = 64*1024;
        info->pixmap.buf_align = 8;
        info->pixmap.access_align = 32;
@@ -590,6 +637,7 @@ int radeonfb_create(struct radeon_device *rdev,
                info->var.transp.offset = 0;
                info->var.transp.length = 0;
                break;
+#ifdef __LITTLE_ENDIAN
        case 15:
                info->var.red.offset = 10;
                info->var.green.offset = 5;
@@ -629,7 +677,29 @@ int radeonfb_create(struct radeon_device *rdev,
                info->var.transp.offset = 24;
                info->var.transp.length = 8;
                break;
+#else
+       case 24:
+               info->var.red.offset = 8;
+               info->var.green.offset = 16;
+               info->var.blue.offset = 24;
+               info->var.red.length = 8;
+               info->var.green.length = 8;
+               info->var.blue.length = 8;
+               info->var.transp.offset = 0;
+               info->var.transp.length = 0;
+               break;
+       case 32:
+               info->var.red.offset = 8;
+               info->var.green.offset = 16;
+               info->var.blue.offset = 24;
+               info->var.red.length = 8;
+               info->var.green.length = 8;
+               info->var.blue.length = 8;
+               info->var.transp.offset = 0;
+               info->var.transp.length = 8;
+               break;
        default:
+#endif
                break;
        }
 
@@ -644,7 +714,7 @@ out_unref:
        if (robj) {
                radeon_object_kunmap(robj);
        }
-       if (ret) {
+       if (fb && ret) {
                list_del(&fb->filp_head);
                drm_gem_object_unreference(gobj);
                drm_framebuffer_cleanup(fb);
@@ -813,6 +883,7 @@ int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
                robj = rfb->obj->driver_private;
                unregister_framebuffer(info);
                radeon_object_kunmap(robj);
+               radeon_object_unpin(robj);
                framebuffer_release(info);
        }
 
index 96afbf5ae2ad7601b1667d54b49c6bba653b2914..b4e48dd2e859c056d8280121f44c2e376070747f 100644 (file)
@@ -195,7 +195,7 @@ retry:
                r = wait_event_interruptible_timeout(rdev->fence_drv.queue,
                                radeon_fence_signaled(fence), timeout);
                if (unlikely(r == -ERESTARTSYS)) {
-                       return -ERESTART;
+                       return -EBUSY;
                }
        } else {
                r = wait_event_timeout(rdev->fence_drv.queue,
index d343a15316ec672cfd3444377d4d1b426994b9a9..2977539880fb6d29b2699465c007c3617d78ec07 100644 (file)
@@ -177,7 +177,7 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
                        return -ENOMEM;
                }
                rdev->gart.pages[p] = pagelist[i];
-               page_base = (uint32_t)rdev->gart.pages_addr[p];
+               page_base = rdev->gart.pages_addr[p];
                for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) {
                        radeon_gart_set_page(rdev, t, page_base);
                        page_base += 4096;
index eb516034235deec6332c00f0f543e0e538fe791b..d880edf254dbad63a73e99ee7c05de40757e9ecc 100644 (file)
@@ -157,9 +157,9 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
        struct radeon_device *rdev = dev->dev_private;
        struct drm_radeon_gem_info *args = data;
 
-       args->vram_size = rdev->mc.vram_size;
+       args->vram_size = rdev->mc.real_vram_size;
        /* FIXME: report somethings that makes sense */
-       args->vram_visible = rdev->mc.vram_size - (4 * 1024 * 1024);
+       args->vram_visible = rdev->mc.real_vram_size - (4 * 1024 * 1024);
        args->gart_size = rdev->mc.gtt_size;
        return 0;
 }
@@ -262,8 +262,34 @@ int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
 int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
                          struct drm_file *filp)
 {
-       /* FIXME: implement */
-       return 0;
+       struct drm_radeon_gem_busy *args = data;
+       struct drm_gem_object *gobj;
+       struct radeon_object *robj;
+       int r;
+       uint32_t cur_placement;
+
+       gobj = drm_gem_object_lookup(dev, filp, args->handle);
+       if (gobj == NULL) {
+               return -EINVAL;
+       }
+       robj = gobj->driver_private;
+       r = radeon_object_busy_domain(robj, &cur_placement);
+       switch (cur_placement) {
+       case TTM_PL_VRAM:
+               args->domain = RADEON_GEM_DOMAIN_VRAM;
+               break;
+       case TTM_PL_TT:
+               args->domain = RADEON_GEM_DOMAIN_GTT;
+               break;
+       case TTM_PL_SYSTEM:
+               args->domain = RADEON_GEM_DOMAIN_CPU;
+       default:
+               break;
+       }
+       mutex_lock(&dev->struct_mutex);
+       drm_gem_object_unreference(gobj);
+       mutex_unlock(&dev->struct_mutex);
+       return r;
 }
 
 int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
@@ -285,3 +311,44 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
        mutex_unlock(&dev->struct_mutex);
        return r;
 }
+
+int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *filp)
+{
+       struct drm_radeon_gem_set_tiling *args = data;
+       struct drm_gem_object *gobj;
+       struct radeon_object *robj;
+       int r = 0;
+
+       DRM_DEBUG("%d \n", args->handle);
+       gobj = drm_gem_object_lookup(dev, filp, args->handle);
+       if (gobj == NULL)
+               return -EINVAL;
+       robj = gobj->driver_private;
+       radeon_object_set_tiling_flags(robj, args->tiling_flags, args->pitch);
+       mutex_lock(&dev->struct_mutex);
+       drm_gem_object_unreference(gobj);
+       mutex_unlock(&dev->struct_mutex);
+       return r;
+}
+
+int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
+                               struct drm_file *filp)
+{
+       struct drm_radeon_gem_get_tiling *args = data;
+       struct drm_gem_object *gobj;
+       struct radeon_object *robj;
+       int r = 0;
+
+       DRM_DEBUG("\n");
+       gobj = drm_gem_object_lookup(dev, filp, args->handle);
+       if (gobj == NULL)
+               return -EINVAL;
+       robj = gobj->driver_private;
+       radeon_object_get_tiling_flags(robj, &args->tiling_flags,
+                                      &args->pitch);
+       mutex_lock(&dev->struct_mutex);
+       drm_gem_object_unreference(gobj);
+       mutex_unlock(&dev->struct_mutex);
+       return r;
+}
index 491d569deb0e02588af0891c23d9dc6ec750708e..9805e4b6ca1b19446502e3ce8aa383f2955b1adb 100644 (file)
 #include "radeon.h"
 #include "atom.h"
 
-static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
-{
-       uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
-       uint32_t irq_mask = RADEON_SW_INT_TEST;
-
-       if (irqs) {
-               WREG32(RADEON_GEN_INT_STATUS, irqs);
-       }
-       return irqs & irq_mask;
-}
-
-int r100_irq_set(struct radeon_device *rdev)
-{
-       uint32_t tmp = 0;
-
-       if (rdev->irq.sw_int) {
-               tmp |= RADEON_SW_INT_ENABLE;
-       }
-       /* Todo go through CRTC and enable vblank int or not */
-       WREG32(RADEON_GEN_INT_CNTL, tmp);
-       return 0;
-}
-
-int r100_irq_process(struct radeon_device *rdev)
-{
-       uint32_t status;
-
-       status = r100_irq_ack(rdev);
-       if (!status) {
-               return IRQ_NONE;
-       }
-       while (status) {
-               /* SW interrupt */
-               if (status & RADEON_SW_INT_TEST) {
-                       radeon_fence_process(rdev);
-               }
-               status = r100_irq_ack(rdev);
-       }
-       return IRQ_HANDLED;
-}
-
-int rs600_irq_set(struct radeon_device *rdev)
-{
-       uint32_t tmp = 0;
-
-       if (rdev->irq.sw_int) {
-               tmp |= RADEON_SW_INT_ENABLE;
-       }
-       WREG32(RADEON_GEN_INT_CNTL, tmp);
-       /* Todo go through CRTC and enable vblank int or not */
-       WREG32(R500_DxMODE_INT_MASK, 0);
-       return 0;
-}
-
 irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS)
 {
        struct drm_device *dev = (struct drm_device *) arg;
index 4612a7c146d18d380ba3a1b544e343c25a53a62e..dce09ada32bcc9461db496c23127b31303d8049b 100644 (file)
@@ -58,6 +58,8 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
        if (r) {
                DRM_ERROR("Failed to initialize radeon, disabling IOCTL\n");
                radeon_device_fini(rdev);
+               kfree(rdev);
+               dev->dev_private = NULL;
                return r;
        }
        return 0;
@@ -93,6 +95,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        case RADEON_INFO_NUM_GB_PIPES:
                value = rdev->num_gb_pipes;
                break;
+       case RADEON_INFO_NUM_Z_PIPES:
+               value = rdev->num_z_pipes;
+               break;
        default:
                DRM_DEBUG("Invalid request %d\n", info->request);
                return -EINVAL;
@@ -139,19 +144,42 @@ void radeon_driver_preclose_kms(struct drm_device *dev,
  */
 u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc)
 {
-       /* FIXME: implement */
-       return 0;
+       struct radeon_device *rdev = dev->dev_private;
+
+       if (crtc < 0 || crtc > 1) {
+               DRM_ERROR("Invalid crtc %d\n", crtc);
+               return -EINVAL;
+       }
+
+       return radeon_get_vblank_counter(rdev, crtc);
 }
 
 int radeon_enable_vblank_kms(struct drm_device *dev, int crtc)
 {
-       /* FIXME: implement */
-       return 0;
+       struct radeon_device *rdev = dev->dev_private;
+
+       if (crtc < 0 || crtc > 1) {
+               DRM_ERROR("Invalid crtc %d\n", crtc);
+               return -EINVAL;
+       }
+
+       rdev->irq.crtc_vblank_int[crtc] = true;
+
+       return radeon_irq_set(rdev);
 }
 
 void radeon_disable_vblank_kms(struct drm_device *dev, int crtc)
 {
-       /* FIXME: implement */
+       struct radeon_device *rdev = dev->dev_private;
+
+       if (crtc < 0 || crtc > 1) {
+               DRM_ERROR("Invalid crtc %d\n", crtc);
+               return;
+       }
+
+       rdev->irq.crtc_vblank_int[crtc] = false;
+
+       radeon_irq_set(rdev);
 }
 
 
@@ -291,5 +319,8 @@ struct drm_ioctl_desc radeon_ioctls_kms[] = {
        DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH),
        DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF(DRM_RADEON_GEM_BUSY, radeon_gem_busy_ioctl, DRM_AUTH),
 };
 int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms);
index 8086ecf7f03d67657ebba92ce113f96fd56f407a..0da72f18fd3aaed205a217abaf45f4489ee7e622 100644 (file)
 #include "radeon_fixed.h"
 #include "radeon.h"
 
+static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
+                                      struct drm_display_mode *mode,
+                                      struct drm_display_mode *adjusted_mode)
+{
+       struct drm_device *dev = crtc->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+       int xres = mode->hdisplay;
+       int yres = mode->vdisplay;
+       bool hscale = true, vscale = true;
+       int hsync_wid;
+       int vsync_wid;
+       int hsync_start;
+       int blank_width;
+       u32 scale, inc, crtc_more_cntl;
+       u32 fp_horz_stretch, fp_vert_stretch, fp_horz_vert_active;
+       u32 fp_h_sync_strt_wid, fp_crtc_h_total_disp;
+       u32 fp_v_sync_strt_wid, fp_crtc_v_total_disp;
+       struct radeon_native_mode *native_mode = &radeon_crtc->native_mode;
+
+       fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) &
+               (RADEON_VERT_STRETCH_RESERVED |
+                RADEON_VERT_AUTO_RATIO_INC);
+       fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) &
+               (RADEON_HORZ_FP_LOOP_STRETCH |
+                RADEON_HORZ_AUTO_RATIO_INC);
+
+       crtc_more_cntl = 0;
+       if ((rdev->family == CHIP_RS100) ||
+           (rdev->family == CHIP_RS200)) {
+               /* This is to workaround the asic bug for RMX, some versions
+                  of BIOS dosen't have this register initialized correctly. */
+               crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN;
+       }
+
+
+       fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff)
+                               | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
+
+       hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
+       if (!hsync_wid)
+               hsync_wid = 1;
+       hsync_start = mode->crtc_hsync_start - 8;
+
+       fp_h_sync_strt_wid = ((hsync_start & 0x1fff)
+                             | ((hsync_wid & 0x3f) << 16)
+                             | ((mode->flags & DRM_MODE_FLAG_NHSYNC)
+                                ? RADEON_CRTC_H_SYNC_POL
+                                : 0));
+
+       fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff)
+                               | ((mode->crtc_vdisplay - 1) << 16));
+
+       vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
+       if (!vsync_wid)
+               vsync_wid = 1;
+
+       fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff)
+                             | ((vsync_wid & 0x1f) << 16)
+                             | ((mode->flags & DRM_MODE_FLAG_NVSYNC)
+                                ? RADEON_CRTC_V_SYNC_POL
+                                : 0));
+
+       fp_horz_vert_active = 0;
+
+       if (native_mode->panel_xres == 0 ||
+           native_mode->panel_yres == 0) {
+               hscale = false;
+               vscale = false;
+       } else {
+               if (xres > native_mode->panel_xres)
+                       xres = native_mode->panel_xres;
+               if (yres > native_mode->panel_yres)
+                       yres = native_mode->panel_yres;
+
+               if (xres == native_mode->panel_xres)
+                       hscale = false;
+               if (yres == native_mode->panel_yres)
+                       vscale = false;
+       }
+
+       switch (radeon_crtc->rmx_type) {
+       case RMX_FULL:
+       case RMX_ASPECT:
+               if (!hscale)
+                       fp_horz_stretch |= ((xres/8-1) << 16);
+               else {
+                       inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0;
+                       scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX)
+                               / native_mode->panel_xres + 1;
+                       fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) |
+                                       RADEON_HORZ_STRETCH_BLEND |
+                                       RADEON_HORZ_STRETCH_ENABLE |
+                                       ((native_mode->panel_xres/8-1) << 16));
+               }
+
+               if (!vscale)
+                       fp_vert_stretch |= ((yres-1) << 12);
+               else {
+                       inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0;
+                       scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX)
+                               / native_mode->panel_yres + 1;
+                       fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) |
+                                       RADEON_VERT_STRETCH_ENABLE |
+                                       RADEON_VERT_STRETCH_BLEND |
+                                       ((native_mode->panel_yres-1) << 12));
+               }
+               break;
+       case RMX_CENTER:
+               fp_horz_stretch |= ((xres/8-1) << 16);
+               fp_vert_stretch |= ((yres-1) << 12);
+
+               crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN |
+                               RADEON_CRTC_AUTO_VERT_CENTER_EN);
+
+               blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8;
+               if (blank_width > 110)
+                       blank_width = 110;
+
+               fp_crtc_h_total_disp = (((blank_width) & 0x3ff)
+                               | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
+
+               hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
+               if (!hsync_wid)
+                       hsync_wid = 1;
+
+               fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff)
+                               | ((hsync_wid & 0x3f) << 16)
+                               | ((mode->flags & DRM_MODE_FLAG_NHSYNC)
+                                       ? RADEON_CRTC_H_SYNC_POL
+                                       : 0));
+
+               fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff)
+                               | ((mode->crtc_vdisplay - 1) << 16));
+
+               vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
+               if (!vsync_wid)
+                       vsync_wid = 1;
+
+               fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff)
+                                       | ((vsync_wid & 0x1f) << 16)
+                                       | ((mode->flags & DRM_MODE_FLAG_NVSYNC)
+                                               ? RADEON_CRTC_V_SYNC_POL
+                                               : 0)));
+
+               fp_horz_vert_active = (((native_mode->panel_yres) & 0xfff) |
+                               (((native_mode->panel_xres / 8) & 0x1ff) << 16));
+               break;
+       case RMX_OFF:
+       default:
+               fp_horz_stretch |= ((xres/8-1) << 16);
+               fp_vert_stretch |= ((yres-1) << 12);
+               break;
+       }
+
+       WREG32(RADEON_FP_HORZ_STRETCH,      fp_horz_stretch);
+       WREG32(RADEON_FP_VERT_STRETCH,      fp_vert_stretch);
+       WREG32(RADEON_CRTC_MORE_CNTL,       crtc_more_cntl);
+       WREG32(RADEON_FP_HORZ_VERT_ACTIVE,  fp_horz_vert_active);
+       WREG32(RADEON_FP_H_SYNC_STRT_WID,   fp_h_sync_strt_wid);
+       WREG32(RADEON_FP_V_SYNC_STRT_WID,   fp_v_sync_strt_wid);
+       WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp);
+       WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp);
+}
+
 void radeon_restore_common_regs(struct drm_device *dev)
 {
        /* don't need this yet */
@@ -145,10 +310,13 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                                                                         RADEON_CRTC_DISP_REQ_EN_B));
                        WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask);
                }
+               drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
+               radeon_crtc_load_lut(crtc);
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
+               drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
                if (radeon_crtc->crtc_id)
                        WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~mask);
                else {
@@ -158,10 +326,6 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                }
                break;
        }
-
-       if (mode != DRM_MODE_DPMS_OFF) {
-               radeon_crtc_load_lut(crtc);
-       }
 }
 
 /* properly set crtc bpp when using atombios */
@@ -235,6 +399,7 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
        uint64_t base;
        uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0;
        uint32_t crtc_pitch, pitch_pixels;
+       uint32_t tiling_flags;
 
        DRM_DEBUG("\n");
 
@@ -244,7 +409,12 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
        if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &base)) {
                return -EINVAL;
        }
-       crtc_offset = (u32)base;
+       /* if scanout was in GTT this really wouldn't work */
+       /* crtc offset is from display base addr not FB location */
+       radeon_crtc->legacy_display_base_addr = rdev->mc.vram_location;
+
+       base -= radeon_crtc->legacy_display_base_addr;
+
        crtc_offset_cntl = 0;
 
        pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
@@ -253,8 +423,12 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
                       (crtc->fb->bits_per_pixel * 8));
        crtc_pitch |= crtc_pitch << 16;
 
-       /* TODO tiling */
-       if (0) {
+       radeon_object_get_tiling_flags(obj->driver_private,
+                                      &tiling_flags, NULL);
+       if (tiling_flags & RADEON_TILING_MICRO)
+               DRM_ERROR("trying to scanout microtiled buffer\n");
+
+       if (tiling_flags & RADEON_TILING_MACRO) {
                if (ASIC_IS_R300(rdev))
                        crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN |
                                             R300_CRTC_MICRO_TILE_BUFFER_DIS |
@@ -270,15 +444,13 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
                        crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN;
        }
 
-
-       /* TODO more tiling */
-       if (0) {
+       if (tiling_flags & RADEON_TILING_MACRO) {
                if (ASIC_IS_R300(rdev)) {
                        crtc_tile_x0_y0 = x | (y << 16);
                        base &= ~0x7ff;
                } else {
                        int byteshift = crtc->fb->bits_per_pixel >> 4;
-                       int tile_addr = (((y >> 3) * crtc->fb->width + x) >> (8 - byteshift)) << 11;
+                       int tile_addr = (((y >> 3) * pitch_pixels +  x) >> (8 - byteshift)) << 11;
                        base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8);
                        crtc_offset_cntl |= (y % 16);
                }
@@ -303,11 +475,9 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
 
        base &= ~7;
 
-       /* update sarea TODO */
-
        crtc_offset = (u32)base;
 
-       WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, rdev->mc.vram_location);
+       WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, radeon_crtc->legacy_display_base_addr);
 
        if (ASIC_IS_R300(rdev)) {
                if (radeon_crtc->crtc_id)
@@ -751,6 +921,8 @@ static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc,
                                   struct drm_display_mode *mode,
                                   struct drm_display_mode *adjusted_mode)
 {
+       if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
+               return false;
        return true;
 }
 
@@ -759,16 +931,25 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc,
                                 struct drm_display_mode *adjusted_mode,
                                 int x, int y, struct drm_framebuffer *old_fb)
 {
-
-       DRM_DEBUG("\n");
+       struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+       struct drm_device *dev = crtc->dev;
+       struct radeon_device *rdev = dev->dev_private;
 
        /* TODO TV */
-
        radeon_crtc_set_base(crtc, x, y, old_fb);
        radeon_set_crtc_timing(crtc, adjusted_mode);
        radeon_set_pll(crtc, adjusted_mode);
-       radeon_init_disp_bandwidth(crtc->dev);
-
+       radeon_bandwidth_update(rdev);
+       if (radeon_crtc->crtc_id == 0) {
+               radeon_legacy_rmx_mode_set(crtc, mode, adjusted_mode);
+       } else {
+               if (radeon_crtc->rmx_type != RMX_OFF) {
+                       /* FIXME: only first crtc has rmx what should we
+                        * do ?
+                        */
+                       DRM_ERROR("Mode need scaling but only first crtc can do that.\n");
+               }
+       }
        return 0;
 }
 
@@ -799,478 +980,3 @@ void radeon_legacy_init_crtc(struct drm_device *dev,
                radeon_crtc->crtc_offset = RADEON_CRTC2_H_TOTAL_DISP - RADEON_CRTC_H_TOTAL_DISP;
        drm_crtc_helper_add(&radeon_crtc->base, &legacy_helper_funcs);
 }
-
-void radeon_init_disp_bw_legacy(struct drm_device *dev,
-                               struct drm_display_mode *mode1,
-                               uint32_t pixel_bytes1,
-                               struct drm_display_mode *mode2,
-                               uint32_t pixel_bytes2)
-{
-       struct radeon_device *rdev = dev->dev_private;
-       fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff;
-       fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff;
-       fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff;
-       uint32_t temp, data, mem_trcd, mem_trp, mem_tras;
-       fixed20_12 memtcas_ff[8] = {
-               fixed_init(1),
-               fixed_init(2),
-               fixed_init(3),
-               fixed_init(0),
-               fixed_init_half(1),
-               fixed_init_half(2),
-               fixed_init(0),
-       };
-       fixed20_12 memtcas_rs480_ff[8] = {
-               fixed_init(0),
-               fixed_init(1),
-               fixed_init(2),
-               fixed_init(3),
-               fixed_init(0),
-               fixed_init_half(1),
-               fixed_init_half(2),
-               fixed_init_half(3),
-       };
-       fixed20_12 memtcas2_ff[8] = {
-               fixed_init(0),
-               fixed_init(1),
-               fixed_init(2),
-               fixed_init(3),
-               fixed_init(4),
-               fixed_init(5),
-               fixed_init(6),
-               fixed_init(7),
-       };
-       fixed20_12 memtrbs[8] = {
-               fixed_init(1),
-               fixed_init_half(1),
-               fixed_init(2),
-               fixed_init_half(2),
-               fixed_init(3),
-               fixed_init_half(3),
-               fixed_init(4),
-               fixed_init_half(4)
-       };
-       fixed20_12 memtrbs_r4xx[8] = {
-               fixed_init(4),
-               fixed_init(5),
-               fixed_init(6),
-               fixed_init(7),
-               fixed_init(8),
-               fixed_init(9),
-               fixed_init(10),
-               fixed_init(11)
-       };
-       fixed20_12 min_mem_eff;
-       fixed20_12 mc_latency_sclk, mc_latency_mclk, k1;
-       fixed20_12 cur_latency_mclk, cur_latency_sclk;
-       fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate,
-               disp_drain_rate2, read_return_rate;
-       fixed20_12 time_disp1_drop_priority;
-       int c;
-       int cur_size = 16;       /* in octawords */
-       int critical_point = 0, critical_point2;
-/*     uint32_t read_return_rate, time_disp1_drop_priority; */
-       int stop_req, max_stop_req;
-
-       min_mem_eff.full = rfixed_const_8(0);
-       /* get modes */
-       if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) {
-               uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER);
-               mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT);
-               mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT);
-               /* check crtc enables */
-               if (mode2)
-                       mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT);
-               if (mode1)
-                       mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT);
-               WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
-       }
-
-       /*
-        * determine is there is enough bw for current mode
-        */
-       mclk_ff.full = rfixed_const(rdev->clock.default_mclk);
-       temp_ff.full = rfixed_const(100);
-       mclk_ff.full = rfixed_div(mclk_ff, temp_ff);
-       sclk_ff.full = rfixed_const(rdev->clock.default_sclk);
-       sclk_ff.full = rfixed_div(sclk_ff, temp_ff);
-
-       temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1);
-       temp_ff.full = rfixed_const(temp);
-       mem_bw.full = rfixed_mul(mclk_ff, temp_ff);
-
-       pix_clk.full = 0;
-       pix_clk2.full = 0;
-       peak_disp_bw.full = 0;
-       if (mode1) {
-               temp_ff.full = rfixed_const(1000);
-               pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */
-               pix_clk.full = rfixed_div(pix_clk, temp_ff);
-               temp_ff.full = rfixed_const(pixel_bytes1);
-               peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff);
-       }
-       if (mode2) {
-               temp_ff.full = rfixed_const(1000);
-               pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */
-               pix_clk2.full = rfixed_div(pix_clk2, temp_ff);
-               temp_ff.full = rfixed_const(pixel_bytes2);
-               peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff);
-       }
-
-       mem_bw.full = rfixed_mul(mem_bw, min_mem_eff);
-       if (peak_disp_bw.full >= mem_bw.full) {
-               DRM_ERROR("You may not have enough display bandwidth for current mode\n"
-                         "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
-       }
-
-       /*  Get values from the EXT_MEM_CNTL register...converting its contents. */
-       temp = RREG32(RADEON_MEM_TIMING_CNTL);
-       if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */
-               mem_trcd = ((temp >> 2) & 0x3) + 1;
-               mem_trp  = ((temp & 0x3)) + 1;
-               mem_tras = ((temp & 0x70) >> 4) + 1;
-       } else if (rdev->family == CHIP_R300 ||
-                  rdev->family == CHIP_R350) { /* r300, r350 */
-               mem_trcd = (temp & 0x7) + 1;
-               mem_trp = ((temp >> 8) & 0x7) + 1;
-               mem_tras = ((temp >> 11) & 0xf) + 4;
-       } else if (rdev->family == CHIP_RV350 ||
-                  rdev->family <= CHIP_RV380) {
-               /* rv3x0 */
-               mem_trcd = (temp & 0x7) + 3;
-               mem_trp = ((temp >> 8) & 0x7) + 3;
-               mem_tras = ((temp >> 11) & 0xf) + 6;
-       } else if (rdev->family == CHIP_R420 ||
-                  rdev->family == CHIP_R423 ||
-                  rdev->family == CHIP_RV410) {
-               /* r4xx */
-               mem_trcd = (temp & 0xf) + 3;
-               if (mem_trcd > 15)
-                       mem_trcd = 15;
-               mem_trp = ((temp >> 8) & 0xf) + 3;
-               if (mem_trp > 15)
-                       mem_trp = 15;
-               mem_tras = ((temp >> 12) & 0x1f) + 6;
-               if (mem_tras > 31)
-                       mem_tras = 31;
-       } else { /* RV200, R200 */
-               mem_trcd = (temp & 0x7) + 1;
-               mem_trp = ((temp >> 8) & 0x7) + 1;
-               mem_tras = ((temp >> 12) & 0xf) + 4;
-       }
-       /* convert to FF */
-       trcd_ff.full = rfixed_const(mem_trcd);
-       trp_ff.full = rfixed_const(mem_trp);
-       tras_ff.full = rfixed_const(mem_tras);
-
-       /* Get values from the MEM_SDRAM_MODE_REG register...converting its */
-       temp = RREG32(RADEON_MEM_SDRAM_MODE_REG);
-       data = (temp & (7 << 20)) >> 20;
-       if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) {
-               if (rdev->family == CHIP_RS480) /* don't think rs400 */
-                       tcas_ff = memtcas_rs480_ff[data];
-               else
-                       tcas_ff = memtcas_ff[data];
-       } else
-               tcas_ff = memtcas2_ff[data];
-
-       if (rdev->family == CHIP_RS400 ||
-           rdev->family == CHIP_RS480) {
-               /* extra cas latency stored in bits 23-25 0-4 clocks */
-               data = (temp >> 23) & 0x7;
-               if (data < 5)
-                       tcas_ff.full += rfixed_const(data);
-       }
-
-       if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) {
-               /* on the R300, Tcas is included in Trbs.
-                */
-               temp = RREG32(RADEON_MEM_CNTL);
-               data = (R300_MEM_NUM_CHANNELS_MASK & temp);
-               if (data == 1) {
-                       if (R300_MEM_USE_CD_CH_ONLY & temp) {
-                               temp = RREG32(R300_MC_IND_INDEX);
-                               temp &= ~R300_MC_IND_ADDR_MASK;
-                               temp |= R300_MC_READ_CNTL_CD_mcind;
-                               WREG32(R300_MC_IND_INDEX, temp);
-                               temp = RREG32(R300_MC_IND_DATA);
-                               data = (R300_MEM_RBS_POSITION_C_MASK & temp);
-                       } else {
-                               temp = RREG32(R300_MC_READ_CNTL_AB);
-                               data = (R300_MEM_RBS_POSITION_A_MASK & temp);
-                       }
-               } else {
-                       temp = RREG32(R300_MC_READ_CNTL_AB);
-                       data = (R300_MEM_RBS_POSITION_A_MASK & temp);
-               }
-               if (rdev->family == CHIP_RV410 ||
-                   rdev->family == CHIP_R420 ||
-                   rdev->family == CHIP_R423)
-                       trbs_ff = memtrbs_r4xx[data];
-               else
-                       trbs_ff = memtrbs[data];
-               tcas_ff.full += trbs_ff.full;
-       }
-
-       sclk_eff_ff.full = sclk_ff.full;
-
-       if (rdev->flags & RADEON_IS_AGP) {
-               fixed20_12 agpmode_ff;
-               agpmode_ff.full = rfixed_const(radeon_agpmode);
-               temp_ff.full = rfixed_const_666(16);
-               sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff);
-       }
-       /* TODO PCIE lanes may affect this - agpmode == 16?? */
-
-       if (ASIC_IS_R300(rdev)) {
-               sclk_delay_ff.full = rfixed_const(250);
-       } else {
-               if ((rdev->family == CHIP_RV100) ||
-                   rdev->flags & RADEON_IS_IGP) {
-                       if (rdev->mc.vram_is_ddr)
-                               sclk_delay_ff.full = rfixed_const(41);
-                       else
-                               sclk_delay_ff.full = rfixed_const(33);
-               } else {
-                       if (rdev->mc.vram_width == 128)
-                               sclk_delay_ff.full = rfixed_const(57);
-                       else
-                               sclk_delay_ff.full = rfixed_const(41);
-               }
-       }
-
-       mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff);
-
-       if (rdev->mc.vram_is_ddr) {
-               if (rdev->mc.vram_width == 32) {
-                       k1.full = rfixed_const(40);
-                       c  = 3;
-               } else {
-                       k1.full = rfixed_const(20);
-                       c  = 1;
-               }
-       } else {
-               k1.full = rfixed_const(40);
-               c  = 3;
-       }
-
-       temp_ff.full = rfixed_const(2);
-       mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff);
-       temp_ff.full = rfixed_const(c);
-       mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff);
-       temp_ff.full = rfixed_const(4);
-       mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff);
-       mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff);
-       mc_latency_mclk.full += k1.full;
-
-       mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff);
-       mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff);
-
-       /*
-         HW cursor time assuming worst case of full size colour cursor.
-       */
-       temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1))));
-       temp_ff.full += trcd_ff.full;
-       if (temp_ff.full < tras_ff.full)
-               temp_ff.full = tras_ff.full;
-       cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff);
-
-       temp_ff.full = rfixed_const(cur_size);
-       cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff);
-       /*
-         Find the total latency for the display data.
-       */
-       disp_latency_overhead.full = rfixed_const(80);
-       disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff);
-       mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full;
-       mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full;
-
-       if (mc_latency_mclk.full > mc_latency_sclk.full)
-               disp_latency.full = mc_latency_mclk.full;
-       else
-               disp_latency.full = mc_latency_sclk.full;
-
-       /* setup Max GRPH_STOP_REQ default value */
-       if (ASIC_IS_RV100(rdev))
-               max_stop_req = 0x5c;
-       else
-               max_stop_req = 0x7c;
-
-       if (mode1) {
-               /*  CRTC1
-                   Set GRPH_BUFFER_CNTL register using h/w defined optimal values.
-                   GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ]
-               */
-               stop_req = mode1->hdisplay * pixel_bytes1 / 16;
-
-               if (stop_req > max_stop_req)
-                       stop_req = max_stop_req;
-
-               /*
-                 Find the drain rate of the display buffer.
-               */
-               temp_ff.full = rfixed_const((16/pixel_bytes1));
-               disp_drain_rate.full = rfixed_div(pix_clk, temp_ff);
-
-               /*
-                 Find the critical point of the display buffer.
-               */
-               crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency);
-               crit_point_ff.full += rfixed_const_half(0);
-
-               critical_point = rfixed_trunc(crit_point_ff);
-
-               if (rdev->disp_priority == 2) {
-                       critical_point = 0;
-               }
-
-               /*
-                 The critical point should never be above max_stop_req-4.  Setting
-                 GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time.
-               */
-               if (max_stop_req - critical_point < 4)
-                       critical_point = 0;
-
-               if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) {
-                       /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/
-                       critical_point = 0x10;
-               }
-
-               temp = RREG32(RADEON_GRPH_BUFFER_CNTL);
-               temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
-               temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
-               temp &= ~(RADEON_GRPH_START_REQ_MASK);
-               if ((rdev->family == CHIP_R350) &&
-                   (stop_req > 0x15)) {
-                       stop_req -= 0x10;
-               }
-               temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
-               temp |= RADEON_GRPH_BUFFER_SIZE;
-               temp &= ~(RADEON_GRPH_CRITICAL_CNTL   |
-                         RADEON_GRPH_CRITICAL_AT_SOF |
-                         RADEON_GRPH_STOP_CNTL);
-               /*
-                 Write the result into the register.
-               */
-               WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
-                                                      (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
-
-#if 0
-               if ((rdev->family == CHIP_RS400) ||
-                   (rdev->family == CHIP_RS480)) {
-                       /* attempt to program RS400 disp regs correctly ??? */
-                       temp = RREG32(RS400_DISP1_REG_CNTL);
-                       temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK |
-                                 RS400_DISP1_STOP_REQ_LEVEL_MASK);
-                       WREG32(RS400_DISP1_REQ_CNTL1, (temp |
-                                                      (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) |
-                                                      (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT)));
-                       temp = RREG32(RS400_DMIF_MEM_CNTL1);
-                       temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK |
-                                 RS400_DISP1_CRITICAL_POINT_STOP_MASK);
-                       WREG32(RS400_DMIF_MEM_CNTL1, (temp |
-                                                     (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) |
-                                                     (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT)));
-               }
-#endif
-
-               DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n",
-                         /*      (unsigned int)info->SavedReg->grph_buffer_cntl, */
-                         (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL));
-       }
-
-       if (mode2) {
-               u32 grph2_cntl;
-               stop_req = mode2->hdisplay * pixel_bytes2 / 16;
-
-               if (stop_req > max_stop_req)
-                       stop_req = max_stop_req;
-
-               /*
-                 Find the drain rate of the display buffer.
-               */
-               temp_ff.full = rfixed_const((16/pixel_bytes2));
-               disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff);
-
-               grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL);
-               grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK);
-               grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
-               grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK);
-               if ((rdev->family == CHIP_R350) &&
-                   (stop_req > 0x15)) {
-                       stop_req -= 0x10;
-               }
-               grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
-               grph2_cntl |= RADEON_GRPH_BUFFER_SIZE;
-               grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL   |
-                         RADEON_GRPH_CRITICAL_AT_SOF |
-                         RADEON_GRPH_STOP_CNTL);
-
-               if ((rdev->family == CHIP_RS100) ||
-                   (rdev->family == CHIP_RS200))
-                       critical_point2 = 0;
-               else {
-                       temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128;
-                       temp_ff.full = rfixed_const(temp);
-                       temp_ff.full = rfixed_mul(mclk_ff, temp_ff);
-                       if (sclk_ff.full < temp_ff.full)
-                               temp_ff.full = sclk_ff.full;
-
-                       read_return_rate.full = temp_ff.full;
-
-                       if (mode1) {
-                               temp_ff.full = read_return_rate.full - disp_drain_rate.full;
-                               time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff);
-                       } else {
-                               time_disp1_drop_priority.full = 0;
-                       }
-                       crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full;
-                       crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2);
-                       crit_point_ff.full += rfixed_const_half(0);
-
-                       critical_point2 = rfixed_trunc(crit_point_ff);
-
-                       if (rdev->disp_priority == 2) {
-                               critical_point2 = 0;
-                       }
-
-                       if (max_stop_req - critical_point2 < 4)
-                               critical_point2 = 0;
-
-               }
-
-               if (critical_point2 == 0 && rdev->family == CHIP_R300) {
-                       /* some R300 cards have problem with this set to 0 */
-                       critical_point2 = 0x10;
-               }
-
-               WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
-                                                 (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
-
-               if ((rdev->family == CHIP_RS400) ||
-                   (rdev->family == CHIP_RS480)) {
-#if 0
-                       /* attempt to program RS400 disp2 regs correctly ??? */
-                       temp = RREG32(RS400_DISP2_REQ_CNTL1);
-                       temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK |
-                                 RS400_DISP2_STOP_REQ_LEVEL_MASK);
-                       WREG32(RS400_DISP2_REQ_CNTL1, (temp |
-                                                      (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) |
-                                                      (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT)));
-                       temp = RREG32(RS400_DISP2_REQ_CNTL2);
-                       temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK |
-                                 RS400_DISP2_CRITICAL_POINT_STOP_MASK);
-                       WREG32(RS400_DISP2_REQ_CNTL2, (temp |
-                                                      (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) |
-                                                      (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT)));
-#endif
-                       WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC);
-                       WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000);
-                       WREG32(RS400_DMIF_MEM_CNTL1,  0x29CA71DC);
-                       WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC);
-               }
-
-               DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n",
-                         (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL));
-       }
-}
index 2c2f42de1d4cd6881890a0749e34e471b4ac3158..9322675ef6d0158806ae7a4123ed927a3c2402da 100644 (file)
 #include "atom.h"
 
 
-static void radeon_legacy_rmx_mode_set(struct drm_encoder *encoder,
-                                      struct drm_display_mode *mode,
-                                      struct drm_display_mode *adjusted_mode)
-{
-       struct drm_device *dev = encoder->dev;
-       struct radeon_device *rdev = dev->dev_private;
-       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       int    xres = mode->hdisplay;
-       int    yres = mode->vdisplay;
-       bool   hscale = true, vscale = true;
-       int    hsync_wid;
-       int    vsync_wid;
-       int    hsync_start;
-       uint32_t scale, inc;
-       uint32_t fp_horz_stretch, fp_vert_stretch, crtc_more_cntl, fp_horz_vert_active;
-       uint32_t fp_h_sync_strt_wid, fp_v_sync_strt_wid, fp_crtc_h_total_disp, fp_crtc_v_total_disp;
-       struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
-
-       DRM_DEBUG("\n");
-
-       fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) &
-               (RADEON_VERT_STRETCH_RESERVED |
-                RADEON_VERT_AUTO_RATIO_INC);
-       fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) &
-               (RADEON_HORZ_FP_LOOP_STRETCH |
-                RADEON_HORZ_AUTO_RATIO_INC);
-
-       crtc_more_cntl = 0;
-       if ((rdev->family == CHIP_RS100) ||
-           (rdev->family == CHIP_RS200)) {
-               /* This is to workaround the asic bug for RMX, some versions
-                  of BIOS dosen't have this register initialized correctly. */
-               crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN;
-       }
-
-
-       fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff)
-                               | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
-
-       hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
-       if (!hsync_wid)
-               hsync_wid = 1;
-       hsync_start = mode->crtc_hsync_start - 8;
-
-       fp_h_sync_strt_wid = ((hsync_start & 0x1fff)
-                             | ((hsync_wid & 0x3f) << 16)
-                             | ((mode->flags & DRM_MODE_FLAG_NHSYNC)
-                                ? RADEON_CRTC_H_SYNC_POL
-                                : 0));
-
-       fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff)
-                               | ((mode->crtc_vdisplay - 1) << 16));
-
-       vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
-       if (!vsync_wid)
-               vsync_wid = 1;
-
-       fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff)
-                             | ((vsync_wid & 0x1f) << 16)
-                             | ((mode->flags & DRM_MODE_FLAG_NVSYNC)
-                                ? RADEON_CRTC_V_SYNC_POL
-                                : 0));
-
-       fp_horz_vert_active = 0;
-
-       if (native_mode->panel_xres == 0 ||
-           native_mode->panel_yres == 0) {
-               hscale = false;
-               vscale = false;
-       } else {
-               if (xres > native_mode->panel_xres)
-                       xres = native_mode->panel_xres;
-               if (yres > native_mode->panel_yres)
-                       yres = native_mode->panel_yres;
-
-               if (xres == native_mode->panel_xres)
-                       hscale = false;
-               if (yres == native_mode->panel_yres)
-                       vscale = false;
-       }
-
-       if (radeon_encoder->flags & RADEON_USE_RMX) {
-               if (radeon_encoder->rmx_type != RMX_CENTER) {
-                       if (!hscale)
-                               fp_horz_stretch |= ((xres/8-1) << 16);
-                       else {
-                               inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0;
-                               scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX)
-                                       / native_mode->panel_xres + 1;
-                               fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) |
-                                                   RADEON_HORZ_STRETCH_BLEND |
-                                                   RADEON_HORZ_STRETCH_ENABLE |
-                                                   ((native_mode->panel_xres/8-1) << 16));
-                       }
-
-                       if (!vscale)
-                               fp_vert_stretch |= ((yres-1) << 12);
-                       else {
-                               inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0;
-                               scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX)
-                                       / native_mode->panel_yres + 1;
-                               fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) |
-                                                   RADEON_VERT_STRETCH_ENABLE |
-                                                   RADEON_VERT_STRETCH_BLEND |
-                                                   ((native_mode->panel_yres-1) << 12));
-                       }
-               } else if (radeon_encoder->rmx_type == RMX_CENTER) {
-                       int    blank_width;
-
-                       fp_horz_stretch |= ((xres/8-1) << 16);
-                       fp_vert_stretch |= ((yres-1) << 12);
-
-                       crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN |
-                                          RADEON_CRTC_AUTO_VERT_CENTER_EN);
-
-                       blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8;
-                       if (blank_width > 110)
-                               blank_width = 110;
-
-                       fp_crtc_h_total_disp = (((blank_width) & 0x3ff)
-                                               | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
-
-                       hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
-                       if (!hsync_wid)
-                               hsync_wid = 1;
-
-                       fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff)
-                                             | ((hsync_wid & 0x3f) << 16)
-                                             | ((mode->flags & DRM_MODE_FLAG_NHSYNC)
-                                                ? RADEON_CRTC_H_SYNC_POL
-                                                : 0));
-
-                       fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff)
-                                               | ((mode->crtc_vdisplay - 1) << 16));
-
-                       vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
-                       if (!vsync_wid)
-                               vsync_wid = 1;
-
-                       fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff)
-                                              | ((vsync_wid & 0x1f) << 16)
-                                              | ((mode->flags & DRM_MODE_FLAG_NVSYNC)
-                                                 ? RADEON_CRTC_V_SYNC_POL
-                                                 : 0)));
-
-                       fp_horz_vert_active = (((native_mode->panel_yres) & 0xfff) |
-                                              (((native_mode->panel_xres / 8) & 0x1ff) << 16));
-               }
-       } else {
-               fp_horz_stretch |= ((xres/8-1) << 16);
-               fp_vert_stretch |= ((yres-1) << 12);
-       }
-
-       WREG32(RADEON_FP_HORZ_STRETCH,      fp_horz_stretch);
-       WREG32(RADEON_FP_VERT_STRETCH,      fp_vert_stretch);
-       WREG32(RADEON_CRTC_MORE_CNTL,       crtc_more_cntl);
-       WREG32(RADEON_FP_HORZ_VERT_ACTIVE,  fp_horz_vert_active);
-       WREG32(RADEON_FP_H_SYNC_STRT_WID,   fp_h_sync_strt_wid);
-       WREG32(RADEON_FP_V_SYNC_STRT_WID,   fp_v_sync_strt_wid);
-       WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp);
-       WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp);
-
-}
-
 static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 {
        struct drm_device *dev = encoder->dev;
@@ -287,9 +123,6 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
 
        DRM_DEBUG("\n");
 
-       if (radeon_crtc->crtc_id == 0)
-               radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
-
        lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
        lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
 
@@ -318,7 +151,7 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
 
        if (radeon_crtc->crtc_id == 0) {
                if (ASIC_IS_R300(rdev)) {
-                       if (radeon_encoder->flags & RADEON_USE_RMX)
+                       if (radeon_encoder->rmx_type != RMX_OFF)
                                lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX;
                } else
                        lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2;
@@ -350,8 +183,6 @@ static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder,
 
        drm_mode_set_crtcinfo(adjusted_mode, 0);
 
-       radeon_encoder->flags &= ~RADEON_USE_RMX;
-
        if (radeon_encoder->rmx_type != RMX_OFF)
                radeon_rmx_mode_fixup(encoder, mode, adjusted_mode);
 
@@ -455,9 +286,6 @@ static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder,
 
        DRM_DEBUG("\n");
 
-       if (radeon_crtc->crtc_id == 0)
-               radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
-
        if (radeon_crtc->crtc_id == 0) {
                if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) {
                        disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) &
@@ -653,9 +481,6 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
 
        DRM_DEBUG("\n");
 
-       if (radeon_crtc->crtc_id == 0)
-               radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
-
        tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL);
        tmp &= 0xfffff;
        if (rdev->family == CHIP_RV280) {
@@ -711,7 +536,7 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
     if (radeon_crtc->crtc_id == 0) {
            if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
                    fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
-                   if (radeon_encoder->flags & RADEON_USE_RMX)
+                   if (radeon_encoder->rmx_type != RMX_OFF)
                            fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
                    else
                            fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
@@ -820,9 +645,6 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
 
        DRM_DEBUG("\n");
 
-       if (radeon_crtc->crtc_id == 0)
-               radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
-
        if (rdev->is_atom_bios) {
                radeon_encoder->pixel_clock = adjusted_mode->clock;
                atombios_external_tmds_setup(encoder, ATOM_ENABLE);
@@ -856,7 +678,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
        if (radeon_crtc->crtc_id == 0) {
                if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) {
                        fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
-                       if (radeon_encoder->flags & RADEON_USE_RMX)
+                       if (radeon_encoder->rmx_type != RMX_OFF)
                                fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX;
                        else
                                fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1;
@@ -1014,9 +836,6 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
 
        DRM_DEBUG("\n");
 
-       if (radeon_crtc->crtc_id == 0)
-               radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
-
        if (rdev->family != CHIP_R200) {
                tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
                if (rdev->family == CHIP_R420 ||
@@ -1243,9 +1062,11 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t
 
        radeon_encoder->encoder_id = encoder_id;
        radeon_encoder->devices = supported_device;
+       radeon_encoder->rmx_type = RMX_OFF;
 
        switch (radeon_encoder->encoder_id) {
        case ENCODER_OBJECT_ID_INTERNAL_LVDS:
+               encoder->possible_crtcs = 0x1;
                drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs, DRM_MODE_ENCODER_LVDS);
                drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs);
                if (rdev->is_atom_bios)
index 9173b687462b01b470421e58a81bae0cc7c2ac3e..3b09a1f2d8f90a08183a0f50ec4c534621e14d2e 100644 (file)
@@ -36,6 +36,9 @@
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
 #include <linux/i2c-algo-bit.h>
+#include "radeon_fixed.h"
+
+struct radeon_device;
 
 #define to_radeon_crtc(x) container_of(x, struct radeon_crtc, base)
 #define to_radeon_connector(x) container_of(x, struct radeon_connector, base)
@@ -124,6 +127,7 @@ struct radeon_tmds_pll {
 #define RADEON_PLL_PREFER_LOW_POST_DIV  (1 << 8)
 #define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9)
 #define RADEON_PLL_USE_FRAC_FB_DIV      (1 << 10)
+#define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
 
 struct radeon_pll {
        uint16_t reference_freq;
@@ -170,6 +174,18 @@ struct radeon_mode_info {
        struct atom_context *atom_context;
        enum radeon_connector_table connector_table;
        bool mode_config_initialized;
+       struct radeon_crtc *crtcs[2];
+};
+
+struct radeon_native_mode {
+       /* preferred mode */
+       uint32_t panel_xres, panel_yres;
+       uint32_t hoverplus, hsync_width;
+       uint32_t hblank;
+       uint32_t voverplus, vsync_width;
+       uint32_t vblank;
+       uint32_t dotclock;
+       uint32_t flags;
 };
 
 struct radeon_crtc {
@@ -185,19 +201,13 @@ struct radeon_crtc {
        uint64_t cursor_addr;
        int cursor_width;
        int cursor_height;
-};
-
-#define RADEON_USE_RMX 1
-
-struct radeon_native_mode {
-       /* preferred mode */
-       uint32_t panel_xres, panel_yres;
-       uint32_t hoverplus, hsync_width;
-       uint32_t hblank;
-       uint32_t voverplus, vsync_width;
-       uint32_t vblank;
-       uint32_t dotclock;
-       uint32_t flags;
+       uint32_t legacy_display_base_addr;
+       uint32_t legacy_cursor_offset;
+       enum radeon_rmx_type rmx_type;
+       uint32_t devices;
+       fixed20_12 vsc;
+       fixed20_12 hsc;
+       struct radeon_native_mode native_mode;
 };
 
 struct radeon_encoder_primary_dac {
@@ -383,16 +393,9 @@ void radeon_enc_destroy(struct drm_encoder *encoder);
 void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj);
 void radeon_combios_asic_init(struct drm_device *dev);
 extern int radeon_static_clocks_init(struct drm_device *dev);
-void radeon_init_disp_bw_legacy(struct drm_device *dev,
-                               struct drm_display_mode *mode1,
-                               uint32_t pixel_bytes1,
-                               struct drm_display_mode *mode2,
-                               uint32_t pixel_bytes2);
-void radeon_init_disp_bw_avivo(struct drm_device *dev,
-                              struct drm_display_mode *mode1,
-                              uint32_t pixel_bytes1,
-                              struct drm_display_mode *mode2,
-                              uint32_t pixel_bytes2);
-void radeon_init_disp_bandwidth(struct drm_device *dev);
+bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
+                                       struct drm_display_mode *mode,
+                                       struct drm_display_mode *adjusted_mode);
+void atom_rv515_force_tv_scaler(struct radeon_device *rdev);
 
 #endif
index 983e8df5e000d392c26b0b711044055137acd761..b85fb83d7ae84610f77a031ff1cdb53bfc0e099f 100644 (file)
@@ -44,6 +44,9 @@ struct radeon_object {
        uint64_t                        gpu_addr;
        void                            *kptr;
        bool                            is_iomem;
+       uint32_t                        tiling_flags;
+       uint32_t                        pitch;
+       int                             surface_reg;
 };
 
 int radeon_ttm_init(struct radeon_device *rdev);
@@ -70,6 +73,7 @@ static void radeon_ttm_object_object_destroy(struct ttm_buffer_object *tobj)
 
        robj = container_of(tobj, struct radeon_object, tobj);
        list_del_init(&robj->list);
+       radeon_object_clear_surface_reg(robj);
        kfree(robj);
 }
 
@@ -99,16 +103,16 @@ static inline uint32_t radeon_object_flags_from_domain(uint32_t domain)
 {
        uint32_t flags = 0;
        if (domain & RADEON_GEM_DOMAIN_VRAM) {
-               flags |= TTM_PL_FLAG_VRAM;
+               flags |= TTM_PL_FLAG_VRAM | TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
        }
        if (domain & RADEON_GEM_DOMAIN_GTT) {
-               flags |= TTM_PL_FLAG_TT;
+               flags |= TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
        }
        if (domain & RADEON_GEM_DOMAIN_CPU) {
-               flags |= TTM_PL_FLAG_SYSTEM;
+               flags |= TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING;
        }
        if (!flags) {
-               flags |= TTM_PL_FLAG_SYSTEM;
+               flags |= TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING;
        }
        return flags;
 }
@@ -141,6 +145,7 @@ int radeon_object_create(struct radeon_device *rdev,
        }
        robj->rdev = rdev;
        robj->gobj = gobj;
+       robj->surface_reg = -1;
        INIT_LIST_HEAD(&robj->list);
 
        flags = radeon_object_flags_from_domain(domain);
@@ -223,7 +228,6 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
 {
        uint32_t flags;
        uint32_t tmp;
-       void *fbptr;
        int r;
 
        flags = radeon_object_flags_from_domain(domain);
@@ -242,10 +246,6 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
                DRM_ERROR("radeon: failed to reserve object for pinning it.\n");
                return r;
        }
-       if (robj->rdev->fbdev_robj == robj) {
-               mutex_lock(&robj->rdev->fbdev_info->lock);
-               radeon_object_kunmap(robj);
-       }
        tmp = robj->tobj.mem.placement;
        ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM);
        robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING;
@@ -261,23 +261,12 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
                DRM_ERROR("radeon: failed to pin object.\n");
        }
        radeon_object_unreserve(robj);
-       if (robj->rdev->fbdev_robj == robj) {
-               if (!r) {
-                       r = radeon_object_kmap(robj, &fbptr);
-               }
-               if (!r) {
-                       robj->rdev->fbdev_info->screen_base = fbptr;
-                       robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr;
-               }
-               mutex_unlock(&robj->rdev->fbdev_info->lock);
-       }
        return r;
 }
 
 void radeon_object_unpin(struct radeon_object *robj)
 {
        uint32_t flags;
-       void *fbptr;
        int r;
 
        spin_lock(&robj->tobj.lock);
@@ -297,10 +286,6 @@ void radeon_object_unpin(struct radeon_object *robj)
                DRM_ERROR("radeon: failed to reserve object for unpinning it.\n");
                return;
        }
-       if (robj->rdev->fbdev_robj == robj) {
-               mutex_lock(&robj->rdev->fbdev_info->lock);
-               radeon_object_kunmap(robj);
-       }
        flags = robj->tobj.mem.placement;
        robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT;
        r = ttm_buffer_object_validate(&robj->tobj,
@@ -310,16 +295,6 @@ void radeon_object_unpin(struct radeon_object *robj)
                DRM_ERROR("radeon: failed to unpin buffer.\n");
        }
        radeon_object_unreserve(robj);
-       if (robj->rdev->fbdev_robj == robj) {
-               if (!r) {
-                       r = radeon_object_kmap(robj, &fbptr);
-               }
-               if (!r) {
-                       robj->rdev->fbdev_info->screen_base = fbptr;
-                       robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr;
-               }
-               mutex_unlock(&robj->rdev->fbdev_info->lock);
-       }
 }
 
 int radeon_object_wait(struct radeon_object *robj)
@@ -334,7 +309,26 @@ int radeon_object_wait(struct radeon_object *robj)
        }
        spin_lock(&robj->tobj.lock);
        if (robj->tobj.sync_obj) {
-               r = ttm_bo_wait(&robj->tobj, true, false, false);
+               r = ttm_bo_wait(&robj->tobj, true, true, false);
+       }
+       spin_unlock(&robj->tobj.lock);
+       radeon_object_unreserve(robj);
+       return r;
+}
+
+int radeon_object_busy_domain(struct radeon_object *robj, uint32_t *cur_placement)
+{
+       int r = 0;
+
+       r = radeon_object_reserve(robj, true);
+       if (unlikely(r != 0)) {
+               DRM_ERROR("radeon: failed to reserve object for waiting.\n");
+               return r;
+       }
+       spin_lock(&robj->tobj.lock);
+       *cur_placement = robj->tobj.mem.mem_type;
+       if (robj->tobj.sync_obj) {
+               r = ttm_bo_wait(&robj->tobj, true, true, true);
        }
        spin_unlock(&robj->tobj.lock);
        radeon_object_unreserve(robj);
@@ -433,7 +427,6 @@ int radeon_object_list_validate(struct list_head *head, void *fence)
        struct radeon_object *robj;
        struct radeon_fence *old_fence = NULL;
        struct list_head *i;
-       uint32_t flags;
        int r;
 
        r = radeon_object_list_reserve(head);
@@ -444,27 +437,25 @@ int radeon_object_list_validate(struct list_head *head, void *fence)
        list_for_each(i, head) {
                lobj = list_entry(i, struct radeon_object_list, list);
                robj = lobj->robj;
-               if (lobj->wdomain) {
-                       flags = radeon_object_flags_from_domain(lobj->wdomain);
-                       flags |= TTM_PL_FLAG_TT;
-               } else {
-                       flags = radeon_object_flags_from_domain(lobj->rdomain);
-                       flags |= TTM_PL_FLAG_TT;
-                       flags |= TTM_PL_FLAG_VRAM;
-               }
                if (!robj->pin_count) {
-                       robj->tobj.proposed_placement = flags | TTM_PL_MASK_CACHING;
+                       if (lobj->wdomain) {
+                               robj->tobj.proposed_placement =
+                                       radeon_object_flags_from_domain(lobj->wdomain);
+                       } else {
+                               robj->tobj.proposed_placement =
+                                       radeon_object_flags_from_domain(lobj->rdomain);
+                       }
                        r = ttm_buffer_object_validate(&robj->tobj,
                                                       robj->tobj.proposed_placement,
                                                       true, false);
                        if (unlikely(r)) {
-                               radeon_object_list_unreserve(head);
                                DRM_ERROR("radeon: failed to validate.\n");
                                return r;
                        }
                        radeon_object_gpu_addr(robj);
                }
                lobj->gpu_offset = robj->gpu_addr;
+               lobj->tiling_flags = robj->tiling_flags;
                if (fence) {
                        old_fence = (struct radeon_fence *)robj->tobj.sync_obj;
                        robj->tobj.sync_obj = radeon_fence_ref(fence);
@@ -509,3 +500,127 @@ unsigned long radeon_object_size(struct radeon_object *robj)
 {
        return robj->tobj.num_pages << PAGE_SHIFT;
 }
+
+int radeon_object_get_surface_reg(struct radeon_object *robj)
+{
+       struct radeon_device *rdev = robj->rdev;
+       struct radeon_surface_reg *reg;
+       struct radeon_object *old_object;
+       int steal;
+       int i;
+
+       if (!robj->tiling_flags)
+               return 0;
+
+       if (robj->surface_reg >= 0) {
+               reg = &rdev->surface_regs[robj->surface_reg];
+               i = robj->surface_reg;
+               goto out;
+       }
+
+       steal = -1;
+       for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) {
+
+               reg = &rdev->surface_regs[i];
+               if (!reg->robj)
+                       break;
+
+               old_object = reg->robj;
+               if (old_object->pin_count == 0)
+                       steal = i;
+       }
+
+       /* if we are all out */
+       if (i == RADEON_GEM_MAX_SURFACES) {
+               if (steal == -1)
+                       return -ENOMEM;
+               /* find someone with a surface reg and nuke their BO */
+               reg = &rdev->surface_regs[steal];
+               old_object = reg->robj;
+               /* blow away the mapping */
+               DRM_DEBUG("stealing surface reg %d from %p\n", steal, old_object);
+               ttm_bo_unmap_virtual(&old_object->tobj);
+               old_object->surface_reg = -1;
+               i = steal;
+       }
+
+       robj->surface_reg = i;
+       reg->robj = robj;
+
+out:
+       radeon_set_surface_reg(rdev, i, robj->tiling_flags, robj->pitch,
+                              robj->tobj.mem.mm_node->start << PAGE_SHIFT,
+                              robj->tobj.num_pages << PAGE_SHIFT);
+       return 0;
+}
+
+void radeon_object_clear_surface_reg(struct radeon_object *robj)
+{
+       struct radeon_device *rdev = robj->rdev;
+       struct radeon_surface_reg *reg;
+
+       if (robj->surface_reg == -1)
+               return;
+
+       reg = &rdev->surface_regs[robj->surface_reg];
+       radeon_clear_surface_reg(rdev, robj->surface_reg);
+
+       reg->robj = NULL;
+       robj->surface_reg = -1;
+}
+
+void radeon_object_set_tiling_flags(struct radeon_object *robj,
+                                   uint32_t tiling_flags, uint32_t pitch)
+{
+       robj->tiling_flags = tiling_flags;
+       robj->pitch = pitch;
+}
+
+void radeon_object_get_tiling_flags(struct radeon_object *robj,
+                                   uint32_t *tiling_flags,
+                                   uint32_t *pitch)
+{
+       if (tiling_flags)
+               *tiling_flags = robj->tiling_flags;
+       if (pitch)
+               *pitch = robj->pitch;
+}
+
+int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved,
+                              bool force_drop)
+{
+       if (!(robj->tiling_flags & RADEON_TILING_SURFACE))
+               return 0;
+
+       if (force_drop) {
+               radeon_object_clear_surface_reg(robj);
+               return 0;
+       }
+
+       if (robj->tobj.mem.mem_type != TTM_PL_VRAM) {
+               if (!has_moved)
+                       return 0;
+
+               if (robj->surface_reg >= 0)
+                       radeon_object_clear_surface_reg(robj);
+               return 0;
+       }
+
+       if ((robj->surface_reg >= 0) && !has_moved)
+               return 0;
+
+       return radeon_object_get_surface_reg(robj);
+}
+
+void radeon_bo_move_notify(struct ttm_buffer_object *bo,
+                         struct ttm_mem_reg *mem)
+{
+       struct radeon_object *robj = container_of(bo, struct radeon_object, tobj);
+       radeon_object_check_tiling(robj, 0, 1);
+}
+
+void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
+{
+       struct radeon_object *robj = container_of(bo, struct radeon_object, tobj);
+       radeon_object_check_tiling(robj, 0, 0);
+}
index e1b618574461b2a4659829a47f9ac986be37dc11..4df43f62c678ae715ec0b8e0a74415d6d74056f2 100644 (file)
 #       define RS400_TMDS2_PLLRST           (1 << 1)
 
 #define RADEON_GEN_INT_CNTL                 0x0040
+#      define RADEON_CRTC_VBLANK_MASK          (1 << 0)
+#      define RADEON_CRTC2_VBLANK_MASK         (1 << 9)
 #      define RADEON_SW_INT_ENABLE             (1 << 25)
 #define RADEON_GEN_INT_STATUS               0x0044
-#       define RADEON_VSYNC_INT_AK          (1 <<  2)
-#       define RADEON_VSYNC_INT             (1 <<  2)
-#       define RADEON_VSYNC2_INT_AK         (1 <<  6)
-#       define RADEON_VSYNC2_INT            (1 <<  6)
+#      define AVIVO_DISPLAY_INT_STATUS         (1 << 0)
+#      define RADEON_CRTC_VBLANK_STAT          (1 << 0)
+#      define RADEON_CRTC_VBLANK_STAT_ACK      (1 << 0)
+#      define RADEON_CRTC2_VBLANK_STAT         (1 << 9)
+#      define RADEON_CRTC2_VBLANK_STAT_ACK     (1 << 9)
 #      define RADEON_SW_INT_FIRE               (1 << 26)
 #      define RADEON_SW_INT_TEST               (1 << 25)
 #      define RADEON_SW_INT_TEST_ACK           (1 << 25)
 #       define RADEON_RE_WIDTH_SHIFT        0
 #       define RADEON_RE_HEIGHT_SHIFT       16
 
+#define RADEON_RB3D_ZPASS_DATA 0x3290
+#define RADEON_RB3D_ZPASS_ADDR 0x3294
+
 #define RADEON_SE_CNTL                      0x1c4c
 #       define RADEON_FFACE_CULL_CW          (0 <<  0)
 #       define RADEON_FFACE_CULL_CCW         (1 <<  0)
 #define RADEON_SCRATCH_REG4            0x15f0
 #define RADEON_SCRATCH_REG5            0x15f4
 
+#define RV530_GB_PIPE_SELECT2           0x4124
+
 #endif
index a853261d188116a6569b013a73e539d02d2d1b57..60d159308b883adddec3628b343a7784c6d22cab 100644 (file)
@@ -126,32 +126,19 @@ static void radeon_ib_align(struct radeon_device *rdev, struct radeon_ib *ib)
        }
 }
 
-static void radeon_ib_cpu_flush(struct radeon_device *rdev,
-                               struct radeon_ib *ib)
-{
-       unsigned long tmp;
-       unsigned i;
-
-       /* To force CPU cache flush ugly but seems reliable */
-       for (i = 0; i < ib->length_dw; i += (rdev->cp.align_mask + 1)) {
-               tmp = readl(&ib->ptr[i]);
-       }
-}
-
 int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
 {
        int r = 0;
 
        mutex_lock(&rdev->ib_pool.mutex);
        radeon_ib_align(rdev, ib);
-       radeon_ib_cpu_flush(rdev, ib);
        if (!ib->length_dw || !rdev->cp.ready) {
                /* TODO: Nothings in the ib we should report. */
                mutex_unlock(&rdev->ib_pool.mutex);
                DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx);
                return -EINVAL;
        }
-       /* 64 dwords should be enought for fence too */
+       /* 64 dwords should be enough for fence too */
        r = radeon_ring_lock(rdev, 64);
        if (r) {
                DRM_ERROR("radeon: scheduling IB failled (%d).\n", r);
diff --git a/drivers/gpu/drm/radeon/radeon_share.h b/drivers/gpu/drm/radeon/radeon_share.h
new file mode 100644 (file)
index 0000000..63a7735
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef __RADEON_SHARE_H__
+#define __RADEON_SHARE_H__
+
+void r100_vram_init_sizes(struct radeon_device *rdev);
+
+void rs690_line_buffer_adjust(struct radeon_device *rdev,
+                             struct drm_display_mode *mode1,
+                             struct drm_display_mode *mode2);
+
+void rv515_bandwidth_avivo_update(struct radeon_device *rdev);
+
+#endif
index 46645f3e03286e448d15659a14e72d24d79fb332..2882f40d5ec563d4ac5760314ca2a8b7b5da8282 100644 (file)
@@ -3081,6 +3081,9 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
        case RADEON_PARAM_NUM_GB_PIPES:
                value = dev_priv->num_gb_pipes;
                break;
+       case RADEON_PARAM_NUM_Z_PIPES:
+               value = dev_priv->num_z_pipes;
+               break;
        default:
                DRM_DEBUG("Invalid parameter %d\n", param->param);
                return -EINVAL;
diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c
new file mode 100644 (file)
index 0000000..03c33cf
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2009 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Michel Dänzer
+ */
+#include <drm/drmP.h>
+#include <drm/radeon_drm.h>
+#include "radeon_reg.h"
+#include "radeon.h"
+
+
+/* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */
+void radeon_test_moves(struct radeon_device *rdev)
+{
+       struct radeon_object *vram_obj = NULL;
+       struct radeon_object **gtt_obj = NULL;
+       struct radeon_fence *fence = NULL;
+       uint64_t gtt_addr, vram_addr;
+       unsigned i, n, size;
+       int r;
+
+       size = 1024 * 1024;
+
+       /* Number of tests =
+        * (Total GTT - IB pool - writeback page - ring buffer) / test size
+        */
+       n = (rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - 4096 -
+            rdev->cp.ring_size) / size;
+
+       gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL);
+       if (!gtt_obj) {
+               DRM_ERROR("Failed to allocate %d pointers\n", n);
+               r = 1;
+               goto out_cleanup;
+       }
+
+       r = radeon_object_create(rdev, NULL, size, true, RADEON_GEM_DOMAIN_VRAM,
+                                false, &vram_obj);
+       if (r) {
+               DRM_ERROR("Failed to create VRAM object\n");
+               goto out_cleanup;
+       }
+
+       r = radeon_object_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr);
+       if (r) {
+               DRM_ERROR("Failed to pin VRAM object\n");
+               goto out_cleanup;
+       }
+
+       for (i = 0; i < n; i++) {
+               void *gtt_map, *vram_map;
+               void **gtt_start, **gtt_end;
+               void **vram_start, **vram_end;
+
+               r = radeon_object_create(rdev, NULL, size, true,
+                                        RADEON_GEM_DOMAIN_GTT, false, gtt_obj + i);
+               if (r) {
+                       DRM_ERROR("Failed to create GTT object %d\n", i);
+                       goto out_cleanup;
+               }
+
+               r = radeon_object_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, &gtt_addr);
+               if (r) {
+                       DRM_ERROR("Failed to pin GTT object %d\n", i);
+                       goto out_cleanup;
+               }
+
+               r = radeon_object_kmap(gtt_obj[i], &gtt_map);
+               if (r) {
+                       DRM_ERROR("Failed to map GTT object %d\n", i);
+                       goto out_cleanup;
+               }
+
+               for (gtt_start = gtt_map, gtt_end = gtt_map + size;
+                    gtt_start < gtt_end;
+                    gtt_start++)
+                       *gtt_start = gtt_start;
+
+               radeon_object_kunmap(gtt_obj[i]);
+
+               r = radeon_fence_create(rdev, &fence);
+               if (r) {
+                       DRM_ERROR("Failed to create GTT->VRAM fence %d\n", i);
+                       goto out_cleanup;
+               }
+
+               r = radeon_copy(rdev, gtt_addr, vram_addr, size / 4096, fence);
+               if (r) {
+                       DRM_ERROR("Failed GTT->VRAM copy %d\n", i);
+                       goto out_cleanup;
+               }
+
+               r = radeon_fence_wait(fence, false);
+               if (r) {
+                       DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i);
+                       goto out_cleanup;
+               }
+
+               radeon_fence_unref(&fence);
+
+               r = radeon_object_kmap(vram_obj, &vram_map);
+               if (r) {
+                       DRM_ERROR("Failed to map VRAM object after copy %d\n", i);
+                       goto out_cleanup;
+               }
+
+               for (gtt_start = gtt_map, gtt_end = gtt_map + size,
+                    vram_start = vram_map, vram_end = vram_map + size;
+                    vram_start < vram_end;
+                    gtt_start++, vram_start++) {
+                       if (*vram_start != gtt_start) {
+                               DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, "
+                                         "expected 0x%p (GTT map 0x%p-0x%p)\n",
+                                         i, *vram_start, gtt_start, gtt_map,
+                                         gtt_end);
+                               radeon_object_kunmap(vram_obj);
+                               goto out_cleanup;
+                       }
+                       *vram_start = vram_start;
+               }
+
+               radeon_object_kunmap(vram_obj);
+
+               r = radeon_fence_create(rdev, &fence);
+               if (r) {
+                       DRM_ERROR("Failed to create VRAM->GTT fence %d\n", i);
+                       goto out_cleanup;
+               }
+
+               r = radeon_copy(rdev, vram_addr, gtt_addr, size / 4096, fence);
+               if (r) {
+                       DRM_ERROR("Failed VRAM->GTT copy %d\n", i);
+                       goto out_cleanup;
+               }
+
+               r = radeon_fence_wait(fence, false);
+               if (r) {
+                       DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i);
+                       goto out_cleanup;
+               }
+
+               radeon_fence_unref(&fence);
+
+               r = radeon_object_kmap(gtt_obj[i], &gtt_map);
+               if (r) {
+                       DRM_ERROR("Failed to map GTT object after copy %d\n", i);
+                       goto out_cleanup;
+               }
+
+               for (gtt_start = gtt_map, gtt_end = gtt_map + size,
+                    vram_start = vram_map, vram_end = vram_map + size;
+                    gtt_start < gtt_end;
+                    gtt_start++, vram_start++) {
+                       if (*gtt_start != vram_start) {
+                               DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, "
+                                         "expected 0x%p (VRAM map 0x%p-0x%p)\n",
+                                         i, *gtt_start, vram_start, vram_map,
+                                         vram_end);
+                               radeon_object_kunmap(gtt_obj[i]);
+                               goto out_cleanup;
+                       }
+               }
+
+               radeon_object_kunmap(gtt_obj[i]);
+
+               DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n",
+                        gtt_addr - rdev->mc.gtt_location);
+       }
+
+out_cleanup:
+       if (vram_obj) {
+               radeon_object_unpin(vram_obj);
+               radeon_object_unref(&vram_obj);
+       }
+       if (gtt_obj) {
+               for (i = 0; i < n; i++) {
+                       if (gtt_obj[i]) {
+                               radeon_object_unpin(gtt_obj[i]);
+                               radeon_object_unref(&gtt_obj[i]);
+                       }
+               }
+               kfree(gtt_obj);
+       }
+       if (fence) {
+               radeon_fence_unref(&fence);
+       }
+       if (r) {
+               printk(KERN_WARNING "Error while testing BO move.\n");
+       }
+}
+
index 1227a97f5169dc3f6c0f34da6bea4d89076e067f..15c3531377ed2188c0e3ce5fad1705db31029288 100644 (file)
@@ -355,23 +355,26 @@ static int radeon_bo_move(struct ttm_buffer_object *bo,
        if (!rdev->cp.ready) {
                /* use memcpy */
                DRM_ERROR("CP is not ready use memcpy.\n");
-               return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+               goto memcpy;
        }
 
        if (old_mem->mem_type == TTM_PL_VRAM &&
            new_mem->mem_type == TTM_PL_SYSTEM) {
-               return radeon_move_vram_ram(bo, evict, interruptible,
+               r = radeon_move_vram_ram(bo, evict, interruptible,
                                            no_wait, new_mem);
        } else if (old_mem->mem_type == TTM_PL_SYSTEM &&
                   new_mem->mem_type == TTM_PL_VRAM) {
-               return radeon_move_ram_vram(bo, evict, interruptible,
+               r = radeon_move_ram_vram(bo, evict, interruptible,
                                            no_wait, new_mem);
        } else {
                r = radeon_move_blit(bo, evict, no_wait, new_mem, old_mem);
-               if (unlikely(r)) {
-                       return r;
-               }
        }
+
+       if (r) {
+memcpy:
+               r = ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
+       }
+
        return r;
 }
 
@@ -429,6 +432,8 @@ static struct ttm_bo_driver radeon_bo_driver = {
        .sync_obj_flush = &radeon_sync_obj_flush,
        .sync_obj_unref = &radeon_sync_obj_unref,
        .sync_obj_ref = &radeon_sync_obj_ref,
+       .move_notify = &radeon_bo_move_notify,
+       .fault_reserve_notify = &radeon_bo_fault_reserve_notify,
 };
 
 int radeon_ttm_init(struct radeon_device *rdev)
@@ -442,13 +447,14 @@ int radeon_ttm_init(struct radeon_device *rdev)
        /* No others user of address space so set it to 0 */
        r = ttm_bo_device_init(&rdev->mman.bdev,
                               rdev->mman.mem_global_ref.object,
-                              &radeon_bo_driver, DRM_FILE_PAGE_OFFSET);
+                              &radeon_bo_driver, DRM_FILE_PAGE_OFFSET,
+                              rdev->need_dma32);
        if (r) {
                DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
                return r;
        }
        r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, 0,
-                          ((rdev->mc.aper_size) >> PAGE_SHIFT));
+                          ((rdev->mc.real_vram_size) >> PAGE_SHIFT));
        if (r) {
                DRM_ERROR("Failed initializing VRAM heap.\n");
                return r;
@@ -465,7 +471,7 @@ int radeon_ttm_init(struct radeon_device *rdev)
                return r;
        }
        DRM_INFO("radeon: %uM of VRAM memory ready\n",
-                rdev->mc.vram_size / (1024 * 1024));
+                rdev->mc.real_vram_size / (1024 * 1024));
        r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, 0,
                           ((rdev->mc.gtt_size) >> PAGE_SHIFT));
        if (r) {
index cc074b5a8f74b13f5f8069b5fc955229e2cb92c1..b29affd9c5d8e87797f34d7afe06b3a03ecc8753 100644 (file)
@@ -29,6 +29,7 @@
 #include <drm/drmP.h>
 #include "radeon_reg.h"
 #include "radeon.h"
+#include "radeon_share.h"
 
 /* rs400,rs480 depends on : */
 void r100_hdp_reset(struct radeon_device *rdev);
@@ -164,7 +165,9 @@ int rs400_gart_enable(struct radeon_device *rdev)
                WREG32(RADEON_BUS_CNTL, tmp);
        }
        /* Table should be in 32bits address space so ignore bits above. */
-       tmp = rdev->gart.table_addr & 0xfffff000;
+       tmp = (u32)rdev->gart.table_addr & 0xfffff000;
+       tmp |= (upper_32_bits(rdev->gart.table_addr) & 0xff) << 4;
+
        WREG32_MC(RS480_GART_BASE, tmp);
        /* TODO: more tweaking here */
        WREG32_MC(RS480_GART_FEATURE_ID,
@@ -201,10 +204,17 @@ void rs400_gart_disable(struct radeon_device *rdev)
 
 int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
 {
+       uint32_t entry;
+
        if (i < 0 || i > rdev->gart.num_gpu_pages) {
                return -EINVAL;
        }
-       rdev->gart.table.ram.ptr[i] = cpu_to_le32(((uint32_t)addr) | 0xC);
+
+       entry = (lower_32_bits(addr) & PAGE_MASK) |
+               ((upper_32_bits(addr) & 0xff) << 4) |
+               0xc;
+       entry = cpu_to_le32(entry);
+       rdev->gart.table.ram.ptr[i] = entry;
        return 0;
 }
 
@@ -223,10 +233,9 @@ int rs400_mc_init(struct radeon_device *rdev)
 
        rs400_gpu_init(rdev);
        rs400_gart_disable(rdev);
-       rdev->mc.gtt_location = rdev->mc.vram_size;
+       rdev->mc.gtt_location = rdev->mc.mc_vram_size;
        rdev->mc.gtt_location += (rdev->mc.gtt_size - 1);
        rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1);
-       rdev->mc.vram_location = 0xFFFFFFFFUL;
        r = radeon_mc_setup(rdev);
        if (r) {
                return r;
@@ -238,7 +247,7 @@ int rs400_mc_init(struct radeon_device *rdev)
                       "programming pipes. Bad things might happen.\n");
        }
 
-       tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
+       tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
        tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16);
        tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16);
        WREG32(RADEON_MC_FB_LOCATION, tmp);
@@ -284,21 +293,12 @@ void rs400_gpu_init(struct radeon_device *rdev)
  */
 void rs400_vram_info(struct radeon_device *rdev)
 {
-       uint32_t tom;
-
        rs400_gart_adjust_size(rdev);
        /* DDR for all card after R300 & IGP */
        rdev->mc.vram_is_ddr = true;
        rdev->mc.vram_width = 128;
 
-       /* read NB_TOM to get the amount of ram stolen for the GPU */
-       tom = RREG32(RADEON_NB_TOM);
-       rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16);
-       WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
-
-       /* Could aper size report 0 ? */
-       rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
-       rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+       r100_vram_init_sizes(rdev);
 }
 
 
index ab0c967553e6086a22e60f867e2f3bc339c68129..02fd11aad6a28bed2f30eb111ec0a187d114cb63 100644 (file)
@@ -223,7 +223,7 @@ int rs600_mc_init(struct radeon_device *rdev)
                printk(KERN_WARNING "Failed to wait MC idle while "
                       "programming pipes. Bad things might happen.\n");
        }
-       tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
+       tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
        tmp = REG_SET(RS600_MC_FB_TOP, tmp >> 16);
        tmp |= REG_SET(RS600_MC_FB_START, rdev->mc.vram_location >> 16);
        WREG32_MC(RS600_MC_FB_LOCATION, tmp);
@@ -239,6 +239,88 @@ void rs600_mc_fini(struct radeon_device *rdev)
 }
 
 
+/*
+ * Interrupts
+ */
+int rs600_irq_set(struct radeon_device *rdev)
+{
+       uint32_t tmp = 0;
+       uint32_t mode_int = 0;
+
+       if (rdev->irq.sw_int) {
+               tmp |= RADEON_SW_INT_ENABLE;
+       }
+       if (rdev->irq.crtc_vblank_int[0]) {
+               tmp |= AVIVO_DISPLAY_INT_STATUS;
+               mode_int |= AVIVO_D1MODE_INT_MASK;
+       }
+       if (rdev->irq.crtc_vblank_int[1]) {
+               tmp |= AVIVO_DISPLAY_INT_STATUS;
+               mode_int |= AVIVO_D2MODE_INT_MASK;
+       }
+       WREG32(RADEON_GEN_INT_CNTL, tmp);
+       WREG32(AVIVO_DxMODE_INT_MASK, mode_int);
+       return 0;
+}
+
+static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_int)
+{
+       uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS);
+       uint32_t irq_mask = RADEON_SW_INT_TEST;
+
+       if (irqs & AVIVO_DISPLAY_INT_STATUS) {
+               *r500_disp_int = RREG32(AVIVO_DISP_INTERRUPT_STATUS);
+               if (*r500_disp_int & AVIVO_D1_VBLANK_INTERRUPT) {
+                       WREG32(AVIVO_D1MODE_VBLANK_STATUS, AVIVO_VBLANK_ACK);
+               }
+               if (*r500_disp_int & AVIVO_D2_VBLANK_INTERRUPT) {
+                       WREG32(AVIVO_D2MODE_VBLANK_STATUS, AVIVO_VBLANK_ACK);
+               }
+       } else {
+               *r500_disp_int = 0;
+       }
+
+       if (irqs) {
+               WREG32(RADEON_GEN_INT_STATUS, irqs);
+       }
+       return irqs & irq_mask;
+}
+
+int rs600_irq_process(struct radeon_device *rdev)
+{
+       uint32_t status;
+       uint32_t r500_disp_int;
+
+       status = rs600_irq_ack(rdev, &r500_disp_int);
+       if (!status && !r500_disp_int) {
+               return IRQ_NONE;
+       }
+       while (status || r500_disp_int) {
+               /* SW interrupt */
+               if (status & RADEON_SW_INT_TEST) {
+                       radeon_fence_process(rdev);
+               }
+               /* Vertical blank interrupts */
+               if (r500_disp_int & AVIVO_D1_VBLANK_INTERRUPT) {
+                       drm_handle_vblank(rdev->ddev, 0);
+               }
+               if (r500_disp_int & AVIVO_D2_VBLANK_INTERRUPT) {
+                       drm_handle_vblank(rdev->ddev, 1);
+               }
+               status = rs600_irq_ack(rdev, &r500_disp_int);
+       }
+       return IRQ_HANDLED;
+}
+
+u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc)
+{
+       if (crtc == 0)
+               return RREG32(AVIVO_D1CRTC_FRAME_COUNT);
+       else
+               return RREG32(AVIVO_D2CRTC_FRAME_COUNT);
+}
+
+
 /*
  * Global GPU functions
  */
@@ -301,6 +383,11 @@ void rs600_vram_info(struct radeon_device *rdev)
        rdev->mc.vram_width = 128;
 }
 
+void rs600_bandwidth_update(struct radeon_device *rdev)
+{
+       /* FIXME: implement, should this be like rs690 ? */
+}
+
 
 /*
  * Indirect registers accessor
@@ -322,3 +409,68 @@ void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
                ((reg) & RS600_MC_ADDR_MASK));
        WREG32(RS600_MC_DATA, v);
 }
+
+static const unsigned rs600_reg_safe_bm[219] = {
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
+       0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000,
+       0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
+       0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF,
+       0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
+       0x00000000, 0x0000C100, 0x00000000, 0x00000000,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF,
+       0x00000000, 0x00000000, 0x00000000, 0x00000000,
+       0x0003FC01, 0xFFFFFCF8, 0xFF800B19, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+};
+
+int rs600_init(struct radeon_device *rdev)
+{
+       rdev->config.r300.reg_safe_bm = rs600_reg_safe_bm;
+       rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rs600_reg_safe_bm);
+       return 0;
+}
index 79ba85042b5fb362d618f9e13284308607c14852..879882533e45a121e47d7eb8340a76b508d5330a 100644 (file)
@@ -28,6 +28,9 @@
 #include "drmP.h"
 #include "radeon_reg.h"
 #include "radeon.h"
+#include "rs690r.h"
+#include "atom.h"
+#include "atom-bits.h"
 
 /* rs690,rs740 depends on : */
 void r100_hdp_reset(struct radeon_device *rdev);
@@ -64,7 +67,7 @@ int rs690_mc_init(struct radeon_device *rdev)
        rs400_gart_disable(rdev);
 
        /* Setup GPU memory space */
-       rdev->mc.gtt_location = rdev->mc.vram_size;
+       rdev->mc.gtt_location = rdev->mc.mc_vram_size;
        rdev->mc.gtt_location += (rdev->mc.gtt_size - 1);
        rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1);
        rdev->mc.vram_location = 0xFFFFFFFFUL;
@@ -79,7 +82,7 @@ int rs690_mc_init(struct radeon_device *rdev)
                printk(KERN_WARNING "Failed to wait MC idle while "
                       "programming pipes. Bad things might happen.\n");
        }
-       tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
+       tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
        tmp = REG_SET(RS690_MC_FB_TOP, tmp >> 16);
        tmp |= REG_SET(RS690_MC_FB_START, rdev->mc.vram_location >> 16);
        WREG32_MC(RS690_MCCFG_FB_LOCATION, tmp);
@@ -138,9 +141,82 @@ void rs690_gpu_init(struct radeon_device *rdev)
 /*
  * VRAM info.
  */
+void rs690_pm_info(struct radeon_device *rdev)
+{
+       int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
+       struct _ATOM_INTEGRATED_SYSTEM_INFO *info;
+       struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *info_v2;
+       void *ptr;
+       uint16_t data_offset;
+       uint8_t frev, crev;
+       fixed20_12 tmp;
+
+       atom_parse_data_header(rdev->mode_info.atom_context, index, NULL,
+                              &frev, &crev, &data_offset);
+       ptr = rdev->mode_info.atom_context->bios + data_offset;
+       info = (struct _ATOM_INTEGRATED_SYSTEM_INFO *)ptr;
+       info_v2 = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *)ptr;
+       /* Get various system informations from bios */
+       switch (crev) {
+       case 1:
+               tmp.full = rfixed_const(100);
+               rdev->pm.igp_sideport_mclk.full = rfixed_const(info->ulBootUpMemoryClock);
+               rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
+               rdev->pm.igp_system_mclk.full = rfixed_const(le16_to_cpu(info->usK8MemoryClock));
+               rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->usFSBClock));
+               rdev->pm.igp_ht_link_width.full = rfixed_const(info->ucHTLinkWidth);
+               break;
+       case 2:
+               tmp.full = rfixed_const(100);
+               rdev->pm.igp_sideport_mclk.full = rfixed_const(info_v2->ulBootUpSidePortClock);
+               rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
+               rdev->pm.igp_system_mclk.full = rfixed_const(info_v2->ulBootUpUMAClock);
+               rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
+               rdev->pm.igp_ht_link_clk.full = rfixed_const(info_v2->ulHTLinkFreq);
+               rdev->pm.igp_ht_link_clk.full = rfixed_div(rdev->pm.igp_ht_link_clk, tmp);
+               rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info_v2->usMinHTLinkWidth));
+               break;
+       default:
+               tmp.full = rfixed_const(100);
+               /* We assume the slower possible clock ie worst case */
+               /* DDR 333Mhz */
+               rdev->pm.igp_sideport_mclk.full = rfixed_const(333);
+               /* FIXME: system clock ? */
+               rdev->pm.igp_system_mclk.full = rfixed_const(100);
+               rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
+               rdev->pm.igp_ht_link_clk.full = rfixed_const(200);
+               rdev->pm.igp_ht_link_width.full = rfixed_const(8);
+               DRM_ERROR("No integrated system info for your GPU, using safe default\n");
+               break;
+       }
+       /* Compute various bandwidth */
+       /* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4  */
+       tmp.full = rfixed_const(4);
+       rdev->pm.k8_bandwidth.full = rfixed_mul(rdev->pm.igp_system_mclk, tmp);
+       /* ht_bandwidth = ht_clk * 2 * ht_width / 8 * 0.8
+        *              = ht_clk * ht_width / 5
+        */
+       tmp.full = rfixed_const(5);
+       rdev->pm.ht_bandwidth.full = rfixed_mul(rdev->pm.igp_ht_link_clk,
+                                               rdev->pm.igp_ht_link_width);
+       rdev->pm.ht_bandwidth.full = rfixed_div(rdev->pm.ht_bandwidth, tmp);
+       if (tmp.full < rdev->pm.max_bandwidth.full) {
+               /* HT link is a limiting factor */
+               rdev->pm.max_bandwidth.full = tmp.full;
+       }
+       /* sideport_bandwidth = (sideport_clk / 2) * 2 * 2 * 0.7
+        *                    = (sideport_clk * 14) / 10
+        */
+       tmp.full = rfixed_const(14);
+       rdev->pm.sideport_bandwidth.full = rfixed_mul(rdev->pm.igp_sideport_mclk, tmp);
+       tmp.full = rfixed_const(10);
+       rdev->pm.sideport_bandwidth.full = rfixed_div(rdev->pm.sideport_bandwidth, tmp);
+}
+
 void rs690_vram_info(struct radeon_device *rdev)
 {
        uint32_t tmp;
+       fixed20_12 a;
 
        rs400_gart_adjust_size(rdev);
        /* DDR for all card after R300 & IGP */
@@ -152,12 +228,409 @@ void rs690_vram_info(struct radeon_device *rdev)
        } else {
                rdev->mc.vram_width = 64;
        }
-       rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
+       rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
+       rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
 
        rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
        rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+       rs690_pm_info(rdev);
+       /* FIXME: we should enforce default clock in case GPU is not in
+        * default setup
+        */
+       a.full = rfixed_const(100);
+       rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
+       rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
+       a.full = rfixed_const(16);
+       /* core_bandwidth = sclk(Mhz) * 16 */
+       rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a);
+}
+
+void rs690_line_buffer_adjust(struct radeon_device *rdev,
+                             struct drm_display_mode *mode1,
+                             struct drm_display_mode *mode2)
+{
+       u32 tmp;
+
+       /*
+        * Line Buffer Setup
+        * There is a single line buffer shared by both display controllers.
+        * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between
+        * the display controllers.  The paritioning can either be done
+        * manually or via one of four preset allocations specified in bits 1:0:
+        *  0 - line buffer is divided in half and shared between crtc
+        *  1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
+        *  2 - D1 gets the whole buffer
+        *  3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
+        * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual
+        * allocation mode. In manual allocation mode, D1 always starts at 0,
+        * D1 end/2 is specified in bits 14:4; D2 allocation follows D1.
+        */
+       tmp = RREG32(DC_LB_MEMORY_SPLIT) & ~DC_LB_MEMORY_SPLIT_MASK;
+       tmp &= ~DC_LB_MEMORY_SPLIT_SHIFT_MODE;
+       /* auto */
+       if (mode1 && mode2) {
+               if (mode1->hdisplay > mode2->hdisplay) {
+                       if (mode1->hdisplay > 2560)
+                               tmp |= DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
+                       else
+                               tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+               } else if (mode2->hdisplay > mode1->hdisplay) {
+                       if (mode2->hdisplay > 2560)
+                               tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
+                       else
+                               tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+               } else
+                       tmp |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
+       } else if (mode1) {
+               tmp |= DC_LB_MEMORY_SPLIT_D1_ONLY;
+       } else if (mode2) {
+               tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
+       }
+       WREG32(DC_LB_MEMORY_SPLIT, tmp);
+}
+
+struct rs690_watermark {
+       u32        lb_request_fifo_depth;
+       fixed20_12 num_line_pair;
+       fixed20_12 estimated_width;
+       fixed20_12 worst_case_latency;
+       fixed20_12 consumption_rate;
+       fixed20_12 active_time;
+       fixed20_12 dbpp;
+       fixed20_12 priority_mark_max;
+       fixed20_12 priority_mark;
+       fixed20_12 sclk;
+};
+
+void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
+                                 struct radeon_crtc *crtc,
+                                 struct rs690_watermark *wm)
+{
+       struct drm_display_mode *mode = &crtc->base.mode;
+       fixed20_12 a, b, c;
+       fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;
+       fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;
+       /* FIXME: detect IGP with sideport memory, i don't think there is any
+        * such product available
+        */
+       bool sideport = false;
+
+       if (!crtc->base.enabled) {
+               /* FIXME: wouldn't it better to set priority mark to maximum */
+               wm->lb_request_fifo_depth = 4;
+               return;
+       }
+
+       if (crtc->vsc.full > rfixed_const(2))
+               wm->num_line_pair.full = rfixed_const(2);
+       else
+               wm->num_line_pair.full = rfixed_const(1);
+
+       b.full = rfixed_const(mode->crtc_hdisplay);
+       c.full = rfixed_const(256);
+       a.full = rfixed_mul(wm->num_line_pair, b);
+       request_fifo_depth.full = rfixed_div(a, c);
+       if (a.full < rfixed_const(4)) {
+               wm->lb_request_fifo_depth = 4;
+       } else {
+               wm->lb_request_fifo_depth = rfixed_trunc(request_fifo_depth);
+       }
+
+       /* Determine consumption rate
+        *  pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000)
+        *  vtaps = number of vertical taps,
+        *  vsc = vertical scaling ratio, defined as source/destination
+        *  hsc = horizontal scaling ration, defined as source/destination
+        */
+       a.full = rfixed_const(mode->clock);
+       b.full = rfixed_const(1000);
+       a.full = rfixed_div(a, b);
+       pclk.full = rfixed_div(b, a);
+       if (crtc->rmx_type != RMX_OFF) {
+               b.full = rfixed_const(2);
+               if (crtc->vsc.full > b.full)
+                       b.full = crtc->vsc.full;
+               b.full = rfixed_mul(b, crtc->hsc);
+               c.full = rfixed_const(2);
+               b.full = rfixed_div(b, c);
+               consumption_time.full = rfixed_div(pclk, b);
+       } else {
+               consumption_time.full = pclk.full;
+       }
+       a.full = rfixed_const(1);
+       wm->consumption_rate.full = rfixed_div(a, consumption_time);
+
+
+       /* Determine line time
+        *  LineTime = total time for one line of displayhtotal
+        *  LineTime = total number of horizontal pixels
+        *  pclk = pixel clock period(ns)
+        */
+       a.full = rfixed_const(crtc->base.mode.crtc_htotal);
+       line_time.full = rfixed_mul(a, pclk);
+
+       /* Determine active time
+        *  ActiveTime = time of active region of display within one line,
+        *  hactive = total number of horizontal active pixels
+        *  htotal = total number of horizontal pixels
+        */
+       a.full = rfixed_const(crtc->base.mode.crtc_htotal);
+       b.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
+       wm->active_time.full = rfixed_mul(line_time, b);
+       wm->active_time.full = rfixed_div(wm->active_time, a);
+
+       /* Maximun bandwidth is the minimun bandwidth of all component */
+       rdev->pm.max_bandwidth = rdev->pm.core_bandwidth;
+       if (sideport) {
+               if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full &&
+                       rdev->pm.sideport_bandwidth.full)
+                       rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth;
+               read_delay_latency.full = rfixed_const(370 * 800 * 1000);
+               read_delay_latency.full = rfixed_div(read_delay_latency,
+                       rdev->pm.igp_sideport_mclk);
+       } else {
+               if (rdev->pm.max_bandwidth.full > rdev->pm.k8_bandwidth.full &&
+                       rdev->pm.k8_bandwidth.full)
+                       rdev->pm.max_bandwidth = rdev->pm.k8_bandwidth;
+               if (rdev->pm.max_bandwidth.full > rdev->pm.ht_bandwidth.full &&
+                       rdev->pm.ht_bandwidth.full)
+                       rdev->pm.max_bandwidth = rdev->pm.ht_bandwidth;
+               read_delay_latency.full = rfixed_const(5000);
+       }
+
+       /* sclk = system clocks(ns) = 1000 / max_bandwidth / 16 */
+       a.full = rfixed_const(16);
+       rdev->pm.sclk.full = rfixed_mul(rdev->pm.max_bandwidth, a);
+       a.full = rfixed_const(1000);
+       rdev->pm.sclk.full = rfixed_div(a, rdev->pm.sclk);
+       /* Determine chunk time
+        * ChunkTime = the time it takes the DCP to send one chunk of data
+        * to the LB which consists of pipeline delay and inter chunk gap
+        * sclk = system clock(ns)
+        */
+       a.full = rfixed_const(256 * 13);
+       chunk_time.full = rfixed_mul(rdev->pm.sclk, a);
+       a.full = rfixed_const(10);
+       chunk_time.full = rfixed_div(chunk_time, a);
+
+       /* Determine the worst case latency
+        * NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines)
+        * WorstCaseLatency = worst case time from urgent to when the MC starts
+        *                    to return data
+        * READ_DELAY_IDLE_MAX = constant of 1us
+        * ChunkTime = time it takes the DCP to send one chunk of data to the LB
+        *             which consists of pipeline delay and inter chunk gap
+        */
+       if (rfixed_trunc(wm->num_line_pair) > 1) {
+               a.full = rfixed_const(3);
+               wm->worst_case_latency.full = rfixed_mul(a, chunk_time);
+               wm->worst_case_latency.full += read_delay_latency.full;
+       } else {
+               a.full = rfixed_const(2);
+               wm->worst_case_latency.full = rfixed_mul(a, chunk_time);
+               wm->worst_case_latency.full += read_delay_latency.full;
+       }
+
+       /* Determine the tolerable latency
+        * TolerableLatency = Any given request has only 1 line time
+        *                    for the data to be returned
+        * LBRequestFifoDepth = Number of chunk requests the LB can
+        *                      put into the request FIFO for a display
+        *  LineTime = total time for one line of display
+        *  ChunkTime = the time it takes the DCP to send one chunk
+        *              of data to the LB which consists of
+        *  pipeline delay and inter chunk gap
+        */
+       if ((2+wm->lb_request_fifo_depth) >= rfixed_trunc(request_fifo_depth)) {
+               tolerable_latency.full = line_time.full;
+       } else {
+               tolerable_latency.full = rfixed_const(wm->lb_request_fifo_depth - 2);
+               tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full;
+               tolerable_latency.full = rfixed_mul(tolerable_latency, chunk_time);
+               tolerable_latency.full = line_time.full - tolerable_latency.full;
+       }
+       /* We assume worst case 32bits (4 bytes) */
+       wm->dbpp.full = rfixed_const(4 * 8);
+
+       /* Determine the maximum priority mark
+        *  width = viewport width in pixels
+        */
+       a.full = rfixed_const(16);
+       wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
+       wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a);
+
+       /* Determine estimated width */
+       estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full;
+       estimated_width.full = rfixed_div(estimated_width, consumption_time);
+       if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) {
+               wm->priority_mark.full = rfixed_const(10);
+       } else {
+               a.full = rfixed_const(16);
+               wm->priority_mark.full = rfixed_div(estimated_width, a);
+               wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full;
+       }
 }
 
+void rs690_bandwidth_update(struct radeon_device *rdev)
+{
+       struct drm_display_mode *mode0 = NULL;
+       struct drm_display_mode *mode1 = NULL;
+       struct rs690_watermark wm0;
+       struct rs690_watermark wm1;
+       u32 tmp;
+       fixed20_12 priority_mark02, priority_mark12, fill_rate;
+       fixed20_12 a, b;
+
+       if (rdev->mode_info.crtcs[0]->base.enabled)
+               mode0 = &rdev->mode_info.crtcs[0]->base.mode;
+       if (rdev->mode_info.crtcs[1]->base.enabled)
+               mode1 = &rdev->mode_info.crtcs[1]->base.mode;
+       /*
+        * Set display0/1 priority up in the memory controller for
+        * modes if the user specifies HIGH for displaypriority
+        * option.
+        */
+       if (rdev->disp_priority == 2) {
+               tmp = RREG32_MC(MC_INIT_MISC_LAT_TIMER);
+               tmp &= ~MC_DISP1R_INIT_LAT_MASK;
+               tmp &= ~MC_DISP0R_INIT_LAT_MASK;
+               if (mode1)
+                       tmp |= (1 << MC_DISP1R_INIT_LAT_SHIFT);
+               if (mode0)
+                       tmp |= (1 << MC_DISP0R_INIT_LAT_SHIFT);
+               WREG32_MC(MC_INIT_MISC_LAT_TIMER, tmp);
+       }
+       rs690_line_buffer_adjust(rdev, mode0, mode1);
+
+       if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740))
+               WREG32(DCP_CONTROL, 0);
+       if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))
+               WREG32(DCP_CONTROL, 2);
+
+       rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0);
+       rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1);
+
+       tmp = (wm0.lb_request_fifo_depth - 1);
+       tmp |= (wm1.lb_request_fifo_depth - 1) << 16;
+       WREG32(LB_MAX_REQ_OUTSTANDING, tmp);
+
+       if (mode0 && mode1) {
+               if (rfixed_trunc(wm0.dbpp) > 64)
+                       a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair);
+               else
+                       a.full = wm0.num_line_pair.full;
+               if (rfixed_trunc(wm1.dbpp) > 64)
+                       b.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair);
+               else
+                       b.full = wm1.num_line_pair.full;
+               a.full += b.full;
+               fill_rate.full = rfixed_div(wm0.sclk, a);
+               if (wm0.consumption_rate.full > fill_rate.full) {
+                       b.full = wm0.consumption_rate.full - fill_rate.full;
+                       b.full = rfixed_mul(b, wm0.active_time);
+                       a.full = rfixed_mul(wm0.worst_case_latency,
+                                               wm0.consumption_rate);
+                       a.full = a.full + b.full;
+                       b.full = rfixed_const(16 * 1000);
+                       priority_mark02.full = rfixed_div(a, b);
+               } else {
+                       a.full = rfixed_mul(wm0.worst_case_latency,
+                                               wm0.consumption_rate);
+                       b.full = rfixed_const(16 * 1000);
+                       priority_mark02.full = rfixed_div(a, b);
+               }
+               if (wm1.consumption_rate.full > fill_rate.full) {
+                       b.full = wm1.consumption_rate.full - fill_rate.full;
+                       b.full = rfixed_mul(b, wm1.active_time);
+                       a.full = rfixed_mul(wm1.worst_case_latency,
+                                               wm1.consumption_rate);
+                       a.full = a.full + b.full;
+                       b.full = rfixed_const(16 * 1000);
+                       priority_mark12.full = rfixed_div(a, b);
+               } else {
+                       a.full = rfixed_mul(wm1.worst_case_latency,
+                                               wm1.consumption_rate);
+                       b.full = rfixed_const(16 * 1000);
+                       priority_mark12.full = rfixed_div(a, b);
+               }
+               if (wm0.priority_mark.full > priority_mark02.full)
+                       priority_mark02.full = wm0.priority_mark.full;
+               if (rfixed_trunc(priority_mark02) < 0)
+                       priority_mark02.full = 0;
+               if (wm0.priority_mark_max.full > priority_mark02.full)
+                       priority_mark02.full = wm0.priority_mark_max.full;
+               if (wm1.priority_mark.full > priority_mark12.full)
+                       priority_mark12.full = wm1.priority_mark.full;
+               if (rfixed_trunc(priority_mark12) < 0)
+                       priority_mark12.full = 0;
+               if (wm1.priority_mark_max.full > priority_mark12.full)
+                       priority_mark12.full = wm1.priority_mark_max.full;
+               WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
+               WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
+               WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
+               WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+       } else if (mode0) {
+               if (rfixed_trunc(wm0.dbpp) > 64)
+                       a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair);
+               else
+                       a.full = wm0.num_line_pair.full;
+               fill_rate.full = rfixed_div(wm0.sclk, a);
+               if (wm0.consumption_rate.full > fill_rate.full) {
+                       b.full = wm0.consumption_rate.full - fill_rate.full;
+                       b.full = rfixed_mul(b, wm0.active_time);
+                       a.full = rfixed_mul(wm0.worst_case_latency,
+                                               wm0.consumption_rate);
+                       a.full = a.full + b.full;
+                       b.full = rfixed_const(16 * 1000);
+                       priority_mark02.full = rfixed_div(a, b);
+               } else {
+                       a.full = rfixed_mul(wm0.worst_case_latency,
+                                               wm0.consumption_rate);
+                       b.full = rfixed_const(16 * 1000);
+                       priority_mark02.full = rfixed_div(a, b);
+               }
+               if (wm0.priority_mark.full > priority_mark02.full)
+                       priority_mark02.full = wm0.priority_mark.full;
+               if (rfixed_trunc(priority_mark02) < 0)
+                       priority_mark02.full = 0;
+               if (wm0.priority_mark_max.full > priority_mark02.full)
+                       priority_mark02.full = wm0.priority_mark_max.full;
+               WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
+               WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
+               WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
+               WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
+       } else {
+               if (rfixed_trunc(wm1.dbpp) > 64)
+                       a.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair);
+               else
+                       a.full = wm1.num_line_pair.full;
+               fill_rate.full = rfixed_div(wm1.sclk, a);
+               if (wm1.consumption_rate.full > fill_rate.full) {
+                       b.full = wm1.consumption_rate.full - fill_rate.full;
+                       b.full = rfixed_mul(b, wm1.active_time);
+                       a.full = rfixed_mul(wm1.worst_case_latency,
+                                               wm1.consumption_rate);
+                       a.full = a.full + b.full;
+                       b.full = rfixed_const(16 * 1000);
+                       priority_mark12.full = rfixed_div(a, b);
+               } else {
+                       a.full = rfixed_mul(wm1.worst_case_latency,
+                                               wm1.consumption_rate);
+                       b.full = rfixed_const(16 * 1000);
+                       priority_mark12.full = rfixed_div(a, b);
+               }
+               if (wm1.priority_mark.full > priority_mark12.full)
+                       priority_mark12.full = wm1.priority_mark.full;
+               if (rfixed_trunc(priority_mark12) < 0)
+                       priority_mark12.full = 0;
+               if (wm1.priority_mark_max.full > priority_mark12.full)
+                       priority_mark12.full = wm1.priority_mark_max.full;
+               WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
+               WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
+               WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
+               WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+       }
+}
 
 /*
  * Indirect registers accessor
@@ -179,3 +652,4 @@ void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
        WREG32(RS690_MC_DATA, v);
        WREG32(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK);
 }
+
diff --git a/drivers/gpu/drm/radeon/rs690r.h b/drivers/gpu/drm/radeon/rs690r.h
new file mode 100644 (file)
index 0000000..c0d9faa
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef RS690R_H
+#define RS690R_H
+
+/* RS690/RS740 registers */
+#define MC_INDEX                       0x0078
+#      define MC_INDEX_MASK                    0x1FF
+#      define MC_INDEX_WR_EN                   (1 << 9)
+#      define MC_INDEX_WR_ACK                  0x7F
+#define MC_DATA                                0x007C
+#define HDP_FB_LOCATION                        0x0134
+#define DC_LB_MEMORY_SPLIT             0x6520
+#define                DC_LB_MEMORY_SPLIT_MASK                 0x00000003
+#define                DC_LB_MEMORY_SPLIT_SHIFT                0
+#define                DC_LB_MEMORY_SPLIT_D1HALF_D2HALF        0
+#define                DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q          1
+#define                DC_LB_MEMORY_SPLIT_D1_ONLY              2
+#define                DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q          3
+#define                DC_LB_MEMORY_SPLIT_SHIFT_MODE           (1 << 2)
+#define                DC_LB_DISP1_END_ADR_SHIFT               4
+#define                DC_LB_DISP1_END_ADR_MASK                0x00007FF0
+#define D1MODE_PRIORITY_A_CNT          0x6548
+#define                MODE_PRIORITY_MARK_MASK                 0x00007FFF
+#define                MODE_PRIORITY_OFF                       (1 << 16)
+#define                MODE_PRIORITY_ALWAYS_ON                 (1 << 20)
+#define                MODE_PRIORITY_FORCE_MASK                (1 << 24)
+#define D1MODE_PRIORITY_B_CNT          0x654C
+#define LB_MAX_REQ_OUTSTANDING         0x6D58
+#define                LB_D1_MAX_REQ_OUTSTANDING_MASK          0x0000000F
+#define                LB_D1_MAX_REQ_OUTSTANDING_SHIFT         0
+#define                LB_D2_MAX_REQ_OUTSTANDING_MASK          0x000F0000
+#define                LB_D2_MAX_REQ_OUTSTANDING_SHIFT         16
+#define DCP_CONTROL                    0x6C9C
+#define D2MODE_PRIORITY_A_CNT          0x6D48
+#define D2MODE_PRIORITY_B_CNT          0x6D4C
+
+/* MC indirect registers */
+#define MC_STATUS_IDLE                         (1 << 0)
+#define MC_MISC_CNTL                   0x18
+#define                DISABLE_GTW                     (1 << 1)
+#define                GART_INDEX_REG_EN               (1 << 12)
+#define                BLOCK_GFX_D3_EN                 (1 << 14)
+#define GART_FEATURE_ID                        0x2B
+#define                HANG_EN                         (1 << 11)
+#define                TLB_ENABLE                      (1 << 18)
+#define                P2P_ENABLE                      (1 << 19)
+#define                GTW_LAC_EN                      (1 << 25)
+#define                LEVEL2_GART                     (0 << 30)
+#define                LEVEL1_GART                     (1 << 30)
+#define                PDC_EN                          (1 << 31)
+#define GART_BASE                      0x2C
+#define GART_CACHE_CNTRL               0x2E
+#      define GART_CACHE_INVALIDATE            (1 << 0)
+#define MC_STATUS                      0x90
+#define MCCFG_FB_LOCATION              0x100
+#define                MC_FB_START_MASK                0x0000FFFF
+#define                MC_FB_START_SHIFT               0
+#define                MC_FB_TOP_MASK                  0xFFFF0000
+#define                MC_FB_TOP_SHIFT                 16
+#define MCCFG_AGP_LOCATION             0x101
+#define                MC_AGP_START_MASK               0x0000FFFF
+#define                MC_AGP_START_SHIFT              0
+#define                MC_AGP_TOP_MASK                 0xFFFF0000
+#define                MC_AGP_TOP_SHIFT                16
+#define MCCFG_AGP_BASE                 0x102
+#define MCCFG_AGP_BASE_2               0x103
+#define MC_INIT_MISC_LAT_TIMER         0x104
+#define                MC_DISP0R_INIT_LAT_SHIFT        8
+#define                MC_DISP0R_INIT_LAT_MASK         0x00000F00
+#define                MC_DISP1R_INIT_LAT_SHIFT        12
+#define                MC_DISP1R_INIT_LAT_MASK         0x0000F000
+
+#endif
index ffea37b1b3e23db02a8f2f59b480cf9274e7233f..0566fb67e4607b4c50d335df74a5ef25d9d55f1a 100644 (file)
@@ -27,8 +27,9 @@
  */
 #include <linux/seq_file.h>
 #include "drmP.h"
-#include "radeon_reg.h"
+#include "rv515r.h"
 #include "radeon.h"
+#include "radeon_share.h"
 
 /* rv515 depends on : */
 void r100_hdp_reset(struct radeon_device *rdev);
@@ -99,26 +100,26 @@ int rv515_mc_init(struct radeon_device *rdev)
                       "programming pipes. Bad things might happen.\n");
        }
        /* Write VRAM size in case we are limiting it */
-       WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
-       tmp = REG_SET(RV515_MC_FB_START, rdev->mc.vram_location >> 16);
+       WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
+       tmp = REG_SET(MC_FB_START, rdev->mc.vram_location >> 16);
        WREG32(0x134, tmp);
-       tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
-       tmp = REG_SET(RV515_MC_FB_TOP, tmp >> 16);
-       tmp |= REG_SET(RV515_MC_FB_START, rdev->mc.vram_location >> 16);
-       WREG32_MC(RV515_MC_FB_LOCATION, tmp);
-       WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16);
+       tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
+       tmp = REG_SET(MC_FB_TOP, tmp >> 16);
+       tmp |= REG_SET(MC_FB_START, rdev->mc.vram_location >> 16);
+       WREG32_MC(MC_FB_LOCATION, tmp);
+       WREG32(HDP_FB_LOCATION, rdev->mc.vram_location >> 16);
        WREG32(0x310, rdev->mc.vram_location);
        if (rdev->flags & RADEON_IS_AGP) {
                tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
-               tmp = REG_SET(RV515_MC_AGP_TOP, tmp >> 16);
-               tmp |= REG_SET(RV515_MC_AGP_START, rdev->mc.gtt_location >> 16);
-               WREG32_MC(RV515_MC_AGP_LOCATION, tmp);
-               WREG32_MC(RV515_MC_AGP_BASE, rdev->mc.agp_base);
-               WREG32_MC(RV515_MC_AGP_BASE_2, 0);
+               tmp = REG_SET(MC_AGP_TOP, tmp >> 16);
+               tmp |= REG_SET(MC_AGP_START, rdev->mc.gtt_location >> 16);
+               WREG32_MC(MC_AGP_LOCATION, tmp);
+               WREG32_MC(MC_AGP_BASE, rdev->mc.agp_base);
+               WREG32_MC(MC_AGP_BASE_2, 0);
        } else {
-               WREG32_MC(RV515_MC_AGP_LOCATION, 0x0FFFFFFF);
-               WREG32_MC(RV515_MC_AGP_BASE, 0);
-               WREG32_MC(RV515_MC_AGP_BASE_2, 0);
+               WREG32_MC(MC_AGP_LOCATION, 0x0FFFFFFF);
+               WREG32_MC(MC_AGP_BASE, 0);
+               WREG32_MC(MC_AGP_BASE_2, 0);
        }
        return 0;
 }
@@ -136,95 +137,67 @@ void rv515_mc_fini(struct radeon_device *rdev)
  */
 void rv515_ring_start(struct radeon_device *rdev)
 {
-       unsigned gb_tile_config;
        int r;
 
-       /* Sub pixel 1/12 so we can have 4K rendering according to doc */
-       gb_tile_config = R300_ENABLE_TILING | R300_TILE_SIZE_16;
-       switch (rdev->num_gb_pipes) {
-       case 2:
-               gb_tile_config |= R300_PIPE_COUNT_R300;
-               break;
-       case 3:
-               gb_tile_config |= R300_PIPE_COUNT_R420_3P;
-               break;
-       case 4:
-               gb_tile_config |= R300_PIPE_COUNT_R420;
-               break;
-       case 1:
-       default:
-               gb_tile_config |= R300_PIPE_COUNT_RV350;
-               break;
-       }
-
        r = radeon_ring_lock(rdev, 64);
        if (r) {
                return;
        }
-       radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0));
-       radeon_ring_write(rdev,
-                         RADEON_ISYNC_ANY2D_IDLE3D |
-                         RADEON_ISYNC_ANY3D_IDLE2D |
-                         RADEON_ISYNC_WAIT_IDLEGUI |
-                         RADEON_ISYNC_CPSCRATCH_IDLEGUI);
-       radeon_ring_write(rdev, PACKET0(R300_GB_TILE_CONFIG, 0));
-       radeon_ring_write(rdev, gb_tile_config);
-       radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
+       radeon_ring_write(rdev, PACKET0(ISYNC_CNTL, 0));
        radeon_ring_write(rdev,
-                         RADEON_WAIT_2D_IDLECLEAN |
-                         RADEON_WAIT_3D_IDLECLEAN);
+                         ISYNC_ANY2D_IDLE3D |
+                         ISYNC_ANY3D_IDLE2D |
+                         ISYNC_WAIT_IDLEGUI |
+                         ISYNC_CPSCRATCH_IDLEGUI);
+       radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0));
+       radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN);
        radeon_ring_write(rdev, PACKET0(0x170C, 0));
        radeon_ring_write(rdev, 1 << 31);
-       radeon_ring_write(rdev, PACKET0(R300_GB_SELECT, 0));
+       radeon_ring_write(rdev, PACKET0(GB_SELECT, 0));
        radeon_ring_write(rdev, 0);
-       radeon_ring_write(rdev, PACKET0(R300_GB_ENABLE, 0));
+       radeon_ring_write(rdev, PACKET0(GB_ENABLE, 0));
        radeon_ring_write(rdev, 0);
        radeon_ring_write(rdev, PACKET0(0x42C8, 0));
        radeon_ring_write(rdev, (1 << rdev->num_gb_pipes) - 1);
-       radeon_ring_write(rdev, PACKET0(R500_VAP_INDEX_OFFSET, 0));
+       radeon_ring_write(rdev, PACKET0(VAP_INDEX_OFFSET, 0));
        radeon_ring_write(rdev, 0);
-       radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
-       radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE);
-       radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
-       radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE);
-       radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
-       radeon_ring_write(rdev,
-                         RADEON_WAIT_2D_IDLECLEAN |
-                         RADEON_WAIT_3D_IDLECLEAN);
-       radeon_ring_write(rdev, PACKET0(R300_GB_AA_CONFIG, 0));
+       radeon_ring_write(rdev, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0));
+       radeon_ring_write(rdev, RB3D_DC_FLUSH | RB3D_DC_FREE);
+       radeon_ring_write(rdev, PACKET0(ZB_ZCACHE_CTLSTAT, 0));
+       radeon_ring_write(rdev, ZC_FLUSH | ZC_FREE);
+       radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0));
+       radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN);
+       radeon_ring_write(rdev, PACKET0(GB_AA_CONFIG, 0));
        radeon_ring_write(rdev, 0);
-       radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
-       radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE);
-       radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
-       radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE);
-       radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS0, 0));
-       radeon_ring_write(rdev,
-                         ((6 << R300_MS_X0_SHIFT) |
-                          (6 << R300_MS_Y0_SHIFT) |
-                          (6 << R300_MS_X1_SHIFT) |
-                          (6 << R300_MS_Y1_SHIFT) |
-                          (6 << R300_MS_X2_SHIFT) |
-                          (6 << R300_MS_Y2_SHIFT) |
-                          (6 << R300_MSBD0_Y_SHIFT) |
-                          (6 << R300_MSBD0_X_SHIFT)));
-       radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS1, 0));
-       radeon_ring_write(rdev,
-                         ((6 << R300_MS_X3_SHIFT) |
-                          (6 << R300_MS_Y3_SHIFT) |
-                          (6 << R300_MS_X4_SHIFT) |
-                          (6 << R300_MS_Y4_SHIFT) |
-                          (6 << R300_MS_X5_SHIFT) |
-                          (6 << R300_MS_Y5_SHIFT) |
-                          (6 << R300_MSBD1_SHIFT)));
-       radeon_ring_write(rdev, PACKET0(R300_GA_ENHANCE, 0));
-       radeon_ring_write(rdev, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL);
-       radeon_ring_write(rdev, PACKET0(R300_GA_POLY_MODE, 0));
+       radeon_ring_write(rdev, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0));
+       radeon_ring_write(rdev, RB3D_DC_FLUSH | RB3D_DC_FREE);
+       radeon_ring_write(rdev, PACKET0(ZB_ZCACHE_CTLSTAT, 0));
+       radeon_ring_write(rdev, ZC_FLUSH | ZC_FREE);
+       radeon_ring_write(rdev, PACKET0(GB_MSPOS0, 0));
        radeon_ring_write(rdev,
-                         R300_FRONT_PTYPE_TRIANGE | R300_BACK_PTYPE_TRIANGE);
-       radeon_ring_write(rdev, PACKET0(R300_GA_ROUND_MODE, 0));
+                         ((6 << MS_X0_SHIFT) |
+                          (6 << MS_Y0_SHIFT) |
+                          (6 << MS_X1_SHIFT) |
+                          (6 << MS_Y1_SHIFT) |
+                          (6 << MS_X2_SHIFT) |
+                          (6 << MS_Y2_SHIFT) |
+                          (6 << MSBD0_Y_SHIFT) |
+                          (6 << MSBD0_X_SHIFT)));
+       radeon_ring_write(rdev, PACKET0(GB_MSPOS1, 0));
        radeon_ring_write(rdev,
-                         R300_GEOMETRY_ROUND_NEAREST |
-                         R300_COLOR_ROUND_NEAREST);
+                         ((6 << MS_X3_SHIFT) |
+                          (6 << MS_Y3_SHIFT) |
+                          (6 << MS_X4_SHIFT) |
+                          (6 << MS_Y4_SHIFT) |
+                          (6 << MS_X5_SHIFT) |
+                          (6 << MS_Y5_SHIFT) |
+                          (6 << MSBD1_SHIFT)));
+       radeon_ring_write(rdev, PACKET0(GA_ENHANCE, 0));
+       radeon_ring_write(rdev, GA_DEADLOCK_CNTL | GA_FASTSYNC_CNTL);
+       radeon_ring_write(rdev, PACKET0(GA_POLY_MODE, 0));
+       radeon_ring_write(rdev, FRONT_PTYPE_TRIANGE | BACK_PTYPE_TRIANGE);
+       radeon_ring_write(rdev, PACKET0(GA_ROUND_MODE, 0));
+       radeon_ring_write(rdev, GEOMETRY_ROUND_NEAREST | COLOR_ROUND_NEAREST);
        radeon_ring_write(rdev, PACKET0(0x20C8, 0));
        radeon_ring_write(rdev, 0);
        radeon_ring_unlock_commit(rdev);
@@ -242,8 +215,8 @@ int rv515_mc_wait_for_idle(struct radeon_device *rdev)
 
        for (i = 0; i < rdev->usec_timeout; i++) {
                /* read MC_STATUS */
-               tmp = RREG32_MC(RV515_MC_STATUS);
-               if (tmp & RV515_MC_STATUS_IDLE) {
+               tmp = RREG32_MC(MC_STATUS);
+               if (tmp & MC_STATUS_IDLE) {
                        return 0;
                }
                DRM_UDELAY(1);
@@ -291,33 +264,33 @@ int rv515_ga_reset(struct radeon_device *rdev)
        reinit_cp = rdev->cp.ready;
        rdev->cp.ready = false;
        for (i = 0; i < rdev->usec_timeout; i++) {
-               WREG32(RADEON_CP_CSQ_MODE, 0);
-               WREG32(RADEON_CP_CSQ_CNTL, 0);
-               WREG32(RADEON_RBBM_SOFT_RESET, 0x32005);
-               (void)RREG32(RADEON_RBBM_SOFT_RESET);
+               WREG32(CP_CSQ_MODE, 0);
+               WREG32(CP_CSQ_CNTL, 0);
+               WREG32(RBBM_SOFT_RESET, 0x32005);
+               (void)RREG32(RBBM_SOFT_RESET);
                udelay(200);
-               WREG32(RADEON_RBBM_SOFT_RESET, 0);
+               WREG32(RBBM_SOFT_RESET, 0);
                /* Wait to prevent race in RBBM_STATUS */
                mdelay(1);
-               tmp = RREG32(RADEON_RBBM_STATUS);
+               tmp = RREG32(RBBM_STATUS);
                if (tmp & ((1 << 20) | (1 << 26))) {
                        DRM_ERROR("VAP & CP still busy (RBBM_STATUS=0x%08X)\n", tmp);
                        /* GA still busy soft reset it */
                        WREG32(0x429C, 0x200);
-                       WREG32(R300_VAP_PVS_STATE_FLUSH_REG, 0);
+                       WREG32(VAP_PVS_STATE_FLUSH_REG, 0);
                        WREG32(0x43E0, 0);
                        WREG32(0x43E4, 0);
                        WREG32(0x24AC, 0);
                }
                /* Wait to prevent race in RBBM_STATUS */
                mdelay(1);
-               tmp = RREG32(RADEON_RBBM_STATUS);
+               tmp = RREG32(RBBM_STATUS);
                if (!(tmp & ((1 << 20) | (1 << 26)))) {
                        break;
                }
        }
        for (i = 0; i < rdev->usec_timeout; i++) {
-               tmp = RREG32(RADEON_RBBM_STATUS);
+               tmp = RREG32(RBBM_STATUS);
                if (!(tmp & ((1 << 20) | (1 << 26)))) {
                        DRM_INFO("GA reset succeed (RBBM_STATUS=0x%08X)\n",
                                 tmp);
@@ -331,7 +304,7 @@ int rv515_ga_reset(struct radeon_device *rdev)
                }
                DRM_UDELAY(1);
        }
-       tmp = RREG32(RADEON_RBBM_STATUS);
+       tmp = RREG32(RBBM_STATUS);
        DRM_ERROR("Failed to reset GA ! (RBBM_STATUS=0x%08X)\n", tmp);
        return -1;
 }
@@ -341,7 +314,7 @@ int rv515_gpu_reset(struct radeon_device *rdev)
        uint32_t status;
 
        /* reset order likely matter */
-       status = RREG32(RADEON_RBBM_STATUS);
+       status = RREG32(RBBM_STATUS);
        /* reset HDP */
        r100_hdp_reset(rdev);
        /* reset rb2d */
@@ -353,12 +326,12 @@ int rv515_gpu_reset(struct radeon_device *rdev)
                rv515_ga_reset(rdev);
        }
        /* reset CP */
-       status = RREG32(RADEON_RBBM_STATUS);
+       status = RREG32(RBBM_STATUS);
        if (status & (1 << 16)) {
                r100_cp_reset(rdev);
        }
        /* Check if GPU is idle */
-       status = RREG32(RADEON_RBBM_STATUS);
+       status = RREG32(RBBM_STATUS);
        if (status & (1 << 31)) {
                DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status);
                return -1;
@@ -377,8 +350,7 @@ static void rv515_vram_get_type(struct radeon_device *rdev)
 
        rdev->mc.vram_width = 128;
        rdev->mc.vram_is_ddr = true;
-       tmp = RREG32_MC(RV515_MC_CNTL);
-       tmp &= RV515_MEM_NUM_CHANNELS_MASK;
+       tmp = RREG32_MC(RV515_MC_CNTL) & MEM_NUM_CHANNELS_MASK;
        switch (tmp) {
        case 0:
                rdev->mc.vram_width = 64;
@@ -394,11 +366,17 @@ static void rv515_vram_get_type(struct radeon_device *rdev)
 
 void rv515_vram_info(struct radeon_device *rdev)
 {
+       fixed20_12 a;
+
        rv515_vram_get_type(rdev);
-       rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
 
-       rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
-       rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
+       r100_vram_init_sizes(rdev);
+       /* FIXME: we should enforce default clock in case GPU is not in
+        * default setup
+        */
+       a.full = rfixed_const(100);
+       rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
+       rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
 }
 
 
@@ -409,38 +387,19 @@ uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg)
 {
        uint32_t r;
 
-       WREG32(R520_MC_IND_INDEX, 0x7f0000 | (reg & 0xffff));
-       r = RREG32(R520_MC_IND_DATA);
-       WREG32(R520_MC_IND_INDEX, 0);
+       WREG32(MC_IND_INDEX, 0x7f0000 | (reg & 0xffff));
+       r = RREG32(MC_IND_DATA);
+       WREG32(MC_IND_INDEX, 0);
        return r;
 }
 
 void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
 {
-       WREG32(R520_MC_IND_INDEX, 0xff0000 | ((reg) & 0xffff));
-       WREG32(R520_MC_IND_DATA, (v));
-       WREG32(R520_MC_IND_INDEX, 0);
-}
-
-uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg)
-{
-       uint32_t r;
-
-       WREG32(RADEON_PCIE_INDEX, ((reg) & 0x7ff));
-       (void)RREG32(RADEON_PCIE_INDEX);
-       r = RREG32(RADEON_PCIE_DATA);
-       return r;
-}
-
-void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
-{
-       WREG32(RADEON_PCIE_INDEX, ((reg) & 0x7ff));
-       (void)RREG32(RADEON_PCIE_INDEX);
-       WREG32(RADEON_PCIE_DATA, (v));
-       (void)RREG32(RADEON_PCIE_DATA);
+       WREG32(MC_IND_INDEX, 0xff0000 | ((reg) & 0xffff));
+       WREG32(MC_IND_DATA, (v));
+       WREG32(MC_IND_INDEX, 0);
 }
 
-
 /*
  * Debugfs info
  */
@@ -452,13 +411,13 @@ static int rv515_debugfs_pipes_info(struct seq_file *m, void *data)
        struct radeon_device *rdev = dev->dev_private;
        uint32_t tmp;
 
-       tmp = RREG32(R400_GB_PIPE_SELECT);
+       tmp = RREG32(GB_PIPE_SELECT);
        seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp);
-       tmp = RREG32(R500_SU_REG_DEST);
+       tmp = RREG32(SU_REG_DEST);
        seq_printf(m, "SU_REG_DEST 0x%08x\n", tmp);
-       tmp = RREG32(R300_GB_TILE_CONFIG);
+       tmp = RREG32(GB_TILE_CONFIG);
        seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp);
-       tmp = RREG32(R300_DST_PIPE_CONFIG);
+       tmp = RREG32(DST_PIPE_CONFIG);
        seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp);
        return 0;
 }
@@ -509,9 +468,9 @@ int rv515_debugfs_ga_info_init(struct radeon_device *rdev)
 /*
  * Asic initialization
  */
-static const unsigned r500_reg_safe_bm[159] = {
+static const unsigned r500_reg_safe_bm[219] = {
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
-       0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF,
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
@@ -549,14 +508,575 @@ static const unsigned r500_reg_safe_bm[159] = {
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
        0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF80FFFF,
        0x00000000, 0x00000000, 0x00000000, 0x00000000,
-       0x0003FC01, 0x3FFFFCF8, 0xFE800B19,
+       0x0003FC01, 0x3FFFFCF8, 0xFF800B19, 0xFFDFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+       0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
 };
 
-
-
 int rv515_init(struct radeon_device *rdev)
 {
        rdev->config.r300.reg_safe_bm = r500_reg_safe_bm;
        rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r500_reg_safe_bm);
        return 0;
 }
+
+void atom_rv515_force_tv_scaler(struct radeon_device *rdev)
+{
+
+       WREG32(0x659C, 0x0);
+       WREG32(0x6594, 0x705);
+       WREG32(0x65A4, 0x10001);
+       WREG32(0x65D8, 0x0);
+       WREG32(0x65B0, 0x0);
+       WREG32(0x65C0, 0x0);
+       WREG32(0x65D4, 0x0);
+       WREG32(0x6578, 0x0);
+       WREG32(0x657C, 0x841880A8);
+       WREG32(0x6578, 0x1);
+       WREG32(0x657C, 0x84208680);
+       WREG32(0x6578, 0x2);
+       WREG32(0x657C, 0xBFF880B0);
+       WREG32(0x6578, 0x100);
+       WREG32(0x657C, 0x83D88088);
+       WREG32(0x6578, 0x101);
+       WREG32(0x657C, 0x84608680);
+       WREG32(0x6578, 0x102);
+       WREG32(0x657C, 0xBFF080D0);
+       WREG32(0x6578, 0x200);
+       WREG32(0x657C, 0x83988068);
+       WREG32(0x6578, 0x201);
+       WREG32(0x657C, 0x84A08680);
+       WREG32(0x6578, 0x202);
+       WREG32(0x657C, 0xBFF080F8);
+       WREG32(0x6578, 0x300);
+       WREG32(0x657C, 0x83588058);
+       WREG32(0x6578, 0x301);
+       WREG32(0x657C, 0x84E08660);
+       WREG32(0x6578, 0x302);
+       WREG32(0x657C, 0xBFF88120);
+       WREG32(0x6578, 0x400);
+       WREG32(0x657C, 0x83188040);
+       WREG32(0x6578, 0x401);
+       WREG32(0x657C, 0x85008660);
+       WREG32(0x6578, 0x402);
+       WREG32(0x657C, 0xBFF88150);
+       WREG32(0x6578, 0x500);
+       WREG32(0x657C, 0x82D88030);
+       WREG32(0x6578, 0x501);
+       WREG32(0x657C, 0x85408640);
+       WREG32(0x6578, 0x502);
+       WREG32(0x657C, 0xBFF88180);
+       WREG32(0x6578, 0x600);
+       WREG32(0x657C, 0x82A08018);
+       WREG32(0x6578, 0x601);
+       WREG32(0x657C, 0x85808620);
+       WREG32(0x6578, 0x602);
+       WREG32(0x657C, 0xBFF081B8);
+       WREG32(0x6578, 0x700);
+       WREG32(0x657C, 0x82608010);
+       WREG32(0x6578, 0x701);
+       WREG32(0x657C, 0x85A08600);
+       WREG32(0x6578, 0x702);
+       WREG32(0x657C, 0x800081F0);
+       WREG32(0x6578, 0x800);
+       WREG32(0x657C, 0x8228BFF8);
+       WREG32(0x6578, 0x801);
+       WREG32(0x657C, 0x85E085E0);
+       WREG32(0x6578, 0x802);
+       WREG32(0x657C, 0xBFF88228);
+       WREG32(0x6578, 0x10000);
+       WREG32(0x657C, 0x82A8BF00);
+       WREG32(0x6578, 0x10001);
+       WREG32(0x657C, 0x82A08CC0);
+       WREG32(0x6578, 0x10002);
+       WREG32(0x657C, 0x8008BEF8);
+       WREG32(0x6578, 0x10100);
+       WREG32(0x657C, 0x81F0BF28);
+       WREG32(0x6578, 0x10101);
+       WREG32(0x657C, 0x83608CA0);
+       WREG32(0x6578, 0x10102);
+       WREG32(0x657C, 0x8018BED0);
+       WREG32(0x6578, 0x10200);
+       WREG32(0x657C, 0x8148BF38);
+       WREG32(0x6578, 0x10201);
+       WREG32(0x657C, 0x84408C80);
+       WREG32(0x6578, 0x10202);
+       WREG32(0x657C, 0x8008BEB8);
+       WREG32(0x6578, 0x10300);
+       WREG32(0x657C, 0x80B0BF78);
+       WREG32(0x6578, 0x10301);
+       WREG32(0x657C, 0x85008C20);
+       WREG32(0x6578, 0x10302);
+       WREG32(0x657C, 0x8020BEA0);
+       WREG32(0x6578, 0x10400);
+       WREG32(0x657C, 0x8028BF90);
+       WREG32(0x6578, 0x10401);
+       WREG32(0x657C, 0x85E08BC0);
+       WREG32(0x6578, 0x10402);
+       WREG32(0x657C, 0x8018BE90);
+       WREG32(0x6578, 0x10500);
+       WREG32(0x657C, 0xBFB8BFB0);
+       WREG32(0x6578, 0x10501);
+       WREG32(0x657C, 0x86C08B40);
+       WREG32(0x6578, 0x10502);
+       WREG32(0x657C, 0x8010BE90);
+       WREG32(0x6578, 0x10600);
+       WREG32(0x657C, 0xBF58BFC8);
+       WREG32(0x6578, 0x10601);
+       WREG32(0x657C, 0x87A08AA0);
+       WREG32(0x6578, 0x10602);
+       WREG32(0x657C, 0x8010BE98);
+       WREG32(0x6578, 0x10700);
+       WREG32(0x657C, 0xBF10BFF0);
+       WREG32(0x6578, 0x10701);
+       WREG32(0x657C, 0x886089E0);
+       WREG32(0x6578, 0x10702);
+       WREG32(0x657C, 0x8018BEB0);
+       WREG32(0x6578, 0x10800);
+       WREG32(0x657C, 0xBED8BFE8);
+       WREG32(0x6578, 0x10801);
+       WREG32(0x657C, 0x89408940);
+       WREG32(0x6578, 0x10802);
+       WREG32(0x657C, 0xBFE8BED8);
+       WREG32(0x6578, 0x20000);
+       WREG32(0x657C, 0x80008000);
+       WREG32(0x6578, 0x20001);
+       WREG32(0x657C, 0x90008000);
+       WREG32(0x6578, 0x20002);
+       WREG32(0x657C, 0x80008000);
+       WREG32(0x6578, 0x20003);
+       WREG32(0x657C, 0x80008000);
+       WREG32(0x6578, 0x20100);
+       WREG32(0x657C, 0x80108000);
+       WREG32(0x6578, 0x20101);
+       WREG32(0x657C, 0x8FE0BF70);
+       WREG32(0x6578, 0x20102);
+       WREG32(0x657C, 0xBFE880C0);
+       WREG32(0x6578, 0x20103);
+       WREG32(0x657C, 0x80008000);
+       WREG32(0x6578, 0x20200);
+       WREG32(0x657C, 0x8018BFF8);
+       WREG32(0x6578, 0x20201);
+       WREG32(0x657C, 0x8F80BF08);
+       WREG32(0x6578, 0x20202);
+       WREG32(0x657C, 0xBFD081A0);
+       WREG32(0x6578, 0x20203);
+       WREG32(0x657C, 0xBFF88000);
+       WREG32(0x6578, 0x20300);
+       WREG32(0x657C, 0x80188000);
+       WREG32(0x6578, 0x20301);
+       WREG32(0x657C, 0x8EE0BEC0);
+       WREG32(0x6578, 0x20302);
+       WREG32(0x657C, 0xBFB082A0);
+       WREG32(0x6578, 0x20303);
+       WREG32(0x657C, 0x80008000);
+       WREG32(0x6578, 0x20400);
+       WREG32(0x657C, 0x80188000);
+       WREG32(0x6578, 0x20401);
+       WREG32(0x657C, 0x8E00BEA0);
+       WREG32(0x6578, 0x20402);
+       WREG32(0x657C, 0xBF8883C0);
+       WREG32(0x6578, 0x20403);
+       WREG32(0x657C, 0x80008000);
+       WREG32(0x6578, 0x20500);
+       WREG32(0x657C, 0x80188000);
+       WREG32(0x6578, 0x20501);
+       WREG32(0x657C, 0x8D00BE90);
+       WREG32(0x6578, 0x20502);
+       WREG32(0x657C, 0xBF588500);
+       WREG32(0x6578, 0x20503);
+       WREG32(0x657C, 0x80008008);
+       WREG32(0x6578, 0x20600);
+       WREG32(0x657C, 0x80188000);
+       WREG32(0x6578, 0x20601);
+       WREG32(0x657C, 0x8BC0BE98);
+       WREG32(0x6578, 0x20602);
+       WREG32(0x657C, 0xBF308660);
+       WREG32(0x6578, 0x20603);
+       WREG32(0x657C, 0x80008008);
+       WREG32(0x6578, 0x20700);
+       WREG32(0x657C, 0x80108000);
+       WREG32(0x6578, 0x20701);
+       WREG32(0x657C, 0x8A80BEB0);
+       WREG32(0x6578, 0x20702);
+       WREG32(0x657C, 0xBF0087C0);
+       WREG32(0x6578, 0x20703);
+       WREG32(0x657C, 0x80008008);
+       WREG32(0x6578, 0x20800);
+       WREG32(0x657C, 0x80108000);
+       WREG32(0x6578, 0x20801);
+       WREG32(0x657C, 0x8920BED0);
+       WREG32(0x6578, 0x20802);
+       WREG32(0x657C, 0xBED08920);
+       WREG32(0x6578, 0x20803);
+       WREG32(0x657C, 0x80008010);
+       WREG32(0x6578, 0x30000);
+       WREG32(0x657C, 0x90008000);
+       WREG32(0x6578, 0x30001);
+       WREG32(0x657C, 0x80008000);
+       WREG32(0x6578, 0x30100);
+       WREG32(0x657C, 0x8FE0BF90);
+       WREG32(0x6578, 0x30101);
+       WREG32(0x657C, 0xBFF880A0);
+       WREG32(0x6578, 0x30200);
+       WREG32(0x657C, 0x8F60BF40);
+       WREG32(0x6578, 0x30201);
+       WREG32(0x657C, 0xBFE88180);
+       WREG32(0x6578, 0x30300);
+       WREG32(0x657C, 0x8EC0BF00);
+       WREG32(0x6578, 0x30301);
+       WREG32(0x657C, 0xBFC88280);
+       WREG32(0x6578, 0x30400);
+       WREG32(0x657C, 0x8DE0BEE0);
+       WREG32(0x6578, 0x30401);
+       WREG32(0x657C, 0xBFA083A0);
+       WREG32(0x6578, 0x30500);
+       WREG32(0x657C, 0x8CE0BED0);
+       WREG32(0x6578, 0x30501);
+       WREG32(0x657C, 0xBF7884E0);
+       WREG32(0x6578, 0x30600);
+       WREG32(0x657C, 0x8BA0BED8);
+       WREG32(0x6578, 0x30601);
+       WREG32(0x657C, 0xBF508640);
+       WREG32(0x6578, 0x30700);
+       WREG32(0x657C, 0x8A60BEE8);
+       WREG32(0x6578, 0x30701);
+       WREG32(0x657C, 0xBF2087A0);
+       WREG32(0x6578, 0x30800);
+       WREG32(0x657C, 0x8900BF00);
+       WREG32(0x6578, 0x30801);
+       WREG32(0x657C, 0xBF008900);
+}
+
+struct rv515_watermark {
+       u32        lb_request_fifo_depth;
+       fixed20_12 num_line_pair;
+       fixed20_12 estimated_width;
+       fixed20_12 worst_case_latency;
+       fixed20_12 consumption_rate;
+       fixed20_12 active_time;
+       fixed20_12 dbpp;
+       fixed20_12 priority_mark_max;
+       fixed20_12 priority_mark;
+       fixed20_12 sclk;
+};
+
+void rv515_crtc_bandwidth_compute(struct radeon_device *rdev,
+                                 struct radeon_crtc *crtc,
+                                 struct rv515_watermark *wm)
+{
+       struct drm_display_mode *mode = &crtc->base.mode;
+       fixed20_12 a, b, c;
+       fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;
+       fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;
+
+       if (!crtc->base.enabled) {
+               /* FIXME: wouldn't it better to set priority mark to maximum */
+               wm->lb_request_fifo_depth = 4;
+               return;
+       }
+
+       if (crtc->vsc.full > rfixed_const(2))
+               wm->num_line_pair.full = rfixed_const(2);
+       else
+               wm->num_line_pair.full = rfixed_const(1);
+
+       b.full = rfixed_const(mode->crtc_hdisplay);
+       c.full = rfixed_const(256);
+       a.full = rfixed_mul(wm->num_line_pair, b);
+       request_fifo_depth.full = rfixed_div(a, c);
+       if (a.full < rfixed_const(4)) {
+               wm->lb_request_fifo_depth = 4;
+       } else {
+               wm->lb_request_fifo_depth = rfixed_trunc(request_fifo_depth);
+       }
+
+       /* Determine consumption rate
+        *  pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000)
+        *  vtaps = number of vertical taps,
+        *  vsc = vertical scaling ratio, defined as source/destination
+        *  hsc = horizontal scaling ration, defined as source/destination
+        */
+       a.full = rfixed_const(mode->clock);
+       b.full = rfixed_const(1000);
+       a.full = rfixed_div(a, b);
+       pclk.full = rfixed_div(b, a);
+       if (crtc->rmx_type != RMX_OFF) {
+               b.full = rfixed_const(2);
+               if (crtc->vsc.full > b.full)
+                       b.full = crtc->vsc.full;
+               b.full = rfixed_mul(b, crtc->hsc);
+               c.full = rfixed_const(2);
+               b.full = rfixed_div(b, c);
+               consumption_time.full = rfixed_div(pclk, b);
+       } else {
+               consumption_time.full = pclk.full;
+       }
+       a.full = rfixed_const(1);
+       wm->consumption_rate.full = rfixed_div(a, consumption_time);
+
+
+       /* Determine line time
+        *  LineTime = total time for one line of displayhtotal
+        *  LineTime = total number of horizontal pixels
+        *  pclk = pixel clock period(ns)
+        */
+       a.full = rfixed_const(crtc->base.mode.crtc_htotal);
+       line_time.full = rfixed_mul(a, pclk);
+
+       /* Determine active time
+        *  ActiveTime = time of active region of display within one line,
+        *  hactive = total number of horizontal active pixels
+        *  htotal = total number of horizontal pixels
+        */
+       a.full = rfixed_const(crtc->base.mode.crtc_htotal);
+       b.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
+       wm->active_time.full = rfixed_mul(line_time, b);
+       wm->active_time.full = rfixed_div(wm->active_time, a);
+
+       /* Determine chunk time
+        * ChunkTime = the time it takes the DCP to send one chunk of data
+        * to the LB which consists of pipeline delay and inter chunk gap
+        * sclk = system clock(Mhz)
+        */
+       a.full = rfixed_const(600 * 1000);
+       chunk_time.full = rfixed_div(a, rdev->pm.sclk);
+       read_delay_latency.full = rfixed_const(1000);
+
+       /* Determine the worst case latency
+        * NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines)
+        * WorstCaseLatency = worst case time from urgent to when the MC starts
+        *                    to return data
+        * READ_DELAY_IDLE_MAX = constant of 1us
+        * ChunkTime = time it takes the DCP to send one chunk of data to the LB
+        *             which consists of pipeline delay and inter chunk gap
+        */
+       if (rfixed_trunc(wm->num_line_pair) > 1) {
+               a.full = rfixed_const(3);
+               wm->worst_case_latency.full = rfixed_mul(a, chunk_time);
+               wm->worst_case_latency.full += read_delay_latency.full;
+       } else {
+               wm->worst_case_latency.full = chunk_time.full + read_delay_latency.full;
+       }
+
+       /* Determine the tolerable latency
+        * TolerableLatency = Any given request has only 1 line time
+        *                    for the data to be returned
+        * LBRequestFifoDepth = Number of chunk requests the LB can
+        *                      put into the request FIFO for a display
+        *  LineTime = total time for one line of display
+        *  ChunkTime = the time it takes the DCP to send one chunk
+        *              of data to the LB which consists of
+        *  pipeline delay and inter chunk gap
+        */
+       if ((2+wm->lb_request_fifo_depth) >= rfixed_trunc(request_fifo_depth)) {
+               tolerable_latency.full = line_time.full;
+       } else {
+               tolerable_latency.full = rfixed_const(wm->lb_request_fifo_depth - 2);
+               tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full;
+               tolerable_latency.full = rfixed_mul(tolerable_latency, chunk_time);
+               tolerable_latency.full = line_time.full - tolerable_latency.full;
+       }
+       /* We assume worst case 32bits (4 bytes) */
+       wm->dbpp.full = rfixed_const(2 * 16);
+
+       /* Determine the maximum priority mark
+        *  width = viewport width in pixels
+        */
+       a.full = rfixed_const(16);
+       wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
+       wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a);
+
+       /* Determine estimated width */
+       estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full;
+       estimated_width.full = rfixed_div(estimated_width, consumption_time);
+       if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) {
+               wm->priority_mark.full = rfixed_const(10);
+       } else {
+               a.full = rfixed_const(16);
+               wm->priority_mark.full = rfixed_div(estimated_width, a);
+               wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full;
+       }
+}
+
+void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
+{
+       struct drm_display_mode *mode0 = NULL;
+       struct drm_display_mode *mode1 = NULL;
+       struct rv515_watermark wm0;
+       struct rv515_watermark wm1;
+       u32 tmp;
+       fixed20_12 priority_mark02, priority_mark12, fill_rate;
+       fixed20_12 a, b;
+
+       if (rdev->mode_info.crtcs[0]->base.enabled)
+               mode0 = &rdev->mode_info.crtcs[0]->base.mode;
+       if (rdev->mode_info.crtcs[1]->base.enabled)
+               mode1 = &rdev->mode_info.crtcs[1]->base.mode;
+       rs690_line_buffer_adjust(rdev, mode0, mode1);
+
+       rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0);
+       rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1);
+
+       tmp = wm0.lb_request_fifo_depth;
+       tmp |= wm1.lb_request_fifo_depth << 16;
+       WREG32(LB_MAX_REQ_OUTSTANDING, tmp);
+
+       if (mode0 && mode1) {
+               if (rfixed_trunc(wm0.dbpp) > 64)
+                       a.full = rfixed_div(wm0.dbpp, wm0.num_line_pair);
+               else
+                       a.full = wm0.num_line_pair.full;
+               if (rfixed_trunc(wm1.dbpp) > 64)
+                       b.full = rfixed_div(wm1.dbpp, wm1.num_line_pair);
+               else
+                       b.full = wm1.num_line_pair.full;
+               a.full += b.full;
+               fill_rate.full = rfixed_div(wm0.sclk, a);
+               if (wm0.consumption_rate.full > fill_rate.full) {
+                       b.full = wm0.consumption_rate.full - fill_rate.full;
+                       b.full = rfixed_mul(b, wm0.active_time);
+                       a.full = rfixed_const(16);
+                       b.full = rfixed_div(b, a);
+                       a.full = rfixed_mul(wm0.worst_case_latency,
+                                               wm0.consumption_rate);
+                       priority_mark02.full = a.full + b.full;
+               } else {
+                       a.full = rfixed_mul(wm0.worst_case_latency,
+                                               wm0.consumption_rate);
+                       b.full = rfixed_const(16 * 1000);
+                       priority_mark02.full = rfixed_div(a, b);
+               }
+               if (wm1.consumption_rate.full > fill_rate.full) {
+                       b.full = wm1.consumption_rate.full - fill_rate.full;
+                       b.full = rfixed_mul(b, wm1.active_time);
+                       a.full = rfixed_const(16);
+                       b.full = rfixed_div(b, a);
+                       a.full = rfixed_mul(wm1.worst_case_latency,
+                                               wm1.consumption_rate);
+                       priority_mark12.full = a.full + b.full;
+               } else {
+                       a.full = rfixed_mul(wm1.worst_case_latency,
+                                               wm1.consumption_rate);
+                       b.full = rfixed_const(16 * 1000);
+                       priority_mark12.full = rfixed_div(a, b);
+               }
+               if (wm0.priority_mark.full > priority_mark02.full)
+                       priority_mark02.full = wm0.priority_mark.full;
+               if (rfixed_trunc(priority_mark02) < 0)
+                       priority_mark02.full = 0;
+               if (wm0.priority_mark_max.full > priority_mark02.full)
+                       priority_mark02.full = wm0.priority_mark_max.full;
+               if (wm1.priority_mark.full > priority_mark12.full)
+                       priority_mark12.full = wm1.priority_mark.full;
+               if (rfixed_trunc(priority_mark12) < 0)
+                       priority_mark12.full = 0;
+               if (wm1.priority_mark_max.full > priority_mark12.full)
+                       priority_mark12.full = wm1.priority_mark_max.full;
+               WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
+               WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
+               WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
+               WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+       } else if (mode0) {
+               if (rfixed_trunc(wm0.dbpp) > 64)
+                       a.full = rfixed_div(wm0.dbpp, wm0.num_line_pair);
+               else
+                       a.full = wm0.num_line_pair.full;
+               fill_rate.full = rfixed_div(wm0.sclk, a);
+               if (wm0.consumption_rate.full > fill_rate.full) {
+                       b.full = wm0.consumption_rate.full - fill_rate.full;
+                       b.full = rfixed_mul(b, wm0.active_time);
+                       a.full = rfixed_const(16);
+                       b.full = rfixed_div(b, a);
+                       a.full = rfixed_mul(wm0.worst_case_latency,
+                                               wm0.consumption_rate);
+                       priority_mark02.full = a.full + b.full;
+               } else {
+                       a.full = rfixed_mul(wm0.worst_case_latency,
+                                               wm0.consumption_rate);
+                       b.full = rfixed_const(16);
+                       priority_mark02.full = rfixed_div(a, b);
+               }
+               if (wm0.priority_mark.full > priority_mark02.full)
+                       priority_mark02.full = wm0.priority_mark.full;
+               if (rfixed_trunc(priority_mark02) < 0)
+                       priority_mark02.full = 0;
+               if (wm0.priority_mark_max.full > priority_mark02.full)
+                       priority_mark02.full = wm0.priority_mark_max.full;
+               WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
+               WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
+               WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
+               WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
+       } else {
+               if (rfixed_trunc(wm1.dbpp) > 64)
+                       a.full = rfixed_div(wm1.dbpp, wm1.num_line_pair);
+               else
+                       a.full = wm1.num_line_pair.full;
+               fill_rate.full = rfixed_div(wm1.sclk, a);
+               if (wm1.consumption_rate.full > fill_rate.full) {
+                       b.full = wm1.consumption_rate.full - fill_rate.full;
+                       b.full = rfixed_mul(b, wm1.active_time);
+                       a.full = rfixed_const(16);
+                       b.full = rfixed_div(b, a);
+                       a.full = rfixed_mul(wm1.worst_case_latency,
+                                               wm1.consumption_rate);
+                       priority_mark12.full = a.full + b.full;
+               } else {
+                       a.full = rfixed_mul(wm1.worst_case_latency,
+                                               wm1.consumption_rate);
+                       b.full = rfixed_const(16 * 1000);
+                       priority_mark12.full = rfixed_div(a, b);
+               }
+               if (wm1.priority_mark.full > priority_mark12.full)
+                       priority_mark12.full = wm1.priority_mark.full;
+               if (rfixed_trunc(priority_mark12) < 0)
+                       priority_mark12.full = 0;
+               if (wm1.priority_mark_max.full > priority_mark12.full)
+                       priority_mark12.full = wm1.priority_mark_max.full;
+               WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
+               WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
+               WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
+               WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
+       }
+}
+
+void rv515_bandwidth_update(struct radeon_device *rdev)
+{
+       uint32_t tmp;
+       struct drm_display_mode *mode0 = NULL;
+       struct drm_display_mode *mode1 = NULL;
+
+       if (rdev->mode_info.crtcs[0]->base.enabled)
+               mode0 = &rdev->mode_info.crtcs[0]->base.mode;
+       if (rdev->mode_info.crtcs[1]->base.enabled)
+               mode1 = &rdev->mode_info.crtcs[1]->base.mode;
+       /*
+        * Set display0/1 priority up in the memory controller for
+        * modes if the user specifies HIGH for displaypriority
+        * option.
+        */
+       if (rdev->disp_priority == 2) {
+               tmp = RREG32_MC(MC_MISC_LAT_TIMER);
+               tmp &= ~MC_DISP1R_INIT_LAT_MASK;
+               tmp &= ~MC_DISP0R_INIT_LAT_MASK;
+               if (mode1)
+                       tmp |= (1 << MC_DISP1R_INIT_LAT_SHIFT);
+               if (mode0)
+                       tmp |= (1 << MC_DISP0R_INIT_LAT_SHIFT);
+               WREG32_MC(MC_MISC_LAT_TIMER, tmp);
+       }
+       rv515_bandwidth_avivo_update(rdev);
+}
diff --git a/drivers/gpu/drm/radeon/rv515r.h b/drivers/gpu/drm/radeon/rv515r.h
new file mode 100644 (file)
index 0000000..f3cf840
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2008 Advanced Micro Devices, Inc.
+ * Copyright 2008 Red Hat Inc.
+ * Copyright 2009 Jerome Glisse.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Dave Airlie
+ *          Alex Deucher
+ *          Jerome Glisse
+ */
+#ifndef RV515R_H
+#define RV515R_H
+
+/* RV515 registers */
+#define PCIE_INDEX                     0x0030
+#define PCIE_DATA                      0x0034
+#define        MC_IND_INDEX                    0x0070
+#define                MC_IND_WR_EN                            (1 << 24)
+#define        MC_IND_DATA                     0x0074
+#define        RBBM_SOFT_RESET                 0x00F0
+#define        CONFIG_MEMSIZE                  0x00F8
+#define HDP_FB_LOCATION                        0x0134
+#define        CP_CSQ_CNTL                     0x0740
+#define        CP_CSQ_MODE                     0x0744
+#define        CP_CSQ_ADDR                     0x07F0
+#define        CP_CSQ_DATA                     0x07F4
+#define        CP_CSQ_STAT                     0x07F8
+#define        CP_CSQ2_STAT                    0x07FC
+#define        RBBM_STATUS                     0x0E40
+#define        DST_PIPE_CONFIG                 0x170C
+#define        WAIT_UNTIL                      0x1720
+#define                WAIT_2D_IDLE                            (1 << 14)
+#define                WAIT_3D_IDLE                            (1 << 15)
+#define                WAIT_2D_IDLECLEAN                       (1 << 16)
+#define                WAIT_3D_IDLECLEAN                       (1 << 17)
+#define        ISYNC_CNTL                      0x1724
+#define                ISYNC_ANY2D_IDLE3D                      (1 << 0)
+#define                ISYNC_ANY3D_IDLE2D                      (1 << 1)
+#define                ISYNC_TRIG2D_IDLE3D                     (1 << 2)
+#define                ISYNC_TRIG3D_IDLE2D                     (1 << 3)
+#define                ISYNC_WAIT_IDLEGUI                      (1 << 4)
+#define                ISYNC_CPSCRATCH_IDLEGUI                 (1 << 5)
+#define        VAP_INDEX_OFFSET                0x208C
+#define        VAP_PVS_STATE_FLUSH_REG         0x2284
+#define        GB_ENABLE                       0x4008
+#define        GB_MSPOS0                       0x4010
+#define                MS_X0_SHIFT                             0
+#define                MS_Y0_SHIFT                             4
+#define                MS_X1_SHIFT                             8
+#define                MS_Y1_SHIFT                             12
+#define                MS_X2_SHIFT                             16
+#define                MS_Y2_SHIFT                             20
+#define                MSBD0_Y_SHIFT                           24
+#define                MSBD0_X_SHIFT                           28
+#define        GB_MSPOS1                       0x4014
+#define                MS_X3_SHIFT                             0
+#define                MS_Y3_SHIFT                             4
+#define                MS_X4_SHIFT                             8
+#define                MS_Y4_SHIFT                             12
+#define                MS_X5_SHIFT                             16
+#define                MS_Y5_SHIFT                             20
+#define                MSBD1_SHIFT                             24
+#define GB_TILE_CONFIG                 0x4018
+#define                ENABLE_TILING                           (1 << 0)
+#define                PIPE_COUNT_MASK                         0x0000000E
+#define                PIPE_COUNT_SHIFT                        1
+#define                TILE_SIZE_8                             (0 << 4)
+#define                TILE_SIZE_16                            (1 << 4)
+#define                TILE_SIZE_32                            (2 << 4)
+#define                SUBPIXEL_1_12                           (0 << 16)
+#define                SUBPIXEL_1_16                           (1 << 16)
+#define        GB_SELECT                       0x401C
+#define        GB_AA_CONFIG                    0x4020
+#define        GB_PIPE_SELECT                  0x402C
+#define        GA_ENHANCE                      0x4274
+#define                GA_DEADLOCK_CNTL                        (1 << 0)
+#define                GA_FASTSYNC_CNTL                        (1 << 1)
+#define        GA_POLY_MODE                    0x4288
+#define                FRONT_PTYPE_POINT                       (0 << 4)
+#define                FRONT_PTYPE_LINE                        (1 << 4)
+#define                FRONT_PTYPE_TRIANGE                     (2 << 4)
+#define                BACK_PTYPE_POINT                        (0 << 7)
+#define                BACK_PTYPE_LINE                         (1 << 7)
+#define                BACK_PTYPE_TRIANGE                      (2 << 7)
+#define        GA_ROUND_MODE                   0x428C
+#define                GEOMETRY_ROUND_TRUNC                    (0 << 0)
+#define                GEOMETRY_ROUND_NEAREST                  (1 << 0)
+#define                COLOR_ROUND_TRUNC                       (0 << 2)
+#define                COLOR_ROUND_NEAREST                     (1 << 2)
+#define        SU_REG_DEST                     0x42C8
+#define        RB3D_DSTCACHE_CTLSTAT           0x4E4C
+#define                RB3D_DC_FLUSH                           (2 << 0)
+#define                RB3D_DC_FREE                            (2 << 2)
+#define                RB3D_DC_FINISH                          (1 << 4)
+#define ZB_ZCACHE_CTLSTAT              0x4F18
+#define                ZC_FLUSH                                (1 << 0)
+#define                ZC_FREE                                 (1 << 1)
+#define DC_LB_MEMORY_SPLIT             0x6520
+#define                DC_LB_MEMORY_SPLIT_MASK                 0x00000003
+#define                DC_LB_MEMORY_SPLIT_SHIFT                0
+#define                DC_LB_MEMORY_SPLIT_D1HALF_D2HALF        0
+#define                DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q          1
+#define                DC_LB_MEMORY_SPLIT_D1_ONLY              2
+#define                DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q          3
+#define                DC_LB_MEMORY_SPLIT_SHIFT_MODE           (1 << 2)
+#define                DC_LB_DISP1_END_ADR_SHIFT               4
+#define                DC_LB_DISP1_END_ADR_MASK                0x00007FF0
+#define D1MODE_PRIORITY_A_CNT          0x6548
+#define                MODE_PRIORITY_MARK_MASK                 0x00007FFF
+#define                MODE_PRIORITY_OFF                       (1 << 16)
+#define                MODE_PRIORITY_ALWAYS_ON                 (1 << 20)
+#define                MODE_PRIORITY_FORCE_MASK                (1 << 24)
+#define D1MODE_PRIORITY_B_CNT          0x654C
+#define LB_MAX_REQ_OUTSTANDING         0x6D58
+#define                LB_D1_MAX_REQ_OUTSTANDING_MASK          0x0000000F
+#define                LB_D1_MAX_REQ_OUTSTANDING_SHIFT         0
+#define                LB_D2_MAX_REQ_OUTSTANDING_MASK          0x000F0000
+#define                LB_D2_MAX_REQ_OUTSTANDING_SHIFT         16
+#define D2MODE_PRIORITY_A_CNT          0x6D48
+#define D2MODE_PRIORITY_B_CNT          0x6D4C
+
+/* ix[MC] registers */
+#define MC_FB_LOCATION                 0x01
+#define                MC_FB_START_MASK                        0x0000FFFF
+#define                MC_FB_START_SHIFT                       0
+#define                MC_FB_TOP_MASK                          0xFFFF0000
+#define                MC_FB_TOP_SHIFT                         16
+#define MC_AGP_LOCATION                        0x02
+#define                MC_AGP_START_MASK                       0x0000FFFF
+#define                MC_AGP_START_SHIFT                      0
+#define                MC_AGP_TOP_MASK                         0xFFFF0000
+#define                MC_AGP_TOP_SHIFT                        16
+#define MC_AGP_BASE                    0x03
+#define MC_AGP_BASE_2                  0x04
+#define        MC_CNTL                         0x5
+#define                MEM_NUM_CHANNELS_MASK                   0x00000003
+#define        MC_STATUS                       0x08
+#define                MC_STATUS_IDLE                          (1 << 4)
+#define        MC_MISC_LAT_TIMER               0x09
+#define                MC_CPR_INIT_LAT_MASK                    0x0000000F
+#define                MC_VF_INIT_LAT_MASK                     0x000000F0
+#define                MC_DISP0R_INIT_LAT_MASK                 0x00000F00
+#define                MC_DISP0R_INIT_LAT_SHIFT                8
+#define                MC_DISP1R_INIT_LAT_MASK                 0x0000F000
+#define                MC_DISP1R_INIT_LAT_SHIFT                12
+#define                MC_FIXED_INIT_LAT_MASK                  0x000F0000
+#define                MC_E2R_INIT_LAT_MASK                    0x00F00000
+#define                SAME_PAGE_PRIO_MASK                     0x0F000000
+#define                MC_GLOBW_INIT_LAT_MASK                  0xF0000000
+
+
+#endif
+
index da50cc51ede3a5f2fdc5083398e2450e85c9a9b0..21d8ffd57308d1a4f994104f74f795e0a6ff1632 100644 (file)
@@ -67,7 +67,7 @@ int rv770_mc_init(struct radeon_device *rdev)
                       "programming pipes. Bad things might happen.\n");
        }
 
-       tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
+       tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
        tmp = REG_SET(R700_MC_FB_TOP, tmp >> 24);
        tmp |= REG_SET(R700_MC_FB_BASE, rdev->mc.vram_location >> 24);
        WREG32(R700_MC_VM_FB_LOCATION, tmp);
index c1c407f7cca3e982bfd51630c2a0e368869bc201..c2b0d710d10f79e06fd21d19c1a061e615eff3ac 100644 (file)
@@ -43,7 +43,6 @@
 #define TTM_BO_HASH_ORDER 13
 
 static int ttm_bo_setup_vm(struct ttm_buffer_object *bo);
-static void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo);
 static int ttm_bo_swapout(struct ttm_mem_shrink *shrink);
 
 static inline uint32_t ttm_bo_type_flags(unsigned type)
@@ -224,6 +223,9 @@ static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc)
        TTM_ASSERT_LOCKED(&bo->mutex);
        bo->ttm = NULL;
 
+       if (bdev->need_dma32)
+               page_flags |= TTM_PAGE_FLAG_DMA32;
+
        switch (bo->type) {
        case ttm_bo_type_device:
                if (zero_alloc)
@@ -304,6 +306,9 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
 
        }
 
+       if (bdev->driver->move_notify)
+               bdev->driver->move_notify(bo, mem);
+
        if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
            !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED))
                ret = ttm_bo_move_ttm(bo, evict, no_wait, mem);
@@ -655,31 +660,52 @@ retry_pre_get:
        return 0;
 }
 
+static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man,
+                                     uint32_t cur_placement,
+                                     uint32_t proposed_placement)
+{
+       uint32_t caching = proposed_placement & TTM_PL_MASK_CACHING;
+       uint32_t result = proposed_placement & ~TTM_PL_MASK_CACHING;
+
+       /**
+        * Keep current caching if possible.
+        */
+
+       if ((cur_placement & caching) != 0)
+               result |= (cur_placement & caching);
+       else if ((man->default_caching & caching) != 0)
+               result |= man->default_caching;
+       else if ((TTM_PL_FLAG_CACHED & caching) != 0)
+               result |= TTM_PL_FLAG_CACHED;
+       else if ((TTM_PL_FLAG_WC & caching) != 0)
+               result |= TTM_PL_FLAG_WC;
+       else if ((TTM_PL_FLAG_UNCACHED & caching) != 0)
+               result |= TTM_PL_FLAG_UNCACHED;
+
+       return result;
+}
+
+
 static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man,
                                 bool disallow_fixed,
                                 uint32_t mem_type,
-                                uint32_t mask, uint32_t *res_mask)
+                                uint32_t proposed_placement,
+                                uint32_t *masked_placement)
 {
        uint32_t cur_flags = ttm_bo_type_flags(mem_type);
 
        if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && disallow_fixed)
                return false;
 
-       if ((cur_flags & mask & TTM_PL_MASK_MEM) == 0)
+       if ((cur_flags & proposed_placement & TTM_PL_MASK_MEM) == 0)
                return false;
 
-       if ((mask & man->available_caching) == 0)
+       if ((proposed_placement & man->available_caching) == 0)
                return false;
-       if (mask & man->default_caching)
-               cur_flags |= man->default_caching;
-       else if (mask & TTM_PL_FLAG_CACHED)
-               cur_flags |= TTM_PL_FLAG_CACHED;
-       else if (mask & TTM_PL_FLAG_WC)
-               cur_flags |= TTM_PL_FLAG_WC;
-       else
-               cur_flags |= TTM_PL_FLAG_UNCACHED;
 
-       *res_mask = cur_flags;
+       cur_flags |= (proposed_placement & man->available_caching);
+
+       *masked_placement = cur_flags;
        return true;
 }
 
@@ -723,6 +749,9 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                if (!type_ok)
                        continue;
 
+               cur_flags = ttm_bo_select_caching(man, bo->mem.placement,
+                                                 cur_flags);
+
                if (mem_type == TTM_PL_SYSTEM)
                        break;
 
@@ -779,6 +808,9 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
                                          proposed_placement, &cur_flags))
                        continue;
 
+               cur_flags = ttm_bo_select_caching(man, bo->mem.placement,
+                                                 cur_flags);
+
                ret = ttm_bo_mem_force_space(bdev, mem, mem_type,
                                             interruptible, no_wait);
 
@@ -1150,13 +1182,14 @@ static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,
 
 int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type)
 {
-       struct ttm_mem_type_manager *man = &bdev->man[mem_type];
+       struct ttm_mem_type_manager *man;
        int ret = -EINVAL;
 
        if (mem_type >= TTM_NUM_MEM_TYPES) {
                printk(KERN_ERR TTM_PFX "Illegal memory type %d\n", mem_type);
                return ret;
        }
+       man = &bdev->man[mem_type];
 
        if (!man->has_type) {
                printk(KERN_ERR TTM_PFX "Trying to take down uninitialized "
@@ -1305,7 +1338,8 @@ EXPORT_SYMBOL(ttm_bo_device_release);
 
 int ttm_bo_device_init(struct ttm_bo_device *bdev,
                       struct ttm_mem_global *mem_glob,
-                      struct ttm_bo_driver *driver, uint64_t file_page_offset)
+                      struct ttm_bo_driver *driver, uint64_t file_page_offset,
+                      bool need_dma32)
 {
        int ret = -EINVAL;
 
@@ -1342,6 +1376,7 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev,
        INIT_LIST_HEAD(&bdev->ddestroy);
        INIT_LIST_HEAD(&bdev->swap_lru);
        bdev->dev_mapping = NULL;
+       bdev->need_dma32 = need_dma32;
        ttm_mem_init_shrink(&bdev->shrink, ttm_bo_swapout);
        ret = ttm_mem_register_shrink(mem_glob, &bdev->shrink);
        if (unlikely(ret != 0)) {
@@ -1419,6 +1454,7 @@ void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo)
 
        unmap_mapping_range(bdev->dev_mapping, offset, holelen, 1);
 }
+EXPORT_SYMBOL(ttm_bo_unmap_virtual);
 
 static void ttm_bo_vm_insert_rb(struct ttm_buffer_object *bo)
 {
@@ -1540,6 +1576,10 @@ int ttm_bo_wait(struct ttm_buffer_object *bo,
                        driver->sync_obj_unref(&sync_obj);
                        driver->sync_obj_unref(&tmp_obj);
                        spin_lock(&bo->lock);
+               } else {
+                       spin_unlock(&bo->lock);
+                       driver->sync_obj_unref(&sync_obj);
+                       spin_lock(&bo->lock);
                }
        }
        return 0;
index 517c8455963312e16c6a515dfc8fed21de16fec3..ad4ada07c6cfbdd1ba2c7775f120b4431293920e 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/highmem.h>
 #include <linux/wait.h>
 #include <linux/vmalloc.h>
-#include <linux/version.h>
 #include <linux/module.h>
 
 void ttm_bo_free_old_node(struct ttm_buffer_object *bo)
@@ -137,7 +136,8 @@ static int ttm_copy_io_page(void *dst, void *src, unsigned long page)
 }
 
 static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src,
-                               unsigned long page)
+                               unsigned long page,
+                               pgprot_t prot)
 {
        struct page *d = ttm_tt_get_page(ttm, page);
        void *dst;
@@ -146,17 +146,35 @@ static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src,
                return -ENOMEM;
 
        src = (void *)((unsigned long)src + (page << PAGE_SHIFT));
-       dst = kmap(d);
+
+#ifdef CONFIG_X86
+       dst = kmap_atomic_prot(d, KM_USER0, prot);
+#else
+       if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
+               dst = vmap(&d, 1, 0, prot);
+       else
+               dst = kmap(d);
+#endif
        if (!dst)
                return -ENOMEM;
 
        memcpy_fromio(dst, src, PAGE_SIZE);
-       kunmap(d);
+
+#ifdef CONFIG_X86
+       kunmap_atomic(dst, KM_USER0);
+#else
+       if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
+               vunmap(dst);
+       else
+               kunmap(d);
+#endif
+
        return 0;
 }
 
 static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst,
-                               unsigned long page)
+                               unsigned long page,
+                               pgprot_t prot)
 {
        struct page *s = ttm_tt_get_page(ttm, page);
        void *src;
@@ -165,12 +183,28 @@ static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst,
                return -ENOMEM;
 
        dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT));
-       src = kmap(s);
+#ifdef CONFIG_X86
+       src = kmap_atomic_prot(s, KM_USER0, prot);
+#else
+       if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
+               src = vmap(&s, 1, 0, prot);
+       else
+               src = kmap(s);
+#endif
        if (!src)
                return -ENOMEM;
 
        memcpy_toio(dst, src, PAGE_SIZE);
-       kunmap(s);
+
+#ifdef CONFIG_X86
+       kunmap_atomic(src, KM_USER0);
+#else
+       if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
+               vunmap(src);
+       else
+               kunmap(s);
+#endif
+
        return 0;
 }
 
@@ -215,11 +249,17 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
 
        for (i = 0; i < new_mem->num_pages; ++i) {
                page = i * dir + add;
-               if (old_iomap == NULL)
-                       ret = ttm_copy_ttm_io_page(ttm, new_iomap, page);
-               else if (new_iomap == NULL)
-                       ret = ttm_copy_io_ttm_page(ttm, old_iomap, page);
-               else
+               if (old_iomap == NULL) {
+                       pgprot_t prot = ttm_io_prot(old_mem->placement,
+                                                   PAGE_KERNEL);
+                       ret = ttm_copy_ttm_io_page(ttm, new_iomap, page,
+                                                  prot);
+               } else if (new_iomap == NULL) {
+                       pgprot_t prot = ttm_io_prot(new_mem->placement,
+                                                   PAGE_KERNEL);
+                       ret = ttm_copy_io_ttm_page(ttm, old_iomap, page,
+                                                  prot);
+               } else
                        ret = ttm_copy_io_page(new_iomap, old_iomap, page);
                if (ret)
                        goto out1;
@@ -510,8 +550,8 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
        if (evict) {
                ret = ttm_bo_wait(bo, false, false, false);
                spin_unlock(&bo->lock);
-               driver->sync_obj_unref(&bo->sync_obj);
-
+               if (tmp_obj)
+                       driver->sync_obj_unref(&tmp_obj);
                if (ret)
                        return ret;
 
@@ -533,6 +573,8 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
 
                set_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags);
                spin_unlock(&bo->lock);
+               if (tmp_obj)
+                       driver->sync_obj_unref(&tmp_obj);
 
                ret = ttm_buffer_object_transfer(bo, &ghost_obj);
                if (ret)
index 27b146c54fbcb4d41c137ea9fb15a4a873ee068f..33de7637c0c63766e4ac933ce5aada21b408a641 100644 (file)
@@ -32,7 +32,6 @@
 #include <ttm/ttm_bo_driver.h>
 #include <ttm/ttm_placement.h>
 #include <linux/mm.h>
-#include <linux/version.h>
 #include <linux/rbtree.h>
 #include <linux/module.h>
 #include <linux/uaccess.h>
@@ -102,6 +101,9 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                return VM_FAULT_NOPAGE;
        }
 
+       if (bdev->driver->fault_reserve_notify)
+               bdev->driver->fault_reserve_notify(bo);
+
        /*
         * Wait for buffer data in transit, due to a pipelined
         * move.
@@ -328,7 +330,7 @@ ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp,
                goto out_unref;
 
        kmap_offset = dev_offset - bo->vm_node->start;
-       if (unlikely(kmap_offset) >= bo->num_pages) {
+       if (unlikely(kmap_offset >= bo->num_pages)) {
                ret = -EFBIG;
                goto out_unref;
        }
@@ -402,7 +404,7 @@ ssize_t ttm_bo_fbdev_io(struct ttm_buffer_object *bo, const char __user *wbuf,
        bool dummy;
 
        kmap_offset = (*f_pos >> PAGE_SHIFT);
-       if (unlikely(kmap_offset) >= bo->num_pages)
+       if (unlikely(kmap_offset >= bo->num_pages))
                return -EFBIG;
 
        page_offset = *f_pos & ~PAGE_MASK;
index 0331fa74cd3f137396bfa79f9683a709e3ddad45..b8b6c4a5f9834a206850b7ce24d678ac861a2d7d 100644 (file)
@@ -28,7 +28,6 @@
  * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
  */
 
-#include <linux/version.h>
 #include <linux/vmalloc.h>
 #include <linux/sched.h>
 #include <linux/highmem.h>
@@ -87,10 +86,16 @@ void ttm_tt_cache_flush(struct page *pages[], unsigned long num_pages)
        unsigned long i;
 
        for (i = 0; i < num_pages; ++i) {
-               if (pages[i]) {
-                       unsigned long start = (unsigned long)page_address(pages[i]);
-                       flush_dcache_range(start, start + PAGE_SIZE);
-               }
+               struct page *page = pages[i];
+               void *page_virtual;
+
+               if (unlikely(page == NULL))
+                       continue;
+
+               page_virtual = kmap_atomic(page, KM_USER0);
+               flush_dcache_range((unsigned long) page_virtual,
+                                  (unsigned long) page_virtual + PAGE_SIZE);
+               kunmap_atomic(page_virtual, KM_USER0);
        }
 #else
        if (on_each_cpu(ttm_tt_ipi_handler, NULL, 1) != 0)
@@ -132,10 +137,17 @@ static void ttm_tt_free_page_directory(struct ttm_tt *ttm)
 
 static struct page *ttm_tt_alloc_page(unsigned page_flags)
 {
+       gfp_t gfp_flags = GFP_USER;
+
        if (page_flags & TTM_PAGE_FLAG_ZERO_ALLOC)
-               return alloc_page(GFP_HIGHUSER | __GFP_ZERO);
+               gfp_flags |= __GFP_ZERO;
+
+       if (page_flags & TTM_PAGE_FLAG_DMA32)
+               gfp_flags |= __GFP_DMA32;
+       else
+               gfp_flags |= __GFP_HIGHMEM;
 
-       return alloc_page(GFP_HIGHUSER);
+       return alloc_page(gfp_flags);
 }
 
 static void ttm_tt_free_user_pages(struct ttm_tt *ttm)
index c248c1d37268ac64cfed64e8b6bfba43b3d80332..5935b8842e8687c144ec6503b85ae7e9bee81b68 100644 (file)
@@ -183,7 +183,7 @@ int via_enable_vblank(struct drm_device *dev, int crtc)
        }
 
        status = VIA_READ(VIA_REG_INTERRUPT);
-       VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE);
+       VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE);
 
        VIA_WRITE8(0x83d4, 0x11);
        VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
@@ -194,6 +194,10 @@ int via_enable_vblank(struct drm_device *dev, int crtc)
 void via_disable_vblank(struct drm_device *dev, int crtc)
 {
        drm_via_private_t *dev_priv = dev->dev_private;
+       u32 status;
+
+       status = VIA_READ(VIA_REG_INTERRUPT);
+       VIA_WRITE(VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE);
 
        VIA_WRITE8(0x83d4, 0x11);
        VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
index f2c21d5d24e80e43bc3e482218fd20873f106c07..5eb10c2ce6654b6794041cfd813c95dc01261835 100644 (file)
@@ -1075,14 +1075,16 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event);
  */
 int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt)
 {
-       struct hid_report_enum *report_enum = hid->report_enum + type;
-       struct hid_driver *hdrv = hid->driver;
+       struct hid_report_enum *report_enum;
+       struct hid_driver *hdrv;
        struct hid_report *report;
        unsigned int i;
        int ret;
 
        if (!hid || !hid->driver)
                return -ENODEV;
+       report_enum = hid->report_enum + type;
+       hdrv = hid->driver;
 
        if (!size) {
                dbg_hid("empty report\n");
index 76c4bbe9dccb334ef64359f701321f8fc13df5b3..3c1fcb7640abe1458d52146f8456c16295ec531f 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/list.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
index 9e9421525fb9125fa962c2266550f67545855b39..215b2addddbb7c5be5e765dcbe0fd771146129db 100644 (file)
@@ -527,8 +527,10 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
                        goto goodreturn;
 
                case HIDIOCGCOLLECTIONINDEX:
+                       i = field->usage[uref->usage_index].collection_index;
+                       unlock_kernel();
                        kfree(uref_multi);
-                       return field->usage[uref->usage_index].collection_index;
+                       return i;
                case HIDIOCGUSAGES:
                        for (i = 0; i < uref_multi->num_values; i++)
                                uref_multi->values[i] =
index ad2b3431b7253091505e726a72d4857b6f708dde..7d3f15d32fdfee8c1829d0f985cbb46331e7fbfa 100644 (file)
@@ -357,7 +357,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
                { "AUX5 Fan",           39, 2, 60, 1, 0 },
                { NULL, 0, 0, 0, 0, 0 } }
        },
-       { 0x0014, NULL /* Abit AB9 Pro, need DMI string */, {
+       { 0x0014, "AB9", /* + AB9 Pro */ {
                { "CPU Core",            0, 0, 10, 1, 0 },
                { "DDR",                 1, 0, 10, 1, 0 },
                { "DDR VTT",             2, 0, 10, 1, 0 },
@@ -455,7 +455,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
                { "AUX3 FAN",           37, 2, 60, 1, 0 },
                { NULL, 0, 0, 0, 0, 0 } }
        },
-       { 0x0018, NULL /* Unknown, need DMI string */, {
+       { 0x0018, "AB9 QuadGT", {
                { "CPU Core",            0, 0, 10, 1, 0 },
                { "DDR2",                1, 0, 20, 1, 0 },
                { "DDR2 VTT",            2, 0, 10, 1, 0 },
@@ -564,7 +564,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
                { "AUX3 Fan",           36, 2, 60, 1, 0 },
                { NULL, 0, 0, 0, 0, 0 } }
        },
-       { 0x001C, NULL /* Unknown, need DMI string */, {
+       { 0x001C, "IX38 QuadGT", {
                { "CPU Core",            0, 0, 10, 1, 0 },
                { "DDR2",                1, 0, 20, 1, 0 },
                { "DDR2 VTT",            2, 0, 10, 1, 0 },
index bff0103610c17ada5bf070cb49a5f95871967678..fe4fa29c9219b9884e2e55065728920240a55e14 100644 (file)
@@ -593,7 +593,11 @@ static int atk_add_sensor(struct atk_data *data, union acpi_object *obj)
        sensor->data = data;
        sensor->id = flags->integer.value;
        sensor->limit1 = limit1->integer.value;
-       sensor->limit2 = limit2->integer.value;
+       if (data->old_interface)
+               sensor->limit2 = limit2->integer.value;
+       else
+               /* The upper limit is expressed as delta from lower limit */
+               sensor->limit2 = sensor->limit1 + limit2->integer.value;
 
        snprintf(sensor->input_attr_name, ATTR_NAME_SIZE,
                        "%s%d_input", base_name, start + *num);
index 86142a858238b8ddc0ccf65282ef56e34bd0b8ff..58f66be61b1fbb5e91498c87829b8c912cedc5bc 100644 (file)
@@ -418,6 +418,7 @@ static ssize_t set_div(struct device *dev, struct device_attribute *devattr,
                data->count = 3;
                break;
        default:
+               mutex_unlock(&data->update_lock);
                dev_err(&client->dev,
                        "illegal value for fan divider (%d)\n", div);
                return -EINVAL;
index 56cd6004da36e1ec08f94e05b890f61239323c08..6290a259456e8fbae6d5df180cd9825033b46217 100644 (file)
@@ -257,7 +257,7 @@ static inline int sht15_update_single_val(struct sht15_data *data,
                                 (data->flag == SHT15_READING_NOTHING),
                                 msecs_to_jiffies(timeout_msecs));
        if (ret == 0) {/* timeout occurred */
-               disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data));;
+               disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data));
                sht15_connection_reset(data);
                return -ETIME;
        }
index a92dbb97ee999255e1ad3d79da106894e83282ef..ba75bfcf14ceb9a0f4d550091d6804e6bf2da081 100644 (file)
@@ -86,6 +86,7 @@ superio_exit(void)
 #define SUPERIO_REG_ACT                0x30
 #define SUPERIO_REG_BASE       0x60
 #define SUPERIO_REG_DEVID      0x20
+#define SUPERIO_REG_DEVREV     0x21
 
 /* Logical device registers */
 
@@ -429,6 +430,9 @@ static int __init smsc47m1_find(unsigned short *addr,
         * The LPC47M292 (device id 0x6B) is somewhat compatible, but it
         * supports a 3rd fan, and the pin configuration registers are
         * unfortunately different.
+        * The LPC47M233 has the same device id (0x6B) but is not compatible.
+        * We check the high bit of the device revision register to
+        * differentiate them.
         */
        switch (val) {
        case 0x51:
@@ -448,6 +452,13 @@ static int __init smsc47m1_find(unsigned short *addr,
                sio_data->type = smsc47m1;
                break;
        case 0x6B:
+               if (superio_inb(SUPERIO_REG_DEVREV) & 0x80) {
+                       pr_debug(DRVNAME ": "
+                                "Found SMSC LPC47M233, unsupported\n");
+                       superio_exit();
+                       return -ENODEV;
+               }
+
                pr_info(DRVNAME ": Found SMSC LPC47M292\n");
                sio_data->type = smsc47m2;
                break;
index aa87b6a3bbef0b1f4b7e086ebc55b3fd638ef885..8206442fbabd80eab83424a5997d4c3eeddd2f35 100644 (file)
@@ -328,6 +328,7 @@ config I2C_DAVINCI
 
 config I2C_DESIGNWARE
        tristate "Synopsys DesignWare"
+       depends on HAVE_CLK
        help
          If you say yes to this option, support will be included for the
          Synopsys DesignWare I2C adapter. Only master mode is supported.
index 3fae3a91ce5b4acb1d6284a838a348229e2d682b..c89687a10835538307212949317042f40042129c 100644 (file)
@@ -187,6 +187,11 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
        davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh);
        davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl);
 
+       /* Respond at reserved "SMBus Host" slave address" (and zero);
+        * we seem to have no option to not respond...
+        */
+       davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08);
+
        dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk);
        dev_dbg(dev->dev, "PSC  = %d\n",
                davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG));
@@ -387,7 +392,7 @@ static void terminate_write(struct davinci_i2c_dev *dev)
        davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
 
        if (!dev->terminate)
-               dev_err(dev->dev, "TDR IRQ while no data to send\n");
+               dev_dbg(dev->dev, "TDR IRQ while no data to send\n");
 }
 
 /*
@@ -473,9 +478,14 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
                        break;
 
                case DAVINCI_I2C_IVR_AAS:
-                       dev_warn(dev->dev, "Address as slave interrupt\n");
-               }/* switch */
-       }/* while */
+                       dev_dbg(dev->dev, "Address as slave interrupt\n");
+                       break;
+
+               default:
+                       dev_warn(dev->dev, "Unrecognized irq stat %d\n", stat);
+                       break;
+               }
+       }
 
        return count ? IRQ_HANDLED : IRQ_NONE;
 }
@@ -505,7 +515,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
+       ioarea = request_mem_region(mem->start, resource_size(mem),
                                    pdev->name);
        if (!ioarea) {
                dev_err(&pdev->dev, "I2C region already claimed\n");
@@ -523,7 +533,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
        dev->irq = irq->start;
        platform_set_drvdata(pdev, dev);
 
-       dev->clk = clk_get(&pdev->dev, "I2CCLK");
+       dev->clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(dev->clk)) {
                r = -ENODEV;
                goto err_free_mem;
@@ -568,7 +578,7 @@ err_free_mem:
        put_device(&pdev->dev);
        kfree(dev);
 err_release_region:
-       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+       release_mem_region(mem->start, resource_size(mem));
 
        return r;
 }
@@ -591,7 +601,7 @@ static int davinci_i2c_remove(struct platform_device *pdev)
        kfree(dev);
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+       release_mem_region(mem->start, resource_size(mem));
        return 0;
 }
 
index e4476743f20330e4653e856ff42cee68b8952469..b1bc6e277d2a1eff1db0876b2e464dd12fba8094 100644 (file)
@@ -85,10 +85,11 @@ static void dump_iic_regs(const char* header, struct ibm_iic_private* dev)
 {
        volatile struct iic_regs __iomem *iic = dev->vaddr;
        printk(KERN_DEBUG "ibm-iic%d: %s\n", dev->idx, header);
-       printk(KERN_DEBUG "  cntl     = 0x%02x, mdcntl = 0x%02x\n"
-              KERN_DEBUG "  sts      = 0x%02x, extsts = 0x%02x\n"
-              KERN_DEBUG "  clkdiv   = 0x%02x, xfrcnt = 0x%02x\n"
-              KERN_DEBUG "  xtcntlss = 0x%02x, directcntl = 0x%02x\n",
+       printk(KERN_DEBUG
+              "  cntl     = 0x%02x, mdcntl = 0x%02x\n"
+              "  sts      = 0x%02x, extsts = 0x%02x\n"
+              "  clkdiv   = 0x%02x, xfrcnt = 0x%02x\n"
+              "  xtcntlss = 0x%02x, directcntl = 0x%02x\n",
                in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts),
                in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt),
                in_8(&iic->xtcntlss), in_8(&iic->directcntl));
index ad8d2010c9211cf0f28f9201aa7346662357626b..827da085813649b9348215fc77f0e8a5021fca0b 100644 (file)
@@ -672,9 +672,17 @@ omap_i2c_isr(int this_irq, void *dev_id)
                        break;
                }
 
-               omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
-
                err = 0;
+complete:
+               /*
+                * Ack the stat in one go, but [R/X]DR and [R/X]RDY should be
+                * acked after the data operation is complete.
+                * Ref: TRM SWPU114Q Figure 18-31
+                */
+               omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat &
+                               ~(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
+                               OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
+
                if (stat & OMAP_I2C_STAT_NACK) {
                        err |= OMAP_I2C_STAT_NACK;
                        omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
@@ -685,16 +693,22 @@ omap_i2c_isr(int this_irq, void *dev_id)
                        err |= OMAP_I2C_STAT_AL;
                }
                if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
-                                       OMAP_I2C_STAT_AL))
+                                       OMAP_I2C_STAT_AL)) {
+                       omap_i2c_ack_stat(dev, stat &
+                               (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
+                               OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
                        omap_i2c_complete_cmd(dev, err);
+                       return IRQ_HANDLED;
+               }
                if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
                        u8 num_bytes = 1;
                        if (dev->fifo_size) {
                                if (stat & OMAP_I2C_STAT_RRDY)
                                        num_bytes = dev->fifo_size;
-                               else
-                                       num_bytes = omap_i2c_read_reg(dev,
-                                                       OMAP_I2C_BUFSTAT_REG);
+                               else    /* read RXSTAT on RDR interrupt */
+                                       num_bytes = (omap_i2c_read_reg(dev,
+                                                       OMAP_I2C_BUFSTAT_REG)
+                                                       >> 8) & 0x3F;
                        }
                        while (num_bytes) {
                                num_bytes--;
@@ -731,9 +745,10 @@ omap_i2c_isr(int this_irq, void *dev_id)
                        if (dev->fifo_size) {
                                if (stat & OMAP_I2C_STAT_XRDY)
                                        num_bytes = dev->fifo_size;
-                               else
+                               else    /* read TXSTAT on XDR interrupt */
                                        num_bytes = omap_i2c_read_reg(dev,
-                                                       OMAP_I2C_BUFSTAT_REG);
+                                                       OMAP_I2C_BUFSTAT_REG)
+                                                       & 0x3F;
                        }
                        while (num_bytes) {
                                num_bytes--;
@@ -760,6 +775,27 @@ omap_i2c_isr(int this_irq, void *dev_id)
                                                        "data to send\n");
                                        break;
                                }
+
+                               /*
+                                * OMAP3430 Errata 1.153: When an XRDY/XDR
+                                * is hit, wait for XUDF before writing data
+                                * to DATA_REG. Otherwise some data bytes can
+                                * be lost while transferring them from the
+                                * memory to the I2C interface.
+                                */
+
+                               if (dev->rev <= OMAP_I2C_REV_ON_3430) {
+                                               while (!(stat & OMAP_I2C_STAT_XUDF)) {
+                                                       if (stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
+                                                               omap_i2c_ack_stat(dev, stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
+                                                               err |= OMAP_I2C_STAT_XUDF;
+                                                               goto complete;
+                                                       }
+                                                       cpu_relax();
+                                                       stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+                                               }
+                               }
+
                                omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
                        }
                        omap_i2c_ack_stat(dev,
@@ -806,7 +842,7 @@ omap_i2c_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
+       ioarea = request_mem_region(mem->start, resource_size(mem),
                        pdev->name);
        if (!ioarea) {
                dev_err(&pdev->dev, "I2C region already claimed\n");
@@ -879,7 +915,7 @@ omap_i2c_probe(struct platform_device *pdev)
        i2c_set_adapdata(adap, dev);
        adap->owner = THIS_MODULE;
        adap->class = I2C_CLASS_HWMON;
-       strncpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
+       strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
        adap->algo = &omap_i2c_algo;
        adap->dev.parent = &pdev->dev;
 
@@ -905,7 +941,7 @@ err_free_mem:
        platform_set_drvdata(pdev, NULL);
        kfree(dev);
 err_release_region:
-       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+       release_mem_region(mem->start, resource_size(mem));
 
        return r;
 }
@@ -925,7 +961,7 @@ omap_i2c_remove(struct platform_device *pdev)
        iounmap(dev->base);
        kfree(dev);
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+       release_mem_region(mem->start, resource_size(mem));
        return 0;
 }
 
index 8f42a4536cdf872d6f10ed8cc4b738d26e642df1..20bb0ceb027b79d029a915187bccf625d3560ec0 100644 (file)
@@ -763,11 +763,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
        dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq);
        dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon);
 
-       /* check for s3c2440 i2c controller  */
-
-       if (s3c24xx_i2c_is2440(i2c))
-               writel(0x0, i2c->regs + S3C2440_IICLC);
-
        return 0;
 }
 
index 1c01083b01b5ac0bc3f7eac54a657a72fb049ea0..820487d0d5c72eb13e301991d7008dec2bba75f5 100644 (file)
@@ -563,7 +563,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
                goto err_irq;
        }
 
-       size = (res->end - res->start) + 1;
+       size = resource_size(res);
 
        pd->reg = ioremap(res->start, size);
        if (pd->reg == NULL) {
@@ -637,7 +637,7 @@ static void __exit sh_mobile_i2c_adap_exit(void)
        platform_driver_unregister(&sh_mobile_i2c_driver);
 }
 
-module_init(sh_mobile_i2c_adap_init);
+subsys_initcall(sh_mobile_i2c_adap_init);
 module_exit(sh_mobile_i2c_adap_exit);
 
 MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver");
index 042fda295f3a557cd56c623a6aab980ae362271e..6407f47bda82db92b5ba2f2926851f774a938e91 100644 (file)
@@ -92,7 +92,7 @@ static int simtec_i2c_probe(struct platform_device *dev)
                goto err;
        }
 
-       size = (res->end-res->start)+1;
+       size = resource_size(res);
 
        pd->ioarea = request_mem_region(res->start, size, dev->name);
        if (pd->ioarea == NULL) {
index 182e711318bacf6793307b6641ab2ab6910158b8..d2728a28a8dba926e563957ad6339db653a7c632 100644 (file)
@@ -117,7 +117,8 @@ enum stu300_error {
        STU300_ERROR_NONE = 0,
        STU300_ERROR_ACKNOWLEDGE_FAILURE,
        STU300_ERROR_BUS_ERROR,
-       STU300_ERROR_ARBITRATION_LOST
+       STU300_ERROR_ARBITRATION_LOST,
+       STU300_ERROR_UNKNOWN
 };
 
 /* timeout waiting for the controller to respond */
@@ -127,7 +128,7 @@ enum stu300_error {
  * The number of address send athemps tried before giving up.
  * If the first one failes it seems like 5 to 8 attempts are required.
  */
-#define NUM_ADDR_RESEND_ATTEMPTS 10
+#define NUM_ADDR_RESEND_ATTEMPTS 12
 
 /* I2C clock speed, in Hz 0-400kHz*/
 static unsigned int scl_frequency = 100000;
@@ -149,6 +150,7 @@ module_param(scl_frequency, uint,  0644);
  * @msg_index: index of current message
  * @msg_len: length of current message
  */
+
 struct stu300_dev {
        struct platform_device  *pdev;
        struct i2c_adapter      adapter;
@@ -188,6 +190,27 @@ static inline u32 stu300_r8(void __iomem *address)
        return readl(address) & 0x000000FFU;
 }
 
+static void stu300_irq_enable(struct stu300_dev *dev)
+{
+       u32 val;
+       val = stu300_r8(dev->virtbase + I2C_CR);
+       val |= I2C_CR_INTERRUPT_ENABLE;
+       /* Twice paranoia (possible HW glitch) */
+       stu300_wr8(val, dev->virtbase + I2C_CR);
+       stu300_wr8(val, dev->virtbase + I2C_CR);
+}
+
+static void stu300_irq_disable(struct stu300_dev *dev)
+{
+       u32 val;
+       val = stu300_r8(dev->virtbase + I2C_CR);
+       val &= ~I2C_CR_INTERRUPT_ENABLE;
+       /* Twice paranoia (possible HW glitch) */
+       stu300_wr8(val, dev->virtbase + I2C_CR);
+       stu300_wr8(val, dev->virtbase + I2C_CR);
+}
+
+
 /*
  * Tells whether a certain event or events occurred in
  * response to a command. The events represent states in
@@ -196,9 +219,10 @@ static inline u32 stu300_r8(void __iomem *address)
  * documentation and can only be treated as abstract state
  * machine states.
  *
- * @ret 0 = event has not occurred, any other value means
- * the event occurred.
+ * @ret 0 = event has not occurred or unknown error, any
+ * other value means the correct event occurred or an error.
  */
+
 static int stu300_event_occurred(struct stu300_dev *dev,
                                   enum stu300_event mr_event) {
        u32 status1;
@@ -206,11 +230,28 @@ static int stu300_event_occurred(struct stu300_dev *dev,
 
        /* What event happened? */
        status1 = stu300_r8(dev->virtbase + I2C_SR1);
+
        if (!(status1 & I2C_SR1_EVF_IND))
                /* No event at all */
                return 0;
+
        status2 = stu300_r8(dev->virtbase + I2C_SR2);
 
+       /* Block any multiple interrupts */
+       stu300_irq_disable(dev);
+
+       /* Check for errors first */
+       if (status2 & I2C_SR2_AF_IND) {
+               dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE;
+               return 1;
+       } else if (status2 & I2C_SR2_BERR_IND) {
+               dev->cmd_err = STU300_ERROR_BUS_ERROR;
+               return 1;
+       } else if (status2 & I2C_SR2_ARLO_IND) {
+               dev->cmd_err = STU300_ERROR_ARBITRATION_LOST;
+               return 1;
+       }
+
        switch (mr_event) {
        case STU300_EVENT_1:
                if (status1 & I2C_SR1_ADSL_IND)
@@ -221,10 +262,6 @@ static int stu300_event_occurred(struct stu300_dev *dev,
        case STU300_EVENT_7:
        case STU300_EVENT_8:
                if (status1 & I2C_SR1_BTF_IND) {
-                       if (status2 & I2C_SR2_AF_IND)
-                               dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE;
-                       else if (status2 & I2C_SR2_BERR_IND)
-                               dev->cmd_err = STU300_ERROR_BUS_ERROR;
                        return 1;
                }
                break;
@@ -240,8 +277,6 @@ static int stu300_event_occurred(struct stu300_dev *dev,
        case STU300_EVENT_6:
                if (status2 & I2C_SR2_ENDAD_IND) {
                        /* First check for any errors */
-                       if (status2 & I2C_SR2_AF_IND)
-                               dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE;
                        return 1;
                }
                break;
@@ -252,8 +287,15 @@ static int stu300_event_occurred(struct stu300_dev *dev,
        default:
                break;
        }
-       if (status2 & I2C_SR2_ARLO_IND)
-               dev->cmd_err = STU300_ERROR_ARBITRATION_LOST;
+       /* If we get here, we're on thin ice.
+        * Here we are in a status where we have
+        * gotten a response that does not match
+        * what we requested.
+        */
+       dev->cmd_err = STU300_ERROR_UNKNOWN;
+       dev_err(&dev->pdev->dev,
+               "Unhandled interrupt! %d sr1: 0x%x sr2: 0x%x\n",
+               mr_event, status1, status2);
        return 0;
 }
 
@@ -262,21 +304,20 @@ static irqreturn_t stu300_irh(int irq, void *data)
        struct stu300_dev *dev = data;
        int res;
 
+       /* Just make sure that the block is clocked */
+       clk_enable(dev->clk);
+
        /* See if this was what we were waiting for */
        spin_lock(&dev->cmd_issue_lock);
-       if (dev->cmd_event != STU300_EVENT_NONE) {
-               res = stu300_event_occurred(dev, dev->cmd_event);
-               if (res || dev->cmd_err != STU300_ERROR_NONE) {
-                       u32 val;
-
-                       complete(&dev->cmd_complete);
-                       /* Block any multiple interrupts */
-                       val = stu300_r8(dev->virtbase + I2C_CR);
-                       val &= ~I2C_CR_INTERRUPT_ENABLE;
-                       stu300_wr8(val, dev->virtbase + I2C_CR);
-               }
-       }
+
+       res = stu300_event_occurred(dev, dev->cmd_event);
+       if (res || dev->cmd_err != STU300_ERROR_NONE)
+               complete(&dev->cmd_complete);
+
        spin_unlock(&dev->cmd_issue_lock);
+
+       clk_disable(dev->clk);
+
        return IRQ_HANDLED;
 }
 
@@ -308,7 +349,6 @@ static int stu300_start_and_await_event(struct stu300_dev *dev,
        stu300_wr8(cr_value, dev->virtbase + I2C_CR);
        ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
                                                        STU300_TIMEOUT);
-
        if (ret < 0) {
                dev_err(&dev->pdev->dev,
                       "wait_for_completion_interruptible_timeout() "
@@ -342,7 +382,6 @@ static int stu300_await_event(struct stu300_dev *dev,
                                enum stu300_event mr_event)
 {
        int ret;
-       u32 val;
 
        if (unlikely(irqs_disabled())) {
                /* TODO: implement polling for this case if need be. */
@@ -354,36 +393,18 @@ static int stu300_await_event(struct stu300_dev *dev,
        /* Is it already here? */
        spin_lock_irq(&dev->cmd_issue_lock);
        dev->cmd_err = STU300_ERROR_NONE;
-       if (stu300_event_occurred(dev, mr_event)) {
-               spin_unlock_irq(&dev->cmd_issue_lock);
-               goto exit_await_check_err;
-       }
-       init_completion(&dev->cmd_complete);
-       dev->cmd_err = STU300_ERROR_NONE;
        dev->cmd_event = mr_event;
 
-       /* Turn on the I2C interrupt for current operation */
-       val = stu300_r8(dev->virtbase + I2C_CR);
-       val |= I2C_CR_INTERRUPT_ENABLE;
-       stu300_wr8(val, dev->virtbase + I2C_CR);
-
-       /* Twice paranoia (possible HW glitch) */
-       stu300_wr8(val, dev->virtbase + I2C_CR);
+       init_completion(&dev->cmd_complete);
 
-       /* Check again: is it already here? */
-       if (unlikely(stu300_event_occurred(dev, mr_event))) {
-               /* Disable IRQ again. */
-               val &= ~I2C_CR_INTERRUPT_ENABLE;
-               stu300_wr8(val, dev->virtbase + I2C_CR);
-               spin_unlock_irq(&dev->cmd_issue_lock);
-               goto exit_await_check_err;
-       }
+       /* Turn on the I2C interrupt for current operation */
+       stu300_irq_enable(dev);
 
        /* Unlock the command block and wait for the event to occur */
        spin_unlock_irq(&dev->cmd_issue_lock);
+
        ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
                                                        STU300_TIMEOUT);
-
        if (ret < 0) {
                dev_err(&dev->pdev->dev,
                       "wait_for_completion_interruptible_timeout()"
@@ -401,7 +422,6 @@ static int stu300_await_event(struct stu300_dev *dev,
                return -ETIMEDOUT;
        }
 
- exit_await_check_err:
        if (dev->cmd_err != STU300_ERROR_NONE) {
                if (mr_event != STU300_EVENT_6) {
                        dev_err(&dev->pdev->dev, "controller "
@@ -457,18 +477,19 @@ struct stu300_clkset {
 };
 
 static const struct stu300_clkset stu300_clktable[] = {
-       { 0, 0xFFU },
-       { 2500000, I2C_OAR2_FR_25_10MHZ },
-       { 10000000, I2C_OAR2_FR_10_1667MHZ },
-       { 16670000, I2C_OAR2_FR_1667_2667MHZ },
-       { 26670000, I2C_OAR2_FR_2667_40MHZ },
-       { 40000000, I2C_OAR2_FR_40_5333MHZ },
-       { 53330000, I2C_OAR2_FR_5333_66MHZ },
-       { 66000000, I2C_OAR2_FR_66_80MHZ },
-       { 80000000, I2C_OAR2_FR_80_100MHZ },
+       { 0,         0xFFU },
+       { 2500000,   I2C_OAR2_FR_25_10MHZ },
+       { 10000000,  I2C_OAR2_FR_10_1667MHZ },
+       { 16670000,  I2C_OAR2_FR_1667_2667MHZ },
+       { 26670000,  I2C_OAR2_FR_2667_40MHZ },
+       { 40000000,  I2C_OAR2_FR_40_5333MHZ },
+       { 53330000,  I2C_OAR2_FR_5333_66MHZ },
+       { 66000000,  I2C_OAR2_FR_66_80MHZ },
+       { 80000000,  I2C_OAR2_FR_80_100MHZ },
        { 100000000, 0xFFU },
 };
 
+
 static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate)
 {
 
@@ -494,10 +515,10 @@ static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate)
 
        if (dev->speed > 100000)
                /* Fast Mode I2C */
-               val = ((clkrate/dev->speed)-9)/3;
+               val = ((clkrate/dev->speed) - 9)/3 + 1;
        else
                /* Standard Mode I2C */
-               val = ((clkrate/dev->speed)-7)/2;
+               val = ((clkrate/dev->speed) - 7)/2 + 1;
 
        /* According to spec the divider must be > 2 */
        if (val < 0x002) {
@@ -557,6 +578,7 @@ static int stu300_init_hw(struct stu300_dev *dev)
         */
        clkrate = clk_get_rate(dev->clk);
        ret = stu300_set_clk(dev, clkrate);
+
        if (ret)
                return ret;
        /*
@@ -641,7 +663,6 @@ static int stu300_xfer_msg(struct i2c_adapter *adap,
        int attempts = 0;
        struct stu300_dev *dev = i2c_get_adapdata(adap);
 
-
        clk_enable(dev->clk);
 
        /* Remove this if (0) to trace each and every message. */
@@ -715,14 +736,15 @@ static int stu300_xfer_msg(struct i2c_adapter *adap,
 
        if (attempts < NUM_ADDR_RESEND_ATTEMPTS && attempts > 0) {
                dev_dbg(&dev->pdev->dev, "managed to get address "
-                      "through after %d attempts\n", attempts);
+                       "through after %d attempts\n", attempts);
        } else if (attempts == NUM_ADDR_RESEND_ATTEMPTS) {
                dev_dbg(&dev->pdev->dev, "I give up, tried %d times "
-                      "to resend address.\n",
-                      NUM_ADDR_RESEND_ATTEMPTS);
+                       "to resend address.\n",
+                       NUM_ADDR_RESEND_ATTEMPTS);
                goto exit_disable;
        }
 
+
        if (msg->flags & I2C_M_RD) {
                /* READ: we read the actual bytes one at a time */
                for (i = 0; i < msg->len; i++) {
@@ -804,8 +826,10 @@ static int stu300_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 {
        int ret = -1;
        int i;
+
        struct stu300_dev *dev = i2c_get_adapdata(adap);
        dev->msg_len = num;
+
        for (i = 0; i < num; i++) {
                /*
                 * Another driver appears to send stop for each message,
@@ -817,6 +841,7 @@ static int stu300_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
                dev->msg_index = i;
 
                ret = stu300_xfer_msg(adap, &msgs[i], (i == (num - 1)));
+
                if (ret != 0) {
                        num = ret;
                        break;
@@ -845,6 +870,7 @@ stu300_probe(struct platform_device *pdev)
        struct resource *res;
        int bus_nr;
        int ret = 0;
+       char clk_name[] = "I2C0";
 
        dev = kzalloc(sizeof(struct stu300_dev), GFP_KERNEL);
        if (!dev) {
@@ -854,7 +880,8 @@ stu300_probe(struct platform_device *pdev)
        }
 
        bus_nr = pdev->id;
-       dev->clk = clk_get(&pdev->dev, NULL);
+       clk_name[3] += (char)bus_nr;
+       dev->clk = clk_get(&pdev->dev, clk_name);
        if (IS_ERR(dev->clk)) {
                ret = PTR_ERR(dev->clk);
                dev_err(&pdev->dev, "could not retrieve i2c bus clock\n");
index 1a9cc135219f4a5ea613c8da9819676cf19da0f4..b96f3025e588245fc498fcaddb78e706bfe03c6e 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/delay.h>
 
 #define TSL2550_DRV_NAME       "tsl2550"
-#define DRIVER_VERSION         "1.1.1"
+#define DRIVER_VERSION         "1.1.2"
 
 /*
  * Defines
@@ -189,13 +189,16 @@ static int tsl2550_calculate_lux(u8 ch0, u8 ch1)
        u8 r = 128;
 
        /* Avoid division by 0 and count 1 cannot be greater than count 0 */
-       if (c0 && (c1 <= c0))
-               r = c1 * 128 / c0;
+       if (c1 <= c0)
+               if (c0) {
+                       r = c1 * 128 / c0;
+
+                       /* Calculate LUX */
+                       lux = ((c0 - c1) * ratio_lut[r]) / 256;
+               } else
+                       lux = 0;
        else
-               return -1;
-
-       /* Calculate LUX */
-       lux = ((c0 - c1) * ratio_lut[r]) / 256;
+               return -EAGAIN;
 
        /* LUX range check */
        return lux > TSL2550_MAX_LUX ? TSL2550_MAX_LUX : lux;
index bd066bb9d61105262c342329fce891f38b015393..09f98ed0731fa251bfb08f46eea0e369eefe3f05 100644 (file)
@@ -135,6 +135,7 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
 
        ide_pci_setup_ports(dev, d, &hw[0], &hws[0]);
        hw[0].irq = 14;
+       hw[1].irq = 15;
 
        return ide_host_add(d, hws, 2, NULL);
 }
index 77f79d26b2648acebfd12ae44d396fd6c0481e34..c509c9916464db7c7819a92e2e9888e0340a67a1 100644 (file)
@@ -92,6 +92,11 @@ int ide_acpi_init(void)
        return 0;
 }
 
+bool ide_port_acpi(ide_hwif_t *hwif)
+{
+       return ide_noacpi == 0 && hwif->acpidata;
+}
+
 /**
  * ide_get_dev_handle - finds acpi_handle and PCI device.function
  * @dev: device to locate
@@ -352,9 +357,6 @@ int ide_acpi_exec_tfs(ide_drive_t *drive)
        unsigned long   gtf_address;
        unsigned long   obj_loc;
 
-       if (ide_noacpi)
-               return 0;
-
        DEBPRINT("call get_GTF, drive=%s port=%d\n", drive->name, drive->dn);
 
        ret = do_drive_get_GTF(drive, &gtf_length, &gtf_address, &obj_loc);
@@ -389,16 +391,6 @@ void ide_acpi_get_timing(ide_hwif_t *hwif)
        struct acpi_buffer      output;
        union acpi_object       *out_obj;
 
-       if (ide_noacpi)
-               return;
-
-       DEBPRINT("ENTER:\n");
-
-       if (!hwif->acpidata) {
-               DEBPRINT("no ACPI data for %s\n", hwif->name);
-               return;
-       }
-
        /* Setting up output buffer for _GTM */
        output.length = ACPI_ALLOCATE_BUFFER;
        output.pointer = NULL;  /* ACPI-CA sets this; save/free it later */
@@ -479,16 +471,6 @@ void ide_acpi_push_timing(ide_hwif_t *hwif)
        struct ide_acpi_drive_link      *master = &hwif->acpidata->master;
        struct ide_acpi_drive_link      *slave = &hwif->acpidata->slave;
 
-       if (ide_noacpi)
-               return;
-
-       DEBPRINT("ENTER:\n");
-
-       if (!hwif->acpidata) {
-               DEBPRINT("no ACPI data for %s\n", hwif->name);
-               return;
-       }
-
        /* Give the GTM buffer + drive Identify data to the channel via the
         * _STM method: */
        /* setup input parameters buffer for _STM */
@@ -527,16 +509,11 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
        ide_drive_t *drive;
        int i;
 
-       if (ide_noacpi || ide_noacpi_psx)
+       if (ide_noacpi_psx)
                return;
 
        DEBPRINT("ENTER:\n");
 
-       if (!hwif->acpidata) {
-               DEBPRINT("no ACPI data for %s\n", hwif->name);
-               return;
-       }
-
        /* channel first and then drives for power on and verse versa for power off */
        if (on)
                acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0);
@@ -616,7 +593,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif)
                                 drive->name, err);
        }
 
-       if (!ide_acpionboot) {
+       if (ide_noacpi || ide_acpionboot == 0) {
                DEBPRINT("ACPI methods disabled on boot\n");
                return;
        }
index 4a19686fcfe9a922ead806d98b62f07144f0c832..6a9a769bffc1993736064c54570aeeeef0c1b989 100644 (file)
@@ -592,9 +592,19 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                        }
                } else if (!blk_pc_request(rq)) {
                        ide_cd_request_sense_fixup(drive, cmd);
-                       /* complain if we still have data left to transfer */
+
                        uptodate = cmd->nleft ? 0 : 1;
-                       if (uptodate == 0)
+
+                       /*
+                        * suck out the remaining bytes from the drive in an
+                        * attempt to complete the data xfer. (see BZ#13399)
+                        */
+                       if (!(stat & ATA_ERR) && !uptodate && thislen) {
+                               ide_pio_bytes(drive, cmd, write, thislen);
+                               uptodate = cmd->nleft ? 0 : 1;
+                       }
+
+                       if (!uptodate)
                                rq->cmd_flags |= REQ_FAILED;
                }
                goto out_end;
@@ -876,9 +886,12 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
                return stat;
 
        /*
-        * Sanity check the given block size
+        * Sanity check the given block size, in so far as making
+        * sure the sectors_per_frame we give to the caller won't
+        * end up being bogus.
         */
        blocklen = be32_to_cpu(capbuf.blocklen);
+       blocklen = (blocklen >> SECTOR_BITS) << SECTOR_BITS;
        switch (blocklen) {
        case 512:
        case 1024:
@@ -886,10 +899,9 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
        case 4096:
                break;
        default:
-               printk(KERN_ERR PFX "%s: weird block size %u\n",
+               printk_once(KERN_ERR PFX "%s: weird block size %u; "
+                               "setting default block size to 2048\n",
                                drive->name, blocklen);
-               printk(KERN_ERR PFX "%s: default to 2kb block size\n",
-                               drive->name);
                blocklen = 2048;
                break;
        }
index 527908ff298c408c0f86fdf24363ea9c70d6e652..063b933d864a81f04acc0bbabdce2ec0297b7088 100644 (file)
@@ -408,6 +408,7 @@ static struct pcmcia_device_id ide_ids[] = {
        PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9),
        PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591),
        PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728),
+       PCMCIA_DEVICE_PROD_ID12("CNF   ", "CD-ROM", 0x46d7db81, 0x66536591),
        PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591),
        PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4),
        PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde),
index 5bf958e5b1d5fabe5019266448fe623065e69a82..1099bf7cf968ac216818e7ed0b6973e6cd6741ce 100644 (file)
@@ -183,6 +183,6 @@ ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq)
        err = setfunc(drive, *(int *)&rq->cmd[1]);
        if (err)
                rq->errors = err;
-       ide_complete_rq(drive, err, ide_rq_bytes(rq));
+       ide_complete_rq(drive, err, blk_rq_bytes(rq));
        return ide_stopped;
 }
index 695181120cdb9f14d0a16740c901345d599d052b..7f878017b736fcd913cfaea1e3939f10bb6cdf82 100644 (file)
@@ -455,6 +455,7 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
 
        rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
        rq->special = cmd;
+       cmd->rq = rq;
 }
 
 ide_devset_get(multcount, mult_count);
index 219e6fb78dc6414304ff8b707c59554f9c82db75..ee58c88dee5a61f51d437d1f618fd89745144785 100644 (file)
@@ -361,9 +361,6 @@ static int ide_tune_dma(ide_drive_t *drive)
        if (__ide_dma_bad_drive(drive))
                return 0;
 
-       if (ide_id_dma_bug(drive))
-               return 0;
-
        if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA)
                return config_drive_for_dma(drive);
 
@@ -394,24 +391,6 @@ static int ide_dma_check(ide_drive_t *drive)
        return -1;
 }
 
-int ide_id_dma_bug(ide_drive_t *drive)
-{
-       u16 *id = drive->id;
-
-       if (id[ATA_ID_FIELD_VALID] & 4) {
-               if ((id[ATA_ID_UDMA_MODES] >> 8) &&
-                   (id[ATA_ID_MWDMA_MODES] >> 8))
-                       goto err_out;
-       } else if ((id[ATA_ID_MWDMA_MODES] >> 8) &&
-                  (id[ATA_ID_SWDMA_MODES] >> 8))
-               goto err_out;
-
-       return 0;
-err_out:
-       printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name);
-       return 1;
-}
-
 int ide_set_dma(ide_drive_t *drive)
 {
        int rc;
index 2b91419796136e24b4a98a27dd85aab0c6caccc0..e9abf2c3c33544c047ec2db7f29f1f295da0a397 100644 (file)
@@ -149,7 +149,7 @@ static inline void ide_complete_drive_reset(ide_drive_t *drive, int err)
        if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) {
                if (err <= 0 && rq->errors == 0)
                        rq->errors = -EIO;
-               ide_complete_rq(drive, err ? err : 0, ide_rq_bytes(rq));
+               ide_complete_rq(drive, err ? err : 0, blk_rq_bytes(rq));
        }
 }
 
index 8b3f204f7d7325955b52b277ede13ab83984aa2e..fefbdfc8db068868afe0dadb0914a948219ea824 100644 (file)
@@ -293,7 +293,7 @@ out_end:
        drive->failed_pc = NULL;
        if (blk_fs_request(rq) == 0 && rq->errors == 0)
                rq->errors = -EIO;
-       ide_complete_rq(drive, -EIO, ide_rq_bytes(rq));
+       ide_complete_rq(drive, -EIO, blk_rq_bytes(rq));
        return ide_stopped;
 }
 
index 1059f809b809bb0f94048361d8b03e990953ccee..db96138fefcdef55f923580a0404674f8178314b 100644 (file)
@@ -112,16 +112,6 @@ void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err)
        }
 }
 
-/* obsolete, blk_rq_bytes() should be used instead */
-unsigned int ide_rq_bytes(struct request *rq)
-{
-       if (blk_pc_request(rq))
-               return blk_rq_bytes(rq);
-       else
-               return blk_rq_cur_sectors(rq) << 9;
-}
-EXPORT_SYMBOL_GPL(ide_rq_bytes);
-
 int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes)
 {
        ide_hwif_t *hwif = drive->hwif;
@@ -152,14 +142,14 @@ void ide_kill_rq(ide_drive_t *drive, struct request *rq)
 
        if ((media == ide_floppy || media == ide_tape) && drv_req) {
                rq->errors = 0;
-               ide_complete_rq(drive, 0, blk_rq_bytes(rq));
        } else {
                if (media == ide_tape)
                        rq->errors = IDE_DRV_ERROR_GENERAL;
                else if (blk_fs_request(rq) == 0 && rq->errors == 0)
                        rq->errors = -EIO;
-               ide_complete_rq(drive, -EIO, ide_rq_bytes(rq));
        }
+
+       ide_complete_rq(drive, -EIO, blk_rq_bytes(rq));
 }
 
 static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
index 82f252c3ee6e500eb85fc466f1fc26e5c71b6d5a..e246d3d3fbcc5c280ff520b090c297eb42c05a1e 100644 (file)
@@ -64,7 +64,8 @@ static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd,
                goto out;
        }
 
-       id = kmalloc(size, GFP_KERNEL);
+       /* ata_id_to_hd_driveid() relies on 'id' to be fully allocated. */
+       id = kmalloc(ATA_ID_WORDS * 2, GFP_KERNEL);
        if (id == NULL) {
                rc = -ENOMEM;
                goto out;
index fa047150a1c691f47f9c74a8404810d451332619..2892b242bbe1c84feed1a343bdbb6494135f9e9a 100644 (file)
@@ -210,6 +210,7 @@ EXPORT_SYMBOL_GPL(ide_in_drive_list);
  */
 static const struct drive_list_entry ivb_list[] = {
        { "QUANTUM FIREBALLlct10 05"    , "A03.0900"    },
+       { "QUANTUM FIREBALLlct20 30"    , "APL.0900"    },
        { "TSSTcorp CDDVDW SH-S202J"    , "SB00"        },
        { "TSSTcorp CDDVDW SH-S202J"    , "SB01"        },
        { "TSSTcorp CDDVDW SH-S202N"    , "SB00"        },
@@ -329,9 +330,6 @@ int ide_driveid_update(ide_drive_t *drive)
 
        kfree(id);
 
-       if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && ide_id_dma_bug(drive))
-               ide_dma_off(drive);
-
        return 1;
 out_err:
        if (rc == 2)
index c14ca144cffe035d7722b6bb9fb8720652ad11bc..ad7be2669dcb9020bc5b91612079d80f21fd6869 100644 (file)
@@ -10,9 +10,11 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg)
        struct request_pm_state rqpm;
        int ret;
 
-       /* call ACPI _GTM only once */
-       if ((drive->dn & 1) == 0 || pair == NULL)
-               ide_acpi_get_timing(hwif);
+       if (ide_port_acpi(hwif)) {
+               /* call ACPI _GTM only once */
+               if ((drive->dn & 1) == 0 || pair == NULL)
+                       ide_acpi_get_timing(hwif);
+       }
 
        memset(&rqpm, 0, sizeof(rqpm));
        rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
@@ -26,9 +28,11 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg)
        ret = blk_execute_rq(drive->queue, NULL, rq, 0);
        blk_put_request(rq);
 
-       /* call ACPI _PS3 only after both devices are suspended */
-       if (ret == 0 && ((drive->dn & 1) || pair == NULL))
-               ide_acpi_set_state(hwif, 0);
+       if (ret == 0 && ide_port_acpi(hwif)) {
+               /* call ACPI _PS3 only after both devices are suspended */
+               if ((drive->dn & 1) || pair == NULL)
+                       ide_acpi_set_state(hwif, 0);
+       }
 
        return ret;
 }
@@ -42,13 +46,15 @@ int generic_ide_resume(struct device *dev)
        struct request_pm_state rqpm;
        int err;
 
-       /* call ACPI _PS0 / _STM only once */
-       if ((drive->dn & 1) == 0 || pair == NULL) {
-               ide_acpi_set_state(hwif, 1);
-               ide_acpi_push_timing(hwif);
-       }
+       if (ide_port_acpi(hwif)) {
+               /* call ACPI _PS0 / _STM only once */
+               if ((drive->dn & 1) == 0 || pair == NULL) {
+                       ide_acpi_set_state(hwif, 1);
+                       ide_acpi_push_timing(hwif);
+               }
 
-       ide_acpi_exec_tfs(drive);
+               ide_acpi_exec_tfs(drive);
+       }
 
        memset(&rqpm, 0, sizeof(rqpm));
        rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
index 51af4eea0d367440d69a9c6db98e097f50ad2d12..1bb106f6221a5aad84aa6385158b23d53b9eaa69 100644 (file)
@@ -818,6 +818,24 @@ static int ide_port_setup_devices(ide_hwif_t *hwif)
        return j;
 }
 
+static void ide_host_enable_irqs(struct ide_host *host)
+{
+       ide_hwif_t *hwif;
+       int i;
+
+       ide_host_for_each_port(i, hwif, host) {
+               if (hwif == NULL)
+                       continue;
+
+               /* clear any pending IRQs */
+               hwif->tp_ops->read_status(hwif);
+
+               /* unmask IRQs */
+               if (hwif->io_ports.ctl_addr)
+                       hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
+       }
+}
+
 /*
  * This routine sets up the IRQ for an IDE interface.
  */
@@ -831,9 +849,6 @@ static int init_irq (ide_hwif_t *hwif)
        if (irq_handler == NULL)
                irq_handler = ide_intr;
 
-       if (io_ports->ctl_addr)
-               hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
-
        if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif))
                goto out_up;
 
@@ -1404,6 +1419,8 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
                        ide_port_tune_devices(hwif);
        }
 
+       ide_host_enable_irqs(host);
+
        ide_host_for_each_port(i, hwif, host) {
                if (hwif == NULL)
                        continue;
index 013dc595fab63754b391b33a7efd6b3e287167c3..bc5fb12b913c365da7610365c2167b7a7820e4de 100644 (file)
@@ -1064,6 +1064,7 @@ static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd,
                tape->best_dsc_rw_freq = config.dsc_rw_frequency;
                break;
        case 0x0350:
+               memset(&config, 0, sizeof(config));
                config.dsc_rw_frequency = (int) tape->best_dsc_rw_freq;
                config.nr_stages = 1;
                if (copy_to_user(argp, &config, sizeof(config)))
index 83b734aec923f795a5e4d79dcc162e68f5efaf5d..52b25f8b111d73fad2b4e6b1252b823854190ec2 100644 (file)
@@ -880,6 +880,7 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud)
        }
 
        shost->hostdata[0] = (unsigned long)lu;
+       shost->max_cmd_len = SBP2_MAX_CDB_SIZE;
 
        if (!scsi_add_host(shost, &ud->device)) {
                lu->shost = shost;
index c5036f1cc5b0d674155ea2a89087e9ba5e981eb5..64a3a66a8a396fdc45d0e09d4f663cacb528f714 100644 (file)
 
 #define SBP2_DEVICE_NAME               "sbp2"
 
+/*
+ * There is no transport protocol limit to the CDB length,  but we implement
+ * a fixed length only.  16 bytes is enough for disks larger than 2 TB.
+ */
+#define SBP2_MAX_CDB_SIZE              16
+
 /*
  * SBP-2 specific definitions
  */
@@ -51,7 +57,7 @@ struct sbp2_command_orb {
        u32 data_descriptor_hi;
        u32 data_descriptor_lo;
        u32 misc;
-       u8 cdb[12];
+       u8 cdb[SBP2_MAX_CDB_SIZE];
 } __attribute__((packed));
 
 #define SBP2_LOGIN_REQUEST             0x0
index 114efd8dc8f585cfc389dfbb28d11c3c0cd0d3fb..1148140d08a1faf72967dc3068e41c71488054d8 100644 (file)
@@ -608,8 +608,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                                                    p, compat_mode);
 
                        if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
-                               return str_to_user(dev_name(&evdev->dev),
-                                                  _IOC_SIZE(cmd), p);
+                               return str_to_user(dev->name, _IOC_SIZE(cmd), p);
 
                        if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
                                return str_to_user(dev->phys, _IOC_SIZE(cmd), p);
index 0e12f89276a370e753ccbb9e111030f5f83ae253..9a1d55b74d7a0b79296ee909a11011140f71d4a3 100644 (file)
@@ -456,8 +456,11 @@ static int joydev_ioctl_common(struct joydev *joydev,
                                unsigned int cmd, void __user *argp)
 {
        struct input_dev *dev = joydev->handle.dev;
+       size_t len;
        int i, j;
+       const char *name;
 
+       /* Process fixed-sized commands. */
        switch (cmd) {
 
        case JS_SET_CAL:
@@ -499,9 +502,22 @@ static int joydev_ioctl_common(struct joydev *joydev,
                return copy_to_user(argp, joydev->corr,
                        sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0;
 
-       case JSIOCSAXMAP:
-               if (copy_from_user(joydev->abspam, argp,
-                                  sizeof(__u8) * (ABS_MAX + 1)))
+       }
+
+       /*
+        * Process variable-sized commands (the axis and button map commands
+        * are considered variable-sized to decouple them from the values of
+        * ABS_MAX and KEY_MAX).
+        */
+       switch (cmd & ~IOCSIZE_MASK) {
+
+       case (JSIOCSAXMAP & ~IOCSIZE_MASK):
+               len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam));
+               /*
+                * FIXME: we should not copy into our axis map before
+                * validating the data.
+                */
+               if (copy_from_user(joydev->abspam, argp, len))
                        return -EFAULT;
 
                for (i = 0; i < joydev->nabs; i++) {
@@ -511,13 +527,17 @@ static int joydev_ioctl_common(struct joydev *joydev,
                }
                return 0;
 
-       case JSIOCGAXMAP:
-               return copy_to_user(argp, joydev->abspam,
-                       sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0;
-
-       case JSIOCSBTNMAP:
-               if (copy_from_user(joydev->keypam, argp,
-                                  sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)))
+       case (JSIOCGAXMAP & ~IOCSIZE_MASK):
+               len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam));
+               return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : 0;
+
+       case (JSIOCSBTNMAP & ~IOCSIZE_MASK):
+               len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam));
+               /*
+                * FIXME: we should not copy into our keymap before
+                * validating the data.
+                */
+               if (copy_from_user(joydev->keypam, argp, len))
                        return -EFAULT;
 
                for (i = 0; i < joydev->nkey; i++) {
@@ -529,25 +549,19 @@ static int joydev_ioctl_common(struct joydev *joydev,
 
                return 0;
 
-       case JSIOCGBTNMAP:
-               return copy_to_user(argp, joydev->keypam,
-                       sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0;
+       case (JSIOCGBTNMAP & ~IOCSIZE_MASK):
+               len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam));
+               return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : 0;
 
-       default:
-               if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) {
-                       int len;
-                       const char *name = dev_name(&dev->dev);
-
-                       if (!name)
-                               return 0;
-                       len = strlen(name) + 1;
-                       if (len > _IOC_SIZE(cmd))
-                               len = _IOC_SIZE(cmd);
-                       if (copy_to_user(argp, name, len))
-                               return -EFAULT;
-                       return len;
-               }
+       case JSIOCGNAME(0):
+               name = dev->name;
+               if (!name)
+                       return 0;
+
+               len = min_t(size_t, _IOC_SIZE(cmd), strlen(name) + 1);
+               return copy_to_user(argp, name, len) ? -EFAULT : len;
        }
+
        return -EINVAL;
 }
 
index baabf8302645511b91c65a02c67baa5e1647218a..f6c688cae33430e877cf88e39f2bfda4553ef145 100644 (file)
@@ -74,6 +74,7 @@ static struct iforce_device iforce_device[] = {
        { 0x05ef, 0x8884, "AVB Mag Turbo Force",                        btn_avb_wheel, abs_wheel, ff_iforce },
        { 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel",   btn_avb_tw, abs_wheel, ff_iforce }, //?
        { 0x061c, 0xc0a4, "ACT LABS Force RS",                          btn_wheel, abs_wheel, ff_iforce }, //?
+       { 0x061c, 0xc084, "ACT LABS Force RS",                          btn_wheel, abs_wheel, ff_iforce },
        { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback",       btn_wheel, abs_wheel, ff_iforce }, //?
        { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel",      btn_wheel, abs_wheel, ff_iforce }, //?
        { 0x06f8, 0x0004, "Gullemot Jet Leader 3D",                     btn_joystick, abs_joystick, ff_iforce }, //?
index f83185aeb511abeab1bae588a06818f4b63c9a71..9f289d8f52c6e70dc0b6c28c0583291e46cdadaa 100644 (file)
@@ -223,6 +223,7 @@ static struct usb_device_id iforce_usb_ids [] = {
        { USB_DEVICE(0x05ef, 0x8884) },         /* AVB Mag Turbo Force */
        { USB_DEVICE(0x05ef, 0x8888) },         /* AVB Top Shot FFB Racing Wheel */
        { USB_DEVICE(0x061c, 0xc0a4) },         /* ACT LABS Force RS */
+       { USB_DEVICE(0x061c, 0xc084) },         /* ACT LABS Force RS */
        { USB_DEVICE(0x06f8, 0x0001) },         /* Guillemot Race Leader Force Feedback */
        { USB_DEVICE(0x06f8, 0x0004) },         /* Guillemot Force Feedback Racing Wheel */
        { USB_DEVICE(0x06f8, 0xa302) },         /* Guillemot Jet Leader 3D */
index b868b8d5fbb3e29c58a78c69f5350098fd9ed6f2..f155ad8cdae7e16b8240b20c95c983be24536c41 100644 (file)
@@ -470,20 +470,20 @@ static void xpad_irq_out(struct urb *urb)
        status = urb->status;
 
        switch (status) {
-               case 0:
+       case 0:
                /* success */
-               break;
-               case -ECONNRESET:
-               case -ENOENT:
-               case -ESHUTDOWN:
-                       /* this urb is terminated, clean up */
-                       dbg("%s - urb shutting down with status: %d",
-                               __func__, status);
-                       return;
-               default:
-                       dbg("%s - nonzero urb status received: %d",
-                               __func__, status);
-                       goto exit;
+               return;
+
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dbg("%s - urb shutting down with status: %d", __func__, status);
+               return;
+
+       default:
+               dbg("%s - nonzero urb status received: %d", __func__, status);
+               goto exit;
        }
 
 exit:
index 9d8f796c6745291f3bd5bccf3a52177c3583c06f..a6b989a9dc07eee021d90e1d6f4ae902da547056 100644 (file)
@@ -12,6 +12,42 @@ menuconfig INPUT_KEYBOARD
 
 if INPUT_KEYBOARD
 
+config KEYBOARD_AAED2000
+       tristate "AAED-2000 keyboard"
+       depends on MACH_AAED2000
+       select INPUT_POLLDEV
+       default y
+       help
+         Say Y here to enable the keyboard on the Agilent AAED-2000
+         development board.
+
+         To compile this driver as a module, choose M here: the
+         module will be called aaed2000_kbd.
+
+config KEYBOARD_AMIGA
+       tristate "Amiga keyboard"
+       depends on AMIGA
+       help
+         Say Y here if you are running Linux on any AMIGA and have a keyboard
+         attached.
+
+         To compile this driver as a module, choose M here: the
+         module will be called amikbd.
+
+config ATARI_KBD_CORE
+       bool
+
+config KEYBOARD_ATARI
+       tristate "Atari keyboard"
+       depends on ATARI
+       select ATARI_KBD_CORE
+       help
+         Say Y here if you are running Linux on any Atari and have a keyboard
+         attached.
+
+         To compile this driver as a module, choose M here: the
+         module will be called atakbd.
+
 config KEYBOARD_ATKBD
        tristate "AT keyboard" if EMBEDDED || !X86
        default y
@@ -68,69 +104,14 @@ config KEYBOARD_ATKBD_RDI_KEYCODES
          right-hand column will be interpreted as the key shown in the
          left-hand column.
 
-config KEYBOARD_SUNKBD
-       tristate "Sun Type 4 and Type 5 keyboard"
-       select SERIO
-       help
-         Say Y here if you want to use a Sun Type 4 or Type 5 keyboard,
-         connected either to the Sun keyboard connector or to an serial
-         (RS-232) port via a simple adapter.
-
-         To compile this driver as a module, choose M here: the
-         module will be called sunkbd.
-
-config KEYBOARD_LKKBD
-       tristate "DECstation/VAXstation LK201/LK401 keyboard"
-       select SERIO
-       help
-         Say Y here if you want to use a LK201 or LK401 style serial
-         keyboard. This keyboard is also useable on PCs if you attach
-         it with the inputattach program. The connector pinout is
-         described within lkkbd.c.
-
-         To compile this driver as a module, choose M here: the
-         module will be called lkkbd.
-
-config KEYBOARD_LOCOMO
-       tristate "LoCoMo Keyboard Support"
-       depends on SHARP_LOCOMO && INPUT_KEYBOARD
-       help
-         Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA
-
-         To compile this driver as a module, choose M here: the
-         module will be called locomokbd.
-
-config KEYBOARD_XTKBD
-       tristate "XT keyboard"
-       select SERIO
-       help
-         Say Y here if you want to use the old IBM PC/XT keyboard (or
-         compatible) on your system. This is only possible with a
-         parallel port keyboard adapter, you cannot connect it to the
-         keyboard port on a PC that runs Linux.
-
-         To compile this driver as a module, choose M here: the
-         module will be called xtkbd.
-
-config KEYBOARD_NEWTON
-       tristate "Newton keyboard"
-       select SERIO
-       help
-         Say Y here if you have a Newton keyboard on a serial port.
-
-         To compile this driver as a module, choose M here: the
-         module will be called newtonkbd.
-
-config KEYBOARD_STOWAWAY
-       tristate "Stowaway keyboard"
-       select SERIO
+config KEYBOARD_BFIN
+       tristate "Blackfin BF54x keypad support"
+       depends on (BF54x && !BF544)
        help
-         Say Y here if you have a Stowaway keyboard on a serial port.
-         Stowaway compatible keyboards like Dicota Input-PDA keyboard
-         are also supported by this driver.
+         Say Y here if you want to use the BF54x keypad.
 
          To compile this driver as a module, choose M here: the
-         module will be called stowaway.
+         module will be called bf54x-keys.
 
 config KEYBOARD_CORGI
        tristate "Corgi keyboard"
@@ -143,61 +124,50 @@ config KEYBOARD_CORGI
          To compile this driver as a module, choose M here: the
          module will be called corgikbd.
 
-config KEYBOARD_SPITZ
-       tristate "Spitz keyboard"
-       depends on PXA_SHARPSL
-       default y
+config KEYBOARD_LKKBD
+       tristate "DECstation/VAXstation LK201/LK401 keyboard"
+       select SERIO
        help
-         Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
-         SL-C3000 and Sl-C3100 series of PDAs.
+         Say Y here if you want to use a LK201 or LK401 style serial
+         keyboard. This keyboard is also useable on PCs if you attach
+         it with the inputattach program. The connector pinout is
+         described within lkkbd.c.
 
          To compile this driver as a module, choose M here: the
-         module will be called spitzkbd.
+         module will be called lkkbd.
 
-config KEYBOARD_TOSA
-       tristate "Tosa keyboard"
-       depends on MACH_TOSA
-       default y
+config KEYBOARD_EP93XX
+       tristate "EP93xx Matrix Keypad support"
+       depends on ARCH_EP93XX
        help
-         Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa)
+         Say Y here to enable the matrix keypad on the Cirrus EP93XX.
 
          To compile this driver as a module, choose M here: the
-         module will be called tosakbd.
+         module will be called ep93xx_keypad.
 
-config KEYBOARD_TOSA_USE_EXT_KEYCODES
-       bool "Tosa keyboard: use extended keycodes"
-       depends on KEYBOARD_TOSA
-       default n
+config KEYBOARD_GPIO
+       tristate "GPIO Buttons"
+       depends on GENERIC_GPIO
        help
-         Say Y here to enable the tosa keyboard driver to generate extended
-         (>= 127) keycodes. Be aware, that they can't be correctly interpreted
-         by either console keyboard driver or by Kdrive keybd driver.
-
-         Say Y only if you know, what you are doing!
+         This driver implements support for buttons connected
+         to GPIO pins of various CPUs (and some other chips).
 
-config KEYBOARD_AMIGA
-       tristate "Amiga keyboard"
-       depends on AMIGA
-       help
-         Say Y here if you are running Linux on any AMIGA and have a keyboard
-         attached.
+         Say Y here if your device has buttons connected
+         directly to such GPIO pins.  Your board-specific
+         setup logic must also provide a platform device,
+         with configuration data saying which GPIOs are used.
 
          To compile this driver as a module, choose M here: the
-         module will be called amikbd.
+         module will be called gpio_keys.
 
-config ATARI_KBD_CORE
-       bool
-
-config KEYBOARD_ATARI
-       tristate "Atari keyboard"
-       depends on ATARI
-       select ATARI_KBD_CORE
+config KEYBOARD_MATRIX
+       tristate "GPIO driven matrix keypad support"
+       depends on GENERIC_GPIO
        help
-         Say Y here if you are running Linux on any Atari and have a keyboard
-         attached.
+         Enable support for GPIO driven matrix keypad.
 
          To compile this driver as a module, choose M here: the
-         module will be called atakbd.
+         module will be called matrix_keypad.
 
 config KEYBOARD_HIL_OLD
        tristate "HP HIL keyboard support (simple driver)"
@@ -261,20 +231,39 @@ config KEYBOARD_LM8323
          To compile this driver as a module, choose M here: the
          module will be called lm8323.
 
-config KEYBOARD_OMAP
-       tristate "TI OMAP keypad support"
-       depends on (ARCH_OMAP1 || ARCH_OMAP2)
+config KEYBOARD_LOCOMO
+       tristate "LoCoMo Keyboard Support"
+       depends on SHARP_LOCOMO
        help
-         Say Y here if you want to use the OMAP keypad.
+         Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA
 
          To compile this driver as a module, choose M here: the
-         module will be called omap-keypad.
+         module will be called locomokbd.
+
+config KEYBOARD_MAPLE
+       tristate "Maple bus keyboard"
+       depends on SH_DREAMCAST && MAPLE
+       help
+         Say Y here if you have a Dreamcast console running Linux and have
+         a keyboard attached to its Maple bus.
+
+         To compile this driver as a module, choose M here: the
+         module will be called maple_keyb.
+
+config KEYBOARD_NEWTON
+       tristate "Newton keyboard"
+       select SERIO
+       help
+         Say Y here if you have a Newton keyboard on a serial port.
+
+         To compile this driver as a module, choose M here: the
+         module will be called newtonkbd.
 
 config KEYBOARD_PXA27x
        tristate "PXA27x/PXA3xx keypad support"
        depends on PXA27x || PXA3xx
        help
-         Enable support for PXA27x/PXA3xx keypad controller
+         Enable support for PXA27x/PXA3xx keypad controller.
 
          To compile this driver as a module, choose M here: the
          module will be called pxa27x_keypad.
@@ -288,51 +277,38 @@ config KEYBOARD_PXA930_ROTARY
          To compile this driver as a module, choose M here: the
          module will be called pxa930_rotary.
 
-config KEYBOARD_AAED2000
-       tristate "AAED-2000 keyboard"
-       depends on MACH_AAED2000
-       select INPUT_POLLDEV
+config KEYBOARD_SPITZ
+       tristate "Spitz keyboard"
+       depends on PXA_SHARPSL
        default y
        help
-         Say Y here to enable the keyboard on the Agilent AAED-2000
-         development board.
-
-         To compile this driver as a module, choose M here: the
-         module will be called aaed2000_kbd.
-
-config KEYBOARD_GPIO
-       tristate "GPIO Buttons"
-       depends on GENERIC_GPIO
-       help
-         This driver implements support for buttons connected
-         to GPIO pins of various CPUs (and some other chips).
-
-         Say Y here if your device has buttons connected
-         directly to such GPIO pins.  Your board-specific
-         setup logic must also provide a platform device,
-         with configuration data saying which GPIOs are used.
+         Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
+         SL-C3000 and Sl-C3100 series of PDAs.
 
          To compile this driver as a module, choose M here: the
-         module will be called gpio-keys.
+         module will be called spitzkbd.
 
-config KEYBOARD_MAPLE
-       tristate "Maple bus keyboard"
-       depends on SH_DREAMCAST && MAPLE
+config KEYBOARD_STOWAWAY
+       tristate "Stowaway keyboard"
+       select SERIO
        help
-         Say Y here if you have a Dreamcast console running Linux and have
-         a keyboard attached to its Maple bus.
+         Say Y here if you have a Stowaway keyboard on a serial port.
+         Stowaway compatible keyboards like Dicota Input-PDA keyboard
+         are also supported by this driver.
 
          To compile this driver as a module, choose M here: the
-         module will be called maple_keyb.
+         module will be called stowaway.
 
-config KEYBOARD_BFIN
-       tristate "Blackfin BF54x keypad support"
-       depends on (BF54x && !BF544)
+config KEYBOARD_SUNKBD
+       tristate "Sun Type 4 and Type 5 keyboard"
+       select SERIO
        help
-         Say Y here if you want to use the BF54x keypad.
+         Say Y here if you want to use a Sun Type 4 or Type 5 keyboard,
+         connected either to the Sun keyboard connector or to an serial
+         (RS-232) port via a simple adapter.
 
          To compile this driver as a module, choose M here: the
-         module will be called bf54x-keys.
+         module will be called sunkbd.
 
 config KEYBOARD_SH_KEYSC
        tristate "SuperH KEYSC keypad support"
@@ -344,13 +320,45 @@ config KEYBOARD_SH_KEYSC
          To compile this driver as a module, choose M here: the
          module will be called sh_keysc.
 
-config KEYBOARD_EP93XX
-       tristate "EP93xx Matrix Keypad support"
-       depends on ARCH_EP93XX
+config KEYBOARD_OMAP
+       tristate "TI OMAP keypad support"
+       depends on (ARCH_OMAP1 || ARCH_OMAP2)
        help
-         Say Y here to enable the matrix keypad on the Cirrus EP93XX.
+         Say Y here if you want to use the OMAP keypad.
 
          To compile this driver as a module, choose M here: the
-         module will be called ep93xx_keypad.
+         module will be called omap-keypad.
+
+config KEYBOARD_TOSA
+       tristate "Tosa keyboard"
+       depends on MACH_TOSA
+       default y
+       help
+         Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa)
+
+         To compile this driver as a module, choose M here: the
+         module will be called tosakbd.
+
+config KEYBOARD_TOSA_USE_EXT_KEYCODES
+       bool "Tosa keyboard: use extended keycodes"
+       depends on KEYBOARD_TOSA
+       help
+         Say Y here to enable the tosa keyboard driver to generate extended
+         (>= 127) keycodes. Be aware, that they can't be correctly interpreted
+         by either console keyboard driver or by Kdrive keybd driver.
+
+         Say Y only if you know, what you are doing!
+
+config KEYBOARD_XTKBD
+       tristate "XT keyboard"
+       select SERIO
+       help
+         Say Y here if you want to use the old IBM PC/XT keyboard (or
+         compatible) on your system. This is only possible with a
+         parallel port keyboard adapter, you cannot connect it to the
+         keyboard port on a PC that runs Linux.
+
+         To compile this driver as a module, choose M here: the
+         module will be called xtkbd.
 
 endif
index 156b647a259b776b07c64b9e2e99ca6d2bad7286..b5b5eae9724fa5f49b651bcd987ebeb5d0707c18 100644 (file)
@@ -4,29 +4,30 @@
 
 # Each configuration option enables a list of files.
 
-obj-$(CONFIG_KEYBOARD_ATKBD)           += atkbd.o
-obj-$(CONFIG_KEYBOARD_SUNKBD)          += sunkbd.o
-obj-$(CONFIG_KEYBOARD_LKKBD)           += lkkbd.o
-obj-$(CONFIG_KEYBOARD_XTKBD)           += xtkbd.o
+obj-$(CONFIG_KEYBOARD_AAED2000)                += aaed2000_kbd.o
 obj-$(CONFIG_KEYBOARD_AMIGA)           += amikbd.o
 obj-$(CONFIG_KEYBOARD_ATARI)           += atakbd.o
-obj-$(CONFIG_KEYBOARD_LOCOMO)          += locomokbd.o
-obj-$(CONFIG_KEYBOARD_NEWTON)          += newtonkbd.o
-obj-$(CONFIG_KEYBOARD_STOWAWAY)                += stowaway.o
+obj-$(CONFIG_KEYBOARD_ATKBD)           += atkbd.o
+obj-$(CONFIG_KEYBOARD_BFIN)            += bf54x-keys.o
 obj-$(CONFIG_KEYBOARD_CORGI)           += corgikbd.o
-obj-$(CONFIG_KEYBOARD_SPITZ)           += spitzkbd.o
-obj-$(CONFIG_KEYBOARD_TOSA)            += tosakbd.o
+obj-$(CONFIG_KEYBOARD_EP93XX)          += ep93xx_keypad.o
+obj-$(CONFIG_KEYBOARD_GPIO)            += gpio_keys.o
 obj-$(CONFIG_KEYBOARD_HIL)             += hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)         += hilkbd.o
+obj-$(CONFIG_KEYBOARD_HP6XX)           += jornada680_kbd.o
+obj-$(CONFIG_KEYBOARD_HP7XX)           += jornada720_kbd.o
+obj-$(CONFIG_KEYBOARD_LKKBD)           += lkkbd.o
 obj-$(CONFIG_KEYBOARD_LM8323)          += lm8323.o
+obj-$(CONFIG_KEYBOARD_LOCOMO)          += locomokbd.o
+obj-$(CONFIG_KEYBOARD_MAPLE)           += maple_keyb.o
+obj-$(CONFIG_KEYBOARD_MATRIX)          += matrix_keypad.o
+obj-$(CONFIG_KEYBOARD_NEWTON)          += newtonkbd.o
 obj-$(CONFIG_KEYBOARD_OMAP)            += omap-keypad.o
 obj-$(CONFIG_KEYBOARD_PXA27x)          += pxa27x_keypad.o
 obj-$(CONFIG_KEYBOARD_PXA930_ROTARY)   += pxa930_rotary.o
-obj-$(CONFIG_KEYBOARD_AAED2000)                += aaed2000_kbd.o
-obj-$(CONFIG_KEYBOARD_GPIO)            += gpio_keys.o
-obj-$(CONFIG_KEYBOARD_HP6XX)           += jornada680_kbd.o
-obj-$(CONFIG_KEYBOARD_HP7XX)           += jornada720_kbd.o
-obj-$(CONFIG_KEYBOARD_MAPLE)           += maple_keyb.o
-obj-$(CONFIG_KEYBOARD_BFIN)            += bf54x-keys.o
 obj-$(CONFIG_KEYBOARD_SH_KEYSC)                += sh_keysc.o
-obj-$(CONFIG_KEYBOARD_EP93XX)          += ep93xx_keypad.o
+obj-$(CONFIG_KEYBOARD_SPITZ)           += spitzkbd.o
+obj-$(CONFIG_KEYBOARD_STOWAWAY)                += stowaway.o
+obj-$(CONFIG_KEYBOARD_SUNKBD)          += sunkbd.o
+obj-$(CONFIG_KEYBOARD_TOSA)            += tosakbd.o
+obj-$(CONFIG_KEYBOARD_XTKBD)           += xtkbd.o
index df3f8aa68115c48109739f84df30eee651a8ef4e..6c6a09b1c0fed5f116ccddd4ab39de971c08e5a4 100644 (file)
@@ -879,6 +879,14 @@ static unsigned int atkbd_hp_zv6100_forced_release_keys[] = {
        0xae, 0xb0, -1U
 };
 
+/*
+ * Perform fixup for HP (Compaq) Presario R4000 R4100 R4200 that don't generate
+ * release for their volume buttons
+ */
+static unsigned int atkbd_hp_r4000_forced_release_keys[] = {
+       0xae, 0xb0, -1U
+};
+
 /*
  * Samsung NC10,NC20 with Fn+F? key release not working
  */
@@ -894,6 +902,13 @@ static unsigned int atkbd_amilo_pa1510_forced_release_keys[] = {
        0xb0, 0xae, -1U
 };
 
+/*
+ * Amilo Pi 3525 key release for Fn+Volume keys not working
+ */
+static unsigned int atkbd_amilo_pi3525_forced_release_keys[] = {
+       0x20, 0xa0, 0x2e, 0xae, 0x30, 0xb0, -1U
+};
+
 /*
  * Amilo Xi 3650 key release for light touch bar not working
  */
@@ -901,6 +916,13 @@ static unsigned int atkbd_amilo_xi3650_forced_release_keys[] = {
        0x67, 0xed, 0x90, 0xa2, 0x99, 0xa4, 0xae, 0xb0, -1U
 };
 
+/*
+ * Soltech TA12 system with broken key release on volume keys and mute key
+ */
+static unsigned int atkdb_soltech_ta12_forced_release_keys[] = {
+       0xa0, 0xae, 0xb0, -1U
+};
+
 /*
  * atkbd_set_keycode_table() initializes keyboard's keycode table
  * according to the selected scancode set
@@ -1522,6 +1544,33 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
                .callback = atkbd_setup_forced_release,
                .driver_data = atkbd_hp_zv6100_forced_release_keys,
        },
+       {
+               .ident = "HP Presario R4000",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4000"),
+               },
+               .callback = atkbd_setup_forced_release,
+               .driver_data = atkbd_hp_r4000_forced_release_keys,
+       },
+       {
+               .ident = "HP Presario R4100",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4100"),
+               },
+               .callback = atkbd_setup_forced_release,
+               .driver_data = atkbd_hp_r4000_forced_release_keys,
+       },
+       {
+               .ident = "HP Presario R4200",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4200"),
+               },
+               .callback = atkbd_setup_forced_release,
+               .driver_data = atkbd_hp_r4000_forced_release_keys,
+       },
        {
                .ident = "Inventec Symphony",
                .matches = {
@@ -1567,6 +1616,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
                .callback = atkbd_setup_forced_release,
                .driver_data = atkbd_amilo_pa1510_forced_release_keys,
        },
+       {
+               .ident = "Fujitsu Amilo Pi 3525",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 3525"),
+               },
+               .callback = atkbd_setup_forced_release,
+               .driver_data = atkbd_amilo_pi3525_forced_release_keys,
+       },
        {
                .ident = "Fujitsu Amilo Xi 3650",
                .matches = {
@@ -1576,6 +1634,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
                .callback = atkbd_setup_forced_release,
                .driver_data = atkbd_amilo_xi3650_forced_release_keys,
        },
+       {
+               .ident = "Soltech Corporation TA12",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Soltech Corporation"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "TA12"),
+               },
+               .callback = atkbd_setup_forced_release,
+               .driver_data = atkdb_soltech_ta12_forced_release_keys,
+       },
        { }
 };
 
index 2157cd7de00ced20c2d253bce59f6a5f37401841..efed0c9e242ed1880f618aa73c67ae0a1eab470b 100644 (file)
@@ -29,7 +29,8 @@
 struct gpio_button_data {
        struct gpio_keys_button *button;
        struct input_dev *input;
-       struct delayed_work work;
+       struct timer_list timer;
+       struct work_struct work;
 };
 
 struct gpio_keys_drvdata {
@@ -40,7 +41,7 @@ struct gpio_keys_drvdata {
 static void gpio_keys_report_event(struct work_struct *work)
 {
        struct gpio_button_data *bdata =
-               container_of(work, struct gpio_button_data, work.work);
+               container_of(work, struct gpio_button_data, work);
        struct gpio_keys_button *button = bdata->button;
        struct input_dev *input = bdata->input;
        unsigned int type = button->type ?: EV_KEY;
@@ -50,17 +51,25 @@ static void gpio_keys_report_event(struct work_struct *work)
        input_sync(input);
 }
 
+static void gpio_keys_timer(unsigned long _data)
+{
+       struct gpio_button_data *data = (struct gpio_button_data *)_data;
+
+       schedule_work(&data->work);
+}
+
 static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
 {
        struct gpio_button_data *bdata = dev_id;
        struct gpio_keys_button *button = bdata->button;
-       unsigned long delay;
 
        BUG_ON(irq != gpio_to_irq(button->gpio));
 
-       delay = button->debounce_interval ?
-                       msecs_to_jiffies(button->debounce_interval) : 0;
-       schedule_delayed_work(&bdata->work, delay);
+       if (button->debounce_interval)
+               mod_timer(&bdata->timer,
+                       jiffies + msecs_to_jiffies(button->debounce_interval));
+       else
+               schedule_work(&bdata->work);
 
        return IRQ_HANDLED;
 }
@@ -107,7 +116,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
 
                bdata->input = input;
                bdata->button = button;
-               INIT_DELAYED_WORK(&bdata->work, gpio_keys_report_event);
+               setup_timer(&bdata->timer,
+                           gpio_keys_timer, (unsigned long)bdata);
+               INIT_WORK(&bdata->work, gpio_keys_report_event);
 
                error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
                if (error < 0) {
@@ -166,7 +177,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
  fail2:
        while (--i >= 0) {
                free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
-               cancel_delayed_work_sync(&ddata->data[i].work);
+               if (pdata->buttons[i].debounce_interval)
+                       del_timer_sync(&ddata->data[i].timer);
+               cancel_work_sync(&ddata->data[i].work);
                gpio_free(pdata->buttons[i].gpio);
        }
 
@@ -190,7 +203,9 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
        for (i = 0; i < pdata->nbuttons; i++) {
                int irq = gpio_to_irq(pdata->buttons[i].gpio);
                free_irq(irq, &ddata->data[i]);
-               cancel_delayed_work_sync(&ddata->data[i].work);
+               if (pdata->buttons[i].debounce_interval)
+                       del_timer_sync(&ddata->data[i].timer);
+               cancel_work_sync(&ddata->data[i].work);
                gpio_free(pdata->buttons[i].gpio);
        }
 
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
new file mode 100644 (file)
index 0000000..541b981
--- /dev/null
@@ -0,0 +1,453 @@
+/*
+ *  GPIO driven matrix keyboard driver
+ *
+ *  Copyright (c) 2008 Marek Vasut <marek.vasut@gmail.com>
+ *
+ *  Based on corgikbd.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/types.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/input/matrix_keypad.h>
+
+struct matrix_keypad {
+       const struct matrix_keypad_platform_data *pdata;
+       struct input_dev *input_dev;
+       unsigned short *keycodes;
+       unsigned int row_shift;
+
+       uint32_t last_key_state[MATRIX_MAX_COLS];
+       struct delayed_work work;
+       bool scan_pending;
+       bool stopped;
+       spinlock_t lock;
+};
+
+/*
+ * NOTE: normally the GPIO has to be put into HiZ when de-activated to cause
+ * minmal side effect when scanning other columns, here it is configured to
+ * be input, and it should work on most platforms.
+ */
+static void __activate_col(const struct matrix_keypad_platform_data *pdata,
+                          int col, bool on)
+{
+       bool level_on = !pdata->active_low;
+
+       if (on) {
+               gpio_direction_output(pdata->col_gpios[col], level_on);
+       } else {
+               gpio_set_value_cansleep(pdata->col_gpios[col], !level_on);
+               gpio_direction_input(pdata->col_gpios[col]);
+       }
+}
+
+static void activate_col(const struct matrix_keypad_platform_data *pdata,
+                        int col, bool on)
+{
+       __activate_col(pdata, col, on);
+
+       if (on && pdata->col_scan_delay_us)
+               udelay(pdata->col_scan_delay_us);
+}
+
+static void activate_all_cols(const struct matrix_keypad_platform_data *pdata,
+                             bool on)
+{
+       int col;
+
+       for (col = 0; col < pdata->num_col_gpios; col++)
+               __activate_col(pdata, col, on);
+}
+
+static bool row_asserted(const struct matrix_keypad_platform_data *pdata,
+                        int row)
+{
+       return gpio_get_value_cansleep(pdata->row_gpios[row]) ?
+                       !pdata->active_low : pdata->active_low;
+}
+
+static void enable_row_irqs(struct matrix_keypad *keypad)
+{
+       const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+       int i;
+
+       for (i = 0; i < pdata->num_row_gpios; i++)
+               enable_irq(gpio_to_irq(pdata->row_gpios[i]));
+}
+
+static void disable_row_irqs(struct matrix_keypad *keypad)
+{
+       const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+       int i;
+
+       for (i = 0; i < pdata->num_row_gpios; i++)
+               disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
+}
+
+/*
+ * This gets the keys from keyboard and reports it to input subsystem
+ */
+static void matrix_keypad_scan(struct work_struct *work)
+{
+       struct matrix_keypad *keypad =
+               container_of(work, struct matrix_keypad, work.work);
+       struct input_dev *input_dev = keypad->input_dev;
+       const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+       uint32_t new_state[MATRIX_MAX_COLS];
+       int row, col, code;
+
+       /* de-activate all columns for scanning */
+       activate_all_cols(pdata, false);
+
+       memset(new_state, 0, sizeof(new_state));
+
+       /* assert each column and read the row status out */
+       for (col = 0; col < pdata->num_col_gpios; col++) {
+
+               activate_col(pdata, col, true);
+
+               for (row = 0; row < pdata->num_row_gpios; row++)
+                       new_state[col] |=
+                               row_asserted(pdata, row) ? (1 << row) : 0;
+
+               activate_col(pdata, col, false);
+       }
+
+       for (col = 0; col < pdata->num_col_gpios; col++) {
+               uint32_t bits_changed;
+
+               bits_changed = keypad->last_key_state[col] ^ new_state[col];
+               if (bits_changed == 0)
+                       continue;
+
+               for (row = 0; row < pdata->num_row_gpios; row++) {
+                       if ((bits_changed & (1 << row)) == 0)
+                               continue;
+
+                       code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
+                       input_event(input_dev, EV_MSC, MSC_SCAN, code);
+                       input_report_key(input_dev,
+                                        keypad->keycodes[code],
+                                        new_state[col] & (1 << row));
+               }
+       }
+       input_sync(input_dev);
+
+       memcpy(keypad->last_key_state, new_state, sizeof(new_state));
+
+       activate_all_cols(pdata, true);
+
+       /* Enable IRQs again */
+       spin_lock_irq(&keypad->lock);
+       keypad->scan_pending = false;
+       enable_row_irqs(keypad);
+       spin_unlock_irq(&keypad->lock);
+}
+
+static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
+{
+       struct matrix_keypad *keypad = id;
+       unsigned long flags;
+
+       spin_lock_irqsave(&keypad->lock, flags);
+
+       /*
+        * See if another IRQ beaten us to it and scheduled the
+        * scan already. In that case we should not try to
+        * disable IRQs again.
+        */
+       if (unlikely(keypad->scan_pending || keypad->stopped))
+               goto out;
+
+       disable_row_irqs(keypad);
+       keypad->scan_pending = true;
+       schedule_delayed_work(&keypad->work,
+               msecs_to_jiffies(keypad->pdata->debounce_ms));
+
+out:
+       spin_unlock_irqrestore(&keypad->lock, flags);
+       return IRQ_HANDLED;
+}
+
+static int matrix_keypad_start(struct input_dev *dev)
+{
+       struct matrix_keypad *keypad = input_get_drvdata(dev);
+
+       keypad->stopped = false;
+       mb();
+
+       /*
+        * Schedule an immediate key scan to capture current key state;
+        * columns will be activated and IRQs be enabled after the scan.
+        */
+       schedule_delayed_work(&keypad->work, 0);
+
+       return 0;
+}
+
+static void matrix_keypad_stop(struct input_dev *dev)
+{
+       struct matrix_keypad *keypad = input_get_drvdata(dev);
+
+       keypad->stopped = true;
+       mb();
+       flush_work(&keypad->work.work);
+       /*
+        * matrix_keypad_scan() will leave IRQs enabled;
+        * we should disable them now.
+        */
+       disable_row_irqs(keypad);
+}
+
+#ifdef CONFIG_PM
+static int matrix_keypad_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct matrix_keypad *keypad = platform_get_drvdata(pdev);
+       const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+       int i;
+
+       matrix_keypad_stop(keypad->input_dev);
+
+       if (device_may_wakeup(&pdev->dev))
+               for (i = 0; i < pdata->num_row_gpios; i++)
+                       enable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
+
+       return 0;
+}
+
+static int matrix_keypad_resume(struct platform_device *pdev)
+{
+       struct matrix_keypad *keypad = platform_get_drvdata(pdev);
+       const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+       int i;
+
+       if (device_may_wakeup(&pdev->dev))
+               for (i = 0; i < pdata->num_row_gpios; i++)
+                       disable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
+
+       matrix_keypad_start(keypad->input_dev);
+
+       return 0;
+}
+#else
+#define matrix_keypad_suspend  NULL
+#define matrix_keypad_resume   NULL
+#endif
+
+static int __devinit init_matrix_gpio(struct platform_device *pdev,
+                                       struct matrix_keypad *keypad)
+{
+       const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+       int i, err = -EINVAL;
+
+       /* initialized strobe lines as outputs, activated */
+       for (i = 0; i < pdata->num_col_gpios; i++) {
+               err = gpio_request(pdata->col_gpios[i], "matrix_kbd_col");
+               if (err) {
+                       dev_err(&pdev->dev,
+                               "failed to request GPIO%d for COL%d\n",
+                               pdata->col_gpios[i], i);
+                       goto err_free_cols;
+               }
+
+               gpio_direction_output(pdata->col_gpios[i], !pdata->active_low);
+       }
+
+       for (i = 0; i < pdata->num_row_gpios; i++) {
+               err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row");
+               if (err) {
+                       dev_err(&pdev->dev,
+                               "failed to request GPIO%d for ROW%d\n",
+                               pdata->row_gpios[i], i);
+                       goto err_free_rows;
+               }
+
+               gpio_direction_input(pdata->row_gpios[i]);
+       }
+
+       for (i = 0; i < pdata->num_row_gpios; i++) {
+               err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
+                               matrix_keypad_interrupt,
+                               IRQF_DISABLED |
+                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                               "matrix-keypad", keypad);
+               if (err) {
+                       dev_err(&pdev->dev,
+                               "Unable to acquire interrupt for GPIO line %i\n",
+                               pdata->row_gpios[i]);
+                       goto err_free_irqs;
+               }
+       }
+
+       /* initialized as disabled - enabled by input->open */
+       disable_row_irqs(keypad);
+       return 0;
+
+err_free_irqs:
+       while (--i >= 0)
+               free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
+       i = pdata->num_row_gpios;
+err_free_rows:
+       while (--i >= 0)
+               gpio_free(pdata->row_gpios[i]);
+       i = pdata->num_col_gpios;
+err_free_cols:
+       while (--i >= 0)
+               gpio_free(pdata->col_gpios[i]);
+
+       return err;
+}
+
+static int __devinit matrix_keypad_probe(struct platform_device *pdev)
+{
+       const struct matrix_keypad_platform_data *pdata;
+       const struct matrix_keymap_data *keymap_data;
+       struct matrix_keypad *keypad;
+       struct input_dev *input_dev;
+       unsigned short *keycodes;
+       unsigned int row_shift;
+       int i;
+       int err;
+
+       pdata = pdev->dev.platform_data;
+       if (!pdata) {
+               dev_err(&pdev->dev, "no platform data defined\n");
+               return -EINVAL;
+       }
+
+       keymap_data = pdata->keymap_data;
+       if (!keymap_data) {
+               dev_err(&pdev->dev, "no keymap data defined\n");
+               return -EINVAL;
+       }
+
+       row_shift = get_count_order(pdata->num_col_gpios);
+
+       keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
+       keycodes = kzalloc((pdata->num_row_gpios << row_shift) *
+                               sizeof(*keycodes),
+                          GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!keypad || !keycodes || !input_dev) {
+               err = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       keypad->input_dev = input_dev;
+       keypad->pdata = pdata;
+       keypad->keycodes = keycodes;
+       keypad->row_shift = row_shift;
+       keypad->stopped = true;
+       INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
+       spin_lock_init(&keypad->lock);
+
+       input_dev->name         = pdev->name;
+       input_dev->id.bustype   = BUS_HOST;
+       input_dev->dev.parent   = &pdev->dev;
+       input_dev->evbit[0]     = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+       input_dev->open         = matrix_keypad_start;
+       input_dev->close        = matrix_keypad_stop;
+
+       input_dev->keycode      = keycodes;
+       input_dev->keycodesize  = sizeof(*keycodes);
+       input_dev->keycodemax   = pdata->num_row_gpios << keypad->row_shift;
+
+       for (i = 0; i < keymap_data->keymap_size; i++) {
+               unsigned int key = keymap_data->keymap[i];
+               unsigned int row = KEY_ROW(key);
+               unsigned int col = KEY_COL(key);
+               unsigned short code = KEY_VAL(key);
+
+               keycodes[MATRIX_SCAN_CODE(row, col, row_shift)] = code;
+               __set_bit(code, input_dev->keybit);
+       }
+       __clear_bit(KEY_RESERVED, input_dev->keybit);
+
+       input_set_capability(input_dev, EV_MSC, MSC_SCAN);
+       input_set_drvdata(input_dev, keypad);
+
+       err = init_matrix_gpio(pdev, keypad);
+       if (err)
+               goto err_free_mem;
+
+       err = input_register_device(keypad->input_dev);
+       if (err)
+               goto err_free_mem;
+
+       device_init_wakeup(&pdev->dev, pdata->wakeup);
+       platform_set_drvdata(pdev, keypad);
+
+       return 0;
+
+err_free_mem:
+       input_free_device(input_dev);
+       kfree(keycodes);
+       kfree(keypad);
+       return err;
+}
+
+static int __devexit matrix_keypad_remove(struct platform_device *pdev)
+{
+       struct matrix_keypad *keypad = platform_get_drvdata(pdev);
+       const struct matrix_keypad_platform_data *pdata = keypad->pdata;
+       int i;
+
+       device_init_wakeup(&pdev->dev, 0);
+
+       for (i = 0; i < pdata->num_row_gpios; i++) {
+               free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
+               gpio_free(pdata->row_gpios[i]);
+       }
+
+       for (i = 0; i < pdata->num_col_gpios; i++)
+               gpio_free(pdata->col_gpios[i]);
+
+       input_unregister_device(keypad->input_dev);
+       platform_set_drvdata(pdev, NULL);
+       kfree(keypad->keycodes);
+       kfree(keypad);
+
+       return 0;
+}
+
+static struct platform_driver matrix_keypad_driver = {
+       .probe          = matrix_keypad_probe,
+       .remove         = __devexit_p(matrix_keypad_remove),
+       .suspend        = matrix_keypad_suspend,
+       .resume         = matrix_keypad_resume,
+       .driver         = {
+               .name   = "matrix-keypad",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init matrix_keypad_init(void)
+{
+       return platform_driver_register(&matrix_keypad_driver);
+}
+
+static void __exit matrix_keypad_exit(void)
+{
+       platform_driver_unregister(&matrix_keypad_driver);
+}
+
+module_init(matrix_keypad_init);
+module_exit(matrix_keypad_exit);
+
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:matrix-keypad");
index 2adf9cb265da69fd67b6d1b8bec3fa3841e95ec2..d114d3a9e1e94b7129870642943d7ac91a368cac 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Cobalt button interface driver.
  *
- *  Copyright (C) 2007-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -148,7 +148,7 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev)
        return 0;
 }
 
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
 MODULE_DESCRIPTION("Cobalt button interface driver");
 MODULE_LICENSE("GPL");
 /* work with hotplug and coldplug */
index 6d67af5387adcfdff514133ca9f1ce9d0bf39f8b..21cb755a54fb925deda36db17933a0991bb0969c 100644 (file)
@@ -114,7 +114,7 @@ static int __devexit pcspkr_remove(struct platform_device *dev)
        return 0;
 }
 
-static int pcspkr_suspend(struct platform_device *dev, pm_message_t state)
+static int pcspkr_suspend(struct device *dev)
 {
        pcspkr_event(NULL, EV_SND, SND_BELL, 0);
 
@@ -127,14 +127,18 @@ static void pcspkr_shutdown(struct platform_device *dev)
        pcspkr_event(NULL, EV_SND, SND_BELL, 0);
 }
 
+static struct dev_pm_ops pcspkr_pm_ops = {
+       .suspend = pcspkr_suspend,
+};
+
 static struct platform_driver pcspkr_platform_driver = {
        .driver         = {
                .name   = "pcspkr",
                .owner  = THIS_MODULE,
+               .pm     = &pcspkr_pm_ops,
        },
        .probe          = pcspkr_probe,
        .remove         = __devexit_p(pcspkr_remove),
-       .suspend        = pcspkr_suspend,
        .shutdown       = pcspkr_shutdown,
 };
 
index 7c8957dd22c03d42252e410af97e385c78b2c4b7..27ee976eb54cea4e561fd32665ccfa539d244b96 100644 (file)
@@ -611,6 +611,20 @@ static struct key_entry keymap_wistron_generic[] __initdata = {
        { KE_END, 0 }
 };
 
+static struct key_entry keymap_prestigio[] __initdata = {
+       { KE_KEY,  0x11, {KEY_PROG1} },
+       { KE_KEY,  0x12, {KEY_PROG2} },
+       { KE_WIFI,  0x30 },
+       { KE_KEY,  0x22, {KEY_REWIND} },
+       { KE_KEY,  0x23, {KEY_FORWARD} },
+       { KE_KEY,  0x24, {KEY_PLAYPAUSE} },
+       { KE_KEY,  0x25, {KEY_STOPCD} },
+       { KE_KEY,  0x31, {KEY_MAIL} },
+       { KE_KEY,  0x36, {KEY_WWW} },
+       { KE_END,  0 }
+};
+
+
 /*
  * If your machine is not here (which is currently rather likely), please send
  * a list of buttons and their key codes (reported when loading this module
@@ -644,6 +658,15 @@ static struct dmi_system_id dmi_ids[] __initdata = {
                },
                .driver_data = keymap_fs_amilo_pro_v2000
        },
+       {
+               .callback = dmi_matched,
+               .ident = "Maxdata Pro 7000 DX",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"),
+               },
+               .driver_data = keymap_fs_amilo_pro_v2000
+       },
        {
                .callback = dmi_matched,
                .ident = "Fujitsu N3510",
@@ -962,6 +985,8 @@ static int __init select_keymap(void)
        if (keymap_name != NULL) {
                if (strcmp (keymap_name, "1557/MS2141") == 0)
                        keymap = keymap_wistron_ms2141;
+               else if (strcmp (keymap_name, "prestigio") == 0)
+                       keymap = keymap_prestigio;
                else if (strcmp (keymap_name, "generic") == 0)
                        keymap = keymap_wistron_generic;
                else {
index 5e5eb88d8d1e04e48b5a0668300ecf56cbe6017d..7b6ce178f1b67d64c92e2e969d256bbe381a86e7 100644 (file)
@@ -46,7 +46,7 @@ static void gpio_mouse_scan(struct input_polled_dev *dev)
        input_sync(input);
 }
 
-static int __init gpio_mouse_probe(struct platform_device *pdev)
+static int __devinit gpio_mouse_probe(struct platform_device *pdev)
 {
        struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data;
        struct input_polled_dev *input_poll;
@@ -170,10 +170,8 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev)
        return 0;
 }
 
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:gpio_mouse");
-
 static struct platform_driver gpio_mouse_device_driver = {
+       .probe          = gpio_mouse_probe,
        .remove         = __devexit_p(gpio_mouse_remove),
        .driver         = {
                .name   = "gpio_mouse",
@@ -183,8 +181,7 @@ static struct platform_driver gpio_mouse_device_driver = {
 
 static int __init gpio_mouse_init(void)
 {
-       return platform_driver_probe(&gpio_mouse_device_driver,
-                       gpio_mouse_probe);
+       return platform_driver_register(&gpio_mouse_device_driver);
 }
 module_init(gpio_mouse_init);
 
@@ -197,3 +194,5 @@ module_exit(gpio_mouse_exit);
 MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
 MODULE_DESCRIPTION("GPIO mouse driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */
+
index b587e2d576ac2983393b5a49791c183250ceb28d..820e51673b262eea190daba8a04f33c96989a54d 100644 (file)
@@ -296,7 +296,7 @@ static void hp_sdc_mlc_out(hil_mlc *mlc)
        priv->tseq[3] = 0;
        if (mlc->opacket & HIL_CTRL_APE) {
                priv->tseq[3] |= HP_SDC_LPC_APE_IPF;
-               down_trylock(&mlc->csem);
+               BUG_ON(down_trylock(&mlc->csem));
        }
  enqueue:
        hp_sdc_enqueue_transaction(&priv->trans);
index fb8a3cd3ffd0ab4685e8e68f5f14b07068266b94..ccbf23ece8e370cc2e59fa4fef47d8cfd9ed5a09 100644 (file)
@@ -77,6 +77,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
                        DMI_MATCH(DMI_BOARD_VERSION, "Rev E"),
                },
        },
+       {
+               .ident = "ASUS G1S",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_BOARD_NAME, "G1S"),
+                       DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+               },
+       },
        {
                /* AUX LOOP command does not raise AUX IRQ */
                .ident = "ASUS P65UP5",
@@ -374,6 +382,14 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"),
                },
        },
+       {
+               .ident = "Acer Aspire 5536",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
+               },
+       },
        { }
 };
 
@@ -392,6 +408,34 @@ static struct dmi_system_id __initdata i8042_dmi_reset_table[] = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."),
                },
        },
+       {
+               .ident = "Acer Aspire One 150",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),
+               },
+       },
+       {
+               .ident = "Advent 4211",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"),
+               },
+       },
+       {
+               .ident = "Medion Akoya Mini E1210",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "E1210"),
+               },
+       },
+       {
+               .ident = "Mivvy M310",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "N10"),
+               },
+       },
        { }
 };
 
index f919bf57293c9fad56d625aa1e497655eda5a04a..582245c497ebfe1e6ff5b8fbe513a31e483de35f 100644 (file)
@@ -934,10 +934,11 @@ static bool i8042_suspended;
 
 static int i8042_suspend(struct platform_device *dev, pm_message_t state)
 {
-       if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) {
+       if (!i8042_suspended && state.event == PM_EVENT_SUSPEND)
                i8042_controller_reset();
-               i8042_suspended = true;
-       }
+
+       i8042_suspended = state.event == PM_EVENT_SUSPEND ||
+                         state.event == PM_EVENT_FREEZE;
 
        return 0;
 }
index fb17573f8f2d90e88072714b0a8fc4b7eb142616..d66f4944f2a0efc0a18508d9c4707bf069567830 100644 (file)
@@ -935,10 +935,11 @@ static int serio_suspend(struct device *dev, pm_message_t state)
 {
        struct serio *serio = to_serio_port(dev);
 
-       if (!serio->suspended && state.event == PM_EVENT_SUSPEND) {
+       if (!serio->suspended && state.event == PM_EVENT_SUSPEND)
                serio_cleanup(serio);
-               serio->suspended = true;
-       }
+
+       serio->suspended = state.event == PM_EVENT_SUSPEND ||
+                          state.event == PM_EVENT_FREEZE;
 
        return 0;
 }
index a9d5031b855e5b3c529cbd5e8b8589cf46fcebab..ea30c983a33efdbd6469cbd2fbc07fe308ade8fe 100644 (file)
@@ -388,6 +388,32 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
        return result;
 }
 
+static int wacom_query_tablet_data(struct usb_interface *intf)
+{
+       unsigned char *rep_data;
+       int limit = 0;
+       int error;
+
+       rep_data = kmalloc(2, GFP_KERNEL);
+       if (!rep_data)
+               return -ENOMEM;
+
+       do {
+               rep_data[0] = 2;
+               rep_data[1] = 2;
+               error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
+                                       2, rep_data, 2);
+               if (error >= 0)
+                       error = usb_get_report(intf,
+                                               WAC_HID_FEATURE_REPORT, 2,
+                                               rep_data, 2);
+       } while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
+
+       kfree(rep_data);
+
+       return error < 0 ? error : 0;
+}
+
 static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
        struct usb_device *dev = interface_to_usbdev(intf);
@@ -398,7 +424,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
        struct wacom_features *features;
        struct input_dev *input_dev;
        int error = -ENOMEM;
-       char rep_data[2], limit = 0;
        struct hid_descriptor *hid_desc;
 
        wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
@@ -489,20 +514,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 
        /*
         * Ask the tablet to report tablet data if it is not a Tablet PC.
-        * Repeat until it succeeds
+        * Note that if query fails it is not a hard failure.
         */
-       if (wacom_wac->features->type != TABLETPC) {
-               do {
-                       rep_data[0] = 2;
-                       rep_data[1] = 2;
-                       error = usb_set_report(intf, WAC_HID_FEATURE_REPORT,
-                                               2, rep_data, 2);
-                       if (error >= 0)
-                               error = usb_get_report(intf,
-                                               WAC_HID_FEATURE_REPORT, 2,
-                                               rep_data, 2);
-               } while ((error < 0 || rep_data[1] != 2) && limit++ < 5);
-       }
+       if (wacom_wac->features->type != TABLETPC)
+               wacom_query_tablet_data(intf);
 
        usb_set_intfdata(intf, wacom);
        return 0;
index 38bf86384aeba4d7b5393f43179e2c4bf55864b9..c896d6a21b7ee6fa53eb8853ff6535a65ae194af 100644 (file)
@@ -384,6 +384,8 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
                        wacom_report_key(wcombo, BTN_STYLUS2, 0);
                        wacom_report_key(wcombo, BTN_TOUCH, 0);
                        wacom_report_abs(wcombo, ABS_WHEEL, 0);
+                       if (wacom->features->type >= INTUOS3S)
+                               wacom_report_abs(wcombo, ABS_Z, 0);
                }
                wacom_report_key(wcombo, wacom->tool[idx], 0);
                wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
@@ -836,6 +838,7 @@ static struct wacom_features wacom_features[] = {
        { "Wacom DTU710",        8,  34080, 27660,  511,  0, PL },
        { "Wacom DTF521",        8,   6282,  4762,  511,  0, PL },
        { "Wacom DTF720",        8,   6858,  5506,  511,  0, PL },
+       { "Wacom DTF720a",       8,   6858,  5506,  511,  0, PL },
        { "Wacom Cintiq Partner",8,  20480, 15360,  511,  0, PTU },
        { "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 31, INTUOS },
        { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 31, INTUOS },
@@ -897,8 +900,9 @@ static struct usb_device_id wacom_ids[] = {
        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) },
        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC2) },
        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
        { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
index 6954f55001080d29b337a37c9398b6c8f867ec1a..3a7a58222f836ed5c9aea5022a1196482c7ee355 100644 (file)
@@ -170,11 +170,11 @@ static void ucb1400_handle_pending_irq(struct ucb1400_ts *ucb)
        ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, isr);
        ucb1400_reg_write(ucb->ac97, UCB_IE_CLEAR, 0);
 
-       if (isr & UCB_IE_TSPX) {
+       if (isr & UCB_IE_TSPX)
                ucb1400_ts_irq_disable(ucb->ac97);
-               enable_irq(ucb->irq);
-       } else
-               printk(KERN_ERR "ucb1400: unexpected IE_STATUS = %#x\n", isr);
+       else
+               dev_dbg(&ucb->ts_idev->dev, "ucb1400: unexpected IE_STATUS = %#x\n", isr);
+       enable_irq(ucb->irq);
 }
 
 static int ucb1400_ts_thread(void *_ucb)
@@ -345,6 +345,7 @@ static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb)
 static int ucb1400_ts_probe(struct platform_device *dev)
 {
        int error, x_res, y_res;
+       u16 fcsr;
        struct ucb1400_ts *ucb = dev->dev.platform_data;
 
        ucb->ts_idev = input_allocate_device();
@@ -382,6 +383,14 @@ static int ucb1400_ts_probe(struct platform_device *dev)
        ucb->ts_idev->evbit[0]          = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
        ucb->ts_idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 
+       /*
+        * Enable ADC filter to prevent horrible jitter on Colibri.
+        * This also further reduces jitter on boards where ADCSYNC
+        * pin is connected.
+        */
+       fcsr = ucb1400_reg_read(ucb->ac97, UCB_FCSR);
+       ucb1400_reg_write(ucb->ac97, UCB_FCSR, fcsr | UCB_FCSR_AVE);
+
        ucb1400_adc_enable(ucb->ac97);
        x_res = ucb1400_ts_read_xres(ucb);
        y_res = ucb1400_ts_read_yres(ucb);
index ec5169604a6a93dd714efcb9648390dea5075eee..2d91049571a4ce20470acb86d7120bee326b911c 100644 (file)
@@ -294,32 +294,33 @@ struct reply_t gigaset_tab_cid[] =
        {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,      606,606, -1,                607, 5, {0}, "+VLS=17\r"},
        {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
+       /* optional dialing responses */
+       {EV_BC_OPEN,  650,650, -1,                651,-1},
+       {RSP_ZVLS,    608,651, 17,                 -1,-1, {ACT_DEBUG}},
+       {RSP_ZCTP,    609,651, -1,                 -1,-1, {ACT_DEBUG}},
+       {RSP_ZCPN,    609,651, -1,                 -1,-1, {ACT_DEBUG}},
+       {RSP_ZSAU,    650,651,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}},
+
+       /* connect */
+       {RSP_ZSAU,    650,650,ZSAU_ACTIVE,        800,-1, {ACT_CONNECT}},
+       {RSP_ZSAU,    651,651,ZSAU_ACTIVE,        800,-1, {ACT_CONNECT,
+                                                          ACT_NOTIFY_BC_UP}},
+       {RSP_ZSAU,    750,750,ZSAU_ACTIVE,        800,-1, {ACT_CONNECT}},
+       {RSP_ZSAU,    751,751,ZSAU_ACTIVE,        800,-1, {ACT_CONNECT,
+                                                          ACT_NOTIFY_BC_UP}},
+       {EV_BC_OPEN,  800,800, -1,                800,-1, {ACT_NOTIFY_BC_UP}},
 
        /* 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,    650,651,ZSAU_DISCONNECT_IND,  0, 0, {ACT_REMOTEREJECT}},
+       {RSP_ZSAU,    750,751,ZSAU_DISCONNECT_IND,  0, 0, {ACT_REMOTEHUP}},
        {RSP_ZSAU,    800,800,ZSAU_DISCONNECT_IND,  0, 0, {ACT_REMOTEHUP}},
 
        /* hangup */
@@ -358,7 +359,8 @@ struct reply_t gigaset_tab_cid[] =
        {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}},
+       {EV_BC_OPEN,  750,750, -1,                751,-1},
+       {EV_TIMEOUT,  750,751, -1,                  0, 0, {ACT_CONNTIMEOUT}},
 
        /* B channel closed (general case) */
        {EV_BC_CLOSED, -1, -1, -1,                 -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME
@@ -876,12 +878,6 @@ static void bchannel_down(struct bc_state *bcs)
 
 static void bchannel_up(struct bc_state *bcs)
 {
-       if (!(bcs->chstate & CHS_D_UP)) {
-               dev_notice(bcs->cs->dev, "%s: D channel not up\n", __func__);
-               bcs->chstate |= CHS_D_UP;
-               gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
-       }
-
        if (bcs->chstate & CHS_B_UP) {
                dev_notice(bcs->cs->dev, "%s: B channel already up\n",
                           __func__);
index 1ebfcab746623d8fd09acf35d6b753afc0963c12..8ff7e35c70696de765b8ab3dc2e4b61a02ee3356 100644 (file)
@@ -408,6 +408,8 @@ static int if_write_room(struct tty_struct *tty)
        return retval;
 }
 
+/* FIXME: This function does not have error returns */
+
 static int if_chars_in_buffer(struct tty_struct *tty)
 {
        struct cardstate *cs;
index db3a1e4cd4893e62af25041d478318035c2bad96..bed38fcc432b62b8a88335a697dfa93295110a2e 100644 (file)
@@ -174,12 +174,6 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
                pr_err("invalid size %d\n", size);
                return -EINVAL;
        }
-       src = iwb->read;
-       if (unlikely(limit >= BAS_OUTBUFSIZE + BAS_OUTBUFPAD ||
-                    (read < src && limit >= src))) {
-               pr_err("isoc write buffer frame reservation violated\n");
-               return -EFAULT;
-       }
 #endif
 
        if (read < write) {
index 8df889b0c1a97b1a6c3546545840bc3279755486..9de54202c90c84828c86cefeeb3408b090ea0bdc 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/kernel_stat.h>
 #include <linux/usb.h>
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
 #include <linux/sched.h>
 #include <linux/moduleparam.h>
 #include "hisax.h"
index b4d4522e50718347f02b88345cc93d50608d9252..2881a66c1aa97c2e78e0c9f3029bbbd44ef0046a 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/isdn.h>
 #include <linux/delay.h>
+#include <linux/smp_lock.h>
 #include "isdn_common.h"
 #include "isdn_tty.h"
 #ifdef CONFIG_ISDN_AUDIO
index 990e6a7e6674dce0c866083fc576ce8acb1d9e52..7e5f30dbc0a0043e8b96ff8b230042e0b76d969c 100644 (file)
@@ -731,10 +731,10 @@ l1oip_socket_thread(void *data)
        while (!signal_pending(current)) {
                struct kvec iov = {
                        .iov_base = recvbuf,
-                       .iov_len = sizeof(recvbuf),
+                       .iov_len = recvbuf_size,
                };
                recvlen = kernel_recvmsg(socket, &msg, &iov, 1,
-                                        sizeof(recvbuf), 0);
+                                        recvbuf_size, 0);
                if (recvlen > 0) {
                        l1oip_socket_parse(hc, &sin_rx, recvbuf, recvlen);
                } else {
@@ -1480,7 +1480,7 @@ l1oip_init(void)
                return -ENOMEM;
 
        l1oip_cnt = 0;
-       while (type[l1oip_cnt] && l1oip_cnt < MAX_CARDS) {
+       while (l1oip_cnt < MAX_CARDS && type[l1oip_cnt]) {
                switch (type[l1oip_cnt] & 0xff) {
                case 1:
                        pri = 0;
index e2f45019ebf0be504bdcd68538cd47f51109c588..3e1532a180ff172df2c92f2c19e8bb3ecdc9f1cd 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/mISDNif.h>
 #include <linux/kthread.h>
+#include <linux/smp_lock.h>
 #include "core.h"
 
 static u_int   *debug;
index 9b60b6b684d9cd7c5a62c843d827e6071491a51f..7c8e7122aaa906785694bca49ff730c9b5712c83 100644 (file)
@@ -75,6 +75,7 @@ config LEDS_ALIX2
        depends on LEDS_CLASS && X86 && EXPERIMENTAL
        help
          This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs.
+         You have to set leds-alix2.force=1 for boards with Award BIOS.
 
 config LEDS_H1940
        tristate "LED Support for iPAQ H1940 device"
@@ -145,15 +146,16 @@ config LEDS_GPIO_OF
          of_platform devices.  For instance, LEDs which are listed in a "dts"
          file.
 
-config LEDS_LP5521
-       tristate "LED Support for the LP5521 LEDs"
+config LEDS_LP3944
+       tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip"
        depends on LEDS_CLASS && I2C
        help
-         If you say 'Y' here you get support for the National Semiconductor
-         LP5521 LED driver used in n8x0 boards.
+    This option enables support for LEDs connected to the National
+    Semiconductor LP3944 Lighting Management Unit (LMU) also known as
+    Fun Light Chip.
 
-         This driver can be built as a module by choosing 'M'. The module
-         will be called leds-lp5521.
+         To compile this driver as a module, choose M here: the
+         module will be called leds-lp3944.
 
 config LEDS_CLEVO_MAIL
        tristate "Mail LED on Clevo notebook"
index 2d41c4dcf92ff9a8db515aac17aee9dc9482db96..e8cdcf77a4c358f7cf1d4ba839f5db6a84df858e 100644 (file)
@@ -20,6 +20,7 @@ obj-$(CONFIG_LEDS_COBALT_RAQ)         += leds-cobalt-raq.o
 obj-$(CONFIG_LEDS_SUNFIRE)             += leds-sunfire.o
 obj-$(CONFIG_LEDS_PCA9532)             += leds-pca9532.o
 obj-$(CONFIG_LEDS_GPIO)                        += leds-gpio.o
+obj-$(CONFIG_LEDS_LP3944)              += leds-lp3944.o
 obj-$(CONFIG_LEDS_CLEVO_MAIL)          += leds-clevo-mail.o
 obj-$(CONFIG_LEDS_HP6XX)               += leds-hp6xx.o
 obj-$(CONFIG_LEDS_FSG)                 += leds-fsg.o
index ddbd7730dfc84dfdcb4e9c776f81fdeb8b5b877e..731d4eef342590dca6566f229d60d7f8add6b872 100644 (file)
@@ -14,7 +14,7 @@
 
 static int force = 0;
 module_param(force, bool, 0444);
-MODULE_PARM_DESC(force, "Assume system has ALIX.2 style LEDs");
+MODULE_PARM_DESC(force, "Assume system has ALIX.2/ALIX.3 style LEDs");
 
 struct alix_led {
        struct led_classdev cdev;
@@ -155,6 +155,11 @@ static int __init alix_led_init(void)
                goto out;
        }
 
+       /* enable output on GPIO for LED 1,2,3 */
+       outl(1 << 6, 0x6104);
+       outl(1 << 9, 0x6184);
+       outl(1 << 11, 0x6184);
+
        pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
        if (!IS_ERR(pdev)) {
                ret = platform_driver_probe(&alix_led_driver, alix_led_probe);
index 4149ecb3a9b2fda0a22cb93c2575ea16096c4bcd..779d7f262c04c39f1355e0dd2a190ca02fb067e3 100644 (file)
@@ -97,6 +97,10 @@ struct bd2802_led {
        enum led_ids                    led_id;
        enum led_colors                 color;
        enum led_bits                   state;
+
+       /* General attributes of RGB LEDs */
+       int                             wave_pattern;
+       int                             rgb_current;
 };
 
 
@@ -254,7 +258,7 @@ static void bd2802_set_on(struct bd2802_led *led, enum led_ids id,
                bd2802_reset_cancel(led);
 
        reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP);
-       bd2802_write_byte(led->client, reg, BD2802_CURRENT_032);
+       bd2802_write_byte(led->client, reg, led->rgb_current);
        reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP);
        bd2802_write_byte(led->client, reg, BD2802_CURRENT_000);
        reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN);
@@ -275,9 +279,9 @@ static void bd2802_set_blink(struct bd2802_led *led, enum led_ids id,
        reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP);
        bd2802_write_byte(led->client, reg, BD2802_CURRENT_000);
        reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP);
-       bd2802_write_byte(led->client, reg, BD2802_CURRENT_032);
+       bd2802_write_byte(led->client, reg, led->rgb_current);
        reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN);
-       bd2802_write_byte(led->client, reg, BD2802_PATTERN_HALF);
+       bd2802_write_byte(led->client, reg, led->wave_pattern);
 
        bd2802_enable(led, id);
        bd2802_update_state(led, id, color, BD2802_BLINK);
@@ -406,7 +410,7 @@ static void bd2802_enable_adv_conf(struct bd2802_led *led)
                ret = device_create_file(&led->client->dev,
                                                bd2802_addr_attributes[i]);
                if (ret) {
-                       dev_err(&led->client->dev, "failed to sysfs file %s\n",
+                       dev_err(&led->client->dev, "failed: sysfs file %s\n",
                                        bd2802_addr_attributes[i]->attr.name);
                        goto failed_remove_files;
                }
@@ -483,6 +487,52 @@ static struct device_attribute bd2802_adv_conf_attr = {
        .store = bd2802_store_adv_conf,
 };
 
+#define BD2802_CONTROL_ATTR(attr_name, name_str)                       \
+static ssize_t bd2802_show_##attr_name(struct device *dev,             \
+       struct device_attribute *attr, char *buf)                       \
+{                                                                      \
+       struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\
+       ssize_t ret;                                                    \
+       down_read(&led->rwsem);                                         \
+       ret = sprintf(buf, "0x%02x\n", led->attr_name);                 \
+       up_read(&led->rwsem);                                           \
+       return ret;                                                     \
+}                                                                      \
+static ssize_t bd2802_store_##attr_name(struct device *dev,            \
+       struct device_attribute *attr, const char *buf, size_t count)   \
+{                                                                      \
+       struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\
+       unsigned long val;                                              \
+       int ret;                                                        \
+       if (!count)                                                     \
+               return -EINVAL;                                         \
+       ret = strict_strtoul(buf, 16, &val);                            \
+       if (ret)                                                        \
+               return ret;                                             \
+       down_write(&led->rwsem);                                        \
+       led->attr_name = val;                                           \
+       up_write(&led->rwsem);                                          \
+       return count;                                                   \
+}                                                                      \
+static struct device_attribute bd2802_##attr_name##_attr = {           \
+       .attr = {                                                       \
+               .name = name_str,                                       \
+               .mode = 0644,                                           \
+               .owner = THIS_MODULE                                    \
+       },                                                              \
+       .show = bd2802_show_##attr_name,                                \
+       .store = bd2802_store_##attr_name,                              \
+};
+
+BD2802_CONTROL_ATTR(wave_pattern, "wave_pattern");
+BD2802_CONTROL_ATTR(rgb_current, "rgb_current");
+
+static struct device_attribute *bd2802_attributes[] = {
+       &bd2802_adv_conf_attr,
+       &bd2802_wave_pattern_attr,
+       &bd2802_rgb_current_attr,
+};
+
 static void bd2802_led_work(struct work_struct *work)
 {
        struct bd2802_led *led = container_of(work, struct bd2802_led, work);
@@ -538,7 +588,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led)
        led->cdev_led1r.brightness = LED_OFF;
        led->cdev_led1r.brightness_set = bd2802_set_led1r_brightness;
        led->cdev_led1r.blink_set = bd2802_set_led1r_blink;
-       led->cdev_led1r.flags |= LED_CORE_SUSPENDRESUME;
 
        ret = led_classdev_register(&led->client->dev, &led->cdev_led1r);
        if (ret < 0) {
@@ -551,7 +600,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led)
        led->cdev_led1g.brightness = LED_OFF;
        led->cdev_led1g.brightness_set = bd2802_set_led1g_brightness;
        led->cdev_led1g.blink_set = bd2802_set_led1g_blink;
-       led->cdev_led1g.flags |= LED_CORE_SUSPENDRESUME;
 
        ret = led_classdev_register(&led->client->dev, &led->cdev_led1g);
        if (ret < 0) {
@@ -564,7 +612,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led)
        led->cdev_led1b.brightness = LED_OFF;
        led->cdev_led1b.brightness_set = bd2802_set_led1b_brightness;
        led->cdev_led1b.blink_set = bd2802_set_led1b_blink;
-       led->cdev_led1b.flags |= LED_CORE_SUSPENDRESUME;
 
        ret = led_classdev_register(&led->client->dev, &led->cdev_led1b);
        if (ret < 0) {
@@ -577,7 +624,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led)
        led->cdev_led2r.brightness = LED_OFF;
        led->cdev_led2r.brightness_set = bd2802_set_led2r_brightness;
        led->cdev_led2r.blink_set = bd2802_set_led2r_blink;
-       led->cdev_led2r.flags |= LED_CORE_SUSPENDRESUME;
 
        ret = led_classdev_register(&led->client->dev, &led->cdev_led2r);
        if (ret < 0) {
@@ -590,7 +636,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led)
        led->cdev_led2g.brightness = LED_OFF;
        led->cdev_led2g.brightness_set = bd2802_set_led2g_brightness;
        led->cdev_led2g.blink_set = bd2802_set_led2g_blink;
-       led->cdev_led2g.flags |= LED_CORE_SUSPENDRESUME;
 
        ret = led_classdev_register(&led->client->dev, &led->cdev_led2g);
        if (ret < 0) {
@@ -640,7 +685,7 @@ static int __devinit bd2802_probe(struct i2c_client *client,
 {
        struct bd2802_led *led;
        struct bd2802_led_platform_data *pdata;
-       int ret;
+       int ret, i;
 
        led = kzalloc(sizeof(struct bd2802_led), GFP_KERNEL);
        if (!led) {
@@ -670,13 +715,20 @@ static int __devinit bd2802_probe(struct i2c_client *client,
        /* To save the power, reset BD2802 after detecting */
        gpio_set_value(led->pdata->reset_gpio, 0);
 
+       /* Default attributes */
+       led->wave_pattern = BD2802_PATTERN_HALF;
+       led->rgb_current = BD2802_CURRENT_032;
+
        init_rwsem(&led->rwsem);
 
-       ret = device_create_file(&client->dev, &bd2802_adv_conf_attr);
-       if (ret) {
-               dev_err(&client->dev, "failed to create sysfs file %s\n",
-                                       bd2802_adv_conf_attr.attr.name);
-               goto failed_free;
+       for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) {
+               ret = device_create_file(&led->client->dev,
+                                               bd2802_attributes[i]);
+               if (ret) {
+                       dev_err(&led->client->dev, "failed: sysfs file %s\n",
+                                       bd2802_attributes[i]->attr.name);
+                       goto failed_unregister_dev_file;
+               }
        }
 
        ret = bd2802_register_led_classdev(led);
@@ -686,7 +738,8 @@ static int __devinit bd2802_probe(struct i2c_client *client,
        return 0;
 
 failed_unregister_dev_file:
-       device_remove_file(&client->dev, &bd2802_adv_conf_attr);
+       for (i--; i >= 0; i--)
+               device_remove_file(&led->client->dev, bd2802_attributes[i]);
 failed_free:
        i2c_set_clientdata(client, NULL);
        kfree(led);
@@ -697,12 +750,14 @@ failed_free:
 static int __exit bd2802_remove(struct i2c_client *client)
 {
        struct bd2802_led *led = i2c_get_clientdata(client);
+       int i;
 
-       bd2802_unregister_led_classdev(led);
        gpio_set_value(led->pdata->reset_gpio, 0);
+       bd2802_unregister_led_classdev(led);
        if (led->adf_on)
                bd2802_disable_adv_conf(led);
-       device_remove_file(&client->dev, &bd2802_adv_conf_attr);
+       for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++)
+               device_remove_file(&led->client->dev, bd2802_attributes[i]);
        i2c_set_clientdata(client, NULL);
        kfree(led);
 
@@ -723,8 +778,7 @@ static int bd2802_resume(struct i2c_client *client)
        struct bd2802_led *led = i2c_get_clientdata(client);
 
        if (!bd2802_is_all_off(led) || led->adf_on) {
-               gpio_set_value(led->pdata->reset_gpio, 1);
-               udelay(100);
+               bd2802_reset_cancel(led);
                bd2802_restore_state(led);
        }
 
@@ -762,4 +816,4 @@ module_exit(bd2802_exit);
 
 MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>");
 MODULE_DESCRIPTION("BD2802 LED driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index ff0e8c3fbf9b79d61365d456d1d78f314390402e..5f1ce810815f51cb150c7f4c2b203505d10447a5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  LEDs driver for the Cobalt Raq series.
  *
- *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2007  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index d2109054de858b95402ee7d0489704561d6750a2..6b06638eb5b42f40ca9c858a4e5d1626c07a0688 100644 (file)
@@ -76,7 +76,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template,
        struct gpio_led_data *led_dat, struct device *parent,
        int (*blink_set)(unsigned, unsigned long *, unsigned long *))
 {
-       int ret;
+       int ret, state;
 
        /* skip leds that aren't available */
        if (!gpio_is_valid(template->gpio)) {
@@ -99,11 +99,15 @@ static int __devinit create_gpio_led(const struct gpio_led *template,
                led_dat->cdev.blink_set = gpio_blink_set;
        }
        led_dat->cdev.brightness_set = gpio_led_set;
-       led_dat->cdev.brightness = LED_OFF;
+       if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP)
+               state = !!gpio_get_value(led_dat->gpio) ^ led_dat->active_low;
+       else
+               state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
+       led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
        if (!template->retain_state_suspended)
                led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
-       ret = gpio_direction_output(led_dat->gpio, led_dat->active_low);
+       ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);
        if (ret < 0)
                goto err;
 
@@ -129,7 +133,7 @@ static void delete_gpio_led(struct gpio_led_data *led)
 }
 
 #ifdef CONFIG_LEDS_GPIO_PLATFORM
-static int gpio_led_probe(struct platform_device *pdev)
+static int __devinit gpio_led_probe(struct platform_device *pdev)
 {
        struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
        struct gpio_led_data *leds_data;
@@ -223,12 +227,22 @@ static int __devinit of_gpio_leds_probe(struct of_device *ofdev,
        memset(&led, 0, sizeof(led));
        for_each_child_of_node(np, child) {
                enum of_gpio_flags flags;
+               const char *state;
 
                led.gpio = of_get_gpio_flags(child, 0, &flags);
                led.active_low = flags & OF_GPIO_ACTIVE_LOW;
                led.name = of_get_property(child, "label", NULL) ? : child->name;
                led.default_trigger =
                        of_get_property(child, "linux,default-trigger", NULL);
+               state = of_get_property(child, "default-state", NULL);
+               if (state) {
+                       if (!strcmp(state, "keep"))
+                               led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
+                       else if(!strcmp(state, "on"))
+                               led.default_state = LEDS_GPIO_DEFSTATE_ON;
+                       else
+                               led.default_state = LEDS_GPIO_DEFSTATE_OFF;
+               }
 
                ret = create_gpio_led(&led, &pdata->led_data[pdata->num_leds++],
                                      &ofdev->dev, NULL);
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c
new file mode 100644 (file)
index 0000000..5946208
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * leds-lp3944.c - driver for National Semiconductor LP3944 Funlight Chip
+ *
+ * Copyright (C) 2009 Antonio Ospite <ospite@studenti.unina.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.
+ *
+ */
+
+/*
+ * I2C driver for National Semiconductor LP3944 Funlight Chip
+ * http://www.national.com/pf/LP/LP3944.html
+ *
+ * This helper chip can drive up to 8 leds, with two programmable DIM modes;
+ * it could even be used as a gpio expander but this driver assumes it is used
+ * as a led controller.
+ *
+ * The DIM modes are used to set _blink_ patterns for leds, the pattern is
+ * specified supplying two parameters:
+ *   - period: from 0s to 1.6s
+ *   - duty cycle: percentage of the period the led is on, from 0 to 100
+ *
+ * LP3944 can be found on Motorola A910 smartphone, where it drives the rgb
+ * leds, the camera flash light and the displays backlights.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/leds-lp3944.h>
+
+/* Read Only Registers */
+#define LP3944_REG_INPUT1     0x00 /* LEDs 0-7 InputRegister (Read Only) */
+#define LP3944_REG_REGISTER1  0x01 /* None (Read Only) */
+
+#define LP3944_REG_PSC0       0x02 /* Frequency Prescaler 0 (R/W) */
+#define LP3944_REG_PWM0       0x03 /* PWM Register 0 (R/W) */
+#define LP3944_REG_PSC1       0x04 /* Frequency Prescaler 1 (R/W) */
+#define LP3944_REG_PWM1       0x05 /* PWM Register 1 (R/W) */
+#define LP3944_REG_LS0        0x06 /* LEDs 0-3 Selector (R/W) */
+#define LP3944_REG_LS1        0x07 /* LEDs 4-7 Selector (R/W) */
+
+/* These registers are not used to control leds in LP3944, they can store
+ * arbitrary values which the chip will ignore.
+ */
+#define LP3944_REG_REGISTER8  0x08
+#define LP3944_REG_REGISTER9  0x09
+
+#define LP3944_DIM0 0
+#define LP3944_DIM1 1
+
+/* period in ms */
+#define LP3944_PERIOD_MIN 0
+#define LP3944_PERIOD_MAX 1600
+
+/* duty cycle is a percentage */
+#define LP3944_DUTY_CYCLE_MIN 0
+#define LP3944_DUTY_CYCLE_MAX 100
+
+#define ldev_to_led(c)       container_of(c, struct lp3944_led_data, ldev)
+
+/* Saved data */
+struct lp3944_led_data {
+       u8 id;
+       enum lp3944_type type;
+       enum lp3944_status status;
+       struct led_classdev ldev;
+       struct i2c_client *client;
+       struct work_struct work;
+};
+
+struct lp3944_data {
+       struct mutex lock;
+       struct i2c_client *client;
+       struct lp3944_led_data leds[LP3944_LEDS_MAX];
+};
+
+static int lp3944_reg_read(struct i2c_client *client, u8 reg, u8 *value)
+{
+       int tmp;
+
+       tmp = i2c_smbus_read_byte_data(client, reg);
+       if (tmp < 0)
+               return -EINVAL;
+
+       *value = tmp;
+
+       return 0;
+}
+
+static int lp3944_reg_write(struct i2c_client *client, u8 reg, u8 value)
+{
+       return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/**
+ * Set the period for DIM status
+ *
+ * @client: the i2c client
+ * @dim: either LP3944_DIM0 or LP3944_DIM1
+ * @period: period of a blink, that is a on/off cycle, expressed in ms.
+ */
+static int lp3944_dim_set_period(struct i2c_client *client, u8 dim, u16 period)
+{
+       u8 psc_reg;
+       u8 psc_value;
+       int err;
+
+       if (dim == LP3944_DIM0)
+               psc_reg = LP3944_REG_PSC0;
+       else if (dim == LP3944_DIM1)
+               psc_reg = LP3944_REG_PSC1;
+       else
+               return -EINVAL;
+
+       /* Convert period to Prescaler value */
+       if (period > LP3944_PERIOD_MAX)
+               return -EINVAL;
+
+       psc_value = (period * 255) / LP3944_PERIOD_MAX;
+
+       err = lp3944_reg_write(client, psc_reg, psc_value);
+
+       return err;
+}
+
+/**
+ * Set the duty cycle for DIM status
+ *
+ * @client: the i2c client
+ * @dim: either LP3944_DIM0 or LP3944_DIM1
+ * @duty_cycle: percentage of a period during which a led is ON
+ */
+static int lp3944_dim_set_dutycycle(struct i2c_client *client, u8 dim,
+                                   u8 duty_cycle)
+{
+       u8 pwm_reg;
+       u8 pwm_value;
+       int err;
+
+       if (dim == LP3944_DIM0)
+               pwm_reg = LP3944_REG_PWM0;
+       else if (dim == LP3944_DIM1)
+               pwm_reg = LP3944_REG_PWM1;
+       else
+               return -EINVAL;
+
+       /* Convert duty cycle to PWM value */
+       if (duty_cycle > LP3944_DUTY_CYCLE_MAX)
+               return -EINVAL;
+
+       pwm_value = (duty_cycle * 255) / LP3944_DUTY_CYCLE_MAX;
+
+       err = lp3944_reg_write(client, pwm_reg, pwm_value);
+
+       return err;
+}
+
+/**
+ * Set the led status
+ *
+ * @led: a lp3944_led_data structure
+ * @status: one of LP3944_LED_STATUS_OFF
+ *                 LP3944_LED_STATUS_ON
+ *                 LP3944_LED_STATUS_DIM0
+ *                 LP3944_LED_STATUS_DIM1
+ */
+static int lp3944_led_set(struct lp3944_led_data *led, u8 status)
+{
+       struct lp3944_data *data = i2c_get_clientdata(led->client);
+       u8 id = led->id;
+       u8 reg;
+       u8 val = 0;
+       int err;
+
+       dev_dbg(&led->client->dev, "%s: %s, status before normalization:%d\n",
+               __func__, led->ldev.name, status);
+
+       switch (id) {
+       case LP3944_LED0:
+       case LP3944_LED1:
+       case LP3944_LED2:
+       case LP3944_LED3:
+               reg = LP3944_REG_LS0;
+               break;
+       case LP3944_LED4:
+       case LP3944_LED5:
+       case LP3944_LED6:
+       case LP3944_LED7:
+               id -= LP3944_LED4;
+               reg = LP3944_REG_LS1;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (status > LP3944_LED_STATUS_DIM1)
+               return -EINVAL;
+
+       /* invert only 0 and 1, leave unchanged the other values,
+        * remember we are abusing status to set blink patterns
+        */
+       if (led->type == LP3944_LED_TYPE_LED_INVERTED && status < 2)
+               status = 1 - status;
+
+       mutex_lock(&data->lock);
+       lp3944_reg_read(led->client, reg, &val);
+
+       val &= ~(LP3944_LED_STATUS_MASK << (id << 1));
+       val |= (status << (id << 1));
+
+       dev_dbg(&led->client->dev, "%s: %s, reg:%d id:%d status:%d val:%#x\n",
+               __func__, led->ldev.name, reg, id, status, val);
+
+       /* set led status */
+       err = lp3944_reg_write(led->client, reg, val);
+       mutex_unlock(&data->lock);
+
+       return err;
+}
+
+static int lp3944_led_set_blink(struct led_classdev *led_cdev,
+                               unsigned long *delay_on,
+                               unsigned long *delay_off)
+{
+       struct lp3944_led_data *led = ldev_to_led(led_cdev);
+       u16 period;
+       u8 duty_cycle;
+       int err;
+
+       /* units are in ms */
+       if (*delay_on + *delay_off > LP3944_PERIOD_MAX)
+               return -EINVAL;
+
+       if (*delay_on == 0 && *delay_off == 0) {
+               /* Special case: the leds subsystem requires a default user
+                * friendly blink pattern for the LED.  Let's blink the led
+                * slowly (1Hz).
+                */
+               *delay_on = 500;
+               *delay_off = 500;
+       }
+
+       period = (*delay_on) + (*delay_off);
+
+       /* duty_cycle is the percentage of period during which the led is ON */
+       duty_cycle = 100 * (*delay_on) / period;
+
+       /* invert duty cycle for inverted leds, this has the same effect of
+        * swapping delay_on and delay_off
+        */
+       if (led->type == LP3944_LED_TYPE_LED_INVERTED)
+               duty_cycle = 100 - duty_cycle;
+
+       /* NOTE: using always the first DIM mode, this means that all leds
+        * will have the same blinking pattern.
+        *
+        * We could find a way later to have two leds blinking in hardware
+        * with different patterns at the same time, falling back to software
+        * control for the other ones.
+        */
+       err = lp3944_dim_set_period(led->client, LP3944_DIM0, period);
+       if (err)
+               return err;
+
+       err = lp3944_dim_set_dutycycle(led->client, LP3944_DIM0, duty_cycle);
+       if (err)
+               return err;
+
+       dev_dbg(&led->client->dev, "%s: OK hardware accelerated blink!\n",
+               __func__);
+
+       led->status = LP3944_LED_STATUS_DIM0;
+       schedule_work(&led->work);
+
+       return 0;
+}
+
+static void lp3944_led_set_brightness(struct led_classdev *led_cdev,
+                                     enum led_brightness brightness)
+{
+       struct lp3944_led_data *led = ldev_to_led(led_cdev);
+
+       dev_dbg(&led->client->dev, "%s: %s, %d\n",
+               __func__, led_cdev->name, brightness);
+
+       led->status = brightness;
+       schedule_work(&led->work);
+}
+
+static void lp3944_led_work(struct work_struct *work)
+{
+       struct lp3944_led_data *led;
+
+       led = container_of(work, struct lp3944_led_data, work);
+       lp3944_led_set(led, led->status);
+}
+
+static int lp3944_configure(struct i2c_client *client,
+                           struct lp3944_data *data,
+                           struct lp3944_platform_data *pdata)
+{
+       int i, err = 0;
+
+       for (i = 0; i < pdata->leds_size; i++) {
+               struct lp3944_led *pled = &pdata->leds[i];
+               struct lp3944_led_data *led = &data->leds[i];
+               led->client = client;
+               led->id = i;
+
+               switch (pled->type) {
+
+               case LP3944_LED_TYPE_LED:
+               case LP3944_LED_TYPE_LED_INVERTED:
+                       led->type = pled->type;
+                       led->status = pled->status;
+                       led->ldev.name = pled->name;
+                       led->ldev.max_brightness = 1;
+                       led->ldev.brightness_set = lp3944_led_set_brightness;
+                       led->ldev.blink_set = lp3944_led_set_blink;
+                       led->ldev.flags = LED_CORE_SUSPENDRESUME;
+
+                       INIT_WORK(&led->work, lp3944_led_work);
+                       err = led_classdev_register(&client->dev, &led->ldev);
+                       if (err < 0) {
+                               dev_err(&client->dev,
+                                       "couldn't register LED %s\n",
+                                       led->ldev.name);
+                               goto exit;
+                       }
+
+                       /* to expose the default value to userspace */
+                       led->ldev.brightness = led->status;
+
+                       /* Set the default led status */
+                       err = lp3944_led_set(led, led->status);
+                       if (err < 0) {
+                               dev_err(&client->dev,
+                                       "%s couldn't set STATUS %d\n",
+                                       led->ldev.name, led->status);
+                               goto exit;
+                       }
+                       break;
+
+               case LP3944_LED_TYPE_NONE:
+               default:
+                       break;
+
+               }
+       }
+       return 0;
+
+exit:
+       if (i > 0)
+               for (i = i - 1; i >= 0; i--)
+                       switch (pdata->leds[i].type) {
+
+                       case LP3944_LED_TYPE_LED:
+                       case LP3944_LED_TYPE_LED_INVERTED:
+                               led_classdev_unregister(&data->leds[i].ldev);
+                               cancel_work_sync(&data->leds[i].work);
+                               break;
+
+                       case LP3944_LED_TYPE_NONE:
+                       default:
+                               break;
+                       }
+
+       return err;
+}
+
+static int __devinit lp3944_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data;
+       struct lp3944_data *data;
+
+       if (lp3944_pdata == NULL) {
+               dev_err(&client->dev, "no platform data\n");
+               return -EINVAL;
+       }
+
+       /* Let's see whether this adapter can support what we need. */
+       if (!i2c_check_functionality(client->adapter,
+                               I2C_FUNC_SMBUS_BYTE_DATA)) {
+               dev_err(&client->dev, "insufficient functionality!\n");
+               return -ENODEV;
+       }
+
+       data = kzalloc(sizeof(struct lp3944_data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->client = client;
+       i2c_set_clientdata(client, data);
+
+       mutex_init(&data->lock);
+
+       dev_info(&client->dev, "lp3944 enabled\n");
+
+       lp3944_configure(client, data, lp3944_pdata);
+       return 0;
+}
+
+static int __devexit lp3944_remove(struct i2c_client *client)
+{
+       struct lp3944_platform_data *pdata = client->dev.platform_data;
+       struct lp3944_data *data = i2c_get_clientdata(client);
+       int i;
+
+       for (i = 0; i < pdata->leds_size; i++)
+               switch (data->leds[i].type) {
+               case LP3944_LED_TYPE_LED:
+               case LP3944_LED_TYPE_LED_INVERTED:
+                       led_classdev_unregister(&data->leds[i].ldev);
+                       cancel_work_sync(&data->leds[i].work);
+                       break;
+
+               case LP3944_LED_TYPE_NONE:
+               default:
+                       break;
+               }
+
+       kfree(data);
+       i2c_set_clientdata(client, NULL);
+
+       return 0;
+}
+
+/* lp3944 i2c driver struct */
+static const struct i2c_device_id lp3944_id[] = {
+       {"lp3944", 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, lp3944_id);
+
+static struct i2c_driver lp3944_driver = {
+       .driver   = {
+                  .name = "lp3944",
+       },
+       .probe    = lp3944_probe,
+       .remove   = __devexit_p(lp3944_remove),
+       .id_table = lp3944_id,
+};
+
+static int __init lp3944_module_init(void)
+{
+       return i2c_add_driver(&lp3944_driver);
+}
+
+static void __exit lp3944_module_exit(void)
+{
+       i2c_del_driver(&lp3944_driver);
+}
+
+module_init(lp3944_module_init);
+module_exit(lp3944_module_exit);
+
+MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
+MODULE_DESCRIPTION("LP3944 Fun Light Chip");
+MODULE_LICENSE("GPL");
index 3937244fdcab8bf31562337430996a6cd7a943c2..dba8921240f262f5fbc70a7dcc0dddfc1bd73161 100644 (file)
@@ -35,7 +35,7 @@ struct pca9532_data {
        struct pca9532_led leds[16];
        struct mutex update_lock;
        struct input_dev    *idev;
-       struct work_struct work;
+       struct work_struct work;
        u8 pwm[2];
        u8 psc[2];
 };
@@ -87,14 +87,14 @@ static int pca9532_calcpwm(struct i2c_client *client, int pwm, int blink,
        if (b > 0xFF)
                return -EINVAL;
        data->pwm[pwm] = b;
-       data->psc[pwm] = blink;
-       return 0;
+       data->psc[pwm] = blink;
+       return 0;
 }
 
 static int pca9532_setpwm(struct i2c_client *client, int pwm)
 {
-       struct pca9532_data *data = i2c_get_clientdata(client);
-       mutex_lock(&data->update_lock);
+       struct pca9532_data *data = i2c_get_clientdata(client);
+       mutex_lock(&data->update_lock);
        i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(pwm),
                data->pwm[pwm]);
        i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(pwm),
@@ -132,11 +132,11 @@ static void pca9532_set_brightness(struct led_classdev *led_cdev,
                led->state = PCA9532_ON;
        else {
                led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */
-               err = pca9532_calcpwm(led->client, 0, 0, value);
+               err = pca9532_calcpwm(led->client, 0, 0, value);
                if (err)
                        return; /* XXX: led api doesn't allow error code? */
        }
-       schedule_work(&led->work);
+       schedule_work(&led->work);
 }
 
 static int pca9532_set_blink(struct led_classdev *led_cdev,
@@ -145,7 +145,7 @@ static int pca9532_set_blink(struct led_classdev *led_cdev,
        struct pca9532_led *led = ldev_to_led(led_cdev);
        struct i2c_client *client = led->client;
        int psc;
-       int err = 0;
+       int err = 0;
 
        if (*delay_on == 0 && *delay_off == 0) {
        /* led subsystem ask us for a blink rate */
@@ -157,11 +157,11 @@ static int pca9532_set_blink(struct led_classdev *led_cdev,
 
        /* Thecus specific: only use PSC/PWM 0 */
        psc = (*delay_on * 152-1)/1000;
-       err = pca9532_calcpwm(client, 0, psc, led_cdev->brightness);
-       if (err)
-               return err;
-       schedule_work(&led->work);
-       return 0;
+       err = pca9532_calcpwm(client, 0, psc, led_cdev->brightness);
+       if (err)
+               return err;
+       schedule_work(&led->work);
+       return 0;
 }
 
 static int pca9532_event(struct input_dev *dev, unsigned int type,
@@ -178,15 +178,15 @@ static int pca9532_event(struct input_dev *dev, unsigned int type,
        else
                data->pwm[1] = 0;
 
-       schedule_work(&data->work);
+       schedule_work(&data->work);
 
-       return 0;
+       return 0;
 }
 
 static void pca9532_input_work(struct work_struct *work)
 {
-       struct pca9532_data *data;
-       data = container_of(work, struct pca9532_data, work);
+       struct pca9532_data *data;
+       data = container_of(work, struct pca9532_data, work);
        mutex_lock(&data->update_lock);
        i2c_smbus_write_byte_data(data->client, PCA9532_REG_PWM(1),
                data->pwm[1]);
@@ -195,11 +195,11 @@ static void pca9532_input_work(struct work_struct *work)
 
 static void pca9532_led_work(struct work_struct *work)
 {
-       struct pca9532_led *led;
-       led = container_of(work, struct pca9532_led, work);
-       if (led->state == PCA9532_PWM0)
-               pca9532_setpwm(led->client, 0);
-       pca9532_setled(led);
+       struct pca9532_led *led;
+       led = container_of(work, struct pca9532_led, work);
+       if (led->state == PCA9532_PWM0)
+               pca9532_setpwm(led->client, 0);
+       pca9532_setled(led);
 }
 
 static int pca9532_configure(struct i2c_client *client,
@@ -232,7 +232,7 @@ static int pca9532_configure(struct i2c_client *client,
                        led->ldev.brightness = LED_OFF;
                        led->ldev.brightness_set = pca9532_set_brightness;
                        led->ldev.blink_set = pca9532_set_blink;
-                       INIT_WORK(&led->work, pca9532_led_work);
+                       INIT_WORK(&led->work, pca9532_led_work);
                        err = led_classdev_register(&client->dev, &led->ldev);
                        if (err < 0) {
                                dev_err(&client->dev,
@@ -262,11 +262,11 @@ static int pca9532_configure(struct i2c_client *client,
                                                BIT_MASK(SND_TONE);
                        data->idev->event = pca9532_event;
                        input_set_drvdata(data->idev, data);
-                       INIT_WORK(&data->work, pca9532_input_work);
+                       INIT_WORK(&data->work, pca9532_input_work);
                        err = input_register_device(data->idev);
                        if (err) {
                                input_free_device(data->idev);
-                               cancel_work_sync(&data->work);
+                               cancel_work_sync(&data->work);
                                data->idev = NULL;
                                goto exit;
                        }
@@ -283,13 +283,13 @@ exit:
                                break;
                        case PCA9532_TYPE_LED:
                                led_classdev_unregister(&data->leds[i].ldev);
-                               cancel_work_sync(&data->leds[i].work);
+                               cancel_work_sync(&data->leds[i].work);
                                break;
                        case PCA9532_TYPE_N2100_BEEP:
                                if (data->idev != NULL) {
                                        input_unregister_device(data->idev);
                                        input_free_device(data->idev);
-                                       cancel_work_sync(&data->work);
+                                       cancel_work_sync(&data->work);
                                        data->idev = NULL;
                                }
                                break;
@@ -340,13 +340,13 @@ static int pca9532_remove(struct i2c_client *client)
                        break;
                case PCA9532_TYPE_LED:
                        led_classdev_unregister(&data->leds[i].ldev);
-                       cancel_work_sync(&data->leds[i].work);
+                       cancel_work_sync(&data->leds[i].work);
                        break;
                case PCA9532_TYPE_N2100_BEEP:
                        if (data->idev != NULL) {
                                input_unregister_device(data->idev);
                                input_free_device(data->idev);
-                               cancel_work_sync(&data->work);
+                               cancel_work_sync(&data->work);
                                data->idev = NULL;
                        }
                        break;
index a247ae63374f161973785a3cb3675b082947cbec..1bc5db4ece0d951e202868a8cc539a34093d5cda 100644 (file)
@@ -117,6 +117,9 @@ static ssize_t gpio_trig_inverted_store(struct device *dev,
 
        gpio_data->inverted = !!inverted;
 
+       /* After inverting, we need to update the LED. */
+       schedule_work(&gpio_data->work);
+
        return n;
 }
 static DEVICE_ATTR(inverted, 0644, gpio_trig_inverted_show,
@@ -146,20 +149,26 @@ static ssize_t gpio_trig_gpio_store(struct device *dev,
                return -EINVAL;
        }
 
+       if (gpio_data->gpio == gpio)
+               return n;
+
        if (!gpio) {
-               free_irq(gpio_to_irq(gpio_data->gpio), led);
+               if (gpio_data->gpio != 0)
+                       free_irq(gpio_to_irq(gpio_data->gpio), led);
+               gpio_data->gpio = 0;
                return n;
        }
 
-       if (gpio_data->gpio > 0 && gpio_data->gpio != gpio)
-               free_irq(gpio_to_irq(gpio_data->gpio), led);
-
-       gpio_data->gpio = gpio;
        ret = request_irq(gpio_to_irq(gpio), gpio_trig_irq,
                        IRQF_SHARED | IRQF_TRIGGER_RISING
                        | IRQF_TRIGGER_FALLING, "ledtrig-gpio", led);
-       if (ret)
+       if (ret) {
                dev_err(dev, "request_irq failed with error %d\n", ret);
+       } else {
+               if (gpio_data->gpio != 0)
+                       free_irq(gpio_to_irq(gpio_data->gpio), led);
+               gpio_data->gpio = gpio;
+       }
 
        return ret ? ret : n;
 }
@@ -211,7 +220,8 @@ static void gpio_trig_deactivate(struct led_classdev *led)
                device_remove_file(led->dev, &dev_attr_inverted);
                device_remove_file(led->dev, &dev_attr_desired_brightness);
                flush_work(&gpio_data->work);
-               free_irq(gpio_to_irq(gpio_data->gpio),led);
+               if (gpio_data->gpio != 0)
+                       free_irq(gpio_to_irq(gpio_data->gpio), led);
                kfree(gpio_data);
        }
 }
index a6974e9b8ebff8c8676f297da0e32a1e3e6d0105..1e2cb846b3c9d7b593d3dd6e5b588a1f3f227991 100644 (file)
@@ -1,6 +1,8 @@
-/*P:400 This contains run_guest() which actually calls into the Host<->Guest
+/*P:400
+ * This contains run_guest() which actually calls into the Host<->Guest
  * Switcher and analyzes the return, such as determining if the Guest wants the
- * Host to do something.  This file also contains useful helper routines. :*/
+ * Host to do something.  This file also contains useful helper routines.
+:*/
 #include <linux/module.h>
 #include <linux/stringify.h>
 #include <linux/stddef.h>
@@ -24,7 +26,8 @@ static struct page **switcher_page;
 /* This One Big lock protects all inter-guest data structures. */
 DEFINE_MUTEX(lguest_lock);
 
-/*H:010 We need to set up the Switcher at a high virtual address.  Remember the
+/*H:010
+ * We need to set up the Switcher at a high virtual address.  Remember the
  * Switcher is a few hundred bytes of assembler code which actually changes the
  * CPU to run the Guest, and then changes back to the Host when a trap or
  * interrupt happens.
@@ -33,7 +36,8 @@ DEFINE_MUTEX(lguest_lock);
  * Host since it will be running as the switchover occurs.
  *
  * Trying to map memory at a particular address is an unusual thing to do, so
- * it's not a simple one-liner. */
+ * it's not a simple one-liner.
+ */
 static __init int map_switcher(void)
 {
        int i, err;
@@ -47,8 +51,10 @@ static __init int map_switcher(void)
         * easy.
         */
 
-       /* We allocate an array of struct page pointers.  map_vm_area() wants
-        * this, rather than just an array of pages. */
+       /*
+        * We allocate an array of struct page pointers.  map_vm_area() wants
+        * this, rather than just an array of pages.
+        */
        switcher_page = kmalloc(sizeof(switcher_page[0])*TOTAL_SWITCHER_PAGES,
                                GFP_KERNEL);
        if (!switcher_page) {
@@ -56,8 +62,10 @@ static __init int map_switcher(void)
                goto out;
        }
 
-       /* Now we actually allocate the pages.  The Guest will see these pages,
-        * so we make sure they're zeroed. */
+       /*
+        * Now we actually allocate the pages.  The Guest will see these pages,
+        * so we make sure they're zeroed.
+        */
        for (i = 0; i < TOTAL_SWITCHER_PAGES; i++) {
                unsigned long addr = get_zeroed_page(GFP_KERNEL);
                if (!addr) {
@@ -67,19 +75,23 @@ static __init int map_switcher(void)
                switcher_page[i] = virt_to_page(addr);
        }
 
-       /* First we check that the Switcher won't overlap the fixmap area at
+       /*
+        * First we check that the Switcher won't overlap the fixmap area at
         * the top of memory.  It's currently nowhere near, but it could have
-        * very strange effects if it ever happened. */
+        * very strange effects if it ever happened.
+        */
        if (SWITCHER_ADDR + (TOTAL_SWITCHER_PAGES+1)*PAGE_SIZE > FIXADDR_START){
                err = -ENOMEM;
                printk("lguest: mapping switcher would thwack fixmap\n");
                goto free_pages;
        }
 
-       /* Now we reserve the "virtual memory area" we want: 0xFFC00000
+       /*
+        * Now we reserve the "virtual memory area" we want: 0xFFC00000
         * (SWITCHER_ADDR).  We might not get it in theory, but in practice
         * it's worked so far.  The end address needs +1 because __get_vm_area
-        * allocates an extra guard page, so we need space for that. */
+        * allocates an extra guard page, so we need space for that.
+        */
        switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE,
                                     VM_ALLOC, SWITCHER_ADDR, SWITCHER_ADDR
                                     + (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE);
@@ -89,11 +101,13 @@ static __init int map_switcher(void)
                goto free_pages;
        }
 
-       /* This code actually sets up the pages we've allocated to appear at
+       /*
+        * This code actually sets up the pages we've allocated to appear at
         * SWITCHER_ADDR.  map_vm_area() takes the vma we allocated above, the
         * kind of pages we're mapping (kernel pages), and a pointer to our
         * array of struct pages.  It increments that pointer, but we don't
-        * care. */
+        * care.
+        */
        pagep = switcher_page;
        err = map_vm_area(switcher_vma, PAGE_KERNEL_EXEC, &pagep);
        if (err) {
@@ -101,8 +115,10 @@ static __init int map_switcher(void)
                goto free_vma;
        }
 
-       /* Now the Switcher is mapped at the right address, we can't fail!
-        * Copy in the compiled-in Switcher code (from <arch>_switcher.S). */
+       /*
+        * Now the Switcher is mapped at the right address, we can't fail!
+        * Copy in the compiled-in Switcher code (from <arch>_switcher.S).
+        */
        memcpy(switcher_vma->addr, start_switcher_text,
               end_switcher_text - start_switcher_text);
 
@@ -124,8 +140,7 @@ out:
 }
 /*:*/
 
-/* Cleaning up the mapping when the module is unloaded is almost...
- * too easy. */
+/* Cleaning up the mapping when the module is unloaded is almost... too easy. */
 static void unmap_switcher(void)
 {
        unsigned int i;
@@ -151,16 +166,19 @@ static void unmap_switcher(void)
  * But we can't trust the Guest: it might be trying to access the Launcher
  * code.  We have to check that the range is below the pfn_limit the Launcher
  * gave us.  We have to make sure that addr + len doesn't give us a false
- * positive by overflowing, too. */
+ * positive by overflowing, too.
+ */
 bool lguest_address_ok(const struct lguest *lg,
                       unsigned long addr, unsigned long len)
 {
        return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr);
 }
 
-/* This routine copies memory from the Guest.  Here we can see how useful the
+/*
+ * This routine copies memory from the Guest.  Here we can see how useful the
  * kill_lguest() routine we met in the Launcher can be: we return a random
- * value (all zeroes) instead of needing to return an error. */
+ * value (all zeroes) instead of needing to return an error.
+ */
 void __lgread(struct lg_cpu *cpu, void *b, unsigned long addr, unsigned bytes)
 {
        if (!lguest_address_ok(cpu->lg, addr, bytes)
@@ -181,9 +199,11 @@ void __lgwrite(struct lg_cpu *cpu, unsigned long addr, const void *b,
 }
 /*:*/
 
-/*H:030 Let's jump straight to the the main loop which runs the Guest.
+/*H:030
+ * Let's jump straight to the the main loop which runs the Guest.
  * Remember, this is called by the Launcher reading /dev/lguest, and we keep
- * going around and around until something interesting happens. */
+ * going around and around until something interesting happens.
+ */
 int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
 {
        /* We stop running once the Guest is dead. */
@@ -195,10 +215,17 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
                if (cpu->hcall)
                        do_hypercalls(cpu);
 
-               /* It's possible the Guest did a NOTIFY hypercall to the
-                * Launcher, in which case we return from the read() now. */
+               /*
+                * It's possible the Guest did a NOTIFY hypercall to the
+                * Launcher.
+                */
                if (cpu->pending_notify) {
+                       /*
+                        * Does it just needs to write to a registered
+                        * eventfd (ie. the appropriate virtqueue thread)?
+                        */
                        if (!send_notify_to_eventfd(cpu)) {
+                               /* OK, we tell the main Laucher. */
                                if (put_user(cpu->pending_notify, user))
                                        return -EFAULT;
                                return sizeof(cpu->pending_notify);
@@ -209,29 +236,39 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
                if (signal_pending(current))
                        return -ERESTARTSYS;
 
-               /* Check if there are any interrupts which can be delivered now:
+               /*
+                * Check if there are any interrupts which can be delivered now:
                 * if so, this sets up the hander to be executed when we next
-                * run the Guest. */
+                * run the Guest.
+                */
                irq = interrupt_pending(cpu, &more);
                if (irq < LGUEST_IRQS)
                        try_deliver_interrupt(cpu, irq, more);
 
-               /* All long-lived kernel loops need to check with this horrible
+               /*
+                * All long-lived kernel loops need to check with this horrible
                 * thing called the freezer.  If the Host is trying to suspend,
-                * it stops us. */
+                * it stops us.
+                */
                try_to_freeze();
 
-               /* Just make absolutely sure the Guest is still alive.  One of
-                * those hypercalls could have been fatal, for example. */
+               /*
+                * Just make absolutely sure the Guest is still alive.  One of
+                * those hypercalls could have been fatal, for example.
+                */
                if (cpu->lg->dead)
                        break;
 
-               /* If the Guest asked to be stopped, we sleep.  The Guest's
-                * clock timer will wake us. */
+               /*
+                * If the Guest asked to be stopped, we sleep.  The Guest's
+                * clock timer will wake us.
+                */
                if (cpu->halted) {
                        set_current_state(TASK_INTERRUPTIBLE);
-                       /* Just before we sleep, make sure no interrupt snuck in
-                        * which we should be doing. */
+                       /*
+                        * Just before we sleep, make sure no interrupt snuck in
+                        * which we should be doing.
+                        */
                        if (interrupt_pending(cpu, &more) < LGUEST_IRQS)
                                set_current_state(TASK_RUNNING);
                        else
@@ -239,8 +276,10 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
                        continue;
                }
 
-               /* OK, now we're ready to jump into the Guest.  First we put up
-                * the "Do Not Disturb" sign: */
+               /*
+                * OK, now we're ready to jump into the Guest.  First we put up
+                * the "Do Not Disturb" sign:
+                */
                local_irq_disable();
 
                /* Actually run the Guest until something happens. */
@@ -327,8 +366,10 @@ static void __exit fini(void)
 }
 /*:*/
 
-/* The Host side of lguest can be a module.  This is a nice way for people to
- * play with it.  */
+/*
+ * The Host side of lguest can be a module.  This is a nice way for people to
+ * play with it.
+ */
 module_init(init);
 module_exit(fini);
 MODULE_LICENSE("GPL");
index c29ffa19cb74410e5b37ddc74bf19d4a45c5d9e7..83511eb0923d2f908a9e884d6470d493548e5cc0 100644 (file)
@@ -1,8 +1,10 @@
-/*P:500 Just as userspace programs request kernel operations through a system
+/*P:500
+ * Just as userspace programs request kernel operations through a system
  * call, the Guest requests Host operations through a "hypercall".  You might
  * notice this nomenclature doesn't really follow any logic, but the name has
  * been around for long enough that we're stuck with it.  As you'd expect, this
- * code is basically a one big switch statement. :*/
+ * code is basically a one big switch statement.
+:*/
 
 /*  Copyright (C) 2006 Rusty Russell IBM Corporation
 
 #include <asm/pgtable.h>
 #include "lg.h"
 
-/*H:120 This is the core hypercall routine: where the Guest gets what it wants.
- * Or gets killed.  Or, in the case of LHCALL_SHUTDOWN, both. */
+/*H:120
+ * This is the core hypercall routine: where the Guest gets what it wants.
+ * Or gets killed.  Or, in the case of LHCALL_SHUTDOWN, both.
+ */
 static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
 {
        switch (args->arg0) {
        case LHCALL_FLUSH_ASYNC:
-               /* This call does nothing, except by breaking out of the Guest
-                * it makes us process all the asynchronous hypercalls. */
+               /*
+                * This call does nothing, except by breaking out of the Guest
+                * it makes us process all the asynchronous hypercalls.
+                */
                break;
        case LHCALL_SEND_INTERRUPTS:
-               /* This call does nothing too, but by breaking out of the Guest
-                * it makes us process any pending interrupts. */
+               /*
+                * This call does nothing too, but by breaking out of the Guest
+                * it makes us process any pending interrupts.
+                */
                break;
        case LHCALL_LGUEST_INIT:
-               /* You can't get here unless you're already initialized.  Don't
-                * do that. */
+               /*
+                * You can't get here unless you're already initialized.  Don't
+                * do that.
+                */
                kill_guest(cpu, "already have lguest_data");
                break;
        case LHCALL_SHUTDOWN: {
-               /* Shutdown is such a trivial hypercall that we do it in four
-                * lines right here. */
                char msg[128];
-               /* If the lgread fails, it will call kill_guest() itself; the
-                * kill_guest() with the message will be ignored. */
+               /*
+                * Shutdown is such a trivial hypercall that we do it in five
+                * lines right here.
+                *
+                * If the lgread fails, it will call kill_guest() itself; the
+                * kill_guest() with the message will be ignored.
+                */
                __lgread(cpu, msg, args->arg1, sizeof(msg));
                msg[sizeof(msg)-1] = '\0';
                kill_guest(cpu, "CRASH: %s", msg);
@@ -60,16 +73,17 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
                break;
        }
        case LHCALL_FLUSH_TLB:
-               /* FLUSH_TLB comes in two flavors, depending on the
-                * argument: */
+               /* FLUSH_TLB comes in two flavors, depending on the argument: */
                if (args->arg1)
                        guest_pagetable_clear_all(cpu);
                else
                        guest_pagetable_flush_user(cpu);
                break;
 
-       /* All these calls simply pass the arguments through to the right
-        * routines. */
+       /*
+        * All these calls simply pass the arguments through to the right
+        * routines.
+        */
        case LHCALL_NEW_PGTABLE:
                guest_new_pagetable(cpu, args->arg1);
                break;
@@ -112,15 +126,16 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
                        kill_guest(cpu, "Bad hypercall %li\n", args->arg0);
        }
 }
-/*:*/
 
-/*H:124 Asynchronous hypercalls are easy: we just look in the array in the
+/*H:124
+ * Asynchronous hypercalls are easy: we just look in the array in the
  * Guest's "struct lguest_data" to see if any new ones are marked "ready".
  *
  * We are careful to do these in order: obviously we respect the order the
  * Guest put them in the ring, but we also promise the Guest that they will
  * happen before any normal hypercall (which is why we check this before
- * checking for a normal hcall). */
+ * checking for a normal hcall).
+ */
 static void do_async_hcalls(struct lg_cpu *cpu)
 {
        unsigned int i;
@@ -133,22 +148,28 @@ static void do_async_hcalls(struct lg_cpu *cpu)
        /* We process "struct lguest_data"s hcalls[] ring once. */
        for (i = 0; i < ARRAY_SIZE(st); i++) {
                struct hcall_args args;
-               /* We remember where we were up to from last time.  This makes
+               /*
+                * We remember where we were up to from last time.  This makes
                 * sure that the hypercalls are done in the order the Guest
-                * places them in the ring. */
+                * places them in the ring.
+                */
                unsigned int n = cpu->next_hcall;
 
                /* 0xFF means there's no call here (yet). */
                if (st[n] == 0xFF)
                        break;
 
-               /* OK, we have hypercall.  Increment the "next_hcall" cursor,
-                * and wrap back to 0 if we reach the end. */
+               /*
+                * OK, we have hypercall.  Increment the "next_hcall" cursor,
+                * and wrap back to 0 if we reach the end.
+                */
                if (++cpu->next_hcall == LHCALL_RING_SIZE)
                        cpu->next_hcall = 0;
 
-               /* Copy the hypercall arguments into a local copy of
-                * the hcall_args struct. */
+               /*
+                * Copy the hypercall arguments into a local copy of the
+                * hcall_args struct.
+                */
                if (copy_from_user(&args, &cpu->lg->lguest_data->hcalls[n],
                                   sizeof(struct hcall_args))) {
                        kill_guest(cpu, "Fetching async hypercalls");
@@ -164,19 +185,25 @@ static void do_async_hcalls(struct lg_cpu *cpu)
                        break;
                }
 
-               /* Stop doing hypercalls if they want to notify the Launcher:
-                * it needs to service this first. */
+               /*
+                * Stop doing hypercalls if they want to notify the Launcher:
+                * it needs to service this first.
+                */
                if (cpu->pending_notify)
                        break;
        }
 }
 
-/* Last of all, we look at what happens first of all.  The very first time the
- * Guest makes a hypercall, we end up here to set things up: */
+/*
+ * Last of all, we look at what happens first of all.  The very first time the
+ * Guest makes a hypercall, we end up here to set things up:
+ */
 static void initialize(struct lg_cpu *cpu)
 {
-       /* You can't do anything until you're initialized.  The Guest knows the
-        * rules, so we're unforgiving here. */
+       /*
+        * You can't do anything until you're initialized.  The Guest knows the
+        * rules, so we're unforgiving here.
+        */
        if (cpu->hcall->arg0 != LHCALL_LGUEST_INIT) {
                kill_guest(cpu, "hypercall %li before INIT", cpu->hcall->arg0);
                return;
@@ -185,32 +212,44 @@ static void initialize(struct lg_cpu *cpu)
        if (lguest_arch_init_hypercalls(cpu))
                kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
 
-       /* The Guest tells us where we're not to deliver interrupts by putting
-        * the range of addresses into "struct lguest_data". */
+       /*
+        * The Guest tells us where we're not to deliver interrupts by putting
+        * the range of addresses into "struct lguest_data".
+        */
        if (get_user(cpu->lg->noirq_start, &cpu->lg->lguest_data->noirq_start)
            || get_user(cpu->lg->noirq_end, &cpu->lg->lguest_data->noirq_end))
                kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
 
-       /* We write the current time into the Guest's data page once so it can
-        * set its clock. */
+       /*
+        * We write the current time into the Guest's data page once so it can
+        * set its clock.
+        */
        write_timestamp(cpu);
 
        /* page_tables.c will also do some setup. */
        page_table_guest_data_init(cpu);
 
-       /* This is the one case where the above accesses might have been the
+       /*
+        * This is the one case where the above accesses might have been the
         * first write to a Guest page.  This may have caused a copy-on-write
         * fault, but the old page might be (read-only) in the Guest
-        * pagetable. */
+        * pagetable.
+        */
        guest_pagetable_clear_all(cpu);
 }
 /*:*/
 
-/*M:013 If a Guest reads from a page (so creates a mapping) that it has never
+/*M:013
+ * If a Guest reads from a page (so creates a mapping) that it has never
  * written to, and then the Launcher writes to it (ie. the output of a virtual
  * device), the Guest will still see the old page.  In practice, this never
  * happens: why would the Guest read a page which it has never written to?  But
- * a similar scenario might one day bite us, so it's worth mentioning. :*/
+ * a similar scenario might one day bite us, so it's worth mentioning.
+ *
+ * Note that if we used a shared anonymous mapping in the Launcher instead of
+ * mapping /dev/zero private, we wouldn't worry about cop-on-write.  And we
+ * need that to switch the Launcher to processes (away from threads) anyway.
+:*/
 
 /*H:100
  * Hypercalls
@@ -229,17 +268,22 @@ void do_hypercalls(struct lg_cpu *cpu)
                return;
        }
 
-       /* The Guest has initialized.
+       /*
+        * The Guest has initialized.
         *
-        * Look in the hypercall ring for the async hypercalls: */
+        * Look in the hypercall ring for the async hypercalls:
+        */
        do_async_hcalls(cpu);
 
-       /* If we stopped reading the hypercall ring because the Guest did a
+       /*
+        * If we stopped reading the hypercall ring because the Guest did a
         * NOTIFY to the Launcher, we want to return now.  Otherwise we do
-        * the hypercall. */
+        * the hypercall.
+        */
        if (!cpu->pending_notify) {
                do_hcall(cpu, cpu->hcall);
-               /* Tricky point: we reset the hcall pointer to mark the
+               /*
+                * Tricky point: we reset the hcall pointer to mark the
                 * hypercall as "done".  We use the hcall pointer rather than
                 * the trap number to indicate a hypercall is pending.
                 * Normally it doesn't matter: the Guest will run again and
@@ -248,13 +292,16 @@ void do_hypercalls(struct lg_cpu *cpu)
                 * However, if we are signalled or the Guest sends I/O to the
                 * Launcher, the run_guest() loop will exit without running the
                 * Guest.  When it comes back it would try to re-run the
-                * hypercall.  Finding that bug sucked. */
+                * hypercall.  Finding that bug sucked.
+                */
                cpu->hcall = NULL;
        }
 }
 
-/* This routine supplies the Guest with time: it's used for wallclock time at
- * initial boot and as a rough time source if the TSC isn't available. */
+/*
+ * This routine supplies the Guest with time: it's used for wallclock time at
+ * initial boot and as a rough time source if the TSC isn't available.
+ */
 void write_timestamp(struct lg_cpu *cpu)
 {
        struct timespec now;
index 0e9067b0d5072194d3ee1d496335cd8222b4109d..18648180db02ed94beaa32f9aec8fbe12e90b1ad 100644 (file)
@@ -1,4 +1,5 @@
-/*P:800 Interrupts (traps) are complicated enough to earn their own file.
+/*P:800
+ * Interrupts (traps) are complicated enough to earn their own file.
  * There are three classes of interrupts:
  *
  * 1) Real hardware interrupts which occur while we're running the Guest,
@@ -10,7 +11,8 @@
  * just like real hardware would deliver them.  Traps from the Guest can be set
  * up to go directly back into the Guest, but sometimes the Host wants to see
  * them first, so we also have a way of "reflecting" them into the Guest as if
- * they had been delivered to it directly. :*/
+ * they had been delivered to it directly.
+:*/
 #include <linux/uaccess.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
@@ -26,8 +28,10 @@ static unsigned long idt_address(u32 lo, u32 hi)
        return (lo & 0x0000FFFF) | (hi & 0xFFFF0000);
 }
 
-/* The "type" of the interrupt handler is a 4 bit field: we only support a
- * couple of types. */
+/*
+ * The "type" of the interrupt handler is a 4 bit field: we only support a
+ * couple of types.
+ */
 static int idt_type(u32 lo, u32 hi)
 {
        return (hi >> 8) & 0xF;
@@ -39,8 +43,10 @@ static bool idt_present(u32 lo, u32 hi)
        return (hi & 0x8000);
 }
 
-/* We need a helper to "push" a value onto the Guest's stack, since that's a
- * big part of what delivering an interrupt does. */
+/*
+ * We need a helper to "push" a value onto the Guest's stack, since that's a
+ * big part of what delivering an interrupt does.
+ */
 static void push_guest_stack(struct lg_cpu *cpu, unsigned long *gstack, u32 val)
 {
        /* Stack grows upwards: move stack then write value. */
@@ -48,7 +54,8 @@ static void push_guest_stack(struct lg_cpu *cpu, unsigned long *gstack, u32 val)
        lgwrite(cpu, *gstack, u32, val);
 }
 
-/*H:210 The set_guest_interrupt() routine actually delivers the interrupt or
+/*H:210
+ * The set_guest_interrupt() routine actually delivers the interrupt or
  * trap.  The mechanics of delivering traps and interrupts to the Guest are the
  * same, except some traps have an "error code" which gets pushed onto the
  * stack as well: the caller tells us if this is one.
@@ -59,7 +66,8 @@ static void push_guest_stack(struct lg_cpu *cpu, unsigned long *gstack, u32 val)
  *
  * We set up the stack just like the CPU does for a real interrupt, so it's
  * identical for the Guest (and the standard "iret" instruction will undo
- * it). */
+ * it).
+ */
 static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi,
                                bool has_err)
 {
@@ -67,20 +75,26 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi,
        u32 eflags, ss, irq_enable;
        unsigned long virtstack;
 
-       /* There are two cases for interrupts: one where the Guest is already
+       /*
+        * There are two cases for interrupts: one where the Guest is already
         * in the kernel, and a more complex one where the Guest is in
-        * userspace.  We check the privilege level to find out. */
+        * userspace.  We check the privilege level to find out.
+        */
        if ((cpu->regs->ss&0x3) != GUEST_PL) {
-               /* The Guest told us their kernel stack with the SET_STACK
-                * hypercall: both the virtual address and the segment */
+               /*
+                * The Guest told us their kernel stack with the SET_STACK
+                * hypercall: both the virtual address and the segment.
+                */
                virtstack = cpu->esp1;
                ss = cpu->ss1;
 
                origstack = gstack = guest_pa(cpu, virtstack);
-               /* We push the old stack segment and pointer onto the new
+               /*
+                * We push the old stack segment and pointer onto the new
                 * stack: when the Guest does an "iret" back from the interrupt
                 * handler the CPU will notice they're dropping privilege
-                * levels and expect these here. */
+                * levels and expect these here.
+                */
                push_guest_stack(cpu, &gstack, cpu->regs->ss);
                push_guest_stack(cpu, &gstack, cpu->regs->esp);
        } else {
@@ -91,18 +105,22 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi,
                origstack = gstack = guest_pa(cpu, virtstack);
        }
 
-       /* Remember that we never let the Guest actually disable interrupts, so
+       /*
+        * Remember that we never let the Guest actually disable interrupts, so
         * the "Interrupt Flag" bit is always set.  We copy that bit from the
         * Guest's "irq_enabled" field into the eflags word: we saw the Guest
-        * copy it back in "lguest_iret". */
+        * copy it back in "lguest_iret".
+        */
        eflags = cpu->regs->eflags;
        if (get_user(irq_enable, &cpu->lg->lguest_data->irq_enabled) == 0
            && !(irq_enable & X86_EFLAGS_IF))
                eflags &= ~X86_EFLAGS_IF;
 
-       /* An interrupt is expected to push three things on the stack: the old
+       /*
+        * An interrupt is expected to push three things on the stack: the old
         * "eflags" word, the old code segment, and the old instruction
-        * pointer. */
+        * pointer.
+        */
        push_guest_stack(cpu, &gstack, eflags);
        push_guest_stack(cpu, &gstack, cpu->regs->cs);
        push_guest_stack(cpu, &gstack, cpu->regs->eip);
@@ -111,15 +129,19 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi,
        if (has_err)
                push_guest_stack(cpu, &gstack, cpu->regs->errcode);
 
-       /* Now we've pushed all the old state, we change the stack, the code
-        * segment and the address to execute. */
+       /*
+        * Now we've pushed all the old state, we change the stack, the code
+        * segment and the address to execute.
+        */
        cpu->regs->ss = ss;
        cpu->regs->esp = virtstack + (gstack - origstack);
        cpu->regs->cs = (__KERNEL_CS|GUEST_PL);
        cpu->regs->eip = idt_address(lo, hi);
 
-       /* There are two kinds of interrupt handlers: 0xE is an "interrupt
-        * gate" which expects interrupts to be disabled on entry. */
+       /*
+        * There are two kinds of interrupt handlers: 0xE is an "interrupt
+        * gate" which expects interrupts to be disabled on entry.
+        */
        if (idt_type(lo, hi) == 0xE)
                if (put_user(0, &cpu->lg->lguest_data->irq_enabled))
                        kill_guest(cpu, "Disabling interrupts");
@@ -130,7 +152,8 @@ static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi,
  *
  * interrupt_pending() returns the first pending interrupt which isn't blocked
  * by the Guest.  It is called before every entry to the Guest, and just before
- * we go to sleep when the Guest has halted itself. */
+ * we go to sleep when the Guest has halted itself.
+ */
 unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more)
 {
        unsigned int irq;
@@ -140,8 +163,10 @@ unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more)
        if (!cpu->lg->lguest_data)
                return LGUEST_IRQS;
 
-       /* Take our "irqs_pending" array and remove any interrupts the Guest
-        * wants blocked: the result ends up in "blk". */
+       /*
+        * Take our "irqs_pending" array and remove any interrupts the Guest
+        * wants blocked: the result ends up in "blk".
+        */
        if (copy_from_user(&blk, cpu->lg->lguest_data->blocked_interrupts,
                           sizeof(blk)))
                return LGUEST_IRQS;
@@ -154,16 +179,20 @@ unsigned int interrupt_pending(struct lg_cpu *cpu, bool *more)
        return irq;
 }
 
-/* This actually diverts the Guest to running an interrupt handler, once an
- * interrupt has been identified by interrupt_pending(). */
+/*
+ * This actually diverts the Guest to running an interrupt handler, once an
+ * interrupt has been identified by interrupt_pending().
+ */
 void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more)
 {
        struct desc_struct *idt;
 
        BUG_ON(irq >= LGUEST_IRQS);
 
-       /* They may be in the middle of an iret, where they asked us never to
-        * deliver interrupts. */
+       /*
+        * They may be in the middle of an iret, where they asked us never to
+        * deliver interrupts.
+        */
        if (cpu->regs->eip >= cpu->lg->noirq_start &&
           (cpu->regs->eip < cpu->lg->noirq_end))
                return;
@@ -187,29 +216,37 @@ void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more)
                }
        }
 
-       /* Look at the IDT entry the Guest gave us for this interrupt.  The
+       /*
+        * Look at the IDT entry the Guest gave us for this interrupt.  The
         * first 32 (FIRST_EXTERNAL_VECTOR) entries are for traps, so we skip
-        * over them. */
+        * over them.
+        */
        idt = &cpu->arch.idt[FIRST_EXTERNAL_VECTOR+irq];
        /* If they don't have a handler (yet?), we just ignore it */
        if (idt_present(idt->a, idt->b)) {
                /* OK, mark it no longer pending and deliver it. */
                clear_bit(irq, cpu->irqs_pending);
-               /* set_guest_interrupt() takes the interrupt descriptor and a
+               /*
+                * set_guest_interrupt() takes the interrupt descriptor and a
                 * flag to say whether this interrupt pushes an error code onto
-                * the stack as well: virtual interrupts never do. */
+                * the stack as well: virtual interrupts never do.
+                */
                set_guest_interrupt(cpu, idt->a, idt->b, false);
        }
 
-       /* Every time we deliver an interrupt, we update the timestamp in the
+       /*
+        * Every time we deliver an interrupt, we update the timestamp in the
         * Guest's lguest_data struct.  It would be better for the Guest if we
         * did this more often, but it can actually be quite slow: doing it
         * here is a compromise which means at least it gets updated every
-        * timer interrupt. */
+        * timer interrupt.
+        */
        write_timestamp(cpu);
 
-       /* If there are no other interrupts we want to deliver, clear
-        * the pending flag. */
+       /*
+        * If there are no other interrupts we want to deliver, clear
+        * the pending flag.
+        */
        if (!more)
                put_user(0, &cpu->lg->lguest_data->irq_pending);
 }
@@ -217,24 +254,29 @@ void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more)
 /* And this is the routine when we want to set an interrupt for the Guest. */
 void set_interrupt(struct lg_cpu *cpu, unsigned int irq)
 {
-       /* Next time the Guest runs, the core code will see if it can deliver
-        * this interrupt. */
+       /*
+        * Next time the Guest runs, the core code will see if it can deliver
+        * this interrupt.
+        */
        set_bit(irq, cpu->irqs_pending);
 
-       /* Make sure it sees it; it might be asleep (eg. halted), or
-        * running the Guest right now, in which case kick_process()
-        * will knock it out. */
+       /*
+        * Make sure it sees it; it might be asleep (eg. halted), or running
+        * the Guest right now, in which case kick_process() will knock it out.
+        */
        if (!wake_up_process(cpu->tsk))
                kick_process(cpu->tsk);
 }
 /*:*/
 
-/* Linux uses trap 128 for system calls.  Plan9 uses 64, and Ron Minnich sent
+/*
+ * Linux uses trap 128 for system calls.  Plan9 uses 64, and Ron Minnich sent
  * me a patch, so we support that too.  It'd be a big step for lguest if half
  * the Plan 9 user base were to start using it.
  *
  * Actually now I think of it, it's possible that Ron *is* half the Plan 9
- * userbase.  Oh well. */
+ * userbase.  Oh well.
+ */
 static bool could_be_syscall(unsigned int num)
 {
        /* Normal Linux SYSCALL_VECTOR or reserved vector? */
@@ -274,9 +316,11 @@ void free_interrupts(void)
                clear_bit(syscall_vector, used_vectors);
 }
 
-/*H:220 Now we've got the routines to deliver interrupts, delivering traps like
+/*H:220
+ * Now we've got the routines to deliver interrupts, delivering traps like
  * page fault is easy.  The only trick is that Intel decided that some traps
- * should have error codes: */
+ * should have error codes:
+ */
 static bool has_err(unsigned int trap)
 {
        return (trap == 8 || (trap >= 10 && trap <= 14) || trap == 17);
@@ -285,13 +329,17 @@ static bool has_err(unsigned int trap)
 /* deliver_trap() returns true if it could deliver the trap. */
 bool deliver_trap(struct lg_cpu *cpu, unsigned int num)
 {
-       /* Trap numbers are always 8 bit, but we set an impossible trap number
-        * for traps inside the Switcher, so check that here. */
+       /*
+        * Trap numbers are always 8 bit, but we set an impossible trap number
+        * for traps inside the Switcher, so check that here.
+        */
        if (num >= ARRAY_SIZE(cpu->arch.idt))
                return false;
 
-       /* Early on the Guest hasn't set the IDT entries (or maybe it put a
-        * bogus one in): if we fail here, the Guest will be killed. */
+       /*
+        * Early on the Guest hasn't set the IDT entries (or maybe it put a
+        * bogus one in): if we fail here, the Guest will be killed.
+        */
        if (!idt_present(cpu->arch.idt[num].a, cpu->arch.idt[num].b))
                return false;
        set_guest_interrupt(cpu, cpu->arch.idt[num].a,
@@ -299,7 +347,8 @@ bool deliver_trap(struct lg_cpu *cpu, unsigned int num)
        return true;
 }
 
-/*H:250 Here's the hard part: returning to the Host every time a trap happens
+/*H:250
+ * Here's the hard part: returning to the Host every time a trap happens
  * and then calling deliver_trap() and re-entering the Guest is slow.
  * Particularly because Guest userspace system calls are traps (usually trap
  * 128).
@@ -311,69 +360,87 @@ bool deliver_trap(struct lg_cpu *cpu, unsigned int num)
  * the other hypervisors would beat it up at lunchtime.
  *
  * This routine indicates if a particular trap number could be delivered
- * directly. */
+ * directly.
+ */
 static bool direct_trap(unsigned int num)
 {
-       /* Hardware interrupts don't go to the Guest at all (except system
-        * call). */
+       /*
+        * Hardware interrupts don't go to the Guest at all (except system
+        * call).
+        */
        if (num >= FIRST_EXTERNAL_VECTOR && !could_be_syscall(num))
                return false;
 
-       /* The Host needs to see page faults (for shadow paging and to save the
+       /*
+        * The Host needs to see page faults (for shadow paging and to save the
         * fault address), general protection faults (in/out emulation) and
         * device not available (TS handling), invalid opcode fault (kvm hcall),
-        * and of course, the hypercall trap. */
+        * and of course, the hypercall trap.
+        */
        return num != 14 && num != 13 && num != 7 &&
                        num != 6 && num != LGUEST_TRAP_ENTRY;
 }
 /*:*/
 
-/*M:005 The Guest has the ability to turn its interrupt gates into trap gates,
+/*M:005
+ * The Guest has the ability to turn its interrupt gates into trap gates,
  * if it is careful.  The Host will let trap gates can go directly to the
  * Guest, but the Guest needs the interrupts atomically disabled for an
  * interrupt gate.  It can do this by pointing the trap gate at instructions
- * within noirq_start and noirq_end, where it can safely disable interrupts. */
+ * within noirq_start and noirq_end, where it can safely disable interrupts.
+ */
 
-/*M:006 The Guests do not use the sysenter (fast system call) instruction,
+/*M:006
+ * The Guests do not use the sysenter (fast system call) instruction,
  * because it's hardcoded to enter privilege level 0 and so can't go direct.
  * It's about twice as fast as the older "int 0x80" system call, so it might
  * still be worthwhile to handle it in the Switcher and lcall down to the
  * Guest.  The sysenter semantics are hairy tho: search for that keyword in
- * entry.S :*/
+ * entry.S
+:*/
 
-/*H:260 When we make traps go directly into the Guest, we need to make sure
+/*H:260
+ * When we make traps go directly into the Guest, we need to make sure
  * the kernel stack is valid (ie. mapped in the page tables).  Otherwise, the
  * CPU trying to deliver the trap will fault while trying to push the interrupt
  * words on the stack: this is called a double fault, and it forces us to kill
  * the Guest.
  *
- * Which is deeply unfair, because (literally!) it wasn't the Guests' fault. */
+ * Which is deeply unfair, because (literally!) it wasn't the Guests' fault.
+ */
 void pin_stack_pages(struct lg_cpu *cpu)
 {
        unsigned int i;
 
-       /* Depending on the CONFIG_4KSTACKS option, the Guest can have one or
-        * two pages of stack space. */
+       /*
+        * Depending on the CONFIG_4KSTACKS option, the Guest can have one or
+        * two pages of stack space.
+        */
        for (i = 0; i < cpu->lg->stack_pages; i++)
-               /* The stack grows *upwards*, so the address we're given is the
+               /*
+                * The stack grows *upwards*, so the address we're given is the
                 * start of the page after the kernel stack.  Subtract one to
                 * get back onto the first stack page, and keep subtracting to
-                * get to the rest of the stack pages. */
+                * get to the rest of the stack pages.
+                */
                pin_page(cpu, cpu->esp1 - 1 - i * PAGE_SIZE);
 }
 
-/* Direct traps also mean that we need to know whenever the Guest wants to use
+/*
+ * Direct traps also mean that we need to know whenever the Guest wants to use
  * a different kernel stack, so we can change the IDT entries to use that
  * stack.  The IDT entries expect a virtual address, so unlike most addresses
  * the Guest gives us, the "esp" (stack pointer) value here is virtual, not
  * physical.
  *
  * In Linux each process has its own kernel stack, so this happens a lot: we
- * change stacks on each context switch. */
+ * change stacks on each context switch.
+ */
 void guest_set_stack(struct lg_cpu *cpu, u32 seg, u32 esp, unsigned int pages)
 {
-       /* You are not allowed have a stack segment with privilege level 0: bad
-        * Guest! */
+       /*
+        * You're not allowed a stack segment with privilege level 0: bad Guest!
+        */
        if ((seg & 0x3) != GUEST_PL)
                kill_guest(cpu, "bad stack segment %i", seg);
        /* We only expect one or two stack pages. */
@@ -387,11 +454,15 @@ void guest_set_stack(struct lg_cpu *cpu, u32 seg, u32 esp, unsigned int pages)
        pin_stack_pages(cpu);
 }
 
-/* All this reference to mapping stacks leads us neatly into the other complex
- * part of the Host: page table handling. */
+/*
+ * All this reference to mapping stacks leads us neatly into the other complex
+ * part of the Host: page table handling.
+ */
 
-/*H:235 This is the routine which actually checks the Guest's IDT entry and
- * transfers it into the entry in "struct lguest": */
+/*H:235
+ * This is the routine which actually checks the Guest's IDT entry and
+ * transfers it into the entry in "struct lguest":
+ */
 static void set_trap(struct lg_cpu *cpu, struct desc_struct *trap,
                     unsigned int num, u32 lo, u32 hi)
 {
@@ -407,30 +478,38 @@ static void set_trap(struct lg_cpu *cpu, struct desc_struct *trap,
        if (type != 0xE && type != 0xF)
                kill_guest(cpu, "bad IDT type %i", type);
 
-       /* We only copy the handler address, present bit, privilege level and
+       /*
+        * We only copy the handler address, present bit, privilege level and
         * type.  The privilege level controls where the trap can be triggered
         * manually with an "int" instruction.  This is usually GUEST_PL,
-        * except for system calls which userspace can use. */
+        * except for system calls which userspace can use.
+        */
        trap->a = ((__KERNEL_CS|GUEST_PL)<<16) | (lo&0x0000FFFF);
        trap->b = (hi&0xFFFFEF00);
 }
 
-/*H:230 While we're here, dealing with delivering traps and interrupts to the
+/*H:230
+ * While we're here, dealing with delivering traps and interrupts to the
  * Guest, we might as well complete the picture: how the Guest tells us where
  * it wants them to go.  This would be simple, except making traps fast
  * requires some tricks.
  *
  * We saw the Guest setting Interrupt Descriptor Table (IDT) entries with the
- * LHCALL_LOAD_IDT_ENTRY hypercall before: that comes here. */
+ * LHCALL_LOAD_IDT_ENTRY hypercall before: that comes here.
+ */
 void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int num, u32 lo, u32 hi)
 {
-       /* Guest never handles: NMI, doublefault, spurious interrupt or
-        * hypercall.  We ignore when it tries to set them. */
+       /*
+        * Guest never handles: NMI, doublefault, spurious interrupt or
+        * hypercall.  We ignore when it tries to set them.
+        */
        if (num == 2 || num == 8 || num == 15 || num == LGUEST_TRAP_ENTRY)
                return;
 
-       /* Mark the IDT as changed: next time the Guest runs we'll know we have
-        * to copy this again. */
+       /*
+        * Mark the IDT as changed: next time the Guest runs we'll know we have
+        * to copy this again.
+        */
        cpu->changed |= CHANGED_IDT;
 
        /* Check that the Guest doesn't try to step outside the bounds. */
@@ -440,9 +519,11 @@ void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int num, u32 lo, u32 hi)
                set_trap(cpu, &cpu->arch.idt[num], num, lo, hi);
 }
 
-/* The default entry for each interrupt points into the Switcher routines which
+/*
+ * The default entry for each interrupt points into the Switcher routines which
  * simply return to the Host.  The run_guest() loop will then call
- * deliver_trap() to bounce it back into the Guest. */
+ * deliver_trap() to bounce it back into the Guest.
+ */
 static void default_idt_entry(struct desc_struct *idt,
                              int trap,
                              const unsigned long handler,
@@ -451,13 +532,17 @@ static void default_idt_entry(struct desc_struct *idt,
        /* A present interrupt gate. */
        u32 flags = 0x8e00;
 
-       /* Set the privilege level on the entry for the hypercall: this allows
-        * the Guest to use the "int" instruction to trigger it. */
+       /*
+        * Set the privilege level on the entry for the hypercall: this allows
+        * the Guest to use the "int" instruction to trigger it.
+        */
        if (trap == LGUEST_TRAP_ENTRY)
                flags |= (GUEST_PL << 13);
        else if (base)
-               /* Copy priv. level from what Guest asked for.  This allows
-                * debug (int 3) traps from Guest userspace, for example. */
+               /*
+                * Copy privilege level from what Guest asked for.  This allows
+                * debug (int 3) traps from Guest userspace, for example.
+                */
                flags |= (base->b & 0x6000);
 
        /* Now pack it into the IDT entry in its weird format. */
@@ -475,16 +560,20 @@ void setup_default_idt_entries(struct lguest_ro_state *state,
                default_idt_entry(&state->guest_idt[i], i, def[i], NULL);
 }
 
-/*H:240 We don't use the IDT entries in the "struct lguest" directly, instead
+/*H:240
+ * We don't use the IDT entries in the "struct lguest" directly, instead
  * we copy them into the IDT which we've set up for Guests on this CPU, just
- * before we run the Guest.  This routine does that copy. */
+ * before we run the Guest.  This routine does that copy.
+ */
 void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
                const unsigned long *def)
 {
        unsigned int i;
 
-       /* We can simply copy the direct traps, otherwise we use the default
-        * ones in the Switcher: they will return to the Host. */
+       /*
+        * We can simply copy the direct traps, otherwise we use the default
+        * ones in the Switcher: they will return to the Host.
+        */
        for (i = 0; i < ARRAY_SIZE(cpu->arch.idt); i++) {
                const struct desc_struct *gidt = &cpu->arch.idt[i];
 
@@ -492,14 +581,16 @@ void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
                if (!direct_trap(i))
                        continue;
 
-               /* Only trap gates (type 15) can go direct to the Guest.
+               /*
+                * Only trap gates (type 15) can go direct to the Guest.
                 * Interrupt gates (type 14) disable interrupts as they are
                 * entered, which we never let the Guest do.  Not present
                 * entries (type 0x0) also can't go direct, of course.
                 *
                 * If it can't go direct, we still need to copy the priv. level:
                 * they might want to give userspace access to a software
-                * interrupt. */
+                * interrupt.
+                */
                if (idt_type(gidt->a, gidt->b) == 0xF)
                        idt[i] = *gidt;
                else
@@ -518,7 +609,8 @@ void copy_traps(const struct lg_cpu *cpu, struct desc_struct *idt,
  * the next timer interrupt (in nanoseconds).  We use the high-resolution timer
  * infrastructure to set a callback at that time.
  *
- * 0 means "turn off the clock". */
+ * 0 means "turn off the clock".
+ */
 void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta)
 {
        ktime_t expires;
@@ -529,9 +621,11 @@ void guest_set_clockevent(struct lg_cpu *cpu, unsigned long delta)
                return;
        }
 
-       /* We use wallclock time here, so the Guest might not be running for
+       /*
+        * We use wallclock time here, so the Guest might not be running for
         * all the time between now and the timer interrupt it asked for.  This
-        * is almost always the right thing to do. */
+        * is almost always the right thing to do.
+        */
        expires = ktime_add_ns(ktime_get_real(), delta);
        hrtimer_start(&cpu->hrt, expires, HRTIMER_MODE_ABS);
 }
index d4e8979735cb002f9f97cf929a1b45a900f2ddc6..bc28745d05af9794f756a5a29e64bb0b51a230ff 100644 (file)
 void free_pagetables(void);
 int init_pagetables(struct page **switcher_page, unsigned int pages);
 
-struct pgdir
-{
+struct pgdir {
        unsigned long gpgdir;
        pgd_t *pgdir;
 };
 
 /* We have two pages shared with guests, per cpu.  */
-struct lguest_pages
-{
+struct lguest_pages {
        /* This is the stack page mapped rw in guest */
        char spare[PAGE_SIZE - sizeof(struct lguest_regs)];
        struct lguest_regs regs;
@@ -38,8 +36,6 @@ struct lguest_pages
 #define CHANGED_GDT_TLS                4 /* Actually a subset of CHANGED_GDT */
 #define CHANGED_ALL            3
 
-struct lguest;
-
 struct lg_cpu {
        unsigned int id;
        struct lguest *lg;
@@ -56,13 +52,13 @@ struct lg_cpu {
 
        unsigned long pending_notify; /* pfn from LHCALL_NOTIFY */
 
-       /* At end of a page shared mapped over lguest_pages in guest.  */
+       /* At end of a page shared mapped over lguest_pages in guest. */
        unsigned long regs_page;
        struct lguest_regs *regs;
 
        struct lguest_pages *last_pages;
 
-       int cpu_pgd; /* which pgd this cpu is currently using */
+       int cpu_pgd; /* Which pgd this cpu is currently using */
 
        /* If a hypercall was asked for, this points to the arguments. */
        struct hcall_args *hcall;
@@ -82,7 +78,7 @@ struct lg_cpu {
 
 struct lg_eventfd {
        unsigned long addr;
-       struct file *event;
+       struct eventfd_ctx *event;
 };
 
 struct lg_eventfd_map {
@@ -91,15 +87,17 @@ struct lg_eventfd_map {
 };
 
 /* The private info the thread maintains about the guest. */
-struct lguest
-{
+struct lguest {
        struct lguest_data __user *lguest_data;
        struct lg_cpu cpus[NR_CPUS];
        unsigned int nr_cpus;
 
        u32 pfn_limit;
-       /* This provides the offset to the base of guest-physical
-        * memory in the Launcher. */
+
+       /*
+        * This provides the offset to the base of guest-physical memory in the
+        * Launcher.
+        */
        void __user *mem_base;
        unsigned long kernel_address;
 
@@ -124,11 +122,13 @@ bool lguest_address_ok(const struct lguest *lg,
 void __lgread(struct lg_cpu *, void *, unsigned long, unsigned);
 void __lgwrite(struct lg_cpu *, unsigned long, const void *, unsigned);
 
-/*H:035 Using memory-copy operations like that is usually inconvient, so we
+/*H:035
+ * Using memory-copy operations like that is usually inconvient, so we
  * have the following helper macros which read and write a specific type (often
  * an unsigned long).
  *
- * This reads into a variable of the given type then returns that. */
+ * This reads into a variable of the given type then returns that.
+ */
 #define lgread(cpu, addr, type)                                                \
        ({ type _v; __lgread((cpu), &_v, (addr), sizeof(_v)); _v; })
 
@@ -142,9 +142,11 @@ void __lgwrite(struct lg_cpu *, unsigned long, const void *, unsigned);
 
 int run_guest(struct lg_cpu *cpu, unsigned long __user *user);
 
-/* Helper macros to obtain the first 12 or the last 20 bits, this is only the
+/*
+ * Helper macros to obtain the first 12 or the last 20 bits, this is only the
  * first step in the migration to the kernel types.  pte_pfn is already defined
- * in the kernel. */
+ * in the kernel.
+ */
 #define pgd_flags(x)   (pgd_val(x) & ~PAGE_MASK)
 #define pgd_pfn(x)     (pgd_val(x) >> PAGE_SHIFT)
 #define pmd_flags(x)    (pmd_val(x) & ~PAGE_MASK)
index e082cdac88b4bb283f41ebb611671d583ca78ecb..b6200bc39b5814460c4a7e451d63c680e593e1f7 100644 (file)
@@ -1,10 +1,12 @@
-/*P:050 Lguest guests use a very simple method to describe devices.  It's a
+/*P:050
+ * Lguest guests use a very simple method to describe devices.  It's a
  * series of device descriptors contained just above the top of normal Guest
  * memory.
  *
  * We use the standard "virtio" device infrastructure, which provides us with a
  * console, a network and a block driver.  Each one expects some configuration
- * information and a "virtqueue" or two to send and receive data. :*/
+ * information and a "virtqueue" or two to send and receive data.
+:*/
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/lguest_launcher.h>
 /* The pointer to our (page) of device descriptions. */
 static void *lguest_devices;
 
-/* For Guests, device memory can be used as normal memory, so we cast away the
- * __iomem to quieten sparse. */
+/*
+ * For Guests, device memory can be used as normal memory, so we cast away the
+ * __iomem to quieten sparse.
+ */
 static inline void *lguest_map(unsigned long phys_addr, unsigned long pages)
 {
        return (__force void *)ioremap_cache(phys_addr, PAGE_SIZE*pages);
@@ -32,8 +36,10 @@ static inline void lguest_unmap(void *addr)
        iounmap((__force void __iomem *)addr);
 }
 
-/*D:100 Each lguest device is just a virtio device plus a pointer to its entry
- * in the lguest_devices page. */
+/*D:100
+ * Each lguest device is just a virtio device plus a pointer to its entry
+ * in the lguest_devices page.
+ */
 struct lguest_device {
        struct virtio_device vdev;
 
@@ -41,9 +47,11 @@ struct lguest_device {
        struct lguest_device_desc *desc;
 };
 
-/* Since the virtio infrastructure hands us a pointer to the virtio_device all
+/*
+ * Since the virtio infrastructure hands us a pointer to the virtio_device all
  * the time, it helps to have a curt macro to get a pointer to the struct
- * lguest_device it's enclosed in.  */
+ * lguest_device it's enclosed in.
+ */
 #define to_lgdev(vd) container_of(vd, struct lguest_device, vdev)
 
 /*D:130
@@ -55,7 +63,8 @@ struct lguest_device {
  * the driver will look at them during setup.
  *
  * A convenient routine to return the device's virtqueue config array:
- * immediately after the descriptor. */
+ * immediately after the descriptor.
+ */
 static struct lguest_vqconfig *lg_vq(const struct lguest_device_desc *desc)
 {
        return (void *)(desc + 1);
@@ -98,10 +107,12 @@ static u32 lg_get_features(struct virtio_device *vdev)
        return features;
 }
 
-/* The virtio core takes the features the Host offers, and copies the
- * ones supported by the driver into the vdev->features array.  Once
- * that's all sorted out, this routine is called so we can tell the
- * Host which features we understand and accept. */
+/*
+ * The virtio core takes the features the Host offers, and copies the ones
+ * supported by the driver into the vdev->features array.  Once that's all
+ * sorted out, this routine is called so we can tell the Host which features we
+ * understand and accept.
+ */
 static void lg_finalize_features(struct virtio_device *vdev)
 {
        unsigned int i, bits;
@@ -112,10 +123,11 @@ static void lg_finalize_features(struct virtio_device *vdev)
        /* Give virtio_ring a chance to accept features. */
        vring_transport_features(vdev);
 
-       /* The vdev->feature array is a Linux bitmask: this isn't the
-        * same as a the simple array of bits used by lguest devices
-        * for features.  So we do this slow, manual conversion which is
-        * completely general. */
+       /*
+        * The vdev->feature array is a Linux bitmask: this isn't the same as a
+        * the simple array of bits used by lguest devices for features.  So we
+        * do this slow, manual conversion which is completely general.
+        */
        memset(out_features, 0, desc->feature_len);
        bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8;
        for (i = 0; i < bits; i++) {
@@ -146,15 +158,19 @@ static void lg_set(struct virtio_device *vdev, unsigned int offset,
        memcpy(lg_config(desc) + offset, buf, len);
 }
 
-/* The operations to get and set the status word just access the status field
- * of the device descriptor. */
+/*
+ * The operations to get and set the status word just access the status field
+ * of the device descriptor.
+ */
 static u8 lg_get_status(struct virtio_device *vdev)
 {
        return to_lgdev(vdev)->desc->status;
 }
 
-/* To notify on status updates, we (ab)use the NOTIFY hypercall, with the
- * descriptor address of the device.  A zero status means "reset". */
+/*
+ * To notify on status updates, we (ab)use the NOTIFY hypercall, with the
+ * descriptor address of the device.  A zero status means "reset".
+ */
 static void set_status(struct virtio_device *vdev, u8 status)
 {
        unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
@@ -191,8 +207,7 @@ static void lg_reset(struct virtio_device *vdev)
  */
 
 /*D:140 This is the information we remember about each virtqueue. */
-struct lguest_vq_info
-{
+struct lguest_vq_info {
        /* A copy of the information contained in the device config. */
        struct lguest_vqconfig config;
 
@@ -200,13 +215,17 @@ struct lguest_vq_info
        void *pages;
 };
 
-/* When the virtio_ring code wants to prod the Host, it calls us here and we
+/*
+ * When the virtio_ring code wants to prod the Host, it calls us here and we
  * make a hypercall.  We hand the physical address of the virtqueue so the Host
- * knows which virtqueue we're talking about. */
+ * knows which virtqueue we're talking about.
+ */
 static void lg_notify(struct virtqueue *vq)
 {
-       /* We store our virtqueue information in the "priv" pointer of the
-        * virtqueue structure. */
+       /*
+        * We store our virtqueue information in the "priv" pointer of the
+        * virtqueue structure.
+        */
        struct lguest_vq_info *lvq = vq->priv;
 
        kvm_hypercall1(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT);
@@ -215,7 +234,8 @@ static void lg_notify(struct virtqueue *vq)
 /* An extern declaration inside a C file is bad form.  Don't do it. */
 extern void lguest_setup_irq(unsigned int irq);
 
-/* This routine finds the first virtqueue described in the configuration of
+/*
+ * This routine finds the Nth virtqueue described in the configuration of
  * this device and sets it up.
  *
  * This is kind of an ugly duckling.  It'd be nicer to have a standard
@@ -223,9 +243,7 @@ extern void lguest_setup_irq(unsigned int irq);
  * everyone wants to do it differently.  The KVM coders want the Guest to
  * allocate its own pages and tell the Host where they are, but for lguest it's
  * simpler for the Host to simply tell us where the pages are.
- *
- * So we provide drivers with a "find the Nth virtqueue and set it up"
- * function. */
+ */
 static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
                                    unsigned index,
                                    void (*callback)(struct virtqueue *vq),
@@ -244,9 +262,11 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
        if (!lvq)
                return ERR_PTR(-ENOMEM);
 
-       /* Make a copy of the "struct lguest_vqconfig" entry, which sits after
+       /*
+        * Make a copy of the "struct lguest_vqconfig" entry, which sits after
         * the descriptor.  We need a copy because the config space might not
-        * be aligned correctly. */
+        * be aligned correctly.
+        */
        memcpy(&lvq->config, lg_vq(ldev->desc)+index, sizeof(lvq->config));
 
        printk("Mapping virtqueue %i addr %lx\n", index,
@@ -261,8 +281,10 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
                goto free_lvq;
        }
 
-       /* OK, tell virtio_ring.c to set up a virtqueue now we know its size
-        * and we've got a pointer to its pages. */
+       /*
+        * OK, tell virtio_ring.c to set up a virtqueue now we know its size
+        * and we've got a pointer to its pages.
+        */
        vq = vring_new_virtqueue(lvq->config.num, LGUEST_VRING_ALIGN,
                                 vdev, lvq->pages, lg_notify, callback, name);
        if (!vq) {
@@ -273,18 +295,23 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
        /* Make sure the interrupt is allocated. */
        lguest_setup_irq(lvq->config.irq);
 
-       /* Tell the interrupt for this virtqueue to go to the virtio_ring
-        * interrupt handler. */
-       /* FIXME: We used to have a flag for the Host to tell us we could use
+       /*
+        * Tell the interrupt for this virtqueue to go to the virtio_ring
+        * interrupt handler.
+        *
+        * FIXME: We used to have a flag for the Host to tell us we could use
         * the interrupt as a source of randomness: it'd be nice to have that
-        * back.. */
+        * back.
+        */
        err = request_irq(lvq->config.irq, vring_interrupt, IRQF_SHARED,
                          dev_name(&vdev->dev), vq);
        if (err)
                goto destroy_vring;
 
-       /* Last of all we hook up our 'struct lguest_vq_info" to the
-        * virtqueue's priv pointer. */
+       /*
+        * Last of all we hook up our 'struct lguest_vq_info" to the
+        * virtqueue's priv pointer.
+        */
        vq->priv = lvq;
        return vq;
 
@@ -358,11 +385,14 @@ static struct virtio_config_ops lguest_config_ops = {
        .del_vqs = lg_del_vqs,
 };
 
-/* The root device for the lguest virtio devices.  This makes them appear as
- * /sys/devices/lguest/0,1,2 not /sys/devices/0,1,2. */
+/*
+ * The root device for the lguest virtio devices.  This makes them appear as
+ * /sys/devices/lguest/0,1,2 not /sys/devices/0,1,2.
+ */
 static struct device *lguest_root;
 
-/*D:120 This is the core of the lguest bus: actually adding a new device.
+/*D:120
+ * This is the core of the lguest bus: actually adding a new device.
  * It's a separate function because it's neater that way, and because an
  * earlier version of the code supported hotplug and unplug.  They were removed
  * early on because they were never used.
@@ -371,14 +401,14 @@ static struct device *lguest_root;
  *
  * It's worth reading this carefully: we start with a pointer to the new device
  * descriptor in the "lguest_devices" page, and the offset into the device
- * descriptor page so we can uniquely identify it if things go badly wrong. */
+ * descriptor page so we can uniquely identify it if things go badly wrong.
+ */
 static void add_lguest_device(struct lguest_device_desc *d,
                              unsigned int offset)
 {
        struct lguest_device *ldev;
 
-       /* Start with zeroed memory; Linux's device layer seems to count on
-        * it. */
+       /* Start with zeroed memory; Linux's device layer counts on it. */
        ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
        if (!ldev) {
                printk(KERN_EMERG "Cannot allocate lguest dev %u type %u\n",
@@ -388,17 +418,25 @@ static void add_lguest_device(struct lguest_device_desc *d,
 
        /* This devices' parent is the lguest/ dir. */
        ldev->vdev.dev.parent = lguest_root;
-       /* We have a unique device index thanks to the dev_index counter. */
+       /*
+        * The device type comes straight from the descriptor.  There's also a
+        * device vendor field in the virtio_device struct, which we leave as
+        * 0.
+        */
        ldev->vdev.id.device = d->type;
-       /* We have a simple set of routines for querying the device's
-        * configuration information and setting its status. */
+       /*
+        * We have a simple set of routines for querying the device's
+        * configuration information and setting its status.
+        */
        ldev->vdev.config = &lguest_config_ops;
        /* And we remember the device's descriptor for lguest_config_ops. */
        ldev->desc = d;
 
-       /* register_virtio_device() sets up the generic fields for the struct
+       /*
+        * register_virtio_device() sets up the generic fields for the struct
         * virtio_device and calls device_register().  This makes the bus
-        * infrastructure look for a matching driver. */
+        * infrastructure look for a matching driver.
+        */
        if (register_virtio_device(&ldev->vdev) != 0) {
                printk(KERN_ERR "Failed to register lguest dev %u type %u\n",
                       offset, d->type);
@@ -406,8 +444,10 @@ static void add_lguest_device(struct lguest_device_desc *d,
        }
 }
 
-/*D:110 scan_devices() simply iterates through the device page.  The type 0 is
- * reserved to mean "end of devices". */
+/*D:110
+ * scan_devices() simply iterates through the device page.  The type 0 is
+ * reserved to mean "end of devices".
+ */
 static void scan_devices(void)
 {
        unsigned int i;
@@ -426,7 +466,8 @@ static void scan_devices(void)
        }
 }
 
-/*D:105 Fairly early in boot, lguest_devices_init() is called to set up the
+/*D:105
+ * Fairly early in boot, lguest_devices_init() is called to set up the
  * lguest device infrastructure.  We check that we are a Guest by checking
  * pv_info.name: there are other ways of checking, but this seems most
  * obvious to me.
@@ -437,7 +478,8 @@ static void scan_devices(void)
  * correct sysfs incantation).
  *
  * Finally we call scan_devices() which adds all the devices found in the
- * lguest_devices page. */
+ * lguest_devices page.
+ */
 static int __init lguest_devices_init(void)
 {
        if (strcmp(pv_info.name, "lguest") != 0)
@@ -456,11 +498,13 @@ static int __init lguest_devices_init(void)
 /* We do this after core stuff, but before the drivers. */
 postcore_initcall(lguest_devices_init);
 
-/*D:150 At this point in the journey we used to now wade through the lguest
+/*D:150
+ * At this point in the journey we used to now wade through the lguest
  * devices themselves: net, block and console.  Since they're all now virtio
  * devices rather than lguest-specific, I've decided to ignore them.  Mostly,
  * they're kind of boring.  But this does mean you'll never experience the
  * thrill of reading the forbidden love scene buried deep in the block driver.
  *
  * "make Launcher" beckons, where we answer questions like "Where do Guests
- * come from?", and "What do you do when someone asks for optimization?". */
+ * come from?", and "What do you do when someone asks for optimization?".
+ */
index 32e297121058a3d7dc52fbd6d347eab496c08252..b4d3f7ca554f0d8e81be09a02d824fb4f84cb978 100644 (file)
@@ -1,8 +1,9 @@
 /*P:200 This contains all the /dev/lguest code, whereby the userspace launcher
  * controls and communicates with the Guest.  For example, the first write will
- * tell us the Guest's memory layout, pagetable, entry point and kernel address
- * offset.  A read will run the Guest until something happens, such as a signal
- * or the Guest doing a NOTIFY out to the Launcher. :*/
+ * tell us the Guest's memory layout and entry point.  A read will run the
+ * Guest until something happens, such as a signal or the Guest doing a NOTIFY
+ * out to the Launcher.
+:*/
 #include <linux/uaccess.h>
 #include <linux/miscdevice.h>
 #include <linux/fs.h>
 #include <linux/file.h>
 #include "lg.h"
 
+/*L:056
+ * Before we move on, let's jump ahead and look at what the kernel does when
+ * it needs to look up the eventfds.  That will complete our picture of how we
+ * use RCU.
+ *
+ * The notification value is in cpu->pending_notify: we return true if it went
+ * to an eventfd.
+ */
 bool send_notify_to_eventfd(struct lg_cpu *cpu)
 {
        unsigned int i;
        struct lg_eventfd_map *map;
 
-       /* lg->eventfds is RCU-protected */
+       /*
+        * This "rcu_read_lock()" helps track when someone is still looking at
+        * the (RCU-using) eventfds array.  It's not actually a lock at all;
+        * indeed it's a noop in many configurations.  (You didn't expect me to
+        * explain all the RCU secrets here, did you?)
+        */
        rcu_read_lock();
+       /*
+        * rcu_dereference is the counter-side of rcu_assign_pointer(); it
+        * makes sure we don't access the memory pointed to by
+        * cpu->lg->eventfds before cpu->lg->eventfds is set.  Sounds crazy,
+        * but Alpha allows this!  Paul McKenney points out that a really
+        * aggressive compiler could have the same effect:
+        *   http://lists.ozlabs.org/pipermail/lguest/2009-July/001560.html
+        *
+        * So play safe, use rcu_dereference to get the rcu-protected pointer:
+        */
        map = rcu_dereference(cpu->lg->eventfds);
+       /*
+        * Simple array search: even if they add an eventfd while we do this,
+        * we'll continue to use the old array and just won't see the new one.
+        */
        for (i = 0; i < map->num; i++) {
                if (map->map[i].addr == cpu->pending_notify) {
                        eventfd_signal(map->map[i].event, 1);
@@ -26,19 +54,50 @@ bool send_notify_to_eventfd(struct lg_cpu *cpu)
                        break;
                }
        }
+       /* We're done with the rcu-protected variable cpu->lg->eventfds. */
        rcu_read_unlock();
+
+       /* If we cleared the notification, it's because we found a match. */
        return cpu->pending_notify == 0;
 }
 
+/*L:055
+ * One of the more tricksy tricks in the Linux Kernel is a technique called
+ * Read Copy Update.  Since one point of lguest is to teach lguest journeyers
+ * about kernel coding, I use it here.  (In case you're curious, other purposes
+ * include learning about virtualization and instilling a deep appreciation for
+ * simplicity and puppies).
+ *
+ * We keep a simple array which maps LHCALL_NOTIFY values to eventfds, but we
+ * add new eventfds without ever blocking readers from accessing the array.
+ * The current Launcher only does this during boot, so that never happens.  But
+ * Read Copy Update is cool, and adding a lock risks damaging even more puppies
+ * than this code does.
+ *
+ * We allocate a brand new one-larger array, copy the old one and add our new
+ * element.  Then we make the lg eventfd pointer point to the new array.
+ * That's the easy part: now we need to free the old one, but we need to make
+ * sure no slow CPU somewhere is still looking at it.  That's what
+ * synchronize_rcu does for us: waits until every CPU has indicated that it has
+ * moved on to know it's no longer using the old one.
+ *
+ * If that's unclear, see http://en.wikipedia.org/wiki/Read-copy-update.
+ */
 static int add_eventfd(struct lguest *lg, unsigned long addr, int fd)
 {
        struct lg_eventfd_map *new, *old = lg->eventfds;
 
+       /*
+        * We don't allow notifications on value 0 anyway (pending_notify of
+        * 0 means "nothing pending").
+        */
        if (!addr)
                return -EINVAL;
 
-       /* Replace the old array with the new one, carefully: others can
-        * be accessing it at the same time */
+       /*
+        * Replace the old array with the new one, carefully: others can
+        * be accessing it at the same time.
+        */
        new = kmalloc(sizeof(*new) + sizeof(new->map[0]) * (old->num + 1),
                      GFP_KERNEL);
        if (!new)
@@ -50,24 +109,43 @@ static int add_eventfd(struct lguest *lg, unsigned long addr, int fd)
 
        /* Now append new entry. */
        new->map[new->num].addr = addr;
-       new->map[new->num].event = eventfd_fget(fd);
+       new->map[new->num].event = eventfd_ctx_fdget(fd);
        if (IS_ERR(new->map[new->num].event)) {
+               int err =  PTR_ERR(new->map[new->num].event);
                kfree(new);
-               return PTR_ERR(new->map[new->num].event);
+               return err;
        }
        new->num++;
 
-       /* Now put new one in place. */
+       /*
+        * Now put new one in place: rcu_assign_pointer() is a fancy way of
+        * doing "lg->eventfds = new", but it uses memory barriers to make
+        * absolutely sure that the contents of "new" written above is nailed
+        * down before we actually do the assignment.
+        *
+        * We have to think about these kinds of things when we're operating on
+        * live data without locks.
+        */
        rcu_assign_pointer(lg->eventfds, new);
 
-       /* We're not in a big hurry.  Wait until noone's looking at old
-        * version, then delete it. */
+       /*
+        * We're not in a big hurry.  Wait until noone's looking at old
+        * version, then free it.
+        */
        synchronize_rcu();
        kfree(old);
 
        return 0;
 }
 
+/*L:052
+ * Receiving notifications from the Guest is usually done by attaching a
+ * particular LHCALL_NOTIFY value to an event filedescriptor.  The eventfd will
+ * become readable when the Guest does an LHCALL_NOTIFY with that value.
+ *
+ * This is really convenient for processing each virtqueue in a separate
+ * thread.
+ */
 static int attach_eventfd(struct lguest *lg, const unsigned long __user *input)
 {
        unsigned long addr, fd;
@@ -79,15 +157,22 @@ static int attach_eventfd(struct lguest *lg, const unsigned long __user *input)
        if (get_user(fd, input) != 0)
                return -EFAULT;
 
+       /*
+        * Just make sure two callers don't add eventfds at once.  We really
+        * only need to lock against callers adding to the same Guest, so using
+        * the Big Lguest Lock is overkill.  But this is setup, not a fast path.
+        */
        mutex_lock(&lguest_lock);
        err = add_eventfd(lg, addr, fd);
        mutex_unlock(&lguest_lock);
 
-       return 0;
+       return err;
 }
 
-/*L:050 Sending an interrupt is done by writing LHREQ_IRQ and an interrupt
- * number to /dev/lguest. */
+/*L:050
+ * Sending an interrupt is done by writing LHREQ_IRQ and an interrupt
+ * number to /dev/lguest.
+ */
 static int user_send_irq(struct lg_cpu *cpu, const unsigned long __user *input)
 {
        unsigned long irq;
@@ -97,12 +182,18 @@ static int user_send_irq(struct lg_cpu *cpu, const unsigned long __user *input)
        if (irq >= LGUEST_IRQS)
                return -EINVAL;
 
+       /*
+        * Next time the Guest runs, the core code will see if it can deliver
+        * this interrupt.
+        */
        set_interrupt(cpu, irq);
        return 0;
 }
 
-/*L:040 Once our Guest is initialized, the Launcher makes it run by reading
- * from /dev/lguest. */
+/*L:040
+ * Once our Guest is initialized, the Launcher makes it run by reading
+ * from /dev/lguest.
+ */
 static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o)
 {
        struct lguest *lg = file->private_data;
@@ -138,8 +229,10 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o)
                return len;
        }
 
-       /* If we returned from read() last time because the Guest sent I/O,
-        * clear the flag. */
+       /*
+        * If we returned from read() last time because the Guest sent I/O,
+        * clear the flag.
+        */
        if (cpu->pending_notify)
                cpu->pending_notify = 0;
 
@@ -147,8 +240,10 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o)
        return run_guest(cpu, (unsigned long __user *)user);
 }
 
-/*L:025 This actually initializes a CPU.  For the moment, a Guest is only
- * uniprocessor, so "id" is always 0. */
+/*L:025
+ * This actually initializes a CPU.  For the moment, a Guest is only
+ * uniprocessor, so "id" is always 0.
+ */
 static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
 {
        /* We have a limited number the number of CPUs in the lguest struct. */
@@ -163,8 +258,10 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
        /* Each CPU has a timer it can set. */
        init_clockdev(cpu);
 
-       /* We need a complete page for the Guest registers: they are accessible
-        * to the Guest and we can only grant it access to whole pages. */
+       /*
+        * We need a complete page for the Guest registers: they are accessible
+        * to the Guest and we can only grant it access to whole pages.
+        */
        cpu->regs_page = get_zeroed_page(GFP_KERNEL);
        if (!cpu->regs_page)
                return -ENOMEM;
@@ -172,29 +269,38 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
        /* We actually put the registers at the bottom of the page. */
        cpu->regs = (void *)cpu->regs_page + PAGE_SIZE - sizeof(*cpu->regs);
 
-       /* Now we initialize the Guest's registers, handing it the start
-        * address. */
+       /*
+        * Now we initialize the Guest's registers, handing it the start
+        * address.
+        */
        lguest_arch_setup_regs(cpu, start_ip);
 
-       /* We keep a pointer to the Launcher task (ie. current task) for when
-        * other Guests want to wake this one (eg. console input). */
+       /*
+        * We keep a pointer to the Launcher task (ie. current task) for when
+        * other Guests want to wake this one (eg. console input).
+        */
        cpu->tsk = current;
 
-       /* We need to keep a pointer to the Launcher's memory map, because if
+       /*
+        * We need to keep a pointer to the Launcher's memory map, because if
         * the Launcher dies we need to clean it up.  If we don't keep a
-        * reference, it is destroyed before close() is called. */
+        * reference, it is destroyed before close() is called.
+        */
        cpu->mm = get_task_mm(cpu->tsk);
 
-       /* We remember which CPU's pages this Guest used last, for optimization
-        * when the same Guest runs on the same CPU twice. */
+       /*
+        * We remember which CPU's pages this Guest used last, for optimization
+        * when the same Guest runs on the same CPU twice.
+        */
        cpu->last_pages = NULL;
 
        /* No error == success. */
        return 0;
 }
 
-/*L:020 The initialization write supplies 3 pointer sized (32 or 64 bit)
- * values (in addition to the LHREQ_INITIALIZE value).  These are:
+/*L:020
+ * The initialization write supplies 3 pointer sized (32 or 64 bit) values (in
+ * addition to the LHREQ_INITIALIZE value).  These are:
  *
  * base: The start of the Guest-physical memory inside the Launcher memory.
  *
@@ -206,14 +312,15 @@ static int lg_cpu_start(struct lg_cpu *cpu, unsigned id, unsigned long start_ip)
  */
 static int initialize(struct file *file, const unsigned long __user *input)
 {
-       /* "struct lguest" contains everything we (the Host) know about a
-        * Guest. */
+       /* "struct lguest" contains all we (the Host) know about a Guest. */
        struct lguest *lg;
        int err;
        unsigned long args[3];
 
-       /* We grab the Big Lguest lock, which protects against multiple
-        * simultaneous initializations. */
+       /*
+        * We grab the Big Lguest lock, which protects against multiple
+        * simultaneous initializations.
+        */
        mutex_lock(&lguest_lock);
        /* You can't initialize twice!  Close the device and start again... */
        if (file->private_data) {
@@ -248,8 +355,10 @@ static int initialize(struct file *file, const unsigned long __user *input)
        if (err)
                goto free_eventfds;
 
-       /* Initialize the Guest's shadow page tables, using the toplevel
-        * address the Launcher gave us.  This allocates memory, so can fail. */
+       /*
+        * Initialize the Guest's shadow page tables, using the toplevel
+        * address the Launcher gave us.  This allocates memory, so can fail.
+        */
        err = init_guest_pagetable(lg);
        if (err)
                goto free_regs;
@@ -274,20 +383,24 @@ unlock:
        return err;
 }
 
-/*L:010 The first operation the Launcher does must be a write.  All writes
+/*L:010
+ * The first operation the Launcher does must be a write.  All writes
  * start with an unsigned long number: for the first write this must be
  * LHREQ_INITIALIZE to set up the Guest.  After that the Launcher can use
- * writes of other values to send interrupts.
+ * writes of other values to send interrupts or set up receipt of notifications.
  *
  * Note that we overload the "offset" in the /dev/lguest file to indicate what
- * CPU number we're dealing with.  Currently this is always 0, since we only
+ * CPU number we're dealing with.  Currently this is always 0 since we only
  * support uniprocessor Guests, but you can see the beginnings of SMP support
- * here. */
+ * here.
+ */
 static ssize_t write(struct file *file, const char __user *in,
                     size_t size, loff_t *off)
 {
-       /* Once the Guest is initialized, we hold the "struct lguest" in the
-        * file private data. */
+       /*
+        * Once the Guest is initialized, we hold the "struct lguest" in the
+        * file private data.
+        */
        struct lguest *lg = file->private_data;
        const unsigned long __user *input = (const unsigned long __user *)in;
        unsigned long req;
@@ -322,13 +435,15 @@ static ssize_t write(struct file *file, const char __user *in,
        }
 }
 
-/*L:060 The final piece of interface code is the close() routine.  It reverses
+/*L:060
+ * The final piece of interface code is the close() routine.  It reverses
  * everything done in initialize().  This is usually called because the
  * Launcher exited.
  *
  * Note that the close routine returns 0 or a negative error number: it can't
  * really fail, but it can whine.  I blame Sun for this wart, and K&R C for
- * letting them do it. :*/
+ * letting them do it.
+:*/
 static int close(struct inode *inode, struct file *file)
 {
        struct lguest *lg = file->private_data;
@@ -338,8 +453,10 @@ static int close(struct inode *inode, struct file *file)
        if (!lg)
                return 0;
 
-       /* We need the big lock, to protect from inter-guest I/O and other
-        * Launchers initializing guests. */
+       /*
+        * We need the big lock, to protect from inter-guest I/O and other
+        * Launchers initializing guests.
+        */
        mutex_lock(&lguest_lock);
 
        /* Free up the shadow page tables for the Guest. */
@@ -350,18 +467,22 @@ static int close(struct inode *inode, struct file *file)
                hrtimer_cancel(&lg->cpus[i].hrt);
                /* We can free up the register page we allocated. */
                free_page(lg->cpus[i].regs_page);
-               /* Now all the memory cleanups are done, it's safe to release
-                * the Launcher's memory management structure. */
+               /*
+                * Now all the memory cleanups are done, it's safe to release
+                * the Launcher's memory management structure.
+                */
                mmput(lg->cpus[i].mm);
        }
 
        /* Release any eventfds they registered. */
        for (i = 0; i < lg->eventfds->num; i++)
-               fput(lg->eventfds->map[i].event);
+               eventfd_ctx_put(lg->eventfds->map[i].event);
        kfree(lg->eventfds);
 
-       /* If lg->dead doesn't contain an error code it will be NULL or a
-        * kmalloc()ed string, either of which is ok to hand to kfree(). */
+       /*
+        * If lg->dead doesn't contain an error code it will be NULL or a
+        * kmalloc()ed string, either of which is ok to hand to kfree().
+        */
        if (!IS_ERR(lg->dead))
                kfree(lg->dead);
        /* Free the memory allocated to the lguest_struct */
@@ -385,7 +506,8 @@ static int close(struct inode *inode, struct file *file)
  *
  * We begin our understanding with the Host kernel interface which the Launcher
  * uses: reading and writing a character device called /dev/lguest.  All the
- * work happens in the read(), write() and close() routines: */
+ * work happens in the read(), write() and close() routines:
+ */
 static struct file_operations lguest_fops = {
        .owner   = THIS_MODULE,
        .release = close,
@@ -393,8 +515,10 @@ static struct file_operations lguest_fops = {
        .read    = read,
 };
 
-/* This is a textbook example of a "misc" character device.  Populate a "struct
- * miscdevice" and register it with misc_register(). */
+/*
+ * This is a textbook example of a "misc" character device.  Populate a "struct
+ * miscdevice" and register it with misc_register().
+ */
 static struct miscdevice lguest_dev = {
        .minor  = MISC_DYNAMIC_MINOR,
        .name   = "lguest",
index a6fe1abda24002d623d74a7914f23b55ad708b4e..a8d0aee3bc0e3dfa7943cd412137a0d44e2d737d 100644 (file)
@@ -1,9 +1,11 @@
-/*P:700 The pagetable code, on the other hand, still shows the scars of
+/*P:700
+ * The pagetable code, on the other hand, still shows the scars of
  * previous encounters.  It's functional, and as neat as it can be in the
  * circumstances, but be wary, for these things are subtle and break easily.
  * The Guest provides a virtual to physical mapping, but we can neither trust
  * it nor use it: we verify and convert it here then point the CPU to the
- * converted Guest pages when running the Guest. :*/
+ * converted Guest pages when running the Guest.
+:*/
 
 /* Copyright (C) Rusty Russell IBM Corporation 2006.
  * GPL v2 and any later version */
 #include <asm/bootparam.h>
 #include "lg.h"
 
-/*M:008 We hold reference to pages, which prevents them from being swapped.
+/*M:008
+ * We hold reference to pages, which prevents them from being swapped.
  * It'd be nice to have a callback in the "struct mm_struct" when Linux wants
  * to swap out.  If we had this, and a shrinker callback to trim PTE pages, we
- * could probably consider launching Guests as non-root. :*/
+ * could probably consider launching Guests as non-root.
+:*/
 
 /*H:300
  * The Page Table Code
  *
- * We use two-level page tables for the Guest.  If you're not entirely
- * comfortable with virtual addresses, physical addresses and page tables then
- * I recommend you review arch/x86/lguest/boot.c's "Page Table Handling" (with
- * diagrams!).
+ * We use two-level page tables for the Guest, or three-level with PAE.  If
+ * you're not entirely comfortable with virtual addresses, physical addresses
+ * and page tables then I recommend you review arch/x86/lguest/boot.c's "Page
+ * Table Handling" (with diagrams!).
  *
  * The Guest keeps page tables, but we maintain the actual ones here: these are
  * called "shadow" page tables.  Which is a very Guest-centric name: these are
  *  (v) Flushing (throwing away) page tables,
  *  (vi) Mapping the Switcher when the Guest is about to run,
  *  (vii) Setting up the page tables initially.
- :*/
+:*/
 
-
-/* 1024 entries in a page table page maps 1024 pages: 4MB.  The Switcher is
- * conveniently placed at the top 4MB, so it uses a separate, complete PTE
- * page.  */
+/*
+ * The Switcher uses the complete top PTE page.  That's 1024 PTE entries (4MB)
+ * or 512 PTE entries with PAE (2MB).
+ */
 #define SWITCHER_PGD_INDEX (PTRS_PER_PGD - 1)
 
-/* For PAE we need the PMD index as well. We use the last 2MB, so we
- * will need the last pmd entry of the last pmd page.  */
+/*
+ * For PAE we need the PMD index as well. We use the last 2MB, so we
+ * will need the last pmd entry of the last pmd page.
+ */
 #ifdef CONFIG_X86_PAE
 #define SWITCHER_PMD_INDEX     (PTRS_PER_PMD - 1)
 #define RESERVE_MEM            2U
 #define CHECK_GPGD_MASK                _PAGE_TABLE
 #endif
 
-/* We actually need a separate PTE page for each CPU.  Remember that after the
+/*
+ * We actually need a separate PTE page for each CPU.  Remember that after the
  * Switcher code itself comes two pages for each CPU, and we don't want this
- * CPU's guest to see the pages of any other CPU. */
+ * CPU's guest to see the pages of any other CPU.
+ */
 static DEFINE_PER_CPU(pte_t *, switcher_pte_pages);
 #define switcher_pte_page(cpu) per_cpu(switcher_pte_pages, cpu)
 
-/*H:320 The page table code is curly enough to need helper functions to keep it
- * clear and clean.
+/*H:320
+ * The page table code is curly enough to need helper functions to keep it
+ * clear and clean.  The kernel itself provides many of them; one advantage
+ * of insisting that the Guest and Host use the same CONFIG_PAE setting.
  *
  * There are two functions which return pointers to the shadow (aka "real")
  * page tables.
@@ -79,7 +89,8 @@ static DEFINE_PER_CPU(pte_t *, switcher_pte_pages);
  * spgd_addr() takes the virtual address and returns a pointer to the top-level
  * page directory entry (PGD) for that address.  Since we keep track of several
  * page tables, the "i" argument tells us which one we're interested in (it's
- * usually the current one). */
+ * usually the current one).
+ */
 static pgd_t *spgd_addr(struct lg_cpu *cpu, u32 i, unsigned long vaddr)
 {
        unsigned int index = pgd_index(vaddr);
@@ -96,9 +107,11 @@ static pgd_t *spgd_addr(struct lg_cpu *cpu, u32 i, unsigned long vaddr)
 }
 
 #ifdef CONFIG_X86_PAE
-/* This routine then takes the PGD entry given above, which contains the
+/*
+ * This routine then takes the PGD entry given above, which contains the
  * address of the PMD page.  It then returns a pointer to the PMD entry for the
- * given address. */
+ * given address.
+ */
 static pmd_t *spmd_addr(struct lg_cpu *cpu, pgd_t spgd, unsigned long vaddr)
 {
        unsigned int index = pmd_index(vaddr);
@@ -119,9 +132,11 @@ static pmd_t *spmd_addr(struct lg_cpu *cpu, pgd_t spgd, unsigned long vaddr)
 }
 #endif
 
-/* This routine then takes the page directory entry returned above, which
+/*
+ * This routine then takes the page directory entry returned above, which
  * contains the address of the page table entry (PTE) page.  It then returns a
- * pointer to the PTE entry for the given address. */
+ * pointer to the PTE entry for the given address.
+ */
 static pte_t *spte_addr(struct lg_cpu *cpu, pgd_t spgd, unsigned long vaddr)
 {
 #ifdef CONFIG_X86_PAE
@@ -139,8 +154,10 @@ static pte_t *spte_addr(struct lg_cpu *cpu, pgd_t spgd, unsigned long vaddr)
        return &page[pte_index(vaddr)];
 }
 
-/* These two functions just like the above two, except they access the Guest
- * page tables.  Hence they return a Guest address. */
+/*
+ * These functions are just like the above two, except they access the Guest
+ * page tables.  Hence they return a Guest address.
+ */
 static unsigned long gpgd_addr(struct lg_cpu *cpu, unsigned long vaddr)
 {
        unsigned int index = vaddr >> (PGDIR_SHIFT);
@@ -148,6 +165,7 @@ static unsigned long gpgd_addr(struct lg_cpu *cpu, unsigned long vaddr)
 }
 
 #ifdef CONFIG_X86_PAE
+/* Follow the PGD to the PMD. */
 static unsigned long gpmd_addr(pgd_t gpgd, unsigned long vaddr)
 {
        unsigned long gpage = pgd_pfn(gpgd) << PAGE_SHIFT;
@@ -155,6 +173,7 @@ static unsigned long gpmd_addr(pgd_t gpgd, unsigned long vaddr)
        return gpage + pmd_index(vaddr) * sizeof(pmd_t);
 }
 
+/* Follow the PMD to the PTE. */
 static unsigned long gpte_addr(struct lg_cpu *cpu,
                               pmd_t gpmd, unsigned long vaddr)
 {
@@ -164,6 +183,7 @@ static unsigned long gpte_addr(struct lg_cpu *cpu,
        return gpage + pte_index(vaddr) * sizeof(pte_t);
 }
 #else
+/* Follow the PGD to the PTE (no mid-level for !PAE). */
 static unsigned long gpte_addr(struct lg_cpu *cpu,
                                pgd_t gpgd, unsigned long vaddr)
 {
@@ -175,17 +195,21 @@ static unsigned long gpte_addr(struct lg_cpu *cpu,
 #endif
 /*:*/
 
-/*M:014 get_pfn is slow: we could probably try to grab batches of pages here as
- * an optimization (ie. pre-faulting). :*/
+/*M:014
+ * get_pfn is slow: we could probably try to grab batches of pages here as
+ * an optimization (ie. pre-faulting).
+:*/
 
-/*H:350 This routine takes a page number given by the Guest and converts it to
+/*H:350
+ * This routine takes a page number given by the Guest and converts it to
  * an actual, physical page number.  It can fail for several reasons: the
  * virtual address might not be mapped by the Launcher, the write flag is set
  * and the page is read-only, or the write flag was set and the page was
  * shared so had to be copied, but we ran out of memory.
  *
  * This holds a reference to the page, so release_pte() is careful to put that
- * back. */
+ * back.
+ */
 static unsigned long get_pfn(unsigned long virtpfn, int write)
 {
        struct page *page;
@@ -198,33 +222,41 @@ static unsigned long get_pfn(unsigned long virtpfn, int write)
        return -1UL;
 }
 
-/*H:340 Converting a Guest page table entry to a shadow (ie. real) page table
+/*H:340
+ * Converting a Guest page table entry to a shadow (ie. real) page table
  * entry can be a little tricky.  The flags are (almost) the same, but the
  * Guest PTE contains a virtual page number: the CPU needs the real page
- * number. */
+ * number.
+ */
 static pte_t gpte_to_spte(struct lg_cpu *cpu, pte_t gpte, int write)
 {
        unsigned long pfn, base, flags;
 
-       /* The Guest sets the global flag, because it thinks that it is using
+       /*
+        * The Guest sets the global flag, because it thinks that it is using
         * PGE.  We only told it to use PGE so it would tell us whether it was
         * flushing a kernel mapping or a userspace mapping.  We don't actually
-        * use the global bit, so throw it away. */
+        * use the global bit, so throw it away.
+        */
        flags = (pte_flags(gpte) & ~_PAGE_GLOBAL);
 
        /* The Guest's pages are offset inside the Launcher. */
        base = (unsigned long)cpu->lg->mem_base / PAGE_SIZE;
 
-       /* We need a temporary "unsigned long" variable to hold the answer from
+       /*
+        * We need a temporary "unsigned long" variable to hold the answer from
         * get_pfn(), because it returns 0xFFFFFFFF on failure, which wouldn't
         * fit in spte.pfn.  get_pfn() finds the real physical number of the
-        * page, given the virtual number. */
+        * page, given the virtual number.
+        */
        pfn = get_pfn(base + pte_pfn(gpte), write);
        if (pfn == -1UL) {
                kill_guest(cpu, "failed to get page %lu", pte_pfn(gpte));
-               /* When we destroy the Guest, we'll go through the shadow page
+               /*
+                * When we destroy the Guest, we'll go through the shadow page
                 * tables and release_pte() them.  Make sure we don't think
-                * this one is valid! */
+                * this one is valid!
+                */
                flags = 0;
        }
        /* Now we assemble our shadow PTE from the page number and flags. */
@@ -234,8 +266,10 @@ static pte_t gpte_to_spte(struct lg_cpu *cpu, pte_t gpte, int write)
 /*H:460 And to complete the chain, release_pte() looks like this: */
 static void release_pte(pte_t pte)
 {
-       /* Remember that get_user_pages_fast() took a reference to the page, in
-        * get_pfn()?  We have to put it back now. */
+       /*
+        * Remember that get_user_pages_fast() took a reference to the page, in
+        * get_pfn()?  We have to put it back now.
+        */
        if (pte_flags(pte) & _PAGE_PRESENT)
                put_page(pte_page(pte));
 }
@@ -273,7 +307,8 @@ static void check_gpmd(struct lg_cpu *cpu, pmd_t gpmd)
  * and return to the Guest without it knowing.
  *
  * If we fixed up the fault (ie. we mapped the address), this routine returns
- * true.  Otherwise, it was a real fault and we need to tell the Guest. */
+ * true.  Otherwise, it was a real fault and we need to tell the Guest.
+ */
 bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
 {
        pgd_t gpgd;
@@ -282,6 +317,7 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
        pte_t gpte;
        pte_t *spte;
 
+       /* Mid level for PAE. */
 #ifdef CONFIG_X86_PAE
        pmd_t *spmd;
        pmd_t gpmd;
@@ -298,22 +334,26 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
        if (!(pgd_flags(*spgd) & _PAGE_PRESENT)) {
                /* No shadow entry: allocate a new shadow PTE page. */
                unsigned long ptepage = get_zeroed_page(GFP_KERNEL);
-               /* This is not really the Guest's fault, but killing it is
-                * simple for this corner case. */
+               /*
+                * This is not really the Guest's fault, but killing it is
+                * simple for this corner case.
+                */
                if (!ptepage) {
                        kill_guest(cpu, "out of memory allocating pte page");
                        return false;
                }
                /* We check that the Guest pgd is OK. */
                check_gpgd(cpu, gpgd);
-               /* And we copy the flags to the shadow PGD entry.  The page
-                * number in the shadow PGD is the page we just allocated. */
+               /*
+                * And we copy the flags to the shadow PGD entry.  The page
+                * number in the shadow PGD is the page we just allocated.
+                */
                set_pgd(spgd, __pgd(__pa(ptepage) | pgd_flags(gpgd)));
        }
 
 #ifdef CONFIG_X86_PAE
        gpmd = lgread(cpu, gpmd_addr(gpgd, vaddr), pmd_t);
-       /* middle level not present?  We can't map it in. */
+       /* Middle level not present?  We can't map it in. */
        if (!(pmd_flags(gpmd) & _PAGE_PRESENT))
                return false;
 
@@ -324,8 +364,10 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
                /* No shadow entry: allocate a new shadow PTE page. */
                unsigned long ptepage = get_zeroed_page(GFP_KERNEL);
 
-               /* This is not really the Guest's fault, but killing it is
-               * simple for this corner case. */
+               /*
+                * This is not really the Guest's fault, but killing it is
+                * simple for this corner case.
+                */
                if (!ptepage) {
                        kill_guest(cpu, "out of memory allocating pte page");
                        return false;
@@ -334,27 +376,37 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
                /* We check that the Guest pmd is OK. */
                check_gpmd(cpu, gpmd);
 
-               /* And we copy the flags to the shadow PMD entry.  The page
-                * number in the shadow PMD is the page we just allocated. */
+               /*
+                * And we copy the flags to the shadow PMD entry.  The page
+                * number in the shadow PMD is the page we just allocated.
+                */
                native_set_pmd(spmd, __pmd(__pa(ptepage) | pmd_flags(gpmd)));
        }
 
-       /* OK, now we look at the lower level in the Guest page table: keep its
-        * address, because we might update it later. */
+       /*
+        * OK, now we look at the lower level in the Guest page table: keep its
+        * address, because we might update it later.
+        */
        gpte_ptr = gpte_addr(cpu, gpmd, vaddr);
 #else
-       /* OK, now we look at the lower level in the Guest page table: keep its
-        * address, because we might update it later. */
+       /*
+        * OK, now we look at the lower level in the Guest page table: keep its
+        * address, because we might update it later.
+        */
        gpte_ptr = gpte_addr(cpu, gpgd, vaddr);
 #endif
+
+       /* Read the actual PTE value. */
        gpte = lgread(cpu, gpte_ptr, pte_t);
 
        /* If this page isn't in the Guest page tables, we can't page it in. */
        if (!(pte_flags(gpte) & _PAGE_PRESENT))
                return false;
 
-       /* Check they're not trying to write to a page the Guest wants
-        * read-only (bit 2 of errcode == write). */
+       /*
+        * Check they're not trying to write to a page the Guest wants
+        * read-only (bit 2 of errcode == write).
+        */
        if ((errcode & 2) && !(pte_flags(gpte) & _PAGE_RW))
                return false;
 
@@ -362,8 +414,10 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
        if ((errcode & 4) && !(pte_flags(gpte) & _PAGE_USER))
                return false;
 
-       /* Check that the Guest PTE flags are OK, and the page number is below
-        * the pfn_limit (ie. not mapping the Launcher binary). */
+       /*
+        * Check that the Guest PTE flags are OK, and the page number is below
+        * the pfn_limit (ie. not mapping the Launcher binary).
+        */
        check_gpte(cpu, gpte);
 
        /* Add the _PAGE_ACCESSED and (for a write) _PAGE_DIRTY flag */
@@ -373,29 +427,40 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
 
        /* Get the pointer to the shadow PTE entry we're going to set. */
        spte = spte_addr(cpu, *spgd, vaddr);
-       /* If there was a valid shadow PTE entry here before, we release it.
-        * This can happen with a write to a previously read-only entry. */
+
+       /*
+        * If there was a valid shadow PTE entry here before, we release it.
+        * This can happen with a write to a previously read-only entry.
+        */
        release_pte(*spte);
 
-       /* If this is a write, we insist that the Guest page is writable (the
-        * final arg to gpte_to_spte()). */
+       /*
+        * If this is a write, we insist that the Guest page is writable (the
+        * final arg to gpte_to_spte()).
+        */
        if (pte_dirty(gpte))
                *spte = gpte_to_spte(cpu, gpte, 1);
        else
-               /* If this is a read, don't set the "writable" bit in the page
+               /*
+                * If this is a read, don't set the "writable" bit in the page
                 * table entry, even if the Guest says it's writable.  That way
                 * we will come back here when a write does actually occur, so
-                * we can update the Guest's _PAGE_DIRTY flag. */
+                * we can update the Guest's _PAGE_DIRTY flag.
+                */
                native_set_pte(spte, gpte_to_spte(cpu, pte_wrprotect(gpte), 0));
 
-       /* Finally, we write the Guest PTE entry back: we've set the
-        * _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags. */
+       /*
+        * Finally, we write the Guest PTE entry back: we've set the
+        * _PAGE_ACCESSED and maybe the _PAGE_DIRTY flags.
+        */
        lgwrite(cpu, gpte_ptr, pte_t, gpte);
 
-       /* The fault is fixed, the page table is populated, the mapping
+       /*
+        * The fault is fixed, the page table is populated, the mapping
         * manipulated, the result returned and the code complete.  A small
         * delay and a trace of alliteration are the only indications the Guest
-        * has that a page fault occurred at all. */
+        * has that a page fault occurred at all.
+        */
        return true;
 }
 
@@ -408,7 +473,8 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode)
  * mapped, so it's overkill.
  *
  * This is a quick version which answers the question: is this virtual address
- * mapped by the shadow page tables, and is it writable? */
+ * mapped by the shadow page tables, and is it writable?
+ */
 static bool page_writable(struct lg_cpu *cpu, unsigned long vaddr)
 {
        pgd_t *spgd;
@@ -428,21 +494,26 @@ static bool page_writable(struct lg_cpu *cpu, unsigned long vaddr)
                return false;
 #endif
 
-       /* Check the flags on the pte entry itself: it must be present and
-        * writable. */
+       /*
+        * Check the flags on the pte entry itself: it must be present and
+        * writable.
+        */
        flags = pte_flags(*(spte_addr(cpu, *spgd, vaddr)));
 
        return (flags & (_PAGE_PRESENT|_PAGE_RW)) == (_PAGE_PRESENT|_PAGE_RW);
 }
 
-/* So, when pin_stack_pages() asks us to pin a page, we check if it's already
+/*
+ * So, when pin_stack_pages() asks us to pin a page, we check if it's already
  * in the page tables, and if not, we call demand_page() with error code 2
- * (meaning "write"). */
+ * (meaning "write").
+ */
 void pin_page(struct lg_cpu *cpu, unsigned long vaddr)
 {
        if (!page_writable(cpu, vaddr) && !demand_page(cpu, vaddr, 2))
                kill_guest(cpu, "bad stack page %#lx", vaddr);
 }
+/*:*/
 
 #ifdef CONFIG_X86_PAE
 static void release_pmd(pmd_t *spmd)
@@ -479,15 +550,21 @@ static void release_pgd(pgd_t *spgd)
 }
 
 #else /* !CONFIG_X86_PAE */
-/*H:450 If we chase down the release_pgd() code, it looks like this: */
+/*H:450
+ * If we chase down the release_pgd() code, the non-PAE version looks like
+ * this.  The PAE version is almost identical, but instead of calling
+ * release_pte it calls release_pmd(), which looks much like this.
+ */
 static void release_pgd(pgd_t *spgd)
 {
        /* If the entry's not present, there's nothing to release. */
        if (pgd_flags(*spgd) & _PAGE_PRESENT) {
                unsigned int i;
-               /* Converting the pfn to find the actual PTE page is easy: turn
+               /*
+                * Converting the pfn to find the actual PTE page is easy: turn
                 * the page number into a physical address, then convert to a
-                * virtual address (easy for kernel pages like this one). */
+                * virtual address (easy for kernel pages like this one).
+                */
                pte_t *ptepage = __va(pgd_pfn(*spgd) << PAGE_SHIFT);
                /* For each entry in the page, we might need to release it. */
                for (i = 0; i < PTRS_PER_PTE; i++)
@@ -499,9 +576,12 @@ static void release_pgd(pgd_t *spgd)
        }
 }
 #endif
-/*H:445 We saw flush_user_mappings() twice: once from the flush_user_mappings()
+
+/*H:445
+ * We saw flush_user_mappings() twice: once from the flush_user_mappings()
  * hypercall and once in new_pgdir() when we re-used a top-level pgdir page.
- * It simply releases every PTE page from 0 up to the Guest's kernel address. */
+ * It simply releases every PTE page from 0 up to the Guest's kernel address.
+ */
 static void flush_user_mappings(struct lguest *lg, int idx)
 {
        unsigned int i;
@@ -510,10 +590,12 @@ static void flush_user_mappings(struct lguest *lg, int idx)
                release_pgd(lg->pgdirs[idx].pgdir + i);
 }
 
-/*H:440 (v) Flushing (throwing away) page tables,
+/*H:440
+ * (v) Flushing (throwing away) page tables,
  *
  * The Guest has a hypercall to throw away the page tables: it's used when a
- * large number of mappings have been changed. */
+ * large number of mappings have been changed.
+ */
 void guest_pagetable_flush_user(struct lg_cpu *cpu)
 {
        /* Drop the userspace part of the current page table. */
@@ -551,9 +633,11 @@ unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr)
        return pte_pfn(gpte) * PAGE_SIZE | (vaddr & ~PAGE_MASK);
 }
 
-/* We keep several page tables.  This is a simple routine to find the page
+/*
+ * We keep several page tables.  This is a simple routine to find the page
  * table (if any) corresponding to this top-level address the Guest has given
- * us. */
+ * us.
+ */
 static unsigned int find_pgdir(struct lguest *lg, unsigned long pgtable)
 {
        unsigned int i;
@@ -563,9 +647,11 @@ static unsigned int find_pgdir(struct lguest *lg, unsigned long pgtable)
        return i;
 }
 
-/*H:435 And this is us, creating the new page directory.  If we really do
+/*H:435
+ * And this is us, creating the new page directory.  If we really do
  * allocate a new one (and so the kernel parts are not there), we set
- * blank_pgdir. */
+ * blank_pgdir.
+ */
 static unsigned int new_pgdir(struct lg_cpu *cpu,
                              unsigned long gpgdir,
                              int *blank_pgdir)
@@ -575,8 +661,10 @@ static unsigned int new_pgdir(struct lg_cpu *cpu,
        pmd_t *pmd_table;
 #endif
 
-       /* We pick one entry at random to throw out.  Choosing the Least
-        * Recently Used might be better, but this is easy. */
+       /*
+        * We pick one entry at random to throw out.  Choosing the Least
+        * Recently Used might be better, but this is easy.
+        */
        next = random32() % ARRAY_SIZE(cpu->lg->pgdirs);
        /* If it's never been allocated at all before, try now. */
        if (!cpu->lg->pgdirs[next].pgdir) {
@@ -587,8 +675,10 @@ static unsigned int new_pgdir(struct lg_cpu *cpu,
                        next = cpu->cpu_pgd;
                else {
 #ifdef CONFIG_X86_PAE
-                       /* In PAE mode, allocate a pmd page and populate the
-                        * last pgd entry. */
+                       /*
+                        * In PAE mode, allocate a pmd page and populate the
+                        * last pgd entry.
+                        */
                        pmd_table = (pmd_t *)get_zeroed_page(GFP_KERNEL);
                        if (!pmd_table) {
                                free_page((long)cpu->lg->pgdirs[next].pgdir);
@@ -598,8 +688,10 @@ static unsigned int new_pgdir(struct lg_cpu *cpu,
                                set_pgd(cpu->lg->pgdirs[next].pgdir +
                                        SWITCHER_PGD_INDEX,
                                        __pgd(__pa(pmd_table) | _PAGE_PRESENT));
-                               /* This is a blank page, so there are no kernel
-                                * mappings: caller must map the stack! */
+                               /*
+                                * This is a blank page, so there are no kernel
+                                * mappings: caller must map the stack!
+                                */
                                *blank_pgdir = 1;
                        }
 #else
@@ -615,19 +707,23 @@ static unsigned int new_pgdir(struct lg_cpu *cpu,
        return next;
 }
 
-/*H:430 (iv) Switching page tables
+/*H:430
+ * (iv) Switching page tables
  *
  * Now we've seen all the page table setting and manipulation, let's see
  * what happens when the Guest changes page tables (ie. changes the top-level
- * pgdir).  This occurs on almost every context switch. */
+ * pgdir).  This occurs on almost every context switch.
+ */
 void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable)
 {
        int newpgdir, repin = 0;
 
        /* Look to see if we have this one already. */
        newpgdir = find_pgdir(cpu->lg, pgtable);
-       /* If not, we allocate or mug an existing one: if it's a fresh one,
-        * repin gets set to 1. */
+       /*
+        * If not, we allocate or mug an existing one: if it's a fresh one,
+        * repin gets set to 1.
+        */
        if (newpgdir == ARRAY_SIZE(cpu->lg->pgdirs))
                newpgdir = new_pgdir(cpu, pgtable, &repin);
        /* Change the current pgd index to the new one. */
@@ -637,9 +733,11 @@ void guest_new_pagetable(struct lg_cpu *cpu, unsigned long pgtable)
                pin_stack_pages(cpu);
 }
 
-/*H:470 Finally, a routine which throws away everything: all PGD entries in all
+/*H:470
+ * Finally, a routine which throws away everything: all PGD entries in all
  * the shadow page tables, including the Guest's kernel mappings.  This is used
- * when we destroy the Guest. */
+ * when we destroy the Guest.
+ */
 static void release_all_pagetables(struct lguest *lg)
 {
        unsigned int i, j;
@@ -656,8 +754,10 @@ static void release_all_pagetables(struct lguest *lg)
                        spgd = lg->pgdirs[i].pgdir + SWITCHER_PGD_INDEX;
                        pmdpage = __va(pgd_pfn(*spgd) << PAGE_SHIFT);
 
-                       /* And release the pmd entries of that pmd page,
-                        * except for the switcher pmd. */
+                       /*
+                        * And release the pmd entries of that pmd page,
+                        * except for the switcher pmd.
+                        */
                        for (k = 0; k < SWITCHER_PMD_INDEX; k++)
                                release_pmd(&pmdpage[k]);
 #endif
@@ -667,10 +767,12 @@ static void release_all_pagetables(struct lguest *lg)
                }
 }
 
-/* We also throw away everything when a Guest tells us it's changed a kernel
+/*
+ * We also throw away everything when a Guest tells us it's changed a kernel
  * mapping.  Since kernel mappings are in every page table, it's easiest to
  * throw them all away.  This traps the Guest in amber for a while as
- * everything faults back in, but it's rare. */
+ * everything faults back in, but it's rare.
+ */
 void guest_pagetable_clear_all(struct lg_cpu *cpu)
 {
        release_all_pagetables(cpu->lg);
@@ -678,15 +780,19 @@ void guest_pagetable_clear_all(struct lg_cpu *cpu)
        pin_stack_pages(cpu);
 }
 /*:*/
-/*M:009 Since we throw away all mappings when a kernel mapping changes, our
+
+/*M:009
+ * Since we throw away all mappings when a kernel mapping changes, our
  * performance sucks for guests using highmem.  In fact, a guest with
  * PAGE_OFFSET 0xc0000000 (the default) and more than about 700MB of RAM is
  * usually slower than a Guest with less memory.
  *
  * This, of course, cannot be fixed.  It would take some kind of... well, I
- * don't know, but the term "puissant code-fu" comes to mind. :*/
+ * don't know, but the term "puissant code-fu" comes to mind.
+:*/
 
-/*H:420 This is the routine which actually sets the page table entry for then
+/*H:420
+ * This is the routine which actually sets the page table entry for then
  * "idx"'th shadow page table.
  *
  * Normally, we can just throw out the old entry and replace it with 0: if they
@@ -715,31 +821,36 @@ static void do_set_pte(struct lg_cpu *cpu, int idx,
                spmd = spmd_addr(cpu, *spgd, vaddr);
                if (pmd_flags(*spmd) & _PAGE_PRESENT) {
 #endif
-                       /* Otherwise, we start by releasing
-                        * the existing entry. */
+                       /* Otherwise, start by releasing the existing entry. */
                        pte_t *spte = spte_addr(cpu, *spgd, vaddr);
                        release_pte(*spte);
 
-                       /* If they're setting this entry as dirty or accessed,
-                        * we might as well put that entry they've given us
-                        * in now.  This shaves 10% off a
-                        * copy-on-write micro-benchmark. */
+                       /*
+                        * If they're setting this entry as dirty or accessed,
+                        * we might as well put that entry they've given us in
+                        * now.  This shaves 10% off a copy-on-write
+                        * micro-benchmark.
+                        */
                        if (pte_flags(gpte) & (_PAGE_DIRTY | _PAGE_ACCESSED)) {
                                check_gpte(cpu, gpte);
                                native_set_pte(spte,
                                                gpte_to_spte(cpu, gpte,
                                                pte_flags(gpte) & _PAGE_DIRTY));
-                       } else
-                               /* Otherwise kill it and we can demand_page()
-                                * it in later. */
+                       } else {
+                               /*
+                                * Otherwise kill it and we can demand_page()
+                                * it in later.
+                                */
                                native_set_pte(spte, __pte(0));
+                       }
 #ifdef CONFIG_X86_PAE
                }
 #endif
        }
 }
 
-/*H:410 Updating a PTE entry is a little trickier.
+/*H:410
+ * Updating a PTE entry is a little trickier.
  *
  * We keep track of several different page tables (the Guest uses one for each
  * process, so it makes sense to cache at least a few).  Each of these have
@@ -748,12 +859,15 @@ static void do_set_pte(struct lg_cpu *cpu, int idx,
  * all the page tables, not just the current one.  This is rare.
  *
  * The benefit is that when we have to track a new page table, we can keep all
- * the kernel mappings.  This speeds up context switch immensely. */
+ * the kernel mappings.  This speeds up context switch immensely.
+ */
 void guest_set_pte(struct lg_cpu *cpu,
                   unsigned long gpgdir, unsigned long vaddr, pte_t gpte)
 {
-       /* Kernel mappings must be changed on all top levels.  Slow, but doesn't
-        * happen often. */
+       /*
+        * Kernel mappings must be changed on all top levels.  Slow, but doesn't
+        * happen often.
+        */
        if (vaddr >= cpu->lg->kernel_address) {
                unsigned int i;
                for (i = 0; i < ARRAY_SIZE(cpu->lg->pgdirs); i++)
@@ -795,19 +909,25 @@ void guest_set_pgd(struct lguest *lg, unsigned long gpgdir, u32 idx)
                /* ... throw it away. */
                release_pgd(lg->pgdirs[pgdir].pgdir + idx);
 }
+
 #ifdef CONFIG_X86_PAE
+/* For setting a mid-level, we just throw everything away.  It's easy. */
 void guest_set_pmd(struct lguest *lg, unsigned long pmdp, u32 idx)
 {
        guest_pagetable_clear_all(&lg->cpus[0]);
 }
 #endif
 
-/* Once we know how much memory we have we can construct simple identity
- * (which set virtual == physical) and linear mappings
- * which will get the Guest far enough into the boot to create its own.
+/*H:505
+ * To get through boot, we construct simple identity page mappings (which
+ * set virtual == physical) and linear mappings which will get the Guest far
+ * enough into the boot to create its own.  The linear mapping means we
+ * simplify the Guest boot, but it makes assumptions about their PAGE_OFFSET,
+ * as you'll see.
  *
  * We lay them out of the way, just below the initrd (which is why we need to
- * know its size here). */
+ * know its size here).
+ */
 static unsigned long setup_pagetables(struct lguest *lg,
                                      unsigned long mem,
                                      unsigned long initrd_size)
@@ -825,8 +945,10 @@ static unsigned long setup_pagetables(struct lguest *lg,
        unsigned int phys_linear;
 #endif
 
-       /* We have mapped_pages frames to map, so we need
-        * linear_pages page tables to map them. */
+       /*
+        * We have mapped_pages frames to map, so we need linear_pages page
+        * tables to map them.
+        */
        mapped_pages = mem / PAGE_SIZE;
        linear_pages = (mapped_pages + PTRS_PER_PTE - 1) / PTRS_PER_PTE;
 
@@ -837,10 +959,16 @@ static unsigned long setup_pagetables(struct lguest *lg,
        linear = (void *)pgdir - linear_pages * PAGE_SIZE;
 
 #ifdef CONFIG_X86_PAE
+       /*
+        * And the single mid page goes below that.  We only use one, but
+        * that's enough to map 1G, which definitely gets us through boot.
+        */
        pmds = (void *)linear - PAGE_SIZE;
 #endif
-       /* Linear mapping is easy: put every page's address into the
-        * mapping in order. */
+       /*
+        * Linear mapping is easy: put every page's address into the
+        * mapping in order.
+        */
        for (i = 0; i < mapped_pages; i++) {
                pte_t pte;
                pte = pfn_pte(i, __pgprot(_PAGE_PRESENT|_PAGE_RW|_PAGE_USER));
@@ -848,11 +976,14 @@ static unsigned long setup_pagetables(struct lguest *lg,
                        return -EFAULT;
        }
 
-       /* The top level points to the linear page table pages above.
-        * We setup the identity and linear mappings here. */
 #ifdef CONFIG_X86_PAE
+       /*
+        * Make the Guest PMD entries point to the corresponding place in the
+        * linear mapping (up to one page worth of PMD).
+        */
        for (i = j = 0; i < mapped_pages && j < PTRS_PER_PMD;
             i += PTRS_PER_PTE, j++) {
+               /* FIXME: native_set_pmd is overkill here. */
                native_set_pmd(&pmd, __pmd(((unsigned long)(linear + i)
                - mem_base) | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER));
 
@@ -860,18 +991,36 @@ static unsigned long setup_pagetables(struct lguest *lg,
                        return -EFAULT;
        }
 
+       /* One PGD entry, pointing to that PMD page. */
        set_pgd(&pgd, __pgd(((u32)pmds - mem_base) | _PAGE_PRESENT));
+       /* Copy it in as the first PGD entry (ie. addresses 0-1G). */
        if (copy_to_user(&pgdir[0], &pgd, sizeof(pgd)) != 0)
                return -EFAULT;
+       /*
+        * And the third PGD entry (ie. addresses 3G-4G).
+        *
+        * FIXME: This assumes that PAGE_OFFSET for the Guest is 0xC0000000.
+        */
        if (copy_to_user(&pgdir[3], &pgd, sizeof(pgd)) != 0)
                return -EFAULT;
 #else
+       /*
+        * The top level points to the linear page table pages above.
+        * We setup the identity and linear mappings here.
+        */
        phys_linear = (unsigned long)linear - mem_base;
        for (i = 0; i < mapped_pages; i += PTRS_PER_PTE) {
                pgd_t pgd;
+               /*
+                * Create a PGD entry which points to the right part of the
+                * linear PTE pages.
+                */
                pgd = __pgd((phys_linear + i * sizeof(pte_t)) |
                            (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER));
 
+               /*
+                * Copy it into the PGD page at 0 and PAGE_OFFSET.
+                */
                if (copy_to_user(&pgdir[i / PTRS_PER_PTE], &pgd, sizeof(pgd))
                    || copy_to_user(&pgdir[pgd_index(PAGE_OFFSET)
                                           + i / PTRS_PER_PTE],
@@ -880,15 +1029,19 @@ static unsigned long setup_pagetables(struct lguest *lg,
        }
 #endif
 
-       /* We return the top level (guest-physical) address: remember where
-        * this is. */
+       /*
+        * We return the top level (guest-physical) address: we remember where
+        * this is to write it into lguest_data when the Guest initializes.
+        */
        return (unsigned long)pgdir - mem_base;
 }
 
-/*H:500 (vii) Setting up the page tables initially.
+/*H:500
+ * (vii) Setting up the page tables initially.
  *
  * When a Guest is first created, the Launcher tells us where the toplevel of
- * its first page table is.  We set some things up here: */
+ * its first page table is.  We set some things up here:
+ */
 int init_guest_pagetable(struct lguest *lg)
 {
        u64 mem;
@@ -898,21 +1051,27 @@ int init_guest_pagetable(struct lguest *lg)
        pgd_t *pgd;
        pmd_t *pmd_table;
 #endif
-       /* Get the Guest memory size and the ramdisk size from the boot header
-        * located at lg->mem_base (Guest address 0). */
+       /*
+        * Get the Guest memory size and the ramdisk size from the boot header
+        * located at lg->mem_base (Guest address 0).
+        */
        if (copy_from_user(&mem, &boot->e820_map[0].size, sizeof(mem))
            || get_user(initrd_size, &boot->hdr.ramdisk_size))
                return -EFAULT;
 
-       /* We start on the first shadow page table, and give it a blank PGD
-        * page. */
+       /*
+        * We start on the first shadow page table, and give it a blank PGD
+        * page.
+        */
        lg->pgdirs[0].gpgdir = setup_pagetables(lg, mem, initrd_size);
        if (IS_ERR_VALUE(lg->pgdirs[0].gpgdir))
                return lg->pgdirs[0].gpgdir;
        lg->pgdirs[0].pgdir = (pgd_t *)get_zeroed_page(GFP_KERNEL);
        if (!lg->pgdirs[0].pgdir)
                return -ENOMEM;
+
 #ifdef CONFIG_X86_PAE
+       /* For PAE, we also create the initial mid-level. */
        pgd = lg->pgdirs[0].pgdir;
        pmd_table = (pmd_t *) get_zeroed_page(GFP_KERNEL);
        if (!pmd_table)
@@ -921,27 +1080,33 @@ int init_guest_pagetable(struct lguest *lg)
        set_pgd(pgd + SWITCHER_PGD_INDEX,
                __pgd(__pa(pmd_table) | _PAGE_PRESENT));
 #endif
+
+       /* This is the current page table. */
        lg->cpus[0].cpu_pgd = 0;
        return 0;
 }
 
-/* When the Guest calls LHCALL_LGUEST_INIT we do more setup. */
+/*H:508 When the Guest calls LHCALL_LGUEST_INIT we do more setup. */
 void page_table_guest_data_init(struct lg_cpu *cpu)
 {
        /* We get the kernel address: above this is all kernel memory. */
        if (get_user(cpu->lg->kernel_address,
                &cpu->lg->lguest_data->kernel_address)
-               /* We tell the Guest that it can't use the top 2 or 4 MB
-                * of virtual addresses used by the Switcher. */
+               /*
+                * We tell the Guest that it can't use the top 2 or 4 MB
+                * of virtual addresses used by the Switcher.
+                */
                || put_user(RESERVE_MEM * 1024 * 1024,
                        &cpu->lg->lguest_data->reserve_mem)
                || put_user(cpu->lg->pgdirs[0].gpgdir,
                        &cpu->lg->lguest_data->pgdir))
                kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
 
-       /* In flush_user_mappings() we loop from 0 to
+       /*
+        * In flush_user_mappings() we loop from 0 to
         * "pgd_index(lg->kernel_address)".  This assumes it won't hit the
-        * Switcher mappings, so check that now. */
+        * Switcher mappings, so check that now.
+        */
 #ifdef CONFIG_X86_PAE
        if (pgd_index(cpu->lg->kernel_address) == SWITCHER_PGD_INDEX &&
                pmd_index(cpu->lg->kernel_address) == SWITCHER_PMD_INDEX)
@@ -964,12 +1129,14 @@ void free_guest_pagetable(struct lguest *lg)
                free_page((long)lg->pgdirs[i].pgdir);
 }
 
-/*H:480 (vi) Mapping the Switcher when the Guest is about to run.
+/*H:480
+ * (vi) Mapping the Switcher when the Guest is about to run.
  *
  * The Switcher and the two pages for this CPU need to be visible in the
  * Guest (and not the pages for other CPUs).  We have the appropriate PTE pages
  * for each CPU already set up, we just need to hook them in now we know which
- * Guest is about to run on this CPU. */
+ * Guest is about to run on this CPU.
+ */
 void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages)
 {
        pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages);
@@ -980,30 +1147,38 @@ void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages)
        pmd_t switcher_pmd;
        pmd_t *pmd_table;
 
+       /* FIXME: native_set_pmd is overkill here. */
        native_set_pmd(&switcher_pmd, pfn_pmd(__pa(switcher_pte_page) >>
                       PAGE_SHIFT, PAGE_KERNEL_EXEC));
 
+       /* Figure out where the pmd page is, by reading the PGD, and converting
+        * it to a virtual address. */
        pmd_table = __va(pgd_pfn(cpu->lg->
                        pgdirs[cpu->cpu_pgd].pgdir[SWITCHER_PGD_INDEX])
                                                                << PAGE_SHIFT);
+       /* Now write it into the shadow page table. */
        native_set_pmd(&pmd_table[SWITCHER_PMD_INDEX], switcher_pmd);
 #else
        pgd_t switcher_pgd;
 
-       /* Make the last PGD entry for this Guest point to the Switcher's PTE
-        * page for this CPU (with appropriate flags). */
+       /*
+        * Make the last PGD entry for this Guest point to the Switcher's PTE
+        * page for this CPU (with appropriate flags).
+        */
        switcher_pgd = __pgd(__pa(switcher_pte_page) | __PAGE_KERNEL_EXEC);
 
        cpu->lg->pgdirs[cpu->cpu_pgd].pgdir[SWITCHER_PGD_INDEX] = switcher_pgd;
 
 #endif
-       /* We also change the Switcher PTE page.  When we're running the Guest,
+       /*
+        * We also change the Switcher PTE page.  When we're running the Guest,
         * we want the Guest's "regs" page to appear where the first Switcher
         * page for this CPU is.  This is an optimization: when the Switcher
         * saves the Guest registers, it saves them into the first page of this
         * CPU's "struct lguest_pages": if we make sure the Guest's register
         * page is already mapped there, we don't have to copy them out
-        * again. */
+        * again.
+        */
        pfn = __pa(cpu->regs_page) >> PAGE_SHIFT;
        native_set_pte(&regs_pte, pfn_pte(pfn, PAGE_KERNEL));
        native_set_pte(&switcher_pte_page[pte_index((unsigned long)pages)],
@@ -1019,10 +1194,12 @@ static void free_switcher_pte_pages(void)
                free_page((long)switcher_pte_page(i));
 }
 
-/*H:520 Setting up the Switcher PTE page for given CPU is fairly easy, given
+/*H:520
+ * Setting up the Switcher PTE page for given CPU is fairly easy, given
  * the CPU number and the "struct page"s for the Switcher code itself.
  *
- * Currently the Switcher is less than a page long, so "pages" is always 1. */
+ * Currently the Switcher is less than a page long, so "pages" is always 1.
+ */
 static __init void populate_switcher_pte_page(unsigned int cpu,
                                              struct page *switcher_page[],
                                              unsigned int pages)
@@ -1043,13 +1220,16 @@ static __init void populate_switcher_pte_page(unsigned int cpu,
        native_set_pte(&pte[i], pfn_pte(page_to_pfn(switcher_page[i]),
                         __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_RW)));
 
-       /* The second page contains the "struct lguest_ro_state", and is
-        * read-only. */
+       /*
+        * The second page contains the "struct lguest_ro_state", and is
+        * read-only.
+        */
        native_set_pte(&pte[i+1], pfn_pte(page_to_pfn(switcher_page[i+1]),
                           __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED)));
 }
 
-/* We've made it through the page table code.  Perhaps our tired brains are
+/*
+ * We've made it through the page table code.  Perhaps our tired brains are
  * still processing the details, or perhaps we're simply glad it's over.
  *
  * If nothing else, note that all this complexity in juggling shadow page tables
@@ -1058,10 +1238,13 @@ static __init void populate_switcher_pte_page(unsigned int cpu,
  * uses exotic direct Guest pagetable manipulation, and why both Intel and AMD
  * have implemented shadow page table support directly into hardware.
  *
- * There is just one file remaining in the Host. */
+ * There is just one file remaining in the Host.
+ */
 
-/*H:510 At boot or module load time, init_pagetables() allocates and populates
- * the Switcher PTE page for each CPU. */
+/*H:510
+ * At boot or module load time, init_pagetables() allocates and populates
+ * the Switcher PTE page for each CPU.
+ */
 __init int init_pagetables(struct page **switcher_page, unsigned int pages)
 {
        unsigned int i;
index 482ed5a18750659e07f7bda54a90429822079b6f..951c57b0a7e075a9d927193d3c54d46ccb682545 100644 (file)
@@ -1,4 +1,5 @@
-/*P:600 The x86 architecture has segments, which involve a table of descriptors
+/*P:600
+ * The x86 architecture has segments, which involve a table of descriptors
  * which can be used to do funky things with virtual address interpretation.
  * We originally used to use segments so the Guest couldn't alter the
  * Guest<->Host Switcher, and then we had to trim Guest segments, and restore
@@ -8,7 +9,8 @@
  *
  * In these modern times, the segment handling code consists of simple sanity
  * checks, and the worst you'll experience reading this code is butterfly-rash
- * from frolicking through its parklike serenity. :*/
+ * from frolicking through its parklike serenity.
+:*/
 #include "lg.h"
 
 /*H:600
  * begin.
  */
 
-/* There are several entries we don't let the Guest set.  The TSS entry is the
+/*
+ * There are several entries we don't let the Guest set.  The TSS entry is the
  * "Task State Segment" which controls all kinds of delicate things.  The
  * LGUEST_CS and LGUEST_DS entries are reserved for the Switcher, and the
- * the Guest can't be trusted to deal with double faults. */
+ * the Guest can't be trusted to deal with double faults.
+ */
 static bool ignored_gdt(unsigned int num)
 {
        return (num == GDT_ENTRY_TSS
@@ -53,42 +57,52 @@ static bool ignored_gdt(unsigned int num)
                || num == GDT_ENTRY_DOUBLEFAULT_TSS);
 }
 
-/*H:630 Once the Guest gave us new GDT entries, we fix them up a little.  We
+/*H:630
+ * Once the Guest gave us new GDT entries, we fix them up a little.  We
  * don't care if they're invalid: the worst that can happen is a General
  * Protection Fault in the Switcher when it restores a Guest segment register
  * which tries to use that entry.  Then we kill the Guest for causing such a
- * mess: the message will be "unhandled trap 256". */
+ * mess: the message will be "unhandled trap 256".
+ */
 static void fixup_gdt_table(struct lg_cpu *cpu, unsigned start, unsigned end)
 {
        unsigned int i;
 
        for (i = start; i < end; i++) {
-               /* We never copy these ones to real GDT, so we don't care what
-                * they say */
+               /*
+                * We never copy these ones to real GDT, so we don't care what
+                * they say
+                */
                if (ignored_gdt(i))
                        continue;
 
-               /* Segment descriptors contain a privilege level: the Guest is
+               /*
+                * Segment descriptors contain a privilege level: the Guest is
                 * sometimes careless and leaves this as 0, even though it's
-                * running at privilege level 1.  If so, we fix it here. */
+                * running at privilege level 1.  If so, we fix it here.
+                */
                if ((cpu->arch.gdt[i].b & 0x00006000) == 0)
                        cpu->arch.gdt[i].b |= (GUEST_PL << 13);
 
-               /* Each descriptor has an "accessed" bit.  If we don't set it
+               /*
+                * Each descriptor has an "accessed" bit.  If we don't set it
                 * now, the CPU will try to set it when the Guest first loads
                 * that entry into a segment register.  But the GDT isn't
-                * writable by the Guest, so bad things can happen. */
+                * writable by the Guest, so bad things can happen.
+                */
                cpu->arch.gdt[i].b |= 0x00000100;
        }
 }
 
-/*H:610 Like the IDT, we never simply use the GDT the Guest gives us.  We keep
+/*H:610
+ * Like the IDT, we never simply use the GDT the Guest gives us.  We keep
  * a GDT for each CPU, and copy across the Guest's entries each time we want to
  * run the Guest on that CPU.
  *
  * This routine is called at boot or modprobe time for each CPU to set up the
  * constant GDT entries: the ones which are the same no matter what Guest we're
- * running. */
+ * running.
+ */
 void setup_default_gdt_entries(struct lguest_ro_state *state)
 {
        struct desc_struct *gdt = state->guest_gdt;
@@ -98,30 +112,37 @@ void setup_default_gdt_entries(struct lguest_ro_state *state)
        gdt[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT;
        gdt[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT;
 
-       /* The TSS segment refers to the TSS entry for this particular CPU.
+       /*
+        * The TSS segment refers to the TSS entry for this particular CPU.
         * Forgive the magic flags: the 0x8900 means the entry is Present, it's
         * privilege level 0 Available 386 TSS system segment, and the 0x67
-        * means Saturn is eclipsed by Mercury in the twelfth house. */
+        * means Saturn is eclipsed by Mercury in the twelfth house.
+        */
        gdt[GDT_ENTRY_TSS].a = 0x00000067 | (tss << 16);
        gdt[GDT_ENTRY_TSS].b = 0x00008900 | (tss & 0xFF000000)
                | ((tss >> 16) & 0x000000FF);
 }
 
-/* This routine sets up the initial Guest GDT for booting.  All entries start
- * as 0 (unusable). */
+/*
+ * This routine sets up the initial Guest GDT for booting.  All entries start
+ * as 0 (unusable).
+ */
 void setup_guest_gdt(struct lg_cpu *cpu)
 {
-       /* Start with full 0-4G segments... */
+       /*
+        * Start with full 0-4G segments...except the Guest is allowed to use
+        * them, so set the privilege level appropriately in the flags.
+        */
        cpu->arch.gdt[GDT_ENTRY_KERNEL_CS] = FULL_EXEC_SEGMENT;
        cpu->arch.gdt[GDT_ENTRY_KERNEL_DS] = FULL_SEGMENT;
-       /* ...except the Guest is allowed to use them, so set the privilege
-        * level appropriately in the flags. */
        cpu->arch.gdt[GDT_ENTRY_KERNEL_CS].b |= (GUEST_PL << 13);
        cpu->arch.gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13);
 }
 
-/*H:650 An optimization of copy_gdt(), for just the three "thead-local storage"
- * entries. */
+/*H:650
+ * An optimization of copy_gdt(), for just the three "thead-local storage"
+ * entries.
+ */
 void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt)
 {
        unsigned int i;
@@ -130,26 +151,34 @@ void copy_gdt_tls(const struct lg_cpu *cpu, struct desc_struct *gdt)
                gdt[i] = cpu->arch.gdt[i];
 }
 
-/*H:640 When the Guest is run on a different CPU, or the GDT entries have
- * changed, copy_gdt() is called to copy the Guest's GDT entries across to this
- * CPU's GDT. */
+/*H:640
+ * When the Guest is run on a different CPU, or the GDT entries have changed,
+ * copy_gdt() is called to copy the Guest's GDT entries across to this CPU's
+ * GDT.
+ */
 void copy_gdt(const struct lg_cpu *cpu, struct desc_struct *gdt)
 {
        unsigned int i;
 
-       /* The default entries from setup_default_gdt_entries() are not
-        * replaced.  See ignored_gdt() above. */
+       /*
+        * The default entries from setup_default_gdt_entries() are not
+        * replaced.  See ignored_gdt() above.
+        */
        for (i = 0; i < GDT_ENTRIES; i++)
                if (!ignored_gdt(i))
                        gdt[i] = cpu->arch.gdt[i];
 }
 
-/*H:620 This is where the Guest asks us to load a new GDT entry
- * (LHCALL_LOAD_GDT_ENTRY).  We tweak the entry and copy it in. */
+/*H:620
+ * This is where the Guest asks us to load a new GDT entry
+ * (LHCALL_LOAD_GDT_ENTRY).  We tweak the entry and copy it in.
+ */
 void load_guest_gdt_entry(struct lg_cpu *cpu, u32 num, u32 lo, u32 hi)
 {
-       /* We assume the Guest has the same number of GDT entries as the
-        * Host, otherwise we'd have to dynamically allocate the Guest GDT. */
+       /*
+        * We assume the Guest has the same number of GDT entries as the
+        * Host, otherwise we'd have to dynamically allocate the Guest GDT.
+        */
        if (num >= ARRAY_SIZE(cpu->arch.gdt))
                kill_guest(cpu, "too many gdt entries %i", num);
 
@@ -157,15 +186,19 @@ void load_guest_gdt_entry(struct lg_cpu *cpu, u32 num, u32 lo, u32 hi)
        cpu->arch.gdt[num].a = lo;
        cpu->arch.gdt[num].b = hi;
        fixup_gdt_table(cpu, num, num+1);
-       /* Mark that the GDT changed so the core knows it has to copy it again,
-        * even if the Guest is run on the same CPU. */
+       /*
+        * Mark that the GDT changed so the core knows it has to copy it again,
+        * even if the Guest is run on the same CPU.
+        */
        cpu->changed |= CHANGED_GDT;
 }
 
-/* This is the fast-track version for just changing the three TLS entries.
+/*
+ * This is the fast-track version for just changing the three TLS entries.
  * Remember that this happens on every context switch, so it's worth
  * optimizing.  But wouldn't it be neater to have a single hypercall to cover
- * both cases? */
+ * both cases?
+ */
 void guest_load_tls(struct lg_cpu *cpu, unsigned long gtls)
 {
        struct desc_struct *tls = &cpu->arch.gdt[GDT_ENTRY_TLS_MIN];
@@ -175,7 +208,6 @@ void guest_load_tls(struct lg_cpu *cpu, unsigned long gtls)
        /* Note that just the TLS entries have changed. */
        cpu->changed |= CHANGED_GDT_TLS;
 }
-/*:*/
 
 /*H:660
  * With this, we have finished the Host.
index eaf722fe309a2919de7cd3488b452b7604d94546..6ae388849a3b1c60c7b7263041c6f46552c1a7fc 100644 (file)
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/*P:450 This file contains the x86-specific lguest code.  It used to be all
+/*P:450
+ * This file contains the x86-specific lguest code.  It used to be all
  * mixed in with drivers/lguest/core.c but several foolhardy code slashers
  * wrestled most of the dependencies out to here in preparation for porting
  * lguest to other architectures (see what I mean by foolhardy?).
  *
  * This also contains a couple of non-obvious setup and teardown pieces which
- * were implemented after days of debugging pain. :*/
+ * were implemented after days of debugging pain.
+:*/
 #include <linux/kernel.h>
 #include <linux/start_kernel.h>
 #include <linux/string.h>
@@ -82,25 +84,33 @@ static DEFINE_PER_CPU(struct lg_cpu *, last_cpu);
  */
 static void copy_in_guest_info(struct lg_cpu *cpu, struct lguest_pages *pages)
 {
-       /* Copying all this data can be quite expensive.  We usually run the
+       /*
+        * Copying all this data can be quite expensive.  We usually run the
         * same Guest we ran last time (and that Guest hasn't run anywhere else
         * meanwhile).  If that's not the case, we pretend everything in the
-        * Guest has changed. */
+        * Guest has changed.
+        */
        if (__get_cpu_var(last_cpu) != cpu || cpu->last_pages != pages) {
                __get_cpu_var(last_cpu) = cpu;
                cpu->last_pages = pages;
                cpu->changed = CHANGED_ALL;
        }
 
-       /* These copies are pretty cheap, so we do them unconditionally: */
-       /* Save the current Host top-level page directory. */
+       /*
+        * These copies are pretty cheap, so we do them unconditionally: */
+       /* Save the current Host top-level page directory.
+        */
        pages->state.host_cr3 = __pa(current->mm->pgd);
-       /* Set up the Guest's page tables to see this CPU's pages (and no
-        * other CPU's pages). */
+       /*
+        * Set up the Guest's page tables to see this CPU's pages (and no
+        * other CPU's pages).
+        */
        map_switcher_in_guest(cpu, pages);
-       /* Set up the two "TSS" members which tell the CPU what stack to use
+       /*
+        * Set up the two "TSS" members which tell the CPU what stack to use
         * for traps which do directly into the Guest (ie. traps at privilege
-        * level 1). */
+        * level 1).
+        */
        pages->state.guest_tss.sp1 = cpu->esp1;
        pages->state.guest_tss.ss1 = cpu->ss1;
 
@@ -125,97 +135,126 @@ static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *pages)
        /* This is a dummy value we need for GCC's sake. */
        unsigned int clobber;
 
-       /* Copy the guest-specific information into this CPU's "struct
-        * lguest_pages". */
+       /*
+        * Copy the guest-specific information into this CPU's "struct
+        * lguest_pages".
+        */
        copy_in_guest_info(cpu, pages);
 
-       /* Set the trap number to 256 (impossible value).  If we fault while
+       /*
+        * Set the trap number to 256 (impossible value).  If we fault while
         * switching to the Guest (bad segment registers or bug), this will
-        * cause us to abort the Guest. */
+        * cause us to abort the Guest.
+        */
        cpu->regs->trapnum = 256;
 
-       /* Now: we push the "eflags" register on the stack, then do an "lcall".
+       /*
+        * Now: we push the "eflags" register on the stack, then do an "lcall".
         * This is how we change from using the kernel code segment to using
         * the dedicated lguest code segment, as well as jumping into the
         * Switcher.
         *
         * The lcall also pushes the old code segment (KERNEL_CS) onto the
         * stack, then the address of this call.  This stack layout happens to
-        * exactly match the stack layout created by an interrupt... */
+        * exactly match the stack layout created by an interrupt...
+        */
        asm volatile("pushf; lcall *lguest_entry"
-                    /* This is how we tell GCC that %eax ("a") and %ebx ("b")
-                     * are changed by this routine.  The "=" means output. */
+                    /*
+                     * This is how we tell GCC that %eax ("a") and %ebx ("b")
+                     * are changed by this routine.  The "=" means output.
+                     */
                     : "=a"(clobber), "=b"(clobber)
-                    /* %eax contains the pages pointer.  ("0" refers to the
+                    /*
+                     * %eax contains the pages pointer.  ("0" refers to the
                      * 0-th argument above, ie "a").  %ebx contains the
                      * physical address of the Guest's top-level page
-                     * directory. */
+                     * directory.
+                     */
                     : "0"(pages), "1"(__pa(cpu->lg->pgdirs[cpu->cpu_pgd].pgdir))
-                    /* We tell gcc that all these registers could change,
+                    /*
+                     * We tell gcc that all these registers could change,
                      * which means we don't have to save and restore them in
-                     * the Switcher. */
+                     * the Switcher.
+                     */
                     : "memory", "%edx", "%ecx", "%edi", "%esi");
 }
 /*:*/
 
-/*M:002 There are hooks in the scheduler which we can register to tell when we
+/*M:002
+ * There are hooks in the scheduler which we can register to tell when we
  * get kicked off the CPU (preempt_notifier_register()).  This would allow us
  * to lazily disable SYSENTER which would regain some performance, and should
  * also simplify copy_in_guest_info().  Note that we'd still need to restore
  * things when we exit to Launcher userspace, but that's fairly easy.
  *
- * We could also try using this hooks for PGE, but that might be too expensive.
+ * We could also try using these hooks for PGE, but that might be too expensive.
  *
- * The hooks were designed for KVM, but we can also put them to good use. :*/
+ * The hooks were designed for KVM, but we can also put them to good use.
+:*/
 
-/*H:040 This is the i386-specific code to setup and run the Guest.  Interrupts
- * are disabled: we own the CPU. */
+/*H:040
+ * This is the i386-specific code to setup and run the Guest.  Interrupts
+ * are disabled: we own the CPU.
+ */
 void lguest_arch_run_guest(struct lg_cpu *cpu)
 {
-       /* Remember the awfully-named TS bit?  If the Guest has asked to set it
+       /*
+        * Remember the awfully-named TS bit?  If the Guest has asked to set it
         * we set it now, so we can trap and pass that trap to the Guest if it
-        * uses the FPU. */
+        * uses the FPU.
+        */
        if (cpu->ts)
                unlazy_fpu(current);
 
-       /* SYSENTER is an optimized way of doing system calls.  We can't allow
+       /*
+        * SYSENTER is an optimized way of doing system calls.  We can't allow
         * it because it always jumps to privilege level 0.  A normal Guest
         * won't try it because we don't advertise it in CPUID, but a malicious
         * Guest (or malicious Guest userspace program) could, so we tell the
-        * CPU to disable it before running the Guest. */
+        * CPU to disable it before running the Guest.
+        */
        if (boot_cpu_has(X86_FEATURE_SEP))
                wrmsr(MSR_IA32_SYSENTER_CS, 0, 0);
 
-       /* Now we actually run the Guest.  It will return when something
+       /*
+        * Now we actually run the Guest.  It will return when something
         * interesting happens, and we can examine its registers to see what it
-        * was doing. */
+        * was doing.
+        */
        run_guest_once(cpu, lguest_pages(raw_smp_processor_id()));
 
-       /* Note that the "regs" structure contains two extra entries which are
+       /*
+        * Note that the "regs" structure contains two extra entries which are
         * not really registers: a trap number which says what interrupt or
         * trap made the switcher code come back, and an error code which some
-        * traps set.  */
+        * traps set.
+        */
 
         /* Restore SYSENTER if it's supposed to be on. */
         if (boot_cpu_has(X86_FEATURE_SEP))
                wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
 
-       /* If the Guest page faulted, then the cr2 register will tell us the
+       /*
+        * If the Guest page faulted, then the cr2 register will tell us the
         * bad virtual address.  We have to grab this now, because once we
         * re-enable interrupts an interrupt could fault and thus overwrite
-        * cr2, or we could even move off to a different CPU. */
+        * cr2, or we could even move off to a different CPU.
+        */
        if (cpu->regs->trapnum == 14)
                cpu->arch.last_pagefault = read_cr2();
-       /* Similarly, if we took a trap because the Guest used the FPU,
+       /*
+        * Similarly, if we took a trap because the Guest used the FPU,
         * we have to restore the FPU it expects to see.
         * math_state_restore() may sleep and we may even move off to
         * a different CPU. So all the critical stuff should be done
-        * before this.  */
+        * before this.
+        */
        else if (cpu->regs->trapnum == 7)
                math_state_restore();
 }
 
-/*H:130 Now we've examined the hypercall code; our Guest can make requests.
+/*H:130
+ * Now we've examined the hypercall code; our Guest can make requests.
  * Our Guest is usually so well behaved; it never tries to do things it isn't
  * allowed to, and uses hypercalls instead.  Unfortunately, Linux's paravirtual
  * infrastructure isn't quite complete, because it doesn't contain replacements
@@ -225,26 +264,33 @@ void lguest_arch_run_guest(struct lg_cpu *cpu)
  *
  * When the Guest uses one of these instructions, we get a trap (General
  * Protection Fault) and come here.  We see if it's one of those troublesome
- * instructions and skip over it.  We return true if we did. */
+ * instructions and skip over it.  We return true if we did.
+ */
 static int emulate_insn(struct lg_cpu *cpu)
 {
        u8 insn;
        unsigned int insnlen = 0, in = 0, shift = 0;
-       /* The eip contains the *virtual* address of the Guest's instruction:
-        * guest_pa just subtracts the Guest's page_offset. */
+       /*
+        * The eip contains the *virtual* address of the Guest's instruction:
+        * guest_pa just subtracts the Guest's page_offset.
+        */
        unsigned long physaddr = guest_pa(cpu, cpu->regs->eip);
 
-       /* This must be the Guest kernel trying to do something, not userspace!
+       /*
+        * This must be the Guest kernel trying to do something, not userspace!
         * The bottom two bits of the CS segment register are the privilege
-        * level. */
+        * level.
+        */
        if ((cpu->regs->cs & 3) != GUEST_PL)
                return 0;
 
        /* Decoding x86 instructions is icky. */
        insn = lgread(cpu, physaddr, u8);
 
-       /* 0x66 is an "operand prefix".  It means it's using the upper 16 bits
-          of the eax register. */
+       /*
+        * 0x66 is an "operand prefix".  It means it's using the upper 16 bits
+        * of the eax register.
+        */
        if (insn == 0x66) {
                shift = 16;
                /* The instruction is 1 byte so far, read the next byte. */
@@ -252,8 +298,10 @@ static int emulate_insn(struct lg_cpu *cpu)
                insn = lgread(cpu, physaddr + insnlen, u8);
        }
 
-       /* We can ignore the lower bit for the moment and decode the 4 opcodes
-        * we need to emulate. */
+       /*
+        * We can ignore the lower bit for the moment and decode the 4 opcodes
+        * we need to emulate.
+        */
        switch (insn & 0xFE) {
        case 0xE4: /* in     <next byte>,%al */
                insnlen += 2;
@@ -274,9 +322,11 @@ static int emulate_insn(struct lg_cpu *cpu)
                return 0;
        }
 
-       /* If it was an "IN" instruction, they expect the result to be read
+       /*
+        * If it was an "IN" instruction, they expect the result to be read
         * into %eax, so we change %eax.  We always return all-ones, which
-        * traditionally means "there's nothing there". */
+        * traditionally means "there's nothing there".
+        */
        if (in) {
                /* Lower bit tells is whether it's a 16 or 32 bit access */
                if (insn & 0x1)
@@ -290,7 +340,8 @@ static int emulate_insn(struct lg_cpu *cpu)
        return 1;
 }
 
-/* Our hypercalls mechanism used to be based on direct software interrupts.
+/*
+ * Our hypercalls mechanism used to be based on direct software interrupts.
  * After Anthony's "Refactor hypercall infrastructure" kvm patch, we decided to
  * change over to using kvm hypercalls.
  *
@@ -318,16 +369,20 @@ static int emulate_insn(struct lg_cpu *cpu)
  */
 static void rewrite_hypercall(struct lg_cpu *cpu)
 {
-       /* This are the opcodes we use to patch the Guest.  The opcode for "int
+       /*
+        * This are the opcodes we use to patch the Guest.  The opcode for "int
         * $0x1f" is "0xcd 0x1f" but vmcall instruction is 3 bytes long, so we
-        * complete the sequence with a NOP (0x90). */
+        * complete the sequence with a NOP (0x90).
+        */
        u8 insn[3] = {0xcd, 0x1f, 0x90};
 
        __lgwrite(cpu, guest_pa(cpu, cpu->regs->eip), insn, sizeof(insn));
-       /* The above write might have caused a copy of that page to be made
+       /*
+        * The above write might have caused a copy of that page to be made
         * (if it was read-only).  We need to make sure the Guest has
         * up-to-date pagetables.  As this doesn't happen often, we can just
-        * drop them all. */
+        * drop them all.
+        */
        guest_pagetable_clear_all(cpu);
 }
 
@@ -335,9 +390,11 @@ static bool is_hypercall(struct lg_cpu *cpu)
 {
        u8 insn[3];
 
-       /* This must be the Guest kernel trying to do something.
+       /*
+        * This must be the Guest kernel trying to do something.
         * The bottom two bits of the CS segment register are the privilege
-        * level. */
+        * level.
+        */
        if ((cpu->regs->cs & 3) != GUEST_PL)
                return false;
 
@@ -351,86 +408,105 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu)
 {
        switch (cpu->regs->trapnum) {
        case 13: /* We've intercepted a General Protection Fault. */
-               /* Check if this was one of those annoying IN or OUT
+               /*
+                * Check if this was one of those annoying IN or OUT
                 * instructions which we need to emulate.  If so, we just go
-                * back into the Guest after we've done it. */
+                * back into the Guest after we've done it.
+                */
                if (cpu->regs->errcode == 0) {
                        if (emulate_insn(cpu))
                                return;
                }
-               /* If KVM is active, the vmcall instruction triggers a
-                * General Protection Fault.  Normally it triggers an
-                * invalid opcode fault (6): */
+               /*
+                * If KVM is active, the vmcall instruction triggers a General
+                * Protection Fault.  Normally it triggers an invalid opcode
+                * fault (6):
+                */
        case 6:
-               /* We need to check if ring == GUEST_PL and
-                * faulting instruction == vmcall. */
+               /*
+                * We need to check if ring == GUEST_PL and faulting
+                * instruction == vmcall.
+                */
                if (is_hypercall(cpu)) {
                        rewrite_hypercall(cpu);
                        return;
                }
                break;
        case 14: /* We've intercepted a Page Fault. */
-               /* The Guest accessed a virtual address that wasn't mapped.
+               /*
+                * The Guest accessed a virtual address that wasn't mapped.
                 * This happens a lot: we don't actually set up most of the page
                 * tables for the Guest at all when we start: as it runs it asks
                 * for more and more, and we set them up as required. In this
                 * case, we don't even tell the Guest that the fault happened.
                 *
                 * The errcode tells whether this was a read or a write, and
-                * whether kernel or userspace code. */
+                * whether kernel or userspace code.
+                */
                if (demand_page(cpu, cpu->arch.last_pagefault,
                                cpu->regs->errcode))
                        return;
 
-               /* OK, it's really not there (or not OK): the Guest needs to
+               /*
+                * OK, it's really not there (or not OK): the Guest needs to
                 * know.  We write out the cr2 value so it knows where the
                 * fault occurred.
                 *
                 * Note that if the Guest were really messed up, this could
                 * happen before it's done the LHCALL_LGUEST_INIT hypercall, so
-                * lg->lguest_data could be NULL */
+                * lg->lguest_data could be NULL
+                */
                if (cpu->lg->lguest_data &&
                    put_user(cpu->arch.last_pagefault,
                             &cpu->lg->lguest_data->cr2))
                        kill_guest(cpu, "Writing cr2");
                break;
        case 7: /* We've intercepted a Device Not Available fault. */
-               /* If the Guest doesn't want to know, we already restored the
-                * Floating Point Unit, so we just continue without telling
-                * it. */
+               /*
+                * If the Guest doesn't want to know, we already restored the
+                * Floating Point Unit, so we just continue without telling it.
+                */
                if (!cpu->ts)
                        return;
                break;
        case 32 ... 255:
-               /* These values mean a real interrupt occurred, in which case
+               /*
+                * These values mean a real interrupt occurred, in which case
                 * the Host handler has already been run. We just do a
                 * friendly check if another process should now be run, then
-                * return to run the Guest again */
+                * return to run the Guest again
+                */
                cond_resched();
                return;
        case LGUEST_TRAP_ENTRY:
-               /* Our 'struct hcall_args' maps directly over our regs: we set
-                * up the pointer now to indicate a hypercall is pending. */
+               /*
+                * Our 'struct hcall_args' maps directly over our regs: we set
+                * up the pointer now to indicate a hypercall is pending.
+                */
                cpu->hcall = (struct hcall_args *)cpu->regs;
                return;
        }
 
        /* We didn't handle the trap, so it needs to go to the Guest. */
        if (!deliver_trap(cpu, cpu->regs->trapnum))
-               /* If the Guest doesn't have a handler (either it hasn't
+               /*
+                * If the Guest doesn't have a handler (either it hasn't
                 * registered any yet, or it's one of the faults we don't let
-                * it handle), it dies with this cryptic error message. */
+                * it handle), it dies with this cryptic error message.
+                */
                kill_guest(cpu, "unhandled trap %li at %#lx (%#lx)",
                           cpu->regs->trapnum, cpu->regs->eip,
                           cpu->regs->trapnum == 14 ? cpu->arch.last_pagefault
                           : cpu->regs->errcode);
 }
 
-/* Now we can look at each of the routines this calls, in increasing order of
+/*
+ * Now we can look at each of the routines this calls, in increasing order of
  * complexity: do_hypercalls(), emulate_insn(), maybe_do_interrupt(),
  * deliver_trap() and demand_page().  After all those, we'll be ready to
  * examine the Switcher, and our philosophical understanding of the Host/Guest
- * duality will be complete. :*/
+ * duality will be complete.
+:*/
 static void adjust_pge(void *on)
 {
        if (on)
@@ -439,13 +515,16 @@ static void adjust_pge(void *on)
                write_cr4(read_cr4() & ~X86_CR4_PGE);
 }
 
-/*H:020 Now the Switcher is mapped and every thing else is ready, we need to do
- * some more i386-specific initialization. */
+/*H:020
+ * Now the Switcher is mapped and every thing else is ready, we need to do
+ * some more i386-specific initialization.
+ */
 void __init lguest_arch_host_init(void)
 {
        int i;
 
-       /* Most of the i386/switcher.S doesn't care that it's been moved; on
+       /*
+        * Most of the i386/switcher.S doesn't care that it's been moved; on
         * Intel, jumps are relative, and it doesn't access any references to
         * external code or data.
         *
@@ -453,7 +532,8 @@ void __init lguest_arch_host_init(void)
         * addresses are placed in a table (default_idt_entries), so we need to
         * update the table with the new addresses.  switcher_offset() is a
         * convenience function which returns the distance between the
-        * compiled-in switcher code and the high-mapped copy we just made. */
+        * compiled-in switcher code and the high-mapped copy we just made.
+        */
        for (i = 0; i < IDT_ENTRIES; i++)
                default_idt_entries[i] += switcher_offset();
 
@@ -468,63 +548,81 @@ void __init lguest_arch_host_init(void)
        for_each_possible_cpu(i) {
                /* lguest_pages() returns this CPU's two pages. */
                struct lguest_pages *pages = lguest_pages(i);
-               /* This is a convenience pointer to make the code fit one
-                * statement to a line. */
+               /* This is a convenience pointer to make the code neater. */
                struct lguest_ro_state *state = &pages->state;
 
-               /* The Global Descriptor Table: the Host has a different one
+               /*
+                * The Global Descriptor Table: the Host has a different one
                 * for each CPU.  We keep a descriptor for the GDT which says
                 * where it is and how big it is (the size is actually the last
-                * byte, not the size, hence the "-1"). */
+                * byte, not the size, hence the "-1").
+                */
                state->host_gdt_desc.size = GDT_SIZE-1;
                state->host_gdt_desc.address = (long)get_cpu_gdt_table(i);
 
-               /* All CPUs on the Host use the same Interrupt Descriptor
+               /*
+                * All CPUs on the Host use the same Interrupt Descriptor
                 * Table, so we just use store_idt(), which gets this CPU's IDT
-                * descriptor. */
+                * descriptor.
+                */
                store_idt(&state->host_idt_desc);
 
-               /* The descriptors for the Guest's GDT and IDT can be filled
+               /*
+                * The descriptors for the Guest's GDT and IDT can be filled
                 * out now, too.  We copy the GDT & IDT into ->guest_gdt and
-                * ->guest_idt before actually running the Guest. */
+                * ->guest_idt before actually running the Guest.
+                */
                state->guest_idt_desc.size = sizeof(state->guest_idt)-1;
                state->guest_idt_desc.address = (long)&state->guest_idt;
                state->guest_gdt_desc.size = sizeof(state->guest_gdt)-1;
                state->guest_gdt_desc.address = (long)&state->guest_gdt;
 
-               /* We know where we want the stack to be when the Guest enters
+               /*
+                * We know where we want the stack to be when the Guest enters
                 * the Switcher: in pages->regs.  The stack grows upwards, so
-                * we start it at the end of that structure. */
+                * we start it at the end of that structure.
+                */
                state->guest_tss.sp0 = (long)(&pages->regs + 1);
-               /* And this is the GDT entry to use for the stack: we keep a
-                * couple of special LGUEST entries. */
+               /*
+                * And this is the GDT entry to use for the stack: we keep a
+                * couple of special LGUEST entries.
+                */
                state->guest_tss.ss0 = LGUEST_DS;
 
-               /* x86 can have a finegrained bitmap which indicates what I/O
+               /*
+                * x86 can have a finegrained bitmap which indicates what I/O
                 * ports the process can use.  We set it to the end of our
-                * structure, meaning "none". */
+                * structure, meaning "none".
+                */
                state->guest_tss.io_bitmap_base = sizeof(state->guest_tss);
 
-               /* Some GDT entries are the same across all Guests, so we can
-                * set them up now. */
+               /*
+                * Some GDT entries are the same across all Guests, so we can
+                * set them up now.
+                */
                setup_default_gdt_entries(state);
                /* Most IDT entries are the same for all Guests, too.*/
                setup_default_idt_entries(state, default_idt_entries);
 
-               /* The Host needs to be able to use the LGUEST segments on this
-                * CPU, too, so put them in the Host GDT. */
+               /*
+                * The Host needs to be able to use the LGUEST segments on this
+                * CPU, too, so put them in the Host GDT.
+                */
                get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT;
                get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT;
        }
 
-       /* In the Switcher, we want the %cs segment register to use the
+       /*
+        * In the Switcher, we want the %cs segment register to use the
         * LGUEST_CS GDT entry: we've put that in the Host and Guest GDTs, so
         * it will be undisturbed when we switch.  To change %cs and jump we
-        * need this structure to feed to Intel's "lcall" instruction. */
+        * need this structure to feed to Intel's "lcall" instruction.
+        */
        lguest_entry.offset = (long)switch_to_guest + switcher_offset();
        lguest_entry.segment = LGUEST_CS;
 
-       /* Finally, we need to turn off "Page Global Enable".  PGE is an
+       /*
+        * Finally, we need to turn off "Page Global Enable".  PGE is an
         * optimization where page table entries are specially marked to show
         * they never change.  The Host kernel marks all the kernel pages this
         * way because it's always present, even when userspace is running.
@@ -534,16 +632,21 @@ void __init lguest_arch_host_init(void)
         * you'll get really weird bugs that you'll chase for two days.
         *
         * I used to turn PGE off every time we switched to the Guest and back
-        * on when we return, but that slowed the Switcher down noticibly. */
+        * on when we return, but that slowed the Switcher down noticibly.
+        */
 
-       /* We don't need the complexity of CPUs coming and going while we're
-        * doing this. */
+       /*
+        * We don't need the complexity of CPUs coming and going while we're
+        * doing this.
+        */
        get_online_cpus();
        if (cpu_has_pge) { /* We have a broader idea of "global". */
                /* Remember that this was originally set (for cleanup). */
                cpu_had_pge = 1;
-               /* adjust_pge is a helper function which sets or unsets the PGE
-                * bit on its CPU, depending on the argument (0 == unset). */
+               /*
+                * adjust_pge is a helper function which sets or unsets the PGE
+                * bit on its CPU, depending on the argument (0 == unset).
+                */
                on_each_cpu(adjust_pge, (void *)0, 1);
                /* Turn off the feature in the global feature set. */
                clear_cpu_cap(&boot_cpu_data, X86_FEATURE_PGE);
@@ -590,26 +693,32 @@ int lguest_arch_init_hypercalls(struct lg_cpu *cpu)
 {
        u32 tsc_speed;
 
-       /* The pointer to the Guest's "struct lguest_data" is the only argument.
-        * We check that address now. */
+       /*
+        * The pointer to the Guest's "struct lguest_data" is the only argument.
+        * We check that address now.
+        */
        if (!lguest_address_ok(cpu->lg, cpu->hcall->arg1,
                               sizeof(*cpu->lg->lguest_data)))
                return -EFAULT;
 
-       /* Having checked it, we simply set lg->lguest_data to point straight
+       /*
+        * Having checked it, we simply set lg->lguest_data to point straight
         * into the Launcher's memory at the right place and then use
         * copy_to_user/from_user from now on, instead of lgread/write.  I put
         * this in to show that I'm not immune to writing stupid
-        * optimizations. */
+        * optimizations.
+        */
        cpu->lg->lguest_data = cpu->lg->mem_base + cpu->hcall->arg1;
 
-       /* We insist that the Time Stamp Counter exist and doesn't change with
+       /*
+        * We insist that the Time Stamp Counter exist and doesn't change with
         * cpu frequency.  Some devious chip manufacturers decided that TSC
         * changes could be handled in software.  I decided that time going
         * backwards might be good for benchmarks, but it's bad for users.
         *
         * We also insist that the TSC be stable: the kernel detects unreliable
-        * TSCs for its own purposes, and we use that here. */
+        * TSCs for its own purposes, and we use that here.
+        */
        if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && !check_tsc_unstable())
                tsc_speed = tsc_khz;
        else
@@ -625,38 +734,47 @@ int lguest_arch_init_hypercalls(struct lg_cpu *cpu)
 }
 /*:*/
 
-/*L:030 lguest_arch_setup_regs()
+/*L:030
+ * lguest_arch_setup_regs()
  *
  * Most of the Guest's registers are left alone: we used get_zeroed_page() to
- * allocate the structure, so they will be 0. */
+ * allocate the structure, so they will be 0.
+ */
 void lguest_arch_setup_regs(struct lg_cpu *cpu, unsigned long start)
 {
        struct lguest_regs *regs = cpu->regs;
 
-       /* There are four "segment" registers which the Guest needs to boot:
+       /*
+        * There are four "segment" registers which the Guest needs to boot:
         * The "code segment" register (cs) refers to the kernel code segment
         * __KERNEL_CS, and the "data", "extra" and "stack" segment registers
         * refer to the kernel data segment __KERNEL_DS.
         *
         * The privilege level is packed into the lower bits.  The Guest runs
-        * at privilege level 1 (GUEST_PL).*/
+        * at privilege level 1 (GUEST_PL).
+        */
        regs->ds = regs->es = regs->ss = __KERNEL_DS|GUEST_PL;
        regs->cs = __KERNEL_CS|GUEST_PL;
 
-       /* The "eflags" register contains miscellaneous flags.  Bit 1 (0x002)
+       /*
+        * The "eflags" register contains miscellaneous flags.  Bit 1 (0x002)
         * is supposed to always be "1".  Bit 9 (0x200) controls whether
         * interrupts are enabled.  We always leave interrupts enabled while
-        * running the Guest. */
+        * running the Guest.
+        */
        regs->eflags = X86_EFLAGS_IF | 0x2;
 
-       /* The "Extended Instruction Pointer" register says where the Guest is
-        * running. */
+       /*
+        * The "Extended Instruction Pointer" register says where the Guest is
+        * running.
+        */
        regs->eip = start;
 
-       /* %esi points to our boot information, at physical address 0, so don't
-        * touch it. */
+       /*
+        * %esi points to our boot information, at physical address 0, so don't
+        * touch it.
+        */
 
-       /* There are a couple of GDT entries the Guest expects when first
-        * booting. */
+       /* There are a couple of GDT entries the Guest expects at boot. */
        setup_guest_gdt(cpu);
 }
index 3fc15318a80ff50e58cdd1f2195748e0e718faff..40634b0db9f754fe822e63856d4a895cdca4100d 100644 (file)
@@ -1,12 +1,15 @@
-/*P:900 This is the Switcher: code which sits at 0xFFC00000 astride both the
- * Host and Guest to do the low-level Guest<->Host switch.  It is as simple as
- * it can be made, but it's naturally very specific to x86.
+/*P:900
+ * This is the Switcher: code which sits at 0xFFC00000 (or 0xFFE00000) astride
+ * both the Host and Guest to do the low-level Guest<->Host switch.  It is as
+ * simple as it can be made, but it's naturally very specific to x86.
  *
  * You have now completed Preparation.  If this has whet your appetite; if you
  * are feeling invigorated and refreshed then the next, more challenging stage
- * can be found in "make Guest". :*/
+ * can be found in "make Guest".
+ :*/
 
-/*M:012 Lguest is meant to be simple: my rule of thumb is that 1% more LOC must
+/*M:012
+ * Lguest is meant to be simple: my rule of thumb is that 1% more LOC must
  * gain at least 1% more performance.  Since neither LOC nor performance can be
  * measured beforehand, it generally means implementing a feature then deciding
  * if it's worth it.  And once it's implemented, who can say no?
  * Host (which is actually really easy).
  *
  * Two questions remain.  Would the performance gain outweigh the complexity?
- * And who would write the verse documenting it? :*/
+ * And who would write the verse documenting it?
+:*/
 
-/*M:011 Lguest64 handles NMI.  This gave me NMI envy (until I looked at their
+/*M:011
+ * Lguest64 handles NMI.  This gave me NMI envy (until I looked at their
  * code).  It's worth doing though, since it would let us use oprofile in the
- * Host when a Guest is running. :*/
+ * Host when a Guest is running.
+:*/
 
 /*S:100
  * Welcome to the Switcher itself!
index 6e149f4a1fff6d1b21decd90fe5109cdc06fa2db..a0f68386c12f3b5aa026f8cae8b470f23be41faa 100644 (file)
@@ -378,6 +378,17 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip,
        dev->ofdev.dev.bus = &macio_bus_type;
        dev->ofdev.dev.release = macio_release_dev;
 
+#ifdef CONFIG_PCI
+       /* Set the DMA ops to the ones from the PCI device, this could be
+        * fishy if we didn't know that on PowerMac it's always direct ops
+        * or iommu ops that will work fine
+        */
+       dev->ofdev.dev.archdata.dma_ops =
+               chip->lbus.pdev->dev.archdata.dma_ops;
+       dev->ofdev.dev.archdata.dma_data =
+               chip->lbus.pdev->dev.archdata.dma_data;
+#endif /* CONFIG_PCI */
+
 #ifdef DEBUG
        printk("preparing mdev @%p, ofdev @%p, dev @%p, kobj @%p\n",
               dev, &dev->ofdev, &dev->ofdev.dev, &dev->ofdev.dev.kobj);
index 4d686c0bdea0f196db01d170a3d287f1e1b6a7d0..9ab5b0c34f0d0e8ff5f759c1e59dfea3948e674a 100644 (file)
@@ -288,7 +288,7 @@ static void maciisi_sync(struct adb_request *req)
        }
        /* This could be BAD... when the ADB controller doesn't respond
         * for this long, it's probably not coming back :-( */
-       if(count >= 50) /* Hopefully shouldn't happen */
+       if (count > 50) /* Hopefully shouldn't happen */
                printk(KERN_ERR "maciisi_send_request: poll timed out!\n");
 }
 
index 9933eb861c7191b34fe43b9ac01deb5e44bd614f..ed1038164019a1d5935937037c6aae2bd429c666 100644 (file)
@@ -776,7 +776,7 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
                 * But don't wait if split was due to the io size restriction
                 */
                if (unlikely(out_of_pages))
-                       congestion_wait(WRITE, HZ/100);
+                       congestion_wait(BLK_RW_ASYNC, HZ/100);
 
                /*
                 * With async crypto it is unsafe to share the crypto context
@@ -1318,7 +1318,7 @@ static int crypt_iterate_devices(struct dm_target *ti,
 {
        struct crypt_config *cc = ti->private;
 
-       return fn(ti, cc->dev, cc->start, data);
+       return fn(ti, cc->dev, cc->start, ti->len, data);
 }
 
 static struct target_type crypt_target = {
index 4e5b843cd4d77fb388920991eefd5540e2399aef..ebe7381f47c8fd5b1d86cd4e603acad20eebe98f 100644 (file)
@@ -324,12 +324,12 @@ static int delay_iterate_devices(struct dm_target *ti,
        struct delay_c *dc = ti->private;
        int ret = 0;
 
-       ret = fn(ti, dc->dev_read, dc->start_read, data);
+       ret = fn(ti, dc->dev_read, dc->start_read, ti->len, data);
        if (ret)
                goto out;
 
        if (dc->dev_write)
-               ret = fn(ti, dc->dev_write, dc->start_write, data);
+               ret = fn(ti, dc->dev_write, dc->start_write, ti->len, data);
 
 out:
        return ret;
index c3ae51584b12f52fc1de3434965329c43a930363..556acff3952fe450e73e4673f46bcac84b453a47 100644 (file)
@@ -171,6 +171,14 @@ static int set_chunk_size(struct dm_exception_store *store,
         */
        chunk_size_ulong = round_up(chunk_size_ulong, PAGE_SIZE >> 9);
 
+       return dm_exception_store_set_chunk_size(store, chunk_size_ulong,
+                                                error);
+}
+
+int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
+                                     unsigned long chunk_size_ulong,
+                                     char **error)
+{
        /* Check chunk_size is a power of 2 */
        if (!is_power_of_2(chunk_size_ulong)) {
                *error = "Chunk size is not a power of 2";
@@ -183,6 +191,11 @@ static int set_chunk_size(struct dm_exception_store *store,
                return -EINVAL;
        }
 
+       if (chunk_size_ulong > INT_MAX >> SECTOR_SHIFT) {
+               *error = "Chunk size is too high";
+               return -EINVAL;
+       }
+
        store->chunk_size = chunk_size_ulong;
        store->chunk_mask = chunk_size_ulong - 1;
        store->chunk_shift = ffs(chunk_size_ulong) - 1;
@@ -195,7 +208,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
                              struct dm_exception_store **store)
 {
        int r = 0;
-       struct dm_exception_store_type *type;
+       struct dm_exception_store_type *type = NULL;
        struct dm_exception_store *tmp_store;
        char persistent;
 
@@ -211,12 +224,15 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
        }
 
        persistent = toupper(*argv[1]);
-       if (persistent != 'P' && persistent != 'N') {
+       if (persistent == 'P')
+               type = get_type("P");
+       else if (persistent == 'N')
+               type = get_type("N");
+       else {
                ti->error = "Persistent flag is not P or N";
                return -EINVAL;
        }
 
-       type = get_type(&persistent);
        if (!type) {
                ti->error = "Exception store type not recognised";
                r = -EINVAL;
index 2442c8c0789808607089722a2157ca94f4176c92..812c71872ba093643ba9a5e603fff2d22e4177fb 100644 (file)
@@ -168,6 +168,10 @@ static inline chunk_t sector_to_chunk(struct dm_exception_store *store,
 int dm_exception_store_type_register(struct dm_exception_store_type *type);
 int dm_exception_store_type_unregister(struct dm_exception_store_type *type);
 
+int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
+                                     unsigned long chunk_size_ulong,
+                                     char **error);
+
 int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
                              unsigned *args_used,
                              struct dm_exception_store **store);
index 9184b6deb8685dc3660e21dd438f6aa8fcd200b3..82f7d6e6b1eab551588ae6b8e917622151c4d4ff 100644 (file)
@@ -139,7 +139,7 @@ static int linear_iterate_devices(struct dm_target *ti,
 {
        struct linear_c *lc = ti->private;
 
-       return fn(ti, lc->dev, lc->start, data);
+       return fn(ti, lc->dev, lc->start, ti->len, data);
 }
 
 static struct target_type linear_target = {
index e69b96560997ee2dfd34236e8c1143d395f7550e..6e186b1a062d39bbf020788483c2d1bde85541a2 100644 (file)
@@ -21,6 +21,7 @@ struct log_c {
        struct dm_target *ti;
        uint32_t region_size;
        region_t region_count;
+       uint64_t luid;
        char uuid[DM_UUID_LEN];
 
        char *usr_argv_str;
@@ -63,7 +64,7 @@ static int userspace_do_request(struct log_c *lc, const char *uuid,
         * restored.
         */
 retry:
-       r = dm_consult_userspace(uuid, request_type, data,
+       r = dm_consult_userspace(uuid, lc->luid, request_type, data,
                                 data_size, rdata, rdata_size);
 
        if (r != -ESRCH)
@@ -74,14 +75,15 @@ retry:
                set_current_state(TASK_INTERRUPTIBLE);
                schedule_timeout(2*HZ);
                DMWARN("Attempting to contact userspace log server...");
-               r = dm_consult_userspace(uuid, DM_ULOG_CTR, lc->usr_argv_str,
+               r = dm_consult_userspace(uuid, lc->luid, DM_ULOG_CTR,
+                                        lc->usr_argv_str,
                                         strlen(lc->usr_argv_str) + 1,
                                         NULL, NULL);
                if (!r)
                        break;
        }
        DMINFO("Reconnected to userspace log server... DM_ULOG_CTR complete");
-       r = dm_consult_userspace(uuid, DM_ULOG_RESUME, NULL,
+       r = dm_consult_userspace(uuid, lc->luid, DM_ULOG_RESUME, NULL,
                                 0, NULL, NULL);
        if (!r)
                goto retry;
@@ -111,10 +113,9 @@ static int build_constructor_string(struct dm_target *ti,
                return -ENOMEM;
        }
 
-       for (i = 0, str_size = 0; i < argc; i++)
-               str_size += sprintf(str + str_size, "%s ", argv[i]);
-       str_size += sprintf(str + str_size, "%llu",
-                           (unsigned long long)ti->len);
+       str_size = sprintf(str, "%llu", (unsigned long long)ti->len);
+       for (i = 0; i < argc; i++)
+               str_size += sprintf(str + str_size, " %s", argv[i]);
 
        *ctr_str = str;
        return str_size;
@@ -154,6 +155,9 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
                return -ENOMEM;
        }
 
+       /* The ptr value is sufficient for local unique id */
+       lc->luid = (uint64_t)lc;
+
        lc->ti = ti;
 
        if (strlen(argv[0]) > (DM_UUID_LEN - 1)) {
@@ -173,7 +177,7 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
        }
 
        /* Send table string */
-       r = dm_consult_userspace(lc->uuid, DM_ULOG_CTR,
+       r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_CTR,
                                 ctr_str, str_size, NULL, NULL);
 
        if (r == -ESRCH) {
@@ -183,7 +187,7 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
 
        /* Since the region size does not change, get it now */
        rdata_size = sizeof(rdata);
-       r = dm_consult_userspace(lc->uuid, DM_ULOG_GET_REGION_SIZE,
+       r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_GET_REGION_SIZE,
                                 NULL, 0, (char *)&rdata, &rdata_size);
 
        if (r) {
@@ -212,7 +216,7 @@ static void userspace_dtr(struct dm_dirty_log *log)
        int r;
        struct log_c *lc = log->context;
 
-       r = dm_consult_userspace(lc->uuid, DM_ULOG_DTR,
+       r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_DTR,
                                 NULL, 0,
                                 NULL, NULL);
 
@@ -227,7 +231,7 @@ static int userspace_presuspend(struct dm_dirty_log *log)
        int r;
        struct log_c *lc = log->context;
 
-       r = dm_consult_userspace(lc->uuid, DM_ULOG_PRESUSPEND,
+       r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_PRESUSPEND,
                                 NULL, 0,
                                 NULL, NULL);
 
@@ -239,7 +243,7 @@ static int userspace_postsuspend(struct dm_dirty_log *log)
        int r;
        struct log_c *lc = log->context;
 
-       r = dm_consult_userspace(lc->uuid, DM_ULOG_POSTSUSPEND,
+       r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_POSTSUSPEND,
                                 NULL, 0,
                                 NULL, NULL);
 
@@ -252,7 +256,7 @@ static int userspace_resume(struct dm_dirty_log *log)
        struct log_c *lc = log->context;
 
        lc->in_sync_hint = 0;
-       r = dm_consult_userspace(lc->uuid, DM_ULOG_RESUME,
+       r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_RESUME,
                                 NULL, 0,
                                 NULL, NULL);
 
@@ -561,6 +565,7 @@ static int userspace_status(struct dm_dirty_log *log, status_type_t status_type,
                            char *result, unsigned maxlen)
 {
        int r = 0;
+       char *table_args;
        size_t sz = (size_t)maxlen;
        struct log_c *lc = log->context;
 
@@ -577,8 +582,12 @@ static int userspace_status(struct dm_dirty_log *log, status_type_t status_type,
                break;
        case STATUSTYPE_TABLE:
                sz = 0;
-               DMEMIT("%s %u %s %s", log->type->name, lc->usr_argc + 1,
-                      lc->uuid, lc->usr_argv_str);
+               table_args = strstr(lc->usr_argv_str, " ");
+               BUG_ON(!table_args); /* There will always be a ' ' */
+               table_args++;
+
+               DMEMIT("%s %u %s %s ", log->type->name, lc->usr_argc,
+                      lc->uuid, table_args);
                break;
        }
        return (r) ? 0 : (int)sz;
index 0ca1ee768a1fcf4ac0f995813e69485dad4b6d0f..ba0edad2d048017bd08257f0c7b34eb9f86bf1ea 100644 (file)
@@ -108,7 +108,7 @@ static int fill_pkg(struct cn_msg *msg, struct dm_ulog_request *tfr)
                                *(pkg->data_size) = 0;
                } else if (tfr->data_size > *(pkg->data_size)) {
                        DMERR("Insufficient space to receive package [%u] "
-                             "(%u vs %lu)", tfr->request_type,
+                             "(%u vs %zu)", tfr->request_type,
                              tfr->data_size, *(pkg->data_size));
 
                        *(pkg->data_size) = 0;
@@ -147,7 +147,8 @@ static void cn_ulog_callback(void *data)
 
 /**
  * dm_consult_userspace
- * @uuid: log's uuid (must be DM_UUID_LEN in size)
+ * @uuid: log's universal unique identifier (must be DM_UUID_LEN in size)
+ * @luid: log's local unique identifier
  * @request_type:  found in include/linux/dm-log-userspace.h
  * @data: data to tx to the server
  * @data_size: size of data in bytes
@@ -163,7 +164,7 @@ static void cn_ulog_callback(void *data)
  *
  * Returns: 0 on success, -EXXX on failure
  **/
-int dm_consult_userspace(const char *uuid, int request_type,
+int dm_consult_userspace(const char *uuid, uint64_t luid, int request_type,
                         char *data, size_t data_size,
                         char *rdata, size_t *rdata_size)
 {
@@ -190,6 +191,7 @@ resend:
 
        memset(tfr, 0, DM_ULOG_PREALLOCED_SIZE - overhead_size);
        memcpy(tfr->uuid, uuid, DM_UUID_LEN);
+       tfr->luid = luid;
        tfr->seq = dm_ulog_seq++;
 
        /*
index c26d8e4e2710b2dcd861d715b498bdbe32f5e962..04ee874f9153e73bdc2e2192840f2e9b36c883d2 100644 (file)
@@ -11,7 +11,7 @@
 
 int dm_ulog_tfr_init(void);
 void dm_ulog_tfr_exit(void);
-int dm_consult_userspace(const char *uuid, int request_type,
+int dm_consult_userspace(const char *uuid, uint64_t luid, int request_type,
                         char *data, size_t data_size,
                         char *rdata, size_t *rdata_size);
 
index c70604a208979b4b1f87e4a9e98f10b5ce00036d..6f0d90d4a541962e0ba289e5e2568da51d6445cb 100644 (file)
@@ -1453,7 +1453,7 @@ static int multipath_iterate_devices(struct dm_target *ti,
 
        list_for_each_entry(pg, &m->priority_groups, list) {
                list_for_each_entry(p, &pg->pgpaths, list) {
-                       ret = fn(ti, p->path.dev, ti->begin, data);
+                       ret = fn(ti, p->path.dev, ti->begin, ti->len, data);
                        if (ret)
                                goto out;
                }
index ce8868c768cce1c411d3ba76d4eae5b9011bee64..33f179e66bf55ab5d99d3c3fee3b4d02ab475c1f 100644 (file)
@@ -638,6 +638,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
                spin_lock_irq(&ms->lock);
                bio_list_merge(&ms->writes, &requeue);
                spin_unlock_irq(&ms->lock);
+               delayed_wake(ms);
        }
 
        /*
@@ -647,7 +648,13 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
         */
        dm_rh_inc_pending(ms->rh, &sync);
        dm_rh_inc_pending(ms->rh, &nosync);
-       ms->log_failure = dm_rh_flush(ms->rh) ? 1 : 0;
+
+       /*
+        * If the flush fails on a previous call and succeeds here,
+        * we must not reset the log_failure variable.  We need
+        * userspace interaction to do that.
+        */
+       ms->log_failure = dm_rh_flush(ms->rh) ? 1 : ms->log_failure;
 
        /*
         * Dispatch io.
@@ -1292,7 +1299,7 @@ static int mirror_iterate_devices(struct dm_target *ti,
 
        for (i = 0; !ret && i < ms->nr_mirrors; i++)
                ret = fn(ti, ms->mirror[i].dev,
-                        ms->mirror[i].offset, data);
+                        ms->mirror[i].offset, ti->len, data);
 
        return ret;
 }
index 6e3fe4f14934811ddd0f9bba845ebdd4bb504036..d5b2e08750d59d6574884c66424916d3d3d6f6ff 100644 (file)
@@ -105,6 +105,13 @@ struct pstore {
         */
        void *zero_area;
 
+       /*
+        * An area used for header. The header can be written
+        * concurrently with metadata (when invalidating the snapshot),
+        * so it needs a separate buffer.
+        */
+       void *header_area;
+
        /*
         * Used to keep track of which metadata area the data in
         * 'chunk' refers to.
@@ -148,16 +155,27 @@ static int alloc_area(struct pstore *ps)
         */
        ps->area = vmalloc(len);
        if (!ps->area)
-               return r;
+               goto err_area;
 
        ps->zero_area = vmalloc(len);
-       if (!ps->zero_area) {
-               vfree(ps->area);
-               return r;
-       }
+       if (!ps->zero_area)
+               goto err_zero_area;
        memset(ps->zero_area, 0, len);
 
+       ps->header_area = vmalloc(len);
+       if (!ps->header_area)
+               goto err_header_area;
+
        return 0;
+
+err_header_area:
+       vfree(ps->zero_area);
+
+err_zero_area:
+       vfree(ps->area);
+
+err_area:
+       return r;
 }
 
 static void free_area(struct pstore *ps)
@@ -169,6 +187,10 @@ static void free_area(struct pstore *ps)
        if (ps->zero_area)
                vfree(ps->zero_area);
        ps->zero_area = NULL;
+
+       if (ps->header_area)
+               vfree(ps->header_area);
+       ps->header_area = NULL;
 }
 
 struct mdata_req {
@@ -188,7 +210,8 @@ static void do_metadata(struct work_struct *work)
 /*
  * Read or write a chunk aligned and sized block of data from a device.
  */
-static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata)
+static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw,
+                   int metadata)
 {
        struct dm_io_region where = {
                .bdev = ps->store->cow->bdev,
@@ -198,7 +221,7 @@ static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata)
        struct dm_io_request io_req = {
                .bi_rw = rw,
                .mem.type = DM_IO_VMA,
-               .mem.ptr.vma = ps->area,
+               .mem.ptr.vma = area,
                .client = ps->io_client,
                .notify.fn = NULL,
        };
@@ -240,7 +263,7 @@ static int area_io(struct pstore *ps, int rw)
 
        chunk = area_location(ps, ps->current_area);
 
-       r = chunk_io(ps, chunk, rw, 0);
+       r = chunk_io(ps, ps->area, chunk, rw, 0);
        if (r)
                return r;
 
@@ -254,20 +277,7 @@ static void zero_memory_area(struct pstore *ps)
 
 static int zero_disk_area(struct pstore *ps, chunk_t area)
 {
-       struct dm_io_region where = {
-               .bdev = ps->store->cow->bdev,
-               .sector = ps->store->chunk_size * area_location(ps, area),
-               .count = ps->store->chunk_size,
-       };
-       struct dm_io_request io_req = {
-               .bi_rw = WRITE,
-               .mem.type = DM_IO_VMA,
-               .mem.ptr.vma = ps->zero_area,
-               .client = ps->io_client,
-               .notify.fn = NULL,
-       };
-
-       return dm_io(&io_req, 1, &where, NULL);
+       return chunk_io(ps, ps->zero_area, area_location(ps, area), WRITE, 0);
 }
 
 static int read_header(struct pstore *ps, int *new_snapshot)
@@ -276,6 +286,7 @@ static int read_header(struct pstore *ps, int *new_snapshot)
        struct disk_header *dh;
        chunk_t chunk_size;
        int chunk_size_supplied = 1;
+       char *chunk_err;
 
        /*
         * Use default chunk size (or hardsect_size, if larger) if none supplied
@@ -297,11 +308,11 @@ static int read_header(struct pstore *ps, int *new_snapshot)
        if (r)
                return r;
 
-       r = chunk_io(ps, 0, READ, 1);
+       r = chunk_io(ps, ps->header_area, 0, READ, 1);
        if (r)
                goto bad;
 
-       dh = (struct disk_header *) ps->area;
+       dh = ps->header_area;
 
        if (le32_to_cpu(dh->magic) == 0) {
                *new_snapshot = 1;
@@ -319,20 +330,25 @@ static int read_header(struct pstore *ps, int *new_snapshot)
        ps->version = le32_to_cpu(dh->version);
        chunk_size = le32_to_cpu(dh->chunk_size);
 
-       if (!chunk_size_supplied || ps->store->chunk_size == chunk_size)
+       if (ps->store->chunk_size == chunk_size)
                return 0;
 
-       DMWARN("chunk size %llu in device metadata overrides "
-              "table chunk size of %llu.",
-              (unsigned long long)chunk_size,
-              (unsigned long long)ps->store->chunk_size);
+       if (chunk_size_supplied)
+               DMWARN("chunk size %llu in device metadata overrides "
+                      "table chunk size of %llu.",
+                      (unsigned long long)chunk_size,
+                      (unsigned long long)ps->store->chunk_size);
 
        /* We had a bogus chunk_size. Fix stuff up. */
        free_area(ps);
 
-       ps->store->chunk_size = chunk_size;
-       ps->store->chunk_mask = chunk_size - 1;
-       ps->store->chunk_shift = ffs(chunk_size) - 1;
+       r = dm_exception_store_set_chunk_size(ps->store, chunk_size,
+                                             &chunk_err);
+       if (r) {
+               DMERR("invalid on-disk chunk size %llu: %s.",
+                     (unsigned long long)chunk_size, chunk_err);
+               return r;
+       }
 
        r = dm_io_client_resize(sectors_to_pages(ps->store->chunk_size),
                                ps->io_client);
@@ -351,15 +367,15 @@ static int write_header(struct pstore *ps)
 {
        struct disk_header *dh;
 
-       memset(ps->area, 0, ps->store->chunk_size << SECTOR_SHIFT);
+       memset(ps->header_area, 0, ps->store->chunk_size << SECTOR_SHIFT);
 
-       dh = (struct disk_header *) ps->area;
+       dh = ps->header_area;
        dh->magic = cpu_to_le32(SNAP_MAGIC);
        dh->valid = cpu_to_le32(ps->valid);
        dh->version = cpu_to_le32(ps->version);
        dh->chunk_size = cpu_to_le32(ps->store->chunk_size);
 
-       return chunk_io(ps, 0, WRITE, 1);
+       return chunk_io(ps, ps->header_area, 0, WRITE, 1);
 }
 
 /*
@@ -679,6 +695,8 @@ static int persistent_ctr(struct dm_exception_store *store,
        ps->valid = 1;
        ps->version = SNAPSHOT_DISK_VERSION;
        ps->area = NULL;
+       ps->zero_area = NULL;
+       ps->header_area = NULL;
        ps->next_free = 2;      /* skipping the header and first area */
        ps->current_committed = 0;
 
index d573165cd2b788968f7d274e03966b96c93da889..57f1bf7f3b7a1d4ffd18f51563a2d5c52b0693ad 100644 (file)
@@ -1176,6 +1176,15 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
        return 0;
 }
 
+static int snapshot_iterate_devices(struct dm_target *ti,
+                                   iterate_devices_callout_fn fn, void *data)
+{
+       struct dm_snapshot *snap = ti->private;
+
+       return fn(ti, snap->origin, 0, ti->len, data);
+}
+
+
 /*-----------------------------------------------------------------
  * Origin methods
  *---------------------------------------------------------------*/
@@ -1410,20 +1419,29 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result,
        return 0;
 }
 
+static int origin_iterate_devices(struct dm_target *ti,
+                                 iterate_devices_callout_fn fn, void *data)
+{
+       struct dm_dev *dev = ti->private;
+
+       return fn(ti, dev, 0, ti->len, data);
+}
+
 static struct target_type origin_target = {
        .name    = "snapshot-origin",
-       .version = {1, 6, 0},
+       .version = {1, 7, 0},
        .module  = THIS_MODULE,
        .ctr     = origin_ctr,
        .dtr     = origin_dtr,
        .map     = origin_map,
        .resume  = origin_resume,
        .status  = origin_status,
+       .iterate_devices = origin_iterate_devices,
 };
 
 static struct target_type snapshot_target = {
        .name    = "snapshot",
-       .version = {1, 6, 0},
+       .version = {1, 7, 0},
        .module  = THIS_MODULE,
        .ctr     = snapshot_ctr,
        .dtr     = snapshot_dtr,
@@ -1431,6 +1449,7 @@ static struct target_type snapshot_target = {
        .end_io  = snapshot_end_io,
        .resume  = snapshot_resume,
        .status  = snapshot_status,
+       .iterate_devices = snapshot_iterate_devices,
 };
 
 static int __init dm_snapshot_init(void)
index b240e85ae39aa4b444135b0a71823e35b03aac49..3e563d251733439a2431b27c6b893299e67b46c3 100644 (file)
@@ -320,17 +320,28 @@ static int stripe_iterate_devices(struct dm_target *ti,
        int ret = 0;
        unsigned i = 0;
 
-       do
+       do {
                ret = fn(ti, sc->stripe[i].dev,
-                        sc->stripe[i].physical_start, data);
-       while (!ret && ++i < sc->stripes);
+                        sc->stripe[i].physical_start,
+                        sc->stripe_width, data);
+       } while (!ret && ++i < sc->stripes);
 
        return ret;
 }
 
+static void stripe_io_hints(struct dm_target *ti,
+                           struct queue_limits *limits)
+{
+       struct stripe_c *sc = ti->private;
+       unsigned chunk_size = (sc->chunk_mask + 1) << 9;
+
+       blk_limits_io_min(limits, chunk_size);
+       limits->io_opt = chunk_size * sc->stripes;
+}
+
 static struct target_type stripe_target = {
        .name   = "striped",
-       .version = {1, 2, 0},
+       .version = {1, 3, 0},
        .module = THIS_MODULE,
        .ctr    = stripe_ctr,
        .dtr    = stripe_dtr,
@@ -338,6 +349,7 @@ static struct target_type stripe_target = {
        .end_io = stripe_end_io,
        .status = stripe_status,
        .iterate_devices = stripe_iterate_devices,
+       .io_hints = stripe_io_hints,
 };
 
 int __init dm_stripe_init(void)
index 4899ebe767c86d342853397e23530cb3b0ea9eea..1a6cb3c7822ed96c6c0b2eaa764522c5f0e7ae89 100644 (file)
@@ -343,10 +343,10 @@ static void close_dev(struct dm_dev_internal *d, struct mapped_device *md)
 }
 
 /*
- * If possible, this checks an area of a destination device is valid.
+ * If possible, this checks an area of a destination device is invalid.
  */
-static int device_area_is_valid(struct dm_target *ti, struct dm_dev *dev,
-                               sector_t start, void *data)
+static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev,
+                                 sector_t start, sector_t len, void *data)
 {
        struct queue_limits *limits = data;
        struct block_device *bdev = dev->bdev;
@@ -357,36 +357,40 @@ static int device_area_is_valid(struct dm_target *ti, struct dm_dev *dev,
        char b[BDEVNAME_SIZE];
 
        if (!dev_size)
-               return 1;
-
-       if ((start >= dev_size) || (start + ti->len > dev_size)) {
-               DMWARN("%s: %s too small for target",
-                      dm_device_name(ti->table->md), bdevname(bdev, b));
                return 0;
+
+       if ((start >= dev_size) || (start + len > dev_size)) {
+               DMWARN("%s: %s too small for target: "
+                      "start=%llu, len=%llu, dev_size=%llu",
+                      dm_device_name(ti->table->md), bdevname(bdev, b),
+                      (unsigned long long)start,
+                      (unsigned long long)len,
+                      (unsigned long long)dev_size);
+               return 1;
        }
 
        if (logical_block_size_sectors <= 1)
-               return 1;
+               return 0;
 
        if (start & (logical_block_size_sectors - 1)) {
                DMWARN("%s: start=%llu not aligned to h/w "
-                      "logical block size %hu of %s",
+                      "logical block size %u of %s",
                       dm_device_name(ti->table->md),
                       (unsigned long long)start,
                       limits->logical_block_size, bdevname(bdev, b));
-               return 0;
+               return 1;
        }
 
-       if (ti->len & (logical_block_size_sectors - 1)) {
+       if (len & (logical_block_size_sectors - 1)) {
                DMWARN("%s: len=%llu not aligned to h/w "
-                      "logical block size %hu of %s",
+                      "logical block size %u of %s",
                       dm_device_name(ti->table->md),
-                      (unsigned long long)ti->len,
+                      (unsigned long long)len,
                       limits->logical_block_size, bdevname(bdev, b));
-               return 0;
+               return 1;
        }
 
-       return 1;
+       return 0;
 }
 
 /*
@@ -482,7 +486,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti,
 #define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))
 
 int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
-                        sector_t start, void *data)
+                        sector_t start, sector_t len, void *data)
 {
        struct queue_limits *limits = data;
        struct block_device *bdev = dev->bdev;
@@ -495,9 +499,16 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
                return 0;
        }
 
-       if (blk_stack_limits(limits, &q->limits, start) < 0)
-               DMWARN("%s: target device %s is misaligned",
-                      dm_device_name(ti->table->md), bdevname(bdev, b));
+       if (blk_stack_limits(limits, &q->limits, start << 9) < 0)
+               DMWARN("%s: target device %s is misaligned: "
+                      "physical_block_size=%u, logical_block_size=%u, "
+                      "alignment_offset=%u, start=%llu",
+                      dm_device_name(ti->table->md), bdevname(bdev, b),
+                      q->limits.physical_block_size,
+                      q->limits.logical_block_size,
+                      q->limits.alignment_offset,
+                      (unsigned long long) start << 9);
+
 
        /*
         * Check if merge fn is supported.
@@ -698,7 +709,7 @@ static int validate_hardware_logical_block_alignment(struct dm_table *table,
 
        if (remaining) {
                DMWARN("%s: table line %u (start sect %llu len %llu) "
-                      "not aligned to h/w logical block size %hu",
+                      "not aligned to h/w logical block size %u",
                       dm_device_name(table->md), i,
                       (unsigned long long) ti->begin,
                       (unsigned long long) ti->len,
@@ -830,11 +841,6 @@ unsigned dm_table_get_type(struct dm_table *t)
        return t->type;
 }
 
-bool dm_table_bio_based(struct dm_table *t)
-{
-       return dm_table_get_type(t) == DM_TYPE_BIO_BASED;
-}
-
 bool dm_table_request_based(struct dm_table *t)
 {
        return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED;
@@ -1001,12 +1007,16 @@ int dm_calculate_queue_limits(struct dm_table *table,
                ti->type->iterate_devices(ti, dm_set_device_limits,
                                          &ti_limits);
 
+               /* Set I/O hints portion of queue limits */
+               if (ti->type->io_hints)
+                       ti->type->io_hints(ti, &ti_limits);
+
                /*
                 * Check each device area is consistent with the target's
                 * overall queue limits.
                 */
-               if (!ti->type->iterate_devices(ti, device_area_is_valid,
-                                              &ti_limits))
+               if (ti->type->iterate_devices(ti, device_area_is_invalid,
+                                             &ti_limits))
                        return -EINVAL;
 
 combine_limits:
index 3c6d4ee8921d23ae0e63850ec47ca7185ef93953..b4845b14740d6f2bb43470d7fe5f35eaf3864d07 100644 (file)
@@ -738,16 +738,22 @@ static void rq_completed(struct mapped_device *md, int run_queue)
        dm_put(md);
 }
 
+static void free_rq_clone(struct request *clone)
+{
+       struct dm_rq_target_io *tio = clone->end_io_data;
+
+       blk_rq_unprep_clone(clone);
+       free_rq_tio(tio);
+}
+
 static void dm_unprep_request(struct request *rq)
 {
        struct request *clone = rq->special;
-       struct dm_rq_target_io *tio = clone->end_io_data;
 
        rq->special = NULL;
        rq->cmd_flags &= ~REQ_DONTPREP;
 
-       blk_rq_unprep_clone(clone);
-       free_rq_tio(tio);
+       free_rq_clone(clone);
 }
 
 /*
@@ -825,8 +831,7 @@ static void dm_end_request(struct request *clone, int error)
                        rq->sense_len = clone->sense_len;
        }
 
-       BUG_ON(clone->bio);
-       free_rq_tio(tio);
+       free_rq_clone(clone);
 
        blk_end_request_all(rq, error);
 
@@ -1017,7 +1022,7 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector,
        clone->bi_flags |= 1 << BIO_CLONED;
 
        if (bio_integrity(bio)) {
-               bio_integrity_clone(clone, bio, GFP_NOIO);
+               bio_integrity_clone(clone, bio, GFP_NOIO, bs);
                bio_integrity_trim(clone,
                                   bio_sector_offset(bio, idx, offset), len);
        }
@@ -1045,7 +1050,7 @@ static struct bio *clone_bio(struct bio *bio, sector_t sector,
        clone->bi_flags &= ~(1 << BIO_SEG_VALID);
 
        if (bio_integrity(bio)) {
-               bio_integrity_clone(clone, bio, GFP_NOIO);
+               bio_integrity_clone(clone, bio, GFP_NOIO, bs);
 
                if (idx != bio->bi_idx || clone->bi_size < bio->bi_size)
                        bio_integrity_trim(clone,
@@ -2203,16 +2208,6 @@ int dm_swap_table(struct mapped_device *md, struct dm_table *table)
                goto out;
        }
 
-       /*
-        * It is enought that blk_queue_ordered() is called only once when
-        * the first bio-based table is bound.
-        *
-        * This setting should be moved to alloc_dev() when request-based dm
-        * supports barrier.
-        */
-       if (!md->map && dm_table_bio_based(table))
-               blk_queue_ordered(md->queue, QUEUE_ORDERED_DRAIN, NULL);
-
        __unbind(md);
        r = __bind(md, table, &limits);
 
index 23278ae80f08dfc90c8458a3b6a700e4a2a87f8b..a7663eba17e2920ba84d5a7f41fe5fa015964590 100644 (file)
@@ -61,7 +61,6 @@ int dm_table_any_congested(struct dm_table *t, int bdi_bits);
 int dm_table_any_busy_target(struct dm_table *t);
 int dm_table_set_type(struct dm_table *t);
 unsigned dm_table_get_type(struct dm_table *t);
-bool dm_table_bio_based(struct dm_table *t);
 bool dm_table_request_based(struct dm_table *t);
 int dm_table_alloc_md_mempools(struct dm_table *t);
 void dm_table_free_md_mempools(struct dm_table *t);
index 15c8b7b25a9b9a053a7296e0ab7abc91efa88e05..5fe39c2a3d2b61b81e0b9a814dee6f636a16f5f3 100644 (file)
@@ -166,8 +166,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
                        rdev->sectors = sectors * mddev->chunk_sectors;
                }
 
-               blk_queue_stack_limits(mddev->queue,
-                                      rdev->bdev->bd_disk->queue);
+               disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                 rdev->data_offset << 9);
                /* as we don't honour merge_bvec_fn, we must never risk
                 * violating it, so limit ->max_sector to one PAGE, as
                 * a one page request is never in violation.
@@ -220,6 +220,7 @@ static int linear_run (mddev_t *mddev)
        mddev->queue->unplug_fn = linear_unplug;
        mddev->queue->backing_dev_info.congested_fn = linear_congested;
        mddev->queue->backing_dev_info.congested_data = mddev;
+       md_integrity_register(mddev);
        return 0;
 }
 
@@ -256,6 +257,7 @@ static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
        rcu_assign_pointer(mddev->private, newconf);
        md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
        set_capacity(mddev->gendisk, mddev->array_sectors);
+       revalidate_disk(mddev->gendisk);
        call_rcu(&oldconf->rcu, free_conf);
        return 0;
 }
index 09be637d52cbb6041a67166807f948f9a00f08f2..9dd872000cec843db28fd393f2eb3023725c4bf4 100644 (file)
@@ -359,6 +359,7 @@ static mddev_t * mddev_find(dev_t unit)
        else
                new->md_minor = MINOR(unit) >> MdpMinorShift;
 
+       mutex_init(&new->open_mutex);
        mutex_init(&new->reconfig_mutex);
        INIT_LIST_HEAD(&new->disks);
        INIT_LIST_HEAD(&new->all_mddevs);
@@ -1308,7 +1309,12 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
        }
        if (mddev->level != LEVEL_MULTIPATH) {
                int role;
-               role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
+               if (rdev->desc_nr < 0 ||
+                   rdev->desc_nr >= le32_to_cpu(sb->max_dev)) {
+                       role = 0xffff;
+                       rdev->desc_nr = -1;
+               } else
+                       role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
                switch(role) {
                case 0xffff: /* spare */
                        break;
@@ -1394,8 +1400,14 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
                if (rdev2->desc_nr+1 > max_dev)
                        max_dev = rdev2->desc_nr+1;
 
-       if (max_dev > le32_to_cpu(sb->max_dev))
+       if (max_dev > le32_to_cpu(sb->max_dev)) {
+               int bmask;
                sb->max_dev = cpu_to_le32(max_dev);
+               rdev->sb_size = max_dev * 2 + 256;
+               bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1;
+               if (rdev->sb_size & bmask)
+                       rdev->sb_size = (rdev->sb_size | bmask) + 1;
+       }
        for (i=0; i<max_dev;i++)
                sb->dev_roles[i] = cpu_to_le16(0xfffe);
        
@@ -1487,37 +1499,76 @@ static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
 
 static LIST_HEAD(pending_raid_disks);
 
-static void md_integrity_check(mdk_rdev_t *rdev, mddev_t *mddev)
+/*
+ * Try to register data integrity profile for an mddev
+ *
+ * This is called when an array is started and after a disk has been kicked
+ * from the array. It only succeeds if all working and active component devices
+ * are integrity capable with matching profiles.
+ */
+int md_integrity_register(mddev_t *mddev)
+{
+       mdk_rdev_t *rdev, *reference = NULL;
+
+       if (list_empty(&mddev->disks))
+               return 0; /* nothing to do */
+       if (blk_get_integrity(mddev->gendisk))
+               return 0; /* already registered */
+       list_for_each_entry(rdev, &mddev->disks, same_set) {
+               /* skip spares and non-functional disks */
+               if (test_bit(Faulty, &rdev->flags))
+                       continue;
+               if (rdev->raid_disk < 0)
+                       continue;
+               /*
+                * If at least one rdev is not integrity capable, we can not
+                * enable data integrity for the md device.
+                */
+               if (!bdev_get_integrity(rdev->bdev))
+                       return -EINVAL;
+               if (!reference) {
+                       /* Use the first rdev as the reference */
+                       reference = rdev;
+                       continue;
+               }
+               /* does this rdev's profile match the reference profile? */
+               if (blk_integrity_compare(reference->bdev->bd_disk,
+                               rdev->bdev->bd_disk) < 0)
+                       return -EINVAL;
+       }
+       /*
+        * All component devices are integrity capable and have matching
+        * profiles, register the common profile for the md device.
+        */
+       if (blk_integrity_register(mddev->gendisk,
+                       bdev_get_integrity(reference->bdev)) != 0) {
+               printk(KERN_ERR "md: failed to register integrity for %s\n",
+                       mdname(mddev));
+               return -EINVAL;
+       }
+       printk(KERN_NOTICE "md: data integrity on %s enabled\n",
+               mdname(mddev));
+       return 0;
+}
+EXPORT_SYMBOL(md_integrity_register);
+
+/* Disable data integrity if non-capable/non-matching disk is being added */
+void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
 {
-       struct mdk_personality *pers = mddev->pers;
-       struct gendisk *disk = mddev->gendisk;
        struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev);
-       struct blk_integrity *bi_mddev = blk_get_integrity(disk);
+       struct blk_integrity *bi_mddev = blk_get_integrity(mddev->gendisk);
 
-       /* Data integrity passthrough not supported on RAID 4, 5 and 6 */
-       if (pers && pers->level >= 4 && pers->level <= 6)
+       if (!bi_mddev) /* nothing to do */
                return;
-
-       /* If rdev is integrity capable, register profile for mddev */
-       if (!bi_mddev && bi_rdev) {
-               if (blk_integrity_register(disk, bi_rdev))
-                       printk(KERN_ERR "%s: %s Could not register integrity!\n",
-                              __func__, disk->disk_name);
-               else
-                       printk(KERN_NOTICE "Enabling data integrity on %s\n",
-                              disk->disk_name);
+       if (rdev->raid_disk < 0) /* skip spares */
                return;
-       }
-
-       /* Check that mddev and rdev have matching profiles */
-       if (blk_integrity_compare(disk, rdev->bdev->bd_disk) < 0) {
-               printk(KERN_ERR "%s: %s/%s integrity mismatch!\n", __func__,
-                      disk->disk_name, rdev->bdev->bd_disk->disk_name);
-               printk(KERN_NOTICE "Disabling data integrity on %s\n",
-                      disk->disk_name);
-               blk_integrity_unregister(disk);
-       }
+       if (bi_rdev && blk_integrity_compare(mddev->gendisk,
+                                            rdev->bdev->bd_disk) >= 0)
+               return;
+       printk(KERN_NOTICE "disabling data integrity on %s\n", mdname(mddev));
+       blk_integrity_unregister(mddev->gendisk);
 }
+EXPORT_SYMBOL(md_integrity_add_rdev);
 
 static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
 {
@@ -1591,7 +1642,6 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
        /* May as well allow recovery to be retried once */
        mddev->recovery_disabled = 0;
 
-       md_integrity_check(rdev, mddev);
        return 0;
 
  fail:
@@ -1756,9 +1806,10 @@ static void print_sb_1(struct mdp_superblock_1 *sb)
        __u8 *uuid;
 
        uuid = sb->set_uuid;
-       printk(KERN_INFO "md:  SB: (V:%u) (F:0x%08x) Array-ID:<%02x%02x%02x%02x"
-                       ":%02x%02x:%02x%02x:%02x%02x:%02x%02x%02x%02x%02x%02x>\n"
-              KERN_INFO "md:    Name: \"%s\" CT:%llu\n",
+       printk(KERN_INFO
+              "md:  SB: (V:%u) (F:0x%08x) Array-ID:<%02x%02x%02x%02x"
+              ":%02x%02x:%02x%02x:%02x%02x:%02x%02x%02x%02x%02x%02x>\n"
+              "md:    Name: \"%s\" CT:%llu\n",
                le32_to_cpu(sb->major_version),
                le32_to_cpu(sb->feature_map),
                uuid[0], uuid[1], uuid[2], uuid[3],
@@ -1770,12 +1821,13 @@ static void print_sb_1(struct mdp_superblock_1 *sb)
                       & MD_SUPERBLOCK_1_TIME_SEC_MASK);
 
        uuid = sb->device_uuid;
-       printk(KERN_INFO "md:       L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu"
+       printk(KERN_INFO
+              "md:       L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu"
                        " RO:%llu\n"
-              KERN_INFO "md:     Dev:%08x UUID: %02x%02x%02x%02x:%02x%02x:%02x%02x:%02x%02x"
-                       ":%02x%02x%02x%02x%02x%02x\n"
-              KERN_INFO "md:       (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n"
-              KERN_INFO "md:         (MaxDev:%u) \n",
+              "md:     Dev:%08x UUID: %02x%02x%02x%02x:%02x%02x:%02x%02x:%02x%02x"
+                       ":%02x%02x%02x%02x%02x%02x\n"
+              "md:       (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n"
+              "md:         (MaxDev:%u) \n",
                le32_to_cpu(sb->level),
                (unsigned long long)le64_to_cpu(sb->size),
                le32_to_cpu(sb->raid_disks),
@@ -1923,17 +1975,14 @@ repeat:
                /* otherwise we have to go forward and ... */
                mddev->events ++;
                if (!mddev->in_sync || mddev->recovery_cp != MaxSector) { /* not clean */
-                       /* .. if the array isn't clean, insist on an odd 'events' */
-                       if ((mddev->events&1)==0) {
-                               mddev->events++;
+                       /* .. if the array isn't clean, an 'even' event must also go
+                        * to spares. */
+                       if ((mddev->events&1)==0)
                                nospares = 0;
-                       }
                } else {
-                       /* otherwise insist on an even 'events' (for clean states) */
-                       if ((mddev->events&1)) {
-                               mddev->events++;
+                       /* otherwise an 'odd' event must go to spares */
+                       if ((mddev->events&1))
                                nospares = 0;
-                       }
                }
        }
 
@@ -2655,6 +2704,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
        ssize_t rv = len;
        struct mdk_personality *pers;
        void *priv;
+       mdk_rdev_t *rdev;
 
        if (mddev->pers == NULL) {
                if (len == 0)
@@ -2734,6 +2784,12 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
        mddev_suspend(mddev);
        mddev->pers->stop(mddev);
        module_put(mddev->pers->owner);
+       /* Invalidate devices that are now superfluous */
+       list_for_each_entry(rdev, &mddev->disks, same_set)
+               if (rdev->raid_disk >= mddev->raid_disks) {
+                       rdev->raid_disk = -1;
+                       clear_bit(In_sync, &rdev->flags);
+               }
        mddev->pers = pers;
        mddev->private = priv;
        strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
@@ -3543,6 +3599,7 @@ max_sync_store(mddev_t *mddev, const char *buf, size_t len)
                if (max < mddev->resync_min)
                        return -EINVAL;
                if (max < mddev->resync_max &&
+                   mddev->ro == 0 &&
                    test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
                        return -EBUSY;
 
@@ -3573,7 +3630,8 @@ 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)
+       if (mddev->pers == NULL || 
+           mddev->pers->quiesce == NULL)
                return -EINVAL;
        if (buf == e || (*e && *e != '\n'))
                return -EINVAL;
@@ -3601,7 +3659,8 @@ 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)
+       if (mddev->pers == NULL ||
+           mddev->pers->quiesce == NULL)
                return -EINVAL;
        if (buf == e || (*e && *e != '\n'))
                return -EINVAL;
@@ -3681,17 +3740,8 @@ array_size_store(mddev_t *mddev, const char *buf, size_t len)
 
        mddev->array_sectors = sectors;
        set_capacity(mddev->gendisk, mddev->array_sectors);
-       if (mddev->pers) {
-               struct block_device *bdev = bdget_disk(mddev->gendisk, 0);
-
-               if (bdev) {
-                       mutex_lock(&bdev->bd_inode->i_mutex);
-                       i_size_write(bdev->bd_inode,
-                                    (loff_t)mddev->array_sectors << 9);
-                       mutex_unlock(&bdev->bd_inode->i_mutex);
-                       bdput(bdev);
-               }
-       }
+       if (mddev->pers)
+               revalidate_disk(mddev->gendisk);
 
        return len;
 }
@@ -3844,11 +3894,9 @@ static int md_alloc(dev_t dev, char *name)
        flush_scheduled_work();
 
        mutex_lock(&disks_mutex);
-       if (mddev->gendisk) {
-               mutex_unlock(&disks_mutex);
-               mddev_put(mddev);
-               return -EEXIST;
-       }
+       error = -EEXIST;
+       if (mddev->gendisk)
+               goto abort;
 
        if (name) {
                /* Need to ensure that 'name' is not a duplicate.
@@ -3860,17 +3908,15 @@ static int md_alloc(dev_t dev, char *name)
                        if (mddev2->gendisk &&
                            strcmp(mddev2->gendisk->disk_name, name) == 0) {
                                spin_unlock(&all_mddevs_lock);
-                               return -EEXIST;
+                               goto abort;
                        }
                spin_unlock(&all_mddevs_lock);
        }
 
+       error = -ENOMEM;
        mddev->queue = blk_alloc_queue(GFP_KERNEL);
-       if (!mddev->queue) {
-               mutex_unlock(&disks_mutex);
-               mddev_put(mddev);
-               return -ENOMEM;
-       }
+       if (!mddev->queue)
+               goto abort;
        mddev->queue->queuedata = mddev;
 
        /* Can be unlocked because the queue is new: no concurrency */
@@ -3880,11 +3926,9 @@ static int md_alloc(dev_t dev, char *name)
 
        disk = alloc_disk(1 << shift);
        if (!disk) {
-               mutex_unlock(&disks_mutex);
                blk_cleanup_queue(mddev->queue);
                mddev->queue = NULL;
-               mddev_put(mddev);
-               return -ENOMEM;
+               goto abort;
        }
        disk->major = MAJOR(mddev->unit);
        disk->first_minor = unit << shift;
@@ -3906,16 +3950,22 @@ static int md_alloc(dev_t dev, char *name)
        mddev->gendisk = disk;
        error = kobject_init_and_add(&mddev->kobj, &md_ktype,
                                     &disk_to_dev(disk)->kobj, "%s", "md");
-       mutex_unlock(&disks_mutex);
-       if (error)
+       if (error) {
+               /* This isn't possible, but as kobject_init_and_add is marked
+                * __must_check, we must do something with the result
+                */
                printk(KERN_WARNING "md: cannot register %s/md - name in use\n",
                       disk->disk_name);
-       else {
+               error = 0;
+       }
+ abort:
+       mutex_unlock(&disks_mutex);
+       if (!error) {
                kobject_uevent(&mddev->kobj, KOBJ_ADD);
                mddev->sysfs_state = sysfs_get_dirent(mddev->kobj.sd, "array_state");
        }
        mddev_put(mddev);
-       return 0;
+       return error;
 }
 
 static struct kobject *md_probe(dev_t dev, int *part, void *data)
@@ -4044,10 +4094,6 @@ static int do_md_run(mddev_t * mddev)
        }
        strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
 
-       if (pers->level >= 4 && pers->level <= 6)
-               /* Cannot support integrity (yet) */
-               blk_integrity_unregister(mddev->gendisk);
-
        if (mddev->reshape_position != MaxSector &&
            pers->start_reshape == NULL) {
                /* This personality cannot handle reshaping... */
@@ -4185,6 +4231,7 @@ static int do_md_run(mddev_t * mddev)
        md_wakeup_thread(mddev->thread);
        md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */
 
+       revalidate_disk(mddev->gendisk);
        mddev->changed = 1;
        md_new_event(mddev);
        sysfs_notify_dirent(mddev->sysfs_state);
@@ -4256,12 +4303,11 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
        struct gendisk *disk = mddev->gendisk;
        mdk_rdev_t *rdev;
 
+       mutex_lock(&mddev->open_mutex);
        if (atomic_read(&mddev->openers) > is_open) {
                printk("md: %s still in use.\n",mdname(mddev));
-               return -EBUSY;
-       }
-
-       if (mddev->pers) {
+               err = -EBUSY;
+       } else if (mddev->pers) {
 
                if (mddev->sync_thread) {
                        set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
@@ -4318,8 +4364,12 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
                if (mode == 1)
                        set_disk_ro(disk, 1);
                clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+               err = 0;
        }
-
+out:
+       mutex_unlock(&mddev->open_mutex);
+       if (err)
+               return err;
        /*
         * Free resources if final stop
         */
@@ -4385,7 +4435,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
        blk_integrity_unregister(disk);
        md_new_event(mddev);
        sysfs_notify_dirent(mddev->sysfs_state);
-out:
        return err;
 }
 
@@ -5083,18 +5132,8 @@ static int update_size(mddev_t *mddev, sector_t num_sectors)
                        return -ENOSPC;
        }
        rv = mddev->pers->resize(mddev, num_sectors);
-       if (!rv) {
-               struct block_device *bdev;
-
-               bdev = bdget_disk(mddev->gendisk, 0);
-               if (bdev) {
-                       mutex_lock(&bdev->bd_inode->i_mutex);
-                       i_size_write(bdev->bd_inode,
-                                    (loff_t)mddev->array_sectors << 9);
-                       mutex_unlock(&bdev->bd_inode->i_mutex);
-                       bdput(bdev);
-               }
-       }
+       if (!rv)
+               revalidate_disk(mddev->gendisk);
        return rv;
 }
 
@@ -5480,12 +5519,12 @@ static int md_open(struct block_device *bdev, fmode_t mode)
        }
        BUG_ON(mddev != bdev->bd_disk->private_data);
 
-       if ((err = mutex_lock_interruptible_nested(&mddev->reconfig_mutex, 1)))
+       if ((err = mutex_lock_interruptible(&mddev->open_mutex)))
                goto out;
 
        err = 0;
        atomic_inc(&mddev->openers);
-       mddev_unlock(mddev);
+       mutex_unlock(&mddev->open_mutex);
 
        check_disk_change(bdev);
  out:
@@ -6334,10 +6373,16 @@ void md_do_sync(mddev_t *mddev)
                        sysfs_notify(&mddev->kobj, NULL, "sync_completed");
                }
 
-               if (j >= mddev->resync_max)
-                       wait_event(mddev->recovery_wait,
-                                  mddev->resync_max > j
-                                  || kthread_should_stop());
+               while (j >= mddev->resync_max && !kthread_should_stop()) {
+                       /* As this condition is controlled by user-space,
+                        * we can block indefinitely, so use '_interruptible'
+                        * to avoid triggering warnings.
+                        */
+                       flush_signals(current); /* just in case */
+                       wait_event_interruptible(mddev->recovery_wait,
+                                                mddev->resync_max > j
+                                                || kthread_should_stop());
+               }
 
                if (kthread_should_stop())
                        goto interrupted;
index 9430a110db934013cd68e30f0cbb563d7da8323b..f8fc188bc762d4b6fe1ffb5dadc9ac43a36d6dff 100644 (file)
@@ -223,6 +223,16 @@ struct mddev_s
                                                            * so we don't loop trying */
 
        int                             in_sync;        /* know to not need resync */
+       /* 'open_mutex' avoids races between 'md_open' and 'do_md_stop', so
+        * that we are never stopping an array while it is open.
+        * 'reconfig_mutex' protects all other reconfiguration.
+        * These locks are separate due to conflicting interactions
+        * with bdev->bd_mutex.
+        * Lock ordering is:
+        *  reconfig_mutex -> bd_mutex : e.g. do_md_run -> revalidate_disk
+        *  bd_mutex -> open_mutex:  e.g. __blkdev_get -> md_open
+        */
+       struct mutex                    open_mutex;
        struct mutex                    reconfig_mutex;
        atomic_t                        active;         /* general refcount */
        atomic_t                        openers;        /* number of active opens */
@@ -431,5 +441,7 @@ extern int md_allow_write(mddev_t *mddev);
 extern void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
 extern void md_set_array_sectors(mddev_t *mddev, sector_t array_sectors);
 extern int md_check_no_bitmap(mddev_t *mddev);
+extern int md_integrity_register(mddev_t *mddev);
+void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
 
 #endif /* _MD_MD_H */
index cbe368fa6598758da4d55b468acd8efd0d6c8710..7140909f6662ae752324e33ad586f02416f7158f 100644 (file)
@@ -294,7 +294,8 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
        for (path = first; path <= last; path++)
                if ((p=conf->multipaths+path)->rdev == NULL) {
                        q = rdev->bdev->bd_disk->queue;
-                       blk_queue_stack_limits(mddev->queue, q);
+                       disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                         rdev->data_offset << 9);
 
                /* as we don't honour merge_bvec_fn, we must never risk
                 * violating it, so limit ->max_sector to one PAGE, as
@@ -312,6 +313,7 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
                        set_bit(In_sync, &rdev->flags);
                        rcu_assign_pointer(p->rdev, rdev);
                        err = 0;
+                       md_integrity_add_rdev(rdev, mddev);
                        break;
                }
 
@@ -344,7 +346,9 @@ static int multipath_remove_disk(mddev_t *mddev, int number)
                        /* lost the race, try later */
                        err = -EBUSY;
                        p->rdev = rdev;
+                       goto abort;
                }
+               md_integrity_register(mddev);
        }
 abort:
 
@@ -463,9 +467,9 @@ static int multipath_run (mddev_t *mddev)
 
                disk = conf->multipaths + disk_idx;
                disk->rdev = rdev;
+               disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                 rdev->data_offset << 9);
 
-               blk_queue_stack_limits(mddev->queue,
-                                      rdev->bdev->bd_disk->queue);
                /* as we don't honour merge_bvec_fn, we must never risk
                 * violating it, not that we ever expect a device with
                 * a merge_bvec_fn to be involved in multipath */
@@ -518,7 +522,7 @@ static int multipath_run (mddev_t *mddev)
        mddev->queue->unplug_fn = multipath_unplug;
        mddev->queue->backing_dev_info.congested_fn = multipath_congested;
        mddev->queue->backing_dev_info.congested_data = mddev;
-
+       md_integrity_register(mddev);
        return 0;
 
 out_free_conf:
index ab4a489d8695f759e1ca4edc252f9636c5c31977..898e2bdfee477a8aba7a41615dee1398f7314646 100644 (file)
@@ -170,8 +170,8 @@ static int create_strip_zones(mddev_t *mddev)
                }
                dev[j] = rdev1;
 
-               blk_queue_stack_limits(mddev->queue,
-                                      rdev1->bdev->bd_disk->queue);
+               disk_stack_limits(mddev->gendisk, rdev1->bdev,
+                                 rdev1->data_offset << 9);
                /* as we don't honour merge_bvec_fn, we must never risk
                 * violating it, so limit ->max_sector to one PAGE, as
                 * a one page request is never in violation.
@@ -250,6 +250,11 @@ static int create_strip_zones(mddev_t *mddev)
                       mddev->chunk_sectors << 9);
                goto abort;
        }
+
+       blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9);
+       blk_queue_io_opt(mddev->queue,
+                        (mddev->chunk_sectors << 9) * mddev->raid_disks);
+
        printk(KERN_INFO "raid0: done.\n");
        mddev->private = conf;
        return 0;
@@ -346,6 +351,7 @@ static int raid0_run(mddev_t *mddev)
 
        blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec);
        dump_zones(mddev);
+       md_integrity_register(mddev);
        return 0;
 }
 
index 89939a7aef570b7673f163b0754bd87493646b25..8726fd7ebce5d7bebfb48012db4785fe4b612c56 100644 (file)
@@ -1123,8 +1123,8 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
        for (mirror = first; mirror <= last; mirror++)
                if ( !(p=conf->mirrors+mirror)->rdev) {
 
-                       blk_queue_stack_limits(mddev->queue,
-                                              rdev->bdev->bd_disk->queue);
+                       disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                         rdev->data_offset << 9);
                        /* as we don't honour merge_bvec_fn, we must never risk
                         * violating it, so limit ->max_sector to one PAGE, as
                         * a one page request is never in violation.
@@ -1144,7 +1144,7 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
                        rcu_assign_pointer(p->rdev, rdev);
                        break;
                }
-
+       md_integrity_add_rdev(rdev, mddev);
        print_conf(conf);
        return err;
 }
@@ -1178,7 +1178,9 @@ static int raid1_remove_disk(mddev_t *mddev, int number)
                        /* lost the race, try later */
                        err = -EBUSY;
                        p->rdev = rdev;
+                       goto abort;
                }
+               md_integrity_register(mddev);
        }
 abort:
 
@@ -1988,9 +1990,8 @@ static int run(mddev_t *mddev)
                disk = conf->mirrors + disk_idx;
 
                disk->rdev = rdev;
-
-               blk_queue_stack_limits(mddev->queue,
-                                      rdev->bdev->bd_disk->queue);
+               disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                 rdev->data_offset << 9);
                /* as we don't honour merge_bvec_fn, we must never risk
                 * violating it, so limit ->max_sector to one PAGE, as
                 * a one page request is never in violation.
@@ -2068,7 +2069,7 @@ static int run(mddev_t *mddev)
        mddev->queue->unplug_fn = raid1_unplug;
        mddev->queue->backing_dev_info.congested_fn = raid1_congested;
        mddev->queue->backing_dev_info.congested_data = mddev;
-
+       md_integrity_register(mddev);
        return 0;
 
 out_no_mem:
@@ -2133,6 +2134,7 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors)
                return -EINVAL;
        set_capacity(mddev->gendisk, mddev->array_sectors);
        mddev->changed = 1;
+       revalidate_disk(mddev->gendisk);
        if (sectors > mddev->dev_sectors &&
            mddev->recovery_cp == MaxSector) {
                mddev->recovery_cp = mddev->dev_sectors;
index ae12ceafe10c557fa79d4e6c367ceae44d144327..3d9020cf6f6e4482c857644f721366fb8102f3d3 100644 (file)
@@ -1151,8 +1151,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
        for ( ; mirror <= last ; mirror++)
                if ( !(p=conf->mirrors+mirror)->rdev) {
 
-                       blk_queue_stack_limits(mddev->queue,
-                                              rdev->bdev->bd_disk->queue);
+                       disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                         rdev->data_offset << 9);
                        /* as we don't honour merge_bvec_fn, we must never risk
                         * violating it, so limit ->max_sector to one PAGE, as
                         * a one page request is never in violation.
@@ -1170,6 +1170,7 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
                        break;
                }
 
+       md_integrity_add_rdev(rdev, mddev);
        print_conf(conf);
        return err;
 }
@@ -1203,7 +1204,9 @@ static int raid10_remove_disk(mddev_t *mddev, int number)
                        /* lost the race, try later */
                        err = -EBUSY;
                        p->rdev = rdev;
+                       goto abort;
                }
+               md_integrity_register(mddev);
        }
 abort:
 
@@ -2044,7 +2047,7 @@ raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks)
 static int run(mddev_t *mddev)
 {
        conf_t *conf;
-       int i, disk_idx;
+       int i, disk_idx, chunk_size;
        mirror_info_t *disk;
        mdk_rdev_t *rdev;
        int nc, fc, fo;
@@ -2130,6 +2133,14 @@ static int run(mddev_t *mddev)
        spin_lock_init(&conf->device_lock);
        mddev->queue->queue_lock = &conf->device_lock;
 
+       chunk_size = mddev->chunk_sectors << 9;
+       blk_queue_io_min(mddev->queue, chunk_size);
+       if (conf->raid_disks % conf->near_copies)
+               blk_queue_io_opt(mddev->queue, chunk_size * conf->raid_disks);
+       else
+               blk_queue_io_opt(mddev->queue, chunk_size *
+                                (conf->raid_disks / conf->near_copies));
+
        list_for_each_entry(rdev, &mddev->disks, same_set) {
                disk_idx = rdev->raid_disk;
                if (disk_idx >= mddev->raid_disks
@@ -2138,9 +2149,8 @@ static int run(mddev_t *mddev)
                disk = conf->mirrors + disk_idx;
 
                disk->rdev = rdev;
-
-               blk_queue_stack_limits(mddev->queue,
-                                      rdev->bdev->bd_disk->queue);
+               disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                 rdev->data_offset << 9);
                /* as we don't honour merge_bvec_fn, we must never risk
                 * violating it, so limit ->max_sector to one PAGE, as
                 * a one page request is never in violation.
@@ -2218,6 +2228,7 @@ static int run(mddev_t *mddev)
 
        if (conf->near_copies < mddev->raid_disks)
                blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec);
+       md_integrity_register(mddev);
        return 0;
 
 out_free_conf:
index f9f991e6e1389ffc90860571edf701ca13a6f292..b8a2c5dc67ba7753d575e27ce0036f440451664d 100644 (file)
@@ -3699,13 +3699,21 @@ static int make_request(struct request_queue *q, struct bio * bi)
                                        goto retry;
                                }
                        }
-                       /* FIXME what if we get a false positive because these
-                        * are being updated.
-                        */
-                       if (logical_sector >= mddev->suspend_lo &&
+
+                       if (bio_data_dir(bi) == WRITE &&
+                           logical_sector >= mddev->suspend_lo &&
                            logical_sector < mddev->suspend_hi) {
                                release_stripe(sh);
-                               schedule();
+                               /* As the suspend_* range is controlled by
+                                * userspace, we want an interruptible
+                                * wait.
+                                */
+                               flush_signals(current);
+                               prepare_to_wait(&conf->wait_for_overlap,
+                                               &w, TASK_INTERRUPTIBLE);
+                               if (logical_sector >= mddev->suspend_lo &&
+                                   logical_sector < mddev->suspend_hi)
+                                       schedule();
                                goto retry;
                        }
 
@@ -3777,7 +3785,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped
                    conf->reshape_progress < raid5_size(mddev, 0, 0)) {
                        sector_nr = raid5_size(mddev, 0, 0)
                                - conf->reshape_progress;
-               } else if (mddev->delta_disks > 0 &&
+               } else if (mddev->delta_disks >= 0 &&
                           conf->reshape_progress > 0)
                        sector_nr = conf->reshape_progress;
                sector_div(sector_nr, new_data_disks);
@@ -3991,6 +3999,9 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski
                return 0;
        }
 
+       /* Allow raid5_quiesce to complete */
+       wait_event(conf->wait_for_overlap, conf->quiesce != 2);
+
        if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
                return reshape_request(mddev, sector_nr, skipped);
 
@@ -4308,6 +4319,15 @@ raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks)
        return sectors * (raid_disks - conf->max_degraded);
 }
 
+static void free_conf(raid5_conf_t *conf)
+{
+       shrink_stripes(conf);
+       safe_put_page(conf->spare_page);
+       kfree(conf->disks);
+       kfree(conf->stripe_hashtbl);
+       kfree(conf);
+}
+
 static raid5_conf_t *setup_conf(mddev_t *mddev)
 {
        raid5_conf_t *conf;
@@ -4439,11 +4459,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev)
 
  abort:
        if (conf) {
-               shrink_stripes(conf);
-               safe_put_page(conf->spare_page);
-               kfree(conf->disks);
-               kfree(conf->stripe_hashtbl);
-               kfree(conf);
+               free_conf(conf);
                return ERR_PTR(-EIO);
        } else
                return ERR_PTR(-ENOMEM);
@@ -4452,7 +4468,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev)
 static int run(mddev_t *mddev)
 {
        raid5_conf_t *conf;
-       int working_disks = 0;
+       int working_disks = 0, chunk_size;
        mdk_rdev_t *rdev;
 
        if (mddev->recovery_cp != MaxSector)
@@ -4493,7 +4509,26 @@ static int run(mddev_t *mddev)
                           (old_disks-max_degraded));
                /* here_old is the first stripe that we might need to read
                 * from */
-               if (here_new >= here_old) {
+               if (mddev->delta_disks == 0) {
+                       /* We cannot be sure it is safe to start an in-place
+                        * reshape.  It is only safe if user-space if monitoring
+                        * and taking constant backups.
+                        * mdadm always starts a situation like this in
+                        * readonly mode so it can take control before
+                        * allowing any writes.  So just check for that.
+                        */
+                       if ((here_new * mddev->new_chunk_sectors != 
+                            here_old * mddev->chunk_sectors) ||
+                           mddev->ro == 0) {
+                               printk(KERN_ERR "raid5: in-place reshape must be started"
+                                      " in read-only mode - aborting\n");
+                               return -EINVAL;
+                       }
+               } else if (mddev->delta_disks < 0
+                   ? (here_new * mddev->new_chunk_sectors <=
+                      here_old * mddev->chunk_sectors)
+                   : (here_new * mddev->new_chunk_sectors >=
+                      here_old * mddev->chunk_sectors)) {
                        /* Reading from the same stripe as writing to - bad */
                        printk(KERN_ERR "raid5: reshape_position too early for "
                               "auto-recovery - aborting.\n");
@@ -4607,18 +4642,22 @@ static int run(mddev_t *mddev)
        md_set_array_sectors(mddev, raid5_size(mddev, 0, 0));
 
        blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec);
+       chunk_size = mddev->chunk_sectors << 9;
+       blk_queue_io_min(mddev->queue, chunk_size);
+       blk_queue_io_opt(mddev->queue, chunk_size *
+                        (conf->raid_disks - conf->max_degraded));
+
+       list_for_each_entry(rdev, &mddev->disks, same_set)
+               disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                 rdev->data_offset << 9);
 
        return 0;
 abort:
        md_unregister_thread(mddev->thread);
        mddev->thread = NULL;
        if (conf) {
-               shrink_stripes(conf);
                print_raid5_conf(conf);
-               safe_put_page(conf->spare_page);
-               kfree(conf->disks);
-               kfree(conf->stripe_hashtbl);
-               kfree(conf);
+               free_conf(conf);
        }
        mddev->private = NULL;
        printk(KERN_ALERT "raid5: failed to run raid set %s\n", mdname(mddev));
@@ -4633,13 +4672,10 @@ static int stop(mddev_t *mddev)
 
        md_unregister_thread(mddev->thread);
        mddev->thread = NULL;
-       shrink_stripes(conf);
-       kfree(conf->stripe_hashtbl);
        mddev->queue->backing_dev_info.congested_fn = NULL;
        blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
        sysfs_remove_group(&mddev->kobj, &raid5_attrs_group);
-       kfree(conf->disks);
-       kfree(conf);
+       free_conf(conf);
        mddev->private = NULL;
        return 0;
 }
@@ -4841,6 +4877,7 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors)
                return -EINVAL;
        set_capacity(mddev->gendisk, mddev->array_sectors);
        mddev->changed = 1;
+       revalidate_disk(mddev->gendisk);
        if (sectors > mddev->dev_sectors && mddev->recovery_cp == MaxSector) {
                mddev->recovery_cp = mddev->dev_sectors;
                set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -4986,7 +5023,7 @@ static int raid5_start_reshape(mddev_t *mddev)
                spin_unlock_irqrestore(&conf->device_lock, flags);
        }
        mddev->raid_disks = conf->raid_disks;
-       mddev->reshape_position = 0;
+       mddev->reshape_position = conf->reshape_progress;
        set_bit(MD_CHANGE_DEVS, &mddev->flags);
 
        clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
@@ -5041,7 +5078,6 @@ static void end_reshape(raid5_conf_t *conf)
  */
 static void raid5_finish_reshape(mddev_t *mddev)
 {
-       struct block_device *bdev;
        raid5_conf_t *conf = mddev->private;
 
        if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
@@ -5050,15 +5086,7 @@ static void raid5_finish_reshape(mddev_t *mddev)
                        md_set_array_sectors(mddev, raid5_size(mddev, 0, 0));
                        set_capacity(mddev->gendisk, mddev->array_sectors);
                        mddev->changed = 1;
-
-                       bdev = bdget_disk(mddev->gendisk, 0);
-                       if (bdev) {
-                               mutex_lock(&bdev->bd_inode->i_mutex);
-                               i_size_write(bdev->bd_inode,
-                                            (loff_t)mddev->array_sectors << 9);
-                               mutex_unlock(&bdev->bd_inode->i_mutex);
-                               bdput(bdev);
-                       }
+                       revalidate_disk(mddev->gendisk);
                } else {
                        int d;
                        mddev->degraded = conf->raid_disks;
@@ -5069,8 +5097,15 @@ static void raid5_finish_reshape(mddev_t *mddev)
                                        mddev->degraded--;
                        for (d = conf->raid_disks ;
                             d < conf->raid_disks - mddev->delta_disks;
-                            d++)
-                               raid5_remove_disk(mddev, d);
+                            d++) {
+                               mdk_rdev_t *rdev = conf->disks[d].rdev;
+                               if (rdev && raid5_remove_disk(mddev, d) == 0) {
+                                       char nm[20];
+                                       sprintf(nm, "rd%d", rdev->raid_disk);
+                                       sysfs_remove_link(&mddev->kobj, nm);
+                                       rdev->raid_disk = -1;
+                               }
+                       }
                }
                mddev->layout = conf->algorithm;
                mddev->chunk_sectors = conf->chunk_sectors;
@@ -5090,12 +5125,18 @@ static void raid5_quiesce(mddev_t *mddev, int state)
 
        case 1: /* stop all writes */
                spin_lock_irq(&conf->device_lock);
-               conf->quiesce = 1;
+               /* '2' tells resync/reshape to pause so that all
+                * active stripes can drain
+                */
+               conf->quiesce = 2;
                wait_event_lock_irq(conf->wait_for_stripe,
                                    atomic_read(&conf->active_stripes) == 0 &&
                                    atomic_read(&conf->active_aligned_reads) == 0,
                                    conf->device_lock, /* nothing */);
+               conf->quiesce = 1;
                spin_unlock_irq(&conf->device_lock);
+               /* allow reshape to continue */
+               wake_up(&conf->wait_for_overlap);
                break;
 
        case 0: /* re-enable writes */
index 825aa1412e6f0ca039cb3729aded3d970fdc266f..9f5dba244cb86e7e361e992bbd45fedd41b1a1f9 100644 (file)
@@ -64,24 +64,22 @@ static int qt1010_writereg(struct qt1010_priv *priv, u8 reg, u8 val)
 /* dump all registers */
 static void qt1010_dump_regs(struct qt1010_priv *priv)
 {
-       char buf[52], buf2[4];
        u8 reg, val;
 
        for (reg = 0; ; reg++) {
                if (reg % 16 == 0) {
                        if (reg)
-                               printk("%s\n", buf);
-                       sprintf(buf, "%02x: ", reg);
+                               printk(KERN_CONT "\n");
+                       printk(KERN_DEBUG "%02x:", reg);
                }
                if (qt1010_readreg(priv, reg, &val) == 0)
-                       sprintf(buf2, "%02x ", val);
+                       printk(KERN_CONT " %02x", val);
                else
-                       strcpy(buf2, "-- ");
-               strcat(buf, buf2);
+                       printk(KERN_CONT " --");
                if (reg == 0x2f)
                        break;
        }
-       printk("%s\n", buf);
+       printk(KERN_CONT "\n");
 }
 
 static int qt1010_set_params(struct dvb_frontend *fe,
index b6da9c3873fef280ba89d00234053d3a62b11ec6..f270e605da8328a728f3c844fbd88d74bcfa0d4d 100644 (file)
@@ -1096,8 +1096,19 @@ static int xc2028_set_params(struct dvb_frontend *fe,
        }
 
        /* All S-code tables need a 200kHz shift */
-       if (priv->ctrl.demod)
+       if (priv->ctrl.demod) {
                demod = priv->ctrl.demod + 200;
+               /*
+                * The DTV7 S-code table needs a 700 kHz shift.
+                * Thanks to Terry Wu <terrywu2009@gmail.com> for reporting this
+                *
+                * DTV7 is only used in Australia.  Germany or Italy may also
+                * use this firmware after initialization, but a tune to a UHF
+                * channel should then cause DTV78 to be used.
+                */
+               if (type & DTV7)
+                       demod += 500;
+       }
 
        return generic_set_freq(fe, p->frequency,
                                T_DIGITAL_TV, type, 0, demod);
@@ -1108,8 +1119,8 @@ static int xc2028_sleep(struct dvb_frontend *fe)
        struct xc2028_data *priv = fe->tuner_priv;
        int rc = 0;
 
-       /* Avoid firmware reload on slow devices */
-       if (no_poweroff)
+       /* Avoid firmware reload on slow devices or if PM disabled */
+       if (no_poweroff || priv->ctrl.disable_power_mgmt)
                return 0;
 
        tuner_dbg("Putting xc2028/3028 into poweroff mode.\n");
index 19de7928a74eb75b5a01177a633acdf7e7768559..a90c35d50add70c00a7deaa7476757d7d9cbd3bc 100644 (file)
@@ -38,6 +38,7 @@ struct xc2028_ctrl {
        unsigned int            input1:1;
        unsigned int            vhfbw7:1;
        unsigned int            uhfbw8:1;
+       unsigned int            disable_power_mgmt:1;
        unsigned int            demod;
        enum firmware_type      type:2;
 };
index efb4a6c2b57a5d39cf9c70a5cef455a9dbb528e4..9a6307a347b21e7169a41f4f4a9d1ecbce15dd3f 100644 (file)
 #include "tuner-simple.h"
 #include "stv0297.h"
 
+
+/* Can we use the specified front-end?  Remember that if we are compiled
+ * into the kernel we can't call code that's in modules.  */
+#define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \
+       (defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE)))
+
 /* lnb control */
-#if defined(CONFIG_DVB_MT312_MODULE) || defined(CONFIG_DVB_STV0299_MODULE)
+#if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299)
 static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
        struct flexcop_device *fc = fe->dvb->priv;
@@ -49,8 +55,7 @@ static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage
 }
 #endif
 
-#if defined(CONFIG_DVB_S5H1420_MODULE) || defined(CONFIG_DVB_STV0299_MODULE) \
-       || defined(CONFIG_DVB_MT312_MODULE)
+#if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312)
 static int flexcop_sleep(struct dvb_frontend* fe)
 {
        struct flexcop_device *fc = fe->dvb->priv;
@@ -61,7 +66,7 @@ static int flexcop_sleep(struct dvb_frontend* fe)
 #endif
 
 /* SkyStar2 DVB-S rev 2.3 */
-#if defined(CONFIG_DVB_MT312_MODULE)
+#if FE_SUPPORTED(MT312)
 static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
 {
 /* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */
@@ -193,10 +198,12 @@ static int skystar2_rev23_attach(struct flexcop_device *fc,
        }
        return 0;
 }
+#else
+#define skystar2_rev23_attach NULL
 #endif
 
 /* SkyStar2 DVB-S rev 2.6 */
-#if defined(CONFIG_DVB_STV0299_MODULE)
+#if FE_SUPPORTED(STV0299)
 static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe,
        u32 srate, u32 ratio)
 {
@@ -321,10 +328,12 @@ static int skystar2_rev26_attach(struct flexcop_device *fc,
        }
        return 0;
 }
+#else
+#define skystar2_rev26_attach NULL
 #endif
 
 /* SkyStar2 DVB-S rev 2.7 */
-#if defined(CONFIG_DVB_S5H1420_MODULE)
+#if FE_SUPPORTED(S5H1420) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_ITD1000)
 static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
        .demod_address = 0x53,
        .invert = 1,
@@ -385,10 +394,12 @@ fail:
        fc->fc_i2c_adap[0].no_base_addr = 0;
        return 0;
 }
+#else
+#define skystar2_rev27_attach NULL
 #endif
 
 /* SkyStar2 rev 2.8 */
-#if defined(CONFIG_DVB_CX24123_MODULE)
+#if FE_SUPPORTED(CX24123) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_CX24113)
 static struct cx24123_config skystar2_rev2_8_cx24123_config = {
        .demod_address = 0x55,
        .dont_use_pll = 1,
@@ -433,10 +444,12 @@ static int skystar2_rev28_attach(struct flexcop_device *fc,
         * IR-receiver (PIC16F818) - but the card has no input for that ??? */
        return 1;
 }
+#else
+#define skystar2_rev28_attach NULL
 #endif
 
 /* AirStar DVB-T */
-#if defined(CONFIG_DVB_MT352_MODULE)
+#if FE_SUPPORTED(MT352)
 static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe)
 {
        static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d };
@@ -495,10 +508,12 @@ static int airstar_dvbt_attach(struct flexcop_device *fc,
        }
        return 0;
 }
+#else
+#define airstar_dvbt_attach NULL
 #endif
 
 /* AirStar ATSC 1st generation */
-#if defined(CONFIG_DVB_BCM3510_MODULE)
+#if FE_SUPPORTED(BCM3510)
 static int flexcop_fe_request_firmware(struct dvb_frontend *fe,
        const struct firmware **fw, char* name)
 {
@@ -517,10 +532,12 @@ static int airstar_atsc1_attach(struct flexcop_device *fc,
        fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
        return fc->fe != NULL;
 }
+#else
+#define airstar_atsc1_attach NULL
 #endif
 
 /* AirStar ATSC 2nd generation */
-#if defined(CONFIG_DVB_NXT200X_MODULE)
+#if FE_SUPPORTED(NXT200X) && FE_SUPPORTED(PLL)
 static struct nxt200x_config samsung_tbmv_config = {
        .demod_address = 0x0a,
 };
@@ -535,10 +552,12 @@ static int airstar_atsc2_attach(struct flexcop_device *fc,
        return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
                            DVB_PLL_SAMSUNG_TBMV);
 }
+#else
+#define airstar_atsc2_attach NULL
 #endif
 
 /* AirStar ATSC 3rd generation */
-#if defined(CONFIG_DVB_LGDT330X_MODULE)
+#if FE_SUPPORTED(LGDT330X)
 static struct lgdt330x_config air2pc_atsc_hd5000_config = {
        .demod_address       = 0x59,
        .demod_chip          = LGDT3303,
@@ -556,10 +575,12 @@ static int airstar_atsc3_attach(struct flexcop_device *fc,
        return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
                            TUNER_LG_TDVS_H06XF);
 }
+#else
+#define airstar_atsc3_attach NULL
 #endif
 
 /* CableStar2 DVB-C */
-#if defined(CONFIG_DVB_STV0297_MODULE)
+#if FE_SUPPORTED(STV0297)
 static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
                struct dvb_frontend_parameters *fep)
 {
@@ -698,39 +719,23 @@ static int cablestar2_attach(struct flexcop_device *fc,
        fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
        return 1;
 }
+#else
+#define cablestar2_attach NULL
 #endif
 
 static struct {
        flexcop_device_type_t type;
        int (*attach)(struct flexcop_device *, struct i2c_adapter *);
 } flexcop_frontends[] = {
-#if defined(CONFIG_DVB_S5H1420_MODULE)
        { FC_SKY_REV27, skystar2_rev27_attach },
-#endif
-#if defined(CONFIG_DVB_CX24123_MODULE)
        { FC_SKY_REV28, skystar2_rev28_attach },
-#endif
-#if defined(CONFIG_DVB_STV0299_MODULE)
        { FC_SKY_REV26, skystar2_rev26_attach },
-#endif
-#if defined(CONFIG_DVB_MT352_MODULE)
        { FC_AIR_DVBT, airstar_dvbt_attach },
-#endif
-#if defined(CONFIG_DVB_NXT200X_MODULE)
        { FC_AIR_ATSC2, airstar_atsc2_attach },
-#endif
-#if defined(CONFIG_DVB_LGDT330X_MODULE)
        { FC_AIR_ATSC3, airstar_atsc3_attach },
-#endif
-#if defined(CONFIG_DVB_BCM3510_MODULE)
        { FC_AIR_ATSC1, airstar_atsc1_attach },
-#endif
-#if defined(CONFIG_DVB_STV0297_MODULE)
        { FC_CABLE, cablestar2_attach },
-#endif
-#if defined(CONFIG_DVB_MT312_MODULE)
        { FC_SKY_REV23, skystar2_rev23_attach },
-#endif
 };
 
 /* try to figure out the frontend */
@@ -738,6 +743,8 @@ int flexcop_frontend_init(struct flexcop_device *fc)
 {
        int i;
        for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) {
+               if (!flexcop_frontends[i].attach)
+                       continue;
                /* type needs to be set before, because of some workarounds
                 * done based on the probed card type */
                fc->dev_type = flexcop_frontends[i].type;
index 4601b059b2b20008b7b277f725ec66d207c83e42..0e246eaad05ab441360963e02672945e6d61534b 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/dvb/ca.h>
 #include "dvbdev.h"
index 79927305e84d42e63030e720a43c617c7f493b04..487919bea7ae0bf147004b6845611f24eea0537f 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/poll.h>
 #include <linux/fs.h>
 #include <linux/list.h>
-#include <linux/smp_lock.h>
 
 #define DVB_MAJOR 212
 
index 4cb31e7c13c2856be433e2feb3feee225d02db64..26690dfb32601b9fcde1825ba41d18392b663d08 100644 (file)
@@ -81,7 +81,6 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req)
 
        switch (req->cmd) {
        case GET_CONFIG:
-       case BOOT:
        case READ_MEMORY:
        case RECONNECT_USB:
        case GET_IR_CODE:
@@ -100,6 +99,7 @@ static int af9015_rw_udev(struct usb_device *udev, struct req_t *req)
        case WRITE_VIRTUAL_MEMORY:
        case COPY_FIRMWARE:
        case DOWNLOAD_FIRMWARE:
+       case BOOT:
                break;
        default:
                err("unknown command:%d", req->cmd);
index 136c5863d81b5859d38fefd33b496932e8f6cca5..12e018b4107daec6758c7571ef3bb3bd4e244159 100644 (file)
@@ -527,6 +527,10 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
        u8 i, buf[3] = {0, 0, 0};
        *auto_mode = 0; /* set if parameters are requested to auto set */
 
+       /* Try auto-detect transmission parameters in case of AUTO requested or
+          garbage parameters given by application for compatibility.
+          MPlayer seems to provide garbage parameters currently. */
+
        switch (params->transmission_mode) {
        case TRANSMISSION_MODE_AUTO:
                *auto_mode = 1;
@@ -536,7 +540,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
                buf[0] |= (1 << 0);
                break;
        default:
-               return -EINVAL;
+               deb_info("%s: invalid transmission_mode\n", __func__);
+               *auto_mode = 1;
        }
 
        switch (params->guard_interval) {
@@ -554,7 +559,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
                buf[0] |= (3 << 2);
                break;
        default:
-               return -EINVAL;
+               deb_info("%s: invalid guard_interval\n", __func__);
+               *auto_mode = 1;
        }
 
        switch (params->hierarchy_information) {
@@ -572,7 +578,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
                buf[0] |= (3 << 4);
                break;
        default:
-               return -EINVAL;
+               deb_info("%s: invalid hierarchy_information\n", __func__);
+               *auto_mode = 1;
        };
 
        switch (params->constellation) {
@@ -587,7 +594,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
                buf[1] |= (2 << 6);
                break;
        default:
-               return -EINVAL;
+               deb_info("%s: invalid constellation\n", __func__);
+               *auto_mode = 1;
        }
 
        /* Use HP. How and which case we can switch to LP? */
@@ -611,7 +619,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
                buf[2] |= (4 << 0);
                break;
        default:
-               return -EINVAL;
+               deb_info("%s: invalid code_rate_HP\n", __func__);
+               *auto_mode = 1;
        }
 
        switch (params->code_rate_LP) {
@@ -638,7 +647,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
                if (params->hierarchy_information == HIERARCHY_AUTO)
                        break;
        default:
-               return -EINVAL;
+               deb_info("%s: invalid code_rate_LP\n", __func__);
+               *auto_mode = 1;
        }
 
        switch (params->bandwidth) {
@@ -651,7 +661,8 @@ static int af9013_set_ofdm_params(struct af9013_state *state,
                buf[1] |= (2 << 2);
                break;
        default:
-               return -EINVAL;
+               deb_info("%s: invalid bandwidth\n", __func__);
+               buf[1] |= (2 << 2); /* cannot auto-detect BW, try 8 MHz */
        }
 
        /* program */
index ace5cb17165daddf0e78c82a08aeaf215b5dec4d..fbd838eca268765e79268a3165f3fb34f9908a8d 100644 (file)
@@ -380,7 +380,7 @@ struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
        struct cx22700_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct cx22700_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct cx22700_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
index 5d1abe34bddb5cfc17694a7459877aaf0cbb86f7..00b5c7e91d5d8189ca212f297fbd0fccf908ae29 100644 (file)
@@ -580,7 +580,7 @@ struct dvb_frontend *cx22702_attach(const struct cx22702_config *config,
        struct cx22702_state *state = NULL;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct cx22702_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct cx22702_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
index 87ae29db024fc2aea18122996b60ac29a879b24d..ffbcfabd83f0c861aa5b0dc2c1532f7380a46750 100644 (file)
@@ -598,7 +598,7 @@ struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
        int ret;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct cx24110_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct cx24110_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
index db8a937cc63008dbabe4a1225810f03e80916d31..a7fc7e53a5518f6b20edbb7d96d050c8a2a5dbe3 100644 (file)
@@ -117,7 +117,7 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void)
        struct dvb_dummy_fe_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* create dvb_frontend */
@@ -137,7 +137,7 @@ struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void)
        struct dvb_dummy_fe_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* create dvb_frontend */
@@ -157,7 +157,7 @@ struct dvb_frontend *dvb_dummy_fe_qam_attach(void)
        struct dvb_dummy_fe_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* create dvb_frontend */
index e1e70e9e0cb9ced61f4b71f96a882bff38d40965..3051b64aa17c6bd3c8d7b3fbaad1727908d92b26 100644 (file)
@@ -501,7 +501,7 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
                           { .addr = config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct l64781_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct l64781_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
index 855852fddf22c4ab294d15c81ee4a89f5df47720..bb37ed289a059542d2821b9612261a18e7751f1e 100644 (file)
@@ -387,7 +387,7 @@ lgs8gl5_attach(const struct lgs8gl5_config *config, struct i2c_adapter *i2c)
        dprintk("%s\n", __func__);
 
        /* Allocate memory for the internal state */
-       state = kmalloc(sizeof(struct lgs8gl5_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct lgs8gl5_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
index a621f727935f217eb91f78e84a025bfc7a36767b..f69daaac78c9bf431d1371914d208ad5a9f9811e 100644 (file)
@@ -782,7 +782,7 @@ struct dvb_frontend *mt312_attach(const struct mt312_config *config,
        struct mt312_state *state = NULL;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct mt312_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
index 0eef22dbf8a041ae5f82e0aecc5cc36770ab1d0a..a763ec756f7f84df840bcb38bfb3816ee016e174 100644 (file)
@@ -545,7 +545,7 @@ struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
        struct nxt6000_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct nxt6000_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct nxt6000_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
index 8133ea3cddd783023ff581c47c904b412ac47c0f..38e67accb8c360af874fc9b3d57804c523d4a34a 100644 (file)
@@ -562,7 +562,7 @@ struct dvb_frontend* or51132_attach(const struct or51132_config* config,
        struct or51132_state* state = NULL;
 
        /* Allocate memory for the internal state */
-       state = kmalloc(sizeof(struct or51132_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct or51132_state), GFP_KERNEL);
        if (state == NULL)
                return NULL;
 
index 16cf2fdd5d7d1c6a14189a5b56312a4b4acb3f99..c709ce6771c86ca831e9e17e1677e03da0b05e7c 100644 (file)
@@ -527,7 +527,7 @@ struct dvb_frontend* or51211_attach(const struct or51211_config* config,
        struct or51211_state* state = NULL;
 
        /* Allocate memory for the internal state */
-       state = kmalloc(sizeof(struct or51211_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct or51211_state), GFP_KERNEL);
        if (state == NULL)
                return NULL;
 
index 3e08d985d6e50cf2f1fb36df3169274c74b22dcb..fb30115184270e38883ebee422c5f54582d58884 100644 (file)
@@ -796,7 +796,7 @@ struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
        u16 reg;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct s5h1409_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct s5h1409_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
index 66e2dd6d6fe4eb725b21f203b21e180081c8ef45..d8adf1e32019a9f7b62a712d693dd242ee79e036 100644 (file)
@@ -844,7 +844,7 @@ struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
        u16 reg;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct s5h1411_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct s5h1411_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
index 0bd16af8a6cd0723ab127f5a8de3c8d99e81e581..9552a22ccffb23b215897979fd51f45a2d8dc07a 100644 (file)
@@ -928,7 +928,7 @@ struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
        dprintk("%s\n", __func__);
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct si21xx_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct si21xx_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
index 1c9a9b4051b9efdbc8a4a9eba005d74f883c4e11..b85eb60a893e34954a313382a2fad0b5d8a88499 100644 (file)
@@ -557,7 +557,7 @@ struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
        struct sp8870_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct sp8870_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct sp8870_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
index 559509ab4dabfc2f4376bb0b46d58315defb74fd..4a7c3d8426088bdccd39ab95b197b8b2963ab3d9 100644 (file)
@@ -557,7 +557,7 @@ struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
        struct sp887x_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct sp887x_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct sp887x_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
index ff1194de34c0cf176f655329af5213754b1f4fab..2930a5d6768a71d89d38ecf8d4a85b87c55a9905 100644 (file)
@@ -570,7 +570,7 @@ struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
        int id;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct stv0288_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct stv0288_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
index 62caf802ed990b0343e50f8374c97f451b7a5e50..4fd7479bb62b98fdba6d933cd1f34ac14ef9b6b3 100644 (file)
@@ -663,7 +663,7 @@ struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
        struct stv0297_state *state = NULL;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct stv0297_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct stv0297_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
index 6c1cb1973c6e09c90010a7ec0167a9e50ae5b23e..9688744697260e440221ce3017a4ebd5e0dac849 100644 (file)
@@ -667,7 +667,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
        int id;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct stv0299_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct stv0299_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
index f648fdb64bb7dd33753522bb70e6619bc8c42f87..f5d7b3277a2fa585360aaafda331669a11ecd95a 100644 (file)
@@ -413,7 +413,7 @@ struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
        u8 id;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct tda10021_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct tda10021_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
index cc8862ce4aae9fff195506148f229cc4336b9eef..4e2a7c8b2f624e41f4d33adb27ef717f5172ae79 100644 (file)
@@ -1095,7 +1095,7 @@ struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
        dprintk(1, "%s()\n", __func__);
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct tda10048_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct tda10048_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
index 4981cef8b444602d5f48a00881e2199843d073d1..f2a8abe0a243b87b09d09df9098991ba23036562 100644 (file)
@@ -1269,7 +1269,7 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
        int id;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
        if (!state) {
                printk(KERN_ERR "Can't alocate memory for tda10045 state\n");
                return NULL;
@@ -1339,7 +1339,7 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
        int id;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
        if (!state) {
                printk(KERN_ERR "Can't alocate memory for tda10046 state\n");
                return NULL;
index a17ce3c4ad860c8959609e22c56679e5a004fda1..f2c8faac6f36426e0c7beb3f361e223b3b12cfcd 100644 (file)
@@ -745,7 +745,7 @@ struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
        dprintk ("%s\n", __func__);
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct tda10086_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct tda10086_state), GFP_KERNEL);
        if (!state)
                return NULL;
 
index 5b843b2e67e874c03f79cdfb1407680e16ee99ad..9369f7442f273b810c8568873047153d7a1149ba 100644 (file)
@@ -417,7 +417,7 @@ struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
        struct tda8083_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct tda8083_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct tda8083_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
index a184597f1d9be0002b8f567b245a849abef6553c..6e78e486551599bc47d76addb4e0af3e284175b6 100644 (file)
@@ -374,7 +374,7 @@ struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
        struct ves1820_state* state = NULL;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct ves1820_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct ves1820_state), GFP_KERNEL);
        if (state == NULL)
                goto error;
 
index bd558960bd87222eed8a71e7f696554e461ea9be..8d7854c2fb0c142683a2c823a3447af61c637438 100644 (file)
@@ -456,7 +456,7 @@ struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
        u8 identity;
 
        /* allocate memory for the internal state */
-       state = kmalloc(sizeof(struct ves1x93_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct ves1x93_state), GFP_KERNEL);
        if (state == NULL) goto error;
 
        /* setup the state */
index 148b6f7f6cb253534b785ef2e6a95769e236fa45..66f5c1fb3074e60e13d481b558d2403803e9d5eb 100644 (file)
@@ -98,7 +98,6 @@ static int zl10353_read_register(struct zl10353_state *state, u8 reg)
 static void zl10353_dump_regs(struct dvb_frontend *fe)
 {
        struct zl10353_state *state = fe->demodulator_priv;
-       char buf[52], buf2[4];
        int ret;
        u8 reg;
 
@@ -106,19 +105,18 @@ static void zl10353_dump_regs(struct dvb_frontend *fe)
        for (reg = 0; ; reg++) {
                if (reg % 16 == 0) {
                        if (reg)
-                               printk(KERN_DEBUG "%s\n", buf);
-                       sprintf(buf, "%02x: ", reg);
+                               printk(KERN_CONT "\n");
+                       printk(KERN_DEBUG "%02x:", reg);
                }
                ret = zl10353_read_register(state, reg);
                if (ret >= 0)
-                       sprintf(buf2, "%02x ", (u8)ret);
+                       printk(KERN_CONT " %02x", (u8)ret);
                else
-                       strcpy(buf2, "-- ");
-               strcat(buf, buf2);
+                       printk(KERN_CONT " --");
                if (reg == 0xff)
                        break;
        }
-       printk(KERN_DEBUG "%s\n", buf);
+       printk(KERN_CONT "\n");
 }
 
 static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
index dd863f26167244b1fa09925b6fa4bcec6ff0b682..8c1aed77ea30b9af7c281b13d079d30923fe7350 100644 (file)
@@ -2,25 +2,33 @@
 # Siano Mobile Silicon Digital TV device configuration
 #
 
-config DVB_SIANO_SMS1XXX
-       tristate "Siano SMS1XXX USB dongle support"
-       depends on DVB_CORE && USB
+config SMS_SIANO_MDTV
+       tristate "Siano SMS1xxx based MDTV receiver"
+       depends on DVB_CORE && INPUT
        ---help---
-         Choose Y here if you have a USB dongle with a SMS1XXX chipset.
+         Choose Y or M here if you have MDTV receiver with a Siano chipset.
 
-         To compile this driver as a module, choose M here: the
-         module will be called sms1xxx.
+         To compile this driver as a module, choose M here
+         (The module will be called smsmdtv).
 
-config DVB_SIANO_SMS1XXX_SMS_IDS
-       bool "Enable support for Siano Mobile Silicon default USB IDs"
-       depends on DVB_SIANO_SMS1XXX
-       default y
-       ---help---
-         Choose Y here if you have a USB dongle with a SMS1XXX chipset
-         that uses Siano Mobile Silicon's default usb vid:pid.
+         Further documentation on this driver can be found on the WWW
+         at http://www.siano-ms.com/
+
+if SMS_SIANO_MDTV
+menu "Siano module components"
 
-         Choose N here if you would prefer to use Siano's external driver.
+# Hardware interfaces support
 
-         Further documentation on this driver can be found on the WWW at
-         <http://www.siano-ms.com/>.
+config SMS_USB_DRV
+       tristate "USB interface support"
+       depends on DVB_CORE && USB
+       ---help---
+         Choose if you would like to have Siano's support for USB interface
 
+config SMS_SDIO_DRV
+       tristate "SDIO interface support"
+       depends on DVB_CORE && MMC
+       ---help---
+         Choose if you would like to have Siano's support for SDIO interface
+endmenu
+endif # SMS_SIANO_MDTV
index c6644d9094338ef252c2ca98ae4fd179199c67d7..c54140b5ab5a11e7defb883e3cda4e73d8b0406d 100644 (file)
@@ -1,8 +1,9 @@
-sms1xxx-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o
 
-obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o
-obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o
-obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsdvb.o
+smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o
+
+obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o
+obj-$(CONFIG_SMS_USB_DRV) += smsusb.o
+obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 
index d8b15d583bdeb2e662a3d336aabd7017d2414722..0420e2885e752971fd4ef1dbc01ac2d4d46e000f 100644 (file)
@@ -116,99 +116,21 @@ static inline void sms_gpio_assign_11xx_default_led_config(
 
 int sms_board_event(struct smscore_device_t *coredev,
                enum SMS_BOARD_EVENTS gevent) {
-       int board_id = smscore_get_board_id(coredev);
-       struct sms_board *board = sms_get_board(board_id);
        struct smscore_gpio_config MyGpioConfig;
 
        sms_gpio_assign_11xx_default_led_config(&MyGpioConfig);
 
        switch (gevent) {
        case BOARD_EVENT_POWER_INIT: /* including hotplug */
-               switch (board_id) {
-               case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
-                       /* set I/O and turn off all LEDs */
-                       smscore_gpio_configure(coredev,
-                                       board->board_cfg.leds_power,
-                                       &MyGpioConfig);
-                       smscore_gpio_set_level(coredev,
-                                       board->board_cfg.leds_power, 0);
-                       smscore_gpio_configure(coredev, board->board_cfg.led0,
-                                       &MyGpioConfig);
-                       smscore_gpio_set_level(coredev,
-                                       board->board_cfg.led0, 0);
-                       smscore_gpio_configure(coredev, board->board_cfg.led1,
-                                       &MyGpioConfig);
-                       smscore_gpio_set_level(coredev,
-                                       board->board_cfg.led1, 0);
-                       break;
-               case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
-               case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
-                       /* set I/O and turn off LNA */
-                       smscore_gpio_configure(coredev,
-                                       board->board_cfg.foreign_lna0_ctrl,
-                                       &MyGpioConfig);
-                       smscore_gpio_set_level(coredev,
-                                       board->board_cfg.foreign_lna0_ctrl,
-                                       0);
-                       break;
-               }
                break; /* BOARD_EVENT_BIND */
 
        case BOARD_EVENT_POWER_SUSPEND:
-               switch (board_id) {
-               case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
-                       smscore_gpio_set_level(coredev,
-                                               board->board_cfg.leds_power, 0);
-                       smscore_gpio_set_level(coredev,
-                                               board->board_cfg.led0, 0);
-                       smscore_gpio_set_level(coredev,
-                                               board->board_cfg.led1, 0);
-                       break;
-               case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
-               case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
-                       smscore_gpio_set_level(coredev,
-                                       board->board_cfg.foreign_lna0_ctrl,
-                                       0);
-                       break;
-               }
                break; /* BOARD_EVENT_POWER_SUSPEND */
 
        case BOARD_EVENT_POWER_RESUME:
-               switch (board_id) {
-               case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
-                       smscore_gpio_set_level(coredev,
-                                               board->board_cfg.leds_power, 1);
-                       smscore_gpio_set_level(coredev,
-                                               board->board_cfg.led0, 1);
-                       smscore_gpio_set_level(coredev,
-                                               board->board_cfg.led1, 0);
-                       break;
-               case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
-               case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
-                       smscore_gpio_set_level(coredev,
-                                       board->board_cfg.foreign_lna0_ctrl,
-                                       1);
-                       break;
-               }
                break; /* BOARD_EVENT_POWER_RESUME */
 
        case BOARD_EVENT_BIND:
-               switch (board_id) {
-               case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
-                       smscore_gpio_set_level(coredev,
-                               board->board_cfg.leds_power, 1);
-                       smscore_gpio_set_level(coredev,
-                               board->board_cfg.led0, 1);
-                       smscore_gpio_set_level(coredev,
-                               board->board_cfg.led1, 0);
-                       break;
-               case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
-               case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
-                       smscore_gpio_set_level(coredev,
-                                       board->board_cfg.foreign_lna0_ctrl,
-                                       1);
-                       break;
-               }
                break; /* BOARD_EVENT_BIND */
 
        case BOARD_EVENT_SCAN_PROG:
@@ -218,20 +140,8 @@ int sms_board_event(struct smscore_device_t *coredev,
        case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL:
                break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */
        case BOARD_EVENT_FE_LOCK:
-               switch (board_id) {
-               case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
-                       smscore_gpio_set_level(coredev,
-                       board->board_cfg.led1, 1);
-                       break;
-               }
                break; /* BOARD_EVENT_FE_LOCK */
        case BOARD_EVENT_FE_UNLOCK:
-               switch (board_id) {
-               case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
-                       smscore_gpio_set_level(coredev,
-                                               board->board_cfg.led1, 0);
-                       break;
-               }
                break; /* BOARD_EVENT_FE_UNLOCK */
        case BOARD_EVENT_DEMOD_LOCK:
                break; /* BOARD_EVENT_DEMOD_LOCK */
@@ -248,20 +158,8 @@ int sms_board_event(struct smscore_device_t *coredev,
        case BOARD_EVENT_RECEPTION_LOST_0:
                break; /* BOARD_EVENT_RECEPTION_LOST_0 */
        case BOARD_EVENT_MULTIPLEX_OK:
-               switch (board_id) {
-               case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
-                       smscore_gpio_set_level(coredev,
-                                               board->board_cfg.led1, 1);
-                       break;
-               }
                break; /* BOARD_EVENT_MULTIPLEX_OK */
        case BOARD_EVENT_MULTIPLEX_ERRORS:
-               switch (board_id) {
-               case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
-                       smscore_gpio_set_level(coredev,
-                                               board->board_cfg.led1, 0);
-                       break;
-               }
                break; /* BOARD_EVENT_MULTIPLEX_ERRORS */
 
        default:
index a246903c3341bea1ba919f9a6b5262e73e3d6d6a..bd9ab9d0d12a27d753f09dd79fcd882d0963d31f 100644 (file)
@@ -816,7 +816,7 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
 
        sms_debug("set device mode to %d", mode);
        if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
-               if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_RAW_TUNER) {
+               if (mode < DEVICE_MODE_DVBT || mode >= DEVICE_MODE_RAW_TUNER) {
                        sms_err("invalid mode specified %d", mode);
                        return -EINVAL;
                }
index 3ee1c3902c56dcc9d56a26380e5dadb07459cd99..266033ae2784ebd5568ab33e6e7a4318add7e234 100644 (file)
@@ -325,6 +325,16 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
                                                0 : -ETIME;
 }
 
+static inline int led_feedback(struct smsdvb_client_t *client)
+{
+       if (client->fe_status & FE_HAS_LOCK)
+               return sms_board_led_feedback(client->coredev,
+                       (client->sms_stat_dvb.ReceptionData.BER
+                       == 0) ? SMS_LED_HI : SMS_LED_LO);
+       else
+               return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
+}
+
 static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
 {
        struct smsdvb_client_t *client;
@@ -332,6 +342,8 @@ static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
 
        *stat = client->fe_status;
 
+       led_feedback(client);
+
        return 0;
 }
 
@@ -342,6 +354,8 @@ static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
 
        *ber = client->sms_stat_dvb.ReceptionData.BER;
 
+       led_feedback(client);
+
        return 0;
 }
 
@@ -359,6 +373,8 @@ static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
                                (client->sms_stat_dvb.ReceptionData.InBandPwr
                                + 95) * 3 / 2;
 
+       led_feedback(client);
+
        return 0;
 }
 
@@ -369,6 +385,8 @@ static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
 
        *snr = client->sms_stat_dvb.ReceptionData.SNR;
 
+       led_feedback(client);
+
        return 0;
 }
 
@@ -379,6 +397,8 @@ static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 
        *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
 
+       led_feedback(client);
+
        return 0;
 }
 
@@ -404,6 +424,8 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe,
                u32             Data[3];
        } Msg;
 
+       int ret;
+
        client->fe_status = FE_HAS_SIGNAL;
        client->event_fe_state = -1;
        client->event_unc_state = -1;
@@ -426,6 +448,23 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe,
        case BANDWIDTH_AUTO: return -EOPNOTSUPP;
        default: return -EINVAL;
        }
+       /* Disable LNA, if any. An error is returned if no LNA is present */
+       ret = sms_board_lna_control(client->coredev, 0);
+       if (ret == 0) {
+               fe_status_t status;
+
+               /* tune with LNA off at first */
+               ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
+                                                 &client->tune_done);
+
+               smsdvb_read_status(fe, &status);
+
+               if (status & FE_HAS_LOCK)
+                       return ret;
+
+               /* previous tune didnt lock - enable LNA and tune again */
+               sms_board_lna_control(client->coredev, 1);
+       }
 
        return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
                                           &client->tune_done);
@@ -451,6 +490,8 @@ static int smsdvb_init(struct dvb_frontend *fe)
        struct smsdvb_client_t *client =
                container_of(fe, struct smsdvb_client_t, frontend);
 
+       sms_board_power(client->coredev, 1);
+
        sms_board_dvb3_event(client, DVB3_EVENT_INIT);
        return 0;
 }
@@ -460,6 +501,9 @@ static int smsdvb_sleep(struct dvb_frontend *fe)
        struct smsdvb_client_t *client =
                container_of(fe, struct smsdvb_client_t, frontend);
 
+       sms_board_led_feedback(client->coredev, SMS_LED_OFF);
+       sms_board_power(client->coredev, 0);
+
        sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
 
        return 0;
index dfaa49a53f325ea917bd72d21fe91cc0a8c80cae..d1d652e7f8905868b27661a60af2f47d87f6ec75 100644 (file)
@@ -46,6 +46,7 @@
 
 #define SMSSDIO_DATA           0x00
 #define SMSSDIO_INT            0x04
+#define SMSSDIO_BLOCK_SIZE     128
 
 static const struct sdio_device_id smssdio_ids[] = {
        {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR),
@@ -85,7 +86,8 @@ static int smssdio_sendrequest(void *context, void *buffer, size_t size)
        sdio_claim_host(smsdev->func);
 
        while (size >= smsdev->func->cur_blksize) {
-               ret = sdio_write_blocks(smsdev->func, SMSSDIO_DATA, buffer, 1);
+               ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA,
+                                       buffer, smsdev->func->cur_blksize);
                if (ret)
                        goto out;
 
@@ -94,8 +96,8 @@ static int smssdio_sendrequest(void *context, void *buffer, size_t size)
        }
 
        if (size) {
-               ret = sdio_write_bytes(smsdev->func, SMSSDIO_DATA,
-                                      buffer, size);
+               ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA,
+                                       buffer, size);
        }
 
 out:
@@ -125,23 +127,23 @@ static void smssdio_interrupt(struct sdio_func *func)
         */
        isr = sdio_readb(func, SMSSDIO_INT, &ret);
        if (ret) {
-               dev_err(&smsdev->func->dev,
-                       "Unable to read interrupt register!\n");
+               sms_err("Unable to read interrupt register!\n");
                return;
        }
 
        if (smsdev->split_cb == NULL) {
                cb = smscore_getbuffer(smsdev->coredev);
                if (!cb) {
-                       dev_err(&smsdev->func->dev,
-                               "Unable to allocate data buffer!\n");
+                       sms_err("Unable to allocate data buffer!\n");
                        return;
                }
 
-               ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1);
+               ret = sdio_memcpy_fromio(smsdev->func,
+                                        cb->p,
+                                        SMSSDIO_DATA,
+                                        SMSSDIO_BLOCK_SIZE);
                if (ret) {
-                       dev_err(&smsdev->func->dev,
-                               "Error %d reading initial block!\n", ret);
+                       sms_err("Error %d reading initial block!\n", ret);
                        return;
                }
 
@@ -152,7 +154,10 @@ static void smssdio_interrupt(struct sdio_func *func)
                        return;
                }
 
-               size = hdr->msgLength - smsdev->func->cur_blksize;
+               if (hdr->msgLength > smsdev->func->cur_blksize)
+                       size = hdr->msgLength - smsdev->func->cur_blksize;
+               else
+                       size = 0;
        } else {
                cb = smsdev->split_cb;
                hdr = cb->p;
@@ -162,23 +167,24 @@ static void smssdio_interrupt(struct sdio_func *func)
                smsdev->split_cb = NULL;
        }
 
-       if (hdr->msgLength > smsdev->func->cur_blksize) {
+       if (size) {
                void *buffer;
 
-               size = ALIGN(size, 128);
-               buffer = cb->p + hdr->msgLength;
+               buffer = cb->p + (hdr->msgLength - size);
+               size = ALIGN(size, SMSSDIO_BLOCK_SIZE);
 
-               BUG_ON(smsdev->func->cur_blksize != 128);
+               BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE);
 
                /*
                 * First attempt to transfer all of it in one go...
                 */
-               ret = sdio_read_blocks(smsdev->func, buffer,
-                                      SMSSDIO_DATA, size / 128);
+               ret = sdio_memcpy_fromio(smsdev->func,
+                                        buffer,
+                                        SMSSDIO_DATA,
+                                        size);
                if (ret && ret != -EINVAL) {
                        smscore_putbuffer(smsdev->coredev, cb);
-                       dev_err(&smsdev->func->dev,
-                               "Error %d reading data from card!\n", ret);
+                       sms_err("Error %d reading data from card!\n", ret);
                        return;
                }
 
@@ -191,12 +197,12 @@ static void smssdio_interrupt(struct sdio_func *func)
                 */
                if (ret == -EINVAL) {
                        while (size) {
-                               ret = sdio_read_blocks(smsdev->func,
-                                                      buffer, SMSSDIO_DATA, 1);
+                               ret = sdio_memcpy_fromio(smsdev->func,
+                                                 buffer, SMSSDIO_DATA,
+                                                 smsdev->func->cur_blksize);
                                if (ret) {
                                        smscore_putbuffer(smsdev->coredev, cb);
-                                       dev_err(&smsdev->func->dev,
-                                               "Error %d reading "
+                                       sms_err("Error %d reading "
                                                "data from card!\n", ret);
                                        return;
                                }
@@ -269,7 +275,7 @@ static int smssdio_probe(struct sdio_func *func,
        if (ret)
                goto release;
 
-       ret = sdio_set_block_size(func, 128);
+       ret = sdio_set_block_size(func, SMSSDIO_BLOCK_SIZE);
        if (ret)
                goto disable;
 
index 68eb4493f991f64d08dc078225dc599380379ccc..d8d4214fd65f2c7af9d3af1a263a30f9dc24e3a9 100644 (file)
@@ -1,5 +1,6 @@
 config TTPCI_EEPROM
        tristate
+       depends on I2C
        default n
 
 config DVB_AV7110
index d1d959ed37b7947562394af311273e0343aec2c6..8d65c652ba5062c5c51765b887ea82ddb616f6f0 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/fs.h>
 #include <linux/timer.h>
 #include <linux/poll.h>
-#include <linux/smp_lock.h>
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
index 837467f93805e9c2f32b37c0f71cce6d3852ffef..575bf9d894193f83d465ced201bad022f1fb87b6 100644 (file)
@@ -58,6 +58,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/input.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
index 640421ceb24a2a48918b1692367c5394c6fd7968..e85f318b4d2b4131ff00395e61d17c66eeeecc18 100644 (file)
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/input.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
@@ -1200,7 +1201,7 @@ static int si470x_fops_release(struct file *file)
                        video_unregister_device(radio->videodev);
                        kfree(radio->buffer);
                        kfree(radio);
-                       goto done;
+                       goto unlock;
                }
 
                /* stop rds reception */
@@ -1213,9 +1214,8 @@ static int si470x_fops_release(struct file *file)
                retval = si470x_stop(radio);
                usb_autopm_put_interface(radio->intf);
        }
-
+unlock:
        mutex_unlock(&radio->disconnect_lock);
-
 done:
        return retval;
 }
index 061e147f6f2638d0c573e741a86d2e9dbe4a0630..dcf9fa9264bb720856775748a3e6e69d373fcee4 100644 (file)
@@ -312,6 +312,14 @@ config VIDEO_OV7670
          OV7670 VGA camera.  It currently only works with the M88ALP01
          controller.
 
+config VIDEO_MT9V011
+       tristate "Micron mt9v011 sensor support"
+       depends on I2C && VIDEO_V4L2
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the Micron
+         mt0v011 1.3 Mpixel camera.  It currently only works with the
+         em28xx driver.
+
 config VIDEO_TCM825X
        tristate "TCM825x camera sensor support"
        depends on I2C && VIDEO_V4L2
@@ -912,6 +920,8 @@ source "drivers/media/video/pwc/Kconfig"
 config USB_ZR364XX
        tristate "USB ZR364XX Camera support"
        depends on VIDEO_V4L2
+       select VIDEOBUF_GEN
+       select VIDEOBUF_VMALLOC
        ---help---
          Say Y here if you want to connect this type of camera to your
          computer's USB port.
index 7fb3add1b387916d9729279b2e78a2a786c7505a..9f2e3214a48207245dc2482b3f1f54777679c48a 100644 (file)
@@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
 obj-$(CONFIG_VIDEO_OV7670)     += ov7670.o
 obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
 obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
+obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
 
 obj-$(CONFIG_SOC_CAMERA_MT9M001)       += mt9m001.o
 obj-$(CONFIG_SOC_CAMERA_MT9M111)       += mt9m111.o
index fdb4adff3d287dd41b0777f9843321cf0c8682ea..ca6558c394be0c97484bc5f67093c9e3962bfe24 100644 (file)
@@ -3324,8 +3324,6 @@ void __devinit bttv_init_card1(struct bttv *btv)
 /* initialization part two -- after registering i2c bus */
 void __devinit bttv_init_card2(struct bttv *btv)
 {
-       int addr=ADDR_UNSET;
-
        btv->tuner_type = UNSET;
 
        if (BTTV_BOARD_UNKNOWN == btv->c.type) {
@@ -3470,9 +3468,6 @@ void __devinit bttv_init_card2(struct bttv *btv)
        btv->pll.pll_current = -1;
 
        /* tuner configuration (from card list / autodetect / insmod option) */
-       if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
-               addr = bttv_tvcards[btv->c.type].tuner_addr;
-
        if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
                if (UNSET == btv->tuner_type)
                        btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type;
@@ -3496,40 +3491,6 @@ void __devinit bttv_init_card2(struct bttv *btv)
        if (UNSET == btv->tuner_type)
                btv->tuner_type = TUNER_ABSENT;
 
-       if (btv->tuner_type != TUNER_ABSENT) {
-               struct tuner_setup tun_setup;
-
-               /* Load tuner module before issuing tuner config call! */
-               if (bttv_tvcards[btv->c.type].has_radio)
-                       v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
-                               &btv->c.i2c_adap, "tuner", "tuner",
-                               v4l2_i2c_tuner_addrs(ADDRS_RADIO));
-               v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
-                               &btv->c.i2c_adap, "tuner", "tuner",
-                               v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
-               v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
-                               &btv->c.i2c_adap, "tuner", "tuner",
-                               v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD));
-
-               tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
-               tun_setup.type = btv->tuner_type;
-               tun_setup.addr = addr;
-
-               if (bttv_tvcards[btv->c.type].has_radio)
-                       tun_setup.mode_mask |= T_RADIO;
-
-               bttv_call_all(btv, tuner, s_type_addr, &tun_setup);
-       }
-
-       if (btv->tda9887_conf) {
-               struct v4l2_priv_tun_config tda9887_cfg;
-
-               tda9887_cfg.tuner = TUNER_TDA9887;
-               tda9887_cfg.priv = &btv->tda9887_conf;
-
-               bttv_call_all(btv, tuner, s_config, &tda9887_cfg);
-       }
-
        btv->dig = bttv_tvcards[btv->c.type].has_dig_in ?
                   bttv_tvcards[btv->c.type].video_inputs - 1 : UNSET;
        btv->svhs = bttv_tvcards[btv->c.type].svhs == NO_SVHS ?
@@ -3540,15 +3501,15 @@ void __devinit bttv_init_card2(struct bttv *btv)
                btv->has_remote = remote[btv->c.nr];
 
        if (bttv_tvcards[btv->c.type].has_radio)
-               btv->has_radio=1;
+               btv->has_radio = 1;
        if (bttv_tvcards[btv->c.type].has_remote)
-               btv->has_remote=1;
+               btv->has_remote = 1;
        if (!bttv_tvcards[btv->c.type].no_gpioirq)
-               btv->gpioirq=1;
+               btv->gpioirq = 1;
        if (bttv_tvcards[btv->c.type].volume_gpio)
-               btv->volume_gpio=bttv_tvcards[btv->c.type].volume_gpio;
+               btv->volume_gpio = bttv_tvcards[btv->c.type].volume_gpio;
        if (bttv_tvcards[btv->c.type].audio_mode_gpio)
-               btv->audio_mode_gpio=bttv_tvcards[btv->c.type].audio_mode_gpio;
+               btv->audio_mode_gpio = bttv_tvcards[btv->c.type].audio_mode_gpio;
 
        if (btv->tuner_type == TUNER_ABSENT)
                return;  /* no tuner or related drivers to load */
@@ -3666,6 +3627,49 @@ no_audio:
 }
 
 
+/* initialize the tuner */
+void __devinit bttv_init_tuner(struct bttv *btv)
+{
+       int addr = ADDR_UNSET;
+
+       if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
+               addr = bttv_tvcards[btv->c.type].tuner_addr;
+
+       if (btv->tuner_type != TUNER_ABSENT) {
+               struct tuner_setup tun_setup;
+
+               /* Load tuner module before issuing tuner config call! */
+               if (bttv_tvcards[btv->c.type].has_radio)
+                       v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
+                               &btv->c.i2c_adap, "tuner", "tuner",
+                               v4l2_i2c_tuner_addrs(ADDRS_RADIO));
+               v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
+                               &btv->c.i2c_adap, "tuner", "tuner",
+                               v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+               v4l2_i2c_new_probed_subdev(&btv->c.v4l2_dev,
+                               &btv->c.i2c_adap, "tuner", "tuner",
+                               v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD));
+
+               tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
+               tun_setup.type = btv->tuner_type;
+               tun_setup.addr = addr;
+
+               if (bttv_tvcards[btv->c.type].has_radio)
+                       tun_setup.mode_mask |= T_RADIO;
+
+               bttv_call_all(btv, tuner, s_type_addr, &tun_setup);
+       }
+
+       if (btv->tda9887_conf) {
+               struct v4l2_priv_tun_config tda9887_cfg;
+
+               tda9887_cfg.tuner = TUNER_TDA9887;
+               tda9887_cfg.priv = &btv->tda9887_conf;
+
+               bttv_call_all(btv, tuner, s_config, &tda9887_cfg);
+       }
+}
+
 /* ----------------------------------------------------------------------- */
 
 static void modtec_eeprom(struct bttv *btv)
index 5eb1464af6703f3825599e05bc4683a2e09dc250..8cc6dd28d6a7a1ca4109064d6d98994d280003a2 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/kdev_t.h>
 #include "bttvp.h"
@@ -4418,6 +4419,7 @@ static int __devinit bttv_probe(struct pci_dev *dev,
 
        /* some card-specific stuff (needs working i2c) */
        bttv_init_card2(btv);
+       bttv_init_tuner(btv);
        init_irqreg(btv);
 
        /* register video4linux + input */
index 3d36daf206f37a3c05f3b8466d6a3e2c237de5be..3ec2402c6b4a188ef54260b1f3012bc977d18ee9 100644 (file)
@@ -283,6 +283,7 @@ extern struct tvcard bttv_tvcards[];
 extern void bttv_idcard(struct bttv *btv);
 extern void bttv_init_card1(struct bttv *btv);
 extern void bttv_init_card2(struct bttv *btv);
+extern void bttv_init_tuner(struct bttv *btv);
 
 /* card-specific funtions */
 extern void tea5757_set_freq(struct bttv *btv, unsigned short freq);
index 10dbd4a11b30f8e4aaf7e0ac2fad97f69bb56dbb..9e39bc5f7b00147098a2c660880e6f3853be5e6d 100644 (file)
@@ -992,7 +992,7 @@ static int accept_bwqcam(struct parport *port)
 
        if (parport[0] && strncmp(parport[0], "auto", 4) != 0) {
                /* user gave parport parameters */
-               for(n=0; parport[n] && n<MAX_CAMS; n++){
+               for (n = 0; n < MAX_CAMS && parport[n]; n++) {
                        char *ep;
                        unsigned long r;
                        r = simple_strtoul(parport[n], &ep, 0);
index c92a25036f0e291768a131ceff4b349b59dd34cd..36f2d76006fd419243472a206b5a78f27489e119 100644 (file)
@@ -198,11 +198,14 @@ static const struct cx18_card_pci_info cx18_pci_mpc718[] = {
 
 static const struct cx18_card cx18_card_mpc718 = {
        .type = CX18_CARD_YUAN_MPC718,
-       .name = "Yuan MPC718",
-       .comment = "Analog video capture works; some audio line in may not.\n",
+       .name = "Yuan MPC718 MiniPCI DVB-T/Analog",
+       .comment = "Experimenters needed for device to work well.\n"
+                 "\tTo help, mail the ivtv-devel list (www.ivtvdriver.org).\n",
        .v4l2_capabilities = CX18_CAP_ENCODER,
        .hw_audio_ctrl = CX18_HW_418_AV,
-       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER | CX18_HW_GPIO_RESET_CTRL,
+       .hw_muxer = CX18_HW_GPIO_MUX,
+       .hw_all = CX18_HW_418_AV | CX18_HW_TUNER |
+                 CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
        .video_inputs = {
                { CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
                { CX18_CARD_INPUT_SVIDEO1,    1,
@@ -211,27 +214,34 @@ static const struct cx18_card cx18_card_mpc718 = {
                { CX18_CARD_INPUT_SVIDEO2,    2,
                                CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
                { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
-               { CX18_CARD_INPUT_COMPOSITE3, 2, CX18_AV_COMPOSITE3 },
        },
        .audio_inputs = {
                { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
-               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 0 },
-               { CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL1, 0 },
+               { CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+               { CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL2, 1 },
        },
-       .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL1, 0 },
        .tuners = {
                /* XC3028 tuner */
                { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
        },
+       /* FIXME - the FM radio is just a guess and driver doesn't use SIF */
+       .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
        .ddr = {
-               /* Probably Samsung K4D263238G-VC33 memory */
-               .chip_config = 0x003,
-               .refresh = 0x30c,
-               .timing1 = 0x23230b73,
-               .timing2 = 0x08,
+               /* Hynix HY5DU283222B DDR RAM */
+               .chip_config = 0x303,
+               .refresh = 0x3bd,
+               .timing1 = 0x36320966,
+               .timing2 = 0x1f,
                .tune_lane = 0,
                .initial_emrs = 2,
        },
+       .gpio_init.initial_value = 0x1,
+       .gpio_init.direction = 0x3,
+       /* FIXME - these GPIO's are just guesses */
+       .gpio_audio_input = { .mask   = 0x3,
+                             .tuner  = 0x1,
+                             .linein = 0x3,
+                             .radio  = 0x1 },
        .xceive_pin = 0,
        .pci_list = cx18_pci_mpc718,
        .i2c = &cx18_i2c_std,
index 5136df198338bbbe6855889b84cf0b5486252b2d..93f0dae01350316d9c13110504df129baa4f5ecb 100644 (file)
@@ -20,6 +20,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  *  02111-1307  USA
  */
+#include <linux/kernel.h>
 
 #include "cx18-driver.h"
 #include "cx18-cards.h"
@@ -317,7 +318,7 @@ int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
                idx = p.audio_properties & 0x03;
                /* The audio clock of the digitizer must match the codec sample
                   rate otherwise you get some very strange effects. */
-               if (idx < sizeof(freqs))
+               if (idx < ARRAY_SIZE(freqs))
                        cx18_call_all(cx, audio, s_clock_freq, freqs[idx]);
                return err;
        }
index 6ea3fe623ef49470d9a900197f41a3768f440596..51a0c33b25b7fc84de53cce923672ee260ed8021 100644 (file)
 #include "s5h1409.h"
 #include "mxl5005s.h"
 #include "zl10353.h"
+
+#include <linux/firmware.h>
+#include "mt352.h"
+#include "mt352_priv.h"
 #include "tuner-xc2028.h"
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
@@ -38,6 +42,11 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 #define CX18_CLOCK_ENABLE2              0xc71024
 #define CX18_DMUX_CLK_MASK              0x0080
 
+/*
+ * CX18_CARD_HVR_1600_ESMT
+ * CX18_CARD_HVR_1600_SAMSUNG
+ */
+
 static struct mxl5005s_config hauppauge_hvr1600_tuner = {
        .i2c_address     = 0xC6 >> 1,
        .if_freq         = IF_FREQ_5380000HZ,
@@ -65,6 +74,9 @@ static struct s5h1409_config hauppauge_hvr1600_config = {
        .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
 };
 
+/*
+ * CX18_CARD_LEADTEK_DVR3100H
+ */
 /* Information/confirmation of proper config values provided by Terry Wu */
 static struct zl10353_config leadtek_dvr3100h_demod = {
        .demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
@@ -74,6 +86,121 @@ static struct zl10353_config leadtek_dvr3100h_demod = {
        .disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
 };
 
+/*
+ * CX18_CARD_YUAN_MPC718
+ */
+/*
+ * Due to
+ *
+ * 1. an absence of information on how to prgram the MT352
+ * 2. the Linux mt352 module pushing MT352 initialzation off onto us here
+ *
+ * We have to use an init sequence that *you* must extract from the Windows
+ * driver (yuanrap.sys) and which we load as a firmware.
+ *
+ * If someone can provide me with a Zarlink MT352 (Intel CE6352?) Design Manual
+ * with chip programming details, then I can remove this annoyance.
+ */
+static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream,
+                                  const struct firmware **fw)
+{
+       struct cx18 *cx = stream->cx;
+       const char *fn = "dvb-cx18-mpc718-mt352.fw";
+       int ret;
+
+       ret = request_firmware(fw, fn, &cx->pci_dev->dev);
+       if (ret)
+               CX18_ERR("Unable to open firmware file %s\n", fn);
+       else {
+               size_t sz = (*fw)->size;
+               if (sz < 2 || sz > 64 || (sz % 2) != 0) {
+                       CX18_ERR("Firmware %s has a bad size: %lu bytes\n",
+                                fn, (unsigned long) sz);
+                       ret = -EILSEQ;
+                       release_firmware(*fw);
+                       *fw = NULL;
+               }
+       }
+
+       if (ret) {
+               CX18_ERR("The MPC718 board variant with the MT352 DVB-T"
+                         "demodualtor will not work without it\n");
+               CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware "
+                         "mpc718' if you need the firmware\n");
+       }
+       return ret;
+}
+
+static int yuan_mpc718_mt352_init(struct dvb_frontend *fe)
+{
+       struct cx18_dvb *dvb = container_of(fe->dvb,
+                                           struct cx18_dvb, dvb_adapter);
+       struct cx18_stream *stream = container_of(dvb, struct cx18_stream, dvb);
+       const struct firmware *fw = NULL;
+       int ret;
+       int i;
+       u8 buf[3];
+
+       ret = yuan_mpc718_mt352_reqfw(stream, &fw);
+       if (ret)
+               return ret;
+
+       /* Loop through all the register-value pairs in the firmware file */
+       for (i = 0; i < fw->size; i += 2) {
+               buf[0] = fw->data[i];
+               /* Intercept a few registers we want to set ourselves */
+               switch (buf[0]) {
+               case TRL_NOMINAL_RATE_0:
+                       /* Set our custom OFDM bandwidth in the case below */
+                       break;
+               case TRL_NOMINAL_RATE_1:
+                       /* 6 MHz: 64/7 * 6/8 / 20.48 * 2^16 = 0x55b6.db6 */
+                       /* 7 MHz: 64/7 * 7/8 / 20.48 * 2^16 = 0x6400 */
+                       /* 8 MHz: 64/7 * 8/8 / 20.48 * 2^16 = 0x7249.249 */
+                       buf[1] = 0x72;
+                       buf[2] = 0x49;
+                       mt352_write(fe, buf, 3);
+                       break;
+               case INPUT_FREQ_0:
+                       /* Set our custom IF in the case below */
+                       break;
+               case INPUT_FREQ_1:
+                       /* 4.56 MHz IF: (20.48 - 4.56)/20.48 * 2^14 = 0x31c0 */
+                       buf[1] = 0x31;
+                       buf[2] = 0xc0;
+                       mt352_write(fe, buf, 3);
+                       break;
+               default:
+                       /* Pass through the register-value pair from the fw */
+                       buf[1] = fw->data[i+1];
+                       mt352_write(fe, buf, 2);
+                       break;
+               }
+       }
+
+       buf[0] = (u8) TUNER_GO;
+       buf[1] = 0x01; /* Go */
+       mt352_write(fe, buf, 2);
+       release_firmware(fw);
+       return 0;
+}
+
+static struct mt352_config yuan_mpc718_mt352_demod = {
+       .demod_address = 0x1e >> 1,
+       .adc_clock     = 20480,     /* 20.480 MHz */
+       .if2           =  4560,     /*  4.560 MHz */
+       .no_tuner      = 1,         /* XC3028 is not behind the gate */
+       .demod_init    = yuan_mpc718_mt352_init,
+};
+
+static struct zl10353_config yuan_mpc718_zl10353_demod = {
+       .demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
+       .if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
+       .parallel_ts           = 1,         /* Not a serial TS */
+       .no_tuner              = 1,         /* XC3028 is not behind the gate */
+       .disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
+};
+
 static int dvb_register(struct cx18_stream *stream);
 
 /* Kernel DVB framework calls this when the feed needs to start.
@@ -113,6 +240,7 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
                break;
 
        case CX18_CARD_LEADTEK_DVR3100H:
+       case CX18_CARD_YUAN_MPC718:
        default:
                /* Assumption - Parallel transport - Signalling
                 * undefined or default.
@@ -326,6 +454,38 @@ static int dvb_register(struct cx18_stream *stream)
                                fe->ops.tuner_ops.set_config(fe, &ctrl);
                }
                break;
+       case CX18_CARD_YUAN_MPC718:
+               /*
+                * TODO
+                * Apparently, these cards also could instead have a
+                * DiBcom demod supported by one of the db7000 drivers
+                */
+               dvb->fe = dvb_attach(mt352_attach,
+                                    &yuan_mpc718_mt352_demod,
+                                    &cx->i2c_adap[1]);
+               if (dvb->fe == NULL)
+                       dvb->fe = dvb_attach(zl10353_attach,
+                                            &yuan_mpc718_zl10353_demod,
+                                            &cx->i2c_adap[1]);
+               if (dvb->fe != NULL) {
+                       struct dvb_frontend *fe;
+                       struct xc2028_config cfg = {
+                               .i2c_adap = &cx->i2c_adap[1],
+                               .i2c_addr = 0xc2 >> 1,
+                               .ctrl = NULL,
+                       };
+                       static struct xc2028_ctrl ctrl = {
+                               .fname   = XC2028_DEFAULT_FIRMWARE,
+                               .max_len = 64,
+                               .demod   = XC3028_FE_ZARLINK456,
+                               .type    = XC2028_AUTO,
+                       };
+
+                       fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
+                       if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+                               fe->ops.tuner_ops.set_config(fe, &ctrl);
+               }
+               break;
        default:
                /* No Digital Tv Support */
                break;
index 2943bfd32a94a4b74acb19d6a9076abd7e1d3388..1a1048b18f7027c67eed1eac69b30fd1ad0b055d 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/firmware.h>
+#include <linux/smp_lock.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <media/cx2341x.h>
@@ -57,7 +58,8 @@ MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
 
 #define dprintk(level, fmt, arg...)\
        do { if (v4l_debug >= level) \
-               printk(KERN_DEBUG "%s: " fmt, dev->name , ## arg);\
+               printk(KERN_DEBUG "%s: " fmt, \
+               (dev) ? dev->name : "cx23885[?]", ## arg); \
        } while (0)
 
 static struct cx23885_tvnorm cx23885_tvnorms[] = {
@@ -1676,6 +1678,7 @@ static struct v4l2_file_operations mpeg_fops = {
        .read          = mpeg_read,
        .poll          = mpeg_poll,
        .mmap          = mpeg_mmap,
+       .ioctl         = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
@@ -1712,6 +1715,8 @@ static struct video_device cx23885_mpeg_template = {
        .fops          = &mpeg_fops,
        .ioctl_ops     = &mpeg_ioctl_ops,
        .minor         = -1,
+       .tvnorms       = CX23885_NORMS,
+       .current_norm  = V4L2_STD_NTSC_M,
 };
 
 void cx23885_417_unregister(struct cx23885_dev *dev)
index 48a975134ac5fba0c3d2ab05a85ca0d035a3eb80..86ac529e62be0be042ea6912225ddf9d7d1d89bc 100644 (file)
@@ -463,6 +463,30 @@ static struct xc5000_config mygica_x8506_xc5000_config = {
        .if_khz = 5380,
 };
 
+static int cx23885_dvb_set_frontend(struct dvb_frontend *fe,
+                                   struct dvb_frontend_parameters *param)
+{
+       struct cx23885_tsport *port = fe->dvb->priv;
+       struct cx23885_dev *dev = port->dev;
+
+       switch (dev->board) {
+       case CX23885_BOARD_HAUPPAUGE_HVR1275:
+               switch (param->u.vsb.modulation) {
+               case VSB_8:
+                       cx23885_gpio_clear(dev, GPIO_5);
+                       break;
+               case QAM_64:
+               case QAM_256:
+               default:
+                       cx23885_gpio_set(dev, GPIO_5);
+                       break;
+               }
+               break;
+       }
+       return (port->set_frontend_save) ?
+               port->set_frontend_save(fe, param) : -ENODEV;
+}
+
 static int dvb_register(struct cx23885_tsport *port)
 {
        struct cx23885_dev *dev = port->dev;
@@ -502,6 +526,12 @@ static int dvb_register(struct cx23885_tsport *port)
                                   0x60, &dev->i2c_bus[1].i2c_adap,
                                   &hauppauge_hvr127x_config);
                }
+
+               /* FIXME: temporary hack */
+               /* define bridge override to set_frontend */
+               port->set_frontend_save = fe0->dvb.frontend->ops.set_frontend;
+               fe0->dvb.frontend->ops.set_frontend = cx23885_dvb_set_frontend;
+
                break;
        case CX23885_BOARD_HAUPPAUGE_HVR1255:
                i2c_bus = &dev->i2c_bus[0];
index 70836af3ab4891a624a87225d6ec0bf2cdd8cf32..5d6093336300dc79731177dbaada479bcd40fcac 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/kmod.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
index 1a2ac518a3f1ae21362ae8694a4289d1d4c78cba..214a55e943b783dc7a6cfaab95bb25f4fe504ee1 100644 (file)
@@ -288,6 +288,10 @@ struct cx23885_tsport {
        /* Allow a single tsport to have multiple frontends */
        u32                        num_frontends;
        void                       *port_priv;
+
+       /* FIXME: temporary hack */
+       int (*set_frontend_save) (struct dvb_frontend *,
+                                 struct dvb_frontend_parameters *);
 };
 
 struct cx23885_dev {
index 44eacfb0d0d6073db886168e8d4120f99cd76ae7..356d6896da3f5877e5961fb4d009309fe68cae33 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/firmware.h>
+#include <linux/smp_lock.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <media/cx2341x.h>
index a5cc1c1fc2d60c30329350a1ee1072c21efe68a5..39465301ec94ea78fa6d6f54ae467f0b9fc3e119 100644 (file)
@@ -3003,6 +3003,14 @@ void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl)
        case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
                ctl->demod = XC3028_FE_OREN538;
                break;
+       case CX88_BOARD_GENIATECH_X8000_MT:
+               /* FIXME: For this board, the xc3028 never recovers after being
+                  powered down (the reset GPIO probably is not set properly).
+                  We don't have access to the hardware so we cannot determine
+                  which GPIO is used for xc3028, so just disable power xc3028
+                  power management for now */
+               ctl->disable_power_mgmt = 1;
+               break;
        case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
        case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
        case CX88_BOARD_PROLINK_PV_8000GT:
index c44e8760021932bf907ce3be5e135db9f661c5a8..e237b507659ba82bc45a03022245118ef41fce2b 100644 (file)
@@ -501,6 +501,7 @@ static struct zl10353_config cx88_pinnacle_hybrid_pctv = {
 static struct zl10353_config cx88_geniatech_x8000_mt = {
        .demod_address = (0x1e >> 1),
        .no_tuner = 1,
+       .disable_i2c_gate_ctrl = 1,
 };
 
 static struct s5h1411_config dvico_fusionhdtv7_config = {
index da4e3912cd374991ba37f560779e2a871f05cf28..7172dcf2a4fa87ed94c4ac3c41789e1ddafc467d 100644 (file)
@@ -116,6 +116,10 @@ static int cx8802_start_dma(struct cx8802_dev    *dev,
                        udelay(100);
                        break;
                case CX88_BOARD_HAUPPAUGE_HVR1300:
+                       /* Enable MPEG parallel IO and video signal pins */
+                       cx_write(MO_PINMUX_IO, 0x88);
+                       cx_write(TS_SOP_STAT, 0);
+                       cx_write(TS_VALERR_CNTRL, 0);
                        break;
                case CX88_BOARD_PINNACLE_PCTV_HD_800i:
                        /* Enable MPEG parallel IO and video signal pins */
index b12770848c00161e5355fd05c0816fbb9e0c3134..2bb54c3ef5cdcefbc708718aebee684005f80e3d 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/kmod.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
index ec2f45dde1643d72a849aa15004bbde91a1ff2c3..0664d111085f262db7e621d21f0ed20b41a85856 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/list.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
index 16a5af30e9d1fd1e4184da4969d5956798f8a76a..6524b493e033ed5529d811bfbaaa488ec6618c16 100644 (file)
@@ -8,6 +8,8 @@ config VIDEO_EM28XX
        select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
        select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO
+
        ---help---
          This is a video4linux driver for Empia 28xx based TV cards.
 
index c43fdb9bc88810c3f2f658f8cb3495d70940a3c2..1c2e544eda73594cb362e1afbea1451b4ae94927 100644 (file)
@@ -157,6 +157,20 @@ static struct em28xx_reg_seq evga_indtube_digital[] = {
        { -1,                   -1,     -1,             -1},
 };
 
+/* Pinnacle Hybrid Pro eb1a:2881 */
+static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = {
+       {EM28XX_R08_GPIO,       0xfd,   ~EM_GPIO_4,     10},
+       {       -1,             -1,     -1,             -1},
+};
+
+static struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = {
+       {EM28XX_R08_GPIO,       0x6e,   ~EM_GPIO_4,     10},
+       {EM2880_R04_GPO,        0x04,   0xff,          100},/* zl10353 reset */
+       {EM2880_R04_GPO,        0x0c,   0xff,            1},
+       {       -1,             -1,     -1,             -1},
+};
+
+
 /* Callback for the most boards */
 static struct em28xx_reg_seq default_tuner_gpio[] = {
        {EM28XX_R08_GPIO,       EM_GPIO_4,      EM_GPIO_4,      10},
@@ -191,18 +205,27 @@ static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = {
        {EM28XX_R08_GPIO,       0xff,   0xff,           10},
        {       -1,             -1,     -1,             -1},
 };
+
+static struct em28xx_reg_seq silvercrest_reg_seq[] = {
+       {EM28XX_R08_GPIO,       0xff,   0xff,           10},
+       {EM28XX_R08_GPIO,       0x01,   0xf7,           10},
+       {       -1,             -1,     -1,             -1},
+};
+
 /*
  *  Board definitions
  */
 struct em28xx_board em28xx_boards[] = {
        [EM2750_BOARD_UNKNOWN] = {
-               .name          = "Unknown EM2750/EM2751 webcam grabber",
-               .xclk          = EM28XX_XCLK_FREQUENCY_48MHZ,
-               .tuner_type    = TUNER_ABSENT,  /* This is a webcam */
+               .name          = "EM2710/EM2750/EM2751 webcam grabber",
+               .xclk          = EM28XX_XCLK_FREQUENCY_20MHZ,
+               .tuner_type    = TUNER_ABSENT,
+               .is_webcam     = 1,
                .input         = { {
                        .type     = EM28XX_VMUX_COMPOSITE1,
                        .vmux     = 0,
                        .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = silvercrest_reg_seq,
                } },
        },
        [EM2800_BOARD_UNKNOWN] = {
@@ -224,13 +247,15 @@ struct em28xx_board em28xx_boards[] = {
        [EM2820_BOARD_UNKNOWN] = {
                .name          = "Unknown EM2750/28xx video grabber",
                .tuner_type    = TUNER_ABSENT,
+               .is_webcam     = 1,     /* To enable sensor probe */
        },
        [EM2750_BOARD_DLCW_130] = {
                /* Beijing Huaqi Information Digital Technology Co., Ltd */
                .name          = "Huaqi DLCW-130",
                .valid         = EM28XX_BOARD_NOT_VALIDATED,
                .xclk          = EM28XX_XCLK_FREQUENCY_48MHZ,
-               .tuner_type    = TUNER_ABSENT,  /* This is a webcam */
+               .tuner_type    = TUNER_ABSENT,
+               .is_webcam     = 1,
                .input         = { {
                        .type     = EM28XX_VMUX_COMPOSITE1,
                        .vmux     = 0,
@@ -431,11 +456,23 @@ struct em28xx_board em28xx_boards[] = {
        [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = {
                .name         = "Videology 20K14XUSB USB2.0",
                .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_ABSENT,   /* This is a webcam */
+               .tuner_type   = TUNER_ABSENT,
+               .is_webcam    = 1,
+               .input        = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = 0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               } },
+       },
+       [EM2820_BOARD_SILVERCREST_WEBCAM] = {
+               .name         = "Silvercrest Webcam 1.3mpix",
+               .tuner_type   = TUNER_ABSENT,
+               .is_webcam    = 1,
                .input        = { {
                        .type     = EM28XX_VMUX_COMPOSITE1,
                        .vmux     = 0,
                        .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = silvercrest_reg_seq,
                } },
        },
        [EM2821_BOARD_SUPERCOMP_USB_2] = {
@@ -479,7 +516,8 @@ struct em28xx_board em28xx_boards[] = {
                /* Beijing Huaqi Information Digital Technology Co., Ltd */
                .name         = "NetGMBH Cam",
                .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_ABSENT,   /* This is a webcam */
+               .tuner_type   = TUNER_ABSENT,
+               .is_webcam    = 1,
                .input        = { {
                        .type     = EM28XX_VMUX_COMPOSITE1,
                        .vmux     = 0,
@@ -584,22 +622,27 @@ struct em28xx_board em28xx_boards[] = {
        },
        [EM2861_BOARD_PLEXTOR_PX_TV100U] = {
                .name         = "Plextor ConvertX PX-TV100U",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .tuner_type   = TUNER_TNF_5335MF,
+               .xclk         = EM28XX_XCLK_I2S_MSB_TIMING |
+                               EM28XX_XCLK_FREQUENCY_12MHZ,
                .tda9887_conf = TDA9887_PRESENT,
                .decoder      = EM28XX_TVP5150,
+               .has_msp34xx  = 1,
                .input        = { {
                        .type     = EM28XX_VMUX_TELEVISION,
                        .vmux     = TVP5150_COMPOSITE0,
                        .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = pinnacle_hybrid_pro_analog,
                }, {
                        .type     = EM28XX_VMUX_COMPOSITE1,
                        .vmux     = TVP5150_COMPOSITE1,
                        .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = pinnacle_hybrid_pro_analog,
                }, {
                        .type     = EM28XX_VMUX_SVIDEO,
                        .vmux     = TVP5150_SVIDEO,
                        .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = pinnacle_hybrid_pro_analog,
                } },
        },
 
@@ -826,7 +869,7 @@ struct em28xx_board em28xx_boards[] = {
                .tuner_gpio     = default_tuner_gpio,
                .decoder        = EM28XX_TVP5150,
                .has_dvb        = 1,
-               .dvb_gpio       = default_analog,
+               .dvb_gpio       = default_digital,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
                        .vmux     = TVP5150_COMPOSITE0,
@@ -1229,25 +1272,26 @@ struct em28xx_board em28xx_boards[] = {
        },
        [EM2881_BOARD_PINNACLE_HYBRID_PRO] = {
                .name         = "Pinnacle Hybrid Pro",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .tuner_type   = TUNER_XC2028,
                .tuner_gpio   = default_tuner_gpio,
                .decoder      = EM28XX_TVP5150,
+               .has_dvb      = 1,
+               .dvb_gpio     = pinnacle_hybrid_pro_digital,
                .input        = { {
                        .type     = EM28XX_VMUX_TELEVISION,
                        .vmux     = TVP5150_COMPOSITE0,
                        .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = default_analog,
+                       .gpio     = pinnacle_hybrid_pro_analog,
                }, {
                        .type     = EM28XX_VMUX_COMPOSITE1,
                        .vmux     = TVP5150_COMPOSITE1,
                        .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = default_analog,
+                       .gpio     = pinnacle_hybrid_pro_analog,
                }, {
                        .type     = EM28XX_VMUX_SVIDEO,
                        .vmux     = TVP5150_SVIDEO,
                        .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = default_analog,
+                       .gpio     = pinnacle_hybrid_pro_analog,
                } },
        },
        [EM2882_BOARD_PINNACLE_HYBRID_PRO] = {
@@ -1505,6 +1549,8 @@ struct usb_device_id em28xx_id_table[] = {
                        .driver_info = EM2750_BOARD_UNKNOWN },
        { USB_DEVICE(0xeb1a, 0x2800),
                        .driver_info = EM2800_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2710),
+                       .driver_info = EM2820_BOARD_UNKNOWN },
        { USB_DEVICE(0xeb1a, 0x2820),
                        .driver_info = EM2820_BOARD_UNKNOWN },
        { USB_DEVICE(0xeb1a, 0x2821),
@@ -1617,6 +1663,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash[] = {
        {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},
        {0x9567eb1a, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028},
        {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028},
+       {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028},
 };
 
 /* I2C devicelist hash table for devices with generic USB IDs */
@@ -1639,6 +1686,11 @@ static unsigned short tvp5150_addrs[] = {
        I2C_CLIENT_END
 };
 
+static unsigned short mt9v011_addrs[] = {
+       0xba >> 1,
+       I2C_CLIENT_END
+};
+
 static unsigned short msp3400_addrs[] = {
        0x80 >> 1,
        0x88 >> 1,
@@ -1678,65 +1730,150 @@ static inline void em28xx_set_model(struct em28xx *dev)
                                       EM28XX_I2C_FREQ_100_KHZ;
 }
 
-/* Since em28xx_pre_card_setup() requires a proper dev->model,
- * this won't work for boards with generic PCI IDs
+
+/* FIXME: Should be replaced by a proper mt9m111 driver */
+static int em28xx_initialize_mt9m111(struct em28xx *dev)
+{
+       int i;
+       unsigned char regs[][3] = {
+               { 0x0d, 0x00, 0x01, },  /* reset and use defaults */
+               { 0x0d, 0x00, 0x00, },
+               { 0x0a, 0x00, 0x21, },
+               { 0x21, 0x04, 0x00, },  /* full readout speed, no row/col skipping */
+       };
+
+       for (i = 0; i < ARRAY_SIZE(regs); i++)
+               i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
+
+       return 0;
+}
+
+
+/* FIXME: Should be replaced by a proper mt9m001 driver */
+static int em28xx_initialize_mt9m001(struct em28xx *dev)
+{
+       int i;
+       unsigned char regs[][3] = {
+               { 0x0d, 0x00, 0x01, },
+               { 0x0d, 0x00, 0x00, },
+               { 0x04, 0x05, 0x00, },  /* hres = 1280 */
+               { 0x03, 0x04, 0x00, },  /* vres = 1024 */
+               { 0x20, 0x11, 0x00, },
+               { 0x06, 0x00, 0x10, },
+               { 0x2b, 0x00, 0x24, },
+               { 0x2e, 0x00, 0x24, },
+               { 0x35, 0x00, 0x24, },
+               { 0x2d, 0x00, 0x20, },
+               { 0x2c, 0x00, 0x20, },
+               { 0x09, 0x0a, 0xd4, },
+               { 0x35, 0x00, 0x57, },
+       };
+
+       for (i = 0; i < ARRAY_SIZE(regs); i++)
+               i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
+
+       return 0;
+}
+
+/* HINT method: webcam I2C chips
+ *
+ * This method works for webcams with Micron sensors
  */
-void em28xx_pre_card_setup(struct em28xx *dev)
+static int em28xx_hint_sensor(struct em28xx *dev)
 {
        int rc;
+       char *sensor_name;
+       unsigned char cmd;
+       __be16 version_be;
+       u16 version;
+
+       /* Micron sensor detection */
+       dev->i2c_client.addr = 0xba >> 1;
+       cmd = 0;
+       i2c_master_send(&dev->i2c_client, &cmd, 1);
+       rc = i2c_master_recv(&dev->i2c_client, (char *)&version_be, 2);
+       if (rc != 2)
+               return -EINVAL;
+
+       version = be16_to_cpu(version_be);
+       switch (version) {
+       case 0x8232:            /* mt9v011 640x480 1.3 Mpix sensor */
+       case 0x8243:            /* mt9v011 rev B 640x480 1.3 Mpix sensor */
+               dev->model = EM2820_BOARD_SILVERCREST_WEBCAM;
+               em28xx_set_model(dev);
+
+               sensor_name = "mt9v011";
+               dev->em28xx_sensor = EM28XX_MT9V011;
+               dev->sensor_xres = 640;
+               dev->sensor_yres = 480;
+               /*
+                * FIXME: mt9v011 uses I2S speed as xtal clk - at least with
+                * the Silvercrest cam I have here for testing - for higher
+                * resolutions, a high clock cause horizontal artifacts, so we
+                * need to use a lower xclk frequency.
+                * Yet, it would be possible to adjust xclk depending on the
+                * desired resolution, since this affects directly the
+                * frame rate.
+                */
+               dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ;
+               dev->sensor_xtal = 4300000;
 
-       em28xx_set_model(dev);
+               /* probably means GRGB 16 bit bayer */
+               dev->vinmode = 0x0d;
+               dev->vinctl = 0x00;
 
-       em28xx_info("Identified as %s (card=%d)\n",
-                   dev->board.name, dev->model);
+               break;
 
-       /* Set the default GPO/GPIO for legacy devices */
-       dev->reg_gpo_num = EM2880_R04_GPO;
-       dev->reg_gpio_num = EM28XX_R08_GPIO;
+       case 0x143a:    /* MT9M111 as found in the ECS G200 */
+               dev->model = EM2750_BOARD_UNKNOWN;
+               em28xx_set_model(dev);
 
-       dev->wait_after_write = 5;
+               sensor_name = "mt9m111";
+               dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ;
+               dev->em28xx_sensor = EM28XX_MT9M111;
+               em28xx_initialize_mt9m111(dev);
+               dev->sensor_xres = 640;
+               dev->sensor_yres = 512;
 
-       /* Based on the Chip ID, set the device configuration */
-       rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
-       if (rc > 0) {
-               dev->chip_id = rc;
+               dev->vinmode = 0x0a;
+               dev->vinctl = 0x00;
 
-               switch (dev->chip_id) {
-               case CHIP_ID_EM2750:
-                       em28xx_info("chip ID is em2750\n");
-                       break;
-               case CHIP_ID_EM2820:
-                       em28xx_info("chip ID is em2820\n");
-                       break;
-               case CHIP_ID_EM2840:
-                       em28xx_info("chip ID is em2840\n");
-                       break;
-               case CHIP_ID_EM2860:
-                       em28xx_info("chip ID is em2860\n");
-                       break;
-               case CHIP_ID_EM2870:
-                       em28xx_info("chip ID is em2870\n");
-                       dev->wait_after_write = 0;
-                       break;
-               case CHIP_ID_EM2874:
-                       em28xx_info("chip ID is em2874\n");
-                       dev->reg_gpio_num = EM2874_R80_GPIO;
-                       dev->wait_after_write = 0;
-                       break;
-               case CHIP_ID_EM2883:
-                       em28xx_info("chip ID is em2882/em2883\n");
-                       dev->wait_after_write = 0;
-                       break;
-               default:
-                       em28xx_info("em28xx chip ID = %d\n", dev->chip_id);
-               }
+               break;
+
+       case 0x8431:
+               dev->model = EM2750_BOARD_UNKNOWN;
+               em28xx_set_model(dev);
+
+               sensor_name = "mt9m001";
+               dev->em28xx_sensor = EM28XX_MT9M001;
+               em28xx_initialize_mt9m001(dev);
+               dev->sensor_xres = 1280;
+               dev->sensor_yres = 1024;
+
+               /* probably means BGGR 16 bit bayer */
+               dev->vinmode = 0x0c;
+               dev->vinctl = 0x00;
+
+               break;
+       default:
+               printk("Unknown Micron Sensor 0x%04x\n", version);
+               return -EINVAL;
        }
 
-       /* Prepopulate cached GPO register content */
-       rc = em28xx_read_reg(dev, dev->reg_gpo_num);
-       if (rc >= 0)
-               dev->reg_gpo = rc;
+       /* Setup webcam defaults */
+       em28xx_pre_card_setup(dev);
+
+       em28xx_errdev("Sensor is %s, using model %s entry.\n",
+                     sensor_name, em28xx_boards[dev->model].name);
+
+       return 0;
+}
 
+/* Since em28xx_pre_card_setup() requires a proper dev->model,
+ * this won't work for boards with generic PCI IDs
+ */
+void em28xx_pre_card_setup(struct em28xx *dev)
+{
        /* Set the initial XCLK and I2C clock values based on the board
           definition */
        em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f);
@@ -1746,9 +1883,8 @@ void em28xx_pre_card_setup(struct em28xx *dev)
        /* request some modules */
        switch (dev->model) {
        case EM2861_BOARD_PLEXTOR_PX_TV100U:
-               /* FIXME guess */
-               /* Turn on analog audio output */
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
+               /* Sets the msp34xx I2S speed */
+               dev->i2s_speed = 2048000;
                break;
        case EM2861_BOARD_KWORLD_PVRTV_300U:
        case EM2880_BOARD_KWORLD_DVB_305U:
@@ -1860,6 +1996,7 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
                ctl->demod = XC3028_FE_ZARLINK456;
                break;
        case EM2880_BOARD_TERRATEC_HYBRID_XS:
+       case EM2881_BOARD_PINNACLE_HYBRID_PRO:
                ctl->demod = XC3028_FE_ZARLINK456;
                break;
        case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
@@ -2085,7 +2222,20 @@ void em28xx_register_i2c_ir(struct em28xx *dev)
 
 void em28xx_card_setup(struct em28xx *dev)
 {
-       em28xx_set_model(dev);
+       /*
+        * If the device can be a webcam, seek for a sensor.
+        * If sensor is not found, then it isn't a webcam.
+        */
+       if (dev->board.is_webcam) {
+               if (em28xx_hint_sensor(dev) < 0)
+                       dev->board.is_webcam = 0;
+               else
+                       dev->progressive = 1;
+       } else
+               em28xx_set_model(dev);
+
+       em28xx_info("Identified as %s (card=%d)\n",
+                   dev->board.name, dev->model);
 
        dev->tuner_type = em28xx_boards[dev->model].tuner_type;
        if (em28xx_boards[dev->model].tuner_addr)
@@ -2156,6 +2306,7 @@ void em28xx_card_setup(struct em28xx *dev)
                   em28xx_set_mode() in em28xx_pre_card_setup() was a no-op,
                   so make the call now so the analog GPIOs are set properly
                   before probing the i2c bus. */
+               em28xx_gpio_set(dev, dev->board.tuner_gpio);
                em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
                break;
        }
@@ -2189,6 +2340,15 @@ void em28xx_card_setup(struct em28xx *dev)
                v4l2_i2c_new_probed_subdev(&dev->v4l2_dev, &dev->i2c_adap,
                        "tvp5150", "tvp5150", tvp5150_addrs);
 
+       if (dev->em28xx_sensor == EM28XX_MT9V011) {
+               struct v4l2_subdev *sd;
+
+               sd = v4l2_i2c_new_probed_subdev(&dev->v4l2_dev,
+                        &dev->i2c_adap, "mt9v011", "mt9v011", mt9v011_addrs);
+               v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal);
+       }
+
+
        if (dev->board.adecoder == EM28XX_TVAUDIO)
                v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
                        "tvaudio", "tvaudio", dev->board.tvaudio_addr);
@@ -2222,7 +2382,9 @@ void em28xx_card_setup(struct em28xx *dev)
        }
 
        em28xx_tuner_setup(dev);
-       em28xx_ir_init(dev);
+
+       if(!disable_ir)
+               em28xx_ir_init(dev);
 }
 
 
@@ -2288,7 +2450,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
                           int minor)
 {
        struct em28xx *dev = *devhandle;
-       int retval = -ENOMEM;
+       int retval;
        int errCode;
 
        dev->udev = udev;
@@ -2305,6 +2467,58 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
        dev->em28xx_read_reg_req = em28xx_read_reg_req;
        dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800;
 
+       em28xx_set_model(dev);
+
+       /* Set the default GPO/GPIO for legacy devices */
+       dev->reg_gpo_num = EM2880_R04_GPO;
+       dev->reg_gpio_num = EM28XX_R08_GPIO;
+
+       dev->wait_after_write = 5;
+
+       /* Based on the Chip ID, set the device configuration */
+       retval = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
+       if (retval > 0) {
+               dev->chip_id = retval;
+
+               switch (dev->chip_id) {
+               case CHIP_ID_EM2710:
+                       em28xx_info("chip ID is em2710\n");
+                       break;
+               case CHIP_ID_EM2750:
+                       em28xx_info("chip ID is em2750\n");
+                       break;
+               case CHIP_ID_EM2820:
+                       em28xx_info("chip ID is em2820 (or em2710)\n");
+                       break;
+               case CHIP_ID_EM2840:
+                       em28xx_info("chip ID is em2840\n");
+                       break;
+               case CHIP_ID_EM2860:
+                       em28xx_info("chip ID is em2860\n");
+                       break;
+               case CHIP_ID_EM2870:
+                       em28xx_info("chip ID is em2870\n");
+                       dev->wait_after_write = 0;
+                       break;
+               case CHIP_ID_EM2874:
+                       em28xx_info("chip ID is em2874\n");
+                       dev->reg_gpio_num = EM2874_R80_GPIO;
+                       dev->wait_after_write = 0;
+                       break;
+               case CHIP_ID_EM2883:
+                       em28xx_info("chip ID is em2882/em2883\n");
+                       dev->wait_after_write = 0;
+                       break;
+               default:
+                       em28xx_info("em28xx chip ID = %d\n", dev->chip_id);
+               }
+       }
+
+       /* Prepopulate cached GPO register content */
+       retval = em28xx_read_reg(dev, dev->reg_gpo_num);
+       if (retval >= 0)
+               dev->reg_gpo = retval;
+
        em28xx_pre_card_setup(dev);
 
        if (!dev->board.is_em2800) {
@@ -2333,6 +2547,12 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
                return errCode;
        }
 
+       /*
+        * Default format, used for tvp5150 or saa711x output formats
+        */
+       dev->vinmode = 0x10;
+       dev->vinctl  = 0x11;
+
        /* Do board specific init and eeprom reading */
        em28xx_card_setup(dev);
 
@@ -2573,6 +2793,7 @@ static int em28xx_usb_probe(struct usb_interface *interface,
        retval = em28xx_init_dev(&dev, udev, interface, nr);
        if (retval) {
                em28xx_devused &= ~(1<<dev->devno);
+               mutex_unlock(&dev->lock);
                kfree(dev);
                goto err;
        }
index c8d7ce8fbd368a403c47e6260e036801182144e9..98e140b5d95e66a48876514721ab203369cf2e89 100644 (file)
@@ -632,6 +632,9 @@ int em28xx_capture_start(struct em28xx *dev, int start)
                return rc;
        }
 
+       if (dev->board.is_webcam)
+               rc = em28xx_write_reg(dev, 0x13, 0x0c);
+
        /* enable video capture */
        rc = em28xx_write_reg(dev, 0x48, 0x00);
 
@@ -650,15 +653,15 @@ int em28xx_set_outfmt(struct em28xx *dev)
        int ret;
 
        ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT,
-                                   dev->format->reg | 0x20, 0x3f);
+                               dev->format->reg | 0x20, 0xff);
        if (ret < 0)
-               return ret;
+                       return ret;
 
-       ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, 0x10);
+       ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
        if (ret < 0)
                return ret;
 
-       return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, 0x11);
+       return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, dev->vinctl);
 }
 
 static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
@@ -695,13 +698,16 @@ static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
 {
        u8 mode;
        /* the em2800 scaler only supports scaling down to 50% */
-       if (dev->board.is_em2800)
+
+       if (dev->board.is_em2800) {
                mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
-       else {
+       else {
                u8 buf[2];
+
                buf[0] = h;
                buf[1] = h >> 8;
                em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
+
                buf[0] = v;
                buf[1] = v >> 8;
                em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
@@ -717,11 +723,17 @@ int em28xx_resolution_set(struct em28xx *dev)
 {
        int width, height;
        width = norm_maxw(dev);
-       height = norm_maxh(dev) >> 1;
+       height = norm_maxh(dev);
+
+       if (!dev->progressive)
+               height >>= norm_maxh(dev);
 
        em28xx_set_outfmt(dev);
+
+
        em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
        em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2);
+
        return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
 }
 
index e7b47c8da8f3e7732208d666d952391717526883..d603575431b44b71d59288ac5d860f6d7e4ae254 100644 (file)
@@ -31,6 +31,8 @@
 #include "lgdt330x.h"
 #include "zl10353.h"
 #include "s5h1409.h"
+#include "mt352.h"
+#include "mt352_priv.h" /* FIXME */
 
 MODULE_DESCRIPTION("driver for em28xx based DVB cards");
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
@@ -243,6 +245,14 @@ static struct s5h1409_config em28xx_s5h1409_with_xc3028 = {
        .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
 };
 
+static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {
+       .demod_address = (0x1e >> 1),
+       .no_tuner = 1,
+       .disable_i2c_gate_ctrl = 1,
+       .parallel_ts = 1,
+       .if2 = 45600,
+};
+
 #ifdef EM28XX_DRX397XD_SUPPORT
 /* [TODO] djh - not sure yet what the device config needs to contain */
 static struct drx397xD_config em28xx_drx397xD_with_xc3028 = {
@@ -250,6 +260,41 @@ static struct drx397xD_config em28xx_drx397xD_with_xc3028 = {
 };
 #endif
 
+static int mt352_terratec_xs_init(struct dvb_frontend *fe)
+{
+       /* Values extracted from a USB trace of the Terratec Windows driver */
+       static u8 clock_config[]   = { CLOCK_CTL,  0x38, 0x2c };
+       static u8 reset[]          = { RESET,      0x80 };
+       static u8 adc_ctl_1_cfg[]  = { ADC_CTL_1,  0x40 };
+       static u8 agc_cfg[]        = { AGC_TARGET, 0x28, 0xa0 };
+       static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 };
+       static u8 rs_err_cfg[]     = { RS_ERR_PER_1, 0x00, 0x4d };
+       static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+       static u8 trl_nom_cfg[]    = { TRL_NOMINAL_RATE_1, 0x64, 0x00 };
+       static u8 tps_given_cfg[]  = { TPS_GIVEN_1, 0x40, 0x80, 0x50 };
+       static u8 tuner_go[]       = { TUNER_GO, 0x01};
+
+       mt352_write(fe, clock_config,   sizeof(clock_config));
+       udelay(200);
+       mt352_write(fe, reset,          sizeof(reset));
+       mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
+       mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
+       mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg));
+       mt352_write(fe, rs_err_cfg,     sizeof(rs_err_cfg));
+       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+       mt352_write(fe, trl_nom_cfg,    sizeof(trl_nom_cfg));
+       mt352_write(fe, tps_given_cfg,  sizeof(tps_given_cfg));
+       mt352_write(fe, tuner_go,       sizeof(tuner_go));
+       return 0;
+}
+
+static struct mt352_config terratec_xs_mt352_cfg = {
+       .demod_address = (0x1e >> 1),
+       .no_tuner = 1,
+       .if2 = 45600,
+       .demod_init = mt352_terratec_xs_init,
+};
+
 /* ------------------------------------------------------------------ */
 
 static int attach_xc3028(u8 addr, struct em28xx *dev)
@@ -432,10 +477,7 @@ static int dvb_init(struct em28xx *dev)
                        goto out_free;
                }
                break;
-       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
-       case EM2880_BOARD_TERRATEC_HYBRID_XS:
        case EM2880_BOARD_KWORLD_DVB_310U:
-       case EM2880_BOARD_EMPIRE_DUAL_TV:
                dvb->frontend = dvb_attach(zl10353_attach,
                                           &em28xx_zl10353_with_xc3028,
                                           &dev->i2c_adap);
@@ -444,6 +486,34 @@ static int dvb_init(struct em28xx *dev)
                        goto out_free;
                }
                break;
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+       case EM2880_BOARD_EMPIRE_DUAL_TV:
+               dvb->frontend = dvb_attach(zl10353_attach,
+                                          &em28xx_zl10353_xc3028_no_i2c_gate,
+                                          &dev->i2c_adap);
+               if (attach_xc3028(0x61, dev) < 0) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       case EM2880_BOARD_TERRATEC_HYBRID_XS:
+       case EM2881_BOARD_PINNACLE_HYBRID_PRO:
+               dvb->frontend = dvb_attach(zl10353_attach,
+                                          &em28xx_zl10353_xc3028_no_i2c_gate,
+                                          &dev->i2c_adap);
+               if (dvb->frontend == NULL) {
+                       /* This board could have either a zl10353 or a mt352.
+                          If the chip id isn't for zl10353, try mt352 */
+                       dvb->frontend = dvb_attach(mt352_attach,
+                                                  &terratec_xs_mt352_cfg,
+                                                  &dev->i2c_adap);
+               }
+
+               if (attach_xc3028(0x61, dev) < 0) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
        case EM2883_BOARD_KWORLD_HYBRID_330U:
        case EM2882_BOARD_EVGA_INDTUBE:
                dvb->frontend = dvb_attach(s5h1409_attach,
index 2c86fcf089f59b45de048179e4be46fe76c989d4..27e33a287dfc8a53da271359aef3c08ac5283517 100644 (file)
@@ -483,7 +483,7 @@ static char *i2c_devs[128] = {
        [0xa0 >> 1] = "eeprom",
        [0xb0 >> 1] = "tda9874",
        [0xb8 >> 1] = "tvp5150a",
-       [0xba >> 1] = "tvp5150a",
+       [0xba >> 1] = "webcam sensor or tvp5150a",
        [0xc0 >> 1] = "tuner (analog)",
        [0xc2 >> 1] = "tuner (analog)",
        [0xc4 >> 1] = "tuner (analog)",
index a2676d63cfd0a673cfd26b6e0ddd593ecab10e5a..6bf84bd787df81765b25d8924463cdbb14f344a4 100644 (file)
 
 /* FIXME: Need to be populated with the other chip ID's */
 enum em28xx_chip_id {
-       CHIP_ID_EM2820 = 18,    /* Also used by em2710 */
+       CHIP_ID_EM2710 = 17,
+       CHIP_ID_EM2820 = 18,    /* Also used by some em2710 */
        CHIP_ID_EM2840 = 20,
        CHIP_ID_EM2750 = 33,
        CHIP_ID_EM2860 = 34,
index 8fe1beecfffac0919d40a31e713510bad33d2559..ab079d9256c463a0c9889841ed3e0946969f1929 100644 (file)
@@ -90,10 +90,35 @@ MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
 /* supported video standards */
 static struct em28xx_fmt format[] = {
        {
-               .name     = "16bpp YUY2, 4:2:2, packed",
+               .name     = "16 bpp YUY2, 4:2:2, packed",
                .fourcc   = V4L2_PIX_FMT_YUYV,
                .depth    = 16,
                .reg      = EM28XX_OUTFMT_YUV422_Y0UY1V,
+       }, {
+               .name     = "16 bpp RGB 565, LE",
+               .fourcc   = V4L2_PIX_FMT_RGB565,
+               .depth    = 16,
+               .reg      = EM28XX_OUTFMT_RGB_16_656,
+       }, {
+               .name     = "8 bpp Bayer BGBG..GRGR",
+               .fourcc   = V4L2_PIX_FMT_SBGGR8,
+               .depth    = 8,
+               .reg      = EM28XX_OUTFMT_RGB_8_BGBG,
+       }, {
+               .name     = "8 bpp Bayer GRGR..BGBG",
+               .fourcc   = V4L2_PIX_FMT_SGRBG8,
+               .depth    = 8,
+               .reg      = EM28XX_OUTFMT_RGB_8_GRGR,
+       }, {
+               .name     = "8 bpp Bayer GBGB..RGRG",
+               .fourcc   = V4L2_PIX_FMT_SGBRG8,
+               .depth    = 8,
+               .reg      = EM28XX_OUTFMT_RGB_8_GBGB,
+       }, {
+               .name     = "12 bpp YUV411",
+               .fourcc   = V4L2_PIX_FMT_YUV411P,
+               .depth    = 12,
+               .reg      = EM28XX_OUTFMT_YUV411,
        },
 };
 
@@ -169,15 +194,24 @@ static void em28xx_copy_video(struct em28xx *dev,
        startread = p;
        remain = len;
 
-       /* Interlaces frame */
-       if (buf->top_field)
+       if (dev->progressive)
                fieldstart = outp;
-       else
-               fieldstart = outp + bytesperline;
+       else {
+               /* Interlaces two half frames */
+               if (buf->top_field)
+                       fieldstart = outp;
+               else
+                       fieldstart = outp + bytesperline;
+       }
 
        linesdone = dma_q->pos / bytesperline;
        currlinedone = dma_q->pos % bytesperline;
-       offset = linesdone * bytesperline * 2 + currlinedone;
+
+       if (dev->progressive)
+               offset = linesdone * bytesperline + currlinedone;
+       else
+               offset = linesdone * bytesperline * 2 + currlinedone;
+
        startwrite = fieldstart + offset;
        lencopy = bytesperline - currlinedone;
        lencopy = lencopy > remain ? remain : lencopy;
@@ -351,7 +385,7 @@ static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
                        em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
                                       len, (p[2] & 1) ? "odd" : "even");
 
-                       if (!(p[2] & 1)) {
+                       if (dev->progressive || !(p[2] & 1)) {
                                if (buf != NULL)
                                        buffer_filled(dev, dma_q, buf);
                                get_next_buf(dma_q, &buf);
@@ -632,8 +666,8 @@ static void get_scale(struct em28xx *dev,
                        unsigned int width, unsigned int height,
                        unsigned int *hscale, unsigned int *vscale)
 {
-       unsigned int          maxw   = norm_maxw(dev);
-       unsigned int          maxh   = norm_maxh(dev);
+       unsigned int          maxw = norm_maxw(dev);
+       unsigned int          maxh = norm_maxh(dev);
 
        *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
        if (*hscale >= 0x4000)
@@ -664,7 +698,10 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
 
        /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
-       f->fmt.pix.field = dev->interlaced ?
+       if (dev->progressive)
+               f->fmt.pix.field = V4L2_FIELD_NONE;
+       else
+               f->fmt.pix.field = dev->interlaced ?
                           V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
 
        mutex_unlock(&dev->lock);
@@ -728,7 +765,33 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3;
        f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
        f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+       if (dev->progressive)
+               f->fmt.pix.field = V4L2_FIELD_NONE;
+       else
+               f->fmt.pix.field = dev->interlaced ?
+                          V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
+
+       return 0;
+}
+
+static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
+                                  unsigned width, unsigned height)
+{
+       struct em28xx_fmt     *fmt;
+
+       fmt = format_by_fourcc(fourcc);
+       if (!fmt)
+               return -EINVAL;
+
+       dev->format = fmt;
+       dev->width  = width;
+       dev->height = height;
+
+       /* set new image size */
+       get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
+
+       em28xx_set_alternate(dev);
+       em28xx_resolution_set(dev);
 
        return 0;
 }
@@ -739,7 +802,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        struct em28xx_fh      *fh  = priv;
        struct em28xx         *dev = fh->dev;
        int                   rc;
-       struct em28xx_fmt     *fmt;
 
        rc = check_dev(dev);
        if (rc < 0)
@@ -749,12 +811,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 
        vidioc_try_fmt_vid_cap(file, priv, f);
 
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-       if (!fmt) {
-               rc = -EINVAL;
-               goto out;
-       }
-
        if (videobuf_queue_is_busy(&fh->vb_vidq)) {
                em28xx_errdev("%s queue busy\n", __func__);
                rc = -EBUSY;
@@ -767,16 +823,8 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
                goto out;
        }
 
-       /* set new image size */
-       dev->width = f->fmt.pix.width;
-       dev->height = f->fmt.pix.height;
-       dev->format = fmt;
-       get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
-
-       em28xx_set_alternate(dev);
-       em28xx_resolution_set(dev);
-
-       rc = 0;
+       rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
+                               f->fmt.pix.width, f->fmt.pix.height);
 
 out:
        mutex_unlock(&dev->lock);
@@ -814,6 +862,41 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
        return 0;
 }
 
+static int vidioc_g_parm(struct file *file, void *priv,
+                        struct v4l2_streamparm *p)
+{
+       struct em28xx_fh   *fh  = priv;
+       struct em28xx      *dev = fh->dev;
+       int rc = 0;
+
+       if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (dev->board.is_webcam)
+               rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0,
+                                               video, g_parm, p);
+       else
+               v4l2_video_std_frame_period(dev->norm,
+                                                &p->parm.capture.timeperframe);
+
+       return rc;
+}
+
+static int vidioc_s_parm(struct file *file, void *priv,
+                        struct v4l2_streamparm *p)
+{
+       struct em28xx_fh   *fh  = priv;
+       struct em28xx      *dev = fh->dev;
+
+       if (!dev->board.is_webcam)
+               return -EINVAL;
+
+       if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       return v4l2_device_call_until_err(&dev->v4l2_dev, 0, video, s_parm, p);
+}
+
 static const char *iname[] = {
        [EM28XX_VMUX_COMPOSITE1] = "Composite1",
        [EM28XX_VMUX_COMPOSITE2] = "Composite2",
@@ -1592,6 +1675,7 @@ static int em28xx_v4l2_open(struct file *filp)
        struct em28xx *dev;
        enum v4l2_buf_type fh_type;
        struct em28xx_fh *fh;
+       enum v4l2_field field;
 
        dev = em28xx_get_device(minor, &fh_type, &radio);
 
@@ -1616,11 +1700,6 @@ static int em28xx_v4l2_open(struct file *filp)
        filp->private_data = fh;
 
        if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
-               dev->width = norm_maxw(dev);
-               dev->height = norm_maxh(dev);
-               dev->hscale = 0;
-               dev->vscale = 0;
-
                em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
                em28xx_set_alternate(dev);
                em28xx_resolution_set(dev);
@@ -1638,8 +1717,13 @@ static int em28xx_v4l2_open(struct file *filp)
 
        dev->users++;
 
+       if (dev->progressive)
+               field = V4L2_FIELD_NONE;
+       else
+               field = V4L2_FIELD_INTERLACED;
+
        videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
-                       NULL, &dev->slock, fh->type, V4L2_FIELD_INTERLACED,
+                       NULL, &dev->slock, fh->type, field,
                        sizeof(struct em28xx_buffer), fh);
 
        mutex_unlock(&dev->lock);
@@ -1858,6 +1942,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
        .vidioc_qbuf                = vidioc_qbuf,
        .vidioc_dqbuf               = vidioc_dqbuf,
        .vidioc_s_std               = vidioc_s_std,
+       .vidioc_g_parm              = vidioc_g_parm,
+       .vidioc_s_parm              = vidioc_s_parm,
        .vidioc_enum_input          = vidioc_enum_input,
        .vidioc_g_input             = vidioc_g_input,
        .vidioc_s_input             = vidioc_s_input,
@@ -1962,15 +2048,14 @@ int em28xx_register_analog_devices(struct em28xx *dev)
 
        /* set default norm */
        dev->norm = em28xx_video_template.current_norm;
-       dev->width = norm_maxw(dev);
-       dev->height = norm_maxh(dev);
        dev->interlaced = EM28XX_INTERLACED_DEFAULT;
-       dev->hscale = 0;
-       dev->vscale = 0;
        dev->ctl_input = 0;
 
        /* Analog specific initialization */
        dev->format = &format[0];
+       em28xx_set_video_format(dev, format[0].fourcc,
+                               norm_maxw(dev), norm_maxh(dev));
+
        video_mux(dev, dev->ctl_input);
 
        /* Audio defaults */
index 813ce45c2f997286f0df6fb99f1b718a491753ab..a2add61f7d59dd4555b48b95b81197f337b85951 100644 (file)
 #define EM2860_BOARD_TERRATEC_AV350              68
 #define EM2882_BOARD_KWORLD_ATSC_315U            69
 #define EM2882_BOARD_EVGA_INDTUBE                70
+#define EM2820_BOARD_SILVERCREST_WEBCAM           71
 
 /* Limits minimum and default number of buffers */
 #define EM28XX_MIN_BUF 4
@@ -357,11 +358,18 @@ struct em28xx_input {
 #define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
 
 enum em28xx_decoder {
-       EM28XX_NODECODER,
+       EM28XX_NODECODER = 0,
        EM28XX_TVP5150,
        EM28XX_SAA711X,
 };
 
+enum em28xx_sensor {
+       EM28XX_NOSENSOR = 0,
+       EM28XX_MT9V011,
+       EM28XX_MT9M001,
+       EM28XX_MT9M111,
+};
+
 enum em28xx_adecoder {
        EM28XX_NOADECODER = 0,
        EM28XX_TVAUDIO,
@@ -388,6 +396,7 @@ struct em28xx_board {
        unsigned int max_range_640_480:1;
        unsigned int has_dvb:1;
        unsigned int has_snapshot_button:1;
+       unsigned int is_webcam:1;
        unsigned int valid:1;
 
        unsigned char xclk, i2c_speed;
@@ -471,6 +480,17 @@ struct em28xx {
        struct v4l2_device v4l2_dev;
        struct em28xx_board board;
 
+       /* Webcam specific fields */
+       enum em28xx_sensor em28xx_sensor;
+       int sensor_xres, sensor_yres;
+       int sensor_xtal;
+
+       /* Allows progressive (e. g. non-interlaced) mode */
+       int progressive;
+
+       /* Vinmode/Vinctl used at the driver */
+       int vinmode, vinctl;
+
        unsigned int stream_on:1;       /* Locks streams */
        unsigned int has_audio_class:1;
        unsigned int has_alsa_audio:1;
@@ -751,17 +771,23 @@ static inline int em28xx_gamma_set(struct em28xx *dev, s32 val)
 /*FIXME: maxw should be dependent of alt mode */
 static inline unsigned int norm_maxw(struct em28xx *dev)
 {
+       if (dev->board.is_webcam)
+               return dev->sensor_xres;
+
        if (dev->board.max_range_640_480)
                return 640;
-       else
-               return 720;
+
+       return 720;
 }
 
 static inline unsigned int norm_maxh(struct em28xx *dev)
 {
+       if (dev->board.is_webcam)
+               return dev->sensor_yres;
+
        if (dev->board.max_range_640_480)
                return 480;
-       else
-               return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
+
+       return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
 }
 #endif
index 578dc4ffc9659454da44d548eb80dd5a0018e87b..e994dcac43ffb6cfa2481ed4ff9df7aa86235a4b 100644 (file)
@@ -102,6 +102,22 @@ config USB_GSPCA_PAC7311
          To compile this driver as a module, choose M here: the
          module will be called gspca_pac7311.
 
+config USB_GSPCA_SN9C20X
+       tristate "SN9C20X USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+        Say Y here if you want support for cameras based on the
+        sn9c20x chips (SN9C201 and SN9C202).
+
+        To compile this driver as a module, choose M here: the
+        module will be called gspca_sn9c20x.
+
+config USB_GSPCA_SN9C20X_EVDEV
+       bool "Enable evdev support"
+       depends on USB_GSPCA_SN9C20X && INPUT
+       ---help---
+        Say Y here in order to enable evdev support for sn9c20x webcam button.
+
 config USB_GSPCA_SONIXB
        tristate "SONIX Bayer USB Camera Driver"
        depends on VIDEO_V4L2 && USB_GSPCA
index 8a6643e8eb96d796ebaf6a02bf73d8e7306a0e7f..f6d3b86e9ad566952840305362b61f5ca1781997 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_USB_GSPCA_OV519)    += gspca_ov519.o
 obj-$(CONFIG_USB_GSPCA_OV534)    += gspca_ov534.o
 obj-$(CONFIG_USB_GSPCA_PAC207)   += gspca_pac207.o
 obj-$(CONFIG_USB_GSPCA_PAC7311)  += gspca_pac7311.o
+obj-$(CONFIG_USB_GSPCA_SN9C20X)  += gspca_sn9c20x.o
 obj-$(CONFIG_USB_GSPCA_SONIXB)   += gspca_sonixb.o
 obj-$(CONFIG_USB_GSPCA_SONIXJ)   += gspca_sonixj.o
 obj-$(CONFIG_USB_GSPCA_SPCA500)  += gspca_spca500.o
@@ -35,6 +36,7 @@ gspca_ov519-objs    := ov519.o
 gspca_ov534-objs    := ov534.o
 gspca_pac207-objs   := pac207.o
 gspca_pac7311-objs  := pac7311.o
+gspca_sn9c20x-objs  := sn9c20x.o
 gspca_sonixb-objs   := sonixb.o
 gspca_sonixj-objs   := sonixj.o
 gspca_spca500-objs  := spca500.o
index 219cfa6fb877e2e20353bd0b160ac8933c8bc266..8d48ea1742c2f7ac808c6b9033d7eba69366ffaa 100644 (file)
@@ -846,6 +846,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
        /* create the JPEG header */
        sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+       if (!sd->jpeg_hdr)
+               return -ENOMEM;
        jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
                        0x22);          /* JPEG 411 */
        jpeg_set_qual(sd->jpeg_hdr, sd->quality);
index 1e89600986c89bd3ce19e2bf8a2d3f78c1ccd097..b8561dfb6c8c7bc08880a9057239f6854c582a5f 100644 (file)
@@ -727,6 +727,74 @@ static int gspca_get_mode(struct gspca_dev *gspca_dev,
        return -EINVAL;
 }
 
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register(struct file *file, void *priv,
+                       struct v4l2_dbg_register *reg)
+{
+       int ret;
+       struct gspca_dev *gspca_dev = priv;
+
+       if (!gspca_dev->sd_desc->get_chip_ident)
+               return -EINVAL;
+
+       if (!gspca_dev->sd_desc->get_register)
+               return -EINVAL;
+
+       if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+               return -ERESTARTSYS;
+       if (gspca_dev->present)
+               ret = gspca_dev->sd_desc->get_register(gspca_dev, reg);
+       else
+               ret = -ENODEV;
+       mutex_unlock(&gspca_dev->usb_lock);
+
+       return ret;
+}
+
+static int vidioc_s_register(struct file *file, void *priv,
+                       struct v4l2_dbg_register *reg)
+{
+       int ret;
+       struct gspca_dev *gspca_dev = priv;
+
+       if (!gspca_dev->sd_desc->get_chip_ident)
+               return -EINVAL;
+
+       if (!gspca_dev->sd_desc->set_register)
+               return -EINVAL;
+
+       if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+               return -ERESTARTSYS;
+       if (gspca_dev->present)
+               ret = gspca_dev->sd_desc->set_register(gspca_dev, reg);
+       else
+               ret = -ENODEV;
+       mutex_unlock(&gspca_dev->usb_lock);
+
+       return ret;
+}
+#endif
+
+static int vidioc_g_chip_ident(struct file *file, void *priv,
+                       struct v4l2_dbg_chip_ident *chip)
+{
+       int ret;
+       struct gspca_dev *gspca_dev = priv;
+
+       if (!gspca_dev->sd_desc->get_chip_ident)
+               return -EINVAL;
+
+       if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+               return -ERESTARTSYS;
+       if (gspca_dev->present)
+               ret = gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip);
+       else
+               ret = -ENODEV;
+       mutex_unlock(&gspca_dev->usb_lock);
+
+       return ret;
+}
+
 static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
                                struct v4l2_fmtdesc *fmtdesc)
 {
@@ -1883,6 +1951,11 @@ static const struct v4l2_ioctl_ops dev_ioctl_ops = {
        .vidioc_s_parm          = vidioc_s_parm,
        .vidioc_s_std           = vidioc_s_std,
        .vidioc_enum_framesizes = vidioc_enum_framesizes,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register      = vidioc_g_register,
+       .vidioc_s_register      = vidioc_s_register,
+#endif
+       .vidioc_g_chip_ident    = vidioc_g_chip_ident,
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
        .vidiocgmbuf          = vidiocgmbuf,
 #endif
index bd1faff8864454a9aa163603570fb62c935eab64..46c4effdfcd5b03776f6798eaafb58aebe9a78fa 100644 (file)
@@ -69,6 +69,10 @@ typedef void (*cam_v_op) (struct gspca_dev *);
 typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *);
 typedef int (*cam_jpg_op) (struct gspca_dev *,
                                struct v4l2_jpegcompression *);
+typedef int (*cam_reg_op) (struct gspca_dev *,
+                               struct v4l2_dbg_register *);
+typedef int (*cam_ident_op) (struct gspca_dev *,
+                               struct v4l2_dbg_chip_ident *);
 typedef int (*cam_streamparm_op) (struct gspca_dev *,
                                  struct v4l2_streamparm *);
 typedef int (*cam_qmnu_op) (struct gspca_dev *,
@@ -105,6 +109,11 @@ struct sd_desc {
        cam_qmnu_op querymenu;
        cam_streamparm_op get_streamparm;
        cam_streamparm_op set_streamparm;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       cam_reg_op set_register;
+       cam_reg_op get_register;
+#endif
+       cam_ident_op get_chip_ident;
 };
 
 /* packet types when moving from iso buf to frame buf */
index 191bcd7189798351e5a171767c86fd5e7b8686b1..0163903d1c0fb4a5dbbe0ec0a0b5bd5fa1b11284 100644 (file)
@@ -474,9 +474,6 @@ static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
 
        PDEBUG(D_V4L2, "Set vertical flip to %d", val);
        err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-       if (err < 0)
-               return err;
-       err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
        if (err < 0)
                return err;
 
@@ -522,9 +519,6 @@ static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
 
        PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
        err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-       if (err < 0)
-               return err;
-       err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
        if (err < 0)
                return err;
 
index 75e8d14e4ac74d0e620eff590d8e32d9fe7e0fab..de769caf013dd2f0e8e4330329e6745840128670 100644 (file)
@@ -201,6 +201,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
        /* create the JPEG header */
        sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+       if (!sd->jpeg_hdr)
+               return -ENOMEM;
        jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
                        0x21);          /* JPEG 422 */
        jpeg_set_qual(sd->jpeg_hdr, sd->quality);
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
new file mode 100644 (file)
index 0000000..fcfbbd3
--- /dev/null
@@ -0,0 +1,2434 @@
+/*
+ *     Sonix sn9c201 sn9c202 library
+ *     Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
+ *     Copyright (C) 2009 Brian Johnson <brijohn@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
+ * 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
+ */
+
+#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/usb/input.h>
+#include <linux/input.h>
+#endif
+
+#include "gspca.h"
+#include "jpeg.h"
+
+#include <media/v4l2-chip-ident.h>
+
+MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
+               "microdia project <microdia@googlegroups.com>");
+MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+#define MODULE_NAME "sn9c20x"
+
+#define MODE_RAW       0x10
+#define MODE_JPEG      0x20
+#define MODE_SXGA      0x80
+
+#define SENSOR_OV9650  0
+#define SENSOR_OV9655  1
+#define SENSOR_SOI968  2
+#define SENSOR_OV7660  3
+#define SENSOR_OV7670  4
+#define SENSOR_MT9V011 5
+#define SENSOR_MT9V111 6
+#define SENSOR_MT9V112 7
+#define SENSOR_MT9M001 8
+#define SENSOR_MT9M111 9
+#define SENSOR_HV7131R 10
+#define SENSOR_MT9VPRB 20
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;
+
+#define MIN_AVG_LUM 80
+#define MAX_AVG_LUM 130
+       atomic_t avg_lum;
+       u8 old_step;
+       u8 older_step;
+       u8 exposure_step;
+
+       u8 brightness;
+       u8 contrast;
+       u8 saturation;
+       s16 hue;
+       u8 gamma;
+       u8 red;
+       u8 blue;
+
+       u8 hflip;
+       u8 vflip;
+       u8 gain;
+       u16 exposure;
+       u8 auto_exposure;
+
+       u8 i2c_addr;
+       u8 sensor;
+       u8 hstart;
+       u8 vstart;
+
+       u8 *jpeg_hdr;
+       u8 quality;
+
+#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
+       struct input_dev *input_dev;
+       u8 input_gpio;
+       struct task_struct *input_task;
+#endif
+};
+
+static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_sethue(struct gspca_dev *gspca_dev, s32 val);
+static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val);
+static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setgain(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val);
+static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val);
+static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val);
+
+static struct ctrl sd_ctrls[] = {
+       {
+#define BRIGHTNESS_IDX 0
+           {
+               .id      = V4L2_CID_BRIGHTNESS,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Brightness",
+               .minimum = 0,
+               .maximum = 0xff,
+               .step    = 1,
+#define BRIGHTNESS_DEFAULT 0x7f
+               .default_value = BRIGHTNESS_DEFAULT,
+           },
+           .set = sd_setbrightness,
+           .get = sd_getbrightness,
+       },
+       {
+#define CONTRAST_IDX 1
+           {
+               .id      = V4L2_CID_CONTRAST,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Contrast",
+               .minimum = 0,
+               .maximum = 0xff,
+               .step    = 1,
+#define CONTRAST_DEFAULT 0x7f
+               .default_value = CONTRAST_DEFAULT,
+           },
+           .set = sd_setcontrast,
+           .get = sd_getcontrast,
+       },
+       {
+#define SATURATION_IDX 2
+           {
+               .id      = V4L2_CID_SATURATION,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Saturation",
+               .minimum = 0,
+               .maximum = 0xff,
+               .step    = 1,
+#define SATURATION_DEFAULT 0x7f
+               .default_value = SATURATION_DEFAULT,
+           },
+           .set = sd_setsaturation,
+           .get = sd_getsaturation,
+       },
+       {
+#define HUE_IDX 3
+           {
+               .id      = V4L2_CID_HUE,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Hue",
+               .minimum = -180,
+               .maximum = 180,
+               .step    = 1,
+#define HUE_DEFAULT 0
+               .default_value = HUE_DEFAULT,
+           },
+           .set = sd_sethue,
+           .get = sd_gethue,
+       },
+       {
+#define GAMMA_IDX 4
+           {
+               .id      = V4L2_CID_GAMMA,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Gamma",
+               .minimum = 0,
+               .maximum = 0xff,
+               .step    = 1,
+#define GAMMA_DEFAULT 0x10
+               .default_value = GAMMA_DEFAULT,
+           },
+           .set = sd_setgamma,
+           .get = sd_getgamma,
+       },
+       {
+#define BLUE_IDX 5
+           {
+               .id      = V4L2_CID_BLUE_BALANCE,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Blue Balance",
+               .minimum = 0,
+               .maximum = 0x7f,
+               .step    = 1,
+#define BLUE_DEFAULT 0x28
+               .default_value = BLUE_DEFAULT,
+           },
+           .set = sd_setbluebalance,
+           .get = sd_getbluebalance,
+       },
+       {
+#define RED_IDX 6
+           {
+               .id      = V4L2_CID_RED_BALANCE,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Red Balance",
+               .minimum = 0,
+               .maximum = 0x7f,
+               .step    = 1,
+#define RED_DEFAULT 0x28
+               .default_value = RED_DEFAULT,
+           },
+           .set = sd_setredbalance,
+           .get = sd_getredbalance,
+       },
+       {
+#define HFLIP_IDX 7
+           {
+               .id      = V4L2_CID_HFLIP,
+               .type    = V4L2_CTRL_TYPE_BOOLEAN,
+               .name    = "Horizontal Flip",
+               .minimum = 0,
+               .maximum = 1,
+               .step    = 1,
+#define HFLIP_DEFAULT 0
+               .default_value = HFLIP_DEFAULT,
+           },
+           .set = sd_sethflip,
+           .get = sd_gethflip,
+       },
+       {
+#define VFLIP_IDX 8
+           {
+               .id      = V4L2_CID_VFLIP,
+               .type    = V4L2_CTRL_TYPE_BOOLEAN,
+               .name    = "Vertical Flip",
+               .minimum = 0,
+               .maximum = 1,
+               .step    = 1,
+#define VFLIP_DEFAULT 0
+               .default_value = VFLIP_DEFAULT,
+           },
+           .set = sd_setvflip,
+           .get = sd_getvflip,
+       },
+       {
+#define EXPOSURE_IDX 9
+           {
+               .id      = V4L2_CID_EXPOSURE,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Exposure",
+               .minimum = 0,
+               .maximum = 0x1780,
+               .step    = 1,
+#define EXPOSURE_DEFAULT 0x33
+               .default_value = EXPOSURE_DEFAULT,
+           },
+           .set = sd_setexposure,
+           .get = sd_getexposure,
+       },
+       {
+#define GAIN_IDX 10
+           {
+               .id      = V4L2_CID_GAIN,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Gain",
+               .minimum = 0,
+               .maximum = 28,
+               .step    = 1,
+#define GAIN_DEFAULT 0x00
+               .default_value = GAIN_DEFAULT,
+           },
+           .set = sd_setgain,
+           .get = sd_getgain,
+       },
+       {
+#define AUTOGAIN_IDX 11
+           {
+               .id      = V4L2_CID_AUTOGAIN,
+               .type    = V4L2_CTRL_TYPE_BOOLEAN,
+               .name    = "Auto Exposure",
+               .minimum = 0,
+               .maximum = 1,
+               .step    = 1,
+#define AUTO_EXPOSURE_DEFAULT 1
+               .default_value = AUTO_EXPOSURE_DEFAULT,
+           },
+           .set = sd_setautoexposure,
+           .get = sd_getautoexposure,
+       },
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 240,
+               .sizeimage = 240 * 120,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0 | MODE_JPEG},
+       {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0 | MODE_RAW},
+       {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+               .bytesperline = 240,
+               .sizeimage = 240 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 480,
+               .sizeimage = 480 * 240 ,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1 | MODE_JPEG},
+       {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 ,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1 | MODE_RAW},
+       {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+               .bytesperline = 480,
+               .sizeimage = 480 * 240 ,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 960,
+               .sizeimage = 960 * 480,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2 | MODE_JPEG},
+       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2 | MODE_RAW},
+       {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+               .bytesperline = 960,
+               .sizeimage = 960 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+};
+
+static const struct v4l2_pix_format sxga_mode[] = {
+       {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 240,
+               .sizeimage = 240 * 120,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0 | MODE_JPEG},
+       {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0 | MODE_RAW},
+       {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+               .bytesperline = 240,
+               .sizeimage = 240 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 480,
+               .sizeimage = 480 * 240 ,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1 | MODE_JPEG},
+       {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 ,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1 | MODE_RAW},
+       {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+               .bytesperline = 480,
+               .sizeimage = 480 * 240 ,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 960,
+               .sizeimage = 960 * 480,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2 | MODE_JPEG},
+       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2 | MODE_RAW},
+       {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+               .bytesperline = 960,
+               .sizeimage = 960 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+       {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 1280,
+               .sizeimage = (1280 * 1024) + 64,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 3 | MODE_RAW | MODE_SXGA},
+};
+
+static const int hsv_red_x[] = {
+       41,  44,  46,  48,  50,  52,  54,  56,
+       58,  60,  62,  64,  66,  68,  70,  72,
+       74,  76,  78,  80,  81,  83,  85,  87,
+       88,  90,  92,  93,  95,  97,  98, 100,
+       101, 102, 104, 105, 107, 108, 109, 110,
+       112, 113, 114, 115, 116, 117, 118, 119,
+       120, 121, 122, 123, 123, 124, 125, 125,
+       126, 127, 127, 128, 128, 129, 129, 129,
+       130, 130, 130, 130, 131, 131, 131, 131,
+       131, 131, 131, 131, 130, 130, 130, 130,
+       129, 129, 129, 128, 128, 127, 127, 126,
+       125, 125, 124, 123, 122, 122, 121, 120,
+       119, 118, 117, 116, 115, 114, 112, 111,
+       110, 109, 107, 106, 105, 103, 102, 101,
+       99,  98,  96,  94,  93,  91,  90,  88,
+       86,  84,  83,  81,  79,  77,  75,  74,
+       72,  70,  68,  66,  64,  62,  60,  58,
+       56,  54,  52,  49,  47,  45,  43,  41,
+       39,  36,  34,  32,  30,  28,  25,  23,
+       21,  19,  16,  14,  12,   9,   7,   5,
+       3,   0,  -1,  -3,  -6,  -8, -10, -12,
+       -15, -17, -19, -22, -24, -26, -28, -30,
+       -33, -35, -37, -39, -41, -44, -46, -48,
+       -50, -52, -54, -56, -58, -60, -62, -64,
+       -66, -68, -70, -72, -74, -76, -78, -80,
+       -81, -83, -85, -87, -88, -90, -92, -93,
+       -95, -97, -98, -100, -101, -102, -104, -105,
+       -107, -108, -109, -110, -112, -113, -114, -115,
+       -116, -117, -118, -119, -120, -121, -122, -123,
+       -123, -124, -125, -125, -126, -127, -127, -128,
+       -128, -128, -128, -128, -128, -128, -128, -128,
+       -128, -128, -128, -128, -128, -128, -128, -128,
+       -128, -128, -128, -128, -128, -128, -128, -128,
+       -128, -127, -127, -126, -125, -125, -124, -123,
+       -122, -122, -121, -120, -119, -118, -117, -116,
+       -115, -114, -112, -111, -110, -109, -107, -106,
+       -105, -103, -102, -101, -99, -98, -96, -94,
+       -93, -91, -90, -88, -86, -84, -83, -81,
+       -79, -77, -75, -74, -72, -70, -68, -66,
+       -64, -62, -60, -58, -56, -54, -52, -49,
+       -47, -45, -43, -41, -39, -36, -34, -32,
+       -30, -28, -25, -23, -21, -19, -16, -14,
+       -12,  -9,  -7,  -5,  -3,   0,   1,   3,
+       6,   8,  10,  12,  15,  17,  19,  22,
+       24,  26,  28,  30,  33,  35,  37,  39, 41
+};
+
+static const int hsv_red_y[] = {
+       82,  80,  78,  76,  74,  73,  71,  69,
+       67,  65,  63,  61,  58,  56,  54,  52,
+       50,  48,  46,  44,  41,  39,  37,  35,
+       32,  30,  28,  26,  23,  21,  19,  16,
+       14,  12,  10,   7,   5,   3,   0,  -1,
+       -3,  -6,  -8, -10, -13, -15, -17, -19,
+       -22, -24, -26, -29, -31, -33, -35, -38,
+       -40, -42, -44, -46, -48, -51, -53, -55,
+       -57, -59, -61, -63, -65, -67, -69, -71,
+       -73, -75, -77, -79, -81, -82, -84, -86,
+       -88, -89, -91, -93, -94, -96, -98, -99,
+       -101, -102, -104, -105, -106, -108, -109, -110,
+       -112, -113, -114, -115, -116, -117, -119, -120,
+       -120, -121, -122, -123, -124, -125, -126, -126,
+       -127, -128, -128, -128, -128, -128, -128, -128,
+       -128, -128, -128, -128, -128, -128, -128, -128,
+       -128, -128, -128, -128, -128, -128, -128, -128,
+       -128, -128, -128, -128, -128, -128, -128, -128,
+       -127, -127, -126, -125, -125, -124, -123, -122,
+       -121, -120, -119, -118, -117, -116, -115, -114,
+       -113, -111, -110, -109, -107, -106, -105, -103,
+       -102, -100, -99, -97, -96, -94, -92, -91,
+       -89, -87, -85, -84, -82, -80, -78, -76,
+       -74, -73, -71, -69, -67, -65, -63, -61,
+       -58, -56, -54, -52, -50, -48, -46, -44,
+       -41, -39, -37, -35, -32, -30, -28, -26,
+       -23, -21, -19, -16, -14, -12, -10,  -7,
+       -5,  -3,   0,   1,   3,   6,   8,  10,
+       13,  15,  17,  19,  22,  24,  26,  29,
+       31,  33,  35,  38,  40,  42,  44,  46,
+       48,  51,  53,  55,  57,  59,  61,  63,
+       65,  67,  69,  71,  73,  75,  77,  79,
+       81,  82,  84,  86,  88,  89,  91,  93,
+       94,  96,  98,  99, 101, 102, 104, 105,
+       106, 108, 109, 110, 112, 113, 114, 115,
+       116, 117, 119, 120, 120, 121, 122, 123,
+       124, 125, 126, 126, 127, 128, 128, 129,
+       129, 130, 130, 131, 131, 131, 131, 132,
+       132, 132, 132, 132, 132, 132, 132, 132,
+       132, 132, 132, 131, 131, 131, 130, 130,
+       130, 129, 129, 128, 127, 127, 126, 125,
+       125, 124, 123, 122, 121, 120, 119, 118,
+       117, 116, 115, 114, 113, 111, 110, 109,
+       107, 106, 105, 103, 102, 100,  99,  97,
+       96, 94, 92, 91, 89, 87, 85, 84, 82
+};
+
+static const int hsv_green_x[] = {
+       -124, -124, -125, -125, -125, -125, -125, -125,
+       -125, -126, -126, -125, -125, -125, -125, -125,
+       -125, -124, -124, -124, -123, -123, -122, -122,
+       -121, -121, -120, -120, -119, -118, -117, -117,
+       -116, -115, -114, -113, -112, -111, -110, -109,
+       -108, -107, -105, -104, -103, -102, -100, -99,
+       -98, -96, -95, -93, -92, -91, -89, -87,
+       -86, -84, -83, -81, -79, -77, -76, -74,
+       -72, -70, -69, -67, -65, -63, -61, -59,
+       -57, -55, -53, -51, -49, -47, -45, -43,
+       -41, -39, -37, -35, -33, -30, -28, -26,
+       -24, -22, -20, -18, -15, -13, -11,  -9,
+       -7,  -4,  -2,   0,   1,   3,   6,   8,
+       10,  12,  14,  17,  19,  21,  23,  25,
+       27,  29,  32,  34,  36,  38,  40,  42,
+       44,  46,  48,  50,  52,  54,  56,  58,
+       60,  62,  64,  66,  68,  70,  71,  73,
+       75,  77,  78,  80,  82,  83,  85,  87,
+       88,  90,  91,  93,  94,  96,  97,  98,
+       100, 101, 102, 104, 105, 106, 107, 108,
+       109, 111, 112, 113, 113, 114, 115, 116,
+       117, 118, 118, 119, 120, 120, 121, 122,
+       122, 123, 123, 124, 124, 124, 125, 125,
+       125, 125, 125, 125, 125, 126, 126, 125,
+       125, 125, 125, 125, 125, 124, 124, 124,
+       123, 123, 122, 122, 121, 121, 120, 120,
+       119, 118, 117, 117, 116, 115, 114, 113,
+       112, 111, 110, 109, 108, 107, 105, 104,
+       103, 102, 100,  99,  98,  96,  95,  93,
+       92,  91,  89,  87,  86,  84,  83,  81,
+       79,  77,  76,  74,  72,  70,  69,  67,
+       65,  63,  61,  59,  57,  55,  53,  51,
+       49,  47,  45,  43,  41,  39,  37,  35,
+       33,  30,  28,  26,  24,  22,  20,  18,
+       15,  13,  11,   9,   7,   4,   2,   0,
+       -1,  -3,  -6,  -8, -10, -12, -14, -17,
+       -19, -21, -23, -25, -27, -29, -32, -34,
+       -36, -38, -40, -42, -44, -46, -48, -50,
+       -52, -54, -56, -58, -60, -62, -64, -66,
+       -68, -70, -71, -73, -75, -77, -78, -80,
+       -82, -83, -85, -87, -88, -90, -91, -93,
+       -94, -96, -97, -98, -100, -101, -102, -104,
+       -105, -106, -107, -108, -109, -111, -112, -113,
+       -113, -114, -115, -116, -117, -118, -118, -119,
+       -120, -120, -121, -122, -122, -123, -123, -124, -124
+};
+
+static const int hsv_green_y[] = {
+       -100, -99, -98, -97, -95, -94, -93, -91,
+       -90, -89, -87, -86, -84, -83, -81, -80,
+       -78, -76, -75, -73, -71, -70, -68, -66,
+       -64, -63, -61, -59, -57, -55, -53, -51,
+       -49, -48, -46, -44, -42, -40, -38, -36,
+       -34, -32, -30, -27, -25, -23, -21, -19,
+       -17, -15, -13, -11,  -9,  -7,  -4,  -2,
+       0,   1,   3,   5,   7,   9,  11,  14,
+       16,  18,  20,  22,  24,  26,  28,  30,
+       32,  34,  36,  38,  40,  42,  44,  46,
+       48,  50,  52,  54,  56,  58,  59,  61,
+       63,  65,  67,  68,  70,  72,  74,  75,
+       77,  78,  80,  82,  83,  85,  86,  88,
+       89,  90,  92,  93,  95,  96,  97,  98,
+       100, 101, 102, 103, 104, 105, 106, 107,
+       108, 109, 110, 111, 112, 112, 113, 114,
+       115, 115, 116, 116, 117, 117, 118, 118,
+       119, 119, 119, 120, 120, 120, 120, 120,
+       121, 121, 121, 121, 121, 121, 120, 120,
+       120, 120, 120, 119, 119, 119, 118, 118,
+       117, 117, 116, 116, 115, 114, 114, 113,
+       112, 111, 111, 110, 109, 108, 107, 106,
+       105, 104, 103, 102, 100,  99,  98,  97,
+       95,  94,  93,  91,  90,  89,  87,  86,
+       84,  83,  81,  80,  78,  76,  75,  73,
+       71,  70,  68,  66,  64,  63,  61,  59,
+       57,  55,  53,  51,  49,  48,  46,  44,
+       42,  40,  38,  36,  34,  32,  30,  27,
+       25,  23,  21,  19,  17,  15,  13,  11,
+       9,   7,   4,   2,   0,  -1,  -3,  -5,
+       -7,  -9, -11, -14, -16, -18, -20, -22,
+       -24, -26, -28, -30, -32, -34, -36, -38,
+       -40, -42, -44, -46, -48, -50, -52, -54,
+       -56, -58, -59, -61, -63, -65, -67, -68,
+       -70, -72, -74, -75, -77, -78, -80, -82,
+       -83, -85, -86, -88, -89, -90, -92, -93,
+       -95, -96, -97, -98, -100, -101, -102, -103,
+       -104, -105, -106, -107, -108, -109, -110, -111,
+       -112, -112, -113, -114, -115, -115, -116, -116,
+       -117, -117, -118, -118, -119, -119, -119, -120,
+       -120, -120, -120, -120, -121, -121, -121, -121,
+       -121, -121, -120, -120, -120, -120, -120, -119,
+       -119, -119, -118, -118, -117, -117, -116, -116,
+       -115, -114, -114, -113, -112, -111, -111, -110,
+       -109, -108, -107, -106, -105, -104, -103, -102, -100
+};
+
+static const int hsv_blue_x[] = {
+       112, 113, 114, 114, 115, 116, 117, 117,
+       118, 118, 119, 119, 120, 120, 120, 121,
+       121, 121, 122, 122, 122, 122, 122, 122,
+       122, 122, 122, 122, 122, 122, 121, 121,
+       121, 120, 120, 120, 119, 119, 118, 118,
+       117, 116, 116, 115, 114, 113, 113, 112,
+       111, 110, 109, 108, 107, 106, 105, 104,
+       103, 102, 100,  99,  98,  97,  95,  94,
+       93,  91,  90,  88,  87,  85,  84,  82,
+       80,  79,  77,  76,  74,  72,  70,  69,
+       67,  65,  63,  61,  60,  58,  56,  54,
+       52,  50,  48,  46,  44,  42,  40,  38,
+       36,  34,  32,  30,  28,  26,  24,  22,
+       19,  17,  15,  13,  11,   9,   7,   5,
+       2,   0,  -1,  -3,  -5,  -7,  -9, -12,
+       -14, -16, -18, -20, -22, -24, -26, -28,
+       -31, -33, -35, -37, -39, -41, -43, -45,
+       -47, -49, -51, -53, -54, -56, -58, -60,
+       -62, -64, -66, -67, -69, -71, -73, -74,
+       -76, -78, -79, -81, -83, -84, -86, -87,
+       -89, -90, -92, -93, -94, -96, -97, -98,
+       -99, -101, -102, -103, -104, -105, -106, -107,
+       -108, -109, -110, -111, -112, -113, -114, -114,
+       -115, -116, -117, -117, -118, -118, -119, -119,
+       -120, -120, -120, -121, -121, -121, -122, -122,
+       -122, -122, -122, -122, -122, -122, -122, -122,
+       -122, -122, -121, -121, -121, -120, -120, -120,
+       -119, -119, -118, -118, -117, -116, -116, -115,
+       -114, -113, -113, -112, -111, -110, -109, -108,
+       -107, -106, -105, -104, -103, -102, -100, -99,
+       -98, -97, -95, -94, -93, -91, -90, -88,
+       -87, -85, -84, -82, -80, -79, -77, -76,
+       -74, -72, -70, -69, -67, -65, -63, -61,
+       -60, -58, -56, -54, -52, -50, -48, -46,
+       -44, -42, -40, -38, -36, -34, -32, -30,
+       -28, -26, -24, -22, -19, -17, -15, -13,
+       -11,  -9,  -7,  -5,  -2,   0,   1,   3,
+       5,   7,   9,  12,  14,  16,  18,  20,
+       22,  24,  26,  28,  31,  33,  35,  37,
+       39,  41,  43,  45,  47,  49,  51,  53,
+       54,  56,  58,  60,  62,  64,  66,  67,
+       69,  71,  73,  74,  76,  78,  79,  81,
+       83,  84,  86,  87,  89,  90,  92,  93,
+       94,  96,  97,  98,  99, 101, 102, 103,
+       104, 105, 106, 107, 108, 109, 110, 111, 112
+};
+
+static const int hsv_blue_y[] = {
+       -11, -13, -15, -17, -19, -21, -23, -25,
+       -27, -29, -31, -33, -35, -37, -39, -41,
+       -43, -45, -46, -48, -50, -52, -54, -55,
+       -57, -59, -61, -62, -64, -66, -67, -69,
+       -71, -72, -74, -75, -77, -78, -80, -81,
+       -83, -84, -86, -87, -88, -90, -91, -92,
+       -93, -95, -96, -97, -98, -99, -100, -101,
+       -102, -103, -104, -105, -106, -106, -107, -108,
+       -109, -109, -110, -111, -111, -112, -112, -113,
+       -113, -114, -114, -114, -115, -115, -115, -115,
+       -116, -116, -116, -116, -116, -116, -116, -116,
+       -116, -115, -115, -115, -115, -114, -114, -114,
+       -113, -113, -112, -112, -111, -111, -110, -110,
+       -109, -108, -108, -107, -106, -105, -104, -103,
+       -102, -101, -100, -99, -98, -97, -96, -95,
+       -94, -93, -91, -90, -89, -88, -86, -85,
+       -84, -82, -81, -79, -78, -76, -75, -73,
+       -71, -70, -68, -67, -65, -63, -62, -60,
+       -58, -56, -55, -53, -51, -49, -47, -45,
+       -44, -42, -40, -38, -36, -34, -32, -30,
+       -28, -26, -24, -22, -20, -18, -16, -14,
+       -12, -10,  -8,  -6,  -4,  -2,   0,   1,
+       3,   5,   7,   9,  11,  13,  15,  17,
+       19,  21,  23,  25,  27,  29,  31,  33,
+       35,  37,  39,  41,  43,  45,  46,  48,
+       50,  52,  54,  55,  57,  59,  61,  62,
+       64,  66,  67,  69,  71,  72,  74,  75,
+       77,  78,  80,  81,  83,  84,  86,  87,
+       88,  90,  91,  92,  93,  95,  96,  97,
+       98,  99, 100, 101, 102, 103, 104, 105,
+       106, 106, 107, 108, 109, 109, 110, 111,
+       111, 112, 112, 113, 113, 114, 114, 114,
+       115, 115, 115, 115, 116, 116, 116, 116,
+       116, 116, 116, 116, 116, 115, 115, 115,
+       115, 114, 114, 114, 113, 113, 112, 112,
+       111, 111, 110, 110, 109, 108, 108, 107,
+       106, 105, 104, 103, 102, 101, 100,  99,
+       98,  97,  96,  95,  94,  93,  91,  90,
+       89,  88,  86,  85,  84,  82,  81,  79,
+       78,  76,  75,  73,  71,  70,  68,  67,
+       65,  63,  62,  60,  58,  56,  55,  53,
+       51,  49,  47,  45,  44,  42,  40,  38,
+       36,  34,  32,  30,  28,  26,  24,  22,
+       20,  18,  16,  14,  12,  10,   8,   6,
+       4,   2,   0,  -1,  -3,  -5,  -7,  -9, -11
+};
+
+static u16 i2c_ident[] = {
+       V4L2_IDENT_OV9650,
+       V4L2_IDENT_OV9655,
+       V4L2_IDENT_SOI968,
+       V4L2_IDENT_OV7660,
+       V4L2_IDENT_OV7670,
+       V4L2_IDENT_MT9V011,
+       V4L2_IDENT_MT9V111,
+       V4L2_IDENT_MT9V112,
+       V4L2_IDENT_MT9M001C12ST,
+       V4L2_IDENT_MT9M111,
+       V4L2_IDENT_HV7131R,
+};
+
+static u16 bridge_init[][2] = {
+       {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
+       {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
+       {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
+       {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
+       {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
+       {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
+       {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
+       {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
+       {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
+       {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
+       {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
+       {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
+       {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
+       {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
+       {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
+       {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
+       {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
+       {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
+       {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80}
+};
+
+/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
+static u8 ov_gain[] = {
+       0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
+       0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
+       0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
+       0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
+       0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
+       0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
+       0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
+       0x70 /* 8x */
+};
+
+/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
+static u16 micron1_gain[] = {
+       /* 1x   1.25x   1.5x    1.75x */
+       0x0020, 0x0028, 0x0030, 0x0038,
+       /* 2x   2.25x   2.5x    2.75x */
+       0x00a0, 0x00a4, 0x00a8, 0x00ac,
+       /* 3x   3.25x   3.5x    3.75x */
+       0x00b0, 0x00b4, 0x00b8, 0x00bc,
+       /* 4x   4.25x   4.5x    4.75x */
+       0x00c0, 0x00c4, 0x00c8, 0x00cc,
+       /* 5x   5.25x   5.5x    5.75x */
+       0x00d0, 0x00d4, 0x00d8, 0x00dc,
+       /* 6x   6.25x   6.5x    6.75x */
+       0x00e0, 0x00e4, 0x00e8, 0x00ec,
+       /* 7x   7.25x   7.5x    7.75x */
+       0x00f0, 0x00f4, 0x00f8, 0x00fc,
+       /* 8x */
+       0x01c0
+};
+
+/* mt9m001 sensor uses a different gain formula then other micron sensors */
+/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
+static u16 micron2_gain[] = {
+       /* 1x   1.25x   1.5x    1.75x */
+       0x0008, 0x000a, 0x000c, 0x000e,
+       /* 2x   2.25x   2.5x    2.75x */
+       0x0010, 0x0012, 0x0014, 0x0016,
+       /* 3x   3.25x   3.5x    3.75x */
+       0x0018, 0x001a, 0x001c, 0x001e,
+       /* 4x   4.25x   4.5x    4.75x */
+       0x0020, 0x0051, 0x0052, 0x0053,
+       /* 5x   5.25x   5.5x    5.75x */
+       0x0054, 0x0055, 0x0056, 0x0057,
+       /* 6x   6.25x   6.5x    6.75x */
+       0x0058, 0x0059, 0x005a, 0x005b,
+       /* 7x   7.25x   7.5x    7.75x */
+       0x005c, 0x005d, 0x005e, 0x005f,
+       /* 8x */
+       0x0060
+};
+
+/* Gain = .5 + bit[7:0] / 16 */
+static u8 hv7131r_gain[] = {
+       0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
+       0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
+       0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
+       0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
+       0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
+       0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
+       0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
+       0x78 /* 8x */
+};
+
+static u8 soi968_init[][2] = {
+       {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f},
+       {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
+       {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
+       {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
+       {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
+       {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
+       {0x13, 0x8a}, {0x12, 0x40}, {0x17, 0x13},
+       {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
+       {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
+       {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
+       {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
+};
+
+static u8 ov7660_init[][2] = {
+       {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
+       {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
+       {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
+       {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
+       {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
+       {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
+};
+
+static u8 ov7670_init[][2] = {
+       {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
+       {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
+       {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
+       {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
+       {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
+       {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
+       {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
+       {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
+       {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
+       {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
+       {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
+       {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
+       {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
+       {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
+       {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
+       {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
+       {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
+       {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
+       {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
+       {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
+       {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
+       {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
+       {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
+       {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
+       {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
+       {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
+       {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
+       {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
+       {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
+       {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
+       {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
+       {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
+       {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
+       {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
+       {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
+       {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
+       {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
+       {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
+       {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
+       {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
+       {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
+       {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
+       {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
+       {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
+       {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
+       {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
+       {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
+       {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
+       {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
+       {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
+       {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
+       {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
+       {0x93, 0x00},
+};
+
+static u8 ov9650_init[][2] = {
+       {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
+       {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
+       {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
+       {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
+       {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
+       {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
+       {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
+       {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
+       {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
+       {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
+       {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
+       {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
+       {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
+       {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
+       {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
+       {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
+       {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
+       {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
+       {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
+       {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
+       {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
+       {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
+       {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
+       {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
+       {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
+       {0xaa, 0x92}, {0xab, 0x0a},
+};
+
+static u8 ov9655_init[][2] = {
+       {0x12, 0x80}, {0x12, 0x01}, {0x0d, 0x00}, {0x0e, 0x61},
+       {0x11, 0x80}, {0x13, 0xba}, {0x14, 0x2e}, {0x16, 0x24},
+       {0x1e, 0x04}, {0x1e, 0x04}, {0x1e, 0x04}, {0x27, 0x08},
+       {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x32, 0xbf},
+       {0x34, 0x3d}, {0x35, 0x00}, {0x36, 0xf8}, {0x38, 0x12},
+       {0x39, 0x57}, {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c},
+       {0x3d, 0x19}, {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40},
+       {0x42, 0x80}, {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a},
+       {0x48, 0x3c}, {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc},
+       {0x4d, 0xdc}, {0x4e, 0xdc}, {0x69, 0x02}, {0x6c, 0x04},
+       {0x6f, 0x9e}, {0x70, 0x05}, {0x71, 0x78}, {0x77, 0x02},
+       {0x8a, 0x23}, {0x8c, 0x0d}, {0x90, 0x7e}, {0x91, 0x7c},
+       {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68}, {0xa6, 0x60},
+       {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92}, {0xab, 0x04},
+       {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80}, {0xaf, 0x80},
+       {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00}, {0xb6, 0xaf},
+       {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44}, {0xbe, 0x3b},
+       {0xbf, 0x3a}, {0xc0, 0xe2}, {0xc1, 0xc8}, {0xc2, 0x01},
+       {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
+       {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x12, 0x61},
+       {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
+       {0x03, 0x12}, {0x17, 0x14}, {0x18, 0x00}, {0x19, 0x01},
+       {0x1a, 0x3d}, {0x32, 0xbf}, {0x11, 0x80}, {0x2a, 0x10},
+       {0x2b, 0x0a}, {0x92, 0x00}, {0x93, 0x00}, {0x1e, 0x04},
+       {0x1e, 0x04}, {0x10, 0x7c}, {0x04, 0x03}, {0xa1, 0x00},
+       {0x2d, 0x00}, {0x2e, 0x00}, {0x00, 0x00}, {0x01, 0x80},
+       {0x02, 0x80}, {0x12, 0x61}, {0x36, 0xfa}, {0x8c, 0x8d},
+       {0xc0, 0xaa}, {0x69, 0x0a}, {0x03, 0x12}, {0x17, 0x14},
+       {0x18, 0x00}, {0x19, 0x01}, {0x1a, 0x3d}, {0x32, 0xbf},
+       {0x11, 0x80}, {0x2a, 0x10}, {0x2b, 0x0a}, {0x92, 0x00},
+       {0x93, 0x00}, {0x04, 0x01}, {0x10, 0x1f}, {0xa1, 0x00},
+       {0x00, 0x0a}, {0xa1, 0x00}, {0x10, 0x5d}, {0x04, 0x03},
+       {0x00, 0x01}, {0xa1, 0x00}, {0x10, 0x7c}, {0x04, 0x03},
+       {0x00, 0x03}, {0x00, 0x0a}, {0x00, 0x10}, {0x00, 0x13},
+};
+
+static u16 mt9v112_init[][2] = {
+       {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
+       {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
+       {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
+       {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
+       {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
+       {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
+       {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
+       {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
+       {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
+       {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
+       {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
+       {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
+       {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
+       {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
+       {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
+       {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
+};
+
+static u16 mt9v111_init[][2] = {
+       {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
+       {0x01, 0x0001}, {0x02, 0x0016}, {0x03, 0x01e1},
+       {0x04, 0x0281}, {0x05, 0x0004}, {0x07, 0x3002},
+       {0x21, 0x0000}, {0x25, 0x4024}, {0x26, 0xff03},
+       {0x27, 0xff10}, {0x2b, 0x7828}, {0x2c, 0xb43c},
+       {0x2d, 0xf0a0}, {0x2e, 0x0c64}, {0x2f, 0x0064},
+       {0x67, 0x4010}, {0x06, 0x301e}, {0x08, 0x0480},
+       {0x01, 0x0004}, {0x02, 0x0016}, {0x03, 0x01e6},
+       {0x04, 0x0286}, {0x05, 0x0004}, {0x06, 0x0000},
+       {0x07, 0x3002}, {0x08, 0x0008}, {0x0c, 0x0000},
+       {0x0d, 0x0000}, {0x0e, 0x0000}, {0x0f, 0x0000},
+       {0x10, 0x0000}, {0x11, 0x0000}, {0x12, 0x00b0},
+       {0x13, 0x007c}, {0x14, 0x0000}, {0x15, 0x0000},
+       {0x16, 0x0000}, {0x17, 0x0000}, {0x18, 0x0000},
+       {0x19, 0x0000}, {0x1a, 0x0000}, {0x1b, 0x0000},
+       {0x1c, 0x0000}, {0x1d, 0x0000}, {0x30, 0x0000},
+       {0x30, 0x0005}, {0x31, 0x0000}, {0x02, 0x0016},
+       {0x03, 0x01e1}, {0x04, 0x0281}, {0x05, 0x0004},
+       {0x06, 0x0000}, {0x07, 0x3002}, {0x06, 0x002d},
+       {0x05, 0x0004}, {0x09, 0x0064}, {0x2b, 0x00a0},
+       {0x2c, 0x00a0}, {0x2d, 0x00a0}, {0x2e, 0x00a0},
+       {0x02, 0x0016}, {0x03, 0x01e1}, {0x04, 0x0281},
+       {0x05, 0x0004}, {0x06, 0x002d}, {0x07, 0x3002},
+       {0x0e, 0x0008}, {0x06, 0x002d}, {0x05, 0x0004},
+};
+
+static u16 mt9v011_init[][2] = {
+       {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
+       {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
+       {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
+       {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
+       {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
+       {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
+       {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
+       {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
+       {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
+       {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
+       {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
+       {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
+       {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
+       {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
+       {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
+       {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
+       {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
+       {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
+       {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
+       {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
+       {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
+       {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
+       {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
+       {0x06, 0x0029}, {0x05, 0x0009},
+};
+
+static u16 mt9m001_init[][2] = {
+       {0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e},
+       {0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501},
+       {0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002},
+       {0x0a, 0x0000}, {0x0c, 0x0000}, {0x11, 0x0000},
+       {0x1e, 0x8000}, {0x5f, 0x8904}, {0x60, 0x0000},
+       {0x61, 0x0000}, {0x62, 0x0498}, {0x63, 0x0000},
+       {0x64, 0x0000}, {0x20, 0x111d}, {0x06, 0x00f2},
+       {0x05, 0x0013}, {0x09, 0x10f2}, {0x07, 0x0003},
+       {0x2b, 0x002a}, {0x2d, 0x002a}, {0x2c, 0x002a},
+       {0x2e, 0x0029}, {0x07, 0x0002},
+};
+
+static u16 mt9m111_init[][2] = {
+       {0xf0, 0x0000}, {0x0d, 0x0008}, {0x0d, 0x0009},
+       {0x0d, 0x0008}, {0xf0, 0x0001}, {0x3a, 0x4300},
+       {0x9b, 0x4300}, {0xa1, 0x0280}, {0xa4, 0x0200},
+       {0x06, 0x308e}, {0xf0, 0x0000},
+};
+
+static u8 hv7131r_init[][2] = {
+       {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
+       {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
+       {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
+       {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
+       {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
+       {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
+       {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
+       {0x23, 0x09}, {0x01, 0x08},
+};
+
+int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int result;
+       result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                       0x00,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       reg,
+                       0x00,
+                       gspca_dev->usb_buf,
+                       length,
+                       500);
+       if (unlikely(result < 0 || result != length)) {
+               err("Read register failed 0x%02X", reg);
+               return -EIO;
+       }
+       return 0;
+}
+
+int reg_w(struct gspca_dev *gspca_dev, u16 reg, const u8 *buffer, int length)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int result;
+       memcpy(gspca_dev->usb_buf, buffer, length);
+       result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                       0x08,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       reg,
+                       0x00,
+                       gspca_dev->usb_buf,
+                       length,
+                       500);
+       if (unlikely(result < 0 || result != length)) {
+               err("Write register failed index 0x%02X", reg);
+               return -EIO;
+       }
+       return 0;
+}
+
+int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
+{
+       u8 data[1] = {value};
+       return reg_w(gspca_dev, reg, data, 1);
+}
+
+int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
+{
+       int i;
+       reg_w(gspca_dev, 0x10c0, buffer, 8);
+       for (i = 0; i < 5; i++) {
+               reg_r(gspca_dev, 0x10c0, 1);
+               if (gspca_dev->usb_buf[0] & 0x04) {
+                       if (gspca_dev->usb_buf[0] & 0x08)
+                               return -1;
+                       return 0;
+               }
+               msleep(1);
+       }
+       return -1;
+}
+
+int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       u8 row[8];
+
+       /*
+        * from the point of view of the bridge, the length
+        * includes the address
+        */
+       row[0] = 0x81 | (2 << 4);
+       row[1] = sd->i2c_addr;
+       row[2] = reg;
+       row[3] = val;
+       row[4] = 0x00;
+       row[5] = 0x00;
+       row[6] = 0x00;
+       row[7] = 0x10;
+
+       return i2c_w(gspca_dev, row);
+}
+
+int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 row[8];
+
+       /*
+        * from the point of view of the bridge, the length
+        * includes the address
+        */
+       row[0] = 0x81 | (3 << 4);
+       row[1] = sd->i2c_addr;
+       row[2] = reg;
+       row[3] = (val >> 8) & 0xff;
+       row[4] = val & 0xff;
+       row[5] = 0x00;
+       row[6] = 0x00;
+       row[7] = 0x10;
+
+       return i2c_w(gspca_dev, row);
+}
+
+int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 row[8];
+
+       row[0] = 0x81 | 0x10;
+       row[1] = sd->i2c_addr;
+       row[2] = reg;
+       row[3] = 0;
+       row[4] = 0;
+       row[5] = 0;
+       row[6] = 0;
+       row[7] = 0x10;
+       reg_w(gspca_dev, 0x10c0, row, 8);
+       msleep(1);
+       row[0] = 0x81 | (2 << 4) | 0x02;
+       row[2] = 0;
+       reg_w(gspca_dev, 0x10c0, row, 8);
+       msleep(1);
+       reg_r(gspca_dev, 0x10c2, 5);
+       *val = gspca_dev->usb_buf[3];
+       return 0;
+}
+
+int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 row[8];
+
+       row[0] = 0x81 | 0x10;
+       row[1] = sd->i2c_addr;
+       row[2] = reg;
+       row[3] = 0;
+       row[4] = 0;
+       row[5] = 0;
+       row[6] = 0;
+       row[7] = 0x10;
+       reg_w(gspca_dev, 0x10c0, row, 8);
+       msleep(1);
+       row[0] = 0x81 | (3 << 4) | 0x02;
+       row[2] = 0;
+       reg_w(gspca_dev, 0x10c0, row, 8);
+       msleep(1);
+       reg_r(gspca_dev, 0x10c2, 5);
+       *val = (gspca_dev->usb_buf[2] << 8) | gspca_dev->usb_buf[3];
+       return 0;
+}
+
+static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
+{
+       int i;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
+               if (i2c_w1(gspca_dev, ov9650_init[i][0],
+                               ov9650_init[i][1]) < 0) {
+                       err("OV9650 sensor initialization failed");
+                       return -ENODEV;
+               }
+       }
+       sd->hstart = 1;
+       sd->vstart = 7;
+       return 0;
+}
+
+static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
+{
+       int i;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
+               if (i2c_w1(gspca_dev, ov9655_init[i][0],
+                               ov9655_init[i][1]) < 0) {
+                       err("OV9655 sensor initialization failed");
+                       return -ENODEV;
+               }
+       }
+       /* disable hflip and vflip */
+       gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
+       sd->hstart = 0;
+       sd->vstart = 7;
+       return 0;
+}
+
+static int soi968_init_sensor(struct gspca_dev *gspca_dev)
+{
+       int i;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
+               if (i2c_w1(gspca_dev, soi968_init[i][0],
+                               soi968_init[i][1]) < 0) {
+                       err("SOI968 sensor initialization failed");
+                       return -ENODEV;
+               }
+       }
+       /* disable hflip and vflip */
+       gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
+       sd->hstart = 60;
+       sd->vstart = 11;
+       return 0;
+}
+
+static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
+{
+       int i;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
+               if (i2c_w1(gspca_dev, ov7660_init[i][0],
+                               ov7660_init[i][1]) < 0) {
+                       err("OV7660 sensor initialization failed");
+                       return -ENODEV;
+               }
+       }
+       /* disable hflip and vflip */
+       gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
+       sd->hstart = 1;
+       sd->vstart = 1;
+       return 0;
+}
+
+static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
+{
+       int i;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
+               if (i2c_w1(gspca_dev, ov7670_init[i][0],
+                               ov7670_init[i][1]) < 0) {
+                       err("OV7670 sensor initialization failed");
+                       return -ENODEV;
+               }
+       }
+       /* disable hflip and vflip */
+       gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
+       sd->hstart = 0;
+       sd->vstart = 1;
+       return 0;
+}
+
+static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+       u16 value;
+       int ret;
+
+       sd->i2c_addr = 0x5d;
+       ret = i2c_r2(gspca_dev, 0xff, &value);
+       if ((ret == 0) && (value == 0x8243)) {
+               for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
+                       if (i2c_w2(gspca_dev, mt9v011_init[i][0],
+                                       mt9v011_init[i][1]) < 0) {
+                               err("MT9V011 sensor initialization failed");
+                               return -ENODEV;
+                       }
+               }
+               sd->hstart = 2;
+               sd->vstart = 2;
+               sd->sensor = SENSOR_MT9V011;
+               info("MT9V011 sensor detected");
+               return 0;
+       }
+
+       sd->i2c_addr = 0x5c;
+       i2c_w2(gspca_dev, 0x01, 0x0004);
+       ret = i2c_r2(gspca_dev, 0xff, &value);
+       if ((ret == 0) && (value == 0x823a)) {
+               for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
+                       if (i2c_w2(gspca_dev, mt9v111_init[i][0],
+                                       mt9v111_init[i][1]) < 0) {
+                               err("MT9V111 sensor initialization failed");
+                               return -ENODEV;
+                       }
+               }
+               sd->hstart = 2;
+               sd->vstart = 2;
+               sd->sensor = SENSOR_MT9V111;
+               info("MT9V111 sensor detected");
+               return 0;
+       }
+
+       sd->i2c_addr = 0x5d;
+       ret = i2c_w2(gspca_dev, 0xf0, 0x0000);
+       if (ret < 0) {
+               sd->i2c_addr = 0x48;
+               i2c_w2(gspca_dev, 0xf0, 0x0000);
+       }
+       ret = i2c_r2(gspca_dev, 0x00, &value);
+       if ((ret == 0) && (value == 0x1229)) {
+               for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
+                       if (i2c_w2(gspca_dev, mt9v112_init[i][0],
+                                       mt9v112_init[i][1]) < 0) {
+                               err("MT9V112 sensor initialization failed");
+                               return -ENODEV;
+                       }
+               }
+               sd->hstart = 6;
+               sd->vstart = 2;
+               sd->sensor = SENSOR_MT9V112;
+               info("MT9V112 sensor detected");
+               return 0;
+       }
+
+       return -ENODEV;
+}
+
+static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+       for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
+               if (i2c_w2(gspca_dev, mt9m111_init[i][0],
+                               mt9m111_init[i][1]) < 0) {
+                       err("MT9M111 sensor initialization failed");
+                       return -ENODEV;
+               }
+       }
+       sd->hstart = 0;
+       sd->vstart = 2;
+       return 0;
+}
+
+static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+       for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
+               if (i2c_w2(gspca_dev, mt9m001_init[i][0],
+                               mt9m001_init[i][1]) < 0) {
+                       err("MT9M001 sensor initialization failed");
+                       return -ENODEV;
+               }
+       }
+       /* disable hflip and vflip */
+       gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
+       sd->hstart = 2;
+       sd->vstart = 2;
+       return 0;
+}
+
+static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
+{
+       int i;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
+               if (i2c_w1(gspca_dev, hv7131r_init[i][0],
+                               hv7131r_init[i][1]) < 0) {
+                       err("HV7131R Sensor initialization failed");
+                       return -ENODEV;
+               }
+       }
+       sd->hstart = 0;
+       sd->vstart = 1;
+       return 0;
+}
+
+#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
+static int input_kthread(void *data)
+{
+       struct gspca_dev *gspca_dev = (struct gspca_dev *)data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       DECLARE_WAIT_QUEUE_HEAD(wait);
+       set_freezable();
+       for (;;) {
+               if (kthread_should_stop())
+                       break;
+
+               if (reg_r(gspca_dev, 0x1005, 1) < 0)
+                       continue;
+
+               input_report_key(sd->input_dev,
+                                KEY_CAMERA,
+                                gspca_dev->usb_buf[0] & sd->input_gpio);
+               input_sync(sd->input_dev);
+
+               wait_event_freezable_timeout(wait,
+                                            kthread_should_stop(),
+                                            msecs_to_jiffies(100));
+       }
+       return 0;
+}
+
+
+static int sn9c20x_input_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       if (sd->input_gpio == 0)
+               return 0;
+
+       sd->input_dev = input_allocate_device();
+       if (!sd->input_dev)
+               return -ENOMEM;
+
+       sd->input_dev->name = "SN9C20X Webcam";
+
+       sd->input_dev->phys = kasprintf(GFP_KERNEL, "usb-%s-%s",
+                                        gspca_dev->dev->bus->bus_name,
+                                        gspca_dev->dev->devpath);
+
+       if (!sd->input_dev->phys)
+               return -ENOMEM;
+
+       usb_to_input_id(gspca_dev->dev, &sd->input_dev->id);
+       sd->input_dev->dev.parent = &gspca_dev->dev->dev;
+
+       set_bit(EV_KEY, sd->input_dev->evbit);
+       set_bit(KEY_CAMERA, sd->input_dev->keybit);
+
+       if (input_register_device(sd->input_dev))
+               return -EINVAL;
+
+       sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%d",
+                                    gspca_dev->vdev.minor);
+
+       if (IS_ERR(sd->input_task))
+               return -EINVAL;
+
+       return 0;
+}
+
+static void sn9c20x_input_cleanup(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       if (sd->input_task != NULL && !IS_ERR(sd->input_task))
+               kthread_stop(sd->input_task);
+
+       if (sd->input_dev != NULL) {
+               input_unregister_device(sd->input_dev);
+               kfree(sd->input_dev->phys);
+               input_free_device(sd->input_dev);
+               sd->input_dev = NULL;
+       }
+}
+#endif
+
+static int set_cmatrix(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 hue_coord, hue_index = 180 + sd->hue;
+       u8 cmatrix[21];
+       memset(cmatrix, 0, 21);
+
+       cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26;
+       cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
+       cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
+       cmatrix[18] = sd->brightness - 0x80;
+
+       hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8;
+       cmatrix[6] = (unsigned char)(hue_coord & 0xff);
+       cmatrix[7] = (unsigned char)((hue_coord >> 8) & 0x0f);
+
+       hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8;
+       cmatrix[8] = (unsigned char)(hue_coord & 0xff);
+       cmatrix[9] = (unsigned char)((hue_coord >> 8) & 0x0f);
+
+       hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8;
+       cmatrix[10] = (unsigned char)(hue_coord & 0xff);
+       cmatrix[11] = (unsigned char)((hue_coord >> 8) & 0x0f);
+
+       hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8;
+       cmatrix[12] = (unsigned char)(hue_coord & 0xff);
+       cmatrix[13] = (unsigned char)((hue_coord >> 8) & 0x0f);
+
+       hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8;
+       cmatrix[14] = (unsigned char)(hue_coord & 0xff);
+       cmatrix[15] = (unsigned char)((hue_coord >> 8) & 0x0f);
+
+       hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8;
+       cmatrix[16] = (unsigned char)(hue_coord & 0xff);
+       cmatrix[17] = (unsigned char)((hue_coord >> 8) & 0x0f);
+
+       return reg_w(gspca_dev, 0x10e1, cmatrix, 21);
+}
+
+static int set_gamma(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 gamma[17];
+       u8 gval = sd->gamma * 0xb8 / 0x100;
+
+
+       gamma[0] = 0x0a;
+       gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
+       gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
+       gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
+       gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
+       gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
+       gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
+       gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
+       gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
+       gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
+       gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
+       gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
+       gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
+       gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
+       gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
+       gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
+       gamma[16] = 0xf5;
+
+       return reg_w(gspca_dev, 0x1190, gamma, 17);
+}
+
+static int set_redblue(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       reg_w1(gspca_dev, 0x118c, sd->red);
+       reg_w1(gspca_dev, 0x118f, sd->blue);
+       return 0;
+}
+
+static int set_hvflip(struct gspca_dev *gspca_dev)
+{
+       u8 value, tslb;
+       u16 value2;
+       struct sd *sd = (struct sd *) gspca_dev;
+       switch (sd->sensor) {
+       case SENSOR_OV9650:
+               i2c_r1(gspca_dev, 0x1e, &value);
+               value &= ~0x30;
+               tslb = 0x01;
+               if (sd->hflip)
+                       value |= 0x20;
+               if (sd->vflip) {
+                       value |= 0x10;
+                       tslb = 0x49;
+               }
+               i2c_w1(gspca_dev, 0x1e, value);
+               i2c_w1(gspca_dev, 0x3a, tslb);
+               break;
+       case SENSOR_MT9V111:
+       case SENSOR_MT9V011:
+               i2c_r2(gspca_dev, 0x20, &value2);
+               value2 &= ~0xc0a0;
+               if (sd->hflip)
+                       value2 |= 0x8080;
+               if (sd->vflip)
+                       value2 |= 0x4020;
+               i2c_w2(gspca_dev, 0x20, value2);
+               break;
+       case SENSOR_MT9M111:
+       case SENSOR_MT9V112:
+               i2c_r2(gspca_dev, 0x20, &value2);
+               value2 &= ~0x0003;
+               if (sd->hflip)
+                       value2 |= 0x0002;
+               if (sd->vflip)
+                       value2 |= 0x0001;
+               i2c_w2(gspca_dev, 0x20, value2);
+               break;
+       case SENSOR_HV7131R:
+               i2c_r1(gspca_dev, 0x01, &value);
+               value &= ~0x03;
+               if (sd->vflip)
+                       value |= 0x01;
+               if (sd->hflip)
+                       value |= 0x02;
+               i2c_w1(gspca_dev, 0x01, value);
+               break;
+       }
+       return 0;
+}
+
+static int set_exposure(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 exp[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e};
+       switch (sd->sensor) {
+       case SENSOR_OV7660:
+       case SENSOR_OV7670:
+       case SENSOR_SOI968:
+       case SENSOR_OV9655:
+       case SENSOR_OV9650:
+               exp[0] |= (3 << 4);
+               exp[2] = 0x2d;
+               exp[3] = sd->exposure & 0xff;
+               exp[4] = sd->exposure >> 8;
+               break;
+       case SENSOR_MT9M001:
+       case SENSOR_MT9M111:
+       case SENSOR_MT9V112:
+       case SENSOR_MT9V111:
+       case SENSOR_MT9V011:
+               exp[0] |= (3 << 4);
+               exp[2] = 0x09;
+               exp[3] = sd->exposure >> 8;
+               exp[4] = sd->exposure & 0xff;
+               break;
+       case SENSOR_HV7131R:
+               exp[0] |= (4 << 4);
+               exp[2] = 0x25;
+               exp[3] = ((sd->exposure * 0xffffff) / 0xffff) >> 16;
+               exp[4] = ((sd->exposure * 0xffffff) / 0xffff) >> 8;
+               exp[5] = ((sd->exposure * 0xffffff) / 0xffff) & 0xff;
+               break;
+       }
+       i2c_w(gspca_dev, exp);
+       return 0;
+}
+
+static int set_gain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 gain[8] = {0x81, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d};
+       switch (sd->sensor) {
+       case SENSOR_OV7660:
+       case SENSOR_OV7670:
+       case SENSOR_SOI968:
+       case SENSOR_OV9655:
+       case SENSOR_OV9650:
+               gain[0] |= (2 << 4);
+               gain[3] = ov_gain[sd->gain];
+               break;
+       case SENSOR_MT9V011:
+       case SENSOR_MT9V111:
+               gain[0] |= (3 << 4);
+               gain[2] = 0x35;
+               gain[3] = micron1_gain[sd->gain] >> 8;
+               gain[4] = micron1_gain[sd->gain] & 0xff;
+               break;
+       case SENSOR_MT9V112:
+       case SENSOR_MT9M111:
+               gain[0] |= (3 << 4);
+               gain[2] = 0x2f;
+               gain[3] = micron1_gain[sd->gain] >> 8;
+               gain[4] = micron1_gain[sd->gain] & 0xff;
+               break;
+       case SENSOR_MT9M001:
+               gain[0] |= (3 << 4);
+               gain[2] = 0x2f;
+               gain[3] = micron2_gain[sd->gain] >> 8;
+               gain[4] = micron2_gain[sd->gain] & 0xff;
+               break;
+       case SENSOR_HV7131R:
+               gain[0] |= (2 << 4);
+               gain[2] = 0x30;
+               gain[3] = hv7131r_gain[sd->gain];
+               break;
+       }
+       i2c_w(gspca_dev, gain);
+       return 0;
+}
+
+static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->brightness = val;
+       if (gspca_dev->streaming)
+               return set_cmatrix(gspca_dev);
+       return 0;
+}
+
+static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       *val = sd->brightness;
+       return 0;
+}
+
+
+static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->contrast = val;
+       if (gspca_dev->streaming)
+               return set_cmatrix(gspca_dev);
+       return 0;
+}
+
+static int sd_getcontrast(struct gspca_dev *gspca_dev, s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       *val = sd->contrast;
+       return 0;
+}
+
+static int sd_setsaturation(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->saturation = val;
+       if (gspca_dev->streaming)
+               return set_cmatrix(gspca_dev);
+       return 0;
+}
+
+static int sd_getsaturation(struct gspca_dev *gspca_dev, s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       *val = sd->saturation;
+       return 0;
+}
+
+static int sd_sethue(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->hue = val;
+       if (gspca_dev->streaming)
+               return set_cmatrix(gspca_dev);
+       return 0;
+}
+
+static int sd_gethue(struct gspca_dev *gspca_dev, s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       *val = sd->hue;
+       return 0;
+}
+
+static int sd_setgamma(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->gamma = val;
+       if (gspca_dev->streaming)
+               return set_gamma(gspca_dev);
+       return 0;
+}
+
+static int sd_getgamma(struct gspca_dev *gspca_dev, s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       *val = sd->gamma;
+       return 0;
+}
+
+static int sd_setredbalance(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->red = val;
+       if (gspca_dev->streaming)
+               return set_redblue(gspca_dev);
+       return 0;
+}
+
+static int sd_getredbalance(struct gspca_dev *gspca_dev, s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       *val = sd->red;
+       return 0;
+}
+
+static int sd_setbluebalance(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->blue = val;
+       if (gspca_dev->streaming)
+               return set_redblue(gspca_dev);
+       return 0;
+}
+
+static int sd_getbluebalance(struct gspca_dev *gspca_dev, s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       *val = sd->blue;
+       return 0;
+}
+
+static int sd_sethflip(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->hflip = val;
+       if (gspca_dev->streaming)
+               return set_hvflip(gspca_dev);
+       return 0;
+}
+
+static int sd_gethflip(struct gspca_dev *gspca_dev, s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       *val = sd->hflip;
+       return 0;
+}
+
+static int sd_setvflip(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->vflip = val;
+       if (gspca_dev->streaming)
+               return set_hvflip(gspca_dev);
+       return 0;
+}
+
+static int sd_getvflip(struct gspca_dev *gspca_dev, s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       *val = sd->vflip;
+       return 0;
+}
+
+static int sd_setexposure(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->exposure = val;
+       if (gspca_dev->streaming)
+               return set_exposure(gspca_dev);
+       return 0;
+}
+
+static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       *val = sd->exposure;
+       return 0;
+}
+
+static int sd_setgain(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->gain = val;
+       if (gspca_dev->streaming)
+               return set_gain(gspca_dev);
+       return 0;
+}
+
+static int sd_getgain(struct gspca_dev *gspca_dev, s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       *val = sd->gain;
+       return 0;
+}
+
+static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       sd->auto_exposure = val;
+       return 0;
+}
+
+static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       *val = sd->auto_exposure;
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
+                       struct v4l2_dbg_register *reg)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       switch (reg->match.type) {
+       case V4L2_CHIP_MATCH_HOST:
+               if (reg->match.addr != 0)
+                       return -EINVAL;
+               if (reg->reg < 0x1000 || reg->reg > 0x11ff)
+                       return -EINVAL;
+               if (reg_r(gspca_dev, reg->reg, 1) < 0)
+                       return -EINVAL;
+               reg->val = gspca_dev->usb_buf[0];
+               return 0;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               if (reg->match.addr != sd->i2c_addr)
+                       return -EINVAL;
+               if (sd->sensor >= SENSOR_MT9V011 &&
+                   sd->sensor <= SENSOR_MT9M111) {
+                       if (i2c_r2(gspca_dev, reg->reg, (u16 *)&reg->val) < 0)
+                               return -EINVAL;
+               } else {
+                       if (i2c_r1(gspca_dev, reg->reg, (u8 *)&reg->val) < 0)
+                               return -EINVAL;
+               }
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
+                       struct v4l2_dbg_register *reg)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       switch (reg->match.type) {
+       case V4L2_CHIP_MATCH_HOST:
+               if (reg->match.addr != 0)
+                       return -EINVAL;
+               if (reg->reg < 0x1000 || reg->reg > 0x11ff)
+                       return -EINVAL;
+               if (reg_w1(gspca_dev, reg->reg, reg->val) < 0)
+                       return -EINVAL;
+               return 0;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               if (reg->match.addr != sd->i2c_addr)
+                       return -EINVAL;
+               if (sd->sensor >= SENSOR_MT9V011 &&
+                   sd->sensor <= SENSOR_MT9M111) {
+                       if (i2c_w2(gspca_dev, reg->reg, reg->val) < 0)
+                               return -EINVAL;
+               } else {
+                       if (i2c_w1(gspca_dev, reg->reg, reg->val) < 0)
+                               return -EINVAL;
+               }
+               return 0;
+       }
+       return -EINVAL;
+}
+#endif
+
+static int sd_chip_ident(struct gspca_dev *gspca_dev,
+                       struct v4l2_dbg_chip_ident *chip)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (chip->match.type) {
+       case V4L2_CHIP_MATCH_HOST:
+               if (chip->match.addr != 0)
+                       return -EINVAL;
+               chip->revision = 0;
+               chip->ident = V4L2_IDENT_SN9C20X;
+               return 0;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               if (chip->match.addr != sd->i2c_addr)
+                       return -EINVAL;
+               chip->revision = 0;
+               chip->ident = i2c_ident[sd->sensor];
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+
+       cam = &gspca_dev->cam;
+
+       sd->sensor = (id->driver_info >> 8) & 0xff;
+       sd->i2c_addr = id->driver_info & 0xff;
+
+       switch (sd->sensor) {
+       case SENSOR_OV9650:
+               cam->cam_mode = sxga_mode;
+               cam->nmodes = ARRAY_SIZE(sxga_mode);
+               break;
+       default:
+               cam->cam_mode = vga_mode;
+               cam->nmodes = ARRAY_SIZE(vga_mode);
+       }
+
+       sd->old_step = 0;
+       sd->older_step = 0;
+       sd->exposure_step = 16;
+
+       sd->brightness = BRIGHTNESS_DEFAULT;
+       sd->contrast = CONTRAST_DEFAULT;
+       sd->saturation = SATURATION_DEFAULT;
+       sd->hue = HUE_DEFAULT;
+       sd->gamma = GAMMA_DEFAULT;
+       sd->red = RED_DEFAULT;
+       sd->blue = BLUE_DEFAULT;
+
+       sd->hflip = HFLIP_DEFAULT;
+       sd->vflip = VFLIP_DEFAULT;
+       sd->exposure = EXPOSURE_DEFAULT;
+       sd->gain = GAIN_DEFAULT;
+       sd->auto_exposure = AUTO_EXPOSURE_DEFAULT;
+
+       sd->quality = 95;
+
+#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
+       sd->input_gpio = (id->driver_info >> 16) & 0xff;
+       if (sn9c20x_input_init(gspca_dev) < 0)
+               return -ENODEV;
+#endif
+       return 0;
+}
+
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+       u8 value;
+       u8 i2c_init[9] =
+               {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
+
+       for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
+               value = bridge_init[i][1];
+               if (reg_w(gspca_dev, bridge_init[i][0], &value, 1) < 0) {
+                       err("Device initialization failed");
+                       return -ENODEV;
+               }
+       }
+
+       if (reg_w(gspca_dev, 0x10c0, i2c_init, 9) < 0) {
+               err("Device initialization failed");
+               return -ENODEV;
+       }
+
+       switch (sd->sensor) {
+       case SENSOR_OV9650:
+               if (ov9650_init_sensor(gspca_dev) < 0)
+                       return -ENODEV;
+               info("OV9650 sensor detected");
+               break;
+       case SENSOR_OV9655:
+               if (ov9655_init_sensor(gspca_dev) < 0)
+                       return -ENODEV;
+               info("OV9655 sensor detected");
+               break;
+       case SENSOR_SOI968:
+               if (soi968_init_sensor(gspca_dev) < 0)
+                       return -ENODEV;
+               info("SOI968 sensor detected");
+               break;
+       case SENSOR_OV7660:
+               if (ov7660_init_sensor(gspca_dev) < 0)
+                       return -ENODEV;
+               info("OV7660 sensor detected");
+               break;
+       case SENSOR_OV7670:
+               if (ov7670_init_sensor(gspca_dev) < 0)
+                       return -ENODEV;
+               info("OV7670 sensor detected");
+               break;
+       case SENSOR_MT9VPRB:
+               if (mt9v_init_sensor(gspca_dev) < 0)
+                       return -ENODEV;
+               break;
+       case SENSOR_MT9M111:
+               if (mt9m111_init_sensor(gspca_dev) < 0)
+                       return -ENODEV;
+               info("MT9M111 sensor detected");
+               break;
+       case SENSOR_MT9M001:
+               if (mt9m001_init_sensor(gspca_dev) < 0)
+                       return -ENODEV;
+               info("MT9M001 sensor detected");
+               break;
+       case SENSOR_HV7131R:
+               if (hv7131r_init_sensor(gspca_dev) < 0)
+                       return -ENODEV;
+               info("HV7131R sensor detected");
+               break;
+       default:
+               info("Unsupported Sensor");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 value;
+       switch (sd->sensor) {
+       case SENSOR_OV9650:
+               if (mode & MODE_SXGA) {
+                       i2c_w1(gspca_dev, 0x17, 0x1b);
+                       i2c_w1(gspca_dev, 0x18, 0xbc);
+                       i2c_w1(gspca_dev, 0x19, 0x01);
+                       i2c_w1(gspca_dev, 0x1a, 0x82);
+                       i2c_r1(gspca_dev, 0x12, &value);
+                       i2c_w1(gspca_dev, 0x12, value & 0x07);
+               } else {
+                       i2c_w1(gspca_dev, 0x17, 0x24);
+                       i2c_w1(gspca_dev, 0x18, 0xc5);
+                       i2c_w1(gspca_dev, 0x19, 0x00);
+                       i2c_w1(gspca_dev, 0x1a, 0x3c);
+                       i2c_r1(gspca_dev, 0x12, &value);
+                       i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
+               }
+               break;
+       }
+}
+
+#define HW_WIN(mode, hstart, vstart) \
+((const u8 []){hstart & 0xff, hstart >> 8, \
+vstart & 0xff, vstart >> 8, \
+(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
+(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
+
+#define CLR_WIN(width, height) \
+((const u8 [])\
+{0, width >> 2, 0, height >> 1,\
+((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+       int width = gspca_dev->width;
+       int height = gspca_dev->height;
+       u8 fmt, scale = 0;
+
+       sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+       if (sd->jpeg_hdr == NULL)
+               return -ENOMEM;
+
+       jpeg_define(sd->jpeg_hdr, height, width,
+                       0x21);
+       jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+
+       if (mode & MODE_RAW)
+               fmt = 0x2d;
+       else if (mode & MODE_JPEG)
+               fmt = 0x2c;
+       else
+               fmt = 0x2f;
+
+       switch (mode & 0x0f) {
+       case 3:
+               scale = 0xc0;
+               info("Set 1280x1024");
+               break;
+       case 2:
+               scale = 0x80;
+               info("Set 640x480");
+               break;
+       case 1:
+               scale = 0x90;
+               info("Set 320x240");
+               break;
+       case 0:
+               scale = 0xa0;
+               info("Set 160x120");
+               break;
+       }
+
+       configure_sensor_output(gspca_dev, mode);
+       reg_w(gspca_dev, 0x1100, sd->jpeg_hdr + JPEG_QT0_OFFSET, 64);
+       reg_w(gspca_dev, 0x1140, sd->jpeg_hdr + JPEG_QT1_OFFSET, 64);
+       reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
+       reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
+       reg_w1(gspca_dev, 0x1189, scale);
+       reg_w1(gspca_dev, 0x10e0, fmt);
+
+       set_cmatrix(gspca_dev);
+       set_gamma(gspca_dev);
+       set_redblue(gspca_dev);
+       set_gain(gspca_dev);
+       set_exposure(gspca_dev);
+       set_hvflip(gspca_dev);
+
+       reg_r(gspca_dev, 0x1061, 1);
+       reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] | 0x02);
+       return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       reg_r(gspca_dev, 0x1061, 1);
+       reg_w1(gspca_dev, 0x1061, gspca_dev->usb_buf[0] & ~0x02);
+}
+
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       kfree(sd->jpeg_hdr);
+}
+
+static void do_autoexposure(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int avg_lum, new_exp;
+
+       if (!sd->auto_exposure)
+               return;
+
+       avg_lum = atomic_read(&sd->avg_lum);
+
+       /*
+        * some hardcoded values are present
+        * like those for maximal/minimal exposure
+        * and exposure steps
+        */
+       if (avg_lum < MIN_AVG_LUM) {
+               if (sd->exposure > 0x1770)
+                       return;
+
+               new_exp = sd->exposure + sd->exposure_step;
+               if (new_exp > 0x1770)
+                       new_exp = 0x1770;
+               if (new_exp < 0x10)
+                       new_exp = 0x10;
+               sd->exposure = new_exp;
+               set_exposure(gspca_dev);
+
+               sd->older_step = sd->old_step;
+               sd->old_step = 1;
+
+               if (sd->old_step ^ sd->older_step)
+                       sd->exposure_step /= 2;
+               else
+                       sd->exposure_step += 2;
+       }
+       if (avg_lum > MAX_AVG_LUM) {
+               if (sd->exposure < 0x10)
+                       return;
+               new_exp = sd->exposure - sd->exposure_step;
+               if (new_exp > 0x1700)
+                       new_exp = 0x1770;
+               if (new_exp < 0x10)
+                       new_exp = 0x10;
+               sd->exposure = new_exp;
+               set_exposure(gspca_dev);
+               sd->older_step = sd->old_step;
+               sd->old_step = 0;
+
+               if (sd->old_step ^ sd->older_step)
+                       sd->exposure_step /= 2;
+               else
+                       sd->exposure_step += 2;
+       }
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       struct gspca_frame *frame,      /* target */
+                       u8 *data,                       /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int avg_lum;
+       static unsigned char frame_header[] =
+               {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
+       if (len == 64 && memcmp(data, frame_header, 6) == 0) {
+               avg_lum = ((data[35] >> 2) & 3) |
+                          (data[20] << 2) |
+                          (data[19] << 10);
+               avg_lum += ((data[35] >> 4) & 3) |
+                           (data[22] << 2) |
+                           (data[21] << 10);
+               avg_lum += ((data[35] >> 6) & 3) |
+                           (data[24] << 2) |
+                           (data[23] << 10);
+               avg_lum += (data[36] & 3) |
+                          (data[26] << 2) |
+                          (data[25] << 10);
+               avg_lum += ((data[36] >> 2) & 3) |
+                           (data[28] << 2) |
+                           (data[27] << 10);
+               avg_lum += ((data[36] >> 4) & 3) |
+                           (data[30] << 2) |
+                           (data[29] << 10);
+               avg_lum += ((data[36] >> 6) & 3) |
+                           (data[32] << 2) |
+                           (data[31] << 10);
+               avg_lum += ((data[44] >> 4) & 3) |
+                           (data[34] << 2) |
+                           (data[33] << 10);
+               avg_lum >>= 9;
+               atomic_set(&sd->avg_lum, avg_lum);
+               gspca_frame_add(gspca_dev, LAST_PACKET,
+                               frame, data, len);
+               return;
+       }
+       if (gspca_dev->last_packet_type == LAST_PACKET) {
+               if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
+                               & MODE_JPEG) {
+                       gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+                               sd->jpeg_hdr, JPEG_HDR_SZ);
+                       gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+                               data, len);
+               } else {
+                       gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+                               data, len);
+               }
+       } else {
+               gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
+       }
+}
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name = MODULE_NAME,
+       .ctrls = sd_ctrls,
+       .nctrls = ARRAY_SIZE(sd_ctrls),
+       .config = sd_config,
+       .init = sd_init,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .stop0 = sd_stop0,
+       .pkt_scan = sd_pkt_scan,
+       .dq_callback = do_autoexposure,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .set_register = sd_dbg_s_register,
+       .get_register = sd_dbg_g_register,
+#endif
+       .get_chip_ident = sd_chip_ident,
+};
+
+#define SN9C20X(sensor, i2c_addr, button_mask) \
+       .driver_info =  (button_mask << 16) \
+                       | (SENSOR_ ## sensor << 8) \
+                       | (i2c_addr)
+
+static const __devinitdata struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
+       {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
+       {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, 0x10)},
+       {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
+       {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
+       {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, 0)},
+       {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
+       {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
+       {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
+       {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
+       {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
+       {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, 0)},
+       {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
+       {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
+       {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
+       {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
+       {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
+       {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
+       {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
+       {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
+       {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
+       {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
+       {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+                   const struct usb_device_id *id)
+{
+       return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
+                               THIS_MODULE);
+}
+
+static void sd_disconnect(struct usb_interface *intf)
+{
+#ifdef CONFIG_USB_GSPCA_SN9C20X_EVDEV
+       struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+
+       sn9c20x_input_cleanup(gspca_dev);
+#endif
+
+       gspca_disconnect(intf);
+}
+
+static struct usb_driver sd_driver = {
+       .name = MODULE_NAME,
+       .id_table = device_table,
+       .probe = sd_probe,
+       .disconnect = sd_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+       int ret;
+       ret = usb_register(&sd_driver);
+       if (ret < 0)
+               return ret;
+       info("registered");
+       return 0;
+}
+static void __exit sd_mod_exit(void)
+{
+       usb_deregister(&sd_driver);
+       info("deregistered");
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
index 0d02f41fa7d099835e390c23e957806c277b4f16..d6332ab80669218cdfa1d5b0fdd3a61874be9fc5 100644 (file)
@@ -1634,6 +1634,8 @@ static void setfreq(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
+       if (gspca_dev->ctrl_dis & (1 << FREQ_IDX))
+               return;
        if (sd->sensor == SENSOR_OV7660) {
                switch (sd->freq) {
                case 0: /* Banding filter disabled */
@@ -1735,6 +1737,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
        /* create the JPEG header */
        sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+       if (!sd->jpeg_hdr)
+               return -ENOMEM;
        jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
                        0x21);          /* JPEG 422 */
        jpeg_set_qual(sd->jpeg_hdr, sd->quality);
index 8806b2ff82bece047379e53fe80ef92c1e629ba2..fab7ef85a6c1dc34f9ca1c4e4f7e12febf6b560a 100644 (file)
@@ -670,6 +670,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
        /* create the JPEG header */
        sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+       if (!sd->jpeg_hdr)
+               return -ENOMEM;
        jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
                        0x22);          /* JPEG 411 */
        jpeg_set_qual(sd->jpeg_hdr, sd->quality);
index f25be20cf1a6f0865e6e8a1757076d2bc6ef4cf3..47628964801e6c350c685ef99529068a9fccdbd7 100644 (file)
@@ -333,6 +333,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
        /* create the JPEG header */
        sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+       if (!sd->jpeg_hdr)
+               return -ENOMEM;
        jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
                        0x22);          /* JPEG 411 */
        jpeg_set_qual(sd->jpeg_hdr, sd->quality);
index 9df7137fe67ec80c19db1a079b70a76688fc6279..992ce530f138d49265ffce759c5e5036c9400312 100644 (file)
 
 #define STV_ISOC_ENDPOINT_ADDR         0x81
 
-#ifndef V4L2_PIX_FMT_SGRBG8
-#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G')
-#endif
-
 #define STV_REG23                      0x0423
 
 /* Control registers of the STV0600 ASIC */
index 3039ec208f3a5e37c029cc44876642eb0611867f..e5024c8496ef75ddd5f35f2f325b77c0c8c4d853 100644 (file)
@@ -64,7 +64,7 @@ static struct v4l2_pix_format hdcs1x00_mode[] = {
        {
                HDCS_1X00_DEF_WIDTH,
                HDCS_1X00_DEF_HEIGHT,
-               V4L2_PIX_FMT_SBGGR8,
+               V4L2_PIX_FMT_SGRBG8,
                V4L2_FIELD_NONE,
                .sizeimage =
                        HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT,
@@ -80,7 +80,7 @@ static struct v4l2_pix_format hdcs1020_mode[] = {
        {
                HDCS_1020_DEF_WIDTH,
                HDCS_1020_DEF_HEIGHT,
-               V4L2_PIX_FMT_SBGGR8,
+               V4L2_PIX_FMT_SGRBG8,
                V4L2_FIELD_NONE,
                .sizeimage =
                        HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT,
@@ -131,9 +131,11 @@ static int hdcs_reg_write_seq(struct sd *sd, u8 reg, u8 *vals, u8 len)
                     (reg + len > 0xff)))
                return -EINVAL;
 
-       for (i = 0; i < len; i++, reg++) {
-               regs[2*i] = reg;
-               regs[2*i+1] = vals[i];
+       for (i = 0; i < len; i++) {
+               regs[2 * i] = reg;
+               regs[2 * i + 1] = vals[i];
+               /* All addresses are shifted left one bit as bit 0 toggles r/w */
+               reg += 2;
        }
 
        return stv06xx_write_sensor_bytes(sd, regs, len);
@@ -174,7 +176,9 @@ static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state)
        }
 
        ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val);
-       if (ret < 0)
+
+       /* Update the state if the write succeeded */
+       if (!ret)
                hdcs->state = state;
 
        return ret;
index 9623f294bdac1aada92418a7b58f0cbf80a21819..5127bbf9dd260ed519397f535953c830e67d16ea 100644 (file)
@@ -973,6 +973,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
        /* create the JPEG header */
        sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+       if (!sd->jpeg_hdr)
+               return -ENOMEM;
        jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
                        0x22);          /* JPEG 411 */
        jpeg_set_qual(sd->jpeg_hdr, sd->quality);
index 08422d315e68023a10c94570b192dffa8e8c2503..3d2756f7874adac447954820267bf519198f53f8 100644 (file)
@@ -7243,6 +7243,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
        /* create the JPEG header */
        sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+       if (!sd->jpeg_hdr)
+               return -ENOMEM;
        jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
                        0x21);          /* JPEG 422 */
        jpeg_set_qual(sd->jpeg_hdr, sd->quality);
index ccd47f57f42cf75633dd6c5badb91786d835d1e0..d678765cbba233a1b6bc869c858532b01735233b 100644 (file)
@@ -1220,6 +1220,8 @@ static const struct video_device hdpvr_video_template = {
                V4L2_STD_PAL_G | V4L2_STD_PAL_H | V4L2_STD_PAL_I |
                V4L2_STD_PAL_D | V4L2_STD_PAL_M | V4L2_STD_PAL_N |
                V4L2_STD_PAL_60,
+       .current_norm           = V4L2_STD_NTSC | V4L2_STD_PAL_M |
+               V4L2_STD_PAL_60,
 };
 
 int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
index a3b77ed3f08949a58729ea1edda921cb762d0dc7..4a9c8ce0ecb307cc07d167a0c6685bcd3583fefe 100644 (file)
@@ -17,6 +17,7 @@
     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 "ivtv-driver.h"
 #include "ivtv-cards.h"
@@ -281,7 +282,7 @@ int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
                idx = p.audio_properties & 0x03;
                /* The audio clock of the digitizer must match the codec sample
                   rate otherwise you get some very strange effects. */
-               if (idx < sizeof(freqs))
+               if (idx < ARRAY_SIZE(freqs))
                        ivtv_call_all(itv, audio, s_clock_freq, freqs[idx]);
                return err;
        }
diff --git a/drivers/media/video/mt9v011.c b/drivers/media/video/mt9v011.c
new file mode 100644 (file)
index 0000000..cc85f77
--- /dev/null
@@ -0,0 +1,634 @@
+/*
+ * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor
+ *
+ * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com)
+ * This code is placed under the terms of the GNU General Public License v2
+ */
+
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/delay.h>
+#include <asm/div64.h>
+#include <media/v4l2-device.h>
+#include "mt9v011.h"
+#include <media/v4l2-i2c-drv.h>
+#include <media/v4l2-chip-ident.h>
+
+MODULE_DESCRIPTION("Micron mt9v011 sensor driver");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_LICENSE("GPL");
+
+
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-2)");
+
+/* supported controls */
+static struct v4l2_queryctrl mt9v011_qctrl[] = {
+       {
+               .id = V4L2_CID_GAIN,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Gain",
+               .minimum = 0,
+               .maximum = (1 << 10) - 1,
+               .step = 1,
+               .default_value = 0x0020,
+               .flags = 0,
+       }, {
+               .id = V4L2_CID_RED_BALANCE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Red Balance",
+               .minimum = -1 << 9,
+               .maximum = (1 << 9) - 1,
+               .step = 1,
+               .default_value = 0,
+               .flags = 0,
+       }, {
+               .id = V4L2_CID_BLUE_BALANCE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Blue Balance",
+               .minimum = -1 << 9,
+               .maximum = (1 << 9) - 1,
+               .step = 1,
+               .default_value = 0,
+               .flags = 0,
+       }, {
+               .id      = V4L2_CID_HFLIP,
+               .type    = V4L2_CTRL_TYPE_BOOLEAN,
+               .name    = "Mirror",
+               .minimum = 0,
+               .maximum = 1,
+               .step    = 1,
+               .default_value = 0,
+               .flags = 0,
+       }, {
+               .id      = V4L2_CID_VFLIP,
+               .type    = V4L2_CTRL_TYPE_BOOLEAN,
+               .name    = "Vflip",
+               .minimum = 0,
+               .maximum = 1,
+               .step    = 1,
+               .default_value = 0,
+               .flags = 0,
+       }, {
+       }
+};
+
+struct mt9v011 {
+       struct v4l2_subdev sd;
+       unsigned width, height;
+       unsigned xtal;
+       unsigned hflip:1;
+       unsigned vflip:1;
+
+       u16 global_gain, red_bal, blue_bal;
+};
+
+static inline struct mt9v011 *to_mt9v011(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct mt9v011, sd);
+}
+
+static int mt9v011_read(struct v4l2_subdev *sd, unsigned char addr)
+{
+       struct i2c_client *c = v4l2_get_subdevdata(sd);
+       __be16 buffer;
+       int rc, val;
+
+       rc = i2c_master_send(c, &addr, 1);
+       if (rc != 1)
+               v4l2_dbg(0, debug, sd,
+                        "i2c i/o error: rc == %d (should be 1)\n", rc);
+
+       msleep(10);
+
+       rc = i2c_master_recv(c, (char *)&buffer, 2);
+       if (rc != 2)
+               v4l2_dbg(0, debug, sd,
+                        "i2c i/o error: rc == %d (should be 2)\n", rc);
+
+       val = be16_to_cpu(buffer);
+
+       v4l2_dbg(2, debug, sd, "mt9v011: read 0x%02x = 0x%04x\n", addr, val);
+
+       return val;
+}
+
+static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr,
+                                u16 value)
+{
+       struct i2c_client *c = v4l2_get_subdevdata(sd);
+       unsigned char buffer[3];
+       int rc;
+
+       buffer[0] = addr;
+       buffer[1] = value >> 8;
+       buffer[2] = value & 0xff;
+
+       v4l2_dbg(2, debug, sd,
+                "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value);
+       rc = i2c_master_send(c, buffer, 3);
+       if (rc != 3)
+               v4l2_dbg(0, debug, sd,
+                        "i2c i/o error: rc == %d (should be 3)\n", rc);
+}
+
+
+struct i2c_reg_value {
+       unsigned char reg;
+       u16           value;
+};
+
+/*
+ * Values used at the original driver
+ * Some values are marked as Reserved at the datasheet
+ */
+static const struct i2c_reg_value mt9v011_init_default[] = {
+               { R0D_MT9V011_RESET, 0x0001 },
+               { R0D_MT9V011_RESET, 0x0000 },
+
+               { R0C_MT9V011_SHUTTER_DELAY, 0x0000 },
+               { R09_MT9V011_SHUTTER_WIDTH, 0x1fc },
+
+               { R0A_MT9V011_CLK_SPEED, 0x0000 },
+               { R1E_MT9V011_DIGITAL_ZOOM,  0x0000 },
+
+               { R07_MT9V011_OUT_CTRL, 0x0002 },       /* chip enable */
+};
+
+static void set_balance(struct v4l2_subdev *sd)
+{
+       struct mt9v011 *core = to_mt9v011(sd);
+       u16 green1_gain, green2_gain, blue_gain, red_gain;
+
+       green1_gain = core->global_gain;
+       green2_gain = core->global_gain;
+
+       blue_gain = core->global_gain +
+                   core->global_gain * core->blue_bal / (1 << 9);
+
+       red_gain = core->global_gain +
+                  core->global_gain * core->blue_bal / (1 << 9);
+
+       mt9v011_write(sd, R2B_MT9V011_GREEN_1_GAIN, green1_gain);
+       mt9v011_write(sd, R2E_MT9V011_GREEN_2_GAIN,  green1_gain);
+       mt9v011_write(sd, R2C_MT9V011_BLUE_GAIN, blue_gain);
+       mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain);
+}
+
+static void calc_fps(struct v4l2_subdev *sd, u32 *numerator, u32 *denominator)
+{
+       struct mt9v011 *core = to_mt9v011(sd);
+       unsigned height, width, hblank, vblank, speed;
+       unsigned row_time, t_time;
+       u64 frames_per_ms;
+       unsigned tmp;
+
+       height = mt9v011_read(sd, R03_MT9V011_HEIGHT);
+       width = mt9v011_read(sd, R04_MT9V011_WIDTH);
+       hblank = mt9v011_read(sd, R05_MT9V011_HBLANK);
+       vblank = mt9v011_read(sd, R06_MT9V011_VBLANK);
+       speed = mt9v011_read(sd, R0A_MT9V011_CLK_SPEED);
+
+       row_time = (width + 113 + hblank) * (speed + 2);
+       t_time = row_time * (height + vblank + 1);
+
+       frames_per_ms = core->xtal * 1000l;
+       do_div(frames_per_ms, t_time);
+       tmp = frames_per_ms;
+
+       v4l2_dbg(1, debug, sd, "Programmed to %u.%03u fps (%d pixel clcks)\n",
+               tmp / 1000, tmp % 1000, t_time);
+
+       if (numerator && denominator) {
+               *numerator = 1000;
+               *denominator = (u32)frames_per_ms;
+       }
+}
+
+static u16 calc_speed(struct v4l2_subdev *sd, u32 numerator, u32 denominator)
+{
+       struct mt9v011 *core = to_mt9v011(sd);
+       unsigned height, width, hblank, vblank;
+       unsigned row_time, line_time;
+       u64 t_time, speed;
+
+       /* Avoid bogus calculus */
+       if (!numerator || !denominator)
+               return 0;
+
+       height = mt9v011_read(sd, R03_MT9V011_HEIGHT);
+       width = mt9v011_read(sd, R04_MT9V011_WIDTH);
+       hblank = mt9v011_read(sd, R05_MT9V011_HBLANK);
+       vblank = mt9v011_read(sd, R06_MT9V011_VBLANK);
+
+       row_time = width + 113 + hblank;
+       line_time = height + vblank + 1;
+
+       t_time = core->xtal * ((u64)numerator);
+       /* round to the closest value */
+       t_time += denominator / 2;
+       do_div(t_time, denominator);
+
+       speed = t_time;
+       do_div(speed, row_time * line_time);
+
+       /* Avoid having a negative value for speed */
+       if (speed < 2)
+               speed = 0;
+       else
+               speed -= 2;
+
+       /* Avoid speed overflow */
+       if (speed > 15)
+               return 15;
+
+       return (u16)speed;
+}
+
+static void set_res(struct v4l2_subdev *sd)
+{
+       struct mt9v011 *core = to_mt9v011(sd);
+       unsigned vstart, hstart;
+
+       /*
+        * The mt9v011 doesn't have scaling. So, in order to select the desired
+        * resolution, we're cropping at the middle of the sensor.
+        * hblank and vblank should be adjusted, in order to warrant that
+        * we'll preserve the line timings for 30 fps, no matter what resolution
+        * is selected.
+        * NOTE: datasheet says that width (and height) should be filled with
+        * width-1. However, this doesn't work, since one pixel per line will
+        * be missing.
+        */
+
+       hstart = 14 + (640 - core->width) / 2;
+       mt9v011_write(sd, R02_MT9V011_COLSTART, hstart);
+       mt9v011_write(sd, R04_MT9V011_WIDTH, core->width);
+       mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width);
+
+       vstart = 8 + (480 - core->height) / 2;
+       mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart);
+       mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height);
+       mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height);
+
+       calc_fps(sd, NULL, NULL);
+};
+
+static void set_read_mode(struct v4l2_subdev *sd)
+{
+       struct mt9v011 *core = to_mt9v011(sd);
+       unsigned mode = 0x1000;
+
+       if (core->hflip)
+               mode |= 0x4000;
+
+       if (core->vflip)
+               mode |= 0x8000;
+
+       mt9v011_write(sd, R20_MT9V011_READ_MODE, mode);
+}
+
+static int mt9v011_reset(struct v4l2_subdev *sd, u32 val)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(mt9v011_init_default); i++)
+               mt9v011_write(sd, mt9v011_init_default[i].reg,
+                              mt9v011_init_default[i].value);
+
+       set_balance(sd);
+       set_res(sd);
+       set_read_mode(sd);
+
+       return 0;
+};
+
+static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+       struct mt9v011 *core = to_mt9v011(sd);
+
+       v4l2_dbg(1, debug, sd, "g_ctrl called\n");
+
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+               ctrl->value = core->global_gain;
+               return 0;
+       case V4L2_CID_RED_BALANCE:
+               ctrl->value = core->red_bal;
+               return 0;
+       case V4L2_CID_BLUE_BALANCE:
+               ctrl->value = core->blue_bal;
+               return 0;
+       case V4L2_CID_HFLIP:
+               ctrl->value = core->hflip ? 1 : 0;
+               return 0;
+       case V4L2_CID_VFLIP:
+               ctrl->value = core->vflip ? 1 : 0;
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int mt9v011_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+       int i;
+
+       v4l2_dbg(1, debug, sd, "queryctrl called\n");
+
+       for (i = 0; i < ARRAY_SIZE(mt9v011_qctrl); i++)
+               if (qc->id && qc->id == mt9v011_qctrl[i].id) {
+                       memcpy(qc, &(mt9v011_qctrl[i]),
+                              sizeof(*qc));
+                       return 0;
+               }
+
+       return -EINVAL;
+}
+
+
+static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+       struct mt9v011 *core = to_mt9v011(sd);
+       u8 i, n;
+       n = ARRAY_SIZE(mt9v011_qctrl);
+
+       for (i = 0; i < n; i++) {
+               if (ctrl->id != mt9v011_qctrl[i].id)
+                       continue;
+               if (ctrl->value < mt9v011_qctrl[i].minimum ||
+                   ctrl->value > mt9v011_qctrl[i].maximum)
+                       return -ERANGE;
+               v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n",
+                                       ctrl->id, ctrl->value);
+               break;
+       }
+
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+               core->global_gain = ctrl->value;
+               break;
+       case V4L2_CID_RED_BALANCE:
+               core->red_bal = ctrl->value;
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               core->blue_bal = ctrl->value;
+               break;
+       case V4L2_CID_HFLIP:
+               core->hflip = ctrl->value;
+               set_read_mode(sd);
+               return 0;
+       case V4L2_CID_VFLIP:
+               core->vflip = ctrl->value;
+               set_read_mode(sd);
+               return 0;
+       default:
+               return -EINVAL;
+       }
+
+       set_balance(sd);
+
+       return 0;
+}
+
+static int mt9v011_enum_fmt(struct v4l2_subdev *sd, struct v4l2_fmtdesc *fmt)
+{
+       if (fmt->index > 0)
+               return -EINVAL;
+
+       fmt->flags = 0;
+       strcpy(fmt->description, "8 bpp Bayer GRGR..BGBG");
+       fmt->pixelformat = V4L2_PIX_FMT_SGRBG8;
+
+       return 0;
+}
+
+static int mt9v011_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+       struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+       if (pix->pixelformat != V4L2_PIX_FMT_SGRBG8)
+               return -EINVAL;
+
+       v4l_bound_align_image(&pix->width, 48, 639, 1,
+                             &pix->height, 32, 480, 1, 0);
+
+       return 0;
+}
+
+static int mt9v011_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+       struct v4l2_captureparm *cp = &parms->parm.capture;
+
+       if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       memset(cp, 0, sizeof(struct v4l2_captureparm));
+       cp->capability = V4L2_CAP_TIMEPERFRAME;
+       calc_fps(sd,
+                &cp->timeperframe.numerator,
+                &cp->timeperframe.denominator);
+
+       return 0;
+}
+
+static int mt9v011_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+       struct v4l2_captureparm *cp = &parms->parm.capture;
+       struct v4l2_fract *tpf = &cp->timeperframe;
+       u16 speed;
+
+       if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (cp->extendedmode != 0)
+               return -EINVAL;
+
+       speed = calc_speed(sd, tpf->numerator, tpf->denominator);
+
+       mt9v011_write(sd, R0A_MT9V011_CLK_SPEED, speed);
+       v4l2_dbg(1, debug, sd, "Setting speed to %d\n", speed);
+
+       /* Recalculate and update fps info */
+       calc_fps(sd, &tpf->numerator, &tpf->denominator);
+
+       return 0;
+}
+
+static int mt9v011_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
+{
+       struct v4l2_pix_format *pix = &fmt->fmt.pix;
+       struct mt9v011 *core = to_mt9v011(sd);
+       int rc;
+
+       rc = mt9v011_try_fmt(sd, fmt);
+       if (rc < 0)
+               return -EINVAL;
+
+       core->width = pix->width;
+       core->height = pix->height;
+
+       set_res(sd);
+
+       return 0;
+}
+
+static int mt9v011_s_config(struct v4l2_subdev *sd, int dumb, void *data)
+{
+       struct mt9v011 *core = to_mt9v011(sd);
+       unsigned *xtal = data;
+
+       v4l2_dbg(1, debug, sd, "s_config called\n");
+
+       if (xtal) {
+               core->xtal = *xtal;
+               v4l2_dbg(1, debug, sd, "xtal set to %d.%03d MHz\n",
+                        *xtal / 1000000, (*xtal / 1000) % 1000);
+       }
+
+       return 0;
+}
+
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9v011_g_register(struct v4l2_subdev *sd,
+                             struct v4l2_dbg_register *reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
+               return -EINVAL;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       reg->val = mt9v011_read(sd, reg->reg & 0xff);
+       reg->size = 2;
+
+       return 0;
+}
+
+static int mt9v011_s_register(struct v4l2_subdev *sd,
+                             struct v4l2_dbg_register *reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
+               return -EINVAL;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff);
+
+       return 0;
+}
+#endif
+
+static int mt9v011_g_chip_ident(struct v4l2_subdev *sd,
+                               struct v4l2_dbg_chip_ident *chip)
+{
+       u16 version;
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION);
+
+       return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_MT9V011,
+                                         version);
+}
+
+static const struct v4l2_subdev_core_ops mt9v011_core_ops = {
+       .queryctrl = mt9v011_queryctrl,
+       .g_ctrl = mt9v011_g_ctrl,
+       .s_ctrl = mt9v011_s_ctrl,
+       .reset = mt9v011_reset,
+       .s_config = mt9v011_s_config,
+       .g_chip_ident = mt9v011_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .g_register = mt9v011_g_register,
+       .s_register = mt9v011_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_video_ops mt9v011_video_ops = {
+       .enum_fmt = mt9v011_enum_fmt,
+       .try_fmt = mt9v011_try_fmt,
+       .s_fmt = mt9v011_s_fmt,
+       .g_parm = mt9v011_g_parm,
+       .s_parm = mt9v011_s_parm,
+};
+
+static const struct v4l2_subdev_ops mt9v011_ops = {
+       .core  = &mt9v011_core_ops,
+       .video = &mt9v011_video_ops,
+};
+
+
+/****************************************************************************
+                       I2C Client & Driver
+ ****************************************************************************/
+
+static int mt9v011_probe(struct i2c_client *c,
+                        const struct i2c_device_id *id)
+{
+       u16 version;
+       struct mt9v011 *core;
+       struct v4l2_subdev *sd;
+
+       /* Check if the adapter supports the needed features */
+       if (!i2c_check_functionality(c->adapter,
+            I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+               return -EIO;
+
+       core = kzalloc(sizeof(struct mt9v011), GFP_KERNEL);
+       if (!core)
+               return -ENOMEM;
+
+       sd = &core->sd;
+       v4l2_i2c_subdev_init(sd, c, &mt9v011_ops);
+
+       /* Check if the sensor is really a MT9V011 */
+       version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION);
+       if ((version != MT9V011_VERSION) &&
+           (version != MT9V011_REV_B_VERSION)) {
+               v4l2_info(sd, "*** unknown micron chip detected (0x%04x).\n",
+                         version);
+               kfree(core);
+               return -EINVAL;
+       }
+
+       core->global_gain = 0x0024;
+       core->width  = 640;
+       core->height = 480;
+       core->xtal = 27000000;  /* Hz */
+
+       v4l_info(c, "chip found @ 0x%02x (%s - chip version 0x%04x)\n",
+                c->addr << 1, c->adapter->name, version);
+
+       return 0;
+}
+
+static int mt9v011_remove(struct i2c_client *c)
+{
+       struct v4l2_subdev *sd = i2c_get_clientdata(c);
+
+       v4l2_dbg(1, debug, sd,
+               "mt9v011.c: removing mt9v011 adapter on address 0x%x\n",
+               c->addr << 1);
+
+       v4l2_device_unregister_subdev(sd);
+       kfree(to_mt9v011(sd));
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id mt9v011_id[] = {
+       { "mt9v011", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, mt9v011_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+       .name = "mt9v011",
+       .probe = mt9v011_probe,
+       .remove = mt9v011_remove,
+       .id_table = mt9v011_id,
+};
diff --git a/drivers/media/video/mt9v011.h b/drivers/media/video/mt9v011.h
new file mode 100644 (file)
index 0000000..3350fd6
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor
+ *
+ * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com)
+ * This code is placed under the terms of the GNU General Public License v2
+ */
+
+#ifndef MT9V011_H_
+#define MT9V011_H_
+
+#define R00_MT9V011_CHIP_VERSION       0x00
+#define R01_MT9V011_ROWSTART           0x01
+#define R02_MT9V011_COLSTART           0x02
+#define R03_MT9V011_HEIGHT             0x03
+#define R04_MT9V011_WIDTH              0x04
+#define R05_MT9V011_HBLANK             0x05
+#define R06_MT9V011_VBLANK             0x06
+#define R07_MT9V011_OUT_CTRL           0x07
+#define R09_MT9V011_SHUTTER_WIDTH      0x09
+#define R0A_MT9V011_CLK_SPEED          0x0a
+#define R0B_MT9V011_RESTART            0x0b
+#define R0C_MT9V011_SHUTTER_DELAY      0x0c
+#define R0D_MT9V011_RESET              0x0d
+#define R1E_MT9V011_DIGITAL_ZOOM       0x1e
+#define R20_MT9V011_READ_MODE          0x20
+#define R2B_MT9V011_GREEN_1_GAIN       0x2b
+#define R2C_MT9V011_BLUE_GAIN          0x2c
+#define R2D_MT9V011_RED_GAIN           0x2d
+#define R2E_MT9V011_GREEN_2_GAIN       0x2e
+#define R35_MT9V011_GLOBAL_GAIN                0x35
+#define RF1_MT9V011_CHIP_ENABLE                0xf1
+
+#define MT9V011_VERSION                        0x8232
+#define MT9V011_REV_B_VERSION          0x8243
+
+#endif
index 2d075205bdfe4b724e22882aa5e6a636edf81cef..736c31d23194525b233966c848ab7cae772c8dc9 100644 (file)
@@ -234,6 +234,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev)
        return ret;
 }
 
+/* Called under spinlock_irqsave(&pcdev->lock, ...) */
 static void mx1_videobuf_queue(struct videobuf_queue *vq,
                                                struct videobuf_buffer *vb)
 {
@@ -241,13 +242,10 @@ static void mx1_videobuf_queue(struct videobuf_queue *vq,
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
        struct mx1_camera_dev *pcdev = ici->priv;
        struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb);
-       unsigned long flags;
 
        dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
                vb, vb->baddr, vb->bsize);
 
-       spin_lock_irqsave(&pcdev->lock, flags);
-
        list_add_tail(&vb->queue, &pcdev->capture);
 
        vb->state = VIDEOBUF_ACTIVE;
@@ -264,8 +262,6 @@ static void mx1_videobuf_queue(struct videobuf_queue *vq,
                        __raw_writel(temp, pcdev->base + CSICR1);
                }
        }
-
-       spin_unlock_irqrestore(&pcdev->lock, flags);
 }
 
 static void mx1_videobuf_release(struct videobuf_queue *vq,
index e605c076ed89d43ae5533e98d5d4dc60009dfd19..9770cb7932caeb07fcb36be6568cac021d405094 100644 (file)
@@ -332,7 +332,10 @@ static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc)
        }
 }
 
-/* Called with .vb_lock held */
+/*
+ * Called with .vb_lock mutex held and
+ * under spinlock_irqsave(&mx3_cam->lock, ...)
+ */
 static void mx3_videobuf_queue(struct videobuf_queue *vq,
                               struct videobuf_buffer *vb)
 {
@@ -346,7 +349,8 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq,
        struct idmac_video_param *video = &ichan->params.video;
        const struct soc_camera_data_format *data_fmt = icd->current_fmt;
        dma_cookie_t cookie;
-       unsigned long flags;
+
+       BUG_ON(!irqs_disabled());
 
        /* This is the configuration of one sg-element */
        video->out_pixel_fmt    = fourcc_to_ipu_pix(data_fmt->fourcc);
@@ -359,8 +363,6 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq,
        memset((void *)vb->baddr, 0xaa, vb->bsize);
 #endif
 
-       spin_lock_irqsave(&mx3_cam->lock, flags);
-
        list_add_tail(&vb->queue, &mx3_cam->capture);
 
        if (!mx3_cam->active) {
@@ -370,24 +372,23 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq,
                vb->state = VIDEOBUF_QUEUED;
        }
 
-       spin_unlock_irqrestore(&mx3_cam->lock, flags);
+       spin_unlock_irq(&mx3_cam->lock);
 
        cookie = txd->tx_submit(txd);
        dev_dbg(&icd->dev, "Submitted cookie %d DMA 0x%08x\n", cookie, sg_dma_address(&buf->sg));
+
+       spin_lock_irq(&mx3_cam->lock);
+
        if (cookie >= 0)
                return;
 
        /* Submit error */
        vb->state = VIDEOBUF_PREPARED;
 
-       spin_lock_irqsave(&mx3_cam->lock, flags);
-
        list_del_init(&vb->queue);
 
        if (mx3_cam->active == buf)
                mx3_cam->active = NULL;
-
-       spin_unlock_irqrestore(&mx3_cam->lock, flags);
 }
 
 /* Called with .vb_lock held */
index db25c3034c11be4e7deb4cc98bf41006b4e860f7..8d17cf61330671f1d71c94dfc82a689f7b0bbf69 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
 #include <linux/usb/input.h>
 #endif
index 0be6f814f5396cb7615484201db3a45a46f98ac5..0b658dee05a41f047fa55f171c4972fc5b140aa3 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/usb.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
-#include <linux/smp_lock.h>
 #include <linux/version.h>
 #include <linux/mutex.h>
 #include <linux/mm.h>
index 46e0d8ad880fc58e56a3928347e52907f6e70cb7..016bb45ba0c3e2f48e1801651c04dab25c262b74 100644 (file)
@@ -612,6 +612,7 @@ static void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev)
        dev_dbg(pcdev->soc_host.dev, "%s\n", __func__);
 }
 
+/* Called under spinlock_irqsave(&pcdev->lock, ...) */
 static void pxa_videobuf_queue(struct videobuf_queue *vq,
                               struct videobuf_buffer *vb)
 {
@@ -619,13 +620,10 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq,
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
        struct pxa_camera_dev *pcdev = ici->priv;
        struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb);
-       unsigned long flags;
 
        dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d active=%p\n", __func__,
                vb, vb->baddr, vb->bsize, pcdev->active);
 
-       spin_lock_irqsave(&pcdev->lock, flags);
-
        list_add_tail(&vb->queue, &pcdev->capture);
 
        vb->state = VIDEOBUF_ACTIVE;
@@ -633,8 +631,6 @@ static void pxa_videobuf_queue(struct videobuf_queue *vq,
 
        if (!pcdev->active)
                pxa_camera_start_capture(pcdev);
-
-       spin_unlock_irqrestore(&pcdev->lock, flags);
 }
 
 static void pxa_videobuf_release(struct videobuf_queue *vq,
@@ -1579,6 +1575,7 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev)
                pcdev->mclk = 20000000;
        }
 
+       pcdev->soc_host.dev = &pdev->dev;
        pcdev->mclk_divisor = mclk_get_divisor(pcdev);
 
        INIT_LIST_HEAD(&pcdev->capture);
@@ -1644,7 +1641,6 @@ static int __devinit pxa_camera_probe(struct platform_device *pdev)
        pcdev->soc_host.drv_name        = PXA_CAM_DRV_NAME;
        pcdev->soc_host.ops             = &pxa_soc_camera_host_ops;
        pcdev->soc_host.priv            = pcdev;
-       pcdev->soc_host.dev             = &pdev->dev;
        pcdev->soc_host.nr              = pdev->id;
 
        err = soc_camera_host_register(&pcdev->soc_host);
index 6be845ccc7d7e7412f97b2e65c32e6cd3deb091e..9e3262c0ba371b1c935100504b8e6444964f7d51 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/videodev2.h>
 #include <linux/version.h>
 #include <linux/mm.h>
+#include <linux/smp_lock.h>
 #include <media/videobuf-vmalloc.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
index 155804b061e948b091b997242dec8ab8c1edd5c1..b624a4c01fdc9faee6e2fe37ad0939da9fdbfee2 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/videotext.h>
 #include <linux/videodev2.h>
index 271d6e931b750ecd9b7c0ee4a499f52a3833476f..12835fb82c9557c56d09d16825d954dd0d24920e 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/videotext.h>
index 06861b782b9529f503ac26102eb17fc2ddd68908..6eebe3ef97d37efa9f8375eafa53e6b75420f79a 100644 (file)
@@ -3331,8 +3331,8 @@ struct saa7134_board saa7134_boards[] = {
                        .gpio = 0x0200100,
                },
        },
-       [SAA7134_BOARD_HAUPPAUGE_HVR1120] = {
-               .name           = "Hauppauge WinTV-HVR1120 ATSC/QAM-Hybrid",
+       [SAA7134_BOARD_HAUPPAUGE_HVR1150] = {
+               .name           = "Hauppauge WinTV-HVR1150 ATSC/QAM-Hybrid",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_TDA8290,
                .radio_type     = UNSET,
@@ -3363,8 +3363,8 @@ struct saa7134_board saa7134_boards[] = {
                        .gpio = 0x0800100, /* GPIO 23 HI for FM */
                },
        },
-       [SAA7134_BOARD_HAUPPAUGE_HVR1110R3] = {
-               .name           = "Hauppauge WinTV-HVR1110r3 DVB-T/Hybrid",
+       [SAA7134_BOARD_HAUPPAUGE_HVR1120] = {
+               .name           = "Hauppauge WinTV-HVR1120 DVB-T/Hybrid",
                .audio_clock    = 0x00187de7,
                .tuner_type     = TUNER_PHILIPS_TDA8290,
                .radio_type     = UNSET,
@@ -5862,31 +5862,31 @@ struct pci_device_id saa7134_pci_tbl[] = {
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
                .subvendor    = 0x0070,
                .subdevice    = 0x6706,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1150,
        },{
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
                .subvendor    = 0x0070,
                .subdevice    = 0x6707,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110R3,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
        },{
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
                .subvendor    = 0x0070,
                .subdevice    = 0x6708,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1150,
        },{
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
                .subvendor    = 0x0070,
                .subdevice    = 0x6709,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110R3,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
        },{
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
                .subvendor    = 0x0070,
                .subdevice    = 0x670a,
-               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110R3,
+               .driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
        },{
                .vendor       = PCI_VENDOR_ID_PHILIPS,
                .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
@@ -6363,8 +6363,8 @@ static int saa7134_tda8290_18271_callback(struct saa7134_dev *dev,
        switch (command) {
        case TDA18271_CALLBACK_CMD_AGC_ENABLE: /* 0 */
                switch (dev->board) {
+               case SAA7134_BOARD_HAUPPAUGE_HVR1150:
                case SAA7134_BOARD_HAUPPAUGE_HVR1120:
-               case SAA7134_BOARD_HAUPPAUGE_HVR1110R3:
                        ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg);
                        break;
                default:
@@ -6384,8 +6384,8 @@ static int saa7134_tda8290_callback(struct saa7134_dev *dev,
        int ret;
 
        switch (dev->board) {
+       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
        case SAA7134_BOARD_HAUPPAUGE_HVR1120:
-       case SAA7134_BOARD_HAUPPAUGE_HVR1110R3:
                /* tda8290 + tda18271 */
                ret = saa7134_tda8290_18271_callback(dev, command, arg);
                break;
@@ -6427,7 +6427,7 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data)
        switch (tv.model) {
        case 67019: /* WinTV-HVR1110 (Retail, IR Blaster, hybrid, FM, SVid/Comp, 3.5mm audio in) */
        case 67109: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */
-       case 67201: /* WinTV-HVR1120 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */
+       case 67201: /* WinTV-HVR1150 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */
        case 67301: /* WinTV-HVR1000 (Retail, IR Receive, analog, no FM, SVid/Comp, 3.5mm audio in) */
        case 67209: /* WinTV-HVR1110 (Retail, IR Receive, hybrid, FM, SVid/Comp, 3.5mm audio in) */
        case 67559: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
@@ -6435,7 +6435,7 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data)
        case 67579: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM) */
        case 67589: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */
        case 67599: /* WinTV-HVR1110 (OEM, no IR, hybrid, no FM, SVid/Comp, RCA aud) */
-       case 67651: /* WinTV-HVR1120 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
+       case 67651: /* WinTV-HVR1150 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
        case 67659: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
                break;
        default:
@@ -6625,8 +6625,8 @@ int saa7134_board_init1(struct saa7134_dev *dev)
 
                saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00);
                break;
+       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
        case SAA7134_BOARD_HAUPPAUGE_HVR1120:
-       case SAA7134_BOARD_HAUPPAUGE_HVR1110R3:
                /* GPIO 26 high for digital, low for analog */
                saa7134_set_gpio(dev, 26, 0);
                msleep(1);
@@ -6891,8 +6891,8 @@ int saa7134_board_init2(struct saa7134_dev *dev)
                       dev->name, saa7134_boards[dev->board].name);
               }
               break;
+       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
        case SAA7134_BOARD_HAUPPAUGE_HVR1120:
-       case SAA7134_BOARD_HAUPPAUGE_HVR1110R3:
                hauppauge_eeprom(dev, dev->eedata+0x80);
                break;
        case SAA7134_BOARD_HAUPPAUGE_HVR1110:
index 31930f26ffc7d5963aab8d24c7b3a70c918a62e3..98f3efd1e944defe96509f6b6dcb8b79ef00a47c 100644 (file)
@@ -1119,7 +1119,7 @@ static int dvb_init(struct saa7134_dev *dev)
                                         &tda827x_cfg_2) < 0)
                        goto dettach_frontend;
                break;
-       case SAA7134_BOARD_HAUPPAUGE_HVR1110R3:
+       case SAA7134_BOARD_HAUPPAUGE_HVR1120:
                fe0->dvb.frontend = dvb_attach(tda10048_attach,
                                               &hcw_tda10048_config,
                                               &dev->i2c_adap);
@@ -1147,7 +1147,7 @@ static int dvb_init(struct saa7134_dev *dev)
                                         &tda827x_cfg_1) < 0)
                        goto dettach_frontend;
                break;
-       case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+       case SAA7134_BOARD_HAUPPAUGE_HVR1150:
                fe0->dvb.frontend = dvb_attach(lgdt3305_attach,
                                               &hcw_lgdt3305_config,
                                               &dev->i2c_adap);
index add1757f89303851afa45f49d5c6975641efde9b..296788c3bf0ecc6ddc14301fb10bf198216e155a 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/delay.h>
 
 #include "saa7134-reg.h"
index 82268848f26a4cc8817e17f7a6c5a4281a6952d4..fb564f14887cc0e814f0adcb29a738595cea937c 100644 (file)
@@ -278,8 +278,8 @@ struct saa7134_format {
 #define SAA7134_BOARD_ASUSTeK_TIGER         152
 #define SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG 153
 #define SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS 154
-#define SAA7134_BOARD_HAUPPAUGE_HVR1120     155
-#define SAA7134_BOARD_HAUPPAUGE_HVR1110R3   156
+#define SAA7134_BOARD_HAUPPAUGE_HVR1150     155
+#define SAA7134_BOARD_HAUPPAUGE_HVR1120   156
 #define SAA7134_BOARD_AVERMEDIA_STUDIO_507UA 157
 #define SAA7134_BOARD_AVERMEDIA_CARDBUS_501 158
 #define SAA7134_BOARD_BEHOLD_505RDS         159
index c8f05297d0f0680acccc7513231a5e561c57b3db..85ffc2cba039b3e6114e5fc8d3bd4671bf9fea20 100644 (file)
@@ -31,6 +31,7 @@ static const char version[] = "0.24";
 #include <linux/init.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/usb.h>
 #include "se401.h"
index 0db88a53d92c54c60830862c6867d4dbe175bdcb..e86878deea71771d16decce32551f8ae78cfe88b 100644 (file)
@@ -282,27 +282,24 @@ out:
        return ret;
 }
 
+/* Called under spinlock_irqsave(&pcdev->lock, ...) */
 static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq,
                                         struct videobuf_buffer *vb)
 {
        struct soc_camera_device *icd = vq->priv_data;
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
-       unsigned long flags;
 
        dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
                vb, vb->baddr, vb->bsize);
 
        vb->state = VIDEOBUF_QUEUED;
-       spin_lock_irqsave(&pcdev->lock, flags);
        list_add_tail(&vb->queue, &pcdev->capture);
 
        if (!pcdev->active) {
                pcdev->active = vb;
                sh_mobile_ceu_capture(pcdev);
        }
-
-       spin_unlock_irqrestore(&pcdev->lock, flags);
 }
 
 static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq,
index 16f595d4337abfb76b3c08d98bad1ced20cf0b9d..9f5ae81678553192b27ec5b41d384a858d603b40 100644 (file)
@@ -237,11 +237,11 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
                return -ENOMEM;
 
        icd->num_user_formats = fmts;
-       fmts = 0;
 
        dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts);
 
        /* Second pass - actually fill data formats */
+       fmts = 0;
        for (i = 0; i < icd->num_formats; i++)
                if (!ici->ops->get_formats) {
                        icd->user_formats[i].host_fmt = icd->formats + i;
@@ -877,8 +877,11 @@ static int soc_camera_probe(struct device *dev)
                        (unsigned short)~0;
 
                ret = soc_camera_init_user_formats(icd);
-               if (ret < 0)
+               if (ret < 0) {
+                       if (icd->ops->remove)
+                               icd->ops->remove(icd);
                        goto eiufmt;
+               }
 
                icd->height     = DEFAULT_HEIGHT;
                icd->width      = DEFAULT_WIDTH;
@@ -902,8 +905,10 @@ static int soc_camera_remove(struct device *dev)
 {
        struct soc_camera_device *icd = to_soc_camera_dev(dev);
 
+       mutex_lock(&icd->video_lock);
        if (icd->ops->remove)
                icd->ops->remove(icd);
+       mutex_unlock(&icd->video_lock);
 
        soc_camera_free_user_formats(icd);
 
@@ -1145,6 +1150,7 @@ evidallocd:
 }
 EXPORT_SYMBOL(soc_camera_video_start);
 
+/* Called from client .remove() methods with .video_lock held */
 void soc_camera_video_stop(struct soc_camera_device *icd)
 {
        struct video_device *vdev = icd->vdev;
@@ -1154,10 +1160,8 @@ void soc_camera_video_stop(struct soc_camera_device *icd)
        if (!icd->dev.parent || !vdev)
                return;
 
-       mutex_lock(&icd->video_lock);
        video_unregister_device(vdev);
        icd->vdev = NULL;
-       mutex_unlock(&icd->video_lock);
 }
 EXPORT_SYMBOL(soc_camera_video_stop);
 
index 2e59370472788712ba3e08ae62dd2b5f2b62f2e0..b154bd961e3b74472d7efccf367c8447004d0f84 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 
 #include <linux/usb.h>
 #include <linux/mm.h>
@@ -1049,8 +1050,8 @@ static int stk_setup_format(struct stk_camera *dev)
                depth = 1;
        else
                depth = 2;
-       while (stk_sizes[i].m != dev->vsettings.mode
-                       && i < ARRAY_SIZE(stk_sizes))
+       while (i < ARRAY_SIZE(stk_sizes) &&
+                       stk_sizes[i].m != dev->vsettings.mode)
                i++;
        if (i == ARRAY_SIZE(stk_sizes)) {
                STK_ERROR("Something is broken in %s\n", __func__);
index 0eb313082c973e78fcfe6e2e935ec1c5751ce5c6..eaada39c76fdfcf5d2273bd3c31af6dca0350da1 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/poll.h>
index 75f286f7a2e9939cfc9d24f25a06d6b50c8cab91..8b4e7dafce7b9d155c254a802282daa0f25f1570 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/init.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/errno.h>
 #include <linux/videodev.h>
index 8d73979596f9d9542c35e10aa158d6792878099a..45fce39ec9ad56b77c5b7db00eca8dccf3d5a0f3 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/firmware.h>
 #include <linux/ihex.h>
index 90b58914f98472644e289c97ce02297490c920d2..90d9b5c0e9a7bc407806e357a32988ed61df5b0e 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/utsname.h>
 #include <linux/highmem.h>
index 89927b7aec28dce2dcd9131b7e36339de826436d..04b47832fa0a5d1d416cdf429cf9e320a69fc59f 100644 (file)
@@ -1845,11 +1845,29 @@ static struct usb_device_id uvc_ids[] = {
          .bInterfaceSubClass   = 1,
          .bInterfaceProtocol   = 0,
          .driver_info          = UVC_QUIRK_STREAM_NO_FID },
-       /* ViMicro */
-       { .match_flags          = USB_DEVICE_ID_MATCH_VENDOR
+       /* ViMicro Vega */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x0ac8,
+         .idProduct            = 0x332d,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_FIX_BANDWIDTH },
+       /* ViMicro - Minoru3D */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x0ac8,
+         .idProduct            = 0x3410,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_FIX_BANDWIDTH },
+       /* ViMicro Venus - Minoru3D */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
                                | USB_DEVICE_ID_MATCH_INT_INFO,
          .idVendor             = 0x0ac8,
-         .idProduct            = 0x0000,
+         .idProduct            = 0x3420,
          .bInterfaceClass      = USB_CLASS_VIDEO,
          .bInterfaceSubClass   = 1,
          .bInterfaceProtocol   = 0,
index f152a9903862abe4780eebe67ba282f2bf6d9eac..1ca6dff7361241069f2a05ba4631bb00ec5b11d5 100644 (file)
@@ -145,8 +145,8 @@ static void uvc_status_complete(struct urb *urb)
                        break;
 
                default:
-                       uvc_printk(KERN_INFO, "unknown event type %u.\n",
-                               dev->status[0]);
+                       uvc_trace(UVC_TRACE_STATUS, "Unknown status event "
+                               "type %u.\n", dev->status[0]);
                        break;
                }
        }
index 31eac66411d736e4330119900e111aa921e841e4..a7f1b69a7dab398522ea9ca994c998be82719063 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/init.h>
 #include <linux/kmod.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
index be64a502ea276e5a49ee3c97bea6d3f9a52a2fec..f2afc4e08379a1cee0c77201190dd698db576fbb 100644 (file)
@@ -1081,8 +1081,10 @@ static long __video_do_ioctl(struct file *file,
                /* Calls the specific handler */
                if (ops->vidioc_g_std)
                        ret = ops->vidioc_g_std(file, fh, id);
-               else
+               else if (vfd->current_norm)
                        *id = vfd->current_norm;
+               else
+                       ret = -EINVAL;
 
                if (!ret)
                        dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
@@ -1553,12 +1555,19 @@ static long __video_do_ioctl(struct file *file,
                                break;
                        ret = ops->vidioc_g_parm(file, fh, p);
                } else {
+                       v4l2_std_id std = vfd->current_norm;
+
                        if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                                return -EINVAL;
 
-                       v4l2_video_std_frame_period(vfd->current_norm,
-                                                   &p->parm.capture.timeperframe);
                        ret = 0;
+                       if (ops->vidioc_g_std)
+                               ret = ops->vidioc_g_std(file, fh, &std);
+                       else if (std == 0)
+                               ret = -EINVAL;
+                       if (ret == 0)
+                               v4l2_video_std_frame_period(std,
+                                                   &p->parm.capture.timeperframe);
                }
 
                dbgarg(cmd, "type=%d\n", p->type);
index cd72668584626974a4c59b2bc0c739c09d2a3360..7705fc6baf00d6eab93fbf43eb17bfb9febece0a 100644 (file)
@@ -343,6 +343,53 @@ static struct bar_std bars[] = {
 #define TO_U(r, g, b) \
        (((-9714 * r - 19070 * g + 28784 * b + 32768) >> 16) + 128)
 
+/* precalculate color bar values to speed up rendering */
+static void precalculate_bars(struct vivi_fh *fh)
+{
+       struct vivi_dev *dev = fh->dev;
+       unsigned char r, g, b;
+       int k, is_yuv;
+
+       fh->input = dev->input;
+
+       for (k = 0; k < 8; k++) {
+               r = bars[fh->input].bar[k][0];
+               g = bars[fh->input].bar[k][1];
+               b = bars[fh->input].bar[k][2];
+               is_yuv = 0;
+
+               switch (fh->fmt->fourcc) {
+               case V4L2_PIX_FMT_YUYV:
+               case V4L2_PIX_FMT_UYVY:
+                       is_yuv = 1;
+                       break;
+               case V4L2_PIX_FMT_RGB565:
+               case V4L2_PIX_FMT_RGB565X:
+                       r >>= 3;
+                       g >>= 2;
+                       b >>= 3;
+                       break;
+               case V4L2_PIX_FMT_RGB555:
+               case V4L2_PIX_FMT_RGB555X:
+                       r >>= 3;
+                       g >>= 3;
+                       b >>= 3;
+                       break;
+               }
+
+               if (is_yuv) {
+                       fh->bars[k][0] = TO_Y(r, g, b); /* Luma */
+                       fh->bars[k][1] = TO_U(r, g, b); /* Cb */
+                       fh->bars[k][2] = TO_V(r, g, b); /* Cr */
+               } else {
+                       fh->bars[k][0] = r;
+                       fh->bars[k][1] = g;
+                       fh->bars[k][2] = b;
+               }
+       }
+
+}
+
 #define TSTAMP_MIN_Y   24
 #define TSTAMP_MAX_Y   (TSTAMP_MIN_Y + 15)
 #define TSTAMP_INPUT_X 10
@@ -755,6 +802,8 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
        buf->vb.height = fh->height;
        buf->vb.field  = field;
 
+       precalculate_bars(fh);
+
        if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
                rc = videobuf_iolock(vq, &buf->vb, NULL);
                if (rc < 0)
@@ -893,53 +942,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
        return 0;
 }
 
-/* precalculate color bar values to speed up rendering */
-static void precalculate_bars(struct vivi_fh *fh)
-{
-       struct vivi_dev *dev = fh->dev;
-       unsigned char r, g, b;
-       int k, is_yuv;
-
-       fh->input = dev->input;
-
-       for (k = 0; k < 8; k++) {
-               r = bars[fh->input].bar[k][0];
-               g = bars[fh->input].bar[k][1];
-               b = bars[fh->input].bar[k][2];
-               is_yuv = 0;
-
-               switch (fh->fmt->fourcc) {
-               case V4L2_PIX_FMT_YUYV:
-               case V4L2_PIX_FMT_UYVY:
-                       is_yuv = 1;
-                       break;
-               case V4L2_PIX_FMT_RGB565:
-               case V4L2_PIX_FMT_RGB565X:
-                       r >>= 3;
-                       g >>= 2;
-                       b >>= 3;
-                       break;
-               case V4L2_PIX_FMT_RGB555:
-               case V4L2_PIX_FMT_RGB555X:
-                       r >>= 3;
-                       g >>= 3;
-                       b >>= 3;
-                       break;
-               }
-
-               if (is_yuv) {
-                       fh->bars[k][0] = TO_Y(r, g, b); /* Luma */
-                       fh->bars[k][1] = TO_U(r, g, b); /* Cb */
-                       fh->bars[k][2] = TO_V(r, g, b); /* Cr */
-               } else {
-                       fh->bars[k][0] = r;
-                       fh->bars[k][1] = g;
-                       fh->bars[k][2] = b;
-               }
-       }
-
-}
-
 /*FIXME: This seems to be generic enough to be at videodev2 */
 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
                                        struct v4l2_format *f)
@@ -965,8 +967,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        fh->vb_vidq.field = f->fmt.pix.field;
        fh->type          = f->type;
 
-       precalculate_bars(fh);
-
        ret = 0;
 out:
        mutex_unlock(&q->vb_lock);
@@ -1357,6 +1357,7 @@ static int __init vivi_create_instance(int inst)
                goto unreg_dev;
 
        *vfd = vivi_template;
+       vfd->debug = debug;
 
        ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
        if (ret < 0)
index 3d7df32a3d8706d30ac56a88fcbc720e7a25a6d6..bcdefb1bcb3dc450a54b0c05fb9e58c7dd91c81b 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
index fc976f42f4328d70bbccb9a65a1d4bd0b5173cf5..2622a6e63da1ed78b1bcaae07b164a33d13c1e66 100644 (file)
@@ -695,7 +695,7 @@ static int zr364xx_release(struct file *file)
        for (i = 0; i < 2; i++) {
                err =
                    send_control_msg(udev, 1, init[cam->method][i].value,
-                                    0, init[i][cam->method].bytes,
+                                    0, init[cam->method][i].bytes,
                                     init[cam->method][i].size);
                if (err < 0) {
                        dev_err(&udev->dev, "error during release sequence\n");
index 7ac12cb0be4a70f8b2bc30279ff56964e030ae0d..5b6e58a3ba46c3934e5ef96bdfcc2479172c20d7 100644 (file)
@@ -32,8 +32,7 @@
  * This driver was tested with firmware revision A4.
  */
 
-#if defined(CONFIG_KEYBOARD_DM355EVM) \
-               || defined(CONFIG_KEYBOARD_DM355EVM_MODULE)
+#if defined(CONFIG_INPUT_DM355EVM) || defined(CONFIG_INPUT_DM355EVM_MODULE)
 #define msp_has_keyboard()     true
 #else
 #define msp_has_keyboard()     false
index 671a7efe86a8b8404ad1e31aa50959ba3167a8a5..c1de4afa89a62fc79055d0bdaa47ad2a31c2adf3 100644 (file)
@@ -238,8 +238,10 @@ static irqreturn_t pcap_adc_irq(int irq, void *_pcap)
        mutex_lock(&pcap->adc_mutex);
        req = pcap->adc_queue[pcap->adc_head];
 
-       if (WARN(!req, KERN_WARNING "adc irq without pending request\n"))
+       if (WARN(!req, KERN_WARNING "adc irq without pending request\n")) {
+               mutex_unlock(&pcap->adc_mutex);
                return IRQ_HANDLED;
+       }
 
        /* read requested channels results */
        ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp);
index 4c7b7962f6b8002b18ef57c0a6d4015bcf7c2fc1..0cc5eeff5ee8bf7cd5568eabfcc31e82b05675b3 100644 (file)
@@ -367,7 +367,8 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
                break;
 
        default:
-               return -1;
+               gate = -1;
+               goto already;
        }
 
        writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
index bae61b22501c2948e60a03cba0c07b4731b1254b..7d430835655faeee2a35e6cfd266fc6376cfc024 100644 (file)
@@ -180,14 +180,9 @@ static struct completion irq_event;
 static int twl4030_irq_thread(void *data)
 {
        long irq = (long)data;
-       struct irq_desc *desc = irq_to_desc(irq);
        static unsigned i2c_errors;
        static const unsigned max_i2c_errors = 100;
 
-       if (!desc) {
-               pr_err("twl4030: Invalid IRQ: %ld\n", irq);
-               return -EINVAL;
-       }
 
        current->flags |= PF_NOFREEZE;
 
@@ -240,7 +235,7 @@ static int twl4030_irq_thread(void *data)
                }
                local_irq_enable();
 
-               desc->chip->unmask(irq);
+               enable_irq(irq);
        }
 
        return 0;
@@ -255,25 +250,13 @@ static int twl4030_irq_thread(void *data)
  * thread.  All we do here is acknowledge and mask the interrupt and wakeup
  * the kernel thread.
  */
-static void handle_twl4030_pih(unsigned int irq, struct irq_desc *desc)
+static irqreturn_t handle_twl4030_pih(int irq, void *devid)
 {
        /* Acknowledge, clear *AND* mask the interrupt... */
-       desc->chip->ack(irq);
-       complete(&irq_event);
-}
-
-static struct task_struct *start_twl4030_irq_thread(long irq)
-{
-       struct task_struct *thread;
-
-       init_completion(&irq_event);
-       thread = kthread_run(twl4030_irq_thread, (void *)irq, "twl4030-irq");
-       if (!thread)
-               pr_err("twl4030: could not create irq %ld thread!\n", irq);
-
-       return thread;
+       disable_irq_nosync(irq);
+       complete(devid);
+       return IRQ_HANDLED;
 }
-
 /*----------------------------------------------------------------------*/
 
 /*
@@ -734,18 +717,28 @@ int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
        }
 
        /* install an irq handler to demultiplex the TWL4030 interrupt */
-       task = start_twl4030_irq_thread(irq_num);
-       if (!task) {
-               pr_err("twl4030: irq thread FAIL\n");
-               status = -ESRCH;
-               goto fail;
-       }
 
-       set_irq_data(irq_num, task);
-       set_irq_chained_handler(irq_num, handle_twl4030_pih);
 
-       return status;
+       init_completion(&irq_event);
 
+       status = request_irq(irq_num, handle_twl4030_pih, IRQF_DISABLED,
+                               "TWL4030-PIH", &irq_event);
+       if (status < 0) {
+               pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status);
+               goto fail_rqirq;
+       }
+
+       task = kthread_run(twl4030_irq_thread, (void *)irq_num, "twl4030-irq");
+       if (IS_ERR(task)) {
+               pr_err("twl4030: could not create irq %d thread!\n", irq_num);
+               status = PTR_ERR(task);
+               goto fail_kthread;
+       }
+       return status;
+fail_kthread:
+       free_irq(irq_num, &irq_event);
+fail_rqirq:
+       /* clean up twl4030_sih_setup */
 fail:
        for (i = irq_base; i < irq_end; i++)
                set_irq_chip_and_handler(i, NULL, NULL);
index d38a7acdb6eca79c1fe4ac4ddfb620f732802ece..d019746551f3481f00c06e209b30a833586e92fa 100644 (file)
@@ -114,7 +114,6 @@ static void sg_dwiter_write_slow(struct sg_mapping_iter *miter, uint32_t data)
                if (!left)
                        return;
                addr += len;
-               flush_kernel_dcache_page(miter->page);
        } while (sg_dwiter_next(miter));
 }
 
@@ -142,9 +141,6 @@ void cb710_sg_dwiter_write_next_block(struct sg_mapping_iter *miter, uint32_t da
                        return;
        } else
                sg_dwiter_write_slow(miter, data);
-
-       if (miter->length == miter->consumed)
-               flush_kernel_dcache_page(miter->page);
 }
 EXPORT_SYMBOL_GPL(cb710_sg_dwiter_write_next_block);
 
index b34cb5f79eea94ce1c23a82f2f33205a93451313..2e535a0ccd5e274c1fc46b700a07a45953022ba8 100644 (file)
@@ -173,6 +173,7 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
                unsigned        segment;
                unsigned        offset = (unsigned) off;
                u8              *cp = bounce + 1;
+               int             sr;
 
                *cp = AT25_WREN;
                status = spi_write(at25->spi, cp, 1);
@@ -214,7 +215,6 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
                timeout = jiffies + msecs_to_jiffies(EE_TIMEOUT);
                retries = 0;
                do {
-                       int     sr;
 
                        sr = spi_w8r8(at25->spi, AT25_RDSR);
                        if (sr < 0 || (sr & AT25_SR_nRDY)) {
@@ -228,7 +228,7 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
                                break;
                } while (retries++ < 3 || time_before_eq(jiffies, timeout));
 
-               if (time_after(jiffies, timeout)) {
+               if ((sr < 0) || (sr & AT25_SR_nRDY)) {
                        dev_err(&at25->spi->dev,
                                "write %d bytes offset %d, "
                                "timeout after %u msecs\n",
index fa2d93a9fb8d7755de89a2f08badce29a07f8983..aed609832bc2bf1c0497dedbd0257bcfcbf7e70a 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/io.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
 #include <linux/miscdevice.h>
index eedbf9c32760f68b76a34726a8358244e1834389..79689b10f937e0b8405a6a3568d5503c532d64a9 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
 #include <linux/miscdevice.h>
index 8d1c60a3f0df9cdb1e178ae85b6605b1557364fb..5d778ec8cdb2aa454224e7a5e5b9f76dc05a49fd 100644 (file)
@@ -235,7 +235,7 @@ xpnet_receive(short partid, int channel, struct xpnet_message *msg)
        skb->ip_summed = CHECKSUM_UNNECESSARY;
 
        dev_dbg(xpnet, "passing skb to network layer\n"
-               KERN_DEBUG "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p "
+               "\tskb->head=0x%p skb->data=0x%p skb->tail=0x%p "
                "skb->end=0x%p skb->len=%d\n",
                (void *)skb->head, (void *)skb->data, skb_tail_pointer(skb),
                skb_end_pointer(skb), skb->len);
@@ -399,7 +399,7 @@ xpnet_send(struct sk_buff *skb, struct xpnet_pending_msg *queued_msg,
        msg->buf_pa = xp_pa((void *)start_addr);
 
        dev_dbg(xpnet, "sending XPC message to %d:%d\n"
-               KERN_DEBUG "msg->buf_pa=0x%lx, msg->size=%u, "
+               "msg->buf_pa=0x%lx, msg->size=%u, "
                "msg->leadin_ignore=%u, msg->tailout_ignore=%u\n",
                dest_partid, XPC_NET_CHANNEL, msg->buf_pa, msg->size,
                msg->leadin_ignore, msg->tailout_ignore);
index 11efefb1af51cebf226a6b6e94b7f7c5d7e5fda9..4e72964a7b431345c37cd0868056de1145b1c76f 100644 (file)
@@ -278,7 +278,7 @@ static int cb710_mmc_receive(struct cb710_slot *slot, struct mmc_data *data)
        if (unlikely(data->blksz & 15 && (data->blocks != 1 || data->blksz != 8)))
                return -EINVAL;
 
-       sg_miter_start(&miter, data->sg, data->sg_len, 0);
+       sg_miter_start(&miter, data->sg, data->sg_len, SG_MITER_TO_SG);
 
        cb710_modify_port_8(slot, CB710_MMC_CONFIG2_PORT,
                15, CB710_MMC_C2_READ_PIO_SIZE_MASK);
@@ -307,7 +307,7 @@ static int cb710_mmc_receive(struct cb710_slot *slot, struct mmc_data *data)
                        goto out;
        }
 out:
-       cb710_sg_miter_stop_writing(&miter);
+       sg_miter_stop(&miter);
        return err;
 }
 
@@ -322,7 +322,7 @@ static int cb710_mmc_send(struct cb710_slot *slot, struct mmc_data *data)
        if (unlikely(data->blocks > 1 && data->blksz & 15))
                return -EINVAL;
 
-       sg_miter_start(&miter, data->sg, data->sg_len, 0);
+       sg_miter_start(&miter, data->sg, data->sg_len, SG_MITER_FROM_SG);
 
        cb710_modify_port_8(slot, CB710_MMC_CONFIG2_PORT,
                0, CB710_MMC_C2_READ_PIO_SIZE_MASK);
index e0be21a4a696d1daf19019eae1bb80651bf2e554..bf98d7cc928aa3e605c81bbe488bf248ebdd2c86 100644 (file)
@@ -652,7 +652,7 @@ static irqreturn_t imxmci_irq(int irq, void *devid)
        set_bit(IMXMCI_PEND_STARTED_b, &host->pending_events);
        tasklet_schedule(&host->tasklet);
 
-       return IRQ_RETVAL(handled);;
+       return IRQ_RETVAL(handled);
 }
 
 static void imxmci_tasklet_fnc(unsigned long data)
index 240608cc7ae9b853c46f696986a821048bebb35b..a461017ce5ce92b6c14c0ca73482f68fd6ad8d7c 100644 (file)
@@ -1313,6 +1313,12 @@ static int mmc_spi_probe(struct spi_device *spi)
        struct mmc_spi_host     *host;
        int                     status;
 
+       /* We rely on full duplex transfers, mostly to reduce
+        * per-transfer overheads (by making fewer transfers).
+        */
+       if (spi->master->flags & SPI_MASTER_HALF_DUPLEX)
+               return -EINVAL;
+
        /* MMC and SD specs only seem to care that sampling is on the
         * rising edge ... meaning SPI modes 0 or 3.  So either SPI mode
         * should be legit.  We'll use mode 0 since the steady state is 0,
index b56d72ff06e9efbf169d5b2f0c7af2c4f6e7589e..34e23489811ae74ea14594f1af1cb84f7a6e6b58 100644 (file)
@@ -384,7 +384,7 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
                                u16 val[2] = {0, 0};
                                val[0] = mvsd_read(MVSD_FIFO);
                                val[1] = mvsd_read(MVSD_FIFO);
-                               memcpy(p, &val, s);
+                               memcpy(p, ((void *)&val) + 4 - s, s);
                                s = 0;
                                intr_status = mvsd_read(MVSD_NOR_INTR_STATUS);
                        }
@@ -423,7 +423,7 @@ static irqreturn_t mvsd_irq(int irq, void *dev)
                if (s < 4) {
                        if (s && (intr_status & MVSD_NOR_TX_AVAIL)) {
                                u16 val[2] = {0, 0};
-                               memcpy(&val, p, s);
+                               memcpy(((void *)&val) + 4 - s, p, s);
                                mvsd_write(MVSD_FIFO, val[0]);
                                mvsd_write(MVSD_FIFO, val[1]);
                                s = 0;
index d7d7109ef47e10b665059433ec962db77f176f7d..e55ac792d68c700e2bfc0d9b86d992c5f4199faf 100644 (file)
@@ -168,12 +168,12 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
 
        if (data->flags & MMC_DATA_READ) {
                host->dma_dir = DMA_FROM_DEVICE;
-               dcmd = DCMD_INCTRGADDR | DCMD_FLOWTRG;
+               dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC;
                DRCMR(host->dma_drcmrtx) = 0;
                DRCMR(host->dma_drcmrrx) = host->dma | DRCMR_MAPVLD;
        } else {
                host->dma_dir = DMA_TO_DEVICE;
-               dcmd = DCMD_INCSRCADDR | DCMD_FLOWSRC;
+               dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG;
                DRCMR(host->dma_drcmrrx) = 0;
                DRCMR(host->dma_drcmrtx) = host->dma | DRCMR_MAPVLD;
        }
index d79fa55c3b8963adf524fde33ed81112800ee7ef..1e8aa590bb39b0a5e650037f61647860fd2b3ec1 100644 (file)
@@ -158,6 +158,13 @@ static unsigned int esdhc_get_max_clock(struct sdhci_host *host)
        return of_host->clock;
 }
 
+static unsigned int esdhc_get_min_clock(struct sdhci_host *host)
+{
+       struct sdhci_of_host *of_host = sdhci_priv(host);
+
+       return of_host->clock / 256 / 16;
+}
+
 static unsigned int esdhc_get_timeout_clock(struct sdhci_host *host)
 {
        struct sdhci_of_host *of_host = sdhci_priv(host);
@@ -184,6 +191,7 @@ static struct sdhci_of_data sdhci_esdhc = {
                .set_clock = esdhc_set_clock,
                .enable_dma = esdhc_enable_dma,
                .get_max_clock = esdhc_get_max_clock,
+               .get_min_clock = esdhc_get_min_clock,
                .get_timeout_clock = esdhc_get_timeout_clock,
        },
 };
@@ -226,7 +234,7 @@ static int __devinit sdhci_of_probe(struct of_device *ofdev,
                return -ENODEV;
 
        host = sdhci_alloc_host(&ofdev->dev, sizeof(*of_host));
-       if (!host)
+       if (IS_ERR(host))
                return -ENOMEM;
 
        of_host = sdhci_priv(host);
index 6779b4ecab185255d630e9c209ea032b979ec6de..fc96f8cb9c0b154db3464a10acdd834d5ec58fa6 100644 (file)
@@ -773,8 +773,14 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
        }
 
        if (!(host->flags & SDHCI_REQ_USE_DMA)) {
-               sg_miter_start(&host->sg_miter,
-                       data->sg, data->sg_len, SG_MITER_ATOMIC);
+               int flags;
+
+               flags = SG_MITER_ATOMIC;
+               if (host->data->flags & MMC_DATA_READ)
+                       flags |= SG_MITER_TO_SG;
+               else
+                       flags |= SG_MITER_FROM_SG;
+               sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
                host->blocks = data->blocks;
        }
 
@@ -1766,7 +1772,10 @@ int sdhci_add_host(struct sdhci_host *host)
         * Set host parameters.
         */
        mmc->ops = &sdhci_ops;
-       mmc->f_min = host->max_clk / 256;
+       if (host->ops->get_min_clock)
+               mmc->f_min = host->ops->get_min_clock(host);
+       else
+               mmc->f_min = host->max_clk / 256;
        mmc->f_max = host->max_clk;
        mmc->caps = MMC_CAP_SDIO_IRQ;
 
index 831ddf7dcb49aef243ececc371d86e51b89eb18f..c77e9ff30223c44ff86da33a2f8a51c18570c520 100644 (file)
@@ -302,6 +302,7 @@ struct sdhci_ops {
 
        int             (*enable_dma)(struct sdhci_host *host);
        unsigned int    (*get_max_clock)(struct sdhci_host *host);
+       unsigned int    (*get_min_clock)(struct sdhci_host *host);
        unsigned int    (*get_timeout_clock)(struct sdhci_host *host);
 };
 
index 5011fa73f91886302135ea08904908c2c6f89461..1479da6d3aa6d78f3462c7817a56dcfede8a764e 100644 (file)
@@ -194,7 +194,7 @@ static struct mtd_partition * newpart(char *s,
        parts[this_part].name = extra_mem;
        extra_mem += name_len + 1;
 
-       dbg(("partition %d: name <%s>, offset %x, size %x, mask flags %x\n",
+       dbg(("partition %d: name <%s>, offset %llx, size %llx, mask flags %x\n",
             this_part,
             parts[this_part].name,
             parts[this_part].offset,
index 59c46126a5ce3ddb63bf4a02aa52c7e621b1b80a..10ed195c0c1cd2ff02c4fe767e3d13dd574c84b8 100644 (file)
@@ -54,7 +54,7 @@
 #define        SR_SRWD                 0x80    /* SR write protect */
 
 /* Define max times to check status register before we give up. */
-#define        MAX_READY_WAIT_JIFFIES  (10 * HZ)       /* eg. M25P128 specs 6s max sector erase */
+#define        MAX_READY_WAIT_JIFFIES  (40 * HZ)       /* M25P16 specs 40s max chip erase */
 #define        CMD_SIZE                4
 
 #ifdef CONFIG_M25PXX_USE_FAST_READ
@@ -736,7 +736,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
                        flash->partitioned = 1;
                        return add_mtd_partitions(&flash->mtd, parts, nr_parts);
                }
-       } else if (data->nr_parts)
+       } else if (data && data->nr_parts)
                dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
                                data->nr_parts, data->name);
 
index 73f05227dc8cb0607d11c6709a2233959f65d92a..d8cf29c01cc46ce6d9c26e01f85dad1630f456b6 100644 (file)
@@ -226,7 +226,7 @@ static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate)
        if (!desperate && inftl->numfreeEUNs < 2) {
                DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free "
                        "EUNs (%d)\n", inftl->numfreeEUNs);
-               return 0xffff;
+               return BLOCK_NIL;
        }
 
        /* Scan for a free block */
@@ -281,7 +281,8 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
        silly = MAX_LOOPS;
        while (thisEUN < inftl->nb_blocks) {
                for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) {
-                       if ((BlockMap[block] != 0xffff) || BlockDeleted[block])
+                       if ((BlockMap[block] != BLOCK_NIL) ||
+                           BlockDeleted[block])
                                continue;
 
                        if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize)
@@ -525,7 +526,7 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
                        if (!silly--) {
                                printk(KERN_WARNING "INFTL: infinite loop in "
                                        "Virtual Unit Chain 0x%x\n", thisVUC);
-                               return 0xffff;
+                               return BLOCK_NIL;
                        }
 
                        /* Skip to next block in chain */
@@ -549,7 +550,7 @@ hitused:
                         * waiting to be picked up. We're going to have to fold
                         * a chain to make room.
                         */
-                       thisEUN = INFTL_makefreeblock(inftl, 0xffff);
+                       thisEUN = INFTL_makefreeblock(inftl, BLOCK_NIL);
 
                        /*
                         * Hopefully we free something, lets try again.
@@ -631,7 +632,7 @@ hitused:
 
        printk(KERN_WARNING "INFTL: error folding to make room for Virtual "
                "Unit Chain 0x%x\n", thisVUC);
-       return 0xffff;
+       return BLOCK_NIL;
 }
 
 /*
index 0b98654d8eed27831b591c3ec2575771c44166d8..7a58bd5522fd736a83584acaf9a9472b4a57e876 100644 (file)
@@ -284,13 +284,6 @@ config MTD_L440GX
 
          BE VERY CAREFUL.
 
-config MTD_SBC8240
-       tristate "Flash device on SBC8240"
-       depends on MTD_JEDECPROBE && 8260
-       help
-          Flash access on the SBC8240 board from Wind River.  See
-          <http://www.windriver.com/products/sbc8240/>
-
 config MTD_TQM8XXL
        tristate "CFI Flash device mapped on TQM8XXL"
        depends on MTD_CFI && TQM8xxL
index 8bae7f9850c0b1acbb2e782734f01bd612f8a985..5beb0662d724b7097d3bb7fd5c62169f715d6a3e 100644 (file)
@@ -50,7 +50,6 @@ obj-$(CONFIG_MTD_UCLINUX)     += uclinux.o
 obj-$(CONFIG_MTD_NETtel)       += nettel.o
 obj-$(CONFIG_MTD_SCB2_FLASH)   += scb2_flash.o
 obj-$(CONFIG_MTD_H720X)                += h720x-flash.o
-obj-$(CONFIG_MTD_SBC8240)      += sbc8240.o
 obj-$(CONFIG_MTD_IXP4XX)       += ixp4xx.o
 obj-$(CONFIG_MTD_IXP2000)      += ixp2000.o
 obj-$(CONFIG_MTD_WRSBC8260)    += wr_sbc82xx_flash.o
index b08a798ee254be0ed501758f0300df314c18078b..2aac41bde8b314feda6bf213472c76277881c6ca 100644 (file)
 #include <mach/hardware.h>
 #include <asm/system.h>
 
-#define SUBDEV_NAME_SIZE       (BUS_ID_SIZE + 2)
-
 struct armflash_subdev_info {
-       char                    name[SUBDEV_NAME_SIZE];
+       char                    *name;
        struct mtd_info         *mtd;
        struct map_info         map;
        struct flash_platform_data *plat;
@@ -134,6 +132,8 @@ static void armflash_subdev_remove(struct armflash_subdev_info *subdev)
                map_destroy(subdev->mtd);
        if (subdev->map.virt)
                iounmap(subdev->map.virt);
+       kfree(subdev->name);
+       subdev->name = NULL;
        release_mem_region(subdev->map.phys, subdev->map.size);
 }
 
@@ -177,16 +177,22 @@ static int armflash_probe(struct platform_device *dev)
 
                if (nr == 1)
                        /* No MTD concatenation, just use the default name */
-                       snprintf(subdev->name, SUBDEV_NAME_SIZE, "%s",
-                                dev_name(&dev->dev));
+                       subdev->name = kstrdup(dev_name(&dev->dev), GFP_KERNEL);
                else
-                       snprintf(subdev->name, SUBDEV_NAME_SIZE, "%s-%d",
-                                dev_name(&dev->dev), i);
+                       subdev->name = kasprintf(GFP_KERNEL, "%s-%d",
+                                                dev_name(&dev->dev), i);
+               if (!subdev->name) {
+                       err = -ENOMEM;
+                       break;
+               }
                subdev->plat = plat;
 
                err = armflash_subdev_probe(subdev, res);
-               if (err)
+               if (err) {
+                       kfree(subdev->name);
+                       subdev->name = NULL;
                        break;
+               }
        }
        info->nr_subdev = i;
 
diff --git a/drivers/mtd/maps/sbc8240.c b/drivers/mtd/maps/sbc8240.c
deleted file mode 100644 (file)
index d5374cd..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Handle mapping of the flash memory access routines on the SBC8240 board.
- *
- * Carolyn Smith, Tektronix, Inc.
- *
- * This code is GPLed
- */
-
-/*
- * The SBC8240 has 2 flash banks.
- * Bank 0 is a 512 KiB AMD AM29F040B; 8 x 64 KiB sectors.
- * It contains the U-Boot code (7 sectors) and the environment (1 sector).
- * Bank 1 is 4 x 1 MiB AMD AM29LV800BT; 15 x 64 KiB sectors, 1 x 32 KiB sector,
- * 2 x 8 KiB sectors, 1 x 16 KiB sectors.
- * Both parts are JEDEC compatible.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <asm/io.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/cfi.h>
-
-#ifdef CONFIG_MTD_PARTITIONS
-#include <linux/mtd/partitions.h>
-#endif
-
-#define        DEBUG
-
-#ifdef DEBUG
-# define debugk(fmt,args...)   printk(fmt ,##args)
-#else
-# define debugk(fmt,args...)
-#endif
-
-
-#define WINDOW_ADDR0   0xFFF00000              /* 512 KiB */
-#define WINDOW_SIZE0   0x00080000
-#define BUSWIDTH0      1
-
-#define WINDOW_ADDR1   0xFF000000              /* 4 MiB */
-#define WINDOW_SIZE1   0x00400000
-#define BUSWIDTH1      8
-
-#define MSG_PREFIX "sbc8240:"  /* prefix for our printk()'s */
-#define MTDID     "sbc8240-%d" /* for mtdparts= partitioning */
-
-
-static struct map_info sbc8240_map[2] = {
-       {
-               .name           = "sbc8240 Flash Bank #0",
-               .size           = WINDOW_SIZE0,
-               .bankwidth       = BUSWIDTH0,
-       },
-       {
-               .name           = "sbc8240 Flash Bank #1",
-               .size           = WINDOW_SIZE1,
-               .bankwidth       = BUSWIDTH1,
-       }
-};
-
-#define NUM_FLASH_BANKS        ARRAY_SIZE(sbc8240_map)
-
-/*
- * The following defines the partition layout of SBC8240 boards.
- *
- * See include/linux/mtd/partitions.h for definition of the
- * mtd_partition structure.
- *
- * The *_max_flash_size is the maximum possible mapped flash size
- * which is not necessarily the actual flash size. It must correspond
- * to the value specified in the mapping definition defined by the
- * "struct map_desc *_io_desc" for the corresponding machine.
- */
-
-#ifdef CONFIG_MTD_PARTITIONS
-
-static struct mtd_partition sbc8240_uboot_partitions [] = {
-       /* Bank 0 */
-       {
-               .name = "U-boot",                       /* U-Boot Firmware      */
-               .offset =       0,
-               .size = 0x00070000,                     /*  7 x 64 KiB sectors  */
-               .mask_flags = MTD_WRITEABLE,            /*  force read-only     */
-       },
-       {
-               .name = "environment",                  /* U-Boot environment   */
-               .offset =       0x00070000,
-               .size = 0x00010000,                     /*  1 x 64 KiB sector   */
-       },
-};
-
-static struct mtd_partition sbc8240_fs_partitions [] = {
-       {
-               .name = "jffs",                         /* JFFS  filesystem     */
-               .offset =       0,
-               .size = 0x003C0000,                     /*  4 * 15 * 64KiB      */
-       },
-       {
-               .name = "tmp32",
-               .offset =       0x003C0000,
-               .size = 0x00020000,                     /*  4 * 32KiB           */
-       },
-       {
-               .name = "tmp8a",
-               .offset =       0x003E0000,
-               .size = 0x00008000,                     /*  4 * 8KiB            */
-       },
-       {
-               .name = "tmp8b",
-               .offset =       0x003E8000,
-               .size = 0x00008000,                     /*  4 * 8KiB            */
-       },
-       {
-               .name = "tmp16",
-               .offset =       0x003F0000,
-               .size = 0x00010000,                     /*  4 * 16KiB           */
-       }
-};
-
-/* trivial struct to describe partition information */
-struct mtd_part_def
-{
-       int nums;
-       unsigned char *type;
-       struct mtd_partition* mtd_part;
-};
-
-static struct mtd_info *sbc8240_mtd[NUM_FLASH_BANKS];
-static struct mtd_part_def sbc8240_part_banks[NUM_FLASH_BANKS];
-
-
-#endif /* CONFIG_MTD_PARTITIONS */
-
-
-static int __init init_sbc8240_mtd (void)
-{
-       static struct _cjs {
-               u_long addr;
-               u_long size;
-       } pt[NUM_FLASH_BANKS] = {
-               {
-                       .addr = WINDOW_ADDR0,
-                       .size = WINDOW_SIZE0
-               },
-               {
-                       .addr = WINDOW_ADDR1,
-                       .size = WINDOW_SIZE1
-               },
-       };
-
-       int devicesfound = 0;
-       int i,j;
-
-       for (i = 0; i < NUM_FLASH_BANKS; i++) {
-               printk (KERN_NOTICE MSG_PREFIX
-                       "Probing 0x%08lx at 0x%08lx\n", pt[i].size, pt[i].addr);
-
-               sbc8240_map[i].map_priv_1 =
-                       (unsigned long) ioremap (pt[i].addr, pt[i].size);
-               if (!sbc8240_map[i].map_priv_1) {
-                       printk (MSG_PREFIX "failed to ioremap\n");
-                       for (j = 0; j < i; j++) {
-                               iounmap((void *) sbc8240_map[j].map_priv_1);
-                               sbc8240_map[j].map_priv_1 = 0;
-                       }
-                       return -EIO;
-               }
-               simple_map_init(&sbc8240_mtd[i]);
-
-               sbc8240_mtd[i] = do_map_probe("jedec_probe", &sbc8240_map[i]);
-
-               if (sbc8240_mtd[i]) {
-                       sbc8240_mtd[i]->module = THIS_MODULE;
-                       devicesfound++;
-               } else {
-                       if (sbc8240_map[i].map_priv_1) {
-                               iounmap((void *) sbc8240_map[i].map_priv_1);
-                               sbc8240_map[i].map_priv_1 = 0;
-                       }
-               }
-       }
-
-       if (!devicesfound) {
-               printk(KERN_NOTICE MSG_PREFIX
-                      "No suppported flash chips found!\n");
-               return -ENXIO;
-       }
-
-#ifdef CONFIG_MTD_PARTITIONS
-       sbc8240_part_banks[0].mtd_part   = sbc8240_uboot_partitions;
-       sbc8240_part_banks[0].type       = "static image";
-       sbc8240_part_banks[0].nums       = ARRAY_SIZE(sbc8240_uboot_partitions);
-       sbc8240_part_banks[1].mtd_part   = sbc8240_fs_partitions;
-       sbc8240_part_banks[1].type       = "static file system";
-       sbc8240_part_banks[1].nums       = ARRAY_SIZE(sbc8240_fs_partitions);
-
-       for (i = 0; i < NUM_FLASH_BANKS; i++) {
-
-               if (!sbc8240_mtd[i]) continue;
-               if (sbc8240_part_banks[i].nums == 0) {
-                       printk (KERN_NOTICE MSG_PREFIX
-                               "No partition info available, registering whole device\n");
-                       add_mtd_device(sbc8240_mtd[i]);
-               } else {
-                       printk (KERN_NOTICE MSG_PREFIX
-                               "Using %s partition definition\n", sbc8240_part_banks[i].mtd_part->name);
-                       add_mtd_partitions (sbc8240_mtd[i],
-                                           sbc8240_part_banks[i].mtd_part,
-                                           sbc8240_part_banks[i].nums);
-               }
-       }
-#else
-       printk(KERN_NOTICE MSG_PREFIX
-              "Registering %d flash banks at once\n", devicesfound);
-
-       for (i = 0; i < devicesfound; i++) {
-               add_mtd_device(sbc8240_mtd[i]);
-       }
-#endif /* CONFIG_MTD_PARTITIONS */
-
-       return devicesfound == 0 ? -ENXIO : 0;
-}
-
-static void __exit cleanup_sbc8240_mtd (void)
-{
-       int i;
-
-       for (i = 0; i < NUM_FLASH_BANKS; i++) {
-               if (sbc8240_mtd[i]) {
-                       del_mtd_device (sbc8240_mtd[i]);
-                       map_destroy (sbc8240_mtd[i]);
-               }
-               if (sbc8240_map[i].map_priv_1) {
-                       iounmap ((void *) sbc8240_map[i].map_priv_1);
-                       sbc8240_map[i].map_priv_1 = 0;
-               }
-       }
-}
-
-module_init (init_sbc8240_mtd);
-module_exit (cleanup_sbc8240_mtd);
-
-MODULE_LICENSE ("GPL");
-MODULE_AUTHOR ("Carolyn Smith <carolyn.smith@tektronix.com>");
-MODULE_DESCRIPTION ("MTD map driver for SBC8240 boards");
-
index c3f62654b6df4bee93cc69a86ca839031186f910..7baba40c1ed225f38921e2143514822080bc67ae 100644 (file)
@@ -144,7 +144,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
        struct mtd_blktrans_ops *tr = dev->tr;
        int ret = -ENODEV;
 
-       if (!try_module_get(dev->mtd->owner))
+       if (!get_mtd_device(NULL, dev->mtd->index))
                goto out;
 
        if (!try_module_get(tr->owner))
@@ -158,7 +158,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
        ret = 0;
        if (tr->open && (ret = tr->open(dev))) {
                dev->mtd->usecount--;
-               module_put(dev->mtd->owner);
+               put_mtd_device(dev->mtd);
        out_tr:
                module_put(tr->owner);
        }
@@ -177,7 +177,7 @@ static int blktrans_release(struct gendisk *disk, fmode_t mode)
 
        if (!ret) {
                dev->mtd->usecount--;
-               module_put(dev->mtd->owner);
+               put_mtd_device(dev->mtd);
                module_put(tr->owner);
        }
 
index 208c6faa0358afe995608599ea7e39dc4a405e6d..77db5ce24d92b9fed41970d83bb1346a95740d85 100644 (file)
@@ -29,6 +29,8 @@ static struct mtdblk_dev {
        enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
 } *mtdblks[MAX_MTD_DEVICES];
 
+static struct mutex mtdblks_lock;
+
 /*
  * Cache stuff...
  *
@@ -270,15 +272,19 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
 
        DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n");
 
+       mutex_lock(&mtdblks_lock);
        if (mtdblks[dev]) {
                mtdblks[dev]->count++;
+               mutex_unlock(&mtdblks_lock);
                return 0;
        }
 
        /* OK, it's not open. Create cache info for it */
        mtdblk = kzalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
-       if (!mtdblk)
+       if (!mtdblk) {
+               mutex_unlock(&mtdblks_lock);
                return -ENOMEM;
+       }
 
        mtdblk->count = 1;
        mtdblk->mtd = mtd;
@@ -291,6 +297,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
        }
 
        mtdblks[dev] = mtdblk;
+       mutex_unlock(&mtdblks_lock);
 
        DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
 
@@ -304,6 +311,8 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
 
        DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");
 
+       mutex_lock(&mtdblks_lock);
+
        mutex_lock(&mtdblk->cache_mutex);
        write_cached_data(mtdblk);
        mutex_unlock(&mtdblk->cache_mutex);
@@ -316,6 +325,9 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
                vfree(mtdblk->cache_data);
                kfree(mtdblk);
        }
+
+       mutex_unlock(&mtdblks_lock);
+
        DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
 
        return 0;
@@ -376,6 +388,8 @@ static struct mtd_blktrans_ops mtdblock_tr = {
 
 static int __init init_mtdblock(void)
 {
+       mutex_init(&mtdblks_lock);
+
        return register_mtd_blktrans(&mtdblock_tr);
 }
 
index fac54a3fa3f189c60aaf58a197be7867aed4ca80..00ebf7af7467b6b35dac1a2e2c32c432b11528ad 100644 (file)
@@ -65,8 +65,8 @@ static void mtd_release(struct device *dev)
 static int mtd_cls_suspend(struct device *dev, pm_message_t state)
 {
        struct mtd_info *mtd = dev_to_mtd(dev);
-       
-       if (mtd->suspend)
+
+       if (mtd && mtd->suspend)
                return mtd->suspend(mtd);
        else
                return 0;
@@ -76,7 +76,7 @@ static int mtd_cls_resume(struct device *dev)
 {
        struct mtd_info *mtd = dev_to_mtd(dev);
        
-       if (mtd->resume)
+       if (mtd && mtd->resume)
                mtd->resume(mtd);
        return 0;
 }
@@ -298,6 +298,7 @@ int add_mtd_device(struct mtd_info *mtd)
                        mtd->dev.class = &mtd_class;
                        mtd->dev.devt = MTD_DEVT(i);
                        dev_set_name(&mtd->dev, "mtd%d", i);
+                       dev_set_drvdata(&mtd->dev, mtd);
                        if (device_register(&mtd->dev) != 0) {
                                mtd_table[i] = NULL;
                                break;
index 2802992b39daf67ce5c917103f03501d113f290e..20c828ba94052daae1e7a79ac4b4edb8f6e51104 100644 (file)
@@ -534,7 +534,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
                                                         &num_partitions);
 
        if ((!partitions) || (num_partitions == 0)) {
-               printk(KERN_ERR "atmel_nand: No parititions defined, or unsupported device.\n");
+               printk(KERN_ERR "atmel_nand: No partitions defined, or unsupported device.\n");
                res = ENXIO;
                goto err_no_partitions;
        }
index 0cd76f89f4b0a43349ff030296a1cd1252169f6c..ebd07e95b8140354ae8c51061ef7cb9b7945d153 100644 (file)
@@ -11,6 +11,8 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
@@ -541,7 +543,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
        struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
                                                        mtd);
        unsigned long timeo = jiffies;
-       int status, state = this->state;
+       int status = NAND_STATUS_FAIL, state = this->state;
 
        if (state == FL_ERASING)
                timeo += (HZ * 400) / 1000;
@@ -556,8 +558,9 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
 
        while (time_before(jiffies, timeo)) {
                status = __raw_readb(this->IO_ADDR_R);
-               if (!(status & 0x40))
+               if (status & NAND_STATUS_READY)
                        break;
+               cond_resched();
        }
        return status;
 }
index 7ad972229db4317153dee8db1a008333e7c019e9..0d9d4bc9c762fe5caeab5770419f14dfe2c81403 100644 (file)
@@ -61,7 +61,7 @@ static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
        buf64 = (uint64_t *)buf;
        while (i < len/8) {
                uint64_t x;
-               asm ("ldrd\t%0, [%1]" : "=r" (x) : "r" (io_base));
+               asm volatile ("ldrd\t%0, [%1]" : "=&r" (x) : "r" (io_base));
                buf64[i++] = x;
        }
        i *= 8;
index e3f8495a94c27492ccaaca85e0a96a1d478a98cd..1002e18829966256bb77833f67501c6871d7d4ce 100644 (file)
@@ -135,16 +135,17 @@ static void nftl_remove_dev(struct mtd_blktrans_dev *dev)
 int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
                  size_t *retlen, uint8_t *buf)
 {
+       loff_t mask = mtd->writesize - 1;
        struct mtd_oob_ops ops;
        int res;
 
        ops.mode = MTD_OOB_PLACE;
-       ops.ooboffs = offs & (mtd->writesize - 1);
+       ops.ooboffs = offs & mask;
        ops.ooblen = len;
        ops.oobbuf = buf;
        ops.datbuf = NULL;
 
-       res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+       res = mtd->read_oob(mtd, offs & ~mask, &ops);
        *retlen = ops.oobretlen;
        return res;
 }
@@ -155,16 +156,17 @@ int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
 int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
                   size_t *retlen, uint8_t *buf)
 {
+       loff_t mask = mtd->writesize - 1;
        struct mtd_oob_ops ops;
        int res;
 
        ops.mode = MTD_OOB_PLACE;
-       ops.ooboffs = offs & (mtd->writesize - 1);
+       ops.ooboffs = offs & mask;
        ops.ooblen = len;
        ops.oobbuf = buf;
        ops.datbuf = NULL;
 
-       res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+       res = mtd->write_oob(mtd, offs & ~mask, &ops);
        *retlen = ops.oobretlen;
        return res;
 }
@@ -177,17 +179,18 @@ int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
 static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
                      size_t *retlen, uint8_t *buf, uint8_t *oob)
 {
+       loff_t mask = mtd->writesize - 1;
        struct mtd_oob_ops ops;
        int res;
 
        ops.mode = MTD_OOB_PLACE;
-       ops.ooboffs = offs;
+       ops.ooboffs = offs & mask;
        ops.ooblen = mtd->oobsize;
        ops.oobbuf = oob;
        ops.datbuf = buf;
        ops.len = len;
 
-       res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+       res = mtd->write_oob(mtd, offs & ~mask, &ops);
        *retlen = ops.retlen;
        return res;
 }
@@ -208,7 +211,7 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate )
        /* Normally, we force a fold to happen before we run out of free blocks completely */
        if (!desperate && nftl->numfreeEUNs < 2) {
                DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n");
-               return 0xffff;
+               return BLOCK_NIL;
        }
 
        /* Scan for a free block */
@@ -230,11 +233,11 @@ static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate )
                        printk("Argh! No free blocks found! LastFreeEUN = %d, "
                               "FirstEUN = %d\n", nftl->LastFreeEUN,
                               le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN));
-                       return 0xffff;
+                       return BLOCK_NIL;
                }
        } while (pot != nftl->LastFreeEUN);
 
-       return 0xffff;
+       return BLOCK_NIL;
 }
 
 static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock )
@@ -431,7 +434,7 @@ static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned p
 
        /* add the header so that it is now a valid chain */
        oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
-       oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff;
+       oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = BLOCK_NIL;
 
        nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8,
                       8, &retlen, (char *)&oob.u);
@@ -515,7 +518,7 @@ static u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock)
        if (ChainLength < 2) {
                printk(KERN_WARNING "No Virtual Unit Chains available for folding. "
                       "Failing request\n");
-               return 0xffff;
+               return BLOCK_NIL;
        }
 
        return NFTL_foldchain (nftl, LongestChain, pendingblock);
@@ -578,7 +581,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
                                printk(KERN_WARNING
                                       "Infinite loop in Virtual Unit Chain 0x%x\n",
                                       thisVUC);
-                               return 0xffff;
+                               return BLOCK_NIL;
                        }
 
                        /* Skip to next block in chain */
@@ -601,7 +604,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
                        //u16 startEUN = nftl->EUNtable[thisVUC];
 
                        //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC);
-                       writeEUN = NFTL_makefreeblock(nftl, 0xffff);
+                       writeEUN = NFTL_makefreeblock(nftl, BLOCK_NIL);
 
                        if (writeEUN == BLOCK_NIL) {
                                /* OK, we accept that the above comment is
@@ -673,7 +676,7 @@ static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block)
 
        printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n",
               thisVUC);
-       return 0xffff;
+       return BLOCK_NIL;
 }
 
 static int nftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
index 38d656b9b2eecc8f5029bb0b7a6e89f921ff5a2d..0108ed42e877b628d773f4ee847bccd47c98bbc7 100644 (file)
@@ -266,7 +266,7 @@ static inline int omap2_onenand_bufferram_offset(struct mtd_info *mtd, int area)
 
        if (ONENAND_CURRENT_BUFFERRAM(this)) {
                if (area == ONENAND_DATARAM)
-                       return mtd->writesize;
+                       return this->writesize;
                if (area == ONENAND_SPARERAM)
                        return mtd->oobsize;
        }
@@ -770,6 +770,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
        }
        iounmap(c->onenand.base);
        release_mem_region(c->phys_base, ONENAND_IO_SIZE);
+       gpmc_cs_free(c->gpmc_cs);
        kfree(c);
 
        return 0;
index 286ed594e5a0ec01d87810c004e0511b78385477..e1f7d0a78b9d58e28a2b6c1fdad43423cddd3956 100644 (file)
@@ -657,6 +657,11 @@ static int io_init(struct ubi_device *ubi)
        if (ubi->mtd->block_isbad && ubi->mtd->block_markbad)
                ubi->bad_allowed = 1;
 
+       if (ubi->mtd->type == MTD_NORFLASH) {
+               ubi_assert(ubi->mtd->writesize == 1);
+               ubi->nor_flash = 1;
+       }
+
        ubi->min_io_size = ubi->mtd->writesize;
        ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
 
@@ -996,6 +1001,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
        ubi_msg("number of PEBs reserved for bad PEB handling: %d",
                ubi->beb_rsvd_pebs);
        ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
+       ubi_msg("image sequence number: %d", ubi->image_seq);
 
        /*
         * The below lock makes sure we do not race with 'ubi_thread()' which
index c0ed60e8ade978ca74091aed6a8e5b14f1a47e63..54b0186915fbf6ab6be8f845a4d942f7f2f277aa 100644 (file)
@@ -44,6 +44,8 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
               be32_to_cpu(ec_hdr->vid_hdr_offset));
        printk(KERN_DEBUG "\tdata_offset    %d\n",
               be32_to_cpu(ec_hdr->data_offset));
+       printk(KERN_DEBUG "\timage_seq      %d\n",
+              be32_to_cpu(ec_hdr->image_seq));
        printk(KERN_DEBUG "\thdr_crc        %#08x\n",
               be32_to_cpu(ec_hdr->hdr_crc));
        printk(KERN_DEBUG "erase counter header hexdump:\n");
index 13777e5beac93344ae759aa2ea0176c796e97d1d..a4da7a09b949b75f5e259837da31190b31874bbc 100644 (file)
@@ -93,6 +93,12 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
 #define UBI_IO_DEBUG 0
 #endif
 
+#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
+#else
+#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
+#endif
+
 #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT
 #define DBG_DISABLE_BGT 1
 #else
@@ -167,6 +173,7 @@ static inline int ubi_dbg_is_erase_failure(void)
 #define ubi_dbg_is_bitflip()       0
 #define ubi_dbg_is_write_failure() 0
 #define ubi_dbg_is_erase_failure() 0
+#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
 
 #endif /* !CONFIG_MTD_UBI_DEBUG */
 #endif /* !__UBI_DEBUG_H__ */
index 0f2034c3ed2f715b4281522aeed820023b9f8f14..e4d9ef0c965a4f432a45913942f03d7702a7b4cb 100644 (file)
@@ -1254,6 +1254,7 @@ out_free:
                if (!ubi->volumes[i])
                        continue;
                kfree(ubi->volumes[i]->eba_tbl);
+               ubi->volumes[i]->eba_tbl = NULL;
        }
        return err;
 }
index 95aaac03f9389a8727b3ed65f91124dc592c15dc..b5e478fa26612b188aa664541503457b2e58d2af 100644 (file)
@@ -332,6 +332,7 @@ static int gluebi_create(struct ubi_device_info *di,
        }
 
        gluebi->vol_id = vi->vol_id;
+       gluebi->ubi_num = vi->ubi_num;
        mtd->type = MTD_UBIVOLUME;
        if (!di->ro_mode)
                mtd->flags = MTD_WRITEABLE;
index effaff28bab18ef4936c69cf354a4b8a11db17dd..4cb69925d8d968f9021626a6dd38933af94842ee 100644 (file)
@@ -98,17 +98,12 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
 static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum);
 static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
                                  const struct ubi_vid_hdr *vid_hdr);
-static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
-                                int len);
-static int paranoid_check_empty(struct ubi_device *ubi, int pnum);
 #else
 #define paranoid_check_not_bad(ubi, pnum) 0
 #define paranoid_check_peb_ec_hdr(ubi, pnum)  0
 #define paranoid_check_ec_hdr(ubi, pnum, ec_hdr)  0
 #define paranoid_check_peb_vid_hdr(ubi, pnum) 0
 #define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0
-#define paranoid_check_all_ff(ubi, pnum, offset, len) 0
-#define paranoid_check_empty(ubi, pnum) 0
 #endif
 
 /**
@@ -244,7 +239,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
                return err > 0 ? -EINVAL : err;
 
        /* The area we are writing to has to contain all 0xFF bytes */
-       err = paranoid_check_all_ff(ubi, pnum, offset, len);
+       err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
        if (err)
                return err > 0 ? -EINVAL : err;
 
@@ -271,8 +266,8 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
        addr = (loff_t)pnum * ubi->peb_size + offset;
        err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf);
        if (err) {
-               ubi_err("error %d while writing %d bytes to PEB %d:%d, written"
-                       " %zd bytes", err, len, pnum, offset, written);
+               ubi_err("error %d while writing %d bytes to PEB %d:%d, written "
+                       "%zd bytes", err, len, pnum, offset, written);
                ubi_dbg_dump_stack();
        } else
                ubi_assert(written == len);
@@ -350,7 +345,7 @@ retry:
                return -EIO;
        }
 
-       err = paranoid_check_all_ff(ubi, pnum, 0, ubi->peb_size);
+       err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size);
        if (err)
                return err > 0 ? -EINVAL : err;
 
@@ -458,6 +453,54 @@ out:
        return err;
 }
 
+/**
+ * nor_erase_prepare - prepare a NOR flash PEB for erasure.
+ * @ubi: UBI device description object
+ * @pnum: physical eraseblock number to prepare
+ *
+ * NOR flash, or at least some of them, have peculiar embedded PEB erasure
+ * algorithm: the PEB is first filled with zeroes, then it is erased. And
+ * filling with zeroes starts from the end of the PEB. This was observed with
+ * Spansion S29GL512N NOR flash.
+ *
+ * This means that in case of a power cut we may end up with intact data at the
+ * beginning of the PEB, and all zeroes at the end of PEB. In other words, the
+ * EC and VID headers are OK, but a large chunk of data at the end of PEB is
+ * zeroed. This makes UBI mistakenly treat this PEB as used and associate it
+ * with an LEB, which leads to subsequent failures (e.g., UBIFS fails).
+ *
+ * This function is called before erasing NOR PEBs and it zeroes out EC and VID
+ * magic numbers in order to invalidate them and prevent the failures. Returns
+ * zero in case of success and a negative error code in case of failure.
+ */
+static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
+{
+       int err;
+       size_t written;
+       loff_t addr;
+       uint32_t data = 0;
+
+       addr = (loff_t)pnum * ubi->peb_size;
+       err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
+       if (err) {
+               ubi_err("error %d while writing 4 bytes to PEB %d:%d, written "
+                       "%zd bytes", err, pnum, 0, written);
+               ubi_dbg_dump_stack();
+               return err;
+       }
+
+       addr += ubi->vid_hdr_aloffset;
+       err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
+       if (err) {
+               ubi_err("error %d while writing 4 bytes to PEB %d:%d, written "
+                       "%zd bytes", err, pnum, ubi->vid_hdr_aloffset, written);
+               ubi_dbg_dump_stack();
+               return err;
+       }
+
+       return 0;
+}
+
 /**
  * ubi_io_sync_erase - synchronously erase a physical eraseblock.
  * @ubi: UBI device description object
@@ -489,6 +532,12 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture)
                return -EROFS;
        }
 
+       if (ubi->nor_flash) {
+               err = nor_erase_prepare(ubi, pnum);
+               if (err)
+                       return err;
+       }
+
        if (torture) {
                ret = torture_peb(ubi, pnum);
                if (ret < 0)
@@ -672,11 +721,6 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
                if (read_err != -EBADMSG &&
                    check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
                        /* The physical eraseblock is supposedly empty */
-                       err = paranoid_check_all_ff(ubi, pnum, 0,
-                                                   ubi->peb_size);
-                       if (err)
-                               return err > 0 ? UBI_IO_BAD_EC_HDR : err;
-
                        if (verbose)
                                ubi_warn("no EC header found at PEB %d, "
                                         "only 0xFF bytes", pnum);
@@ -752,6 +796,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
        ec_hdr->version = UBI_VERSION;
        ec_hdr->vid_hdr_offset = cpu_to_be32(ubi->vid_hdr_offset);
        ec_hdr->data_offset = cpu_to_be32(ubi->leb_start);
+       ec_hdr->image_seq = cpu_to_be32(ubi->image_seq);
        crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
        ec_hdr->hdr_crc = cpu_to_be32(crc);
 
@@ -947,15 +992,6 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
                if (read_err != -EBADMSG &&
                    check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
                        /* The physical eraseblock is supposedly free */
-
-                       /*
-                        * The below is just a paranoid check, it has to be
-                        * compiled out if paranoid checks are disabled.
-                        */
-                       err = paranoid_check_empty(ubi, pnum);
-                       if (err)
-                               return err > 0 ? UBI_IO_BAD_VID_HDR : err;
-
                        if (verbose)
                                ubi_warn("no VID header found at PEB %d, "
                                         "only 0xFF bytes", pnum);
@@ -1229,7 +1265,7 @@ exit:
 }
 
 /**
- * paranoid_check_all_ff - check that a region of flash is empty.
+ * ubi_dbg_check_all_ff - check that a region of flash is empty.
  * @ubi: UBI device description object
  * @pnum: the physical eraseblock number to check
  * @offset: the starting offset within the physical eraseblock to check
@@ -1239,8 +1275,7 @@ exit:
  * @offset of the physical eraseblock @pnum, %1 if not, and a negative error
  * code if an error occurred.
  */
-static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
-                                int len)
+int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
 {
        size_t read;
        int err;
@@ -1276,74 +1311,4 @@ error:
        return err;
 }
 
-/**
- * paranoid_check_empty - whether a PEB is empty.
- * @ubi: UBI device description object
- * @pnum: the physical eraseblock number to check
- *
- * This function makes sure PEB @pnum is empty, which means it contains only
- * %0xFF data bytes. Returns zero if the PEB is empty, %1 if not, and a
- * negative error code in case of failure.
- *
- * Empty PEBs have the EC header, and do not have the VID header. The caller of
- * this function should have already made sure the PEB does not have the VID
- * header. However, this function re-checks that, because it is possible that
- * the header and data has already been written to the PEB.
- *
- * Let's consider a possible scenario. Suppose there are 2 tasks - A and B.
- * Task A is in 'wear_leveling_worker()'. It is reading VID header of PEB X to
- * find which LEB it corresponds to. PEB X is currently unmapped, and has no
- * VID header. Task B is trying to write to PEB X.
- *
- * Task A: in 'ubi_io_read_vid_hdr()': reads the VID header from PEB X. The
- *         read data contain all 0xFF bytes;
- * Task B: writes VID header and some data to PEB X;
- * Task A: assumes PEB X is empty, calls 'paranoid_check_empty()'. And if we
- *         do not re-read the VID header, and do not cancel the checking if it
- *         is there, we fail.
- */
-static int paranoid_check_empty(struct ubi_device *ubi, int pnum)
-{
-       int err, offs = ubi->vid_hdr_aloffset, len = ubi->vid_hdr_alsize;
-       size_t read;
-       uint32_t magic;
-       const struct ubi_vid_hdr *vid_hdr;
-
-       mutex_lock(&ubi->dbg_buf_mutex);
-       err = ubi->mtd->read(ubi->mtd, offs, len, &read, ubi->dbg_peb_buf);
-       if (err && err != -EUCLEAN) {
-               ubi_err("error %d while reading %d bytes from PEB %d:%d, "
-                       "read %zd bytes", err, len, pnum, offs, read);
-               goto error;
-       }
-
-       vid_hdr = ubi->dbg_peb_buf;
-       magic = be32_to_cpu(vid_hdr->magic);
-       if (magic == UBI_VID_HDR_MAGIC)
-               /* The PEB contains VID header, so it is not empty */
-               goto out;
-
-       err = check_pattern(ubi->dbg_peb_buf, 0xFF, len);
-       if (err == 0) {
-               ubi_err("flash region at PEB %d:%d, length %d does not "
-                       "contain all 0xFF bytes", pnum, offs, len);
-               goto fail;
-       }
-
-out:
-       mutex_unlock(&ubi->dbg_buf_mutex);
-       return 0;
-
-fail:
-       ubi_err("paranoid check failed for PEB %d", pnum);
-       ubi_msg("hex dump of the %d-%d region", offs, offs + len);
-       print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
-                      ubi->dbg_peb_buf, len, 1);
-       err = 1;
-error:
-       ubi_dbg_dump_stack();
-       mutex_unlock(&ubi->dbg_buf_mutex);
-       return err;
-}
-
 #endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
index c3d653ba5ca0153c45ccbfd21a6d106bfa1b6220..b847745394b42d46869cdc892043abe46288809d 100644 (file)
@@ -757,6 +757,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
        si->is_empty = 0;
 
        if (!ec_corr) {
+               int image_seq;
+
                /* Make sure UBI version is OK */
                if (ech->version != UBI_VERSION) {
                        ubi_err("this UBI version is %d, image version is %d",
@@ -778,6 +780,29 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
                        ubi_dbg_dump_ec_hdr(ech);
                        return -EINVAL;
                }
+
+               /*
+                * Make sure that all PEBs have the same image sequence number.
+                * This allows us to detect situations when users flash UBI
+                * images incorrectly, so that the flash has the new UBI image
+                * and leftovers from the old one. This feature was added
+                * relatively recently, and the sequence number was always
+                * zero, because old UBI implementations always set it to zero.
+                * For this reasons, we do not panic if some PEBs have zero
+                * sequence number, while other PEBs have non-zero sequence
+                * number.
+                */
+               image_seq = be32_to_cpu(ech->image_seq);
+               if (!si->image_seq_set) {
+                       ubi->image_seq = image_seq;
+                       si->image_seq_set = 1;
+               } else if (ubi->image_seq && ubi->image_seq != image_seq) {
+                       ubi_err("bad image sequence number %d in PEB %d, "
+                               "expected %d", image_seq, pnum, ubi->image_seq);
+                       ubi_dbg_dump_ec_hdr(ech);
+                       return -EINVAL;
+               }
+
        }
 
        /* OK, we've done with the EC header, let's look at the VID header */
index 61df208e2f2077de860db28494e8639349368111..1017cf12def56253606168e3c2ad18af674b8eae 100644 (file)
@@ -102,6 +102,7 @@ struct ubi_scan_volume {
  * @mean_ec: mean erase counter value
  * @ec_sum: a temporary variable used when calculating @mean_ec
  * @ec_count: a temporary variable used when calculating @mean_ec
+ * @image_seq_set: indicates @ubi->image_seq is known
  *
  * This data structure contains the result of scanning and may be used by other
  * UBI sub-systems to build final UBI data structures, further error-recovery
@@ -124,6 +125,7 @@ struct ubi_scan_info {
        int mean_ec;
        uint64_t ec_sum;
        int ec_count;
+       int image_seq_set;
 };
 
 struct ubi_device;
index 8419fdccc79cbcbdadb639b8188c65eab18bd468..503ea9b273094670d0933baafbfbfb04ae6d88cd 100644 (file)
@@ -129,6 +129,7 @@ enum {
  * @ec: the erase counter
  * @vid_hdr_offset: where the VID header starts
  * @data_offset: where the user data start
+ * @image_seq: image sequence number
  * @padding2: reserved for future, zeroes
  * @hdr_crc: erase counter header CRC checksum
  *
@@ -144,6 +145,14 @@ enum {
  * volume identifier header and user data, relative to the beginning of the
  * physical eraseblock. These values have to be the same for all physical
  * eraseblocks.
+ *
+ * The @image_seq field is used to validate a UBI image that has been prepared
+ * for a UBI device. The @image_seq value can be any value, but it must be the
+ * same on all eraseblocks. UBI will ensure that all new erase counter headers
+ * also contain this value, and will check the value when scanning at start-up.
+ * One way to make use of @image_seq is to increase its value by one every time
+ * an image is flashed over an existing image, then, if the flashing does not
+ * complete, UBI will detect the error when scanning.
  */
 struct ubi_ec_hdr {
        __be32  magic;
@@ -152,7 +161,8 @@ struct ubi_ec_hdr {
        __be64  ec; /* Warning: the current limit is 31-bit anyway! */
        __be32  vid_hdr_offset;
        __be32  data_offset;
-       __u8    padding2[36];
+       __be32  image_seq;
+       __u8    padding2[32];
        __be32  hdr_crc;
 } __attribute__ ((packed));
 
index 28acd133c997987eedefe9c926313a4dd207ffb9..6a5fe963378367ab48f871cbd6893d56d4ed454e 100644 (file)
@@ -301,6 +301,7 @@ struct ubi_wl_entry;
  *                @vol->readers, @vol->writers, @vol->exclusive,
  *                @vol->ref_count, @vol->mapping and @vol->eba_tbl.
  * @ref_count: count of references on the UBI device
+ * @image_seq: image sequence number recorded on EC headers
  *
  * @rsvd_pebs: count of reserved physical eraseblocks
  * @avail_pebs: count of available physical eraseblocks
@@ -372,6 +373,7 @@ struct ubi_wl_entry;
  * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset
  * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or
  *               not
+ * @nor_flash: non-zero if working on top of NOR flash
  * @mtd: MTD device descriptor
  *
  * @peb_buf1: a buffer of PEB size used for different purposes
@@ -390,6 +392,7 @@ struct ubi_device {
        struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT];
        spinlock_t volumes_lock;
        int ref_count;
+       int image_seq;
 
        int rsvd_pebs;
        int avail_pebs;
@@ -452,7 +455,8 @@ struct ubi_device {
        int vid_hdr_offset;
        int vid_hdr_aloffset;
        int vid_hdr_shift;
-       int bad_allowed;
+       unsigned int bad_allowed:1;
+       unsigned int nor_flash:1;
        struct mtd_info *mtd;
 
        void *peb_buf1;
index 2b2472300610f166eb897a53647436f4307c9456..600c7229d5cf21b0d959ca2d7c1a86ccc676e4af 100644 (file)
@@ -459,6 +459,14 @@ retry:
        dbg_wl("PEB %d EC %d", e->pnum, e->ec);
        prot_queue_add(ubi, e);
        spin_unlock(&ubi->wl_lock);
+
+       err = ubi_dbg_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
+                                  ubi->peb_size - ubi->vid_hdr_aloffset);
+       if (err) {
+               ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum);
+               return err > 0 ? -EINVAL : err;
+       }
+
        return e->pnum;
 }
 
index 3e00fa8ea65f106544c7a5f67a4c6535d499c690..4a7c32895be52fecbd2ce7ae87d75b639b4dc15a 100644 (file)
@@ -832,7 +832,9 @@ static int corkscrew_open(struct net_device *dev)
                        skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
                        vp->rx_ring[i].addr = isa_virt_to_bus(skb->data);
                }
-               vp->rx_ring[i - 1].next = isa_virt_to_bus(&vp->rx_ring[0]);     /* Wrap the ring. */
+               if (i != 0)
+                       vp->rx_ring[i - 1].next =
+                               isa_virt_to_bus(&vp->rx_ring[0]);       /* Wrap the ring. */
                outl(isa_virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
        }
        if (vp->full_bus_master_tx) {   /* Boomerang bus master Tx. */
index c34aee91250b031176b3028563498ae62e0c0d1a..45675889850b419201314f3ed5c7edb16cda0315 100644 (file)
@@ -235,6 +235,7 @@ enum vortex_chips {
        CH_3C900B_FL,
        CH_3C905_1,
        CH_3C905_2,
+       CH_3C905B_TX,
        CH_3C905B_1,
 
        CH_3C905B_2,
@@ -307,6 +308,8 @@ static struct vortex_chip_info {
         PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
        {"3c905 Boomerang 100baseT4",
         PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
+       {"3C905B-TX Fast Etherlink XL PCI",
+        PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
        {"3c905B Cyclone 100baseTx",
         PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
 
@@ -389,6 +392,7 @@ static struct pci_device_id vortex_pci_tbl[] = {
        { 0x10B7, 0x900A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900B_FL },
        { 0x10B7, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_1 },
        { 0x10B7, 0x9051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_2 },
+       { 0x10B7, 0x9054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_TX },
        { 0x10B7, 0x9055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_1 },
 
        { 0x10B7, 0x9058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_2 },
@@ -2721,13 +2725,15 @@ dump_tx_ring(struct net_device *dev)
                                   &vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);
                        issue_and_wait(dev, DownStall);
                        for (i = 0; i < TX_RING_SIZE; i++) {
-                               pr_err("  %d: @%p  length %8.8x status %8.8x\n", i,
-                                          &vp->tx_ring[i],
+                               unsigned int length;
+
 #if DO_ZEROCOPY
-                                          le32_to_cpu(vp->tx_ring[i].frag[0].length),
+                               length = le32_to_cpu(vp->tx_ring[i].frag[0].length);
 #else
-                                          le32_to_cpu(vp->tx_ring[i].length),
+                               length = le32_to_cpu(vp->tx_ring[i].length);
 #endif
+                               pr_err("  %d: @%p  length %8.8x status %8.8x\n",
+                                          i, &vp->tx_ring[i], length,
                                           le32_to_cpu(vp->tx_ring[i].status));
                        }
                        if (!stalled)
index 50efde11ea6c8790e8f0e679d9faaeb15e40f6f6..d0dbbf39349a3cb87d6eb19c51591bb736c9b9f5 100644 (file)
@@ -515,7 +515,7 @@ rx_status_loop:
                dma_addr_t mapping;
                struct sk_buff *skb, *new_skb;
                struct cp_desc *desc;
-               unsigned buflen;
+               const unsigned buflen = cp->rx_buf_sz;
 
                skb = cp->rx_skb[rx_tail];
                BUG_ON(!skb);
@@ -549,8 +549,7 @@ rx_status_loop:
                        pr_debug("%s: rx slot %d status 0x%x len %d\n",
                               dev->name, rx_tail, status, len);
 
-               buflen = cp->rx_buf_sz + NET_IP_ALIGN;
-               new_skb = netdev_alloc_skb(dev, buflen);
+               new_skb = netdev_alloc_skb(dev, buflen + NET_IP_ALIGN);
                if (!new_skb) {
                        dev->stats.rx_dropped++;
                        goto rx_next;
index 8ae72ec14456d4dc2e31141777a1bf35776fc78a..0e2ba21d4441810a279432229d7d078ef3e65bdd 100644 (file)
@@ -908,6 +908,7 @@ static const struct net_device_ops rtl8139_netdev_ops = {
        .ndo_open               = rtl8139_open,
        .ndo_stop               = rtl8139_close,
        .ndo_get_stats          = rtl8139_get_stats,
+       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = rtl8139_set_mac_address,
        .ndo_start_xmit         = rtl8139_start_xmit,
index c155bd3ec9f1a47640d4706626f544afe2e335bb..5ce7cbabd7a786cb6297617f765064672a68a918 100644 (file)
@@ -1727,7 +1727,16 @@ config KS8842
        tristate "Micrel KSZ8842"
        depends on HAS_IOMEM
        help
-         This platform driver is for Micrel KSZ8842 chip.
+         This platform driver is for Micrel KSZ8842 / KS8842
+         2-port ethernet switch chip (managed, VLAN, QoS).
+
+config KS8851
+       tristate "Micrel KS8851 SPI"
+       depends on SPI
+       select MII
+       select CRC32
+       help
+         SPI driver for Micrel KS8851 SPI attached network chip.
 
 config VIA_RHINE
        tristate "VIA Rhine support"
index 4b58a59f211b4e329e791ae3bf881a7f9edf7a81..ead8cab3cfe1d464dd0294949efaf1f02ec4d3be 100644 (file)
@@ -88,6 +88,7 @@ obj-$(CONFIG_SKGE) += skge.o
 obj-$(CONFIG_SKY2) += sky2.o
 obj-$(CONFIG_SKFP) += skfp/
 obj-$(CONFIG_KS8842)   += ks8842.o
+obj-$(CONFIG_KS8851)   += ks8851.o
 obj-$(CONFIG_VIA_RHINE) += via-rhine.o
 obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o
 obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
index 85a18175730ba249ab36c5985a654e34df1eb05c..08787f5a22a3dee8f9b10799332333cd3a398089 100644 (file)
@@ -569,16 +569,8 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
 
 #ifdef DEBUG_DRIVER
        /* dump the packet */
-       {
-               int i;
-
-               for (i = 0; i < 64; i++) {
-                       if ((i % 16) == 0)
-                               printk("\n" KERN_DEBUG);
-                       printk ("%2.2x ", skb->data [i]);
-               }
-               printk("\n");
-       }
+       print_hex_dump(KERN_DEBUG, "skb->data: ", DUMP_PREFIX_NONE,
+                      16, 1, skb->data, 64, true);
 #endif
        entry = lp->tx_new & lp->tx_ring_mod_mask;
        ib->btx_ring [entry].length = (-skblen) | 0xf000;
index d6d4ab3b430ccf77a25fe865384f3daaa8b6b7b4..7d227cdab9f8c5617ca2855303f4118ca0fc6fcb 100644 (file)
@@ -158,15 +158,12 @@ module_exit(arcnet_exit);
 void arcnet_dump_skb(struct net_device *dev,
                     struct sk_buff *skb, char *desc)
 {
-       int i;
+       char hdr[32];
 
-       printk(KERN_DEBUG "%6s: skb dump (%s) follows:", dev->name, desc);
-       for (i = 0; i < skb->len; i++) {
-               if (i % 16 == 0)
-                       printk("\n" KERN_DEBUG "[%04X] ", i);
-               printk("%02X ", ((u_char *) skb->data)[i]);
-       }
-       printk("\n");
+       /* dump the packet */
+       snprintf(hdr, sizeof(hdr), "%6s:%s skb->data:", dev->name, desc);
+       print_hex_dump(KERN_DEBUG, hdr, DUMP_PREFIX_OFFSET,
+                      16, 1, skb->data, skb->len, true);
 }
 
 EXPORT_SYMBOL(arcnet_dump_skb);
@@ -184,6 +181,7 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum,
        int i, length;
        unsigned long flags = 0;
        static uint8_t buf[512];
+       char hdr[32];
 
        /* hw.copy_from_card expects IRQ context so take the IRQ lock
           to keep it single threaded */
@@ -197,14 +195,10 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum,
        /* if the offset[0] byte is nonzero, this is a 256-byte packet */
        length = (buf[2] ? 256 : 512);
 
-       printk(KERN_DEBUG "%6s: packet dump (%s) follows:", dev->name, desc);
-       for (i = 0; i < length; i++) {
-               if (i % 16 == 0)
-                       printk("\n" KERN_DEBUG "[%04X] ", i);
-               printk("%02X ", buf[i]);
-       }
-       printk("\n");
-
+       /* dump the packet */
+       snprintf(hdr, sizeof(hdr), "%6s:%s packet dump:", dev->name, desc);
+       print_hex_dump(KERN_DEBUG, hdr, DUMP_PREFIX_OFFSET,
+                      16, 1, buf, length, true);
 }
 
 #else
index 2895db13bfa4459cebc86b89c2e7dc1fc5971495..c37ee9e6b67b93c989de07689c0c47bad7150d50 100644 (file)
@@ -63,3 +63,11 @@ config IXP4XX_ETH
        help
          Say Y here if you want to use built-in Ethernet ports
          on IXP4xx processor.
+
+config W90P910_ETH
+       tristate "Nuvoton w90p910 Ethernet support"
+       depends on ARM && ARCH_W90X900
+       select PHYLIB
+       help
+         Say Y here if you want to use built-in Ethernet ports
+         on w90p910 processor.
index 811a3ccd14c107c56136af8884022f7cd9f4498f..303171f589e61f2379587f9d13ddbc4b416263e6 100644 (file)
@@ -11,3 +11,4 @@ obj-$(CONFIG_ARM_AT91_ETHER)  += at91_ether.o
 obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o
 obj-$(CONFIG_EP93XX_ETH)       += ep93xx_eth.o
 obj-$(CONFIG_IXP4XX_ETH)       += ixp4xx_eth.o
+obj-$(CONFIG_W90P910_ETH)      += w90p910_ether.o
index 2e7419a6119181b29538720114e59b74bf15c578..5041d10bae9d9611c280ad50b17068349e9decd9 100644 (file)
@@ -1228,7 +1228,6 @@ static int at91ether_resume(struct platform_device *pdev)
 #endif
 
 static struct platform_driver at91ether_driver = {
-       .probe          = at91ether_probe,
        .remove         = __devexit_p(at91ether_remove),
        .suspend        = at91ether_suspend,
        .resume         = at91ether_resume,
@@ -1240,7 +1239,7 @@ static struct platform_driver at91ether_driver = {
 
 static int __init at91ether_init(void)
 {
-       return platform_driver_register(&at91ether_driver);
+       return platform_driver_probe(&at91ether_driver, at91ether_probe);
 }
 
 static void __exit at91ether_exit(void)
index 6f42ad728915b2683ee9ee66a9e11562c890453e..3fe09876e76d3f5c62e0878adf7545317760a2c3 100644 (file)
@@ -1142,7 +1142,9 @@ static const struct net_device_ops ixp4xx_netdev_ops = {
        .ndo_start_xmit = eth_xmit,
        .ndo_set_multicast_list = eth_set_mcast_list,
        .ndo_do_ioctl = eth_ioctl,
-
+       .ndo_change_mtu = eth_change_mtu,
+       .ndo_set_mac_address = eth_mac_addr,
+       .ndo_validate_addr = eth_validate_addr,
 };
 
 static int __devinit eth_init_one(struct platform_device *pdev)
diff --git a/drivers/net/arm/w90p910_ether.c b/drivers/net/arm/w90p910_ether.c
new file mode 100644 (file)
index 0000000..ddd231c
--- /dev/null
@@ -0,0 +1,1105 @@
+/*
+ * Copyright (c) 2008-2009 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@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;version 2 of the License.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mii.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#define DRV_MODULE_NAME                "w90p910-emc"
+#define DRV_MODULE_VERSION     "0.1"
+
+/* Ethernet MAC Registers */
+#define REG_CAMCMR             0x00
+#define REG_CAMEN              0x04
+#define REG_CAMM_BASE          0x08
+#define REG_CAML_BASE          0x0c
+#define REG_TXDLSA             0x88
+#define REG_RXDLSA             0x8C
+#define REG_MCMDR              0x90
+#define REG_MIID               0x94
+#define REG_MIIDA              0x98
+#define REG_FFTCR              0x9C
+#define REG_TSDR               0xa0
+#define REG_RSDR               0xa4
+#define REG_DMARFC             0xa8
+#define REG_MIEN               0xac
+#define REG_MISTA              0xb0
+#define REG_CTXDSA             0xcc
+#define REG_CTXBSA             0xd0
+#define REG_CRXDSA             0xd4
+#define REG_CRXBSA             0xd8
+
+/* mac controller bit */
+#define MCMDR_RXON             0x01
+#define MCMDR_ACP              (0x01 << 3)
+#define MCMDR_SPCRC            (0x01 << 5)
+#define MCMDR_TXON             (0x01 << 8)
+#define MCMDR_FDUP             (0x01 << 18)
+#define MCMDR_ENMDC            (0x01 << 19)
+#define MCMDR_OPMOD            (0x01 << 20)
+#define SWR                    (0x01 << 24)
+
+/* cam command regiser */
+#define CAMCMR_AUP             0x01
+#define CAMCMR_AMP             (0x01 << 1)
+#define CAMCMR_ABP             (0x01 << 2)
+#define CAMCMR_CCAM            (0x01 << 3)
+#define CAMCMR_ECMP            (0x01 << 4)
+#define CAM0EN                 0x01
+
+/* mac mii controller bit */
+#define MDCCR                  (0x0a << 20)
+#define PHYAD                  (0x01 << 8)
+#define PHYWR                  (0x01 << 16)
+#define PHYBUSY                        (0x01 << 17)
+#define PHYPRESP               (0x01 << 18)
+#define CAM_ENTRY_SIZE         0x08
+
+/* rx and tx status */
+#define TXDS_TXCP              (0x01 << 19)
+#define RXDS_CRCE              (0x01 << 17)
+#define RXDS_PTLE              (0x01 << 19)
+#define RXDS_RXGD              (0x01 << 20)
+#define RXDS_ALIE              (0x01 << 21)
+#define RXDS_RP                        (0x01 << 22)
+
+/* mac interrupt status*/
+#define MISTA_EXDEF            (0x01 << 19)
+#define MISTA_TXBERR           (0x01 << 24)
+#define MISTA_TDU              (0x01 << 23)
+#define MISTA_RDU              (0x01 << 10)
+#define MISTA_RXBERR           (0x01 << 11)
+
+#define ENSTART                        0x01
+#define ENRXINTR               0x01
+#define ENRXGD                 (0x01 << 4)
+#define ENRXBERR               (0x01 << 11)
+#define ENTXINTR               (0x01 << 16)
+#define ENTXCP                 (0x01 << 18)
+#define ENTXABT                        (0x01 << 21)
+#define ENTXBERR               (0x01 << 24)
+#define ENMDC                  (0x01 << 19)
+#define PHYBUSY                        (0x01 << 17)
+#define MDCCR_VAL              0xa00000
+
+/* rx and tx owner bit */
+#define RX_OWEN_DMA            (0x01 << 31)
+#define RX_OWEN_CPU            (~(0x03 << 30))
+#define TX_OWEN_DMA            (0x01 << 31)
+#define TX_OWEN_CPU            (~(0x01 << 31))
+
+/* tx frame desc controller bit */
+#define MACTXINTEN             0x04
+#define CRCMODE                        0x02
+#define PADDINGMODE            0x01
+
+/* fftcr controller bit */
+#define TXTHD                  (0x03 << 8)
+#define BLENGTH                        (0x01 << 20)
+
+/* global setting for driver */
+#define RX_DESC_SIZE           50
+#define TX_DESC_SIZE           10
+#define MAX_RBUFF_SZ           0x600
+#define MAX_TBUFF_SZ           0x600
+#define TX_TIMEOUT             50
+#define DELAY                  1000
+#define CAM0                   0x0
+
+static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg);
+
+struct w90p910_rxbd {
+       unsigned int sl;
+       unsigned int buffer;
+       unsigned int reserved;
+       unsigned int next;
+};
+
+struct w90p910_txbd {
+       unsigned int mode;
+       unsigned int buffer;
+       unsigned int sl;
+       unsigned int next;
+};
+
+struct recv_pdesc {
+       struct w90p910_rxbd desclist[RX_DESC_SIZE];
+       char recv_buf[RX_DESC_SIZE][MAX_RBUFF_SZ];
+};
+
+struct tran_pdesc {
+       struct w90p910_txbd desclist[TX_DESC_SIZE];
+       char tran_buf[RX_DESC_SIZE][MAX_TBUFF_SZ];
+};
+
+struct  w90p910_ether {
+       struct recv_pdesc *rdesc;
+       struct recv_pdesc *rdesc_phys;
+       struct tran_pdesc *tdesc;
+       struct tran_pdesc *tdesc_phys;
+       struct net_device_stats stats;
+       struct platform_device *pdev;
+       struct sk_buff *skb;
+       struct clk *clk;
+       struct clk *rmiiclk;
+       struct mii_if_info mii;
+       struct timer_list check_timer;
+       void __iomem *reg;
+       unsigned int rxirq;
+       unsigned int txirq;
+       unsigned int cur_tx;
+       unsigned int cur_rx;
+       unsigned int finish_tx;
+       unsigned int rx_packets;
+       unsigned int rx_bytes;
+       unsigned int start_tx_ptr;
+       unsigned int start_rx_ptr;
+       unsigned int linkflag;
+       spinlock_t lock;
+};
+
+static void update_linkspeed_register(struct net_device *dev,
+                               unsigned int speed, unsigned int duplex)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = __raw_readl(ether->reg + REG_MCMDR);
+
+       if (speed == SPEED_100) {
+               /* 100 full/half duplex */
+               if (duplex == DUPLEX_FULL) {
+                       val |= (MCMDR_OPMOD | MCMDR_FDUP);
+               } else {
+                       val |= MCMDR_OPMOD;
+                       val &= ~MCMDR_FDUP;
+               }
+       } else {
+               /* 10 full/half duplex */
+               if (duplex == DUPLEX_FULL) {
+                       val |= MCMDR_FDUP;
+                       val &= ~MCMDR_OPMOD;
+               } else {
+                       val &= ~(MCMDR_FDUP | MCMDR_OPMOD);
+               }
+       }
+
+       __raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void update_linkspeed(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       struct platform_device *pdev;
+       unsigned int bmsr, bmcr, lpa, speed, duplex;
+
+       pdev = ether->pdev;
+
+       if (!mii_link_ok(&ether->mii)) {
+               ether->linkflag = 0x0;
+               netif_carrier_off(dev);
+               dev_warn(&pdev->dev, "%s: Link down.\n", dev->name);
+               return;
+       }
+
+       if (ether->linkflag == 1)
+               return;
+
+       bmsr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMSR);
+       bmcr = w90p910_mdio_read(dev, ether->mii.phy_id, MII_BMCR);
+
+       if (bmcr & BMCR_ANENABLE) {
+               if (!(bmsr & BMSR_ANEGCOMPLETE))
+                       return;
+
+               lpa = w90p910_mdio_read(dev, ether->mii.phy_id, MII_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_linkspeed_register(dev, speed, duplex);
+
+       dev_info(&pdev->dev, "%s: Link now %i-%s\n", dev->name, speed,
+                       (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
+       ether->linkflag = 0x01;
+
+       netif_carrier_on(dev);
+}
+
+static void w90p910_check_link(unsigned long dev_id)
+{
+       struct net_device *dev = (struct net_device *) dev_id;
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       update_linkspeed(dev);
+       mod_timer(&ether->check_timer, jiffies + msecs_to_jiffies(1000));
+}
+
+static void w90p910_write_cam(struct net_device *dev,
+                               unsigned int x, unsigned char *pval)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int msw, lsw;
+
+       msw = (pval[0] << 24) | (pval[1] << 16) | (pval[2] << 8) | pval[3];
+
+       lsw = (pval[4] << 24) | (pval[5] << 16);
+
+       __raw_writel(lsw, ether->reg + REG_CAML_BASE + x * CAM_ENTRY_SIZE);
+       __raw_writel(msw, ether->reg + REG_CAMM_BASE + x * CAM_ENTRY_SIZE);
+}
+
+static void w90p910_init_desc(struct net_device *dev)
+{
+       struct w90p910_ether *ether;
+       struct w90p910_txbd  *tdesc, *tdesc_phys;
+       struct w90p910_rxbd  *rdesc, *rdesc_phys;
+       unsigned int i, j;
+
+       ether = netdev_priv(dev);
+
+       ether->tdesc = (struct tran_pdesc *)
+                       dma_alloc_coherent(NULL, sizeof(struct tran_pdesc),
+                               (dma_addr_t *) &ether->tdesc_phys, GFP_KERNEL);
+
+       ether->rdesc = (struct recv_pdesc *)
+                       dma_alloc_coherent(NULL, sizeof(struct recv_pdesc),
+                               (dma_addr_t *) &ether->rdesc_phys, GFP_KERNEL);
+
+       for (i = 0; i < TX_DESC_SIZE; i++) {
+               tdesc = &(ether->tdesc->desclist[i]);
+
+               j = ((i + 1) / TX_DESC_SIZE);
+
+               if (j != 0) {
+                       tdesc_phys = &(ether->tdesc_phys->desclist[0]);
+                       ether->start_tx_ptr = (unsigned int)tdesc_phys;
+                       tdesc->next = (unsigned int)ether->start_tx_ptr;
+               } else {
+                       tdesc_phys = &(ether->tdesc_phys->desclist[i+1]);
+                       tdesc->next = (unsigned int)tdesc_phys;
+               }
+
+               tdesc->buffer = (unsigned int)ether->tdesc_phys->tran_buf[i];
+               tdesc->sl = 0;
+               tdesc->mode = 0;
+       }
+
+       for (i = 0; i < RX_DESC_SIZE; i++) {
+               rdesc = &(ether->rdesc->desclist[i]);
+
+               j = ((i + 1) / RX_DESC_SIZE);
+
+               if (j != 0) {
+                       rdesc_phys = &(ether->rdesc_phys->desclist[0]);
+                       ether->start_rx_ptr = (unsigned int)rdesc_phys;
+                       rdesc->next = (unsigned int)ether->start_rx_ptr;
+               } else {
+                       rdesc_phys = &(ether->rdesc_phys->desclist[i+1]);
+                       rdesc->next = (unsigned int)rdesc_phys;
+               }
+
+               rdesc->sl = RX_OWEN_DMA;
+               rdesc->buffer = (unsigned int)ether->rdesc_phys->recv_buf[i];
+         }
+}
+
+static void w90p910_set_fifo_threshold(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = TXTHD | BLENGTH;
+       __raw_writel(val, ether->reg + REG_FFTCR);
+}
+
+static void w90p910_return_default_idle(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = __raw_readl(ether->reg + REG_MCMDR);
+       val |= SWR;
+       __raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void w90p910_trigger_rx(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       __raw_writel(ENSTART, ether->reg + REG_RSDR);
+}
+
+static void w90p910_trigger_tx(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       __raw_writel(ENSTART, ether->reg + REG_TSDR);
+}
+
+static void w90p910_enable_mac_interrupt(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = ENTXINTR | ENRXINTR | ENRXGD | ENTXCP;
+       val |= ENTXBERR | ENRXBERR | ENTXABT;
+
+       __raw_writel(val, ether->reg + REG_MIEN);
+}
+
+static void w90p910_get_and_clear_int(struct net_device *dev,
+                                                       unsigned int *val)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       *val = __raw_readl(ether->reg + REG_MISTA);
+       __raw_writel(*val, ether->reg + REG_MISTA);
+}
+
+static void w90p910_set_global_maccmd(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = __raw_readl(ether->reg + REG_MCMDR);
+       val |= MCMDR_SPCRC | MCMDR_ENMDC | MCMDR_ACP | ENMDC;
+       __raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void w90p910_enable_cam(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       w90p910_write_cam(dev, CAM0, dev->dev_addr);
+
+       val = __raw_readl(ether->reg + REG_CAMEN);
+       val |= CAM0EN;
+       __raw_writel(val, ether->reg + REG_CAMEN);
+}
+
+static void w90p910_enable_cam_command(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = CAMCMR_ECMP | CAMCMR_ABP | CAMCMR_AMP;
+       __raw_writel(val, ether->reg + REG_CAMCMR);
+}
+
+static void w90p910_enable_tx(struct net_device *dev, unsigned int enable)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = __raw_readl(ether->reg + REG_MCMDR);
+
+       if (enable)
+               val |= MCMDR_TXON;
+       else
+               val &= ~MCMDR_TXON;
+
+       __raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void w90p910_enable_rx(struct net_device *dev, unsigned int enable)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       unsigned int val;
+
+       val = __raw_readl(ether->reg + REG_MCMDR);
+
+       if (enable)
+               val |= MCMDR_RXON;
+       else
+               val &= ~MCMDR_RXON;
+
+       __raw_writel(val, ether->reg + REG_MCMDR);
+}
+
+static void w90p910_set_curdest(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       __raw_writel(ether->start_rx_ptr, ether->reg + REG_RXDLSA);
+       __raw_writel(ether->start_tx_ptr, ether->reg + REG_TXDLSA);
+}
+
+static void w90p910_reset_mac(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       spin_lock(&ether->lock);
+
+       w90p910_enable_tx(dev, 0);
+       w90p910_enable_rx(dev, 0);
+       w90p910_set_fifo_threshold(dev);
+       w90p910_return_default_idle(dev);
+
+       if (!netif_queue_stopped(dev))
+               netif_stop_queue(dev);
+
+       w90p910_init_desc(dev);
+
+       dev->trans_start = jiffies;
+       ether->cur_tx = 0x0;
+       ether->finish_tx = 0x0;
+       ether->cur_rx = 0x0;
+
+       w90p910_set_curdest(dev);
+       w90p910_enable_cam(dev);
+       w90p910_enable_cam_command(dev);
+       w90p910_enable_mac_interrupt(dev);
+       w90p910_enable_tx(dev, 1);
+       w90p910_enable_rx(dev, 1);
+       w90p910_trigger_tx(dev);
+       w90p910_trigger_rx(dev);
+
+       dev->trans_start = jiffies;
+
+       if (netif_queue_stopped(dev))
+               netif_wake_queue(dev);
+
+       spin_unlock(&ether->lock);
+}
+
+static void w90p910_mdio_write(struct net_device *dev,
+                                       int phy_id, int reg, int data)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       struct platform_device *pdev;
+       unsigned int val, i;
+
+       pdev = ether->pdev;
+
+       __raw_writel(data, ether->reg + REG_MIID);
+
+       val = (phy_id << 0x08) | reg;
+       val |= PHYBUSY | PHYWR | MDCCR_VAL;
+       __raw_writel(val, ether->reg + REG_MIIDA);
+
+       for (i = 0; i < DELAY; i++) {
+               if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0)
+                       break;
+       }
+
+       if (i == DELAY)
+               dev_warn(&pdev->dev, "mdio write timed out\n");
+}
+
+static int w90p910_mdio_read(struct net_device *dev, int phy_id, int reg)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       struct platform_device *pdev;
+       unsigned int val, i, data;
+
+       pdev = ether->pdev;
+
+       val = (phy_id << 0x08) | reg;
+       val |= PHYBUSY | MDCCR_VAL;
+       __raw_writel(val, ether->reg + REG_MIIDA);
+
+       for (i = 0; i < DELAY; i++) {
+               if ((__raw_readl(ether->reg + REG_MIIDA) & PHYBUSY) == 0)
+                       break;
+       }
+
+       if (i == DELAY) {
+               dev_warn(&pdev->dev, "mdio read timed out\n");
+               data = 0xffff;
+       } else {
+               data = __raw_readl(ether->reg + REG_MIID);
+       }
+
+       return data;
+}
+
+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);
+       w90p910_write_cam(dev, CAM0, dev->dev_addr);
+
+       return 0;
+}
+
+static int w90p910_ether_close(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       dma_free_writecombine(NULL, sizeof(struct w90p910_rxbd),
+                               ether->rdesc, (dma_addr_t)ether->rdesc_phys);
+       dma_free_writecombine(NULL, sizeof(struct w90p910_txbd),
+                               ether->tdesc, (dma_addr_t)ether->tdesc_phys);
+
+       netif_stop_queue(dev);
+
+       del_timer_sync(&ether->check_timer);
+       clk_disable(ether->rmiiclk);
+       clk_disable(ether->clk);
+
+       free_irq(ether->txirq, dev);
+       free_irq(ether->rxirq, dev);
+
+       return 0;
+}
+
+static struct net_device_stats *w90p910_ether_stats(struct net_device *dev)
+{
+       struct w90p910_ether *ether;
+
+       ether = netdev_priv(dev);
+
+       return &ether->stats;
+}
+
+static int w90p910_send_frame(struct net_device *dev,
+                                       unsigned char *data, int length)
+{
+       struct w90p910_ether *ether;
+       struct w90p910_txbd *txbd;
+       struct platform_device *pdev;
+       unsigned char *buffer;
+
+       ether = netdev_priv(dev);
+       pdev = ether->pdev;
+
+       txbd = &ether->tdesc->desclist[ether->cur_tx];
+       buffer = ether->tdesc->tran_buf[ether->cur_tx];
+       if (length > 1514) {
+               dev_err(&pdev->dev, "send data %d bytes, check it\n", length);
+               length = 1514;
+       }
+
+       txbd->sl = length & 0xFFFF;
+
+       memcpy(buffer, data, length);
+
+       txbd->mode = TX_OWEN_DMA | PADDINGMODE | CRCMODE | MACTXINTEN;
+
+       w90p910_enable_tx(dev, 1);
+
+       w90p910_trigger_tx(dev);
+
+       ether->cur_tx = (ether->cur_tx+1) % TX_DESC_SIZE;
+       txbd = &ether->tdesc->desclist[ether->cur_tx];
+
+       dev->trans_start = jiffies;
+
+       if (txbd->mode & TX_OWEN_DMA)
+               netif_stop_queue(dev);
+
+       return 0;
+}
+
+static int w90p910_ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       if (!(w90p910_send_frame(dev, skb->data, skb->len))) {
+               ether->skb = skb;
+               dev_kfree_skb_irq(skb);
+               return 0;
+       }
+       return -1;
+}
+
+static irqreturn_t w90p910_tx_interrupt(int irq, void *dev_id)
+{
+       struct w90p910_ether *ether;
+       struct w90p910_txbd  *txbd;
+       struct platform_device *pdev;
+       struct tran_pdesc *tran_pdesc;
+       struct net_device *dev;
+       unsigned int cur_entry, entry, status;
+
+       dev = (struct net_device *)dev_id;
+       ether = netdev_priv(dev);
+       pdev = ether->pdev;
+
+       spin_lock(&ether->lock);
+
+       w90p910_get_and_clear_int(dev, &status);
+
+       cur_entry = __raw_readl(ether->reg + REG_CTXDSA);
+
+       tran_pdesc = ether->tdesc_phys;
+       entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]);
+
+       while (entry != cur_entry) {
+               txbd = &ether->tdesc->desclist[ether->finish_tx];
+
+               ether->finish_tx = (ether->finish_tx + 1) % TX_DESC_SIZE;
+
+               if (txbd->sl & TXDS_TXCP) {
+                       ether->stats.tx_packets++;
+                       ether->stats.tx_bytes += txbd->sl & 0xFFFF;
+               } else {
+                       ether->stats.tx_errors++;
+               }
+
+               txbd->sl = 0x0;
+               txbd->mode = 0x0;
+
+               if (netif_queue_stopped(dev))
+                       netif_wake_queue(dev);
+
+               entry = (unsigned int)(&tran_pdesc->desclist[ether->finish_tx]);
+       }
+
+       if (status & MISTA_EXDEF) {
+               dev_err(&pdev->dev, "emc defer exceed interrupt\n");
+       } else if (status & MISTA_TXBERR) {
+                       dev_err(&pdev->dev, "emc bus error interrupt\n");
+                       w90p910_reset_mac(dev);
+               } else if (status & MISTA_TDU) {
+                               if (netif_queue_stopped(dev))
+                                       netif_wake_queue(dev);
+                       }
+
+       spin_unlock(&ether->lock);
+
+       return IRQ_HANDLED;
+}
+
+static void netdev_rx(struct net_device *dev)
+{
+       struct w90p910_ether *ether;
+       struct w90p910_rxbd *rxbd;
+       struct platform_device *pdev;
+       struct recv_pdesc *rdesc_phys;
+       struct sk_buff *skb;
+       unsigned char *data;
+       unsigned int length, status, val, entry;
+
+       ether = netdev_priv(dev);
+       pdev = ether->pdev;
+       rdesc_phys = ether->rdesc_phys;
+
+       rxbd = &ether->rdesc->desclist[ether->cur_rx];
+
+       do {
+               val = __raw_readl(ether->reg + REG_CRXDSA);
+               entry = (unsigned int)&rdesc_phys->desclist[ether->cur_rx];
+
+               if (val == entry)
+                       break;
+
+               status = rxbd->sl;
+               length = status & 0xFFFF;
+
+               if (status & RXDS_RXGD) {
+                       data = ether->rdesc->recv_buf[ether->cur_rx];
+                       skb = dev_alloc_skb(length+2);
+                       if (!skb) {
+                               dev_err(&pdev->dev, "get skb buffer error\n");
+                               ether->stats.rx_dropped++;
+                               return;
+                       }
+
+                       skb->dev = dev;
+                       skb_reserve(skb, 2);
+                       skb_put(skb, length);
+                       skb_copy_to_linear_data(skb, data, length);
+                       skb->protocol = eth_type_trans(skb, dev);
+                       ether->stats.rx_packets++;
+                       ether->stats.rx_bytes += length;
+                       netif_rx(skb);
+               } else {
+                       ether->stats.rx_errors++;
+
+                       if (status & RXDS_RP) {
+                               dev_err(&pdev->dev, "rx runt err\n");
+                               ether->stats.rx_length_errors++;
+                       } else if (status & RXDS_CRCE) {
+                                       dev_err(&pdev->dev, "rx crc err\n");
+                                       ether->stats.rx_crc_errors++;
+                               }
+
+                       if (status & RXDS_ALIE) {
+                               dev_err(&pdev->dev, "rx aligment err\n");
+                               ether->stats.rx_frame_errors++;
+                       } else if (status & RXDS_PTLE) {
+                                       dev_err(&pdev->dev, "rx longer err\n");
+                                       ether->stats.rx_over_errors++;
+                               }
+                       }
+
+               rxbd->sl = RX_OWEN_DMA;
+               rxbd->reserved = 0x0;
+               ether->cur_rx = (ether->cur_rx+1) % RX_DESC_SIZE;
+               rxbd = &ether->rdesc->desclist[ether->cur_rx];
+
+               dev->last_rx = jiffies;
+       } while (1);
+}
+
+static irqreturn_t w90p910_rx_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev;
+       struct w90p910_ether  *ether;
+       struct platform_device *pdev;
+       unsigned int status;
+
+       dev = (struct net_device *)dev_id;
+       ether = netdev_priv(dev);
+       pdev = ether->pdev;
+
+       spin_lock(&ether->lock);
+
+       w90p910_get_and_clear_int(dev, &status);
+
+       if (status & MISTA_RDU) {
+               netdev_rx(dev);
+
+               w90p910_trigger_rx(dev);
+
+               spin_unlock(&ether->lock);
+               return IRQ_HANDLED;
+       } else if (status & MISTA_RXBERR) {
+                       dev_err(&pdev->dev, "emc rx bus error\n");
+                       w90p910_reset_mac(dev);
+               }
+
+       netdev_rx(dev);
+       spin_unlock(&ether->lock);
+       return IRQ_HANDLED;
+}
+
+static int w90p910_ether_open(struct net_device *dev)
+{
+       struct w90p910_ether *ether;
+       struct platform_device *pdev;
+
+       ether = netdev_priv(dev);
+       pdev = ether->pdev;
+
+       w90p910_reset_mac(dev);
+       w90p910_set_fifo_threshold(dev);
+       w90p910_set_curdest(dev);
+       w90p910_enable_cam(dev);
+       w90p910_enable_cam_command(dev);
+       w90p910_enable_mac_interrupt(dev);
+       w90p910_set_global_maccmd(dev);
+       w90p910_enable_rx(dev, 1);
+
+       ether->rx_packets = 0x0;
+       ether->rx_bytes = 0x0;
+
+       if (request_irq(ether->txirq, w90p910_tx_interrupt,
+                                               0x0, pdev->name, dev)) {
+               dev_err(&pdev->dev, "register irq tx failed\n");
+               return -EAGAIN;
+       }
+
+       if (request_irq(ether->rxirq, w90p910_rx_interrupt,
+                                               0x0, pdev->name, dev)) {
+               dev_err(&pdev->dev, "register irq rx failed\n");
+               return -EAGAIN;
+       }
+
+       mod_timer(&ether->check_timer, jiffies + msecs_to_jiffies(1000));
+       netif_start_queue(dev);
+       w90p910_trigger_rx(dev);
+
+       dev_info(&pdev->dev, "%s is OPENED\n", dev->name);
+
+       return 0;
+}
+
+static void w90p910_ether_set_multicast_list(struct net_device *dev)
+{
+       struct w90p910_ether *ether;
+       unsigned int rx_mode;
+
+       ether = netdev_priv(dev);
+
+       if (dev->flags & IFF_PROMISC)
+               rx_mode = CAMCMR_AUP | CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP;
+       else if ((dev->flags & IFF_ALLMULTI) || dev->mc_list)
+                       rx_mode = CAMCMR_AMP | CAMCMR_ABP | CAMCMR_ECMP;
+               else
+                               rx_mode = CAMCMR_ECMP | CAMCMR_ABP;
+       __raw_writel(rx_mode, ether->reg + REG_CAMCMR);
+}
+
+static int w90p910_ether_ioctl(struct net_device *dev,
+                                               struct ifreq *ifr, int cmd)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       struct mii_ioctl_data *data = if_mii(ifr);
+
+       return generic_mii_ioctl(&ether->mii, data, cmd, NULL);
+}
+
+static void w90p910_get_drvinfo(struct net_device *dev,
+                                       struct ethtool_drvinfo *info)
+{
+       strcpy(info->driver, DRV_MODULE_NAME);
+       strcpy(info->version, DRV_MODULE_VERSION);
+}
+
+static int w90p910_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       return mii_ethtool_gset(&ether->mii, cmd);
+}
+
+static int w90p910_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       return mii_ethtool_sset(&ether->mii, cmd);
+}
+
+static int w90p910_nway_reset(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       return mii_nway_restart(&ether->mii);
+}
+
+static u32 w90p910_get_link(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       return mii_link_ok(&ether->mii);
+}
+
+static const struct ethtool_ops w90p910_ether_ethtool_ops = {
+       .get_settings   = w90p910_get_settings,
+       .set_settings   = w90p910_set_settings,
+       .get_drvinfo    = w90p910_get_drvinfo,
+       .nway_reset     = w90p910_nway_reset,
+       .get_link       = w90p910_get_link,
+};
+
+static const struct net_device_ops w90p910_ether_netdev_ops = {
+       .ndo_open               = w90p910_ether_open,
+       .ndo_stop               = w90p910_ether_close,
+       .ndo_start_xmit         = w90p910_ether_start_xmit,
+       .ndo_get_stats          = w90p910_ether_stats,
+       .ndo_set_multicast_list = w90p910_ether_set_multicast_list,
+       .ndo_set_mac_address    = set_mac_address,
+       .ndo_do_ioctl           = w90p910_ether_ioctl,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+};
+
+static void __init get_mac_address(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+       struct platform_device *pdev;
+       char addr[6];
+
+       pdev = ether->pdev;
+
+       addr[0] = 0x00;
+       addr[1] = 0x02;
+       addr[2] = 0xac;
+       addr[3] = 0x55;
+       addr[4] = 0x88;
+       addr[5] = 0xa8;
+
+       if (is_valid_ether_addr(addr))
+               memcpy(dev->dev_addr, &addr, 0x06);
+       else
+               dev_err(&pdev->dev, "invalid mac address\n");
+}
+
+static int w90p910_ether_setup(struct net_device *dev)
+{
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       ether_setup(dev);
+       dev->netdev_ops = &w90p910_ether_netdev_ops;
+       dev->ethtool_ops = &w90p910_ether_ethtool_ops;
+
+       dev->tx_queue_len = 16;
+       dev->dma = 0x0;
+       dev->watchdog_timeo = TX_TIMEOUT;
+
+       get_mac_address(dev);
+
+       spin_lock_init(&ether->lock);
+
+       ether->cur_tx = 0x0;
+       ether->cur_rx = 0x0;
+       ether->finish_tx = 0x0;
+       ether->linkflag = 0x0;
+       ether->mii.phy_id = 0x01;
+       ether->mii.phy_id_mask = 0x1f;
+       ether->mii.reg_num_mask = 0x1f;
+       ether->mii.dev = dev;
+       ether->mii.mdio_read = w90p910_mdio_read;
+       ether->mii.mdio_write = w90p910_mdio_write;
+
+       setup_timer(&ether->check_timer, w90p910_check_link,
+                                               (unsigned long)dev);
+
+       return 0;
+}
+
+static int __devinit w90p910_ether_probe(struct platform_device *pdev)
+{
+       struct w90p910_ether *ether;
+       struct net_device *dev;
+       struct resource *res;
+       int error;
+
+       dev = alloc_etherdev(sizeof(struct w90p910_ether));
+       if (!dev)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to get I/O memory\n");
+               error = -ENXIO;
+               goto failed_free;
+       }
+
+       res = request_mem_region(res->start, resource_size(res), pdev->name);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to request I/O memory\n");
+               error = -EBUSY;
+               goto failed_free;
+       }
+
+       ether = netdev_priv(dev);
+
+       ether->reg = ioremap(res->start, resource_size(res));
+       if (ether->reg == NULL) {
+               dev_err(&pdev->dev, "failed to remap I/O memory\n");
+               error = -ENXIO;
+               goto failed_free_mem;
+       }
+
+       ether->txirq = platform_get_irq(pdev, 0);
+       if (ether->txirq < 0) {
+               dev_err(&pdev->dev, "failed to get ether tx irq\n");
+               error = -ENXIO;
+               goto failed_free_io;
+       }
+
+       ether->rxirq = platform_get_irq(pdev, 1);
+       if (ether->rxirq < 0) {
+               dev_err(&pdev->dev, "failed to get ether rx irq\n");
+               error = -ENXIO;
+               goto failed_free_txirq;
+       }
+
+       platform_set_drvdata(pdev, dev);
+
+       ether->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(ether->clk)) {
+               dev_err(&pdev->dev, "failed to get ether clock\n");
+               error = PTR_ERR(ether->clk);
+               goto failed_free_rxirq;
+       }
+
+       ether->rmiiclk = clk_get(&pdev->dev, "RMII");
+       if (IS_ERR(ether->rmiiclk)) {
+               dev_err(&pdev->dev, "failed to get ether clock\n");
+               error = PTR_ERR(ether->rmiiclk);
+               goto failed_put_clk;
+       }
+
+       ether->pdev = pdev;
+
+       w90p910_ether_setup(dev);
+
+       error = register_netdev(dev);
+       if (error != 0) {
+               dev_err(&pdev->dev, "Regiter EMC w90p910 FAILED\n");
+               error = -ENODEV;
+               goto failed_put_rmiiclk;
+       }
+
+       return 0;
+failed_put_rmiiclk:
+       clk_put(ether->rmiiclk);
+failed_put_clk:
+       clk_put(ether->clk);
+failed_free_rxirq:
+       free_irq(ether->rxirq, pdev);
+       platform_set_drvdata(pdev, NULL);
+failed_free_txirq:
+       free_irq(ether->txirq, pdev);
+failed_free_io:
+       iounmap(ether->reg);
+failed_free_mem:
+       release_mem_region(res->start, resource_size(res));
+failed_free:
+       free_netdev(dev);
+       return error;
+}
+
+static int __devexit w90p910_ether_remove(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+       struct w90p910_ether *ether = netdev_priv(dev);
+
+       unregister_netdev(dev);
+       clk_put(ether->rmiiclk);
+       clk_put(ether->clk);
+       del_timer_sync(&ether->check_timer);
+       platform_set_drvdata(pdev, NULL);
+       free_netdev(dev);
+       return 0;
+}
+
+static struct platform_driver w90p910_ether_driver = {
+       .probe          = w90p910_ether_probe,
+       .remove         = __devexit_p(w90p910_ether_remove),
+       .driver         = {
+               .name   = "nuc900-emc",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init w90p910_ether_init(void)
+{
+       return platform_driver_register(&w90p910_ether_driver);
+}
+
+static void __exit w90p910_ether_exit(void)
+{
+       platform_driver_unregister(&w90p910_ether_driver);
+}
+
+module_init(w90p910_ether_init);
+module_exit(w90p910_ether_exit);
+
+MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
+MODULE_DESCRIPTION("w90p910 MAC driver!");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:nuc900-emc");
+
index 18b566ad4fd17cedda3deff1fa2fefc45aa262a9..cf30e278f182f0a47e8b2770513994f2b9af77e1 100644 (file)
@@ -318,7 +318,7 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
                                pos3 = mca_read_stored_pos( slot, 3 );
                                pos4 = mca_read_stored_pos( slot, 4 );
 
-                               for (l_i = 0; l_i < 0x09; l_i++)
+                               for (l_i = 0; l_i < 8; l_i++)
                                        if (( pos3 & 0x07) == at1700_ioaddr_pattern[l_i])
                                                break;
                                ioaddr = at1700_mca_probe_list[l_i];
index e1658ef3fcdf04f0e75f71af8ddfae7e0113476a..2a1120ad2e74a4da9bf7186a0e7359d96a7e4ed3 100644 (file)
@@ -188,14 +188,14 @@ struct atl1c_tpd_ext_desc {
 #define RRS_HDS_TYPE_DATA      2
 
 #define RRS_IS_NO_HDS_TYPE(flag) \
-       (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == 0)
+       ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == 0)
 
 #define RRS_IS_HDS_HEAD(flag) \
-       (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \
+       ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \
                        RRS_HDS_TYPE_HEAD)
 
 #define RRS_IS_HDS_DATA(flag) \
-       (((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK == \
+       ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \
                        RRS_HDS_TYPE_DATA)
 
 /* rrs word 3 bit 0:31 */
@@ -245,7 +245,7 @@ struct atl1c_tpd_ext_desc {
 #define RRS_PACKET_TYPE_802_3          1
 #define RRS_PACKET_TYPE_ETH    0
 #define RRS_PACKET_IS_ETH(word) \
-       (((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK == \
+       ((((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK) == \
                        RRS_PACKET_TYPE_ETH)
 #define RRS_RXD_IS_VALID(word) \
        ((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1)
index e4afbd628c23e8f8b4594e44988d37e6842592cb..00d11b480af30b48956bb1633a329f282c584222 100644 (file)
@@ -232,11 +232,11 @@ static void atl1c_get_drvinfo(struct net_device *netdev,
 {
        struct atl1c_adapter *adapter = netdev_priv(netdev);
 
-       strncpy(drvinfo->driver,  atl1c_driver_name, sizeof(drvinfo->driver));
-       strncpy(drvinfo->version, atl1c_driver_version,
+       strlcpy(drvinfo->driver,  atl1c_driver_name, sizeof(drvinfo->driver));
+       strlcpy(drvinfo->version, atl1c_driver_version,
                sizeof(drvinfo->version));
-       strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
-       strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
        drvinfo->n_stats = 0;
        drvinfo->testinfo_len = 0;
@@ -281,6 +281,8 @@ static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        if (wol->wolopts & WAKE_PHY)
                adapter->wol |= AT_WUFC_LNKC;
 
+       device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
        return 0;
 }
 
index cd547a205fb96d9d9a71f37cfbc57286686f31d2..a383122679de029b4e33a652d7007d071339cf3e 100644 (file)
@@ -1689,7 +1689,7 @@ static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, u8 que,
                if (likely(RRS_RXD_IS_VALID(rrs->word3))) {
                        rfd_num = (rrs->word0 >> RRS_RX_RFD_CNT_SHIFT) &
                                RRS_RX_RFD_CNT_MASK;
-                       if (unlikely(rfd_num) != 1)
+                       if (unlikely(rfd_num != 1))
                                /* TODO support mul rfd*/
                                if (netif_msg_rx_err(adapter))
                                        dev_warn(&pdev->dev,
index 619c6583e1aac7ca5e8dd1ff263fab6325b6193c..4003955d7a9650b3ed095ee516b3f671f666e37d 100644 (file)
@@ -365,6 +365,8 @@ static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        if (wol->wolopts & WAKE_PHY)
                adapter->wol |= AT_WUFC_LNKC;
 
+       device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
        return 0;
 }
 
index 94d7325caf4ffc5a893c274dc3cf56a0e957897a..8bca12f71390db026025bb25eca3d76640223268 100644 (file)
@@ -3378,11 +3378,11 @@ static void atl1_get_drvinfo(struct net_device *netdev,
 {
        struct atl1_adapter *adapter = netdev_priv(netdev);
 
-       strncpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver));
-       strncpy(drvinfo->version, ATLX_DRIVER_VERSION,
+       strlcpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver));
+       strlcpy(drvinfo->version, ATLX_DRIVER_VERSION,
                sizeof(drvinfo->version));
-       strncpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
-       strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
        drvinfo->eedump_len = ATL1_EEDUMP_LEN;
 }
index c734b1983ec14667bc2debd4d5eec05b4f66369d..204db961029e798e74a8dc990d7b086207c0771c 100644 (file)
@@ -2071,7 +2071,7 @@ static int atl2_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))
                return -EOPNOTSUPP;
 
-       if (wol->wolopts & (WAKE_MCAST|WAKE_BCAST|WAKE_MCAST))
+       if (wol->wolopts & (WAKE_UCAST | WAKE_BCAST | WAKE_MCAST))
                return -EOPNOTSUPP;
 
        /* these settings will always override what we currently have */
index 36d4d377ec2fc5df3a78a96f609aa6055e7ad167..bafca672ea7d7d2857bc52b17bfe051cea8b4716 100644 (file)
@@ -952,9 +952,10 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
        int rc = NETDEV_TX_OK;
        dma_addr_t mapping;
        u32 len, entry, ctrl;
+       unsigned long flags;
 
        len = skb->len;
-       spin_lock_irq(&bp->lock);
+       spin_lock_irqsave(&bp->lock, flags);
 
        /* This is a hard error, log it. */
        if (unlikely(TX_BUFFS_AVAIL(bp) < 1)) {
@@ -1027,7 +1028,7 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
        dev->trans_start = jiffies;
 
 out_unlock:
-       spin_unlock_irq(&bp->lock);
+       spin_unlock_irqrestore(&bp->lock, flags);
 
        return rc;
 
index f703758f0a6e4f7fdaa730dbe53fec400b86d5f7..5b4bf3d2cdc2ecb9b6c85544d96a7d7f48ef156a 100644 (file)
@@ -73,7 +73,7 @@ static inline char *nic_name(struct pci_dev *pdev)
 #define RX_FRAGS_REFILL_WM     (RX_Q_LEN - MAX_RX_POST)
 
 #define BE_MAX_LRO_DESCRIPTORS  16
-#define BE_MAX_FRAGS_PER_FRAME  16
+#define BE_MAX_FRAGS_PER_FRAME  (min((u32) 16, (u32) MAX_SKB_FRAGS))
 
 struct be_dma_mem {
        void *va;
index 9592f22e4c8c29a139dd5fb523b300aacc63b9d6..cccc5419ad72a5f02b1e5109ed66315995eb3668 100644 (file)
@@ -162,8 +162,8 @@ be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce)
                return -EINVAL;
 
        adapter->max_rx_coal = coalesce->rx_max_coalesced_frames;
-       if (adapter->max_rx_coal > MAX_SKB_FRAGS)
-               adapter->max_rx_coal = MAX_SKB_FRAGS - 1;
+       if (adapter->max_rx_coal > BE_MAX_FRAGS_PER_FRAME)
+               adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME;
 
        /* if AIC is being turned on now, start with an EQD of 0 */
        if (rx_eq->enable_aic == 0 &&
index b02e805c1db37c8e645510b6b479905b74d19e56..29c33c709c6d11262024d46768870ffc53921c6e 100644 (file)
 #define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK        0x7     /* bits 26 - 28 */
 #define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT       26
 
+/********* ISR0 Register offset **********/
+#define CEV_ISR0_OFFSET                        0xC18
+#define CEV_ISR_SIZE                           4
+
 /********* Event Q door bell *************/
 #define DB_EQ_OFFSET                   DB_CQ_OFFSET
 #define DB_EQ_RING_ID_MASK             0x1FF   /* bits 0 - 8 */
index 66c10c87f5175151d54cff2fedb9a1f96d551201..dea3155688bbc570eaa6ba52f94832efe8170f80 100644 (file)
@@ -666,8 +666,8 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
 {
        struct be_queue_info *rxq = &adapter->rx_obj.q;
        struct be_rx_page_info *page_info;
-       u16 rxq_idx, i, num_rcvd;
-       u32 pktsize, hdr_len, curr_frag_len;
+       u16 rxq_idx, i, num_rcvd, j;
+       u32 pktsize, hdr_len, curr_frag_len, size;
        u8 *start;
 
        rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
@@ -708,23 +708,34 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
        }
 
        /* More frags present for this completion */
-       pktsize -= curr_frag_len; /* account for above copied frag */
-       for (i = 1; i < num_rcvd; i++) {
+       size = pktsize;
+       for (i = 1, j = 0; i < num_rcvd; i++) {
+               size -= curr_frag_len;
                index_inc(&rxq_idx, rxq->len);
                page_info = get_rx_page_info(adapter, rxq_idx);
 
-               curr_frag_len = min(pktsize, rx_frag_size);
+               curr_frag_len = min(size, rx_frag_size);
+
+               /* Coalesce all frags from the same physical page in one slot */
+               if (page_info->page_offset == 0) {
+                       /* Fresh page */
+                       j++;
+                       skb_shinfo(skb)->frags[j].page = page_info->page;
+                       skb_shinfo(skb)->frags[j].page_offset =
+                                                       page_info->page_offset;
+                       skb_shinfo(skb)->frags[j].size = 0;
+                       skb_shinfo(skb)->nr_frags++;
+               } else {
+                       put_page(page_info->page);
+               }
 
-               skb_shinfo(skb)->frags[i].page = page_info->page;
-               skb_shinfo(skb)->frags[i].page_offset = page_info->page_offset;
-               skb_shinfo(skb)->frags[i].size = curr_frag_len;
+               skb_shinfo(skb)->frags[j].size += curr_frag_len;
                skb->len += curr_frag_len;
                skb->data_len += curr_frag_len;
-               skb_shinfo(skb)->nr_frags++;
-               pktsize -= curr_frag_len;
 
                memset(page_info, 0, sizeof(*page_info));
        }
+       BUG_ON(j > MAX_SKB_FRAGS);
 
 done:
        be_rx_stats_update(adapter, pktsize, num_rcvd);
@@ -786,7 +797,7 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter,
        struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME];
        struct be_queue_info *rxq = &adapter->rx_obj.q;
        u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len;
-       u16 i, rxq_idx = 0, vid;
+       u16 i, rxq_idx = 0, vid, j;
 
        num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
        pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
@@ -794,20 +805,28 @@ static void be_rx_compl_process_lro(struct be_adapter *adapter,
        rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
 
        remaining = pkt_size;
-       for (i = 0; i < num_rcvd; i++) {
+       for (i = 0, j = -1; i < num_rcvd; i++) {
                page_info = get_rx_page_info(adapter, rxq_idx);
 
                curr_frag_len = min(remaining, rx_frag_size);
 
-               rx_frags[i].page = page_info->page;
-               rx_frags[i].page_offset = page_info->page_offset;
-               rx_frags[i].size = curr_frag_len;
-               remaining -= curr_frag_len;
+               /* Coalesce all frags from the same physical page in one slot */
+               if (i == 0 || page_info->page_offset == 0) {
+                       /* First frag or Fresh page */
+                       j++;
+                       rx_frags[j].page = page_info->page;
+                       rx_frags[j].page_offset = page_info->page_offset;
+                       rx_frags[j].size = 0;
+               } else {
+                       put_page(page_info->page);
+               }
+               rx_frags[j].size += curr_frag_len;
 
+               remaining -= curr_frag_len;
                index_inc(&rxq_idx, rxq->len);
-
                memset(page_info, 0, sizeof(*page_info));
        }
+       BUG_ON(j > MAX_SKB_FRAGS);
 
        if (likely(!vlanf)) {
                lro_receive_frags(&adapter->rx_obj.lro_mgr, rx_frags, pkt_size,
@@ -1255,15 +1274,17 @@ static irqreturn_t be_intx(int irq, void *dev)
 {
        struct be_adapter *adapter = dev;
        struct be_ctrl_info *ctrl = &adapter->ctrl;
-       int rx, tx;
+        int isr;
 
-       tx = event_handle(ctrl, &adapter->tx_eq);
-       rx = event_handle(ctrl, &adapter->rx_eq);
+       isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET +
+                      ctrl->pci_func * CEV_ISR_SIZE);
+       if (!isr)
+                return IRQ_NONE;
 
-       if (rx || tx)
-               return IRQ_HANDLED;
-       else
-               return IRQ_NONE;
+        event_handle(ctrl, &adapter->tx_eq);
+        event_handle(ctrl, &adapter->rx_eq);
+
+        return IRQ_HANDLED;
 }
 
 static irqreturn_t be_msix_rx(int irq, void *dev)
index 9578a3dfac01333a696050e0f95abc0aa8c6da46..206144f2470f388588e40cc1638f2fa3027608b5 100644 (file)
@@ -428,10 +428,11 @@ bmac_init_phy(struct net_device *dev)
        printk(KERN_DEBUG "phy registers:");
        for (addr = 0; addr < 32; ++addr) {
                if ((addr & 7) == 0)
-                       printk("\n" KERN_DEBUG);
-               printk(" %.4x", bmac_mif_read(dev, addr));
+                       printk(KERN_DEBUG);
+               printk(KERN_CONT " %.4x", bmac_mif_read(dev, addr));
        }
-       printk("\n");
+       printk(KERN_CONT "\n");
+
        if (bp->is_bmac_plus) {
                unsigned int capable, ctrl;
 
index b70cc99962fcfcf6ccb655213ccf0f1f0225fa89..06b901152d4487fa04164437cc179661b44657fe 100644 (file)
@@ -399,9 +399,11 @@ static int bnx2_unregister_cnic(struct net_device *dev)
        struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
        struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
 
+       mutex_lock(&bp->cnic_lock);
        cp->drv_state = 0;
        bnapi->cnic_present = 0;
        rcu_assign_pointer(bp->cnic_ops, NULL);
+       mutex_unlock(&bp->cnic_lock);
        synchronize_rcu();
        return 0;
 }
@@ -429,13 +431,13 @@ bnx2_cnic_stop(struct bnx2 *bp)
        struct cnic_ops *c_ops;
        struct cnic_ctl_info info;
 
-       rcu_read_lock();
-       c_ops = rcu_dereference(bp->cnic_ops);
+       mutex_lock(&bp->cnic_lock);
+       c_ops = bp->cnic_ops;
        if (c_ops) {
                info.cmd = CNIC_CTL_STOP_CMD;
                c_ops->cnic_ctl(bp->cnic_data, &info);
        }
-       rcu_read_unlock();
+       mutex_unlock(&bp->cnic_lock);
 }
 
 static void
@@ -444,8 +446,8 @@ bnx2_cnic_start(struct bnx2 *bp)
        struct cnic_ops *c_ops;
        struct cnic_ctl_info info;
 
-       rcu_read_lock();
-       c_ops = rcu_dereference(bp->cnic_ops);
+       mutex_lock(&bp->cnic_lock);
+       c_ops = bp->cnic_ops;
        if (c_ops) {
                if (!(bp->flags & BNX2_FLAG_USING_MSIX)) {
                        struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
@@ -455,7 +457,7 @@ bnx2_cnic_start(struct bnx2 *bp)
                info.cmd = CNIC_CTL_START_CMD;
                c_ops->cnic_ctl(bp->cnic_data, &info);
        }
-       rcu_read_unlock();
+       mutex_unlock(&bp->cnic_lock);
 }
 
 #else
@@ -7663,6 +7665,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 
        spin_lock_init(&bp->phy_lock);
        spin_lock_init(&bp->indirect_lock);
+#ifdef BCM_CNIC
+       mutex_init(&bp->cnic_lock);
+#endif
        INIT_WORK(&bp->reset_task, bnx2_reset_task);
 
        dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
index f1edfaa9e56acd87afd0cb41aa20cd23248f7880..a4f12fd0ecd214cdea03039a5af5a0c69e1a8e2e 100644 (file)
@@ -6902,6 +6902,7 @@ struct bnx2 {
        u32                     idle_chk_status_idx;
 
 #ifdef BCM_CNIC
+       struct mutex            cnic_lock;
        struct cnic_eth_dev     cnic_eth_dev;
 #endif
 
index 8678457849f9ff32e5bb7b71c1af55fc43c7824f..85a737c5c23f2647577127b1e045edbaafc058a0 100644 (file)
@@ -902,6 +902,8 @@ struct bnx2x {
        u16                     rx_quick_cons_trip;
        u16                     rx_ticks_int;
        u16                     rx_ticks;
+/* Maximal coalescing timeout in us */
+#define BNX2X_MAX_COALESCE_TOUT                (0xf0*12)
 
        u32                     lin_cnt;
 
index ed648acef7cffef16ee31923562b0a8b9c9ed731..2ee581a2cdec7f6210d0f95a71e996ec788299c5 100644 (file)
@@ -4212,13 +4212,14 @@ static void bnx2x_turn_off_sf(struct bnx2x *bp, u8 port)
 u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
                              u8 *version, u16 len)
 {
-       struct bnx2x *bp = params->bp;
+       struct bnx2x *bp;
        u32 ext_phy_type = 0;
        u32 spirom_ver = 0;
        u8 status = 0 ;
 
        if (version == NULL || params == NULL)
                return -EINVAL;
+       bp = params->bp;
 
        spirom_ver = REG_RD(bp, params->shmem_base +
                   offsetof(struct shmem_region,
index fbf1352e9c1cbd5701202a65ed95f962c6e6d486..c36a5f33739f5f30eafa70162dd59a689571a8d6 100644 (file)
@@ -484,8 +484,9 @@ static void bnx2x_fw_dump(struct bnx2x *bp)
 
        mark = REG_RD(bp, MCP_REG_MCPR_SCRATCH + 0xf104);
        mark = ((mark + 0x3) & ~0x3);
-       printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n" KERN_ERR, mark);
+       printk(KERN_ERR PFX "begin fw dump (mark 0x%x)\n", mark);
 
+       printk(KERN_ERR PFX);
        for (offset = mark - 0x08000000; offset <= 0xF900; offset += 0x8*4) {
                for (word = 0; word < 8; word++)
                        data[word] = htonl(REG_RD(bp, MCP_REG_MCPR_SCRATCH +
@@ -500,7 +501,7 @@ static void bnx2x_fw_dump(struct bnx2x *bp)
                data[8] = 0x0;
                printk(KERN_CONT "%s", (char *)data);
        }
-       printk("\n" KERN_ERR PFX "end of fw dump\n");
+       printk(KERN_ERR PFX "end of fw dump\n");
 }
 
 static void bnx2x_panic_dump(struct bnx2x *bp)
@@ -4434,7 +4435,7 @@ static void bnx2x_update_coalesce(struct bnx2x *bp)
                REG_WR16(bp, BAR_USTRORM_INTMEM +
                         USTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
                                                     U_SB_ETH_RX_CQ_INDEX),
-                        bp->rx_ticks ? 0 : 1);
+                        (bp->rx_ticks/12) ? 0 : 1);
 
                /* HC_INDEX_C_ETH_TX_CQ_CONS */
                REG_WR8(bp, BAR_CSTRORM_INTMEM +
@@ -4444,7 +4445,7 @@ static void bnx2x_update_coalesce(struct bnx2x *bp)
                REG_WR16(bp, BAR_CSTRORM_INTMEM +
                         CSTORM_SB_HC_DISABLE_OFFSET(port, sb_id,
                                                     C_SB_ETH_TX_CQ_INDEX),
-                        bp->tx_ticks ? 0 : 1);
+                        (bp->tx_ticks/12) ? 0 : 1);
        }
 }
 
@@ -7354,7 +7355,7 @@ static void bnx2x_reset_task(struct work_struct *work)
 #ifdef BNX2X_STOP_ON_ERROR
        BNX2X_ERR("reset task called but STOP_ON_ERROR defined"
                  " so reset not done to allow debug dump,\n"
-        KERN_ERR " you will need to reboot when done\n");
+                 " you will need to reboot when done\n");
        return;
 #endif
 
@@ -8637,6 +8638,14 @@ static int bnx2x_nway_reset(struct net_device *dev)
        return 0;
 }
 
+static u32
+bnx2x_get_link(struct net_device *dev)
+{
+       struct bnx2x *bp = netdev_priv(dev);
+
+       return bp->link_vars.link_up;
+}
+
 static int bnx2x_get_eeprom_len(struct net_device *dev)
 {
        struct bnx2x *bp = netdev_priv(dev);
@@ -9061,12 +9070,12 @@ static int bnx2x_set_coalesce(struct net_device *dev,
        struct bnx2x *bp = netdev_priv(dev);
 
        bp->rx_ticks = (u16) coal->rx_coalesce_usecs;
-       if (bp->rx_ticks > 3000)
-               bp->rx_ticks = 3000;
+       if (bp->rx_ticks > BNX2X_MAX_COALESCE_TOUT)
+               bp->rx_ticks = BNX2X_MAX_COALESCE_TOUT;
 
        bp->tx_ticks = (u16) coal->tx_coalesce_usecs;
-       if (bp->tx_ticks > 0x3000)
-               bp->tx_ticks = 0x3000;
+       if (bp->tx_ticks > BNX2X_MAX_COALESCE_TOUT)
+               bp->tx_ticks = BNX2X_MAX_COALESCE_TOUT;
 
        if (netif_running(dev))
                bnx2x_update_coalesce(bp);
@@ -10034,7 +10043,7 @@ static struct ethtool_ops bnx2x_ethtool_ops = {
        .get_msglevel           = bnx2x_get_msglevel,
        .set_msglevel           = bnx2x_set_msglevel,
        .nway_reset             = bnx2x_nway_reset,
-       .get_link               = ethtool_op_get_link,
+       .get_link               = bnx2x_get_link,
        .get_eeprom_len         = bnx2x_get_eeprom_len,
        .get_eeprom             = bnx2x_get_eeprom,
        .set_eeprom             = bnx2x_set_eeprom,
index d927f71af8a31b9096b4ded0f9b18ab47a847116..aa1be1feceedad372f01d082904b66470f55273e 100644 (file)
@@ -1459,8 +1459,16 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
         * ether type (eg ARPHRD_ETHER and ARPHRD_INFINIBAND) share the same bond
         */
        if (bond->slave_cnt == 0) {
-               if (slave_dev->type != ARPHRD_ETHER)
-                       bond_setup_by_slave(bond_dev, slave_dev);
+               if (bond_dev->type != slave_dev->type) {
+                       dev_close(bond_dev);
+                       pr_debug("%s: change device type from %d to %d\n",
+                               bond_dev->name, bond_dev->type, slave_dev->type);
+                       if (slave_dev->type != ARPHRD_ETHER)
+                               bond_setup_by_slave(bond_dev, slave_dev);
+                       else
+                               ether_setup(bond_dev);
+                       dev_open(bond_dev);
+               }
        } else if (bond_dev->type != slave_dev->type) {
                pr_err(DRV_NAME ": %s ether type (%d) is different "
                        "from other slaves (%d), can not enslave it.\n",
index 574daddc21bfb02817fb3b49cfe5dec624936f8e..e1a4f8214239059ce079480bd4b2a5f08bd167c2 100644 (file)
@@ -346,7 +346,7 @@ void can_restart(unsigned long data)
        skb = dev_alloc_skb(sizeof(struct can_frame));
        if (skb == NULL) {
                err = -ENOMEM;
-               goto out;
+               goto restart;
        }
        skb->dev = dev;
        skb->protocol = htons(ETH_P_CAN);
@@ -361,13 +361,13 @@ void can_restart(unsigned long data)
        stats->rx_packets++;
        stats->rx_bytes += cf->can_dlc;
 
+restart:
        dev_dbg(dev->dev.parent, "restarted\n");
        priv->can_stats.restarts++;
 
        /* Now restart the device */
        err = priv->do_set_mode(dev, CAN_MODE_START);
 
-out:
        netif_carrier_on(dev);
        if (err)
                dev_err(dev->dev.parent, "Error %d during restart", err);
@@ -473,6 +473,10 @@ int open_candev(struct net_device *dev)
                return -EINVAL;
        }
 
+       /* Switch carrier on if device was stopped while in bus-off state */
+       if (!netif_carrier_ok(dev))
+               netif_carrier_on(dev);
+
        setup_timer(&priv->restart_timer, can_restart, (unsigned long)dev);
 
        return 0;
@@ -607,11 +611,18 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
+static int can_newlink(struct net_device *dev,
+                      struct nlattr *tb[], struct nlattr *data[])
+{
+       return -EOPNOTSUPP;
+}
+
 static struct rtnl_link_ops can_link_ops __read_mostly = {
        .kind           = "can",
        .maxtype        = IFLA_CAN_MAX,
        .policy         = can_policy,
        .setup          = can_setup,
+       .newlink        = can_newlink,
        .changelink     = can_changelink,
        .fill_info      = can_fill_info,
        .fill_xstats    = can_fill_xstats,
index 571f133a8fec5a94bf1493defb66f56c56520681..08ebee79d8a6a5e5d850922654b2529a34200d98 100644 (file)
@@ -63,7 +63,6 @@
 #include <linux/can.h>
 #include <linux/can/dev.h>
 #include <linux/can/error.h>
-#include <linux/can/dev.h>
 
 #include "sja1000.h"
 
index 4d1515f45ba24657777370c151eb26e475f9b85e..74c342959b7bdf98072311fd371b5e78d302b7e0 100644 (file)
@@ -138,6 +138,16 @@ static struct cnic_dev *cnic_from_netdev(struct net_device *netdev)
        return NULL;
 }
 
+static inline void ulp_get(struct cnic_ulp_ops *ulp_ops)
+{
+       atomic_inc(&ulp_ops->ref_count);
+}
+
+static inline void ulp_put(struct cnic_ulp_ops *ulp_ops)
+{
+       atomic_dec(&ulp_ops->ref_count);
+}
+
 static void cnic_ctx_wr(struct cnic_dev *dev, u32 cid_addr, u32 off, u32 val)
 {
        struct cnic_local *cp = dev->cnic_priv;
@@ -227,7 +237,7 @@ static int cnic_send_nlmsg(struct cnic_local *cp, u32 type,
        }
 
        rcu_read_lock();
-       ulp_ops = rcu_dereference(cp->ulp_ops[CNIC_ULP_ISCSI]);
+       ulp_ops = rcu_dereference(cnic_ulp_tbl[CNIC_ULP_ISCSI]);
        if (ulp_ops)
                ulp_ops->iscsi_nl_send_msg(cp->dev, msg_type, buf, len);
        rcu_read_unlock();
@@ -319,6 +329,20 @@ static int cnic_abort_prep(struct cnic_sock *csk)
        return 0;
 }
 
+static void cnic_uio_stop(void)
+{
+       struct cnic_dev *dev;
+
+       read_lock(&cnic_dev_lock);
+       list_for_each_entry(dev, &cnic_dev_list, list) {
+               struct cnic_local *cp = dev->cnic_priv;
+
+               if (cp->cnic_uinfo)
+                       cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
+       }
+       read_unlock(&cnic_dev_lock);
+}
+
 int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops)
 {
        struct cnic_dev *dev;
@@ -344,6 +368,7 @@ int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops)
        }
        read_unlock(&cnic_dev_lock);
 
+       atomic_set(&ulp_ops->ref_count, 0);
        rcu_assign_pointer(cnic_ulp_tbl[ulp_type], ulp_ops);
        mutex_unlock(&cnic_lock);
 
@@ -365,6 +390,8 @@ int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops)
 int cnic_unregister_driver(int ulp_type)
 {
        struct cnic_dev *dev;
+       struct cnic_ulp_ops *ulp_ops;
+       int i = 0;
 
        if (ulp_type >= MAX_CNIC_ULP_TYPE) {
                printk(KERN_ERR PFX "cnic_unregister_driver: Bad type %d\n",
@@ -372,7 +399,8 @@ int cnic_unregister_driver(int ulp_type)
                return -EINVAL;
        }
        mutex_lock(&cnic_lock);
-       if (!cnic_ulp_tbl[ulp_type]) {
+       ulp_ops = cnic_ulp_tbl[ulp_type];
+       if (!ulp_ops) {
                printk(KERN_ERR PFX "cnic_unregister_driver: Type %d has not "
                                    "been registered\n", ulp_type);
                goto out_unlock;
@@ -390,10 +418,21 @@ int cnic_unregister_driver(int ulp_type)
        }
        read_unlock(&cnic_dev_lock);
 
+       if (ulp_type == CNIC_ULP_ISCSI)
+               cnic_uio_stop();
+
        rcu_assign_pointer(cnic_ulp_tbl[ulp_type], NULL);
 
        mutex_unlock(&cnic_lock);
        synchronize_rcu();
+       while ((atomic_read(&ulp_ops->ref_count) != 0) && (i < 20)) {
+               msleep(100);
+               i++;
+       }
+
+       if (atomic_read(&ulp_ops->ref_count) != 0)
+               printk(KERN_WARNING PFX "%s: Failed waiting for ref count to go"
+                                       " to zero.\n", dev->netdev->name);
        return 0;
 
 out_unlock:
@@ -449,6 +488,7 @@ EXPORT_SYMBOL(cnic_register_driver);
 static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type)
 {
        struct cnic_local *cp = dev->cnic_priv;
+       int i = 0;
 
        if (ulp_type >= MAX_CNIC_ULP_TYPE) {
                printk(KERN_ERR PFX "cnic_unregister_device: Bad type %d\n",
@@ -469,6 +509,15 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type)
 
        synchronize_rcu();
 
+       while (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type]) &&
+              i < 20) {
+               msleep(100);
+               i++;
+       }
+       if (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type]))
+               printk(KERN_WARNING PFX "%s: Failed waiting for ULP up call"
+                                       " to complete.\n", dev->netdev->name);
+
        return 0;
 }
 EXPORT_SYMBOL(cnic_unregister_driver);
@@ -632,7 +681,6 @@ static void cnic_free_resc(struct cnic_dev *dev)
        int i = 0;
 
        if (cp->cnic_uinfo) {
-               cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
                while (cp->uio_dev != -1 && i < 15) {
                        msleep(100);
                        i++;
@@ -1057,18 +1105,26 @@ static void cnic_ulp_stop(struct cnic_dev *dev)
        struct cnic_local *cp = dev->cnic_priv;
        int if_type;
 
-       rcu_read_lock();
+       if (cp->cnic_uinfo)
+               cnic_send_nlmsg(cp, ISCSI_KEVENT_IF_DOWN, NULL);
+
        for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
                struct cnic_ulp_ops *ulp_ops;
 
-               ulp_ops = rcu_dereference(cp->ulp_ops[if_type]);
-               if (!ulp_ops)
+               mutex_lock(&cnic_lock);
+               ulp_ops = cp->ulp_ops[if_type];
+               if (!ulp_ops) {
+                       mutex_unlock(&cnic_lock);
                        continue;
+               }
+               set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
+               mutex_unlock(&cnic_lock);
 
                if (test_and_clear_bit(ULP_F_START, &cp->ulp_flags[if_type]))
                        ulp_ops->cnic_stop(cp->ulp_handle[if_type]);
+
+               clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
        }
-       rcu_read_unlock();
 }
 
 static void cnic_ulp_start(struct cnic_dev *dev)
@@ -1076,18 +1132,23 @@ static void cnic_ulp_start(struct cnic_dev *dev)
        struct cnic_local *cp = dev->cnic_priv;
        int if_type;
 
-       rcu_read_lock();
        for (if_type = 0; if_type < MAX_CNIC_ULP_TYPE; if_type++) {
                struct cnic_ulp_ops *ulp_ops;
 
-               ulp_ops = rcu_dereference(cp->ulp_ops[if_type]);
-               if (!ulp_ops || !ulp_ops->cnic_start)
+               mutex_lock(&cnic_lock);
+               ulp_ops = cp->ulp_ops[if_type];
+               if (!ulp_ops || !ulp_ops->cnic_start) {
+                       mutex_unlock(&cnic_lock);
                        continue;
+               }
+               set_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
+               mutex_unlock(&cnic_lock);
 
                if (!test_and_set_bit(ULP_F_START, &cp->ulp_flags[if_type]))
                        ulp_ops->cnic_start(cp->ulp_handle[if_type]);
+
+               clear_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[if_type]);
        }
-       rcu_read_unlock();
 }
 
 static int cnic_ctl(void *data, struct cnic_ctl_info *info)
@@ -1097,22 +1158,18 @@ static int cnic_ctl(void *data, struct cnic_ctl_info *info)
        switch (info->cmd) {
        case CNIC_CTL_STOP_CMD:
                cnic_hold(dev);
-               mutex_lock(&cnic_lock);
 
                cnic_ulp_stop(dev);
                cnic_stop_hw(dev);
 
-               mutex_unlock(&cnic_lock);
                cnic_put(dev);
                break;
        case CNIC_CTL_START_CMD:
                cnic_hold(dev);
-               mutex_lock(&cnic_lock);
 
                if (!cnic_start_hw(dev))
                        cnic_ulp_start(dev);
 
-               mutex_unlock(&cnic_lock);
                cnic_put(dev);
                break;
        default:
@@ -1126,19 +1183,23 @@ static void cnic_ulp_init(struct cnic_dev *dev)
        int i;
        struct cnic_local *cp = dev->cnic_priv;
 
-       rcu_read_lock();
        for (i = 0; i < MAX_CNIC_ULP_TYPE_EXT; i++) {
                struct cnic_ulp_ops *ulp_ops;
 
-               ulp_ops = rcu_dereference(cnic_ulp_tbl[i]);
-               if (!ulp_ops || !ulp_ops->cnic_init)
+               mutex_lock(&cnic_lock);
+               ulp_ops = cnic_ulp_tbl[i];
+               if (!ulp_ops || !ulp_ops->cnic_init) {
+                       mutex_unlock(&cnic_lock);
                        continue;
+               }
+               ulp_get(ulp_ops);
+               mutex_unlock(&cnic_lock);
 
                if (!test_and_set_bit(ULP_F_INIT, &cp->ulp_flags[i]))
                        ulp_ops->cnic_init(dev);
 
+               ulp_put(ulp_ops);
        }
-       rcu_read_unlock();
 }
 
 static void cnic_ulp_exit(struct cnic_dev *dev)
@@ -1146,19 +1207,23 @@ static void cnic_ulp_exit(struct cnic_dev *dev)
        int i;
        struct cnic_local *cp = dev->cnic_priv;
 
-       rcu_read_lock();
        for (i = 0; i < MAX_CNIC_ULP_TYPE_EXT; i++) {
                struct cnic_ulp_ops *ulp_ops;
 
-               ulp_ops = rcu_dereference(cnic_ulp_tbl[i]);
-               if (!ulp_ops || !ulp_ops->cnic_exit)
+               mutex_lock(&cnic_lock);
+               ulp_ops = cnic_ulp_tbl[i];
+               if (!ulp_ops || !ulp_ops->cnic_exit) {
+                       mutex_unlock(&cnic_lock);
                        continue;
+               }
+               ulp_get(ulp_ops);
+               mutex_unlock(&cnic_lock);
 
                if (test_and_clear_bit(ULP_F_INIT, &cp->ulp_flags[i]))
                        ulp_ops->cnic_exit(dev);
 
+               ulp_put(ulp_ops);
        }
-       rcu_read_unlock();
 }
 
 static int cnic_cm_offload_pg(struct cnic_sock *csk)
@@ -2374,21 +2439,45 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
        return 0;
 }
 
-static int cnic_start_hw(struct cnic_dev *dev)
+static int cnic_register_netdev(struct cnic_dev *dev)
 {
        struct cnic_local *cp = dev->cnic_priv;
        struct cnic_eth_dev *ethdev = cp->ethdev;
        int err;
 
-       if (test_bit(CNIC_F_CNIC_UP, &dev->flags))
-               return -EALREADY;
+       if (!ethdev)
+               return -ENODEV;
+
+       if (ethdev->drv_state & CNIC_DRV_STATE_REGD)
+               return 0;
 
        err = ethdev->drv_register_cnic(dev->netdev, cp->cnic_ops, dev);
-       if (err) {
+       if (err)
                printk(KERN_ERR PFX "%s: register_cnic failed\n",
                       dev->netdev->name);
-               goto err2;
-       }
+
+       return err;
+}
+
+static void cnic_unregister_netdev(struct cnic_dev *dev)
+{
+       struct cnic_local *cp = dev->cnic_priv;
+       struct cnic_eth_dev *ethdev = cp->ethdev;
+
+       if (!ethdev)
+               return;
+
+       ethdev->drv_unregister_cnic(dev->netdev);
+}
+
+static int cnic_start_hw(struct cnic_dev *dev)
+{
+       struct cnic_local *cp = dev->cnic_priv;
+       struct cnic_eth_dev *ethdev = cp->ethdev;
+       int err;
+
+       if (test_bit(CNIC_F_CNIC_UP, &dev->flags))
+               return -EALREADY;
 
        dev->regview = ethdev->io_base;
        cp->chip_id = ethdev->chip_id;
@@ -2419,18 +2508,13 @@ static int cnic_start_hw(struct cnic_dev *dev)
        return 0;
 
 err1:
-       ethdev->drv_unregister_cnic(dev->netdev);
        cp->free_resc(dev);
        pci_dev_put(dev->pcidev);
-err2:
        return err;
 }
 
 static void cnic_stop_bnx2_hw(struct cnic_dev *dev)
 {
-       struct cnic_local *cp = dev->cnic_priv;
-       struct cnic_eth_dev *ethdev = cp->ethdev;
-
        cnic_disable_bnx2_int_sync(dev);
 
        cnic_reg_wr_ind(dev, BNX2_CP_SCRATCH + 0x20, 0);
@@ -2442,8 +2526,6 @@ static void cnic_stop_bnx2_hw(struct cnic_dev *dev)
        cnic_setup_5709_context(dev, 0);
        cnic_free_irq(dev);
 
-       ethdev->drv_unregister_cnic(dev->netdev);
-
        cnic_free_resc(dev);
 }
 
@@ -2524,7 +2606,7 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev)
        probe = symbol_get(bnx2_cnic_probe);
        if (probe) {
                ethdev = (*probe)(dev);
-               symbol_put_addr(probe);
+               symbol_put(bnx2_cnic_probe);
        }
        if (!ethdev)
                return NULL;
@@ -2627,10 +2709,12 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
                else if (event == NETDEV_UNREGISTER)
                        cnic_ulp_exit(dev);
                else if (event == NETDEV_UP) {
-                       mutex_lock(&cnic_lock);
+                       if (cnic_register_netdev(dev) != 0) {
+                               cnic_put(dev);
+                               goto done;
+                       }
                        if (!cnic_start_hw(dev))
                                cnic_ulp_start(dev);
-                       mutex_unlock(&cnic_lock);
                }
 
                rcu_read_lock();
@@ -2649,10 +2733,9 @@ static int cnic_netdev_event(struct notifier_block *this, unsigned long event,
                rcu_read_unlock();
 
                if (event == NETDEV_GOING_DOWN) {
-                       mutex_lock(&cnic_lock);
                        cnic_ulp_stop(dev);
                        cnic_stop_hw(dev);
-                       mutex_unlock(&cnic_lock);
+                       cnic_unregister_netdev(dev);
                } else if (event == NETDEV_UNREGISTER) {
                        write_lock(&cnic_dev_lock);
                        list_del_init(&dev->list);
@@ -2684,6 +2767,7 @@ static void cnic_release(void)
                }
 
                cnic_ulp_exit(dev);
+               cnic_unregister_netdev(dev);
                list_del_init(&dev->list);
                cnic_free_dev(dev);
        }
index 5192d4a9df5a5d56a48e22632a2fa75badb9e4fb..a94b302bb4648d751053b8cc8eea98473c12c1f6 100644 (file)
@@ -176,6 +176,7 @@ struct cnic_local {
        unsigned long ulp_flags[MAX_CNIC_ULP_TYPE];
 #define ULP_F_INIT     0
 #define ULP_F_START    1
+#define ULP_F_CALL_PENDING     2
        struct cnic_ulp_ops *ulp_ops[MAX_CNIC_ULP_TYPE];
 
        /* protected by ulp_lock */
index d1bce27ee99e9a28dc42f1773e889f88fd0b60f6..a49235739eef9444d1596df5dfb5248a4aba8a1e 100644 (file)
@@ -290,6 +290,7 @@ struct cnic_ulp_ops {
        void (*iscsi_nl_send_msg)(struct cnic_dev *dev, u32 msg_type,
                                  char *data, u16 data_size);
        struct module *owner;
+       atomic_t ref_count;
 };
 
 extern int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops);
index 58afafbd3b9cb9695bcf6fe570c07b493a30d881..fd5e32cbcb8778bb7ed02fdd0d7bf6ec6d1e9163 100644 (file)
@@ -1097,7 +1097,7 @@ static const struct net_device_ops cpmac_netdev_ops = {
        .ndo_start_xmit         = cpmac_start_xmit,
        .ndo_tx_timeout         = cpmac_tx_timeout,
        .ndo_set_multicast_list = cpmac_set_multicast_list,
-       .ndo_so_ioctl           = cpmac_ioctl,
+       .ndo_do_ioctl           = cpmac_ioctl,
        .ndo_set_config         = cpmac_config,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
index 3eee666a9cd26773fa4712704cf7066ec7f0cbc5..55445f980f9c975596d41b3a9e9a0887155f061b 100644 (file)
@@ -1524,6 +1524,7 @@ static void net_timeout(struct net_device *dev)
 static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
        struct net_local *lp = netdev_priv(dev);
+       unsigned long flags;
 
        if (net_debug > 3) {
                printk("%s: sent %d byte packet of type %x\n",
@@ -1535,7 +1536,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
                   ask the chip to start transmitting before the
                   whole packet has been completely uploaded. */
 
-       spin_lock_irq(&lp->lock);
+       spin_lock_irqsave(&lp->lock, flags);
        netif_stop_queue(dev);
 
        /* initiate a transmit sequence */
@@ -1549,13 +1550,13 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
                 * we're waiting for TxOk, so return 1 and requeue this packet.
                 */
 
-               spin_unlock_irq(&lp->lock);
+               spin_unlock_irqrestore(&lp->lock, flags);
                if (net_debug) printk("cs89x0: Tx buffer not free!\n");
                return NETDEV_TX_BUSY;
        }
        /* Write the contents of the packet */
        writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1);
-       spin_unlock_irq(&lp->lock);
+       spin_unlock_irqrestore(&lp->lock, flags);
        lp->stats.tx_bytes += skb->len;
        dev->trans_start = jiffies;
        dev_kfree_skb (skb);
index 538dda4422dca039b01715e8ca10892af4954ea1..fb5df5c6203e9541849fce56a52abfaedfbe7391 100644 (file)
@@ -642,8 +642,7 @@ static int setup_sge_qsets(struct adapter *adap)
                struct port_info *pi = netdev_priv(dev);
 
                pi->qs = &adap->sge.qs[pi->first_qset];
-               for (j = pi->first_qset; j < pi->first_qset + pi->nqsets;
-                    ++j, ++qset_idx) {
+               for (j = 0; j < pi->nqsets; ++j, ++qset_idx) {
                        set_qset_lro(dev, qset_idx, pi->rx_offload & T3_LRO);
                        err = t3_sge_alloc_qset(adap, qset_idx, 1,
                                (adap->flags & USING_MSIX) ? qset_idx + 1 :
index 2df8fb0af701a0e081d8fee4820bb4047e2d6a6c..12fd446f9895036c6e7f099e0abc7517d9678f59 100644 (file)
@@ -1820,11 +1820,19 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
        struct device *emac_dev = &priv->ndev->dev;
        struct sockaddr *sa = addr;
 
+       if (!is_valid_ether_addr(sa->sa_data))
+               return -EINVAL;
+
        /* Store mac addr in priv and rx channel and set it in EMAC hw */
        memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
-       memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len);
        memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len);
-       emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr);
+
+       /* If the interface is down - rxch is NULL. */
+       /* MAC address is configured only after the interface is enabled. */
+       if (netif_running(ndev)) {
+               memcpy(rxch->mac_addr, sa->sa_data, ndev->addr_len);
+               emac_setmac(priv, EMAC_DEF_RX_CH, rxch->mac_addr);
+       }
 
        if (netif_msg_drv(priv))
                dev_notice(emac_dev, "DaVinci EMAC: emac_dev_setmac_addr %pM\n",
index 895d72143ee049757c3750ae096cad3c8387c02a..4b6a219fecea8b44be1f192db3b1352b28bc5702 100644 (file)
@@ -268,8 +268,9 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
                printk(KERN_INFO "tx_coalesce:\t%d packets\n",
                                tx_coalesce);
        if (np->coalesce)
-               printk(KERN_INFO "rx_coalesce:\t%d packets\n"
-                      KERN_INFO "rx_timeout: \t%d ns\n",
+               printk(KERN_INFO
+                      "rx_coalesce:\t%d packets\n"
+                      "rx_timeout: \t%d ns\n",
                                np->rx_coalesce, np->rx_timeout*640);
        if (np->vlan)
                printk(KERN_INFO "vlan(id):\t%d\n", np->vlan);
@@ -1522,9 +1523,9 @@ mii_get_media (struct net_device *dev)
                        printk (KERN_INFO "Operating at 10 Mbps, ");
                }
                if (bmcr & MII_BMCR_DUPLEX_MODE) {
-                       printk ("Full duplex\n");
+                       printk (KERN_CONT "Full duplex\n");
                } else {
-                       printk ("Half duplex\n");
+                       printk (KERN_CONT "Half duplex\n");
                }
        }
        if (np->tx_flow)
@@ -1614,9 +1615,9 @@ mii_set_media (struct net_device *dev)
                }
                if (np->full_duplex) {
                        bmcr |= MII_BMCR_DUPLEX_MODE;
-                       printk ("Full duplex\n");
+                       printk (KERN_CONT "Full duplex\n");
                } else {
-                       printk ("Half duplex\n");
+                       printk (KERN_CONT "Half duplex\n");
                }
 #if 0
                /* Set 1000BaseT Master/Slave setting */
@@ -1669,9 +1670,9 @@ mii_get_media_pcs (struct net_device *dev)
                __u16 bmcr = mii_read (dev, phy_addr, PCS_BMCR);
                printk (KERN_INFO "Operating at 1000 Mbps, ");
                if (bmcr & MII_BMCR_DUPLEX_MODE) {
-                       printk ("Full duplex\n");
+                       printk (KERN_CONT "Full duplex\n");
                } else {
-                       printk ("Half duplex\n");
+                       printk (KERN_CONT "Half duplex\n");
                }
        }
        if (np->tx_flow)
index efa680f4b8ddceebf8ce166cc3d02409de533a5e..3a6735dc9f6a6158bf04196c22c144133de55408 100644 (file)
@@ -1897,6 +1897,9 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
 
                        if (ioread8(&nic->csr->scb.status) & rus_no_res)
                                nic->ru_running = RU_SUSPENDED;
+               pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr,
+                                              sizeof(struct rfd),
+                                              PCI_DMA_FROMDEVICE);
                return -ENODATA;
        }
 
index 5e3356f8eb5af5ae1611af238f40fcdaff6c0f94..5b8cbdb4b5201fa71223bd409b5d2ddf5e8f6287 100644 (file)
@@ -2185,12 +2185,16 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
        /* Free all the Rx ring sk_buffs */
        for (i = 0; i < rx_ring->count; i++) {
                buffer_info = &rx_ring->buffer_info[i];
-               if (buffer_info->skb) {
+               if (buffer_info->dma) {
                        pci_unmap_single(pdev,
                                         buffer_info->dma,
                                         buffer_info->length,
                                         PCI_DMA_FROMDEVICE);
+               }
+
+               buffer_info->dma = 0;
 
+               if (buffer_info->skb) {
                        dev_kfree_skb(buffer_info->skb);
                        buffer_info->skb = NULL;
                }
@@ -4033,6 +4037,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
                                 buffer_info->dma,
                                 buffer_info->length,
                                 PCI_DMA_FROMDEVICE);
+               buffer_info->dma = 0;
 
                length = le16_to_cpu(rx_desc->length);
                /* !EOP means multiple descriptors were used to store a single
@@ -4222,6 +4227,7 @@ map_skb:
                        pci_unmap_single(pdev, buffer_info->dma,
                                         adapter->rx_buffer_len,
                                         PCI_DMA_FROMDEVICE);
+                       buffer_info->dma = 0;
 
                        break; /* while !buffer_info->skb */
                }
@@ -4817,6 +4823,9 @@ static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
 
        netif_device_detach(netdev);
 
+       if (state == pci_channel_io_perm_failure)
+               return PCI_ERS_RESULT_DISCONNECT;
+
        if (netif_running(netdev))
                e1000_down(adapter);
        pci_disable_device(pdev);
index 8890c97e1120436cc68c3b930a8bf78e9cb24369..c0f185beb8bc1a7cdd1dd04393f5635470b7473c 100644 (file)
 #define E1000_STATUS_SPEED_100  0x00000040      /* Speed 100Mb/s */
 #define E1000_STATUS_SPEED_1000 0x00000080      /* Speed 1000Mb/s */
 #define E1000_STATUS_LAN_INIT_DONE 0x00000200   /* Lan Init Completion by NVM */
+#define E1000_STATUS_PHYRA      0x00000400      /* PHY Reset Asserted */
 #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */
 
 /* Constants used to interpret the masked PCI-X bus speed. */
 #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
 #define PHY_EXT_STATUS   0x0F /* Extended Status Reg */
 
+#define PHY_CONTROL_LB   0x4000 /* PHY Loopback bit */
+
 /* NVM Control */
 #define E1000_EECD_SK        0x00000001 /* NVM Clock */
 #define E1000_EECD_CS        0x00000002 /* NVM Chip Select */
index 163c1c0cfee7004b7fdcf7935300aacb3431b049..fd44d9f907696aff5ee2fdb6558d79feaf0b27e7 100644 (file)
@@ -215,6 +215,7 @@ enum e1e_registers {
        E1000_SWSM      = 0x05B50, /* SW Semaphore */
        E1000_FWSM      = 0x05B54, /* FW Semaphore */
        E1000_SWSM2     = 0x05B58, /* Driver-only SW semaphore */
+       E1000_CRC_OFFSET = 0x05F50, /* CRC Offset register */
        E1000_HICR      = 0x08F00, /* Host Interface Control */
 };
 
@@ -302,6 +303,9 @@ enum e1e_registers {
 #define E1000_KMRNCTRLSTA_REN          0x00200000
 #define E1000_KMRNCTRLSTA_DIAG_OFFSET  0x3    /* Kumeran Diagnostic */
 #define E1000_KMRNCTRLSTA_DIAG_NELPBK  0x1000 /* Nearend Loopback mode */
+#define E1000_KMRNCTRLSTA_K1_CONFIG    0x7
+#define E1000_KMRNCTRLSTA_K1_ENABLE    0x140E
+#define E1000_KMRNCTRLSTA_K1_DISABLE   0x1400
 
 #define IFE_PHY_EXTENDED_STATUS_CONTROL        0x10
 #define IFE_PHY_SPECIAL_CONTROL                0x11 /* 100BaseTx PHY Special Control */
index 9e23f50fb9cdfa32be3428fbc540e3312d16018e..99df2abf82a956d52d0e80658f0e655cb8cfe89d 100644 (file)
@@ -338,9 +338,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
        struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
-       u32 gfpreg;
-       u32 sector_base_addr;
-       u32 sector_end_addr;
+       u32 gfpreg, sector_base_addr, sector_end_addr;
        u16 i;
 
        /* Can't read flash registers if the register set isn't mapped. */
@@ -446,6 +444,95 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
        return 0;
 }
 
+/**
+ *  e1000_check_for_copper_link_ich8lan - Check for link (Copper)
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks to see of the link status of the hardware has changed.  If a
+ *  change in link status has been detected, then we read the PHY registers
+ *  to get the current speed/duplex if link exists.
+ **/
+static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
+{
+       struct e1000_mac_info *mac = &hw->mac;
+       s32 ret_val;
+       bool link;
+
+       /*
+        * We only want to go out to the PHY registers to see if Auto-Neg
+        * has completed and/or if our link status has changed.  The
+        * get_link_status flag is set upon receiving a Link Status
+        * Change or Rx Sequence Error interrupt.
+        */
+       if (!mac->get_link_status) {
+               ret_val = 0;
+               goto out;
+       }
+
+       if (hw->mac.type == e1000_pchlan) {
+               ret_val = e1000e_write_kmrn_reg(hw,
+                                                  E1000_KMRNCTRLSTA_K1_CONFIG,
+                                                  E1000_KMRNCTRLSTA_K1_ENABLE);
+               if (ret_val)
+                       goto out;
+       }
+
+       /*
+        * First we want to see if the MII Status Register reports
+        * link.  If so, then we want to get the current speed/duplex
+        * of the PHY.
+        */
+       ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link);
+       if (ret_val)
+               goto out;
+
+       if (!link)
+               goto out; /* No link detected */
+
+       mac->get_link_status = false;
+
+       if (hw->phy.type == e1000_phy_82578) {
+               ret_val = e1000_link_stall_workaround_hv(hw);
+               if (ret_val)
+                       goto out;
+       }
+
+       /*
+        * Check if there was DownShift, must be checked
+        * immediately after link-up
+        */
+       e1000e_check_downshift(hw);
+
+       /*
+        * If we are forcing speed/duplex, then we simply return since
+        * we have already determined whether we have link or not.
+        */
+       if (!mac->autoneg) {
+               ret_val = -E1000_ERR_CONFIG;
+               goto out;
+       }
+
+       /*
+        * Auto-Neg is enabled.  Auto Speed Detection takes care
+        * of MAC speed/duplex configuration.  So we only need to
+        * configure Collision Distance in the MAC.
+        */
+       e1000e_config_collision_dist(hw);
+
+       /*
+        * Configure Flow Control now that Auto-Neg has completed.
+        * First, we need to restore the desired flow control
+        * settings because we may have had to re-autoneg with a
+        * different link partner.
+        */
+       ret_val = e1000e_config_fc_after_link_up(hw);
+       if (ret_val)
+               hw_dbg(hw, "Error configuring flow control\n");
+
+out:
+       return ret_val;
+}
+
 static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
@@ -490,8 +577,8 @@ static DEFINE_MUTEX(nvm_mutex);
  **/
 static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
 {
-       u32 extcnf_ctrl;
-       u32 timeout = PHY_CFG_TIMEOUT;
+       u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT;
+       s32 ret_val = 0;
 
        might_sleep();
 
@@ -499,28 +586,46 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
 
        while (timeout) {
                extcnf_ctrl = er32(EXTCNF_CTRL);
+               if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG))
+                       break;
 
-               if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)) {
-                       extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
-                       ew32(EXTCNF_CTRL, extcnf_ctrl);
+               mdelay(1);
+               timeout--;
+       }
+
+       if (!timeout) {
+               hw_dbg(hw, "SW/FW/HW has locked the resource for too long.\n");
+               ret_val = -E1000_ERR_CONFIG;
+               goto out;
+       }
+
+       timeout = PHY_CFG_TIMEOUT * 2;
+
+       extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
+       ew32(EXTCNF_CTRL, extcnf_ctrl);
+
+       while (timeout) {
+               extcnf_ctrl = er32(EXTCNF_CTRL);
+               if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)
+                       break;
 
-                       extcnf_ctrl = er32(EXTCNF_CTRL);
-                       if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)
-                               break;
-               }
                mdelay(1);
                timeout--;
        }
 
        if (!timeout) {
-               hw_dbg(hw, "FW or HW has locked the resource for too long.\n");
+               hw_dbg(hw, "Failed to acquire the semaphore.\n");
                extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
                ew32(EXTCNF_CTRL, extcnf_ctrl);
-               mutex_unlock(&nvm_mutex);
-               return -E1000_ERR_CONFIG;
+               ret_val = -E1000_ERR_CONFIG;
+               goto out;
        }
 
-       return 0;
+out:
+       if (ret_val)
+               mutex_unlock(&nvm_mutex);
+
+       return ret_val;
 }
 
 /**
@@ -693,6 +798,38 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
        return ret_val;
 }
 
+/**
+ *  e1000_lan_init_done_ich8lan - Check for PHY config completion
+ *  @hw: pointer to the HW structure
+ *
+ *  Check the appropriate indication the MAC has finished configuring the
+ *  PHY after a software reset.
+ **/
+static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
+{
+       u32 data, loop = E1000_ICH8_LAN_INIT_TIMEOUT;
+
+       /* Wait for basic configuration completes before proceeding */
+       do {
+               data = er32(STATUS);
+               data &= E1000_STATUS_LAN_INIT_DONE;
+               udelay(100);
+       } while ((!data) && --loop);
+
+       /*
+        * If basic configuration is incomplete before the above loop
+        * count reaches 0, loading the configuration from NVM will
+        * leave the PHY in a bad state possibly resulting in no link.
+        */
+       if (loop == 0)
+               hw_dbg(hw, "LAN_INIT_DONE not set, increase timeout\n");
+
+       /* Clear the Init Done bit for the next init event */
+       data = er32(STATUS);
+       data &= ~E1000_STATUS_LAN_INIT_DONE;
+       ew32(STATUS, data);
+}
+
 /**
  *  e1000_phy_hw_reset_ich8lan - Performs a PHY reset
  *  @hw: pointer to the HW structure
@@ -707,13 +844,15 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
        u32 i;
        u32 data, cnf_size, cnf_base_addr, sw_cfg_mask;
        s32 ret_val;
-       u16 loop = E1000_ICH8_LAN_INIT_TIMEOUT;
        u16 word_addr, reg_data, reg_addr, phy_page = 0;
 
        ret_val = e1000e_phy_hw_reset_generic(hw);
        if (ret_val)
                return ret_val;
 
+       /* Allow time for h/w to get to a quiescent state after reset */
+       mdelay(10);
+
        if (hw->mac.type == e1000_pchlan) {
                ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
                if (ret_val)
@@ -741,26 +880,8 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
                if (!(data & sw_cfg_mask))
                        return 0;
 
-               /* Wait for basic configuration completes before proceeding*/
-               do {
-                       data = er32(STATUS);
-                       data &= E1000_STATUS_LAN_INIT_DONE;
-                       udelay(100);
-               } while ((!data) && --loop);
-
-               /*
-                * If basic configuration is incomplete before the above loop
-                * count reaches 0, loading the configuration from NVM will
-                * leave the PHY in a bad state possibly resulting in no link.
-                */
-               if (loop == 0) {
-                       hw_dbg(hw, "LAN_INIT_DONE not set, increase timeout\n");
-               }
-
-               /* Clear the Init Done bit for the next init event */
-               data = er32(STATUS);
-               data &= ~E1000_STATUS_LAN_INIT_DONE;
-               ew32(STATUS, data);
+               /* Wait for basic configuration completes before proceeding */
+               e1000_lan_init_done_ich8lan(hw);
 
                /*
                 * Make sure HW does not configure LCD from PHY
@@ -961,12 +1082,14 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
                phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
                ew32(PHY_CTRL, phy_ctrl);
 
+               if (phy->type != e1000_phy_igp_3)
+                       return 0;
+
                /*
                 * Call gig speed drop workaround on LPLU before accessing
                 * any PHY registers
                 */
-               if ((hw->mac.type == e1000_ich8lan) &&
-                   (hw->phy.type == e1000_phy_igp_3))
+               if (hw->mac.type == e1000_ich8lan)
                        e1000e_gig_downshift_workaround_ich8lan(hw);
 
                /* When LPLU is enabled, we should disable SmartSpeed */
@@ -979,6 +1102,9 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
                phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
                ew32(PHY_CTRL, phy_ctrl);
 
+               if (phy->type != e1000_phy_igp_3)
+                       return 0;
+
                /*
                 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
                 * during Dx states where the power conservation is most
@@ -1038,6 +1164,10 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
        if (!active) {
                phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;
                ew32(PHY_CTRL, phy_ctrl);
+
+               if (phy->type != e1000_phy_igp_3)
+                       return 0;
+
                /*
                 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
                 * during Dx states where the power conservation is most
@@ -1073,12 +1203,14 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
                phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
                ew32(PHY_CTRL, phy_ctrl);
 
+               if (phy->type != e1000_phy_igp_3)
+                       return 0;
+
                /*
                 * Call gig speed drop workaround on LPLU before accessing
                 * any PHY registers
                 */
-               if ((hw->mac.type == e1000_ich8lan) &&
-                   (hw->phy.type == e1000_phy_igp_3))
+               if (hw->mac.type == e1000_ich8lan)
                        e1000e_gig_downshift_workaround_ich8lan(hw);
 
                /* When LPLU is enabled, we should disable SmartSpeed */
@@ -1175,7 +1307,7 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
        struct e1000_nvm_info *nvm = &hw->nvm;
        struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
        u32 act_offset;
-       s32 ret_val;
+       s32 ret_val = 0;
        u32 bank = 0;
        u16 i, word;
 
@@ -1190,12 +1322,15 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
                goto out;
 
        ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
-       if (ret_val)
-               goto release;
+       if (ret_val) {
+               hw_dbg(hw, "Could not detect valid bank, assuming bank 0\n");
+               bank = 0;
+       }
 
        act_offset = (bank) ? nvm->flash_bank_size : 0;
        act_offset += offset;
 
+       ret_val = 0;
        for (i = 0; i < words; i++) {
                if ((dev_spec->shadow_ram) &&
                    (dev_spec->shadow_ram[offset+i].modified)) {
@@ -1210,7 +1345,6 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
                }
        }
 
-release:
        e1000_release_swflag_ich8lan(hw);
 
 out:
@@ -1461,7 +1595,6 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
        struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
-       s32 ret_val;
        u16 i;
 
        if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
@@ -1470,17 +1603,11 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
                return -E1000_ERR_NVM;
        }
 
-       ret_val = e1000_acquire_swflag_ich8lan(hw);
-       if (ret_val)
-               return ret_val;
-
        for (i = 0; i < words; i++) {
                dev_spec->shadow_ram[offset+i].modified = 1;
                dev_spec->shadow_ram[offset+i].value = data[i];
        }
 
-       e1000_release_swflag_ich8lan(hw);
-
        return 0;
 }
 
@@ -1521,8 +1648,8 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
         */
        ret_val =  e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
        if (ret_val) {
-               e1000_release_swflag_ich8lan(hw);
-               goto out;
+               hw_dbg(hw, "Could not detect valid bank, assuming bank 0\n");
+               bank = 0;
        }
 
        if (bank == 0) {
@@ -1905,19 +2032,15 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
                break;
        case 1:
                sector_size = ICH_FLASH_SEG_SIZE_4K;
-               iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_4K;
+               iteration = 1;
                break;
        case 2:
-               if (hw->mac.type == e1000_ich9lan) {
-                       sector_size = ICH_FLASH_SEG_SIZE_8K;
-                       iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_8K;
-               } else {
-                       return -E1000_ERR_NVM;
-               }
+               sector_size = ICH_FLASH_SEG_SIZE_8K;
+               iteration = 1;
                break;
        case 3:
                sector_size = ICH_FLASH_SEG_SIZE_64K;
-               iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_64K;
+               iteration = 1;
                break;
        default:
                return -E1000_ERR_NVM;
@@ -1925,7 +2048,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
 
        /* Start with the base address, then add the sector offset. */
        flash_linear_addr = hw->nvm.flash_base_addr;
-       flash_linear_addr += (bank) ? (sector_size * iteration) : 0;
+       flash_linear_addr += (bank) ? flash_bank_size : 0;
 
        for (j = 0; j < iteration ; j++) {
                do {
@@ -2143,6 +2266,12 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
        ctrl = er32(CTRL);
 
        if (!e1000_check_reset_block(hw)) {
+               /* Clear PHY Reset Asserted bit */
+               if (hw->mac.type >= e1000_pchlan) {
+                       u32 status = er32(STATUS);
+                       ew32(STATUS, status & ~E1000_STATUS_PHYRA);
+               }
+
                /*
                 * PHY HW reset requires MAC CORE reset at the same
                 * time to make sure the interface between MAC and the
@@ -2156,23 +2285,34 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
        ew32(CTRL, (ctrl | E1000_CTRL_RST));
        msleep(20);
 
-       if (!ret_val) {
-               /* release the swflag because it is not reset by
-                * hardware reset
-                */
+       if (!ret_val)
                e1000_release_swflag_ich8lan(hw);
-       }
 
-       ret_val = e1000e_get_auto_rd_done(hw);
-       if (ret_val) {
-               /*
-                * When auto config read does not complete, do not
-                * return with an error. This can happen in situations
-                * where there is no eeprom and prevents getting link.
-                */
-               hw_dbg(hw, "Auto Read Done did not complete\n");
+       if (ctrl & E1000_CTRL_PHY_RST)
+               ret_val = hw->phy.ops.get_cfg_done(hw);
+
+       if (hw->mac.type >= e1000_ich10lan) {
+               e1000_lan_init_done_ich8lan(hw);
+       } else {
+               ret_val = e1000e_get_auto_rd_done(hw);
+               if (ret_val) {
+                       /*
+                        * When auto config read does not complete, do not
+                        * return with an error. This can happen in situations
+                        * where there is no eeprom and prevents getting link.
+                        */
+                       hw_dbg(hw, "Auto Read Done did not complete\n");
+               }
        }
 
+       /*
+        * For PCH, this write will make sure that any noise
+        * will be detected as a CRC error and be dropped rather than show up
+        * as a bad packet to the DMA engine.
+        */
+       if (hw->mac.type == e1000_pchlan)
+               ew32(CRC_OFFSET, 0x65656565);
+
        ew32(IMC, 0xffffffff);
        icr = er32(ICR);
 
@@ -2222,6 +2362,18 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
        for (i = 0; i < mac->mta_reg_count; i++)
                E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
 
+       /*
+        * The 82578 Rx buffer will stall if wakeup is enabled in host and
+        * the ME.  Reading the BM_WUC register will clear the host wakeup bit.
+        * Reset the phy after disabling host wakeup to reset the Rx buffer.
+        */
+       if (hw->phy.type == e1000_phy_82578) {
+               hw->phy.ops.read_phy_reg(hw, BM_WUC, &i);
+               ret_val = e1000_phy_hw_reset_ich8lan(hw);
+               if (ret_val)
+                       return ret_val;
+       }
+
        /* Setup link and flow control */
        ret_val = e1000_setup_link_ich8lan(hw);
 
@@ -2253,16 +2405,6 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
        ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
        ew32(CTRL_EXT, ctrl_ext);
 
-       /*
-        * The 82578 Rx buffer will stall if wakeup is enabled in host and
-        * the ME.  Reading the BM_WUC register will clear the host wakeup bit.
-        * Reset the phy after disabling host wakeup to reset the Rx buffer.
-        */
-       if (hw->phy.type == e1000_phy_82578) {
-               e1e_rphy(hw, BM_WUC, &i);
-               e1000e_phy_hw_reset_generic(hw);
-       }
-
        /*
         * Clear all of the statistics registers (clear on read).  It is
         * important that we do this after we have tried to establish link
@@ -2485,6 +2627,14 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
        if (ret_val)
                return ret_val;
 
+       if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) {
+               ret_val = e1000e_write_kmrn_reg(hw,
+                                                 E1000_KMRNCTRLSTA_K1_CONFIG,
+                                                 E1000_KMRNCTRLSTA_K1_DISABLE);
+               if (ret_val)
+                       return ret_val;
+       }
+
        if ((hw->mac.type == e1000_ich8lan) &&
            (hw->phy.type == e1000_phy_igp_3) &&
            (*speed == SPEED_1000)) {
@@ -2850,6 +3000,16 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
 {
        u32 bank = 0;
 
+       if (hw->mac.type >= e1000_pchlan) {
+               u32 status = er32(STATUS);
+
+               if (status & E1000_STATUS_PHYRA)
+                       ew32(STATUS, status & ~E1000_STATUS_PHYRA);
+               else
+                       hw_dbg(hw,
+                              "PHY Reset Asserted not set - needs delay\n");
+       }
+
        e1000e_get_cfg_done(hw);
 
        /* If EEPROM is not marked present, init the IGP 3 PHY manually */
@@ -2921,7 +3081,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
 static struct e1000_mac_operations ich8_mac_ops = {
        .id_led_init            = e1000e_id_led_init,
        .check_mng_mode         = e1000_check_mng_mode_ich8lan,
-       .check_for_link         = e1000e_check_for_copper_link,
+       .check_for_link         = e1000_check_for_copper_link_ich8lan,
        /* cleanup_led dependent on mac type */
        .clear_hw_cntrs         = e1000_clear_hw_cntrs_ich8lan,
        .get_bus_info           = e1000_get_bus_info_ich8lan,
index be6d9e9903741650ff5fe83ff1797d112a4c53ce..99ba2b8a2a054b5b7cc2a2200ab3520bff113d06 100644 (file)
@@ -378,12 +378,6 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
 
        mac->get_link_status = 0;
 
-       if (hw->phy.type == e1000_phy_82578) {
-               ret_val = e1000_link_stall_workaround_hv(hw);
-               if (ret_val)
-                       return ret_val;
-       }
-
        /*
         * Check if there was DownShift, must be checked
         * immediately after link-up
index 679885a122b4da068878a4bcd471c45ecd4e905a..fa92a683aefd3944d65cf5d6c72e042c6d34281d 100644 (file)
@@ -4538,8 +4538,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
                /* Allow time for pending master requests to run */
                e1000e_disable_pcie_master(&adapter->hw);
 
-               if ((adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) &&
-                   !(hw->mac.ops.check_mng_mode(hw))) {
+               if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) {
                        /* enable wakeup by the PHY */
                        retval = e1000_init_phy_wakeup(adapter, wufc);
                        if (retval)
@@ -4557,7 +4556,8 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
        *enable_wake = !!wufc;
 
        /* make sure adapter isn't asleep if manageability is enabled */
-       if (adapter->flags & FLAG_MNG_PT_ENABLED)
+       if ((adapter->flags & FLAG_MNG_PT_ENABLED) ||
+           (hw->mac.ops.check_mng_mode(hw)))
                *enable_wake = true;
 
        if (adapter->hw.phy.type == e1000_phy_igp_3)
@@ -4670,14 +4670,6 @@ static int e1000_resume(struct pci_dev *pdev)
                return err;
        }
 
-       /* AER (Advanced Error Reporting) hooks */
-       err = pci_enable_pcie_error_reporting(pdev);
-       if (err) {
-               dev_err(&pdev->dev, "pci_enable_pcie_error_reporting failed "
-                                   "0x%x\n", err);
-               /* non-fatal, continue */
-       }
-
        pci_set_master(pdev);
 
        pci_enable_wake(pdev, PCI_D3hot, 0);
@@ -4785,6 +4777,9 @@ static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
 
        netif_device_detach(netdev);
 
+       if (state == pci_channel_io_perm_failure)
+               return PCI_ERS_RESULT_DISCONNECT;
+
        if (netif_running(netdev))
                e1000e_down(adapter);
        pci_disable_device(pdev);
@@ -4987,6 +4982,14 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
        if (err)
                goto err_pci_reg;
 
+       /* AER (Advanced Error Reporting) hooks */
+       err = pci_enable_pcie_error_reporting(pdev);
+       if (err) {
+               dev_err(&pdev->dev, "pci_enable_pcie_error_reporting failed "
+                       "0x%x\n", err);
+               /* non-fatal, continue */
+       }
+
        pci_set_master(pdev);
        /* PCI config space info */
        err = pci_save_state(pdev);
index e23459cf3d0eecbc64329d40db9de98aa19c7634..994401fd0664fbc188980ea188e33bdf95fdb0ec 100644 (file)
@@ -1531,7 +1531,12 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
                 */
                ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status);
                if (ret_val)
-                       break;
+                       /*
+                        * If the first read fails, another entity may have
+                        * ownership of the resources, wait and try again to
+                        * see if they have relinquished the resources yet.
+                        */
+                       udelay(usec_interval);
                ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status);
                if (ret_val)
                        break;
@@ -2737,6 +2742,11 @@ s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
        if (hw->phy.type != e1000_phy_82578)
                goto out;
 
+       /* Do not apply workaround if in PHY loopback bit 14 set */
+       hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &data);
+       if (data & PHY_CONTROL_LB)
+               goto out;
+
        /* check if link is up and at 1Gbps */
        ret_val = hw->phy.ops.read_phy_reg(hw, BM_CS_STATUS, &data);
        if (ret_val)
index cc2ab6412c7382484073f405306a4a76775b59bd..4f70034853482ef8c51262892002756c22599ae2 100644 (file)
@@ -1784,7 +1784,7 @@ int __init init_module(void)
                printk(KERN_INFO "eepro_init_module: Auto-detecting boards (May God protect us...)\n");
        }
 
-       for (i = 0; io[i] != -1 && i < MAX_EEPRO; i++) {
+       for (i = 0; i < MAX_EEPRO && io[i] != -1; i++) {
                dev = alloc_etherdev(sizeof(struct eepro_local));
                if (!dev)
                        break;
index 1686dca2874865a7d012bbc39bd9d77c63b305eb..1f016d66684ac79cecef3350487c35a716a19ba3 100644 (file)
@@ -1474,13 +1474,13 @@ static void eexp_hw_init586(struct net_device *dev)
        outw(0x0000, ioaddr + 0x800c);
        outw(0x0000, ioaddr + 0x800e);
 
-       for (i = 0; i < (sizeof(start_code)); i+=32) {
+       for (i = 0; i < ARRAY_SIZE(start_code) * 2; i+=32) {
                int j;
                outw(i, ioaddr + SM_PTR);
-               for (j = 0; j < 16; j+=2)
+               for (j = 0; j < 16 && (i+j)/2 < ARRAY_SIZE(start_code); j+=2)
                        outw(start_code[(i+j)/2],
                             ioaddr+0x4000+j);
-               for (j = 0; j < 16; j+=2)
+               for (j = 0; j < 16 && (i+j+16)/2 < ARRAY_SIZE(start_code); j+=2)
                        outw(start_code[(i+j+16)/2],
                             ioaddr+0x8000+j);
        }
index 78952f8324e222df8320162cbe8eb911af58a738..fa311a950996720895026f7e3e9d079165f5759c 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME       "ehea"
-#define DRV_VERSION    "EHEA_0101"
+#define DRV_VERSION    "EHEA_0102"
 
 /* eHEA capability flags */
 #define DLPAR_PORT_ADD_REM 1
index 147c4b088fb3c3467fa3b9027aa887067ccf8114..977c3d358279378086f2e82ee03ed21f31221dc7 100644 (file)
@@ -1545,6 +1545,9 @@ static int ehea_clean_portres(struct ehea_port *port, struct ehea_port_res *pr)
 {
        int ret, i;
 
+       if (pr->qp)
+               netif_napi_del(&pr->napi);
+
        ret = ehea_destroy_qp(pr->qp);
 
        if (!ret) {
@@ -3080,7 +3083,9 @@ static const struct net_device_ops ehea_netdev_ops = {
        .ndo_poll_controller    = ehea_netpoll,
 #endif
        .ndo_get_stats          = ehea_get_stats,
+       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = ehea_set_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_multicast_list = ehea_set_multicast_list,
        .ndo_change_mtu         = ehea_change_mtu,
        .ndo_vlan_rx_register   = ehea_vlan_rx_register,
index b60e27dfcfa7c24a3c576ca1f5713e30befb4d60..88d7ebf31220c701f7f8e09ca551fbdc0f121e79 100644 (file)
@@ -338,8 +338,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
 #ifndef MODULE
        static int printed_version;
        if (!printed_version++)
-               printk (KERN_INFO "%s" KERN_INFO "%s",
-                       version, version2);
+               printk(KERN_INFO "%s%s", version, version2);
 #endif
 
        card_idx++;
@@ -1600,7 +1599,7 @@ static int __init epic_init (void)
 {
 /* when a module, this is printed whether or not devices are found in probe */
 #ifdef MODULE
-       printk (KERN_INFO "%s" KERN_INFO "%s",
+       printk (KERN_INFO "%s%s",
                version, version2);
 #endif
 
index 891be28a7d4f43625ad5072c77b372e854564a01..160655d2458159c84ad1656554f853356ab6f98a 100644 (file)
@@ -584,7 +584,8 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
        if (np->flags == HAS_MII_XCVR) {
                int phy, phy_idx = 0;
 
-               for (phy = 1; phy < 32 && phy_idx < 4; phy++) {
+               for (phy = 1; phy < 32 && phy_idx < ARRAY_SIZE(np->phys);
+                              phy++) {
                        int mii_status = mdio_read(dev, phy, 1);
 
                        if (mii_status != 0xffff && mii_status != 0x0000) {
@@ -1209,17 +1210,20 @@ static void fealnx_tx_timeout(struct net_device *dev)
        unsigned long flags;
        int i;
 
-       printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
-              " resetting...\n", dev->name, ioread32(ioaddr + ISR));
+       printk(KERN_WARNING
+              "%s: Transmit timed out, status %8.8x, resetting...\n",
+              dev->name, ioread32(ioaddr + ISR));
 
        {
                printk(KERN_DEBUG "  Rx ring %p: ", np->rx_ring);
                for (i = 0; i < RX_RING_SIZE; i++)
-                       printk(" %8.8x", (unsigned int) np->rx_ring[i].status);
-               printk("\n" KERN_DEBUG "  Tx ring %p: ", np->tx_ring);
+                       printk(KERN_CONT " %8.8x",
+                              (unsigned int) np->rx_ring[i].status);
+               printk(KERN_CONT "\n");
+               printk(KERN_DEBUG "  Tx ring %p: ", np->tx_ring);
                for (i = 0; i < TX_RING_SIZE; i++)
-                       printk(" %4.4x", np->tx_ring[i].status);
-               printk("\n");
+                       printk(KERN_CONT " %4.4x", np->tx_ring[i].status);
+               printk(KERN_CONT "\n");
        }
 
        spin_lock_irqsave(&np->lock, flags);
index 0f19b743749bdf8b52783793276c36a247f3f928..c9fd82d3a80d0dba6290af1720a9f11ccd0ca460 100644 (file)
@@ -285,6 +285,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        struct bufdesc *bdp;
+       void *bufaddr;
        unsigned short  status;
        unsigned long flags;
 
@@ -312,7 +313,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        status &= ~BD_ENET_TX_STATS;
 
        /* Set buffer length and buffer pointer */
-       bdp->cbd_bufaddr = __pa(skb->data);
+       bufaddr = skb->data;
        bdp->cbd_datlen = skb->len;
 
        /*
@@ -320,11 +321,11 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
         * 4-byte boundaries. Use bounce buffers to copy data
         * and get it aligned. Ugh.
         */
-       if (bdp->cbd_bufaddr & FEC_ALIGNMENT) {
+       if (((unsigned long) bufaddr) & FEC_ALIGNMENT) {
                unsigned int index;
                index = bdp - fep->tx_bd_base;
                memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len);
-               bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]);
+               bufaddr = fep->tx_bounce[index];
        }
 
        /* Save skb pointer */
@@ -336,7 +337,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        /* Push the data cache so the CPM does not get stale memory
         * data.
         */
-       bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data,
+       bdp->cbd_bufaddr = dma_map_single(&dev->dev, bufaddr,
                        FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
 
        /* Send it on its way.  Tell FEC it's ready, interrupt when done,
@@ -1642,6 +1643,7 @@ static const struct net_device_ops fec_netdev_ops = {
        .ndo_stop               = fec_enet_close,
        .ndo_start_xmit         = fec_enet_start_xmit,
        .ndo_set_multicast_list = set_multicast_list,
+       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_tx_timeout         = fec_timeout,
        .ndo_set_mac_address    = fec_set_mac_address,
index 30b7dd671336b45434bdefff08c137da3ee8bf9a..cc47f3f057c7464b2f5096e7810bad46c9362cf7 100644 (file)
 
 #else
 
-#define FEC_ECNTRL;            0x000 /* Ethernet control reg */
-#define FEC_IEVENT;            0x004 /* Interrupt even reg */
-#define FEC_IMASK;             0x008 /* Interrupt mask reg */
-#define FEC_IVEC;              0x00c /* Interrupt vec status reg */
-#define FEC_R_DES_ACTIVE;      0x010 /* Receive descriptor reg */
-#define FEC_X_DES_ACTIVE;      0x01c /* Transmit descriptor reg */
+#define FEC_ECNTRL             0x000 /* Ethernet control reg */
+#define FEC_IEVENT             0x004 /* Interrupt even reg */
+#define FEC_IMASK              0x008 /* Interrupt mask reg */
+#define FEC_IVEC               0x00c /* Interrupt vec status reg */
+#define FEC_R_DES_ACTIVE       0x010 /* Receive descriptor reg */
+#define FEC_X_DES_ACTIVE       0x014 /* Transmit descriptor reg */
 #define FEC_MII_DATA           0x040 /* MII manage frame reg */
 #define FEC_MII_SPEED          0x044 /* MII speed control reg */
 #define FEC_R_BOUND            0x08c /* FIFO receive bound reg */
index cc786333d95c87cd84d34a1b189c43f9b60367c1..c40113f58963f9f765268141db1d78f367125a8c 100644 (file)
@@ -309,6 +309,7 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct mpc52xx_fec_priv *priv = netdev_priv(dev);
        struct bcom_fec_bd *bd;
+       unsigned long flags;
 
        if (bcom_queue_full(priv->tx_dmatsk)) {
                if (net_ratelimit())
@@ -316,7 +317,7 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev)
                return NETDEV_TX_BUSY;
        }
 
-       spin_lock_irq(&priv->lock);
+       spin_lock_irqsave(&priv->lock, flags);
        dev->trans_start = jiffies;
 
        bd = (struct bcom_fec_bd *)
@@ -332,7 +333,7 @@ static int mpc52xx_fec_start_xmit(struct sk_buff *skb, struct net_device *dev)
                netif_stop_queue(dev);
        }
 
-       spin_unlock_irq(&priv->lock);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        return NETDEV_TX_OK;
 }
index 1094d292630f758039802b2b23387a320250a5f1..3b4e0766c7b2a614be5c0451bb925e789c980bf3 100644 (file)
@@ -3514,11 +3514,13 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
        nv_msi_workaround(np);
 
 #ifdef CONFIG_FORCEDETH_NAPI
-       napi_schedule(&np->napi);
-
-       /* Disable furthur irq's
-          (msix not enabled with napi) */
-       writel(0, base + NvRegIrqMask);
+       if (napi_schedule_prep(&np->napi)) {
+               /*
+                * Disable further irq's (msix not enabled with napi)
+                */
+               writel(0, base + NvRegIrqMask);
+               __napi_schedule(&np->napi);
+       }
 
 #else
        do
@@ -3615,12 +3617,13 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
        nv_msi_workaround(np);
 
 #ifdef CONFIG_FORCEDETH_NAPI
-       napi_schedule(&np->napi);
-
-       /* Disable furthur irq's
-          (msix not enabled with napi) */
-       writel(0, base + NvRegIrqMask);
-
+       if (napi_schedule_prep(&np->napi)) {
+               /*
+                * Disable further irq's (msix not enabled with napi)
+                */
+               writel(0, base + NvRegIrqMask);
+               __napi_schedule(&np->napi);
+       }
 #else
        do
        {
index b892c3ad9a742de2957dd5b1a0c14be158d52b8c..2bc2d2b20644ba924f0031c512b9a8468cc46fa0 100644 (file)
@@ -754,17 +754,16 @@ static int fs_init_phy(struct net_device *dev)
        fep->oldlink = 0;
        fep->oldspeed = 0;
        fep->oldduplex = -1;
-       if(fep->fpi->phy_node)
-               phydev = of_phy_connect(dev, fep->fpi->phy_node,
-                                       &fs_adjust_link, 0,
-                                       PHY_INTERFACE_MODE_MII);
-       else {
-               printk("No phy bus ID specified in BSP code\n");
-               return -EINVAL;
+
+       phydev = of_phy_connect(dev, fep->fpi->phy_node, &fs_adjust_link, 0,
+                               PHY_INTERFACE_MODE_MII);
+       if (!phydev) {
+               phydev = of_phy_connect_fixed_link(dev, &fs_adjust_link,
+                                                  PHY_INTERFACE_MODE_MII);
        }
-       if (IS_ERR(phydev)) {
-               printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
-               return PTR_ERR(phydev);
+       if (!phydev) {
+               dev_err(&dev->dev, "Could not attach to PHY\n");
+               return -ENODEV;
        }
 
        fep->phydev = phydev;
@@ -1005,6 +1004,7 @@ static int __devinit fs_enet_probe(struct of_device *ofdev,
                goto out_free_fpi;
        }
 
+       SET_NETDEV_DEV(ndev, &ofdev->dev);
        dev_set_drvdata(&ofdev->dev, ndev);
 
        fep = netdev_priv(ndev);
index 3af581303ca2b79577d18d0df4d6c64b6d341152..d167090248e2f31d6ba7211e447e3bd68dc43da6 100644 (file)
@@ -188,7 +188,7 @@ static int fsl_pq_mdio_find_free(struct mii_bus *new_bus)
 }
 
 
-#ifdef CONFIG_GIANFAR
+#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE)
 static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs)
 {
        struct gfar __iomem *enet_regs;
@@ -206,7 +206,7 @@ static u32 __iomem *get_gfar_tbipa(struct fsl_pq_mdio __iomem *regs)
 #endif
 
 
-#ifdef CONFIG_UCC_GETH
+#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE)
 static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id)
 {
        struct device_node *np = NULL;
@@ -291,7 +291,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev,
        if (of_device_is_compatible(np, "fsl,gianfar-mdio") ||
                        of_device_is_compatible(np, "fsl,gianfar-tbi") ||
                        of_device_is_compatible(np, "gianfar")) {
-#ifdef CONFIG_GIANFAR
+#if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE)
                tbipa = get_gfar_tbipa(regs);
 #else
                err = -ENODEV;
@@ -299,7 +299,7 @@ static int fsl_pq_mdio_probe(struct of_device *ofdev,
 #endif
        } else if (of_device_is_compatible(np, "fsl,ucc-mdio") ||
                        of_device_is_compatible(np, "ucc_geth_phy")) {
-#ifdef CONFIG_UCC_GETH
+#if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE)
                u32 id;
                static u32 mii_mng_master;
 
index 4ae1d259fced7d6525a6818a1c641db5d1cf3850..a00ec639c38039ad56f17706a5441cabe2c3fc20 100644 (file)
@@ -156,6 +156,8 @@ static const struct net_device_ops gfar_netdev_ops = {
        .ndo_tx_timeout = gfar_timeout,
        .ndo_do_ioctl = gfar_ioctl,
        .ndo_vlan_rx_register = gfar_vlan_rx_register,
+       .ndo_set_mac_address = eth_mac_addr,
+       .ndo_validate_addr = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = gfar_netpoll,
 #endif
@@ -262,15 +264,6 @@ static int gfar_of_init(struct net_device *dev)
                priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;
 
        priv->phy_node = of_parse_phandle(np, "phy-handle", 0);
-       if (!priv->phy_node) {
-               u32 *fixed_link;
-
-               fixed_link = (u32 *)of_get_property(np, "fixed-link", NULL);
-               if (!fixed_link) {
-                       err = -ENODEV;
-                       goto err_out;
-               }
-       }
 
        /* Find the TBI PHY.  If it's not there, we don't support SGMII */
        priv->tbi_node = of_parse_phandle(np, "tbi-handle", 0);
@@ -498,6 +491,7 @@ static int gfar_remove(struct of_device *ofdev)
 
        dev_set_drvdata(&ofdev->dev, NULL);
 
+       unregister_netdev(priv->ndev);
        iounmap(priv->regs);
        free_netdev(priv->ndev);
 
@@ -657,13 +651,14 @@ static int init_phy(struct net_device *dev)
 
        interface = gfar_get_interface(dev);
 
-       if (priv->phy_node) {
-               priv->phydev = of_phy_connect(dev, priv->phy_node, &adjust_link,
-                                             0, interface);
-               if (!priv->phydev) {
-                       dev_err(&dev->dev, "error: Could not attach to PHY\n");
-                       return -ENODEV;
-               }
+       priv->phydev = of_phy_connect(dev, priv->phy_node, &adjust_link, 0,
+                                     interface);
+       if (!priv->phydev)
+               priv->phydev = of_phy_connect_fixed_link(dev, &adjust_link,
+                                                        interface);
+       if (!priv->phydev) {
+               dev_err(&dev->dev, "could not attach to PHY\n");
+               return -ENODEV;
        }
 
        if (interface == PHY_INTERFACE_MODE_SGMII)
@@ -942,6 +937,7 @@ int startup_gfar(struct net_device *dev)
        struct gfar __iomem *regs = priv->regs;
        int err = 0;
        u32 rctrl = 0;
+       u32 tctrl = 0;
        u32 attrs = 0;
 
        gfar_write(&regs->imask, IMASK_INIT_CLEAR);
@@ -1117,11 +1113,19 @@ int startup_gfar(struct net_device *dev)
                rctrl |= RCTRL_PADDING(priv->padding);
        }
 
+       /* keep vlan related bits if it's enabled */
+       if (priv->vlgrp) {
+               rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
+               tctrl |= TCTRL_VLINS;
+       }
+
        /* Init rctrl based on our settings */
        gfar_write(&priv->regs->rctrl, rctrl);
 
        if (dev->features & NETIF_F_IP_CSUM)
-               gfar_write(&priv->regs->tctrl, TCTRL_INIT_CSUM);
+               tctrl |= TCTRL_INIT_CSUM;
+
+       gfar_write(&priv->regs->tctrl, tctrl);
 
        /* Set the extraction length and index */
        attrs = ATTRELI_EL(priv->rx_stash_size) |
@@ -1456,7 +1460,6 @@ static void gfar_vlan_rx_register(struct net_device *dev,
 
                /* Enable VLAN tag extraction */
                tempval = gfar_read(&priv->regs->rctrl);
-               tempval |= RCTRL_VLEX;
                tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT);
                gfar_write(&priv->regs->rctrl, tempval);
        } else {
index dbf06e9313cc27750362aa59ab6bb779051f81b8..2234118eedbb66a2aa1c884aab228332f0706d0a 100644 (file)
@@ -366,9 +366,8 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
                return -EINVAL;
        }
 
-       priv->rxic = mk_ic_value(
-               gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs),
-               cvals->rx_max_coalesced_frames);
+       priv->rxic = mk_ic_value(cvals->rx_max_coalesced_frames,
+               gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs));
 
        /* Set up tx coalescing */
        if ((cvals->tx_coalesce_usecs == 0) ||
@@ -390,9 +389,8 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
                return -EINVAL;
        }
 
-       priv->txic = mk_ic_value(
-               gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs),
-               cvals->tx_max_coalesced_frames);
+       priv->txic = mk_ic_value(cvals->tx_max_coalesced_frames,
+               gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs));
 
        gfar_write(&priv->regs->rxic, 0);
        if (priv->rxcoalescing)
index 9d5b62cb30f790de7f198b4d67e7e619b82d7878..d62378cbc149ee6bb502953da22515689d737f6b 100644 (file)
@@ -173,8 +173,8 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 
 static const char version[] __devinitconst =
 KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Written by Donald Becker\n"
-KERN_INFO "   Some modifications by Eric kasten <kasten@nscl.msu.edu>\n"
-KERN_INFO "   Further modifications by Keith Underwood <keithu@parl.clemson.edu>\n";
+"   Some modifications by Eric kasten <kasten@nscl.msu.edu>\n"
+"   Further modifications by Keith Underwood <keithu@parl.clemson.edu>\n";
 
 
 /* IP_MF appears to be only defined in <netinet/ip.h>, however,
@@ -1080,11 +1080,14 @@ static void hamachi_tx_timeout(struct net_device *dev)
        {
                printk(KERN_DEBUG "  Rx ring %p: ", hmp->rx_ring);
                for (i = 0; i < RX_RING_SIZE; i++)
-                       printk(" %8.8x", le32_to_cpu(hmp->rx_ring[i].status_n_length));
-               printk("\n"KERN_DEBUG"  Tx ring %p: ", hmp->tx_ring);
+                       printk(KERN_CONT " %8.8x",
+                              le32_to_cpu(hmp->rx_ring[i].status_n_length));
+               printk(KERN_CONT "\n");
+               printk(KERN_DEBUG"  Tx ring %p: ", hmp->tx_ring);
                for (i = 0; i < TX_RING_SIZE; i++)
-                       printk(" %4.4x", le32_to_cpu(hmp->tx_ring[i].status_n_length));
-               printk("\n");
+                       printk(KERN_CONT " %4.4x",
+                              le32_to_cpu(hmp->tx_ring[i].status_n_length));
+               printk(KERN_CONT "\n");
        }
 
        /* Reinit the hardware and make sure the Rx and Tx processes
@@ -1753,13 +1756,13 @@ static int hamachi_close(struct net_device *dev)
 
 #ifdef __i386__
        if (hamachi_debug > 2) {
-               printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n",
+               printk(KERN_DEBUG "  Tx ring at %8.8x:\n",
                           (int)hmp->tx_ring_dma);
                for (i = 0; i < TX_RING_SIZE; i++)
-                       printk(" %c #%d desc. %8.8x %8.8x.\n",
+                       printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x.\n",
                                   readl(ioaddr + TxCurPtr) == (long)&hmp->tx_ring[i] ? '>' : ' ',
                                   i, hmp->tx_ring[i].status_n_length, hmp->tx_ring[i].addr);
-               printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n",
+               printk(KERN_DEBUG "  Rx ring %8.8x:\n",
                           (int)hmp->rx_ring_dma);
                for (i = 0; i < RX_RING_SIZE; i++) {
                        printk(KERN_DEBUG " %c #%d desc. %4.4x %8.8x\n",
@@ -1770,7 +1773,7 @@ static int hamachi_close(struct net_device *dev)
                                        u16 *addr = (u16 *)
                                                hmp->rx_skbuff[i]->data;
                                        int j;
-
+                                       printk(KERN_DEBUG "Addr: ");
                                        for (j = 0; j < 0x50; j++)
                                                printk(" %4.4x", addr[j]);
                                        printk("\n");
index 155160052c8bd5dc690c1bfe04b253654e739cab..981ab530e9aca771028a1a4f636a514fb19bf18c 100644 (file)
@@ -3,7 +3,7 @@
  *             devices like TTY. It interfaces between a raw TTY and the
  *             kernel's AX.25 protocol layers.
  *
- * Authors:    Andreas Könsgen <ajk@iehk.rwth-aachen.de>
+ * Authors:    Andreas Könsgen <ajk@comnets.uni-bremen.de>
  *              Ralf Baechle DL5RB <ralf@linux-mips.org>
  *
  * Quite a lot of stuff "stolen" by Joerg Reuter from slip.c, written by
index 5e4b7afd068395b343f5ad267673eed7090e197a..352703255bba8a8c4efc9dec9454487078686713 100644 (file)
@@ -68,7 +68,7 @@ static const char paranoia_str[] = KERN_ERR
 
 static const char bc_drvname[] = "baycom_epp";
 static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n";
+"baycom_epp: version 0.7 compiled " __TIME__ " " __DATE__ "\n";
 
 /* --------------------------------------------------------------------- */
 
index 2e6fc4dc74b12c9ccbb66a5469752b65109484e4..5f5af9a606f8aaddbb4b8724a651db14e5ecee05 100644 (file)
 
 static const char bc_drvname[] = "baycom_par";
 static const char bc_drvinfo[] = KERN_INFO "baycom_par: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "baycom_par: version 0.9 compiled " __TIME__ " " __DATE__ "\n";
+"baycom_par: version 0.9 compiled " __TIME__ " " __DATE__ "\n";
 
 /* --------------------------------------------------------------------- */
 
index b6a816e60c0f74593b5e24d4cdded1115a6cc38b..aa4488e871b24d0497d3fcb92bf1954e01eab29d 100644 (file)
@@ -91,7 +91,7 @@
 
 static const char bc_drvname[] = "baycom_ser_fdx";
 static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "baycom_ser_fdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n";
+"baycom_ser_fdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n";
 
 /* --------------------------------------------------------------------- */
 
index 3bcc57acbe6d9515ec49922fd2a529f27a8b2418..88c59359602029440c00c947cb77f3351e23ef54 100644 (file)
@@ -79,7 +79,7 @@
 
 static const char bc_drvname[] = "baycom_ser_hdx";
 static const char bc_drvinfo[] = KERN_INFO "baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
-KERN_INFO "baycom_ser_hdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n";
+"baycom_ser_hdx: version 0.10 compiled " __TIME__ " " __DATE__ "\n";
 
 /* --------------------------------------------------------------------- */
 
index beb84213b6719ba614641e56af5862dd5581ad9e..f0f890803710bed42418201bf2bb4fa58f25cb99 100644 (file)
@@ -1305,6 +1305,8 @@ static int emac_close(struct net_device *ndev)
 
        free_irq(dev->emac_irq, dev);
 
+       netif_carrier_off(ndev);
+
        return 0;
 }
 
index 1d5379de6900f5558e8130b0e4c84b5e3e85f818..8d76cb89dbd61e6d252ed30fbe1bf211f5081732 100644 (file)
@@ -188,11 +188,12 @@ void rgmii_put_mdio(struct of_device *ofdev, int input)
 void rgmii_detach(struct of_device *ofdev, int input)
 {
        struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
-       struct rgmii_regs __iomem *p = dev->base;
-
-       mutex_lock(&dev->lock);
+       struct rgmii_regs __iomem *p;
 
        BUG_ON(!dev || dev->users == 0);
+       p = dev->base;
+
+       mutex_lock(&dev->lock);
 
        RGMII_DBG(dev, "detach(%d)" NL, input);
 
index efd9be214885cbc4c5c5282df7072aee901beff9..ac28dd5a4fd137f7cd522bbcf20fb3338ecffc38 100644 (file)
@@ -190,6 +190,10 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
                phy->ops.write_reg          = igb_write_phy_reg_igp;
        }
 
+       /* set lan id */
+       hw->bus.func = (rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) >>
+                      E1000_STATUS_FUNC_SHIFT;
+
        /* Set phy->phy_addr and phy->id. */
        ret_val = igb_get_phy_id_82575(hw);
        if (ret_val)
index ea17319624aa7cc3c2cc51c1ae04044f69e14dba..adb09d32625df3c2b4a565324f17927ed2db033d 100644 (file)
@@ -127,14 +127,48 @@ static void igb_restore_vlan(struct igb_adapter *);
 static void igb_ping_all_vfs(struct igb_adapter *);
 static void igb_msg_task(struct igb_adapter *);
 static int igb_rcv_msg_from_vf(struct igb_adapter *, u32);
-static inline void igb_set_rah_pool(struct e1000_hw *, int , int);
 static void igb_set_mc_list_pools(struct igb_adapter *, int, u16);
 static void igb_vmm_control(struct igb_adapter *);
-static inline void igb_set_vmolr(struct e1000_hw *, int);
-static inline int igb_set_vf_rlpml(struct igb_adapter *, int, int);
 static int igb_set_vf_mac(struct igb_adapter *adapter, int, unsigned char *);
 static void igb_restore_vf_multicasts(struct igb_adapter *adapter);
 
+static inline void igb_set_vmolr(struct e1000_hw *hw, int vfn)
+{
+       u32 reg_data;
+
+       reg_data = rd32(E1000_VMOLR(vfn));
+       reg_data |= E1000_VMOLR_BAM |    /* Accept broadcast */
+                   E1000_VMOLR_ROPE |   /* Accept packets matched in UTA */
+                   E1000_VMOLR_ROMPE |  /* Accept packets matched in MTA */
+                   E1000_VMOLR_AUPE |   /* Accept untagged packets */
+                   E1000_VMOLR_STRVLAN; /* Strip vlan tags */
+       wr32(E1000_VMOLR(vfn), reg_data);
+}
+
+static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
+                                 int vfn)
+{
+       struct e1000_hw *hw = &adapter->hw;
+       u32 vmolr;
+
+       vmolr = rd32(E1000_VMOLR(vfn));
+       vmolr &= ~E1000_VMOLR_RLPML_MASK;
+       vmolr |= size | E1000_VMOLR_LPE;
+       wr32(E1000_VMOLR(vfn), vmolr);
+
+       return 0;
+}
+
+static inline void igb_set_rah_pool(struct e1000_hw *hw, int pool, int entry)
+{
+       u32 reg_data;
+
+       reg_data = rd32(E1000_RAH(entry));
+       reg_data &= ~E1000_RAH_POOL_MASK;
+       reg_data |= E1000_RAH_POOL_1 << pool;;
+       wr32(E1000_RAH(entry), reg_data);
+}
+
 #ifdef CONFIG_PM
 static int igb_suspend(struct pci_dev *, pm_message_t);
 static int igb_resume(struct pci_dev *);
@@ -4549,11 +4583,12 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring,
                cleaned = true;
                cleaned_count++;
 
+               /* this is the fast path for the non-packet split case */
                if (!adapter->rx_ps_hdr_size) {
                        pci_unmap_single(pdev, buffer_info->dma,
-                                        adapter->rx_buffer_len +
-                                          NET_IP_ALIGN,
+                                        adapter->rx_buffer_len,
                                         PCI_DMA_FROMDEVICE);
+                       buffer_info->dma = 0;
                        skb_put(skb, length);
                        goto send_up;
                }
@@ -4570,8 +4605,9 @@ static bool igb_clean_rx_irq_adv(struct igb_ring *rx_ring,
 
                if (!skb_shinfo(skb)->nr_frags) {
                        pci_unmap_single(pdev, buffer_info->dma,
-                                        adapter->rx_ps_hdr_size + NET_IP_ALIGN,
+                                        adapter->rx_ps_hdr_size,
                                         PCI_DMA_FROMDEVICE);
+                       buffer_info->dma = 0;
                        skb_put(skb, hlen);
                }
 
@@ -4713,7 +4749,6 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring,
                bufsz = adapter->rx_ps_hdr_size;
        else
                bufsz = adapter->rx_buffer_len;
-       bufsz += NET_IP_ALIGN;
 
        while (cleaned_count--) {
                rx_desc = E1000_RX_DESC_ADV(*rx_ring, i);
@@ -4737,7 +4772,7 @@ static void igb_alloc_rx_buffers_adv(struct igb_ring *rx_ring,
                }
 
                if (!buffer_info->skb) {
-                       skb = netdev_alloc_skb(netdev, bufsz);
+                       skb = netdev_alloc_skb(netdev, bufsz + NET_IP_ALIGN);
                        if (!skb) {
                                adapter->alloc_rx_buff_failed++;
                                goto no_buffers;
@@ -5338,6 +5373,9 @@ static pci_ers_result_t igb_io_error_detected(struct pci_dev *pdev,
 
        netif_device_detach(netdev);
 
+       if (state == pci_channel_io_perm_failure)
+               return PCI_ERS_RESULT_DISCONNECT;
+
        if (netif_running(netdev))
                igb_down(adapter);
        pci_disable_device(pdev);
@@ -5414,43 +5452,6 @@ static void igb_io_resume(struct pci_dev *pdev)
        igb_get_hw_control(adapter);
 }
 
-static inline void igb_set_vmolr(struct e1000_hw *hw, int vfn)
-{
-       u32 reg_data;
-
-       reg_data = rd32(E1000_VMOLR(vfn));
-       reg_data |= E1000_VMOLR_BAM |    /* Accept broadcast */
-                   E1000_VMOLR_ROPE |   /* Accept packets matched in UTA */
-                   E1000_VMOLR_ROMPE |  /* Accept packets matched in MTA */
-                   E1000_VMOLR_AUPE |   /* Accept untagged packets */
-                   E1000_VMOLR_STRVLAN; /* Strip vlan tags */
-       wr32(E1000_VMOLR(vfn), reg_data);
-}
-
-static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size,
-                                 int vfn)
-{
-       struct e1000_hw *hw = &adapter->hw;
-       u32 vmolr;
-
-       vmolr = rd32(E1000_VMOLR(vfn));
-       vmolr &= ~E1000_VMOLR_RLPML_MASK;
-       vmolr |= size | E1000_VMOLR_LPE;
-       wr32(E1000_VMOLR(vfn), vmolr);
-
-       return 0;
-}
-
-static inline void igb_set_rah_pool(struct e1000_hw *hw, int pool, int entry)
-{
-       u32 reg_data;
-
-       reg_data = rd32(E1000_RAH(entry));
-       reg_data &= ~E1000_RAH_POOL_MASK;
-       reg_data |= E1000_RAH_POOL_1 << pool;;
-       wr32(E1000_RAH(entry), reg_data);
-}
-
 static void igb_set_mc_list_pools(struct igb_adapter *adapter,
                                  int entry_count, u16 total_rar_filters)
 {
index 2a4faf9ade69d7893a73d67e57411f1bab85eb24..a9a61efa964cf7b7cc32b439952ed2a444fa1ebe 100644 (file)
@@ -274,6 +274,8 @@ static s32 e1000_set_vfta_vf(struct e1000_hw *hw, u16 vid, bool set)
 
        err = mbx->ops.read_posted(hw, msgbuf, 2);
 
+       msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS;
+
        /* if nacked the vlan was rejected */
        if (!err && (msgbuf[0] == (E1000_VF_SET_VLAN | E1000_VT_MSGTYPE_NACK)))
                err = -E1000_ERR_MAC_INIT;
@@ -317,6 +319,8 @@ static void e1000_rar_set_vf(struct e1000_hw *hw, u8 * addr, u32 index)
        if (!ret_val)
                ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
 
+       msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS;
+
        /* if nacked the address was rejected, use "perm_addr" */
        if (!ret_val &&
            (msgbuf[0] == (E1000_VF_SET_MAC_ADDR | E1000_VT_MSGTYPE_NACK)))
index c4361d466597c50963c9a0dc594c6cd3b3e41b7e..ee1cff5c9b21cb1918589cbe555d1706402eac60 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
-#include <linux/etherdevice.h>
 #include <linux/slab.h>
 #include <linux/rtnetlink.h>
 #include <linux/interrupt.h>
@@ -205,9 +204,6 @@ static const struct net_device_ops au1k_irda_netdev_ops = {
        .ndo_start_xmit         = au1k_irda_hard_xmit,
        .ndo_tx_timeout         = au1k_tx_timeout,
        .ndo_do_ioctl           = au1k_irda_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
 };
 
 static int au1k_irda_net_init(struct net_device *dev)
index f3eed6a8fba5e154df75dc1d0f901aef083a0681..911c082cee5acfa258211b117c1f018bcd9dbb49 100644 (file)
@@ -677,6 +677,14 @@ static int bfin_sir_init_iobuf(iobuff_t *io, int size)
        return 0;
 }
 
+static const struct net_device_ops bfin_sir_ndo = {
+       .ndo_open               = bfin_sir_open,
+       .ndo_stop               = bfin_sir_stop,
+       .ndo_start_xmit         = bfin_sir_hard_xmit,
+       .ndo_do_ioctl           = bfin_sir_ioctl,
+       .ndo_get_stats          = bfin_sir_stats,
+};
+
 static int __devinit bfin_sir_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
@@ -718,12 +726,8 @@ static int __devinit bfin_sir_probe(struct platform_device *pdev)
        if (err)
                goto err_mem_3;
 
-       dev->hard_start_xmit = bfin_sir_hard_xmit;
-       dev->open            = bfin_sir_open;
-       dev->stop            = bfin_sir_stop;
-       dev->do_ioctl        = bfin_sir_ioctl;
-       dev->get_stats       = bfin_sir_stats;
-       dev->irq             = sir_port->irq;
+       dev->netdev_ops = &bfin_sir_ndo;
+       dev->irq = sir_port->irq;
 
        irda_init_max_qos_capabilies(&self->qos);
 
index d53aa9582137d241f0cdf22e092de488ec81efb9..20f9bc6266882eae0dae82707d9935f6bee1b8d4 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/tty.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
-#include <linux/smp_lock.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
 
index 3376a4f39e0a1eb02b6287a9355159c3aca7fc0f..77d10edefd2579cd06c7e53f065bdf3dda7a96e7 100644 (file)
@@ -803,9 +803,6 @@ static const struct net_device_ops pxa_irda_netdev_ops = {
        .ndo_stop               = pxa_irda_stop,
        .ndo_start_xmit         = pxa_irda_hard_xmit,
        .ndo_do_ioctl           = pxa_irda_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
 };
 
 static int pxa_irda_probe(struct platform_device *pdev)
@@ -830,6 +827,7 @@ static int pxa_irda_probe(struct platform_device *pdev)
        if (!dev)
                goto err_mem_3;
 
+       SET_NETDEV_DEV(dev, &pdev->dev);
        si = netdev_priv(dev);
        si->dev = &pdev->dev;
        si->pdata = pdev->dev.platform_data;
index 2aeb2e6aec1bb583e6867d4716f85f5eec3bfa83..b039cb081e943c24ca6ee464c05f9a5b7b6f2c0f 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
-#include <linux/etherdevice.h>
 #include <linux/slab.h>
 #include <linux/rtnetlink.h>
 #include <linux/interrupt.h>
@@ -881,9 +880,6 @@ static const struct net_device_ops sa1100_irda_netdev_ops = {
        .ndo_stop               = sa1100_irda_stop,
        .ndo_start_xmit         = sa1100_irda_hard_xmit,
        .ndo_do_ioctl           = sa1100_irda_ioctl,
-       .ndo_change_mtu         = eth_change_mtu,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
 };
 
 static int sa1100_irda_probe(struct platform_device *pdev)
index d0883835b0c6e0a179ac8107daaba9e6c204771f..fe4f2b2bff96dc579791cd5c1f41e832f3c51ccc 100644 (file)
@@ -115,7 +115,7 @@ static int __init w83977af_init(void)
 
        IRDA_DEBUG(0, "%s()\n", __func__ );
 
-       for (i=0; (io[i] < 2000) && (i < ARRAY_SIZE(dev_self)); i++) {
+       for (i=0; i < ARRAY_SIZE(dev_self) && io[i] < 2000; i++) {
                if (w83977af_open(i, io[i], irq[i], dma[i]) == 0)
                        return 0;
        }
index 73585fd8f29fdaee4a4647e6cdebe986c396e5ff..d12377b843581c1947fd1bdb33b9e9fe6d6ca4e4 100644 (file)
@@ -430,7 +430,8 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
         * hardware interrupt handler.  Queue flow control is
         * thus managed under this lock as well.
         */
-       spin_lock_irq(&np->lock);
+       unsigned long flags;
+       spin_lock_irqsave(&np->lock, flags);
 
        add_to_tx_ring(np, skb, length);
        dev->trans_start = jiffies;
@@ -446,7 +447,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
         * is when the transmit statistics are updated.
         */
 
-       spin_unlock_irq(&np->lock);
+       spin_unlock_irqrestore(&np->lock, flags);
 #else
        /* This is the case for older hardware which takes
         * a single transmit buffer at a time, and it is
index cd22323cfd2276009b15bf0254bdcfbbafce00e5..2c4dc8221dcd9d7f102ab29543e682fc23926332 100644 (file)
@@ -96,6 +96,8 @@
 #define IXGBE_TX_FLAGS_VLAN_PRIO_MASK   0x0000e000
 #define IXGBE_TX_FLAGS_VLAN_SHIFT      16
 
+#define IXGBE_MAX_RSC_INT_RATE          162760
+
 /* wrapper around a pointer to a socket buffer,
  * so a DMA handle can be stored along with the buffer */
 struct ixgbe_tx_buffer {
@@ -134,6 +136,8 @@ struct ixgbe_ring {
 
        u8 queue_index; /* needed for multiqueue queue management */
 
+#define IXGBE_RING_RX_PS_ENABLED                (u8)(1)
+       u8 flags;                       /* per ring feature flags */
        u16 head;
        u16 tail;
 
@@ -327,6 +331,7 @@ struct ixgbe_adapter {
 #define IXGBE_FLAG_IN_SFP_MOD_TASK              (u32)(1 << 25)
 #define IXGBE_FLAG_FDIR_HASH_CAPABLE            (u32)(1 << 26)
 #define IXGBE_FLAG_FDIR_PERFECT_CAPABLE         (u32)(1 << 27)
+#define IXGBE_FLAG_FCOE_CAPABLE                 (u32)(1 << 28)
 #define IXGBE_FLAG_FCOE_ENABLED                 (u32)(1 << 29)
 
        u32 flags2;
index b9923047ce11469a2e5fb82369d7b00ec4845e24..522c03bc1dad8da4bd03138115e9177f935e9bc2 100644 (file)
@@ -49,6 +49,51 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw,
 static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
                                        u8 *eeprom_data);
 
+/**
+ *  ixgbe_set_pcie_completion_timeout - set pci-e completion timeout
+ *  @hw: pointer to the HW structure
+ *
+ *  The defaults for 82598 should be in the range of 50us to 50ms,
+ *  however the hardware default for these parts is 500us to 1ms which is less
+ *  than the 10ms recommended by the pci-e spec.  To address this we need to
+ *  increase the value to either 10ms to 250ms for capability version 1 config,
+ *  or 16ms to 55ms for version 2.
+ **/
+void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw)
+{
+       struct ixgbe_adapter *adapter = hw->back;
+       u32 gcr = IXGBE_READ_REG(hw, IXGBE_GCR);
+       u16 pcie_devctl2;
+
+       /* only take action if timeout value is defaulted to 0 */
+       if (gcr & IXGBE_GCR_CMPL_TMOUT_MASK)
+               goto out;
+
+       /*
+        * if capababilities version is type 1 we can write the
+        * timeout of 10ms to 250ms through the GCR register
+        */
+       if (!(gcr & IXGBE_GCR_CAP_VER2)) {
+               gcr |= IXGBE_GCR_CMPL_TMOUT_10ms;
+               goto out;
+       }
+
+       /*
+        * for version 2 capabilities we need to write the config space
+        * directly in order to set the completion timeout value for
+        * 16ms to 55ms
+        */
+       pci_read_config_word(adapter->pdev,
+                            IXGBE_PCI_DEVICE_CONTROL2, &pcie_devctl2);
+       pcie_devctl2 |= IXGBE_PCI_DEVICE_CONTROL2_16ms;
+       pci_write_config_word(adapter->pdev,
+                             IXGBE_PCI_DEVICE_CONTROL2, pcie_devctl2);
+out:
+       /* disable completion timeout resend */
+       gcr &= ~IXGBE_GCR_CMPL_TMOUT_RESEND;
+       IXGBE_WRITE_REG(hw, IXGBE_GCR, gcr);
+}
+
 /**
  *  ixgbe_get_pcie_msix_count_82598 - Gets MSI-X vector count
  *  @hw: pointer to hardware structure
@@ -152,6 +197,26 @@ out:
        return ret_val;
 }
 
+/**
+ *  ixgbe_start_hw_82598 - Prepare hardware for Tx/Rx
+ *  @hw: pointer to hardware structure
+ *
+ *  Starts the hardware using the generic start_hw function.
+ *  Then set pcie completion timeout
+ **/
+s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw)
+{
+       s32 ret_val = 0;
+
+       ret_val = ixgbe_start_hw_generic(hw);
+
+       /* set the completion timeout for interface */
+       if (ret_val == 0)
+               ixgbe_set_pcie_completion_timeout(hw);
+
+       return ret_val;
+}
+
 /**
  *  ixgbe_get_link_capabilities_82598 - Determines link capabilities
  *  @hw: pointer to hardware structure
@@ -1085,7 +1150,7 @@ out:
 static struct ixgbe_mac_operations mac_ops_82598 = {
        .init_hw                = &ixgbe_init_hw_generic,
        .reset_hw               = &ixgbe_reset_hw_82598,
-       .start_hw               = &ixgbe_start_hw_generic,
+       .start_hw               = &ixgbe_start_hw_82598,
        .clear_hw_cntrs         = &ixgbe_clear_hw_cntrs_generic,
        .get_media_type         = &ixgbe_get_media_type_82598,
        .get_supported_physical_layer = &ixgbe_get_supported_physical_layer_82598,
index d56890f5c9d53f736c1ba58c5c1d73f5e2c131d2..1c7265732900643ce27365c23212613c9d674c8d 100644 (file)
@@ -106,8 +106,6 @@ static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
-       DPRINTK(DRV, INFO, "Get DCB Admin Mode.\n");
-
        return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED);
 }
 
@@ -116,8 +114,6 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
        u8 err = 0;
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
-       DPRINTK(DRV, INFO, "Set DCB Admin Mode.\n");
-
        if (state > 0) {
                /* Turn on DCB */
                if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
@@ -138,7 +134,23 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
                        adapter->hw.fc.requested_mode = ixgbe_fc_none;
                }
                adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
+               if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+                       adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
+                       adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+               }
                adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
+#ifdef IXGBE_FCOE
+               /* Turn on FCoE offload */
+               if ((adapter->flags & IXGBE_FLAG_FCOE_CAPABLE) &&
+                   (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))) {
+                       adapter->flags |= IXGBE_FLAG_FCOE_ENABLED;
+                       adapter->ring_feature[RING_F_FCOE].indices =
+                               IXGBE_FCRETA_SIZE;
+                       netdev->features |= NETIF_F_FCOE_CRC;
+                       netdev->features |= NETIF_F_FSO;
+                       netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1;
+               }
+#endif /* IXGBE_FCOE */
                ixgbe_init_interrupt_scheme(adapter);
                if (netif_running(netdev))
                        netdev->netdev_ops->ndo_open(netdev);
@@ -154,6 +166,20 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
                        adapter->dcb_cfg.pfc_mode_enable = false;
                        adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
                        adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
+                       if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+                               adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+
+#ifdef IXGBE_FCOE
+                       /* Turn off FCoE offload */
+                       if (adapter->flags & (IXGBE_FLAG_FCOE_CAPABLE |
+                            IXGBE_FLAG_FCOE_ENABLED)) {
+                               adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
+                               adapter->ring_feature[RING_F_FCOE].indices = 0;
+                               netdev->features &= ~NETIF_F_FCOE_CRC;
+                               netdev->features &= ~NETIF_F_FSO;
+                               netdev->fcoe_ddp_xid = 0;
+                       }
+#endif /* IXGBE_FCOE */
                        ixgbe_init_interrupt_scheme(adapter);
                        if (netif_running(netdev))
                                netdev->netdev_ops->ndo_open(netdev);
@@ -169,6 +195,8 @@ static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev,
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
        int i, j;
 
+       memset(perm_addr, 0xff, MAX_ADDR_LEN);
+
        for (i = 0; i < netdev->addr_len; i++)
                perm_addr[i] = adapter->hw.mac.perm_addr[i];
 
index 86f4f3e36f27fc8d3ff0cccd734d8d691694bbd3..dff8dfac7ed99edbedd1eed40e8a052a8eef2b88 100644 (file)
@@ -139,7 +139,7 @@ static int ixgbe_get_settings(struct net_device *netdev,
        ecmd->autoneg = AUTONEG_ENABLE;
        ecmd->transceiver = XCVR_EXTERNAL;
        if ((hw->phy.media_type == ixgbe_media_type_copper) ||
-           (hw->mac.type == ixgbe_mac_82599EB)) {
+           (hw->phy.multispeed_fiber)) {
                ecmd->supported |= (SUPPORTED_1000baseT_Full |
                                    SUPPORTED_Autoneg);
 
@@ -217,7 +217,7 @@ static int ixgbe_set_settings(struct net_device *netdev,
        s32 err = 0;
 
        if ((hw->phy.media_type == ixgbe_media_type_copper) ||
-           (hw->mac.type == ixgbe_mac_82599EB)) {
+           (hw->phy.multispeed_fiber)) {
                /* 10000/copper and 1000/copper must autoneg
                 * this function does not support any duplex forcing, but can
                 * limit the advertising of the adapter to only 10000 or 1000 */
@@ -245,6 +245,7 @@ static int ixgbe_set_settings(struct net_device *netdev,
        } else {
                /* in this case we currently only support 10Gb/FULL */
                if ((ecmd->autoneg == AUTONEG_ENABLE) ||
+                   (ecmd->advertising != ADVERTISED_10000baseT_Full) ||
                    (ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL))
                        return -EINVAL;
        }
@@ -1829,7 +1830,6 @@ static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter,
                break;
        default:
                wol->supported = 0;
-               retval = 0;
        }
 
        return retval;
@@ -1948,6 +1948,7 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                               struct ethtool_coalesce *ec)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
+       struct ixgbe_q_vector *q_vector;
        int i;
 
        if (ec->tx_max_coalesced_frames_irq)
@@ -1975,18 +1976,31 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
                 * any other value means disable eitr, which is best
                 * served by setting the interrupt rate very high
                 */
-               adapter->eitr_param = IXGBE_MAX_INT_RATE;
+               if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
+                       adapter->eitr_param = IXGBE_MAX_RSC_INT_RATE;
+               else
+                       adapter->eitr_param = IXGBE_MAX_INT_RATE;
                adapter->itr_setting = 0;
        }
 
-       for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) {
-               struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
-               if (q_vector->txr_count && !q_vector->rxr_count)
-                       /* tx vector gets half the rate */
-                       q_vector->eitr = (adapter->eitr_param >> 1);
-               else
-                       /* rx only or mixed */
-                       q_vector->eitr = adapter->eitr_param;
+       /* MSI/MSIx Interrupt Mode */
+       if (adapter->flags &
+           (IXGBE_FLAG_MSIX_ENABLED | IXGBE_FLAG_MSI_ENABLED)) {
+               int num_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+               for (i = 0; i < num_vectors; i++) {
+                       q_vector = adapter->q_vector[i];
+                       if (q_vector->txr_count && !q_vector->rxr_count)
+                               /* tx vector gets half the rate */
+                               q_vector->eitr = (adapter->eitr_param >> 1);
+                       else
+                               /* rx only or mixed */
+                               q_vector->eitr = adapter->eitr_param;
+                       ixgbe_write_eitr(q_vector);
+               }
+       /* Legacy Interrupt Mode */
+       } else {
+               q_vector = adapter->q_vector[0];
+               q_vector->eitr = adapter->eitr_param;
                ixgbe_write_eitr(q_vector);
        }
 
@@ -1999,13 +2013,13 @@ static int ixgbe_set_flags(struct net_device *netdev, u32 data)
 
        ethtool_op_set_flags(netdev, data);
 
-       if (!(adapter->flags & IXGBE_FLAG2_RSC_CAPABLE))
+       if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE))
                return 0;
 
        /* if state changes we need to update adapter->flags and reset */
        if ((!!(data & ETH_FLAG_LRO)) != 
-           (!!(adapter->flags & IXGBE_FLAG2_RSC_ENABLED))) {
-               adapter->flags ^= IXGBE_FLAG2_RSC_ENABLED;
+           (!!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) {
+               adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
                if (netif_running(netdev))
                        ixgbe_reinit_locked(adapter);
                else
index fa9f24e23683003d8d8b531f22793f87d1880cf7..28cf104e36cc57de90af65c37a0981ab07dc205e 100644 (file)
@@ -336,7 +336,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
                /* return 0 to bypass going to ULD for DDPed data */
                if (fcstat == IXGBE_RXDADV_STAT_FCSTAT_DDP)
                        rc = 0;
-               else
+               else if (ddp->len)
                        rc = ddp->len;
        }
 
index e756e220db326a98dc4b7d44d5b5b139ab33a807..77b0381a2b5c7a3837ab58232ad85ea0eeb2fea6 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
+#include <linux/pkt_sched.h>
 #include <linux/ipv6.h>
 #include <net/checksum.h>
 #include <net/ip6_checksum.h>
@@ -491,12 +492,12 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector,
 
        skb_record_rx_queue(skb, ring->queue_index);
        if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
-               if (adapter->vlgrp && is_vlan && (tag != 0))
+               if (adapter->vlgrp && is_vlan && (tag & VLAN_VID_MASK))
                        vlan_gro_receive(napi, adapter->vlgrp, tag, skb);
                else
                        napi_gro_receive(napi, skb);
        } else {
-               if (adapter->vlgrp && is_vlan && (tag != 0))
+               if (adapter->vlgrp && is_vlan && (tag & VLAN_VID_MASK))
                        vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
                else
                        netif_rx(skb);
@@ -510,8 +511,11 @@ static void ixgbe_receive_skb(struct ixgbe_q_vector *q_vector,
  * @skb: skb currently being received and modified
  **/
 static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter,
-                                     u32 status_err, struct sk_buff *skb)
+                                    union ixgbe_adv_rx_desc *rx_desc,
+                                    struct sk_buff *skb)
 {
+       u32 status_err = le32_to_cpu(rx_desc->wb.upper.status_error);
+
        skb->ip_summed = CHECKSUM_NONE;
 
        /* Rx csum disabled */
@@ -529,6 +533,16 @@ static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter,
                return;
 
        if (status_err & IXGBE_RXDADV_ERR_TCPE) {
+               u16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info;
+
+               /*
+                * 82599 errata, UDP frames with a 0 checksum can be marked as
+                * checksum errors.
+                */
+               if ((pkt_info & IXGBE_RXDADV_PKTTYPE_UDP) &&
+                   (adapter->hw.mac.type == ixgbe_mac_82599EB))
+                       return;
+
                adapter->hw_csum_rx_error++;
                return;
        }
@@ -563,7 +577,6 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
        union ixgbe_adv_rx_desc *rx_desc;
        struct ixgbe_rx_buffer *bi;
        unsigned int i;
-       unsigned int bufsz = rx_ring->rx_buf_len + NET_IP_ALIGN;
 
        i = rx_ring->next_to_use;
        bi = &rx_ring->rx_buffer_info[i];
@@ -572,7 +585,7 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
                rx_desc = IXGBE_RX_DESC_ADV(*rx_ring, i);
 
                if (!bi->page_dma &&
-                   (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)) {
+                   (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)) {
                        if (!bi->page) {
                                bi->page = alloc_page(GFP_ATOMIC);
                                if (!bi->page) {
@@ -593,7 +606,9 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
 
                if (!bi->skb) {
                        struct sk_buff *skb;
-                       skb = netdev_alloc_skb(adapter->netdev, bufsz);
+                       skb = netdev_alloc_skb(adapter->netdev,
+                                              (rx_ring->rx_buf_len +
+                                               NET_IP_ALIGN));
 
                        if (!skb) {
                                adapter->alloc_rx_buff_failed++;
@@ -608,12 +623,13 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
                        skb_reserve(skb, NET_IP_ALIGN);
 
                        bi->skb = skb;
-                       bi->dma = pci_map_single(pdev, skb->data, bufsz,
+                       bi->dma = pci_map_single(pdev, skb->data,
+                                                rx_ring->rx_buf_len,
                                                 PCI_DMA_FROMDEVICE);
                }
                /* Refresh the desc even if buffer_addrs didn't change because
                 * each write-back erases this info. */
-               if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
+               if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
                        rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma);
                        rx_desc->read.hdr_addr = cpu_to_le64(bi->dma);
                } else {
@@ -710,7 +726,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                        break;
                (*work_done)++;
 
-               if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
+               if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
                        hdr_info = le16_to_cpu(ixgbe_get_hdr_info(rx_desc));
                        len = (hdr_info & IXGBE_RXDADV_HDRBUFLEN_MASK) >>
                               IXGBE_RXDADV_HDRBUFLEN_SHIFT;
@@ -732,6 +748,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                        pci_unmap_single(pdev, rx_buffer_info->dma,
                                         rx_ring->rx_buf_len,
                                         PCI_DMA_FROMDEVICE);
+                       rx_buffer_info->dma = 0;
                        skb_put(skb, len);
                }
 
@@ -763,7 +780,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                prefetch(next_rxd);
                cleaned_count++;
 
-               if (adapter->flags & IXGBE_FLAG2_RSC_CAPABLE)
+               if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)
                        rsc_count = ixgbe_get_rsc_count(rx_desc);
 
                if (rsc_count) {
@@ -781,7 +798,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                        rx_ring->stats.packets++;
                        rx_ring->stats.bytes += skb->len;
                } else {
-                       if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
+                       if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
                                rx_buffer_info->skb = next_buffer->skb;
                                rx_buffer_info->dma = next_buffer->dma;
                                next_buffer->skb = skb;
@@ -799,7 +816,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                        goto next_desc;
                }
 
-               ixgbe_rx_checksum(adapter, staterr, skb);
+               ixgbe_rx_checksum(adapter, rx_desc, skb);
 
                /* probably a little skewed due to removing CRC */
                total_rx_bytes += skb->len;
@@ -1881,46 +1898,19 @@ static void ixgbe_configure_tx(struct ixgbe_adapter *adapter)
 
 #define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
 
-static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index)
+static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter,
+                                   struct ixgbe_ring *rx_ring)
 {
-       struct ixgbe_ring *rx_ring;
        u32 srrctl;
-       int queue0 = 0;
-       unsigned long mask;
+       int index;
        struct ixgbe_ring_feature *feature = adapter->ring_feature;
 
-       if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
-               if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-                       int dcb_i = feature[RING_F_DCB].indices;
-                       if (dcb_i == 8)
-                               queue0 = index >> 4;
-                       else if (dcb_i == 4)
-                               queue0 = index >> 5;
-                       else
-                               dev_err(&adapter->pdev->dev, "Invalid DCB "
-                                       "configuration\n");
-#ifdef IXGBE_FCOE
-                       if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
-                               struct ixgbe_ring_feature *f;
-
-                               rx_ring = &adapter->rx_ring[queue0];
-                               f = &adapter->ring_feature[RING_F_FCOE];
-                               if ((queue0 == 0) && (index > rx_ring->reg_idx))
-                                       queue0 = f->mask + index -
-                                                rx_ring->reg_idx - 1;
-                       }
-#endif /* IXGBE_FCOE */
-               } else {
-                       queue0 = index;
-               }
-       } else {
+       index = rx_ring->reg_idx;
+       if (adapter->hw.mac.type == ixgbe_mac_82598EB) {
+               unsigned long mask;
                mask = (unsigned long) feature[RING_F_RSS].mask;
-               queue0 = index & mask;
                index = index & mask;
        }
-
-       rx_ring = &adapter->rx_ring[queue0];
-
        srrctl = IXGBE_READ_REG(&adapter->hw, IXGBE_SRRCTL(index));
 
        srrctl &= ~IXGBE_SRRCTL_BSIZEHDR_MASK;
@@ -1929,7 +1919,7 @@ static void ixgbe_configure_srrctl(struct ixgbe_adapter *adapter, int index)
        srrctl |= (IXGBE_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) &
                  IXGBE_SRRCTL_BSIZEHDR_MASK;
 
-       if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
+       if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
 #if (PAGE_SIZE / 2) > IXGBE_MAX_RXBUFFER
                srrctl |= IXGBE_MAX_RXBUFFER >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
 #else
@@ -1985,6 +1975,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
 {
        u64 rdba;
        struct ixgbe_hw *hw = &adapter->hw;
+       struct ixgbe_ring *rx_ring;
        struct net_device *netdev = adapter->netdev;
        int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
        int i, j;
@@ -2001,11 +1992,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
        /* Decide whether to use packet split mode or not */
        adapter->flags |= IXGBE_FLAG_RX_PS_ENABLED;
 
-#ifdef IXGBE_FCOE
-       if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)
-               adapter->flags &= ~IXGBE_FLAG_RX_PS_ENABLED;
-#endif /* IXGBE_FCOE */
-
        /* Set the RX buffer length according to the mode */
        if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
                rx_buf_len = IXGBE_RX_HDR_SIZE;
@@ -2019,7 +2005,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
                        IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype);
                }
        } else {
-               if (!(adapter->flags & IXGBE_FLAG2_RSC_ENABLED) &&
+               if (!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) &&
                    (netdev->mtu <= ETH_DATA_LEN))
                        rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE;
                else
@@ -2053,29 +2039,35 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
         * the Base and Length of the Rx Descriptor Ring
         */
        for (i = 0; i < adapter->num_rx_queues; i++) {
-               rdba = adapter->rx_ring[i].dma;
-               j = adapter->rx_ring[i].reg_idx;
+               rx_ring = &adapter->rx_ring[i];
+               rdba = rx_ring->dma;
+               j = rx_ring->reg_idx;
                IXGBE_WRITE_REG(hw, IXGBE_RDBAL(j), (rdba & DMA_BIT_MASK(32)));
                IXGBE_WRITE_REG(hw, IXGBE_RDBAH(j), (rdba >> 32));
                IXGBE_WRITE_REG(hw, IXGBE_RDLEN(j), rdlen);
                IXGBE_WRITE_REG(hw, IXGBE_RDH(j), 0);
                IXGBE_WRITE_REG(hw, IXGBE_RDT(j), 0);
-               adapter->rx_ring[i].head = IXGBE_RDH(j);
-               adapter->rx_ring[i].tail = IXGBE_RDT(j);
-               adapter->rx_ring[i].rx_buf_len = rx_buf_len;
+               rx_ring->head = IXGBE_RDH(j);
+               rx_ring->tail = IXGBE_RDT(j);
+               rx_ring->rx_buf_len = rx_buf_len;
+
+               if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED)
+                       rx_ring->flags |= IXGBE_RING_RX_PS_ENABLED;
 
 #ifdef IXGBE_FCOE
                if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
                        struct ixgbe_ring_feature *f;
                        f = &adapter->ring_feature[RING_F_FCOE];
-                       if ((rx_buf_len < IXGBE_FCOE_JUMBO_FRAME_SIZE) &&
-                           (i >= f->mask) && (i < f->mask + f->indices))
-                               adapter->rx_ring[i].rx_buf_len =
-                                       IXGBE_FCOE_JUMBO_FRAME_SIZE;
+                       if ((i >= f->mask) && (i < f->mask + f->indices)) {
+                               rx_ring->flags &= ~IXGBE_RING_RX_PS_ENABLED;
+                               if (rx_buf_len < IXGBE_FCOE_JUMBO_FRAME_SIZE)
+                                       rx_ring->rx_buf_len =
+                                               IXGBE_FCOE_JUMBO_FRAME_SIZE;
+                       }
                }
 
 #endif /* IXGBE_FCOE */
-               ixgbe_configure_srrctl(adapter, j);
+               ixgbe_configure_srrctl(adapter, rx_ring);
        }
 
        if (hw->mac.type == ixgbe_mac_82598EB) {
@@ -2148,10 +2140,11 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
                IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
        }
 
-       if (adapter->flags & IXGBE_FLAG2_RSC_ENABLED) {
+       if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED) {
                /* Enable 82599 HW-RSC */
                for (i = 0; i < adapter->num_rx_queues; i++) {
-                       j = adapter->rx_ring[i].reg_idx;
+                       rx_ring = &adapter->rx_ring[i];
+                       j = rx_ring->reg_idx;
                        rscctrl = IXGBE_READ_REG(hw, IXGBE_RSCCTL(j));
                        rscctrl |= IXGBE_RSCCTL_RSCEN;
                        /*
@@ -2159,7 +2152,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
                         * total size of max desc * buf_len is not greater
                         * than 65535
                         */
-                       if (adapter->flags & IXGBE_FLAG_RX_PS_ENABLED) {
+                       if (rx_ring->flags & IXGBE_RING_RX_PS_ENABLED) {
 #if (MAX_SKB_FRAGS > 16)
                                rscctrl |= IXGBE_RSCCTL_MAXDESC_16;
 #elif (MAX_SKB_FRAGS > 8)
@@ -2694,16 +2687,23 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
 
        /*
         * For hot-pluggable SFP+ devices, a new SFP+ module may have
-        * arrived before interrupts were enabled.  We need to kick off
-        * the SFP+ module setup first, then try to bring up link.
+        * arrived before interrupts were enabled but after probe.  Such
+        * devices wouldn't have their type identified yet. We need to
+        * kick off the SFP+ module setup first, then try to bring up link.
         * If we're not hot-pluggable SFP+, we just need to configure link
         * and bring it up.
         */
-       err = hw->phy.ops.identify(hw);
-       if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-               DPRINTK(PROBE, ERR, "PHY not supported on this NIC %d\n", err);
-               ixgbe_down(adapter);
-               return err;
+       if (hw->phy.type == ixgbe_phy_unknown) {
+               err = hw->phy.ops.identify(hw);
+               if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+                       /*
+                        * Take the device down and schedule the sfp tasklet
+                        * which will unregister_netdev and log it.
+                        */
+                       ixgbe_down(adapter);
+                       schedule_work(&adapter->sfp_config_module_task);
+                       return err;
+               }
        }
 
        if (ixgbe_is_sfp(hw)) {
@@ -2812,9 +2812,11 @@ static void ixgbe_clean_rx_ring(struct ixgbe_adapter *adapter,
                }
                if (!rx_buffer_info->page)
                        continue;
-               pci_unmap_page(pdev, rx_buffer_info->page_dma, PAGE_SIZE / 2,
-                              PCI_DMA_FROMDEVICE);
-               rx_buffer_info->page_dma = 0;
+               if (rx_buffer_info->page_dma) {
+                       pci_unmap_page(pdev, rx_buffer_info->page_dma,
+                                      PAGE_SIZE / 2, PCI_DMA_FROMDEVICE);
+                       rx_buffer_info->page_dma = 0;
+               }
                put_page(rx_buffer_info->page);
                rx_buffer_info->page = NULL;
                rx_buffer_info->page_offset = 0;
@@ -3118,7 +3120,11 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter)
 #endif
                if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
                        DPRINTK(PROBE, INFO, "FCOE enabled with RSS \n");
-                       ixgbe_set_rss_queues(adapter);
+                       if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
+                           (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
+                               ixgbe_set_fdir_queues(adapter);
+                       else
+                               ixgbe_set_rss_queues(adapter);
                }
                /* adding FCoE rx rings to the end */
                f->mask = adapter->num_rx_queues;
@@ -3376,7 +3382,12 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter)
                }
 #endif /* CONFIG_IXGBE_DCB */
                if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
-                       ixgbe_cache_ring_rss(adapter);
+                       if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
+                           (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
+                               ixgbe_cache_ring_fdir(adapter);
+                       else
+                               ixgbe_cache_ring_rss(adapter);
+
                        fcoe_i = f->mask;
                }
                for (i = 0; i < f->indices; i++, fcoe_i++)
@@ -3716,14 +3727,15 @@ static void ixgbe_sfp_task(struct work_struct *work)
        if ((hw->phy.type == ixgbe_phy_nl) &&
            (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
                s32 ret = hw->phy.ops.identify_sfp(hw);
-               if (ret)
+               if (ret == IXGBE_ERR_SFP_NOT_PRESENT)
                        goto reschedule;
                ret = hw->phy.ops.reset(hw);
                if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-                       DPRINTK(PROBE, ERR, "failed to initialize because an "
-                               "unsupported SFP+ module type was detected.\n"
-                               "Reload the driver after installing a "
-                               "supported module.\n");
+                       dev_err(&adapter->pdev->dev, "failed to initialize "
+                               "because an unsupported SFP+ module type "
+                               "was detected.\n"
+                               "Reload the driver after installing a "
+                               "supported module.\n");
                        unregister_netdev(adapter->netdev);
                } else {
                        DPRINTK(PROBE, INFO, "detected SFP+: %d\n",
@@ -3776,16 +3788,17 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
                adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82598;
        } else if (hw->mac.type == ixgbe_mac_82599EB) {
                adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599;
-               adapter->flags |= IXGBE_FLAG2_RSC_CAPABLE;
-               adapter->flags |= IXGBE_FLAG2_RSC_ENABLED;
+               adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE;
+               adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
                adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
                adapter->ring_feature[RING_F_FDIR].indices =
                                                         IXGBE_MAX_FDIR_INDICES;
                adapter->atr_sample_rate = 20;
                adapter->fdir_pballoc = 0;
 #ifdef IXGBE_FCOE
-               adapter->flags |= IXGBE_FLAG_FCOE_ENABLED;
-               adapter->ring_feature[RING_F_FCOE].indices = IXGBE_FCRETA_SIZE;
+               adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE;
+               adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
+               adapter->ring_feature[RING_F_FCOE].indices = 0;
 #endif /* IXGBE_FCOE */
        }
 
@@ -4502,7 +4515,8 @@ static void ixgbe_multispeed_fiber_task(struct work_struct *work)
        u32 autoneg;
 
        adapter->flags |= IXGBE_FLAG_IN_SFP_LINK_TASK;
-       if (hw->mac.ops.get_link_capabilities)
+       autoneg = hw->phy.autoneg_advertised;
+       if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
                hw->mac.ops.get_link_capabilities(hw, &autoneg,
                                                  &hw->mac.autoneg);
        if (hw->mac.ops.setup_link_speed)
@@ -4524,10 +4538,17 @@ static void ixgbe_sfp_config_module_task(struct work_struct *work)
        u32 err;
 
        adapter->flags |= IXGBE_FLAG_IN_SFP_MOD_TASK;
+
+       /* Time for electrical oscillations to settle down */
+       msleep(100);
        err = hw->phy.ops.identify_sfp(hw);
+
        if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-               DPRINTK(PROBE, ERR, "PHY not supported on this NIC %d\n", err);
-               ixgbe_down(adapter);
+               dev_err(&adapter->pdev->dev, "failed to initialize because "
+                       "an unsupported SFP+ module type was detected.\n"
+                       "Reload the driver after installing a supported "
+                       "module.\n");
+               unregister_netdev(adapter->netdev);
                return;
        }
        hw->mac.ops.setup_sfp(hw);
@@ -5095,9 +5116,6 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        int count = 0;
        unsigned int f;
 
-       r_idx = skb->queue_mapping;
-       tx_ring = &adapter->tx_ring[r_idx];
-
        if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
                tx_flags |= vlan_tx_tag_get(skb);
                if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
@@ -5107,11 +5125,19 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
                tx_flags |= IXGBE_TX_FLAGS_VLAN;
        } else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-               tx_flags |= (skb->queue_mapping << 13);
-               tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
-               tx_flags |= IXGBE_TX_FLAGS_VLAN;
+               if (skb->priority != TC_PRIO_CONTROL) {
+                       tx_flags |= (skb->queue_mapping << 13);
+                       tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
+                       tx_flags |= IXGBE_TX_FLAGS_VLAN;
+               } else {
+                       skb->queue_mapping =
+                               adapter->ring_feature[RING_F_DCB].indices-1;
+               }
        }
 
+       r_idx = skb->queue_mapping;
+       tx_ring = &adapter->tx_ring[r_idx];
+
        if ((adapter->flags & IXGBE_FLAG_FCOE_ENABLED) &&
            (skb->protocol == htons(ETH_P_FCOE)))
                tx_flags |= IXGBE_TX_FLAGS_FCOE;
@@ -5310,12 +5336,19 @@ static int ixgbe_del_sanmac_netdev(struct net_device *dev)
 static void ixgbe_netpoll(struct net_device *netdev)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
+       int i;
 
-       disable_irq(adapter->pdev->irq);
        adapter->flags |= IXGBE_FLAG_IN_NETPOLL;
-       ixgbe_intr(adapter->pdev->irq, netdev);
+       if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
+               int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
+               for (i = 0; i < num_q_vectors; i++) {
+                       struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
+                       ixgbe_msix_clean_many(0, q_vector);
+               }
+       } else {
+               ixgbe_intr(adapter->pdev->irq, netdev);
+       }
        adapter->flags &= ~IXGBE_FLAG_IN_NETPOLL;
-       enable_irq(adapter->pdev->irq);
 }
 #endif
 
@@ -5513,8 +5546,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
                          round_jiffies(jiffies + (2 * HZ)));
                err = 0;
        } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-               dev_err(&adapter->pdev->dev, "failed to load because an "
-                       "unsupported SFP+ module type was detected.\n");
+               dev_err(&adapter->pdev->dev, "failed to initialize because "
+                       "an unsupported SFP+ module type was detected.\n"
+                       "Reload the driver after installing a supported "
+                       "module.\n");
                goto err_sw_init;
        } else if (err) {
                dev_err(&adapter->pdev->dev, "HW Init failed: %d\n", err);
@@ -5548,29 +5583,18 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 #endif
 
 #ifdef IXGBE_FCOE
-       if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
+       if (adapter->flags & IXGBE_FLAG_FCOE_CAPABLE) {
                if (hw->mac.ops.get_device_caps) {
                        hw->mac.ops.get_device_caps(hw, &device_caps);
-                       if (!(device_caps & IXGBE_DEVICE_CAPS_FCOE_OFFLOADS)) {
-                               netdev->features |= NETIF_F_FCOE_CRC;
-                               netdev->features |= NETIF_F_FSO;
-                               netdev->fcoe_ddp_xid = IXGBE_FCOE_DDP_MAX - 1;
-                               DPRINTK(DRV, INFO, "FCoE enabled, "
-                                       "disabling Flow Director\n");
-                               adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
-                               adapter->flags &=
-                                       ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
-                               adapter->atr_sample_rate = 0;
-                       } else {
-                               adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED;
-                       }
+                       if (device_caps & IXGBE_DEVICE_CAPS_FCOE_OFFLOADS)
+                               adapter->flags &= ~IXGBE_FLAG_FCOE_CAPABLE;
                }
        }
 #endif /* IXGBE_FCOE */
        if (pci_using_dac)
                netdev->features |= NETIF_F_HIGHDMA;
 
-       if (adapter->flags & IXGBE_FLAG2_RSC_ENABLED)
+       if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
                netdev->features |= NETIF_F_LRO;
 
        /* make sure the EEPROM is good */
@@ -5612,7 +5636,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
                adapter->wol = 0;
                break;
        }
-       device_init_wakeup(&adapter->pdev->dev, true);
        device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
 
        /* pick up the PCI bus settings for reporting later */
index 453e966762f0e3a6f8f14c603ccbb031849ab5de..9ecad17522c33285fd7b8755cd1eaa3d4d6015bc 100644 (file)
@@ -60,6 +60,7 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
 
        if (hw->phy.type == ixgbe_phy_unknown) {
                for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
+                       hw->phy.mdio.prtad = phy_addr;
                        if (mdio45_probe(&hw->phy.mdio, phy_addr) == 0) {
                                ixgbe_get_phy_id(hw);
                                hw->phy.type =
@@ -68,6 +69,8 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
                                break;
                        }
                }
+               /* clear value if nothing found */
+               hw->phy.mdio.prtad = 0;
        } else {
                status = 0;
        }
index fa87309dc0877b39447138232c2f44c74d2282d4..be90eb4575f6253712782cc4b22e04bc9e07a4e3 100644 (file)
 #define IXGBE_ECC_STATUS_82599  0x110E0
 #define IXGBE_BAR_CTRL_82599    0x110F4
 
+/* PCI Express Control */
+#define IXGBE_GCR_CMPL_TMOUT_MASK       0x0000F000
+#define IXGBE_GCR_CMPL_TMOUT_10ms       0x00001000
+#define IXGBE_GCR_CMPL_TMOUT_RESEND     0x00010000
+#define IXGBE_GCR_CAP_VER2              0x00040000
+
 /* Time Sync Registers */
 #define IXGBE_TSYNCRXCTL 0x05188 /* Rx Time Sync Control register - RW */
 #define IXGBE_TSYNCTXCTL 0x08C00 /* Tx Time Sync Control register - RW */
 
 /* PCI Bus Info */
 #define IXGBE_PCI_LINK_STATUS     0xB2
+#define IXGBE_PCI_DEVICE_CONTROL2 0xC8
 #define IXGBE_PCI_LINK_WIDTH      0x3F0
 #define IXGBE_PCI_LINK_WIDTH_1    0x10
 #define IXGBE_PCI_LINK_WIDTH_2    0x20
 #define IXGBE_PCI_LINK_SPEED_5000 0x2
 #define IXGBE_PCI_HEADER_TYPE_REGISTER  0x0E
 #define IXGBE_PCI_HEADER_TYPE_MULTIFUNC 0x80
+#define IXGBE_PCI_DEVICE_CONTROL2_16ms  0x0005
 
 /* Number of 100 microseconds we wait for PCI Express master disable */
 #define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800
index 2a0174b62e964d613102e0ef14e32828b3b91c34..92fb8235c76689c2ea3b6f1c079a65536bd035a1 100644 (file)
@@ -41,6 +41,7 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev)
        struct ixpdev_priv *ip = netdev_priv(dev);
        struct ixpdev_tx_desc *desc;
        int entry;
+       unsigned long flags;
 
        if (unlikely(skb->len > PAGE_SIZE)) {
                /* @@@ Count drops.  */
@@ -63,11 +64,11 @@ static int ixpdev_xmit(struct sk_buff *skb, struct net_device *dev)
 
        dev->trans_start = jiffies;
 
-       local_irq_disable();
+       local_irq_save(flags);
        ip->tx_queue_entries++;
        if (ip->tx_queue_entries == TX_BUF_COUNT_PER_CHAN)
                netif_stop_queue(dev);
-       local_irq_enable();
+       local_irq_restore(flags);
 
        return 0;
 }
index d12106b47bf2a6cbd9130c9f5840a4322108f5d2..2f286091394d3241bc0bff2cef271ee79c141c00 100644 (file)
@@ -229,6 +229,7 @@ static int __init jazz_sonic_probe(struct platform_device *pdev)
        lp = netdev_priv(dev);
        lp->device = &pdev->dev;
        SET_NETDEV_DEV(dev, &pdev->dev);
+       platform_set_drvdata(pdev, dev);
 
        netdev_boot_setup_check(dev);
 
diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c
new file mode 100644 (file)
index 0000000..9a1dea6
--- /dev/null
@@ -0,0 +1,1322 @@
+/* drivers/net/ks8651.c
+ *
+ * Copyright 2009 Simtec Electronics
+ *     http://www.simtec.co.uk/
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define DEBUG
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/cache.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+
+#include <linux/spi/spi.h>
+
+#include "ks8851.h"
+
+/**
+ * struct ks8851_rxctrl - KS8851 driver rx control
+ * @mchash: Multicast hash-table data.
+ * @rxcr1: KS_RXCR1 register setting
+ * @rxcr2: KS_RXCR2 register setting
+ *
+ * Representation of the settings needs to control the receive filtering
+ * such as the multicast hash-filter and the receive register settings. This
+ * is used to make the job of working out if the receive settings change and
+ * then issuing the new settings to the worker that will send the necessary
+ * commands.
+ */
+struct ks8851_rxctrl {
+       u16     mchash[4];
+       u16     rxcr1;
+       u16     rxcr2;
+};
+
+/**
+ * union ks8851_tx_hdr - tx header data
+ * @txb: The header as bytes
+ * @txw: The header as 16bit, little-endian words
+ *
+ * A dual representation of the tx header data to allow
+ * access to individual bytes, and to allow 16bit accesses
+ * with 16bit alignment.
+ */
+union ks8851_tx_hdr {
+       u8      txb[6];
+       __le16  txw[3];
+};
+
+/**
+ * struct ks8851_net - KS8851 driver private data
+ * @netdev: The network device we're bound to
+ * @spidev: The spi device we're bound to.
+ * @lock: Lock to ensure that the device is not accessed when busy.
+ * @statelock: Lock on this structure for tx list.
+ * @mii: The MII state information for the mii calls.
+ * @rxctrl: RX settings for @rxctrl_work.
+ * @tx_work: Work queue for tx packets
+ * @irq_work: Work queue for servicing interrupts
+ * @rxctrl_work: Work queue for updating RX mode and multicast lists
+ * @txq: Queue of packets for transmission.
+ * @spi_msg1: pre-setup SPI transfer with one message, @spi_xfer1.
+ * @spi_msg2: pre-setup SPI transfer with two messages, @spi_xfer2.
+ * @txh: Space for generating packet TX header in DMA-able data
+ * @rxd: Space for receiving SPI data, in DMA-able space.
+ * @txd: Space for transmitting SPI data, in DMA-able space.
+ * @msg_enable: The message flags controlling driver output (see ethtool).
+ * @fid: Incrementing frame id tag.
+ * @rc_ier: Cached copy of KS_IER.
+ * @rc_rxqcr: Cached copy of KS_RXQCR.
+ *
+ * The @lock ensures that the chip is protected when certain operations are
+ * in progress. When the read or write packet transfer is in progress, most
+ * of the chip registers are not ccessible until the transfer is finished and
+ * the DMA has been de-asserted.
+ *
+ * The @statelock is used to protect information in the structure which may
+ * need to be accessed via several sources, such as the network driver layer
+ * or one of the work queues.
+ *
+ * We align the buffers we may use for rx/tx to ensure that if the SPI driver
+ * wants to DMA map them, it will not have any problems with data the driver
+ * modifies.
+ */
+struct ks8851_net {
+       struct net_device       *netdev;
+       struct spi_device       *spidev;
+       struct mutex            lock;
+       spinlock_t              statelock;
+
+       union ks8851_tx_hdr     txh ____cacheline_aligned;
+       u8                      rxd[8];
+       u8                      txd[8];
+
+       u32                     msg_enable ____cacheline_aligned;
+       u16                     tx_space;
+       u8                      fid;
+
+       u16                     rc_ier;
+       u16                     rc_rxqcr;
+
+       struct mii_if_info      mii;
+       struct ks8851_rxctrl    rxctrl;
+
+       struct work_struct      tx_work;
+       struct work_struct      irq_work;
+       struct work_struct      rxctrl_work;
+
+       struct sk_buff_head     txq;
+
+       struct spi_message      spi_msg1;
+       struct spi_message      spi_msg2;
+       struct spi_transfer     spi_xfer1;
+       struct spi_transfer     spi_xfer2[2];
+};
+
+static int msg_enable;
+
+#define ks_info(_ks, _msg...) dev_info(&(_ks)->spidev->dev, _msg)
+#define ks_warn(_ks, _msg...) dev_warn(&(_ks)->spidev->dev, _msg)
+#define ks_dbg(_ks, _msg...) dev_dbg(&(_ks)->spidev->dev, _msg)
+#define ks_err(_ks, _msg...) dev_err(&(_ks)->spidev->dev, _msg)
+
+/* shift for byte-enable data */
+#define BYTE_EN(_x)    ((_x) << 2)
+
+/* turn register number and byte-enable mask into data for start of packet */
+#define MK_OP(_byteen, _reg) (BYTE_EN(_byteen) | (_reg)  << (8+2) | (_reg) >> 6)
+
+/* SPI register read/write calls.
+ *
+ * All these calls issue SPI transactions to access the chip's registers. They
+ * all require that the necessary lock is held to prevent accesses when the
+ * chip is busy transfering packet data (RX/TX FIFO accesses).
+ */
+
+/**
+ * ks8851_wrreg16 - write 16bit register value to chip
+ * @ks: The chip state
+ * @reg: The register address
+ * @val: The value to write
+ *
+ * Issue a write to put the value @val into the register specified in @reg.
+ */
+static void ks8851_wrreg16(struct ks8851_net *ks, unsigned reg, unsigned val)
+{
+       struct spi_transfer *xfer = &ks->spi_xfer1;
+       struct spi_message *msg = &ks->spi_msg1;
+       __le16 txb[2];
+       int ret;
+
+       txb[0] = cpu_to_le16(MK_OP(reg & 2 ? 0xC : 0x03, reg) | KS_SPIOP_WR);
+       txb[1] = cpu_to_le16(val);
+
+       xfer->tx_buf = txb;
+       xfer->rx_buf = NULL;
+       xfer->len = 4;
+
+       ret = spi_sync(ks->spidev, msg);
+       if (ret < 0)
+               ks_err(ks, "spi_sync() failed\n");
+}
+
+/**
+ * ks8851_rx_1msg - select whether to use one or two messages for spi read
+ * @ks: The device structure
+ *
+ * Return whether to generate a single message with a tx and rx buffer
+ * supplied to spi_sync(), or alternatively send the tx and rx buffers
+ * as separate messages.
+ *
+ * Depending on the hardware in use, a single message may be more efficient
+ * on interrupts or work done by the driver.
+ *
+ * This currently always returns true until we add some per-device data passed
+ * from the platform code to specify which mode is better.
+ */
+static inline bool ks8851_rx_1msg(struct ks8851_net *ks)
+{
+       return true;
+}
+
+/**
+ * ks8851_rdreg - issue read register command and return the data
+ * @ks: The device state
+ * @op: The register address and byte enables in message format.
+ * @rxb: The RX buffer to return the result into
+ * @rxl: The length of data expected.
+ *
+ * This is the low level read call that issues the necessary spi message(s)
+ * to read data from the register specified in @op.
+ */
+static void ks8851_rdreg(struct ks8851_net *ks, unsigned op,
+                        u8 *rxb, unsigned rxl)
+{
+       struct spi_transfer *xfer;
+       struct spi_message *msg;
+       __le16 *txb = (__le16 *)ks->txd;
+       u8 *trx = ks->rxd;
+       int ret;
+
+       txb[0] = cpu_to_le16(op | KS_SPIOP_RD);
+
+       if (ks8851_rx_1msg(ks)) {
+               msg = &ks->spi_msg1;
+               xfer = &ks->spi_xfer1;
+
+               xfer->tx_buf = txb;
+               xfer->rx_buf = trx;
+               xfer->len = rxl + 2;
+       } else {
+               msg = &ks->spi_msg2;
+               xfer = ks->spi_xfer2;
+
+               xfer->tx_buf = txb;
+               xfer->rx_buf = NULL;
+               xfer->len = 2;
+
+               xfer++;
+               xfer->tx_buf = NULL;
+               xfer->rx_buf = trx;
+               xfer->len = rxl;
+       }
+
+       ret = spi_sync(ks->spidev, msg);
+       if (ret < 0)
+               ks_err(ks, "read: spi_sync() failed\n");
+       else if (ks8851_rx_1msg(ks))
+               memcpy(rxb, trx + 2, rxl);
+       else
+               memcpy(rxb, trx, rxl);
+}
+
+/**
+ * ks8851_rdreg8 - read 8 bit register from device
+ * @ks: The chip information
+ * @reg: The register address
+ *
+ * Read a 8bit register from the chip, returning the result
+*/
+static unsigned ks8851_rdreg8(struct ks8851_net *ks, unsigned reg)
+{
+       u8 rxb[1];
+
+       ks8851_rdreg(ks, MK_OP(1 << (reg & 3), reg), rxb, 1);
+       return rxb[0];
+}
+
+/**
+ * ks8851_rdreg16 - read 16 bit register from device
+ * @ks: The chip information
+ * @reg: The register address
+ *
+ * Read a 16bit register from the chip, returning the result
+*/
+static unsigned ks8851_rdreg16(struct ks8851_net *ks, unsigned reg)
+{
+       __le16 rx = 0;
+
+       ks8851_rdreg(ks, MK_OP(reg & 2 ? 0xC : 0x3, reg), (u8 *)&rx, 2);
+       return le16_to_cpu(rx);
+}
+
+/**
+ * ks8851_rdreg32 - read 32 bit register from device
+ * @ks: The chip information
+ * @reg: The register address
+ *
+ * Read a 32bit register from the chip.
+ *
+ * Note, this read requires the address be aligned to 4 bytes.
+*/
+static unsigned ks8851_rdreg32(struct ks8851_net *ks, unsigned reg)
+{
+       __le32 rx = 0;
+
+       WARN_ON(reg & 3);
+
+       ks8851_rdreg(ks, MK_OP(0xf, reg), (u8 *)&rx, 4);
+       return le32_to_cpu(rx);
+}
+
+/**
+ * ks8851_soft_reset - issue one of the soft reset to the device
+ * @ks: The device state.
+ * @op: The bit(s) to set in the GRR
+ *
+ * Issue the relevant soft-reset command to the device's GRR register
+ * specified by @op.
+ *
+ * Note, the delays are in there as a caution to ensure that the reset
+ * has time to take effect and then complete. Since the datasheet does
+ * not currently specify the exact sequence, we have chosen something
+ * that seems to work with our device.
+ */
+static void ks8851_soft_reset(struct ks8851_net *ks, unsigned op)
+{
+       ks8851_wrreg16(ks, KS_GRR, op);
+       mdelay(1);      /* wait a short time to effect reset */
+       ks8851_wrreg16(ks, KS_GRR, 0);
+       mdelay(1);      /* wait for condition to clear */
+}
+
+/**
+ * ks8851_write_mac_addr - write mac address to device registers
+ * @dev: The network device
+ *
+ * Update the KS8851 MAC address registers from the address in @dev.
+ *
+ * This call assumes that the chip is not running, so there is no need to
+ * shutdown the RXQ process whilst setting this.
+*/
+static int ks8851_write_mac_addr(struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       u16 *mcp = (u16 *)dev->dev_addr;
+
+       mutex_lock(&ks->lock);
+
+       ks8851_wrreg16(ks, KS_MARL, mcp[0]);
+       ks8851_wrreg16(ks, KS_MARM, mcp[1]);
+       ks8851_wrreg16(ks, KS_MARH, mcp[2]);
+
+       mutex_unlock(&ks->lock);
+
+       return 0;
+}
+
+/**
+ * ks8851_init_mac - initialise the mac address
+ * @ks: The device structure
+ *
+ * Get or create the initial mac address for the device and then set that
+ * into the station address register. Currently we assume that the device
+ * does not have a valid mac address in it, and so we use random_ether_addr()
+ * to create a new one.
+ *
+ * In future, the driver should check to see if the device has an EEPROM
+ * attached and whether that has a valid ethernet address in it.
+ */
+static void ks8851_init_mac(struct ks8851_net *ks)
+{
+       struct net_device *dev = ks->netdev;
+
+       random_ether_addr(dev->dev_addr);
+       ks8851_write_mac_addr(dev);
+}
+
+/**
+ * ks8851_irq - device interrupt handler
+ * @irq: Interrupt number passed from the IRQ hnalder.
+ * @pw: The private word passed to register_irq(), our struct ks8851_net.
+ *
+ * Disable the interrupt from happening again until we've processed the
+ * current status by scheduling ks8851_irq_work().
+ */
+static irqreturn_t ks8851_irq(int irq, void *pw)
+{
+       struct ks8851_net *ks = pw;
+
+       disable_irq_nosync(irq);
+       schedule_work(&ks->irq_work);
+       return IRQ_HANDLED;
+}
+
+/**
+ * ks8851_rdfifo - read data from the receive fifo
+ * @ks: The device state.
+ * @buff: The buffer address
+ * @len: The length of the data to read
+ *
+ * Issue an RXQ FIFO read command and read the @len ammount of data from
+ * the FIFO into the buffer specified by @buff.
+ */
+static void ks8851_rdfifo(struct ks8851_net *ks, u8 *buff, unsigned len)
+{
+       struct spi_transfer *xfer = ks->spi_xfer2;
+       struct spi_message *msg = &ks->spi_msg2;
+       u8 txb[1];
+       int ret;
+
+       if (netif_msg_rx_status(ks))
+               ks_dbg(ks, "%s: %d@%p\n", __func__, len, buff);
+
+       /* set the operation we're issuing */
+       txb[0] = KS_SPIOP_RXFIFO;
+
+       xfer->tx_buf = txb;
+       xfer->rx_buf = NULL;
+       xfer->len = 1;
+
+       xfer++;
+       xfer->rx_buf = buff;
+       xfer->tx_buf = NULL;
+       xfer->len = len;
+
+       ret = spi_sync(ks->spidev, msg);
+       if (ret < 0)
+               ks_err(ks, "%s: spi_sync() failed\n", __func__);
+}
+
+/**
+ * ks8851_dbg_dumpkkt - dump initial packet contents to debug
+ * @ks: The device state
+ * @rxpkt: The data for the received packet
+ *
+ * Dump the initial data from the packet to dev_dbg().
+*/
+static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt)
+{
+       ks_dbg(ks, "pkt %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n",
+              rxpkt[4], rxpkt[5], rxpkt[6], rxpkt[7],
+              rxpkt[8], rxpkt[9], rxpkt[10], rxpkt[11],
+              rxpkt[12], rxpkt[13], rxpkt[14], rxpkt[15]);
+}
+
+/**
+ * ks8851_rx_pkts - receive packets from the host
+ * @ks: The device information.
+ *
+ * This is called from the IRQ work queue when the system detects that there
+ * are packets in the receive queue. Find out how many packets there are and
+ * read them from the FIFO.
+ */
+static void ks8851_rx_pkts(struct ks8851_net *ks)
+{
+       struct sk_buff *skb;
+       unsigned rxfc;
+       unsigned rxlen;
+       unsigned rxstat;
+       u32 rxh;
+       u8 *rxpkt;
+
+       rxfc = ks8851_rdreg8(ks, KS_RXFC);
+
+       if (netif_msg_rx_status(ks))
+               ks_dbg(ks, "%s: %d packets\n", __func__, rxfc);
+
+       /* Currently we're issuing a read per packet, but we could possibly
+        * improve the code by issuing a single read, getting the receive
+        * header, allocating the packet and then reading the packet data
+        * out in one go.
+        *
+        * This form of operation would require us to hold the SPI bus'
+        * chipselect low during the entie transaction to avoid any
+        * reset to the data stream comming from the chip.
+        */
+
+       for (; rxfc != 0; rxfc--) {
+               rxh = ks8851_rdreg32(ks, KS_RXFHSR);
+               rxstat = rxh & 0xffff;
+               rxlen = rxh >> 16;
+
+               if (netif_msg_rx_status(ks))
+                       ks_dbg(ks, "rx: stat 0x%04x, len 0x%04x\n",
+                               rxstat, rxlen);
+
+               /* the length of the packet includes the 32bit CRC */
+
+               /* set dma read address */
+               ks8851_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI | 0x00);
+
+               /* start the packet dma process, and set auto-dequeue rx */
+               ks8851_wrreg16(ks, KS_RXQCR,
+                              ks->rc_rxqcr | RXQCR_SDA | RXQCR_ADRFE);
+
+               if (rxlen > 0) {
+                       skb = netdev_alloc_skb(ks->netdev, rxlen + 2 + 8);
+                       if (!skb) {
+                               /* todo - dump frame and move on */
+                       }
+
+                       /* two bytes to ensure ip is aligned, and four bytes
+                        * for the status header and 4 bytes of garbage */
+                       skb_reserve(skb, 2 + 4 + 4);
+
+                       rxpkt = skb_put(skb, rxlen - 4) - 8;
+
+                       /* align the packet length to 4 bytes, and add 4 bytes
+                        * as we're getting the rx status header as well */
+                       ks8851_rdfifo(ks, rxpkt, ALIGN(rxlen, 4) + 8);
+
+                       if (netif_msg_pktdata(ks))
+                               ks8851_dbg_dumpkkt(ks, rxpkt);
+
+                       skb->protocol = eth_type_trans(skb, ks->netdev);
+                       netif_rx(skb);
+
+                       ks->netdev->stats.rx_packets++;
+                       ks->netdev->stats.rx_bytes += rxlen - 4;
+               }
+
+               ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
+       }
+}
+
+/**
+ * ks8851_irq_work - work queue handler for dealing with interrupt requests
+ * @work: The work structure that was scheduled by schedule_work()
+ *
+ * This is the handler invoked when the ks8851_irq() is called to find out
+ * what happened, as we cannot allow ourselves to sleep whilst waiting for
+ * anything other process has the chip's lock.
+ *
+ * Read the interrupt status, work out what needs to be done and then clear
+ * any of the interrupts that are not needed.
+ */
+static void ks8851_irq_work(struct work_struct *work)
+{
+       struct ks8851_net *ks = container_of(work, struct ks8851_net, irq_work);
+       unsigned status;
+       unsigned handled = 0;
+
+       mutex_lock(&ks->lock);
+
+       status = ks8851_rdreg16(ks, KS_ISR);
+
+       if (netif_msg_intr(ks))
+               dev_dbg(&ks->spidev->dev, "%s: status 0x%04x\n",
+                       __func__, status);
+
+       if (status & IRQ_LCI) {
+               /* should do something about checking link status */
+               handled |= IRQ_LCI;
+       }
+
+       if (status & IRQ_LDI) {
+               u16 pmecr = ks8851_rdreg16(ks, KS_PMECR);
+               pmecr &= ~PMECR_WKEVT_MASK;
+               ks8851_wrreg16(ks, KS_PMECR, pmecr | PMECR_WKEVT_LINK);
+
+               handled |= IRQ_LDI;
+       }
+
+       if (status & IRQ_RXPSI)
+               handled |= IRQ_RXPSI;
+
+       if (status & IRQ_TXI) {
+               handled |= IRQ_TXI;
+
+               /* no lock here, tx queue should have been stopped */
+
+               /* update our idea of how much tx space is available to the
+                * system */
+               ks->tx_space = ks8851_rdreg16(ks, KS_TXMIR);
+
+               if (netif_msg_intr(ks))
+                       ks_dbg(ks, "%s: txspace %d\n", __func__, ks->tx_space);
+       }
+
+       if (status & IRQ_RXI)
+               handled |= IRQ_RXI;
+
+       if (status & IRQ_SPIBEI) {
+               dev_err(&ks->spidev->dev, "%s: spi bus error\n", __func__);
+               handled |= IRQ_SPIBEI;
+       }
+
+       ks8851_wrreg16(ks, KS_ISR, handled);
+
+       if (status & IRQ_RXI) {
+               /* the datasheet says to disable the rx interrupt during
+                * packet read-out, however we're masking the interrupt
+                * from the device so do not bother masking just the RX
+                * from the device. */
+
+               ks8851_rx_pkts(ks);
+       }
+
+       /* if something stopped the rx process, probably due to wanting
+        * to change the rx settings, then do something about restarting
+        * it. */
+       if (status & IRQ_RXPSI) {
+               struct ks8851_rxctrl *rxc = &ks->rxctrl;
+
+               /* update the multicast hash table */
+               ks8851_wrreg16(ks, KS_MAHTR0, rxc->mchash[0]);
+               ks8851_wrreg16(ks, KS_MAHTR1, rxc->mchash[1]);
+               ks8851_wrreg16(ks, KS_MAHTR2, rxc->mchash[2]);
+               ks8851_wrreg16(ks, KS_MAHTR3, rxc->mchash[3]);
+
+               ks8851_wrreg16(ks, KS_RXCR2, rxc->rxcr2);
+               ks8851_wrreg16(ks, KS_RXCR1, rxc->rxcr1);
+       }
+
+       mutex_unlock(&ks->lock);
+
+       if (status & IRQ_TXI)
+               netif_wake_queue(ks->netdev);
+
+       enable_irq(ks->netdev->irq);
+}
+
+/**
+ * calc_txlen - calculate size of message to send packet
+ * @len: Lenght of data
+ *
+ * Returns the size of the TXFIFO message needed to send
+ * this packet.
+ */
+static inline unsigned calc_txlen(unsigned len)
+{
+       return ALIGN(len + 4, 4);
+}
+
+/**
+ * ks8851_wrpkt - write packet to TX FIFO
+ * @ks: The device state.
+ * @txp: The sk_buff to transmit.
+ * @irq: IRQ on completion of the packet.
+ *
+ * Send the @txp to the chip. This means creating the relevant packet header
+ * specifying the length of the packet and the other information the chip
+ * needs, such as IRQ on completion. Send the header and the packet data to
+ * the device.
+ */
+static void ks8851_wrpkt(struct ks8851_net *ks, struct sk_buff *txp, bool irq)
+{
+       struct spi_transfer *xfer = ks->spi_xfer2;
+       struct spi_message *msg = &ks->spi_msg2;
+       unsigned fid = 0;
+       int ret;
+
+       if (netif_msg_tx_queued(ks))
+               dev_dbg(&ks->spidev->dev, "%s: skb %p, %d@%p, irq %d\n",
+                       __func__, txp, txp->len, txp->data, irq);
+
+       fid = ks->fid++;
+       fid &= TXFR_TXFID_MASK;
+
+       if (irq)
+               fid |= TXFR_TXIC;       /* irq on completion */
+
+       /* start header at txb[1] to align txw entries */
+       ks->txh.txb[1] = KS_SPIOP_TXFIFO;
+       ks->txh.txw[1] = cpu_to_le16(fid);
+       ks->txh.txw[2] = cpu_to_le16(txp->len);
+
+       xfer->tx_buf = &ks->txh.txb[1];
+       xfer->rx_buf = NULL;
+       xfer->len = 5;
+
+       xfer++;
+       xfer->tx_buf = txp->data;
+       xfer->rx_buf = NULL;
+       xfer->len = ALIGN(txp->len, 4);
+
+       ret = spi_sync(ks->spidev, msg);
+       if (ret < 0)
+               ks_err(ks, "%s: spi_sync() failed\n", __func__);
+}
+
+/**
+ * ks8851_done_tx - update and then free skbuff after transmitting
+ * @ks: The device state
+ * @txb: The buffer transmitted
+ */
+static void ks8851_done_tx(struct ks8851_net *ks, struct sk_buff *txb)
+{
+       struct net_device *dev = ks->netdev;
+
+       dev->stats.tx_bytes += txb->len;
+       dev->stats.tx_packets++;
+
+       dev_kfree_skb(txb);
+}
+
+/**
+ * ks8851_tx_work - process tx packet(s)
+ * @work: The work strucutre what was scheduled.
+ *
+ * This is called when a number of packets have been scheduled for
+ * transmission and need to be sent to the device.
+ */
+static void ks8851_tx_work(struct work_struct *work)
+{
+       struct ks8851_net *ks = container_of(work, struct ks8851_net, tx_work);
+       struct sk_buff *txb;
+       bool last = false;
+
+       mutex_lock(&ks->lock);
+
+       while (!last) {
+               txb = skb_dequeue(&ks->txq);
+               last = skb_queue_empty(&ks->txq);
+
+               ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA);
+               ks8851_wrpkt(ks, txb, last);
+               ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
+               ks8851_wrreg16(ks, KS_TXQCR, TXQCR_METFE);
+
+               ks8851_done_tx(ks, txb);
+       }
+
+       mutex_unlock(&ks->lock);
+}
+
+/**
+ * ks8851_set_powermode - set power mode of the device
+ * @ks: The device state
+ * @pwrmode: The power mode value to write to KS_PMECR.
+ *
+ * Change the power mode of the chip.
+ */
+static void ks8851_set_powermode(struct ks8851_net *ks, unsigned pwrmode)
+{
+       unsigned pmecr;
+
+       if (netif_msg_hw(ks))
+               ks_dbg(ks, "setting power mode %d\n", pwrmode);
+
+       pmecr = ks8851_rdreg16(ks, KS_PMECR);
+       pmecr &= ~PMECR_PM_MASK;
+       pmecr |= pwrmode;
+
+       ks8851_wrreg16(ks, KS_PMECR, pmecr);
+}
+
+/**
+ * ks8851_net_open - open network device
+ * @dev: The network device being opened.
+ *
+ * Called when the network device is marked active, such as a user executing
+ * 'ifconfig up' on the device.
+ */
+static int ks8851_net_open(struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+
+       /* lock the card, even if we may not actually be doing anything
+        * else at the moment */
+       mutex_lock(&ks->lock);
+
+       if (netif_msg_ifup(ks))
+               ks_dbg(ks, "opening %s\n", dev->name);
+
+       /* bring chip out of any power saving mode it was in */
+       ks8851_set_powermode(ks, PMECR_PM_NORMAL);
+
+       /* issue a soft reset to the RX/TX QMU to put it into a known
+        * state. */
+       ks8851_soft_reset(ks, GRR_QMU);
+
+       /* setup transmission parameters */
+
+       ks8851_wrreg16(ks, KS_TXCR, (TXCR_TXE | /* enable transmit process */
+                                    TXCR_TXPE | /* pad to min length */
+                                    TXCR_TXCRC | /* add CRC */
+                                    TXCR_TXFCE)); /* enable flow control */
+
+       /* auto-increment tx data, reset tx pointer */
+       ks8851_wrreg16(ks, KS_TXFDPR, TXFDPR_TXFPAI);
+
+       /* setup receiver control */
+
+       ks8851_wrreg16(ks, KS_RXCR1, (RXCR1_RXPAFMA | /*  from mac filter */
+                                     RXCR1_RXFCE | /* enable flow control */
+                                     RXCR1_RXBE | /* broadcast enable */
+                                     RXCR1_RXUE | /* unicast enable */
+                                     RXCR1_RXE)); /* enable rx block */
+
+       /* transfer entire frames out in one go */
+       ks8851_wrreg16(ks, KS_RXCR2, RXCR2_SRDBL_FRAME);
+
+       /* set receive counter timeouts */
+       ks8851_wrreg16(ks, KS_RXDTTR, 1000); /* 1ms after first frame to IRQ */
+       ks8851_wrreg16(ks, KS_RXDBCTR, 4096); /* >4Kbytes in buffer to IRQ */
+       ks8851_wrreg16(ks, KS_RXFCTR, 10);  /* 10 frames to IRQ */
+
+       ks->rc_rxqcr = (RXQCR_RXFCTE |  /* IRQ on frame count exceeded */
+                       RXQCR_RXDBCTE | /* IRQ on byte count exceeded */
+                       RXQCR_RXDTTE);  /* IRQ on time exceeded */
+
+       ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
+
+       /* clear then enable interrupts */
+
+#define STD_IRQ (IRQ_LCI |     /* Link Change */       \
+                IRQ_TXI |      /* TX done */           \
+                IRQ_RXI |      /* RX done */           \
+                IRQ_SPIBEI |   /* SPI bus error */     \
+                IRQ_TXPSI |    /* TX process stop */   \
+                IRQ_RXPSI)     /* RX process stop */
+
+       ks->rc_ier = STD_IRQ;
+       ks8851_wrreg16(ks, KS_ISR, STD_IRQ);
+       ks8851_wrreg16(ks, KS_IER, STD_IRQ);
+
+       netif_start_queue(ks->netdev);
+
+       if (netif_msg_ifup(ks))
+               ks_dbg(ks, "network device %s up\n", dev->name);
+
+       mutex_unlock(&ks->lock);
+       return 0;
+}
+
+/**
+ * ks8851_net_stop - close network device
+ * @dev: The device being closed.
+ *
+ * Called to close down a network device which has been active. Cancell any
+ * work, shutdown the RX and TX process and then place the chip into a low
+ * power state whilst it is not being used.
+ */
+static int ks8851_net_stop(struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+
+       if (netif_msg_ifdown(ks))
+               ks_info(ks, "%s: shutting down\n", dev->name);
+
+       netif_stop_queue(dev);
+
+       mutex_lock(&ks->lock);
+
+       /* stop any outstanding work */
+       flush_work(&ks->irq_work);
+       flush_work(&ks->tx_work);
+       flush_work(&ks->rxctrl_work);
+
+       /* turn off the IRQs and ack any outstanding */
+       ks8851_wrreg16(ks, KS_IER, 0x0000);
+       ks8851_wrreg16(ks, KS_ISR, 0xffff);
+
+       /* shutdown RX process */
+       ks8851_wrreg16(ks, KS_RXCR1, 0x0000);
+
+       /* shutdown TX process */
+       ks8851_wrreg16(ks, KS_TXCR, 0x0000);
+
+       /* set powermode to soft power down to save power */
+       ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN);
+
+       /* ensure any queued tx buffers are dumped */
+       while (!skb_queue_empty(&ks->txq)) {
+               struct sk_buff *txb = skb_dequeue(&ks->txq);
+
+               if (netif_msg_ifdown(ks))
+                       ks_dbg(ks, "%s: freeing txb %p\n", __func__, txb);
+
+               dev_kfree_skb(txb);
+       }
+
+       mutex_unlock(&ks->lock);
+       return 0;
+}
+
+/**
+ * ks8851_start_xmit - transmit packet
+ * @skb: The buffer to transmit
+ * @dev: The device used to transmit the packet.
+ *
+ * Called by the network layer to transmit the @skb. Queue the packet for
+ * the device and schedule the necessary work to transmit the packet when
+ * it is free.
+ *
+ * We do this to firstly avoid sleeping with the network device locked,
+ * and secondly so we can round up more than one packet to transmit which
+ * means we can try and avoid generating too many transmit done interrupts.
+ */
+static int ks8851_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       unsigned needed = calc_txlen(skb->len);
+       int ret = NETDEV_TX_OK;
+
+       if (netif_msg_tx_queued(ks))
+               ks_dbg(ks, "%s: skb %p, %d@%p\n", __func__,
+                      skb, skb->len, skb->data);
+
+       spin_lock(&ks->statelock);
+
+       if (needed > ks->tx_space) {
+               netif_stop_queue(dev);
+               ret = NETDEV_TX_BUSY;
+       } else {
+               ks->tx_space -= needed;
+               skb_queue_tail(&ks->txq, skb);
+       }
+
+       spin_unlock(&ks->statelock);
+       schedule_work(&ks->tx_work);
+
+       return ret;
+}
+
+/**
+ * ks8851_rxctrl_work - work handler to change rx mode
+ * @work: The work structure this belongs to.
+ *
+ * Lock the device and issue the necessary changes to the receive mode from
+ * the network device layer. This is done so that we can do this without
+ * having to sleep whilst holding the network device lock.
+ *
+ * Since the recommendation from Micrel is that the RXQ is shutdown whilst the
+ * receive parameters are programmed, we issue a write to disable the RXQ and
+ * then wait for the interrupt handler to be triggered once the RXQ shutdown is
+ * complete. The interrupt handler then writes the new values into the chip.
+ */
+static void ks8851_rxctrl_work(struct work_struct *work)
+{
+       struct ks8851_net *ks = container_of(work, struct ks8851_net, rxctrl_work);
+
+       mutex_lock(&ks->lock);
+
+       /* need to shutdown RXQ before modifying filter parameters */
+       ks8851_wrreg16(ks, KS_RXCR1, 0x00);
+
+       mutex_unlock(&ks->lock);
+}
+
+static void ks8851_set_rx_mode(struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       struct ks8851_rxctrl rxctrl;
+
+       memset(&rxctrl, 0, sizeof(rxctrl));
+
+       if (dev->flags & IFF_PROMISC) {
+               /* interface to receive everything */
+
+               rxctrl.rxcr1 = RXCR1_RXAE | RXCR1_RXINVF;
+       } else if (dev->flags & IFF_ALLMULTI) {
+               /* accept all multicast packets */
+
+               rxctrl.rxcr1 = (RXCR1_RXME | RXCR1_RXAE |
+                               RXCR1_RXPAFMA | RXCR1_RXMAFMA);
+       } else if (dev->flags & IFF_MULTICAST && dev->mc_count > 0) {
+               struct dev_mc_list *mcptr = dev->mc_list;
+               u32 crc;
+               int i;
+
+               /* accept some multicast */
+
+               for (i = dev->mc_count; i > 0; i--) {
+                       crc = ether_crc(ETH_ALEN, mcptr->dmi_addr);
+                       crc >>= (32 - 6);  /* get top six bits */
+
+                       rxctrl.mchash[crc >> 4] |= (1 << (crc & 0xf));
+                       mcptr = mcptr->next;
+               }
+
+               rxctrl.rxcr1 = RXCR1_RXME | RXCR1_RXAE | RXCR1_RXPAFMA;
+       } else {
+               /* just accept broadcast / unicast */
+               rxctrl.rxcr1 = RXCR1_RXPAFMA;
+       }
+
+       rxctrl.rxcr1 |= (RXCR1_RXUE | /* unicast enable */
+                        RXCR1_RXBE | /* broadcast enable */
+                        RXCR1_RXE | /* RX process enable */
+                        RXCR1_RXFCE); /* enable flow control */
+
+       rxctrl.rxcr2 |= RXCR2_SRDBL_FRAME;
+
+       /* schedule work to do the actual set of the data if needed */
+
+       spin_lock(&ks->statelock);
+
+       if (memcmp(&rxctrl, &ks->rxctrl, sizeof(rxctrl)) != 0) {
+               memcpy(&ks->rxctrl, &rxctrl, sizeof(ks->rxctrl));
+               schedule_work(&ks->rxctrl_work);
+       }
+
+       spin_unlock(&ks->statelock);
+}
+
+static int ks8851_set_mac_address(struct net_device *dev, void *addr)
+{
+       struct sockaddr *sa = addr;
+
+       if (netif_running(dev))
+               return -EBUSY;
+
+       if (!is_valid_ether_addr(sa->sa_data))
+               return -EADDRNOTAVAIL;
+
+       memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
+       return ks8851_write_mac_addr(dev);
+}
+
+static int ks8851_net_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+
+       if (!netif_running(dev))
+               return -EINVAL;
+
+       return generic_mii_ioctl(&ks->mii, if_mii(req), cmd, NULL);
+}
+
+static const struct net_device_ops ks8851_netdev_ops = {
+       .ndo_open               = ks8851_net_open,
+       .ndo_stop               = ks8851_net_stop,
+       .ndo_do_ioctl           = ks8851_net_ioctl,
+       .ndo_start_xmit         = ks8851_start_xmit,
+       .ndo_set_mac_address    = ks8851_set_mac_address,
+       .ndo_set_rx_mode        = ks8851_set_rx_mode,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
+/* ethtool support */
+
+static void ks8851_get_drvinfo(struct net_device *dev,
+                              struct ethtool_drvinfo *di)
+{
+       strlcpy(di->driver, "KS8851", sizeof(di->driver));
+       strlcpy(di->version, "1.00", sizeof(di->version));
+       strlcpy(di->bus_info, dev_name(dev->dev.parent), sizeof(di->bus_info));
+}
+
+static u32 ks8851_get_msglevel(struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       return ks->msg_enable;
+}
+
+static void ks8851_set_msglevel(struct net_device *dev, u32 to)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       ks->msg_enable = to;
+}
+
+static int ks8851_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       return mii_ethtool_gset(&ks->mii, cmd);
+}
+
+static int ks8851_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       return mii_ethtool_sset(&ks->mii, cmd);
+}
+
+static u32 ks8851_get_link(struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       return mii_link_ok(&ks->mii);
+}
+
+static int ks8851_nway_reset(struct net_device *dev)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       return mii_nway_restart(&ks->mii);
+}
+
+static const struct ethtool_ops ks8851_ethtool_ops = {
+       .get_drvinfo    = ks8851_get_drvinfo,
+       .get_msglevel   = ks8851_get_msglevel,
+       .set_msglevel   = ks8851_set_msglevel,
+       .get_settings   = ks8851_get_settings,
+       .set_settings   = ks8851_set_settings,
+       .get_link       = ks8851_get_link,
+       .nway_reset     = ks8851_nway_reset,
+};
+
+/* MII interface controls */
+
+/**
+ * ks8851_phy_reg - convert MII register into a KS8851 register
+ * @reg: MII register number.
+ *
+ * Return the KS8851 register number for the corresponding MII PHY register
+ * if possible. Return zero if the MII register has no direct mapping to the
+ * KS8851 register set.
+ */
+static int ks8851_phy_reg(int reg)
+{
+       switch (reg) {
+       case MII_BMCR:
+               return KS_P1MBCR;
+       case MII_BMSR:
+               return KS_P1MBSR;
+       case MII_PHYSID1:
+               return KS_PHY1ILR;
+       case MII_PHYSID2:
+               return KS_PHY1IHR;
+       case MII_ADVERTISE:
+               return KS_P1ANAR;
+       case MII_LPA:
+               return KS_P1ANLPR;
+       }
+
+       return 0x0;
+}
+
+/**
+ * ks8851_phy_read - MII interface PHY register read.
+ * @dev: The network device the PHY is on.
+ * @phy_addr: Address of PHY (ignored as we only have one)
+ * @reg: The register to read.
+ *
+ * This call reads data from the PHY register specified in @reg. Since the
+ * device does not support all the MII registers, the non-existant values
+ * are always returned as zero.
+ *
+ * We return zero for unsupported registers as the MII code does not check
+ * the value returned for any error status, and simply returns it to the
+ * caller. The mii-tool that the driver was tested with takes any -ve error
+ * as real PHY capabilities, thus displaying incorrect data to the user.
+ */
+static int ks8851_phy_read(struct net_device *dev, int phy_addr, int reg)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       int ksreg;
+       int result;
+
+       ksreg = ks8851_phy_reg(reg);
+       if (!ksreg)
+               return 0x0;     /* no error return allowed, so use zero */
+
+       mutex_lock(&ks->lock);
+       result = ks8851_rdreg16(ks, ksreg);
+       mutex_unlock(&ks->lock);
+
+       return result;
+}
+
+static void ks8851_phy_write(struct net_device *dev,
+                            int phy, int reg, int value)
+{
+       struct ks8851_net *ks = netdev_priv(dev);
+       int ksreg;
+
+       ksreg = ks8851_phy_reg(reg);
+       if (ksreg) {
+               mutex_lock(&ks->lock);
+               ks8851_wrreg16(ks, ksreg, value);
+               mutex_unlock(&ks->lock);
+       }
+}
+
+/**
+ * ks8851_read_selftest - read the selftest memory info.
+ * @ks: The device state
+ *
+ * Read and check the TX/RX memory selftest information.
+ */
+static int ks8851_read_selftest(struct ks8851_net *ks)
+{
+       unsigned both_done = MBIR_TXMBF | MBIR_RXMBF;
+       int ret = 0;
+       unsigned rd;
+
+       rd = ks8851_rdreg16(ks, KS_MBIR);
+
+       if ((rd & both_done) != both_done) {
+               ks_warn(ks, "Memory selftest not finished\n");
+               return 0;
+       }
+
+       if (rd & MBIR_TXMBFA) {
+               ks_err(ks, "TX memory selftest fail\n");
+               ret |= 1;
+       }
+
+       if (rd & MBIR_RXMBFA) {
+               ks_err(ks, "RX memory selftest fail\n");
+               ret |= 2;
+       }
+
+       return 0;
+}
+
+/* driver bus management functions */
+
+static int __devinit ks8851_probe(struct spi_device *spi)
+{
+       struct net_device *ndev;
+       struct ks8851_net *ks;
+       int ret;
+
+       ndev = alloc_etherdev(sizeof(struct ks8851_net));
+       if (!ndev) {
+               dev_err(&spi->dev, "failed to alloc ethernet device\n");
+               return -ENOMEM;
+       }
+
+       spi->bits_per_word = 8;
+
+       ks = netdev_priv(ndev);
+
+       ks->netdev = ndev;
+       ks->spidev = spi;
+       ks->tx_space = 6144;
+
+       mutex_init(&ks->lock);
+       spin_lock_init(&ks->statelock);
+
+       INIT_WORK(&ks->tx_work, ks8851_tx_work);
+       INIT_WORK(&ks->irq_work, ks8851_irq_work);
+       INIT_WORK(&ks->rxctrl_work, ks8851_rxctrl_work);
+
+       /* initialise pre-made spi transfer messages */
+
+       spi_message_init(&ks->spi_msg1);
+       spi_message_add_tail(&ks->spi_xfer1, &ks->spi_msg1);
+
+       spi_message_init(&ks->spi_msg2);
+       spi_message_add_tail(&ks->spi_xfer2[0], &ks->spi_msg2);
+       spi_message_add_tail(&ks->spi_xfer2[1], &ks->spi_msg2);
+
+       /* setup mii state */
+       ks->mii.dev             = ndev;
+       ks->mii.phy_id          = 1,
+       ks->mii.phy_id_mask     = 1;
+       ks->mii.reg_num_mask    = 0xf;
+       ks->mii.mdio_read       = ks8851_phy_read;
+       ks->mii.mdio_write      = ks8851_phy_write;
+
+       dev_info(&spi->dev, "message enable is %d\n", msg_enable);
+
+       /* set the default message enable */
+       ks->msg_enable = netif_msg_init(msg_enable, (NETIF_MSG_DRV |
+                                                    NETIF_MSG_PROBE |
+                                                    NETIF_MSG_LINK));
+
+       skb_queue_head_init(&ks->txq);
+
+       SET_ETHTOOL_OPS(ndev, &ks8851_ethtool_ops);
+       SET_NETDEV_DEV(ndev, &spi->dev);
+
+       dev_set_drvdata(&spi->dev, ks);
+
+       ndev->if_port = IF_PORT_100BASET;
+       ndev->netdev_ops = &ks8851_netdev_ops;
+       ndev->irq = spi->irq;
+
+       /* simple check for a valid chip being connected to the bus */
+
+       if ((ks8851_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) {
+               dev_err(&spi->dev, "failed to read device ID\n");
+               ret = -ENODEV;
+               goto err_id;
+       }
+
+       ks8851_read_selftest(ks);
+       ks8851_init_mac(ks);
+
+       ret = request_irq(spi->irq, ks8851_irq, IRQF_TRIGGER_LOW,
+                         ndev->name, ks);
+       if (ret < 0) {
+               dev_err(&spi->dev, "failed to get irq\n");
+               goto err_irq;
+       }
+
+       ret = register_netdev(ndev);
+       if (ret) {
+               dev_err(&spi->dev, "failed to register network device\n");
+               goto err_netdev;
+       }
+
+       dev_info(&spi->dev, "revision %d, MAC %pM, IRQ %d\n",
+                CIDER_REV_GET(ks8851_rdreg16(ks, KS_CIDER)),
+                ndev->dev_addr, ndev->irq);
+
+       return 0;
+
+
+err_netdev:
+       free_irq(ndev->irq, ndev);
+
+err_id:
+err_irq:
+       free_netdev(ndev);
+       return ret;
+}
+
+static int __devexit ks8851_remove(struct spi_device *spi)
+{
+       struct ks8851_net *priv = dev_get_drvdata(&spi->dev);
+
+       if (netif_msg_drv(priv))
+               dev_info(&spi->dev, "remove");
+
+       unregister_netdev(priv->netdev);
+       free_irq(spi->irq, priv);
+       free_netdev(priv->netdev);
+
+       return 0;
+}
+
+static struct spi_driver ks8851_driver = {
+       .driver = {
+               .name = "ks8851",
+               .owner = THIS_MODULE,
+       },
+       .probe = ks8851_probe,
+       .remove = __devexit_p(ks8851_remove),
+};
+
+static int __init ks8851_init(void)
+{
+       return spi_register_driver(&ks8851_driver);
+}
+
+static void __exit ks8851_exit(void)
+{
+       spi_unregister_driver(&ks8851_driver);
+}
+
+module_init(ks8851_init);
+module_exit(ks8851_exit);
+
+MODULE_DESCRIPTION("KS8851 Network driver");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL");
+
+module_param_named(message, msg_enable, int, 0);
+MODULE_PARM_DESC(message, "Message verbosity level (0=none, 31=all)");
diff --git a/drivers/net/ks8851.h b/drivers/net/ks8851.h
new file mode 100644 (file)
index 0000000..85abe14
--- /dev/null
@@ -0,0 +1,296 @@
+/* drivers/net/ks8851.h
+ *
+ * Copyright 2009 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *
+ * KS8851 register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define KS_CCR                                 0x08
+#define CCR_EEPROM                             (1 << 9)
+#define CCR_SPI                                        (1 << 8)
+#define CCR_32PIN                              (1 << 0)
+
+/* MAC address registers */
+#define KS_MARL                                        0x10
+#define KS_MARM                                        0x12
+#define KS_MARH                                        0x14
+
+#define KS_OBCR                                        0x20
+#define OBCR_ODS_16mA                          (1 << 6)
+
+#define KS_EEPCR                               0x22
+#define EEPCR_EESA                             (1 << 4)
+#define EEPCR_EESB                             (1 << 3)
+#define EEPCR_EEDO                             (1 << 2)
+#define EEPCR_EESCK                            (1 << 1)
+#define EEPCR_EECS                             (1 << 0)
+
+#define KS_MBIR                                        0x24
+#define MBIR_TXMBF                             (1 << 12)
+#define MBIR_TXMBFA                            (1 << 11)
+#define MBIR_RXMBF                             (1 << 4)
+#define MBIR_RXMBFA                            (1 << 3)
+
+#define KS_GRR                                 0x26
+#define GRR_QMU                                        (1 << 1)
+#define GRR_GSR                                        (1 << 0)
+
+#define KS_WFCR                                        0x2A
+#define WFCR_MPRXE                             (1 << 7)
+#define WFCR_WF3E                              (1 << 3)
+#define WFCR_WF2E                              (1 << 2)
+#define WFCR_WF1E                              (1 << 1)
+#define WFCR_WF0E                              (1 << 0)
+
+#define KS_WF0CRC0                             0x30
+#define KS_WF0CRC1                             0x32
+#define KS_WF0BM0                              0x34
+#define KS_WF0BM1                              0x36
+#define KS_WF0BM2                              0x38
+#define KS_WF0BM3                              0x3A
+
+#define KS_WF1CRC0                             0x40
+#define KS_WF1CRC1                             0x42
+#define KS_WF1BM0                              0x44
+#define KS_WF1BM1                              0x46
+#define KS_WF1BM2                              0x48
+#define KS_WF1BM3                              0x4A
+
+#define KS_WF2CRC0                             0x50
+#define KS_WF2CRC1                             0x52
+#define KS_WF2BM0                              0x54
+#define KS_WF2BM1                              0x56
+#define KS_WF2BM2                              0x58
+#define KS_WF2BM3                              0x5A
+
+#define KS_WF3CRC0                             0x60
+#define KS_WF3CRC1                             0x62
+#define KS_WF3BM0                              0x64
+#define KS_WF3BM1                              0x66
+#define KS_WF3BM2                              0x68
+#define KS_WF3BM3                              0x6A
+
+#define KS_TXCR                                        0x70
+#define TXCR_TCGICMP                           (1 << 8)
+#define TXCR_TCGUDP                            (1 << 7)
+#define TXCR_TCGTCP                            (1 << 6)
+#define TXCR_TCGIP                             (1 << 5)
+#define TXCR_FTXQ                              (1 << 4)
+#define TXCR_TXFCE                             (1 << 3)
+#define TXCR_TXPE                              (1 << 2)
+#define TXCR_TXCRC                             (1 << 1)
+#define TXCR_TXE                               (1 << 0)
+
+#define KS_TXSR                                        0x72
+#define TXSR_TXLC                              (1 << 13)
+#define TXSR_TXMC                              (1 << 12)
+#define TXSR_TXFID_MASK                                (0x3f << 0)
+#define TXSR_TXFID_SHIFT                       (0)
+#define TXSR_TXFID_GET(_v)                     (((_v) >> 0) & 0x3f)
+
+#define KS_RXCR1                               0x74
+#define RXCR1_FRXQ                             (1 << 15)
+#define RXCR1_RXUDPFCC                         (1 << 14)
+#define RXCR1_RXTCPFCC                         (1 << 13)
+#define RXCR1_RXIPFCC                          (1 << 12)
+#define RXCR1_RXPAFMA                          (1 << 11)
+#define RXCR1_RXFCE                            (1 << 10)
+#define RXCR1_RXEFE                            (1 << 9)
+#define RXCR1_RXMAFMA                          (1 << 8)
+#define RXCR1_RXBE                             (1 << 7)
+#define RXCR1_RXME                             (1 << 6)
+#define RXCR1_RXUE                             (1 << 5)
+#define RXCR1_RXAE                             (1 << 4)
+#define RXCR1_RXINVF                           (1 << 1)
+#define RXCR1_RXE                              (1 << 0)
+
+#define KS_RXCR2                               0x76
+#define RXCR2_SRDBL_MASK                       (0x7 << 5)
+#define RXCR2_SRDBL_SHIFT                      (5)
+#define RXCR2_SRDBL_4B                         (0x0 << 5)
+#define RXCR2_SRDBL_8B                         (0x1 << 5)
+#define RXCR2_SRDBL_16B                                (0x2 << 5)
+#define RXCR2_SRDBL_32B                                (0x3 << 5)
+#define RXCR2_SRDBL_FRAME                      (0x4 << 5)
+#define RXCR2_IUFFP                            (1 << 4)
+#define RXCR2_RXIUFCEZ                         (1 << 3)
+#define RXCR2_UDPLFE                           (1 << 2)
+#define RXCR2_RXICMPFCC                                (1 << 1)
+#define RXCR2_RXSAF                            (1 << 0)
+
+#define KS_TXMIR                               0x78
+
+#define KS_RXFHSR                              0x7C
+#define RXFSHR_RXFV                            (1 << 15)
+#define RXFSHR_RXICMPFCS                       (1 << 13)
+#define RXFSHR_RXIPFCS                         (1 << 12)
+#define RXFSHR_RXTCPFCS                                (1 << 11)
+#define RXFSHR_RXUDPFCS                                (1 << 10)
+#define RXFSHR_RXBF                            (1 << 7)
+#define RXFSHR_RXMF                            (1 << 6)
+#define RXFSHR_RXUF                            (1 << 5)
+#define RXFSHR_RXMR                            (1 << 4)
+#define RXFSHR_RXFT                            (1 << 3)
+#define RXFSHR_RXFTL                           (1 << 2)
+#define RXFSHR_RXRF                            (1 << 1)
+#define RXFSHR_RXCE                            (1 << 0)
+
+#define KS_RXFHBCR                             0x7E
+#define KS_TXQCR                               0x80
+#define TXQCR_AETFE                            (1 << 2)
+#define TXQCR_TXQMAM                           (1 << 1)
+#define TXQCR_METFE                            (1 << 0)
+
+#define KS_RXQCR                               0x82
+#define RXQCR_RXDTTS                           (1 << 12)
+#define RXQCR_RXDBCTS                          (1 << 11)
+#define RXQCR_RXFCTS                           (1 << 10)
+#define RXQCR_RXIPHTOE                         (1 << 9)
+#define RXQCR_RXDTTE                           (1 << 7)
+#define RXQCR_RXDBCTE                          (1 << 6)
+#define RXQCR_RXFCTE                           (1 << 5)
+#define RXQCR_ADRFE                            (1 << 4)
+#define RXQCR_SDA                              (1 << 3)
+#define RXQCR_RRXEF                            (1 << 0)
+
+#define KS_TXFDPR                              0x84
+#define TXFDPR_TXFPAI                          (1 << 14)
+#define TXFDPR_TXFP_MASK                       (0x7ff << 0)
+#define TXFDPR_TXFP_SHIFT                      (0)
+
+#define KS_RXFDPR                              0x86
+#define RXFDPR_RXFPAI                          (1 << 14)
+
+#define KS_RXDTTR                              0x8C
+#define KS_RXDBCTR                             0x8E
+
+#define KS_IER                                 0x90
+#define KS_ISR                                 0x92
+#define IRQ_LCI                                        (1 << 15)
+#define IRQ_TXI                                        (1 << 14)
+#define IRQ_RXI                                        (1 << 13)
+#define IRQ_RXOI                               (1 << 11)
+#define IRQ_TXPSI                              (1 << 9)
+#define IRQ_RXPSI                              (1 << 8)
+#define IRQ_TXSAI                              (1 << 6)
+#define IRQ_RXWFDI                             (1 << 5)
+#define IRQ_RXMPDI                             (1 << 4)
+#define IRQ_LDI                                        (1 << 3)
+#define IRQ_EDI                                        (1 << 2)
+#define IRQ_SPIBEI                             (1 << 1)
+#define IRQ_DEDI                               (1 << 0)
+
+#define KS_RXFCTR                              0x9C
+#define KS_RXFC                                        0x9D
+#define RXFCTR_RXFC_MASK                       (0xff << 8)
+#define RXFCTR_RXFC_SHIFT                      (8)
+#define RXFCTR_RXFC_GET(_v)                    (((_v) >> 8) & 0xff)
+#define RXFCTR_RXFCT_MASK                      (0xff << 0)
+#define RXFCTR_RXFCT_SHIFT                     (0)
+
+#define KS_TXNTFSR                             0x9E
+
+#define KS_MAHTR0                              0xA0
+#define KS_MAHTR1                              0xA2
+#define KS_MAHTR2                              0xA4
+#define KS_MAHTR3                              0xA6
+
+#define KS_FCLWR                               0xB0
+#define KS_FCHWR                               0xB2
+#define KS_FCOWR                               0xB4
+
+#define KS_CIDER                               0xC0
+#define CIDER_ID                               0x8870
+#define CIDER_REV_MASK                         (0x7 << 1)
+#define CIDER_REV_SHIFT                                (1)
+#define CIDER_REV_GET(_v)                      (((_v) >> 1) & 0x7)
+
+#define KS_CGCR                                        0xC6
+
+#define KS_IACR                                        0xC8
+#define IACR_RDEN                              (1 << 12)
+#define IACR_TSEL_MASK                         (0x3 << 10)
+#define IACR_TSEL_SHIFT                                (10)
+#define IACR_TSEL_MIB                          (0x3 << 10)
+#define IACR_ADDR_MASK                         (0x1f << 0)
+#define IACR_ADDR_SHIFT                                (0)
+
+#define KS_IADLR                               0xD0
+#define KS_IAHDR                               0xD2
+
+#define KS_PMECR                               0xD4
+#define PMECR_PME_DELAY                                (1 << 14)
+#define PMECR_PME_POL                          (1 << 12)
+#define PMECR_WOL_WAKEUP                       (1 << 11)
+#define PMECR_WOL_MAGICPKT                     (1 << 10)
+#define PMECR_WOL_LINKUP                       (1 << 9)
+#define PMECR_WOL_ENERGY                       (1 << 8)
+#define PMECR_AUTO_WAKE_EN                     (1 << 7)
+#define PMECR_WAKEUP_NORMAL                    (1 << 6)
+#define PMECR_WKEVT_MASK                       (0xf << 2)
+#define PMECR_WKEVT_SHIFT                      (2)
+#define PMECR_WKEVT_GET(_v)                    (((_v) >> 2) & 0xf)
+#define PMECR_WKEVT_ENERGY                     (0x1 << 2)
+#define PMECR_WKEVT_LINK                       (0x2 << 2)
+#define PMECR_WKEVT_MAGICPKT                   (0x4 << 2)
+#define PMECR_WKEVT_FRAME                      (0x8 << 2)
+#define PMECR_PM_MASK                          (0x3 << 0)
+#define PMECR_PM_SHIFT                         (0)
+#define PMECR_PM_NORMAL                                (0x0 << 0)
+#define PMECR_PM_ENERGY                                (0x1 << 0)
+#define PMECR_PM_SOFTDOWN                      (0x2 << 0)
+#define PMECR_PM_POWERSAVE                     (0x3 << 0)
+
+/* Standard MII PHY data */
+#define KS_P1MBCR                              0xE4
+#define KS_P1MBSR                              0xE6
+#define KS_PHY1ILR                             0xE8
+#define KS_PHY1IHR                             0xEA
+#define KS_P1ANAR                              0xEC
+#define KS_P1ANLPR                             0xEE
+
+#define KS_P1SCLMD                             0xF4
+#define P1SCLMD_LEDOFF                         (1 << 15)
+#define P1SCLMD_TXIDS                          (1 << 14)
+#define P1SCLMD_RESTARTAN                      (1 << 13)
+#define P1SCLMD_DISAUTOMDIX                    (1 << 10)
+#define P1SCLMD_FORCEMDIX                      (1 << 9)
+#define P1SCLMD_AUTONEGEN                      (1 << 7)
+#define P1SCLMD_FORCE100                       (1 << 6)
+#define P1SCLMD_FORCEFDX                       (1 << 5)
+#define P1SCLMD_ADV_FLOW                       (1 << 4)
+#define P1SCLMD_ADV_100BT_FDX                  (1 << 3)
+#define P1SCLMD_ADV_100BT_HDX                  (1 << 2)
+#define P1SCLMD_ADV_10BT_FDX                   (1 << 1)
+#define P1SCLMD_ADV_10BT_HDX                   (1 << 0)
+
+#define KS_P1CR                                        0xF6
+#define P1CR_HP_MDIX                           (1 << 15)
+#define P1CR_REV_POL                           (1 << 13)
+#define P1CR_OP_100M                           (1 << 10)
+#define P1CR_OP_FDX                            (1 << 9)
+#define P1CR_OP_MDI                            (1 << 7)
+#define P1CR_AN_DONE                           (1 << 6)
+#define P1CR_LINK_GOOD                         (1 << 5)
+#define P1CR_PNTR_FLOW                         (1 << 4)
+#define P1CR_PNTR_100BT_FDX                    (1 << 3)
+#define P1CR_PNTR_100BT_HDX                    (1 << 2)
+#define P1CR_PNTR_10BT_FDX                     (1 << 1)
+#define P1CR_PNTR_10BT_HDX                     (1 << 0)
+
+/* TX Frame control */
+
+#define TXFR_TXIC                              (1 << 15)
+#define TXFR_TXFID_MASK                                (0x3f << 0)
+#define TXFR_TXFID_SHIFT                       (0)
+
+/* SPI frame opcodes */
+#define KS_SPIOP_RD                            (0x00)
+#define KS_SPIOP_WR                            (0x40)
+#define KS_SPIOP_RXFIFO                                (0x80)
+#define KS_SPIOP_TXFIFO                                (0xC0)
index 5b5c25368d1e559e9f2dbbb71013f13efa293ce7..e3601cf3f9315e8462ec530cd25866ed5a78adbc 100644 (file)
@@ -620,6 +620,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
        dma_addr_t mapping;
        unsigned int len, entry;
        u32 ctrl;
+       unsigned long flags;
 
 #ifdef DEBUG
        int i;
@@ -635,12 +636,12 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
 #endif
 
        len = skb->len;
-       spin_lock_irq(&bp->lock);
+       spin_lock_irqsave(&bp->lock, flags);
 
        /* This is a hard error, log it. */
        if (TX_BUFFS_AVAIL(bp) < 1) {
                netif_stop_queue(dev);
-               spin_unlock_irq(&bp->lock);
+               spin_unlock_irqrestore(&bp->lock, flags);
                dev_err(&bp->pdev->dev,
                        "BUG! Tx Ring full when queue awake!\n");
                dev_dbg(&bp->pdev->dev, "tx_head = %u, tx_tail = %u\n",
@@ -674,7 +675,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (TX_BUFFS_AVAIL(bp) < 1)
                netif_stop_queue(dev);
 
-       spin_unlock_irq(&bp->lock);
+       spin_unlock_irqrestore(&bp->lock, flags);
 
        dev->trans_start = jiffies;
 
index acd143da161d5da4a6e757e10c8b6a9a4e2bc809..61eabcac734cdbce1de299924867858740a92ac3 100644 (file)
@@ -179,7 +179,7 @@ static const struct net_device_ops macsonic_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
-static int __init macsonic_init(struct net_device *dev)
+static int __devinit macsonic_init(struct net_device *dev)
 {
        struct sonic_local* lp = netdev_priv(dev);
 
@@ -223,7 +223,7 @@ static int __init macsonic_init(struct net_device *dev)
        return 0;
 }
 
-static int __init mac_onboard_sonic_ethernet_addr(struct net_device *dev)
+static int __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
 {
        struct sonic_local *lp = netdev_priv(dev);
        const int prom_addr = ONBOARD_SONIC_PROM_BASE;
@@ -288,7 +288,7 @@ static int __init mac_onboard_sonic_ethernet_addr(struct net_device *dev)
        } else return 0;
 }
 
-static int __init mac_onboard_sonic_probe(struct net_device *dev)
+static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
 {
        /* Bwahahaha */
        static int once_is_more_than_enough;
@@ -409,7 +409,7 @@ static int __init mac_onboard_sonic_probe(struct net_device *dev)
        return macsonic_init(dev);
 }
 
-static int __init mac_nubus_sonic_ethernet_addr(struct net_device *dev,
+static int __devinit mac_nubus_sonic_ethernet_addr(struct net_device *dev,
                                                unsigned long prom_addr,
                                                int id)
 {
@@ -424,7 +424,7 @@ static int __init mac_nubus_sonic_ethernet_addr(struct net_device *dev,
        return 0;
 }
 
-static int __init macsonic_ident(struct nubus_dev *ndev)
+static int __devinit macsonic_ident(struct nubus_dev *ndev)
 {
        if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC &&
            ndev->dr_sw == NUBUS_DRSW_SONIC_LC)
@@ -449,7 +449,7 @@ static int __init macsonic_ident(struct nubus_dev *ndev)
        return -1;
 }
 
-static int __init mac_nubus_sonic_probe(struct net_device *dev)
+static int __devinit mac_nubus_sonic_probe(struct net_device *dev)
 {
        static int slots;
        struct nubus_dev* ndev = NULL;
@@ -562,7 +562,7 @@ static int __init mac_nubus_sonic_probe(struct net_device *dev)
        return macsonic_init(dev);
 }
 
-static int __init mac_sonic_probe(struct platform_device *pdev)
+static int __devinit mac_sonic_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
        struct sonic_local *lp;
@@ -575,6 +575,7 @@ static int __init mac_sonic_probe(struct platform_device *pdev)
        lp = netdev_priv(dev);
        lp->device = &pdev->dev;
        SET_NETDEV_DEV(dev, &pdev->dev);
+       platform_set_drvdata(pdev, dev);
 
        /* This will catch fatal stuff like -ENOMEM as well as success */
        err = mac_onboard_sonic_probe(dev);
index dc45e9856c35bcd810ad9ab4363d2174a3e2e3ee..6851bdb2ce29957b2293e4bb59e7bb1b37e6ae4c 100644 (file)
 #include <linux/mdio.h>
 #include <linux/module.h>
 
+MODULE_DESCRIPTION("Generic support for MDIO-compatible transceivers");
+MODULE_AUTHOR("Copyright 2006-2009 Solarflare Communications Inc.");
+MODULE_LICENSE("GPL");
+
 /**
  * mdio45_probe - probe for an MDIO (clause 45) device
  * @mdio: MDIO interface
index 2845a0560b84e18fcd28c64e9caa145b59c9a034..65ec77dc31f5b5c4a542a22a2f7d11c464a9d664 100644 (file)
@@ -80,7 +80,9 @@ enum {
        /* Bad management packet (silently discarded): */
        CMD_STAT_BAD_PKT        = 0x30,
        /* More outstanding CQEs in CQ than new CQ size: */
-       CMD_STAT_BAD_SIZE       = 0x40
+       CMD_STAT_BAD_SIZE       = 0x40,
+       /* Multi Function device support required: */
+       CMD_STAT_MULTI_FUNC_REQ = 0x50,
 };
 
 enum {
@@ -128,6 +130,7 @@ static int mlx4_status_to_errno(u8 status)
                [CMD_STAT_LAM_NOT_PRE]    = -EAGAIN,
                [CMD_STAT_BAD_PKT]        = -EINVAL,
                [CMD_STAT_BAD_SIZE]       = -ENOMEM,
+               [CMD_STAT_MULTI_FUNC_REQ] = -EACCES,
        };
 
        if (status >= ARRAY_SIZE(trans_table) ||
index 091f99052c91673f4536004e885cdebca05f598c..86467b444ac679ab4b4a62e25aaba29c38d12bf2 100644 (file)
@@ -220,7 +220,7 @@ static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        cmd->autoneg = AUTONEG_DISABLE;
        cmd->supported = SUPPORTED_10000baseT_Full;
-       cmd->advertising = SUPPORTED_10000baseT_Full;
+       cmd->advertising = ADVERTISED_1000baseT_Full;
        if (netif_carrier_ok(dev)) {
                cmd->speed = SPEED_10000;
                cmd->duplex = DUPLEX_FULL;
index 91bdfdfd431f214665e3b66c6c9028de3f64ff04..3ac0404d0d11e6391531385e7a79bd4662a4602a 100644 (file)
@@ -506,8 +506,9 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
                                 PCI_DMA_FROMDEVICE);
        }
        /* Adjust size of last fragment to match actual length */
-       skb_frags_rx[nr - 1].size = length -
-               priv->frag_info[nr - 1].frag_prefix_size;
+       if (nr > 0)
+               skb_frags_rx[nr - 1].size = length -
+                       priv->frag_info[nr - 1].frag_prefix_size;
        return nr;
 
 fail:
index 08c43f2ae72b0f9fb0ebf4eb08926ceefd5f5fb3..62208401c4df36d307a83eab67d8df7cfc8f5d84 100644 (file)
@@ -249,6 +249,7 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
                                pci_unmap_page(mdev->pdev,
                                        (dma_addr_t) be64_to_cpu(data->addr),
                                         frag->size, PCI_DMA_TODEVICE);
+                               ++data;
                        }
                }
                /* Stamp the freed descriptor */
@@ -436,6 +437,7 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind)
 {
        struct mlx4_en_cq *cq = &priv->tx_cq[tx_ind];
        struct mlx4_en_tx_ring *ring = &priv->tx_ring[tx_ind];
+       unsigned long flags;
 
        /* If we don't have a pending timer, set one up to catch our recent
           post in case the interface becomes idle */
@@ -444,9 +446,9 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind)
 
        /* Poll the CQ every mlx4_en_TX_MODER_POLL packets */
        if ((++ring->poll_cnt & (MLX4_EN_TX_POLL_MODER - 1)) == 0)
-               if (spin_trylock_irq(&ring->comp_lock)) {
+               if (spin_trylock_irqsave(&ring->comp_lock, flags)) {
                        mlx4_en_process_tx_cq(priv->dev, cq);
-                       spin_unlock_irq(&ring->comp_lock);
+                       spin_unlock_irqrestore(&ring->comp_lock, flags);
                }
 }
 
index 018348c011933b1240153f24ee95ba836c83c22c..dac621b1e9fc9a287fb8b4f7fdfa4f538ecc2a77 100644 (file)
@@ -729,7 +729,10 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
 
        err = mlx4_QUERY_FW(dev);
        if (err) {
-               mlx4_err(dev, "QUERY_FW command failed, aborting.\n");
+               if (err == -EACCES)
+                       mlx4_info(dev, "non-primary physical function, skipping.\n");
+               else
+                       mlx4_err(dev, "QUERY_FW command failed, aborting.\n");
                return err;
        }
 
@@ -1285,6 +1288,7 @@ static struct pci_device_id mlx4_pci_table[] = {
        { PCI_VDEVICE(MELLANOX, 0x6750) }, /* MT25408 "Hermon" EN 10GigE PCIe gen2 */
        { PCI_VDEVICE(MELLANOX, 0x6372) }, /* MT25458 ConnectX EN 10GBASE-T 10GigE */
        { PCI_VDEVICE(MELLANOX, 0x675a) }, /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */
+       { PCI_VDEVICE(MELLANOX, 0x6764) }, /* MT26468 ConnectX EN 10GigE PCIe gen2*/
        { 0, }
 };
 
index c9bfe4eea189d9d113feac1a99174b73eb0f4eeb..78c088331f57031e4eb152a66037759f8dee8796 100644 (file)
@@ -130,8 +130,8 @@ static int full_duplex[MAX_UNITS];
 static const char version[] __devinitconst =
   KERN_INFO DRV_NAME " dp8381x driver, version "
       DRV_VERSION ", " DRV_RELDATE "\n"
-  KERN_INFO "  originally by Donald Becker <becker@scyld.com>\n"
-  KERN_INFO "  2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n";
+  "  originally by Donald Becker <becker@scyld.com>\n"
+  "  2.4.x kernel port by Jeff Garzik, Tjeerd Mulder\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("National Semiconductor DP8381x series PCI Ethernet driver");
index 5c3e242428f11a1b5ff2e98a782614031d00a9cf..992dbfffdb05ece983205f5ffe71d5e6073af208 100644 (file)
@@ -321,7 +321,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
        }
 
        if (ei_debug  &&  version_printed++ == 0)
-               printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
+               printk(KERN_INFO "%s%s", version1, version2);
 
        printk(KERN_INFO "NE*000 ethercard probe at %#3lx:", ioaddr);
 
index 970cedeb5f37ba6923454aea9a2fc41ef63519cc..a9c1fcca5e754064e48d420b33334591bce486d5 100644 (file)
 #define _NETXEN_NIC_LINUX_SUBVERSION 30
 #define NETXEN_NIC_LINUX_VERSIONID  "4.0.30"
 
-#define NETXEN_VERSION_CODE(a, b, c)   (((a) << 16) + ((b) << 8) + (c))
+#define NETXEN_VERSION_CODE(a, b, c)   (((a) << 24) + ((b) << 16) + (c))
+#define _major(v)      (((v) >> 24) & 0xff)
+#define _minor(v)      (((v) >> 16) & 0xff)
+#define _build(v)      ((v) & 0xffff)
+
+/* version in image has weird encoding:
+ *  7:0  - major
+ * 15:8  - minor
+ * 31:16 - build (little endian)
+ */
+#define NETXEN_DECODE_VERSION(v) \
+       NETXEN_VERSION_CODE(((v) & 0xff), (((v) >> 8) & 0xff), ((v) >> 16))
 
 #define NETXEN_NUM_FLASH_SECTORS (64)
 #define NETXEN_FLASH_SECTOR_SIZE (64 * 1024)
 #define NETXEN_CTX_SIGNATURE   0xdee0
 #define NETXEN_CTX_SIGNATURE_V2        0x0002dee0
 #define NETXEN_CTX_RESET       0xbad0
+#define NETXEN_CTX_D3_RESET    0xacc0
 #define NETXEN_RCV_PRODUCER(ringid)    (ringid)
 
 #define PHAN_PEG_RCV_INITIALIZED       0xff01
@@ -614,6 +626,7 @@ struct netxen_new_user_info {
 #define NX_P2_MN_ROMIMAGE      0
 #define NX_P3_CT_ROMIMAGE      1
 #define NX_P3_MN_ROMIMAGE      2
+#define NX_FLASH_ROMIMAGE      3
 
 #define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */
 
@@ -761,6 +774,8 @@ struct nx_host_tx_ring {
        u32 crb_cmd_consumer;
        u32 num_desc;
 
+       struct netdev_queue *txq;
+
        struct netxen_cmd_buffer *cmd_buf_arr;
        struct cmd_desc_type0 *desc_head;
        dma_addr_t phys_addr;
@@ -1239,11 +1254,11 @@ struct netxen_adapter {
        u8 mc_enabled;
        u8 max_mc_count;
        u8 rss_supported;
-       u8 resv2;
+       u8 link_changed;
        u32 resv3;
 
        u8 has_link_events;
-       u8 resv1;
+       u8 fw_type;
        u16 tx_context_id;
        u16 mtu;
        u16 is_up;
@@ -1387,6 +1402,7 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter);
 int netxen_initialize_adapter_offload(struct netxen_adapter *adapter);
 int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
 int netxen_load_firmware(struct netxen_adapter *adapter);
+int netxen_need_fw_reset(struct netxen_adapter *adapter);
 void netxen_request_firmware(struct netxen_adapter *adapter);
 void netxen_release_firmware(struct netxen_adapter *adapter);
 int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);
index 4754f5cffad078ce53436b26330b6a0623ee4749..9f8ae4719e2fb4a9d91d4893db5baf675ccd7616 100644 (file)
@@ -684,10 +684,8 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
                        goto err_out_free;
        } else {
                err = netxen_init_old_ctx(adapter);
-               if (err) {
-                       netxen_free_hw_resources(adapter);
-                       return err;
-               }
+               if (err)
+                       goto err_out_free;
        }
 
        return 0;
@@ -708,15 +706,18 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter)
        int port = adapter->portnum;
 
        if (adapter->fw_major >= 4) {
-               nx_fw_cmd_destroy_tx_ctx(adapter);
                nx_fw_cmd_destroy_rx_ctx(adapter);
+               nx_fw_cmd_destroy_tx_ctx(adapter);
        } else {
                netxen_api_lock(adapter);
                NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port),
-                               NETXEN_CTX_RESET | port);
+                               NETXEN_CTX_D3_RESET | port);
                netxen_api_unlock(adapter);
        }
 
+       /* Allow dma queues to drain after context reset */
+       msleep(20);
+
        recv_ctx = &adapter->recv_ctx;
 
        if (recv_ctx->hwctx != NULL) {
index 3cc047844af30d42b555efe35e2aca774c14d4eb..82410367564838aff7f2b5872c3c436a377a183c 100644 (file)
@@ -853,6 +853,7 @@ enum {
 #define NX_PEG_TUNE_CAPABILITY         (NETXEN_CAM_RAM(0x02c))
 
 #define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL               (0x14)
+#define NETXEN_PEG_ALIVE_COUNTER       (NETXEN_CAM_RAM(0xb0))
 
 #define        ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
 #define ISR_LEGACY_INT_TRIGGERED(VAL)  (((VAL) & 0x300) == 0x200)
index ce3b89d2cbb6c11e3ab5749446bec617dcc4edeb..b9123d445c966bbfc2ae7dc7e6f7e9ec46b9711c 100644 (file)
@@ -461,13 +461,14 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
        i = 0;
 
        tx_ring = adapter->tx_ring;
-       netif_tx_lock_bh(adapter->netdev);
+       __netif_tx_lock_bh(tx_ring->txq);
 
        producer = tx_ring->producer;
        consumer = tx_ring->sw_consumer;
 
-       if (nr_desc >= find_diff_among(producer, consumer, tx_ring->num_desc)) {
-               netif_tx_unlock_bh(adapter->netdev);
+       if (nr_desc >= netxen_tx_avail(tx_ring)) {
+               netif_tx_stop_queue(tx_ring->txq);
+               __netif_tx_unlock_bh(tx_ring->txq);
                return -EBUSY;
        }
 
@@ -490,7 +491,7 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
 
        netxen_nic_update_cmd_producer(adapter, tx_ring);
 
-       netif_tx_unlock_bh(adapter->netdev);
+       __netif_tx_unlock_bh(tx_ring->txq);
 
        return 0;
 }
index 055bb61d6e7773b5177e342ebfcc952f4f0a008b..5d3343ef3d86312713481186b541656b1eba3470 100644 (file)
@@ -214,6 +214,7 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
        adapter->tx_ring = tx_ring;
 
        tx_ring->num_desc = adapter->num_txd;
+       tx_ring->txq = netdev_get_tx_queue(netdev, 0);
 
        cmd_buf_arr = vmalloc(TX_BUFF_RINGSIZE(tx_ring));
        if (cmd_buf_arr == NULL) {
@@ -683,12 +684,85 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
        return 0;
 }
 
+int
+netxen_need_fw_reset(struct netxen_adapter *adapter)
+{
+       u32 count, old_count;
+       u32 val, version, major, minor, build;
+       int i, timeout;
+       u8 fw_type;
+
+       /* NX2031 firmware doesn't support heartbit */
+       if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+               return 1;
+
+       /* last attempt had failed */
+       if (NXRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED)
+               return 1;
+
+       old_count = count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
+
+       for (i = 0; i < 10; i++) {
+
+               timeout = msleep_interruptible(200);
+               if (timeout) {
+                       NXWR32(adapter, CRB_CMDPEG_STATE,
+                                       PHAN_INITIALIZE_FAILED);
+                       return -EINTR;
+               }
+
+               count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
+               if (count != old_count)
+                       break;
+       }
+
+       /* firmware is dead */
+       if (count == old_count)
+               return 1;
+
+       /* check if we have got newer or different file firmware */
+       if (adapter->fw) {
+
+               const struct firmware *fw = adapter->fw;
+
+               val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
+               version = NETXEN_DECODE_VERSION(val);
+
+               major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
+               minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
+               build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
+
+               if (version > NETXEN_VERSION_CODE(major, minor, build))
+                       return 1;
+
+               if (version == NETXEN_VERSION_CODE(major, minor, build)) {
+
+                       val = NXRD32(adapter, NETXEN_MIU_MN_CONTROL);
+                       fw_type = (val & 0x4) ?
+                               NX_P3_CT_ROMIMAGE : NX_P3_MN_ROMIMAGE;
+
+                       if (adapter->fw_type != fw_type)
+                               return 1;
+               }
+       }
+
+       return 0;
+}
+
+static char *fw_name[] = {
+       "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin", "flash",
+};
+
 int
 netxen_load_firmware(struct netxen_adapter *adapter)
 {
        u64 *ptr64;
        u32 i, flashaddr, size;
        const struct firmware *fw = adapter->fw;
+       struct pci_dev *pdev = adapter->pdev;
+
+       dev_info(&pdev->dev, "loading firmware from %s\n",
+                       fw_name[adapter->fw_type]);
 
        if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
                NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1);
@@ -756,7 +830,7 @@ static int
 netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname)
 {
        __le32 val;
-       u32 major, minor, build, ver, min_ver, bios;
+       u32 ver, min_ver, bios;
        struct pci_dev *pdev = adapter->pdev;
        const struct firmware *fw = adapter->fw;
 
@@ -768,21 +842,18 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname)
                return -EINVAL;
 
        val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]);
-       major = (__force u32)val & 0xff;
-       minor = ((__force u32)val >> 8) & 0xff;
-       build = (__force u32)val >> 16;
 
        if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
                min_ver = NETXEN_VERSION_CODE(4, 0, 216);
        else
                min_ver = NETXEN_VERSION_CODE(3, 4, 216);
 
-       ver = NETXEN_VERSION_CODE(major, minor, build);
+       ver = NETXEN_DECODE_VERSION(val);
 
-       if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) {
+       if ((_major(ver) > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) {
                dev_err(&pdev->dev,
                                "%s: firmware version %d.%d.%d unsupported\n",
-                               fwname, major, minor, build);
+                               fwname, _major(ver), _minor(ver), _build(ver));
                return -EINVAL;
        }
 
@@ -798,22 +869,21 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname)
        if (netxen_rom_fast_read(adapter,
                        NX_FW_VERSION_OFFSET, (int *)&val))
                return -EIO;
-       major = (__force u32)val & 0xff;
-       minor = ((__force u32)val >> 8) & 0xff;
-       build = (__force u32)val >> 16;
-       if (NETXEN_VERSION_CODE(major, minor, build) > ver)
+       val = NETXEN_DECODE_VERSION(val);
+       if (val > ver) {
+               dev_info(&pdev->dev, "%s: firmware is older than flash\n",
+                               fwname);
                return -EINVAL;
+       }
 
        NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
        return 0;
 }
 
-static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" };
-
 void netxen_request_firmware(struct netxen_adapter *adapter)
 {
        u32 capability, flashed_ver;
-       int fw_type;
+       u8 fw_type;
        struct pci_dev *pdev = adapter->pdev;
        int rc = 0;
 
@@ -830,6 +900,8 @@ request_mn:
 
        netxen_rom_fast_read(adapter,
                        NX_FW_VERSION_OFFSET, (int *)&flashed_ver);
+       flashed_ver = NETXEN_DECODE_VERSION(flashed_ver);
+
        if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) {
                capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY);
                if (capability & NX_PEG_TUNE_MN_PRESENT) {
@@ -838,6 +910,10 @@ request_mn:
                }
        }
 
+       fw_type = NX_FLASH_ROMIMAGE;
+       adapter->fw = NULL;
+       goto done;
+
 request_fw:
        rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev);
        if (rc != 0) {
@@ -846,6 +922,7 @@ request_fw:
                        goto request_mn;
                }
 
+               fw_type = NX_FLASH_ROMIMAGE;
                adapter->fw = NULL;
                goto done;
        }
@@ -859,16 +936,13 @@ request_fw:
                        goto request_mn;
                }
 
+               fw_type = NX_FLASH_ROMIMAGE;
                adapter->fw = NULL;
                goto done;
        }
 
 done:
-       if (adapter->fw)
-               dev_info(&pdev->dev, "loading firmware from file %s\n",
-                               fw_name[fw_type]);
-       else
-               dev_info(&pdev->dev, "loading firmware from flash\n");
+       adapter->fw_type = fw_type;
 }
 
 
@@ -1327,10 +1401,10 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
                smp_mb();
 
                if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
-                       netif_tx_lock(netdev);
+                       __netif_tx_lock(tx_ring->txq, smp_processor_id());
                        if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH)
                                netif_wake_queue(netdev);
-                       netif_tx_unlock(netdev);
+                       __netif_tx_unlock(tx_ring->txq);
                }
        }
        /*
index 2919a2d12bf40c5327f4979059eed3ea1de78878..28f270f5ac784e47d6c12110752f988bcae65b33 100644 (file)
@@ -94,10 +94,6 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
 
 MODULE_DEVICE_TABLE(pci, netxen_pci_tbl);
 
-static struct workqueue_struct *netxen_workq;
-#define SCHEDULE_WORK(tp)      queue_work(netxen_workq, tp)
-#define FLUSH_SCHEDULED_WORK() flush_workqueue(netxen_workq)
-
 static void netxen_watchdog(unsigned long);
 
 static uint32_t crb_cmd_producer[4] = {
@@ -171,6 +167,8 @@ netxen_free_sds_rings(struct netxen_recv_context *recv_ctx)
 {
        if (recv_ctx->sds_rings != NULL)
                kfree(recv_ctx->sds_rings);
+
+       recv_ctx->sds_rings = NULL;
 }
 
 static int
@@ -192,6 +190,21 @@ netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev)
        return 0;
 }
 
+static void
+netxen_napi_del(struct netxen_adapter *adapter)
+{
+       int ring;
+       struct nx_host_sds_ring *sds_ring;
+       struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+               sds_ring = &recv_ctx->sds_rings[ring];
+               netif_napi_del(&sds_ring->napi);
+       }
+
+       netxen_free_sds_rings(&adapter->recv_ctx);
+}
+
 static void
 netxen_napi_enable(struct netxen_adapter *adapter)
 {
@@ -215,13 +228,13 @@ netxen_napi_disable(struct netxen_adapter *adapter)
 
        for (ring = 0; ring < adapter->max_sds_rings; ring++) {
                sds_ring = &recv_ctx->sds_rings[ring];
-               napi_disable(&sds_ring->napi);
                netxen_nic_disable_int(sds_ring);
-               synchronize_irq(sds_ring->irq);
+               napi_synchronize(&sds_ring->napi);
+               napi_disable(&sds_ring->napi);
        }
 }
 
-static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id)
+static int nx_set_dma_mask(struct netxen_adapter *adapter)
 {
        struct pci_dev *pdev = adapter->pdev;
        uint64_t mask, cmask;
@@ -229,19 +242,17 @@ static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id)
        adapter->pci_using_dac = 0;
 
        mask = DMA_BIT_MASK(32);
-       /*
-        * Consistent DMA mask is set to 32 bit because it cannot be set to
-        * 35 bits. For P3 also leave it at 32 bits for now. Only the rings
-        * come off this pool.
-        */
        cmask = DMA_BIT_MASK(32);
 
+       if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
 #ifndef CONFIG_IA64
-       if (revision_id >= NX_P3_B0)
-               mask = DMA_BIT_MASK(39);
-       else if (revision_id == NX_P2_C1)
                mask = DMA_BIT_MASK(35);
 #endif
+       } else {
+               mask = DMA_BIT_MASK(39);
+               cmask = mask;
+       }
+
        if (pci_set_dma_mask(pdev, mask) == 0 &&
                pci_set_consistent_dma_mask(pdev, cmask) == 0) {
                adapter->pci_using_dac = 1;
@@ -256,13 +267,13 @@ static int
 nx_update_dma_mask(struct netxen_adapter *adapter)
 {
        int change, shift, err;
-       uint64_t mask, old_mask;
+       uint64_t mask, old_mask, old_cmask;
        struct pci_dev *pdev = adapter->pdev;
 
        change = 0;
 
        shift = NXRD32(adapter, CRB_DMA_SHIFT);
-       if (shift >= 32)
+       if (shift > 32)
                return 0;
 
        if (NX_IS_REVISION_P3(adapter->ahw.revision_id) && (shift > 9))
@@ -272,14 +283,29 @@ nx_update_dma_mask(struct netxen_adapter *adapter)
 
        if (change) {
                old_mask = pdev->dma_mask;
-               mask = (1ULL<<(32+shift)) - 1;
+               old_cmask = pdev->dev.coherent_dma_mask;
+
+               mask = DMA_BIT_MASK(32+shift);
 
                err = pci_set_dma_mask(pdev, mask);
                if (err)
-                       return pci_set_dma_mask(pdev, old_mask);
+                       goto err_out;
+
+               if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+
+                       err = pci_set_consistent_dma_mask(pdev, mask);
+                       if (err)
+                               goto err_out;
+               }
+               dev_info(&pdev->dev, "using %d-bit dma mask\n", 32+shift);
        }
 
        return 0;
+
+err_out:
+       pci_set_dma_mask(pdev, old_mask);
+       pci_set_consistent_dma_mask(pdev, old_cmask);
+       return err;
 }
 
 static void netxen_check_options(struct netxen_adapter *adapter)
@@ -718,6 +744,10 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw)
        if (request_fw)
                netxen_request_firmware(adapter);
 
+       err = netxen_need_fw_reset(adapter);
+       if (err <= 0)
+               return err;
+
        if (first_boot != 0x55555555) {
                NXWR32(adapter, CRB_CMDPEG_STATE, 0);
                netxen_pinit_from_rom(adapter, 0);
@@ -829,11 +859,11 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
 
        adapter->ahw.linkup = 0;
 
-       netxen_napi_enable(adapter);
-
        if (adapter->max_sds_rings > 1)
                netxen_config_rss(adapter, 1);
 
+       netxen_napi_enable(adapter);
+
        if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION)
                netxen_linkevent_request(adapter, 1);
        else
@@ -847,8 +877,9 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
 static void
 netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
 {
+       spin_lock(&adapter->tx_clean_lock);
        netif_carrier_off(netdev);
-       netif_stop_queue(netdev);
+       netif_tx_disable(netdev);
 
        if (adapter->stop_port)
                adapter->stop_port(adapter);
@@ -859,8 +890,8 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
        netxen_napi_disable(adapter);
 
        netxen_release_tx_buffers(adapter);
+       spin_unlock(&adapter->tx_clean_lock);
 
-       FLUSH_SCHEDULED_WORK();
        del_timer_sync(&adapter->watchdog_timer);
 }
 
@@ -875,10 +906,12 @@ netxen_nic_attach(struct netxen_adapter *adapter)
        struct nx_host_tx_ring *tx_ring;
 
        err = netxen_init_firmware(adapter);
-       if (err != 0) {
-               printk(KERN_ERR "Failed to init firmware\n");
-               return -EIO;
-       }
+       if (err)
+               return err;
+
+       err = netxen_napi_add(adapter, netdev);
+       if (err)
+               return err;
 
        if (adapter->fw_major < 4)
                adapter->max_rds_rings = 3;
@@ -939,9 +972,10 @@ err_out_free_sw:
 static void
 netxen_nic_detach(struct netxen_adapter *adapter)
 {
-       netxen_release_rx_buffers(adapter);
        netxen_free_hw_resources(adapter);
+       netxen_release_rx_buffers(adapter);
        netxen_nic_free_irq(adapter);
+       netxen_napi_del(adapter);
        netxen_free_sw_resources(adapter);
 
        adapter->is_up = 0;
@@ -1000,7 +1034,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        revision_id = pdev->revision;
        adapter->ahw.revision_id = revision_id;
 
-       err = nx_set_dma_mask(adapter, revision_id);
+       err = nx_set_dma_mask(adapter);
        if (err)
                goto err_out_free_netdev;
 
@@ -1086,9 +1120,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        netdev->irq = adapter->msix_entries[0].vector;
 
-       if (netxen_napi_add(adapter, netdev))
-               goto err_out_disable_msi;
-
        init_timer(&adapter->watchdog_timer);
        adapter->watchdog_timer.function = &netxen_watchdog;
        adapter->watchdog_timer.data = (unsigned long)adapter;
@@ -1158,6 +1189,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
 
        unregister_netdev(netdev);
 
+       cancel_work_sync(&adapter->watchdog_task);
+       cancel_work_sync(&adapter->tx_timeout_task);
+
        if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
                netxen_nic_detach(adapter);
        }
@@ -1166,7 +1200,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
                netxen_free_adapter_offload(adapter);
 
        netxen_teardown_intr(adapter);
-       netxen_free_sds_rings(&adapter->recv_ctx);
 
        netxen_cleanup_pci_map(adapter);
 
@@ -1192,6 +1225,9 @@ netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state)
        if (netif_running(netdev))
                netxen_nic_down(adapter, netdev);
 
+       cancel_work_sync(&adapter->watchdog_task);
+       cancel_work_sync(&adapter->tx_timeout_task);
+
        if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC)
                netxen_nic_detach(adapter);
 
@@ -1529,10 +1565,7 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter)
                printk(KERN_ALERT
                       "%s: Device temperature %d degrees C exceeds"
                       " maximum allowed. Hardware has been shut down.\n",
-                      netxen_nic_driver_name, temp_val);
-
-               netif_carrier_off(netdev);
-               netif_stop_queue(netdev);
+                      netdev->name, temp_val);
                rv = 1;
        } else if (temp_state == NX_TEMP_WARN) {
                if (adapter->temp == NX_TEMP_NORMAL) {
@@ -1540,13 +1573,13 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter)
                               "%s: Device temperature %d degrees C "
                               "exceeds operating range."
                               " Immediate action needed.\n",
-                              netxen_nic_driver_name, temp_val);
+                              netdev->name, temp_val);
                }
        } else {
                if (adapter->temp == NX_TEMP_WARN) {
                        printk(KERN_INFO
                               "%s: Device temperature is now %d degrees C"
-                              " in normal range.\n", netxen_nic_driver_name,
+                              " in normal range.\n", netdev->name,
                               temp_val);
                }
        }
@@ -1566,10 +1599,7 @@ void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup)
                        netif_carrier_off(netdev);
                        netif_stop_queue(netdev);
                }
-
-               if (!adapter->has_link_events)
-                       netxen_nic_set_link_parameters(adapter);
-
+               adapter->link_changed = !adapter->has_link_events;
        } else if (!adapter->ahw.linkup && linkup) {
                printk(KERN_INFO "%s: %s NIC Link is up\n",
                       netxen_nic_driver_name, netdev->name);
@@ -1578,9 +1608,7 @@ void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup)
                        netif_carrier_on(netdev);
                        netif_wake_queue(netdev);
                }
-
-               if (!adapter->has_link_events)
-                       netxen_nic_set_link_parameters(adapter);
+               adapter->link_changed = !adapter->has_link_events;
        }
 }
 
@@ -1607,11 +1635,36 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
        netxen_advert_link_change(adapter, linkup);
 }
 
+static void netxen_nic_thermal_shutdown(struct netxen_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
+
+       netif_device_detach(netdev);
+       netxen_nic_down(adapter, netdev);
+       netxen_nic_detach(adapter);
+}
+
 static void netxen_watchdog(unsigned long v)
 {
        struct netxen_adapter *adapter = (struct netxen_adapter *)v;
 
-       SCHEDULE_WORK(&adapter->watchdog_task);
+       if (netxen_nic_check_temp(adapter))
+               goto do_sched;
+
+       if (!adapter->has_link_events) {
+               netxen_nic_handle_phy_intr(adapter);
+
+               if (adapter->link_changed)
+                       goto do_sched;
+       }
+
+       if (netif_running(adapter->netdev))
+               mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+
+       return;
+
+do_sched:
+       schedule_work(&adapter->watchdog_task);
 }
 
 void netxen_watchdog_task(struct work_struct *work)
@@ -1619,11 +1672,13 @@ void netxen_watchdog_task(struct work_struct *work)
        struct netxen_adapter *adapter =
                container_of(work, struct netxen_adapter, watchdog_task);
 
-       if ((adapter->portnum  == 0) && netxen_nic_check_temp(adapter))
+       if (adapter->temp == NX_TEMP_PANIC) {
+               netxen_nic_thermal_shutdown(adapter);
                return;
+       }
 
-       if (!adapter->has_link_events)
-               netxen_nic_handle_phy_intr(adapter);
+       if (adapter->link_changed)
+               netxen_nic_set_link_parameters(adapter);
 
        if (netif_running(adapter->netdev))
                mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
@@ -1631,9 +1686,8 @@ void netxen_watchdog_task(struct work_struct *work)
 
 static void netxen_tx_timeout(struct net_device *netdev)
 {
-       struct netxen_adapter *adapter = (struct netxen_adapter *)
-                                               netdev_priv(netdev);
-       SCHEDULE_WORK(&adapter->tx_timeout_task);
+       struct netxen_adapter *adapter = netdev_priv(netdev);
+       schedule_work(&adapter->tx_timeout_task);
 }
 
 static void netxen_tx_timeout_task(struct work_struct *work)
@@ -1641,6 +1695,9 @@ static void netxen_tx_timeout_task(struct work_struct *work)
        struct netxen_adapter *adapter =
                container_of(work, struct netxen_adapter, tx_timeout_task);
 
+       if (!netif_running(adapter->netdev))
+               return;
+
        printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
               netxen_nic_driver_name, adapter->netdev->name);
 
@@ -1753,7 +1810,8 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget)
 
        if ((work_done < budget) && tx_complete) {
                napi_complete(&sds_ring->napi);
-               netxen_nic_enable_int(sds_ring);
+               if (netif_running(adapter->netdev))
+                       netxen_nic_enable_int(sds_ring);
        }
 
        return work_done;
@@ -1786,9 +1844,6 @@ static int __init netxen_init_module(void)
 {
        printk(KERN_INFO "%s\n", netxen_nic_driver_string);
 
-       if ((netxen_workq = create_singlethread_workqueue("netxen")) == NULL)
-               return -ENOMEM;
-
        return pci_register_driver(&netxen_driver);
 }
 
@@ -1797,7 +1852,6 @@ module_init(netxen_init_module);
 static void __exit netxen_exit_module(void)
 {
        pci_unregister_driver(&netxen_driver);
-       destroy_workqueue(netxen_workq);
 }
 
 module_exit(netxen_exit_module);
index 8c1f6988f398bdbc42305fb1aed09fffb9db97ed..89f7b2ad523116c51ea7d612d43e32205c8515d6 100644 (file)
@@ -105,7 +105,7 @@ IVc. Errata
 
 static char version[] __devinitdata =
 KERN_INFO NETDRV_DRIVER_LOAD_MSG "\n"
-KERN_INFO "  Support available from http://foo.com/bar/baz.html\n";
+"  Support available from http://foo.com/bar/baz.html\n";
 
 /* define to 1 to enable PIO instead of MMIO */
 #undef USE_IO_OPS
index ec7cf5ac4f0595275551e3addecf16747be79c92..690b9c76d34ebf9f22772a727268e1441db4d92f 100644 (file)
@@ -156,6 +156,7 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev);
 static int el3_rx(struct net_device *dev);
 static int el3_close(struct net_device *dev);
 static void el3_tx_timeout(struct net_device *dev);
+static void set_rx_mode(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static const struct ethtool_ops netdev_ethtool_ops;
 
@@ -488,8 +489,7 @@ static void tc589_reset(struct net_device *dev)
     /* Switch to register set 1 for normal use. */
     EL3WINDOW(1);
 
-    /* Accept b-cast and phys addr only. */
-    outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
+    set_rx_mode(dev);
     outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
     outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
     outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
@@ -700,7 +700,7 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id)
                if (fifo_diag & 0x2000) {
                    /* Rx underrun */
                    tc589_wait_for_completion(dev, RxReset);
-                   set_multicast_list(dev);
+                   set_rx_mode(dev);
                    outw(RxEnable, ioaddr + EL3_CMD);
                }
                outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
@@ -905,14 +905,11 @@ static int el3_rx(struct net_device *dev)
     return 0;
 }
 
-static void set_multicast_list(struct net_device *dev)
+static void set_rx_mode(struct net_device *dev)
 {
-    struct el3_private *lp = netdev_priv(dev);
-    struct pcmcia_device *link = lp->p_dev;
     unsigned int ioaddr = dev->base_addr;
     u16 opts = SetRxFilter | RxStation | RxBroadcast;
 
-    if (!pcmcia_dev_present(link)) return;
     if (dev->flags & IFF_PROMISC)
        opts |= RxMulticast | RxProm;
     else if (dev->mc_count || (dev->flags & IFF_ALLMULTI))
@@ -920,6 +917,16 @@ static void set_multicast_list(struct net_device *dev)
     outw(opts, ioaddr + EL3_CMD);
 }
 
+static void set_multicast_list(struct net_device *dev)
+{
+       struct el3_private *priv = netdev_priv(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       set_rx_mode(dev);
+       spin_unlock_irqrestore(&priv->lock, flags);
+}
+
 static int el3_close(struct net_device *dev)
 {
     struct el3_private *lp = netdev_priv(dev);
index f51944b28cfa7008bd05f282844013e5459c6fc2..06618af1a4680d6c208536c903aa5de8638e8d2f 100644 (file)
@@ -298,14 +298,11 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)
 
     strcpy(info->node.dev_name, dev->name);
 
-    printk(KERN_INFO "%s: port %#3lx, irq %d,",
-           dev->name, dev->base_addr, dev->irq);
-    printk (" mmio %#5lx,", (u_long)ti->mmio);
-    printk (" sram %#5lx,", (u_long)ti->sram_base << 12);
-    printk ("\n" KERN_INFO "  hwaddr=");
-    for (i = 0; i < TR_ALEN; i++)
-        printk("%02X", dev->dev_addr[i]);
-    printk("\n");
+    printk(KERN_INFO
+          "%s: port %#3lx, irq %d,  mmio %#5lx, sram %#5lx, hwaddr=%pM\n",
+           dev->name, dev->base_addr, dev->irq,
+          (u_long)ti->mmio, (u_long)(ti->sram_base << 12),
+          dev->dev_addr);
     return 0;
 
 cs_failed:
index 02ef63ed1f99ba6b6d630822baa6b5ddf897e2d2..36de91baf2387dbe5eaf88270f7aeacd4992c75d 100644 (file)
@@ -1425,15 +1425,12 @@ static void BuildLAF(int *ladrf, int *adr)
   ladrf[byte] |= (1 << (hashcode & 7));
 
 #ifdef PCMCIA_DEBUG
-  if (pc_debug > 2) {
-    printk(KERN_DEBUG "    adr =");
-    for (i = 0; i < 6; i++)
-      printk(" %02X", adr[i]);
-    printk("\n" KERN_DEBUG "    hashcode = %d(decimal), ladrf[0:63]"
-          " =", hashcode);
-    for (i = 0; i < 8; i++)
-      printk(" %02X", ladrf[i]);
-    printk("\n");
+  if (pc_debug > 2)
+    printk(KERN_DEBUG "    adr =%pM\n", adr);
+  printk(KERN_DEBUG "    hashcode = %d(decimal), ladrf[0:63] =", hashcode);
+  for (i = 0; i < 8; i++)
+    printk(KERN_CONT " %02X", ladrf[i]);
+  printk(KERN_CONT "\n");
   }
 #endif
 } /* BuildLAF */
index 652a368883612f6c837e2e5b1c1123f29187c2ae..9ef1c1bfa83d3062b6c2d903faceee333eb47141 100644 (file)
@@ -1727,6 +1727,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50),
        PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110),
        PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941),
+       PCMCIA_DEVICE_PROD_ID12("RIOS Systems Co.", "PC CARD3 ETHERNET", 0x7dd33481, 0x10b41826),
        PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df),
        PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0),
        PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd),
index 1c35e1d637a0e30aecd6f3369a0f89cdbf34b972..23e1a0750fe0eba518dc87b1bfbbef7e4cf8283b 100644 (file)
@@ -485,7 +485,7 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev,
                                           &new_ring_dma_addr);
        if (new_tx_ring == NULL) {
                if (netif_msg_drv(lp))
-                       printk("\n" KERN_ERR
+                       printk(KERN_ERR
                               "%s: Consistent memory allocation failed.\n",
                               dev->name);
                return;
@@ -496,7 +496,7 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev,
                                GFP_ATOMIC);
        if (!new_dma_addr_list) {
                if (netif_msg_drv(lp))
-                       printk("\n" KERN_ERR
+                       printk(KERN_ERR
                               "%s: Memory allocation failed.\n", dev->name);
                goto free_new_tx_ring;
        }
@@ -505,7 +505,7 @@ static void pcnet32_realloc_tx_ring(struct net_device *dev,
                                GFP_ATOMIC);
        if (!new_skb_list) {
                if (netif_msg_drv(lp))
-                       printk("\n" KERN_ERR
+                       printk(KERN_ERR
                               "%s: Memory allocation failed.\n", dev->name);
                goto free_new_lists;
        }
@@ -563,7 +563,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
                                           &new_ring_dma_addr);
        if (new_rx_ring == NULL) {
                if (netif_msg_drv(lp))
-                       printk("\n" KERN_ERR
+                       printk(KERN_ERR
                               "%s: Consistent memory allocation failed.\n",
                               dev->name);
                return;
@@ -574,7 +574,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
                                GFP_ATOMIC);
        if (!new_dma_addr_list) {
                if (netif_msg_drv(lp))
-                       printk("\n" KERN_ERR
+                       printk(KERN_ERR
                               "%s: Memory allocation failed.\n", dev->name);
                goto free_new_rx_ring;
        }
@@ -583,7 +583,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
                                GFP_ATOMIC);
        if (!new_skb_list) {
                if (netif_msg_drv(lp))
-                       printk("\n" KERN_ERR
+                       printk(KERN_ERR
                               "%s: Memory allocation failed.\n", dev->name);
                goto free_new_lists;
        }
@@ -1611,8 +1611,11 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
                if (pcnet32_dwio_read_csr(ioaddr, 0) == 4
                    && pcnet32_dwio_check(ioaddr)) {
                        a = &pcnet32_dwio;
-               } else
+               } else {
+                       if (pcnet32_debug & NETIF_MSG_PROBE)
+                               printk(KERN_ERR PFX "No access methods\n");
                        goto err_release_region;
+               }
        }
 
        chip_version =
@@ -1719,7 +1722,9 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
                ret = -ENOMEM;
                goto err_release_region;
        }
-       SET_NETDEV_DEV(dev, &pdev->dev);
+
+       if (pdev)
+               SET_NETDEV_DEV(dev, &pdev->dev);
 
        if (pcnet32_debug & NETIF_MSG_PROBE)
                printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr);
@@ -1766,38 +1771,38 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
                /* Version 0x2623 and 0x2624 */
                if (((chip_version + 1) & 0xfffe) == 0x2624) {
                        i = a->read_csr(ioaddr, 80) & 0x0C00;   /* Check tx_start_pt */
-                       printk("\n" KERN_INFO "    tx_start_pt(0x%04x):", i);
+                       printk(KERN_INFO "    tx_start_pt(0x%04x):", i);
                        switch (i >> 10) {
                        case 0:
-                               printk("  20 bytes,");
+                               printk(KERN_CONT "  20 bytes,");
                                break;
                        case 1:
-                               printk("  64 bytes,");
+                               printk(KERN_CONT "  64 bytes,");
                                break;
                        case 2:
-                               printk(" 128 bytes,");
+                               printk(KERN_CONT " 128 bytes,");
                                break;
                        case 3:
-                               printk("~220 bytes,");
+                               printk(KERN_CONT "~220 bytes,");
                                break;
                        }
                        i = a->read_bcr(ioaddr, 18);    /* Check Burst/Bus control */
-                       printk(" BCR18(%x):", i & 0xffff);
+                       printk(KERN_CONT " BCR18(%x):", i & 0xffff);
                        if (i & (1 << 5))
-                               printk("BurstWrEn ");
+                               printk(KERN_CONT "BurstWrEn ");
                        if (i & (1 << 6))
-                               printk("BurstRdEn ");
+                               printk(KERN_CONT "BurstRdEn ");
                        if (i & (1 << 7))
-                               printk("DWordIO ");
+                               printk(KERN_CONT "DWordIO ");
                        if (i & (1 << 11))
-                               printk("NoUFlow ");
+                               printk(KERN_CONT "NoUFlow ");
                        i = a->read_bcr(ioaddr, 25);
-                       printk("\n" KERN_INFO "    SRAMSIZE=0x%04x,", i << 8);
+                       printk(KERN_INFO "    SRAMSIZE=0x%04x,", i << 8);
                        i = a->read_bcr(ioaddr, 26);
-                       printk(" SRAM_BND=0x%04x,", i << 8);
+                       printk(KERN_CONT " SRAM_BND=0x%04x,", i << 8);
                        i = a->read_bcr(ioaddr, 27);
                        if (i & (1 << 14))
-                               printk("LowLatRx");
+                               printk(KERN_CONT "LowLatRx");
                }
        }
 
@@ -1818,7 +1823,6 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
 
        spin_lock_init(&lp->lock);
 
-       SET_NETDEV_DEV(dev, &pdev->dev);
        lp->name = chipname;
        lp->shared_irq = shared;
        lp->tx_ring_size = TX_RING_SIZE;        /* default tx ring size */
@@ -1835,7 +1839,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
        lp->chip_version = chip_version;
        lp->msg_enable = pcnet32_debug;
        if ((cards_found >= MAX_UNITS)
-           || (options[cards_found] > sizeof(options_mapping)))
+           || (options[cards_found] >= sizeof(options_mapping)))
                lp->options = PCNET32_PORT_ASEL;
        else
                lp->options = options_mapping[options[cards_found]];
@@ -1852,12 +1856,6 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
            ((cards_found >= MAX_UNITS) || full_duplex[cards_found]))
                lp->options |= PCNET32_PORT_FD;
 
-       if (!a) {
-               if (pcnet32_debug & NETIF_MSG_PROBE)
-                       printk(KERN_ERR PFX "No access methods\n");
-               ret = -ENODEV;
-               goto err_free_consistent;
-       }
        lp->a = *a;
 
        /* prior to register_netdev, dev->name is not yet correct */
@@ -1973,14 +1971,13 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
 
        return 0;
 
-      err_free_ring:
+err_free_ring:
        pcnet32_free_ring(dev);
-      err_free_consistent:
        pci_free_consistent(lp->pci_dev, sizeof(*lp->init_block),
                            lp->init_block, lp->init_dma_addr);
-      err_free_netdev:
+err_free_netdev:
        free_netdev(dev);
-      err_release_region:
+err_release_region:
        release_region(ioaddr, PCNET32_TOTAL_SIZE);
        return ret;
 }
@@ -1996,7 +1993,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name)
                                           &lp->tx_ring_dma_addr);
        if (lp->tx_ring == NULL) {
                if (netif_msg_drv(lp))
-                       printk("\n" KERN_ERR PFX
+                       printk(KERN_ERR PFX
                               "%s: Consistent memory allocation failed.\n",
                               name);
                return -ENOMEM;
@@ -2008,7 +2005,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name)
                                           &lp->rx_ring_dma_addr);
        if (lp->rx_ring == NULL) {
                if (netif_msg_drv(lp))
-                       printk("\n" KERN_ERR PFX
+                       printk(KERN_ERR PFX
                               "%s: Consistent memory allocation failed.\n",
                               name);
                return -ENOMEM;
@@ -2018,7 +2015,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name)
                                  GFP_ATOMIC);
        if (!lp->tx_dma_addr) {
                if (netif_msg_drv(lp))
-                       printk("\n" KERN_ERR PFX
+                       printk(KERN_ERR PFX
                               "%s: Memory allocation failed.\n", name);
                return -ENOMEM;
        }
@@ -2027,7 +2024,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name)
                                  GFP_ATOMIC);
        if (!lp->rx_dma_addr) {
                if (netif_msg_drv(lp))
-                       printk("\n" KERN_ERR PFX
+                       printk(KERN_ERR PFX
                               "%s: Memory allocation failed.\n", name);
                return -ENOMEM;
        }
@@ -2036,7 +2033,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name)
                                GFP_ATOMIC);
        if (!lp->tx_skbuff) {
                if (netif_msg_drv(lp))
-                       printk("\n" KERN_ERR PFX
+                       printk(KERN_ERR PFX
                               "%s: Memory allocation failed.\n", name);
                return -ENOMEM;
        }
@@ -2045,7 +2042,7 @@ static int pcnet32_alloc_ring(struct net_device *dev, const char *name)
                                GFP_ATOMIC);
        if (!lp->rx_skbuff) {
                if (netif_msg_drv(lp))
-                       printk("\n" KERN_ERR PFX
+                       printk(KERN_ERR PFX
                               "%s: Memory allocation failed.\n", name);
                return -ENOMEM;
        }
@@ -2089,6 +2086,7 @@ static void pcnet32_free_ring(struct net_device *dev)
 static int pcnet32_open(struct net_device *dev)
 {
        struct pcnet32_private *lp = netdev_priv(dev);
+       struct pci_dev *pdev = lp->pci_dev;
        unsigned long ioaddr = dev->base_addr;
        u16 val;
        int i;
@@ -2149,9 +2147,9 @@ static int pcnet32_open(struct net_device *dev)
        lp->a.write_csr(ioaddr, 124, val);
 
        /* Allied Telesyn AT 2700/2701 FX are 100Mbit only and do not negotiate */
-       if (lp->pci_dev->subsystem_vendor == PCI_VENDOR_ID_AT &&
-           (lp->pci_dev->subsystem_device == PCI_SUBDEVICE_ID_AT_2700FX ||
-            lp->pci_dev->subsystem_device == PCI_SUBDEVICE_ID_AT_2701FX)) {
+       if (pdev && pdev->subsystem_vendor == PCI_VENDOR_ID_AT &&
+           (pdev->subsystem_device == PCI_SUBDEVICE_ID_AT_2700FX ||
+            pdev->subsystem_device == PCI_SUBDEVICE_ID_AT_2701FX)) {
                if (lp->options & PCNET32_PORT_ASEL) {
                        lp->options = PCNET32_PORT_FD | PCNET32_PORT_100;
                        if (netif_msg_link(lp))
index 33984b737233c8cb13d9d0dbf9a2e0d6d915601e..22cdd451fb822ca0e6f64d944e4fd8fa177da29c 100644 (file)
@@ -30,6 +30,7 @@
 
 #ifdef CONFIG_OF_GPIO
 #include <linux/of_gpio.h>
+#include <linux/of_mdio.h>
 #include <linux/of_platform.h>
 #endif
 
@@ -81,13 +82,12 @@ static struct mdiobb_ops mdio_gpio_ops = {
        .get_mdio_data = mdio_get,
 };
 
-static int __devinit mdio_gpio_bus_init(struct device *dev,
+static struct mii_bus * __devinit mdio_gpio_bus_init(struct device *dev,
                                        struct mdio_gpio_platform_data *pdata,
                                        int bus_id)
 {
        struct mii_bus *new_bus;
        struct mdio_gpio_info *bitbang;
-       int ret = -ENOMEM;
        int i;
 
        bitbang = kzalloc(sizeof(*bitbang), GFP_KERNEL);
@@ -104,8 +104,6 @@ static int __devinit mdio_gpio_bus_init(struct device *dev,
 
        new_bus->name = "GPIO Bitbanged MDIO",
 
-       ret = -ENODEV;
-
        new_bus->phy_mask = pdata->phy_mask;
        new_bus->irq = pdata->irqs;
        new_bus->parent = dev;
@@ -129,15 +127,8 @@ static int __devinit mdio_gpio_bus_init(struct device *dev,
 
        dev_set_drvdata(dev, new_bus);
 
-       ret = mdiobus_register(new_bus);
-       if (ret)
-               goto out_free_all;
-
-       return 0;
+       return new_bus;
 
-out_free_all:
-       dev_set_drvdata(dev, NULL);
-       gpio_free(bitbang->mdio);
 out_free_mdc:
        gpio_free(bitbang->mdc);
 out_free_bus:
@@ -145,30 +136,47 @@ out_free_bus:
 out_free_bitbang:
        kfree(bitbang);
 out:
-       return ret;
+       return NULL;
 }
 
-static void __devexit mdio_gpio_bus_destroy(struct device *dev)
+static void __devinit mdio_gpio_bus_deinit(struct device *dev)
 {
        struct mii_bus *bus = dev_get_drvdata(dev);
        struct mdio_gpio_info *bitbang = bus->priv;
 
-       mdiobus_unregister(bus);
-       free_mdio_bitbang(bus);
        dev_set_drvdata(dev, NULL);
-       gpio_free(bitbang->mdc);
        gpio_free(bitbang->mdio);
+       gpio_free(bitbang->mdc);
+       free_mdio_bitbang(bus);
        kfree(bitbang);
 }
 
+static void __devexit mdio_gpio_bus_destroy(struct device *dev)
+{
+       struct mii_bus *bus = dev_get_drvdata(dev);
+
+       mdiobus_unregister(bus);
+       mdio_gpio_bus_deinit(dev);
+}
+
 static int __devinit mdio_gpio_probe(struct platform_device *pdev)
 {
        struct mdio_gpio_platform_data *pdata = pdev->dev.platform_data;
+       struct mii_bus *new_bus;
+       int ret;
 
        if (!pdata)
                return -ENODEV;
 
-       return mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id);
+       new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id);
+       if (!new_bus)
+               return -ENODEV;
+
+       ret = mdiobus_register(new_bus);
+       if (ret)
+               mdio_gpio_bus_deinit(&pdev->dev);
+
+       return ret;
 }
 
 static int __devexit mdio_gpio_remove(struct platform_device *pdev)
@@ -179,29 +187,12 @@ static int __devexit mdio_gpio_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_OF_GPIO
-static void __devinit add_phy(struct mdio_gpio_platform_data *pdata,
-                             struct device_node *np)
-{
-       const u32 *data;
-       int len, id, irq;
-
-       data = of_get_property(np, "reg", &len);
-       if (!data || len != 4)
-               return;
-
-       id = *data;
-       pdata->phy_mask &= ~(1 << id);
-
-       irq = of_irq_to_resource(np, 0, NULL);
-       if (irq)
-               pdata->irqs[id] = irq;
-}
 
 static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
                                         const struct of_device_id *match)
 {
-       struct device_node *np = NULL;
        struct mdio_gpio_platform_data *pdata;
+       struct mii_bus *new_bus;
        int ret;
 
        pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
@@ -215,14 +206,18 @@ static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
 
        ret = of_get_gpio(ofdev->node, 1);
        if (ret < 0)
-                goto out_free;
+               goto out_free;
        pdata->mdio = ret;
 
-       while ((np = of_get_next_child(ofdev->node, np)))
-               if (!strcmp(np->type, "ethernet-phy"))
-                       add_phy(pdata, np);
+       new_bus = mdio_gpio_bus_init(&ofdev->dev, pdata, pdata->mdc);
+       if (!new_bus)
+               return -ENODEV;
 
-       return mdio_gpio_bus_init(&ofdev->dev, pdata, pdata->mdc);
+       ret = of_mdiobus_register(new_bus, ofdev->node);
+       if (ret)
+               mdio_gpio_bus_deinit(&ofdev->dev);
+
+       return ret;
 
 out_free:
        kfree(pdata);
index 61755cbd978e4aee3cfae9306395d80763abceef..eda94fcd4065a9391150c4ce27ff8c01553af2bf 100644 (file)
@@ -928,13 +928,32 @@ static void phy_state_machine(struct work_struct *work)
                                 * Otherwise, it's 0, and we're
                                 * still waiting for AN */
                                if (err > 0) {
-                                       phydev->state = PHY_RUNNING;
+                                       err = phy_read_status(phydev);
+                                       if (err)
+                                               break;
+
+                                       if (phydev->link) {
+                                               phydev->state = PHY_RUNNING;
+                                               netif_carrier_on(phydev->attached_dev);
+                                       } else
+                                               phydev->state = PHY_NOLINK;
+                                       phydev->adjust_link(phydev->attached_dev);
                                } else {
                                        phydev->state = PHY_AN;
                                        phydev->link_timeout = PHY_AN_TIMEOUT;
                                }
-                       } else
-                               phydev->state = PHY_RUNNING;
+                       } else {
+                               err = phy_read_status(phydev);
+                               if (err)
+                                       break;
+
+                               if (phydev->link) {
+                                       phydev->state = PHY_RUNNING;
+                                       netif_carrier_on(phydev->attached_dev);
+                               } else
+                                       phydev->state = PHY_NOLINK;
+                               phydev->adjust_link(phydev->attached_dev);
+                       }
                        break;
        }
 
index eba937c463767fd1e07ea2425db0a17165e263ab..b10fedd8214394b591bfb81bd102c8d38fce9fb1 100644 (file)
@@ -134,8 +134,10 @@ int phy_scan_fixups(struct phy_device *phydev)
 
                        err = fixup->run(phydev);
 
-                       if (err < 0)
+                       if (err < 0) {
+                               mutex_unlock(&phy_fixup_lock);
                                return err;
+                       }
                }
        }
        mutex_unlock(&phy_fixup_lock);
index 7a62f781fef2b83fdfe55dc0cad944cb5a2d7c8b..2ca8b0d84ee2d7f2647e3064e6f1615f116c1294 100644 (file)
@@ -270,6 +270,9 @@ static const struct net_device_ops plip_netdev_ops = {
        .ndo_stop                = plip_close,
        .ndo_start_xmit          = plip_tx_packet,
        .ndo_do_ioctl            = plip_ioctl,
+       .ndo_change_mtu          = eth_change_mtu,
+       .ndo_set_mac_address     = eth_mac_addr,
+       .ndo_validate_addr       = eth_validate_addr,
 };
 
 /* Entry point of PLIP driver.
index 17c116bb332c7e0c41da3f97aeb3ac3755097e87..6de8399d6dd92d26875cca679ec332c19082d736 100644 (file)
@@ -356,6 +356,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
        if (!skb_queue_empty(&ap->rqueue))
                tasklet_schedule(&ap->tsk);
        ap_put(ap);
+       tty_unthrottle(tty);
 }
 
 static void
index 639d11bc444e8a07a88c50beaddf9f867f126aee..cd37d739ac74b08a833907874cbeef4922c73080 100644 (file)
@@ -1384,7 +1384,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
 
        /* create a     fragment for each channel */
        bits = B;
-       while (nfree > 0 &&     len     > 0) {
+       while (len      > 0) {
                list = list->next;
                if (list ==     &ppp->channels) {
                        i =     0;
@@ -1431,29 +1431,31 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
                *otherwise divide it according to the speed
                *of the channel we are going to transmit on
                */
-               if (pch->speed == 0) {
-                       flen = totlen/nfree     ;
-                       if (nbigger > 0) {
-                               flen++;
-                               nbigger--;
-                       }
-               } else {
-                       flen = (((totfree - nzero)*(totlen + hdrlen*totfree)) /
-                               ((totspeed*totfree)/pch->speed)) - hdrlen;
-                       if (nbigger > 0) {
-                               flen += ((totfree - nzero)*pch->speed)/totspeed;
-                               nbigger -= ((totfree - nzero)*pch->speed)/
+               if (nfree > 0) {
+                       if (pch->speed == 0) {
+                               flen = totlen/nfree     ;
+                               if (nbigger > 0) {
+                                       flen++;
+                                       nbigger--;
+                               }
+                       } else {
+                               flen = (((totfree - nzero)*(totlen + hdrlen*totfree)) /
+                                       ((totspeed*totfree)/pch->speed)) - hdrlen;
+                               if (nbigger > 0) {
+                                       flen += ((totfree - nzero)*pch->speed)/totspeed;
+                                       nbigger -= ((totfree - nzero)*pch->speed)/
                                                        totspeed;
+                               }
                        }
+                       nfree--;
                }
-               nfree--;
 
                /*
                 *check if we are on the last channel or
                 *we exceded the lenght of the data     to
                 *fragment
                 */
-               if ((nfree == 0) || (flen > len))
+               if ((nfree <= 0) || (flen > len))
                        flen = len;
                /*
                 *it is not worth to tx on slow channels:
@@ -1467,7 +1469,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
                        continue;
                }
 
-               mtu     = pch->chan->mtu + 2 - hdrlen;
+               mtu     = pch->chan->mtu - hdrlen;
                if (mtu < 4)
                        mtu     = 4;
                if (flen > mtu)
index aa3d39f38e2257deee5e72e9df06453be96e3046..d2fa2db1358633771439013546758654444c6a00 100644 (file)
@@ -397,6 +397,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
        if (!skb_queue_empty(&ap->rqueue))
                tasklet_schedule(&ap->tsk);
        sp_put(ap);
+       tty_unthrottle(tty);
 }
 
 static void
index f0031f1f97e5e1b7bd52d825021fa3783c93885a..5f2090233d7bd8ba3eb6a82fa8613db0f29f6348 100644 (file)
@@ -1063,6 +1063,7 @@ static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        else {
                int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
 
+               po = NULL;
                while (++hash < PPPOE_HASH_SIZE) {
                        po = pn->hash_table[hash];
                        if (po)
index e7935d09c896786083606cc23d962a6504aed9a5..e0f9219a0aea8b60927d3ec0ef6861d8b1880261 100644 (file)
@@ -2680,6 +2680,7 @@ out_unregister_pppol2tp_proto:
 static void __exit pppol2tp_exit(void)
 {
        unregister_pppox_proto(PX_PROTO_OL2TP);
+       unregister_pernet_gen_device(pppol2tp_net_id, &pppol2tp_net_ops);
        proto_unregister(&pppol2tp_sk_proto);
 }
 
index d1a5fb4d6acb1e63e479abea8db9a1e1f4a3e5f7..a3932c9f3406c9d4e75967fc392d759cffb78330 100644 (file)
@@ -1411,6 +1411,7 @@ static const struct net_device_ops gelic_netdevice_ops = {
        .ndo_set_multicast_list = gelic_net_set_multi,
        .ndo_change_mtu = gelic_net_change_mtu,
        .ndo_tx_timeout = gelic_net_tx_timeout,
+       .ndo_set_mac_address = eth_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = gelic_net_poll_controller,
index b6b3ca9bdb213a9fa995b35cda8cc72f0cf480d2..6932b08d746b38b1c830d3ea3f720496562e9129 100644 (file)
@@ -2707,6 +2707,7 @@ static const struct net_device_ops gelic_wl_netdevice_ops = {
        .ndo_set_multicast_list = gelic_net_set_multi,
        .ndo_change_mtu = gelic_net_change_mtu,
        .ndo_tx_timeout = gelic_net_tx_timeout,
+       .ndo_set_mac_address = eth_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = gelic_net_poll_controller,
index 156e02e8905ddc0b3ddc00bbdef4110bdb6ad165..6ed5317ab1c09a11d6d71eb05c7046f19cfe9bad 100644 (file)
@@ -1607,6 +1607,8 @@ int ql_mb_get_fw_state(struct ql_adapter *qdev);
 int ql_cam_route_initialize(struct ql_adapter *qdev);
 int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data);
 int ql_mb_about_fw(struct ql_adapter *qdev);
+void ql_link_on(struct ql_adapter *qdev);
+void ql_link_off(struct ql_adapter *qdev);
 
 #if 1
 #define QL_ALL_DUMP
index 37c99fe79770fc78de8c6a9cec9c15a743f50bef..eb6a9ee640ed9fdb2711d4244732ba17fca136e3 100644 (file)
@@ -59,7 +59,7 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev)
                        cqicb->pkt_delay =
                            cpu_to_le16(qdev->tx_max_coalesced_frames);
                        cqicb->flags = FLAGS_LI;
-                       status = ql_write_cfg(qdev, cqicb, sizeof(cqicb),
+                       status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb),
                                                CFG_LCQ, rx_ring->cq_id);
                        if (status) {
                                QPRINTK(qdev, IFUP, ERR,
@@ -82,7 +82,7 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev)
                        cqicb->pkt_delay =
                            cpu_to_le16(qdev->rx_max_coalesced_frames);
                        cqicb->flags = FLAGS_LI;
-                       status = ql_write_cfg(qdev, cqicb, sizeof(cqicb),
+                       status = ql_write_cfg(qdev, cqicb, sizeof(*cqicb),
                                                CFG_LCQ, rx_ring->cq_id);
                        if (status) {
                                QPRINTK(qdev, IFUP, ERR,
index 90d1f76c0e8b074729047d5d7aed9440b8d8315f..5768af17f168b668a28e55bc65460a82cd87ef03 100644 (file)
@@ -214,6 +214,10 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit,
                return -ENOMEM;
        }
 
+       status = ql_sem_spinlock(qdev, SEM_ICB_MASK);
+       if (status)
+               return status;
+
        status = ql_wait_cfg(qdev, bit);
        if (status) {
                QPRINTK(qdev, IFUP, ERR,
@@ -221,12 +225,8 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit,
                goto exit;
        }
 
-       status = ql_sem_spinlock(qdev, SEM_ICB_MASK);
-       if (status)
-               goto exit;
        ql_write32(qdev, ICB_L, (u32) map);
        ql_write32(qdev, ICB_H, (u32) (map >> 32));
-       ql_sem_unlock(qdev, SEM_ICB_MASK);      /* does flush too */
 
        mask = CFG_Q_MASK | (bit << 16);
        value = bit | (q_id << CFG_Q_SHIFT);
@@ -237,6 +237,7 @@ int ql_write_cfg(struct ql_adapter *qdev, void *ptr, int size, u32 bit,
         */
        status = ql_wait_cfg(qdev, bit);
 exit:
+       ql_sem_unlock(qdev, SEM_ICB_MASK);      /* does flush too */
        pci_unmap_single(qdev->pdev, map, size, direction);
        return status;
 }
@@ -412,6 +413,57 @@ exit:
        return status;
 }
 
+/* Set or clear MAC address in hardware. We sometimes
+ * have to clear it to prevent wrong frame routing
+ * especially in a bonding environment.
+ */
+static int ql_set_mac_addr(struct ql_adapter *qdev, int set)
+{
+       int status;
+       char zero_mac_addr[ETH_ALEN];
+       char *addr;
+
+       if (set) {
+               addr = &qdev->ndev->dev_addr[0];
+               QPRINTK(qdev, IFUP, DEBUG,
+                       "Set Mac addr %02x:%02x:%02x:%02x:%02x:%02x\n",
+                       addr[0], addr[1], addr[2], addr[3],
+                       addr[4], addr[5]);
+       } else {
+               memset(zero_mac_addr, 0, ETH_ALEN);
+               addr = &zero_mac_addr[0];
+               QPRINTK(qdev, IFUP, DEBUG,
+                               "Clearing MAC address on %s\n",
+                               qdev->ndev->name);
+       }
+       status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
+       if (status)
+               return status;
+       status = ql_set_mac_addr_reg(qdev, (u8 *) addr,
+                       MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ);
+       ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
+       if (status)
+               QPRINTK(qdev, IFUP, ERR, "Failed to init mac "
+                       "address.\n");
+       return status;
+}
+
+void ql_link_on(struct ql_adapter *qdev)
+{
+       QPRINTK(qdev, LINK, ERR, "%s: Link is up.\n",
+                                qdev->ndev->name);
+       netif_carrier_on(qdev->ndev);
+       ql_set_mac_addr(qdev, 1);
+}
+
+void ql_link_off(struct ql_adapter *qdev)
+{
+       QPRINTK(qdev, LINK, ERR, "%s: Link is down.\n",
+                                qdev->ndev->name);
+       netif_carrier_off(qdev->ndev);
+       ql_set_mac_addr(qdev, 0);
+}
+
 /* Get a specific frame routing value from the CAM.
  * Used for debug and reg dump.
  */
@@ -1628,7 +1680,7 @@ static void ql_process_mac_tx_intr(struct ql_adapter *qdev,
        tx_ring = &qdev->tx_ring[mac_rsp->txq_idx];
        tx_ring_desc = &tx_ring->q[mac_rsp->tid];
        ql_unmap_send(qdev, tx_ring_desc, tx_ring_desc->map_cnt);
-       qdev->stats.tx_bytes += tx_ring_desc->map_cnt;
+       qdev->stats.tx_bytes += (tx_ring_desc->skb)->len;
        qdev->stats.tx_packets++;
        dev_kfree_skb(tx_ring_desc->skb);
        tx_ring_desc->skb = NULL;
@@ -1660,13 +1712,13 @@ static void ql_process_mac_tx_intr(struct ql_adapter *qdev,
 /* Fire up a handler to reset the MPI processor. */
 void ql_queue_fw_error(struct ql_adapter *qdev)
 {
-       netif_carrier_off(qdev->ndev);
+       ql_link_off(qdev);
        queue_delayed_work(qdev->workqueue, &qdev->mpi_reset_work, 0);
 }
 
 void ql_queue_asic_error(struct ql_adapter *qdev)
 {
-       netif_carrier_off(qdev->ndev);
+       ql_link_off(qdev);
        ql_disable_interrupts(qdev);
        /* Clear adapter up bit to signal the recovery
         * process that it shouldn't kill the reset worker
@@ -2104,7 +2156,7 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev)
        }
        tx_ring_desc = &tx_ring->q[tx_ring->prod_idx];
        mac_iocb_ptr = tx_ring_desc->queue_entry;
-       memset((void *)mac_iocb_ptr, 0, sizeof(mac_iocb_ptr));
+       memset((void *)mac_iocb_ptr, 0, sizeof(*mac_iocb_ptr));
 
        mac_iocb_ptr->opcode = OPCODE_OB_MAC_IOCB;
        mac_iocb_ptr->tid = tx_ring_desc->index;
@@ -2743,7 +2795,7 @@ static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring)
 
        ql_init_tx_ring(qdev, tx_ring);
 
-       err = ql_write_cfg(qdev, wqicb, sizeof(wqicb), CFG_LRQ,
+       err = ql_write_cfg(qdev, wqicb, sizeof(*wqicb), CFG_LRQ,
                           (u16) tx_ring->wq_id);
        if (err) {
                QPRINTK(qdev, IFUP, ERR, "Failed to load tx_ring.\n");
@@ -3008,7 +3060,7 @@ static int ql_start_rss(struct ql_adapter *qdev)
        int i;
        u8 *hash_id = (u8 *) ricb->hash_cq_id;
 
-       memset((void *)ricb, 0, sizeof(ricb));
+       memset((void *)ricb, 0, sizeof(*ricb));
 
        ricb->base_cq = qdev->rss_ring_first_cq_id | RSS_L4K;
        ricb->flags =
@@ -3030,7 +3082,7 @@ static int ql_start_rss(struct ql_adapter *qdev)
 
        QPRINTK(qdev, IFUP, DEBUG, "Initializing RSS.\n");
 
-       status = ql_write_cfg(qdev, ricb, sizeof(ricb), CFG_LR, 0);
+       status = ql_write_cfg(qdev, ricb, sizeof(*ricb), CFG_LR, 0);
        if (status) {
                QPRINTK(qdev, IFUP, ERR, "Failed to load RICB.\n");
                return status;
@@ -3039,25 +3091,40 @@ static int ql_start_rss(struct ql_adapter *qdev)
        return status;
 }
 
-/* Initialize the frame-to-queue routing. */
-static int ql_route_initialize(struct ql_adapter *qdev)
+static int ql_clear_routing_entries(struct ql_adapter *qdev)
 {
-       int status = 0;
-       int i;
+       int i, status = 0;
 
        status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK);
        if (status)
                return status;
-
        /* Clear all the entries in the routing table. */
        for (i = 0; i < 16; i++) {
                status = ql_set_routing_reg(qdev, i, 0, 0);
                if (status) {
                        QPRINTK(qdev, IFUP, ERR,
-                               "Failed to init routing register for CAM packets.\n");
-                       goto exit;
+                               "Failed to init routing register for CAM "
+                               "packets.\n");
+                       break;
                }
        }
+       ql_sem_unlock(qdev, SEM_RT_IDX_MASK);
+       return status;
+}
+
+/* Initialize the frame-to-queue routing. */
+static int ql_route_initialize(struct ql_adapter *qdev)
+{
+       int status = 0;
+
+       status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK);
+       if (status)
+               return status;
+
+       /* Clear all the entries in the routing table. */
+       status = ql_clear_routing_entries(qdev);
+       if (status)
+               goto exit;
 
        status = ql_set_routing_reg(qdev, RT_IDX_ALL_ERR_SLOT, RT_IDX_ERR, 1);
        if (status) {
@@ -3096,14 +3163,15 @@ exit:
 
 int ql_cam_route_initialize(struct ql_adapter *qdev)
 {
-       int status;
+       int status, set;
 
-       status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
-       if (status)
-               return status;
-       status = ql_set_mac_addr_reg(qdev, (u8 *) qdev->ndev->perm_addr,
-                            MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ);
-       ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
+       /* If check if the link is up and use to
+        * determine if we are setting or clearing
+        * the MAC address in the CAM.
+        */
+       set = ql_read32(qdev, STS);
+       set &= qdev->port_link_up;
+       status = ql_set_mac_addr(qdev, set);
        if (status) {
                QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n");
                return status;
@@ -3210,9 +3278,17 @@ static int ql_adapter_reset(struct ql_adapter *qdev)
 {
        u32 value;
        int status = 0;
-       unsigned long end_jiffies = jiffies +
-               max((unsigned long)1, usecs_to_jiffies(30));
+       unsigned long end_jiffies;
 
+       /* Clear all the entries in the routing table. */
+       status = ql_clear_routing_entries(qdev);
+       if (status) {
+               QPRINTK(qdev, IFUP, ERR, "Failed to clear routing bits.\n");
+               return status;
+       }
+
+       end_jiffies = jiffies +
+               max((unsigned long)1, usecs_to_jiffies(30));
        ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR);
 
        do {
@@ -3252,7 +3328,7 @@ static int ql_adapter_down(struct ql_adapter *qdev)
        int i, status = 0;
        struct rx_ring *rx_ring;
 
-       netif_carrier_off(qdev->ndev);
+       ql_link_off(qdev);
 
        /* Don't kill the reset worker thread if we
         * are in the process of recovery.
@@ -3319,8 +3395,12 @@ static int ql_adapter_up(struct ql_adapter *qdev)
        }
        set_bit(QL_ADAPTER_UP, &qdev->flags);
        ql_alloc_rx_buffers(qdev);
-       if ((ql_read32(qdev, STS) & qdev->port_init))
-               netif_carrier_on(qdev->ndev);
+       /* If the port is initialized and the
+        * link is up the turn on the carrier.
+        */
+       if ((ql_read32(qdev, STS) & qdev->port_init) &&
+                       (ql_read32(qdev, STS) & qdev->port_link_up))
+               ql_link_on(qdev);
        ql_enable_interrupts(qdev);
        ql_enable_all_completion_interrupts(qdev);
        netif_tx_start_all_queues(qdev->ndev);
@@ -3346,11 +3426,6 @@ static int ql_get_adapter_resources(struct ql_adapter *qdev)
                return -ENOMEM;
        }
        status = ql_request_irq(qdev);
-       if (status)
-               goto err_irq;
-       return status;
-err_irq:
-       ql_free_mem_resources(qdev);
        return status;
 }
 
@@ -3414,7 +3489,7 @@ static int ql_configure_rings(struct ql_adapter *qdev)
 
        for (i = 0; i < qdev->tx_ring_count; i++) {
                tx_ring = &qdev->tx_ring[i];
-               memset((void *)tx_ring, 0, sizeof(tx_ring));
+               memset((void *)tx_ring, 0, sizeof(*tx_ring));
                tx_ring->qdev = qdev;
                tx_ring->wq_id = i;
                tx_ring->wq_len = qdev->tx_ring_size;
@@ -3430,7 +3505,7 @@ static int ql_configure_rings(struct ql_adapter *qdev)
 
        for (i = 0; i < qdev->rx_ring_count; i++) {
                rx_ring = &qdev->rx_ring[i];
-               memset((void *)rx_ring, 0, sizeof(rx_ring));
+               memset((void *)rx_ring, 0, sizeof(*rx_ring));
                rx_ring->qdev = qdev;
                rx_ring->cq_id = i;
                rx_ring->cpu = i % cpu_cnt;     /* CPU to run handler on. */
@@ -3789,7 +3864,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
        int pos, err = 0;
        u16 val16;
 
-       memset((void *)qdev, 0, sizeof(qdev));
+       memset((void *)qdev, 0, sizeof(*qdev));
        err = pci_enable_device(pdev);
        if (err) {
                dev_err(&pdev->dev, "PCI device enable failed.\n");
@@ -3976,7 +4051,7 @@ static int __devinit qlge_probe(struct pci_dev *pdev,
                pci_disable_device(pdev);
                return err;
        }
-       netif_carrier_off(ndev);
+       ql_link_off(qdev);
        ql_display_dev_info(ndev);
        cards_found++;
        return 0;
index 71afbf8b9c50c23d9c36acbc788dcda20d7e5336..6685bd97da91f211452743dd7cfd9c5ae77996a3 100644 (file)
@@ -238,7 +238,7 @@ static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp)
                                &qdev->mpi_port_cfg_work, 0);
        }
 
-       netif_carrier_on(qdev->ndev);
+       ql_link_on(qdev);
 }
 
 static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp)
@@ -251,7 +251,7 @@ static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp)
        if (status)
                QPRINTK(qdev, DRV, ERR, "Link down AEN broken!\n");
 
-       netif_carrier_off(qdev->ndev);
+       ql_link_off(qdev);
 }
 
 static int ql_sfp_in(struct ql_adapter *qdev, struct mbox_params *mbcp)
@@ -849,7 +849,7 @@ void ql_mpi_idc_work(struct work_struct *work)
        case MB_CMD_PORT_RESET:
        case MB_CMD_SET_PORT_CFG:
        case MB_CMD_STOP_FW:
-               netif_carrier_off(qdev->ndev);
+               ql_link_off(qdev);
                /* Signal the resulting link up AEN
                 * that the frame routing and mac addr
                 * needs to be set.
index ed63d23a645233f9da9a6e88abb51632fdf5f98d..961b5397a531ea3800ccf43ac4f9b12a7e6849c2 100644 (file)
@@ -49,8 +49,8 @@
 #include <asm/processor.h>
 
 #define DRV_NAME       "r6040"
-#define DRV_VERSION    "0.23"
-#define DRV_RELDATE    "05May2009"
+#define DRV_VERSION    "0.24"
+#define DRV_RELDATE    "08Jul2009"
 
 /* PHY CHIP Address */
 #define PHY1_ADDR      1       /* For MAC1 */
@@ -704,8 +704,11 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id)
        /* Read MISR status and clear */
        status = ioread16(ioaddr + MISR);
 
-       if (status == 0x0000 || status == 0xffff)
+       if (status == 0x0000 || status == 0xffff) {
+               /* Restore RDC MAC interrupt */
+               iowrite16(misr, ioaddr + MIER);
                return IRQ_NONE;
+       }
 
        /* RX interrupt request */
        if (status & RX_INTS) {
index 4b53b58d75fc0375e03579e79c9dbb5adf808056..b82780d805f544c50b341ed1f34f07f41e400c99 100644 (file)
@@ -2060,8 +2060,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                }
        }
 
-       pci_set_master(pdev);
-
        /* ioremap MMIO region */
        ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE);
        if (!ioaddr) {
@@ -2089,6 +2087,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        RTL_W16(IntrStatus, 0xffff);
 
+       pci_set_master(pdev);
+
        /* Identify chip attached to board */
        rtl8169_get_mac_version(tp, ioaddr);
 
@@ -3874,6 +3874,15 @@ static void rtl_shutdown(struct pci_dev *pdev)
        spin_unlock_irq(&tp->lock);
 
        if (system_state == SYSTEM_POWER_OFF) {
+               /* WoL fails with some 8168 when the receiver is disabled. */
+               if (tp->features & RTL_FEATURE_WOL) {
+                       pci_clear_master(pdev);
+
+                       RTL_W8(ChipCmd, CmdRxEnb);
+                       /* PCI commit */
+                       RTL_R8(ChipCmd);
+               }
+
                pci_wake_from_d3(pdev, true);
                pci_set_power_state(pdev, PCI_D3hot);
        }
index 5345e47b35ac9c19ea11198810b442af6f5ecae8..4525cbe8dd69c0dd2585568eb28555b6ff2205b9 100644 (file)
@@ -793,7 +793,7 @@ static inline int s6gmac_phy_start(struct net_device *dev)
        struct s6gmac *pd = netdev_priv(dev);
        int i = 0;
        struct phy_device *p = NULL;
-       while ((!(p = pd->mii.bus->phy_map[i])) && (i < PHY_MAX_ADDR))
+       while ((i < PHY_MAX_ADDR) && (!(p = pd->mii.bus->phy_map[i])))
                i++;
        p = phy_connect(dev, dev_name(&p->dev), &s6gmac_adjust_link, 0,
                        PHY_INTERFACE_MODE_RGMII);
index 18821f217e19fa286a732973cfc917463638e672..e3156c97bb58b5a163a5c8f6531cbf8b842a4201 100644 (file)
@@ -1593,6 +1593,7 @@ out:
 static struct pci_device_id sc92031_pci_device_id_table[] __devinitdata = {
        { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x2031) },
        { PCI_DEVICE(PCI_VENDOR_ID_SILAN, 0x8139) },
+       { PCI_DEVICE(0x1088, 0x2031) },
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, sc92031_pci_device_id_table);
index 341882f959f3c9eb12de2cb5afa4b422062c5636..a2d82ddb3b4d790bc70c1ec4a87ed873eef3d8b1 100644 (file)
@@ -865,8 +865,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
        struct sh_eth_private *mdp = netdev_priv(ndev);
        struct sh_eth_cpu_data *cd = mdp->cd;
        irqreturn_t ret = IRQ_NONE;
-       u32 ioaddr, boguscnt = RX_RING_SIZE;
-       u32 intr_status = 0;
+       u32 ioaddr, intr_status = 0;
 
        ioaddr = ndev->base_addr;
        spin_lock(&mdp->lock);
@@ -901,12 +900,6 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
        if (intr_status & cd->eesr_err_check)
                sh_eth_error(ndev, intr_status);
 
-       if (--boguscnt < 0) {
-               printk(KERN_WARNING
-                      "%s: Too much work at interrupt, status=0x%4.4x.\n",
-                      ndev->name, intr_status);
-       }
-
 other_irq:
        spin_unlock(&mdp->lock);
 
index 60d502eef4fc36868d6fac2099f14ec852855497..543af2044f40df39eea68d5eef6608dc1847613a 100644 (file)
@@ -3854,8 +3854,10 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
        skge->speed = -1;
        skge->advertising = skge_supported_modes(hw);
 
-       if (device_may_wakeup(&hw->pdev->dev))
+       if (device_can_wakeup(&hw->pdev->dev)) {
                skge->wol = wol_supported(hw) & WAKE_MAGIC;
+               device_set_wakeup_enable(&hw->pdev->dev, skge->wol);
+       }
 
        hw->dev[port] = dev;
 
index 7681d28c53d7778a15c1795e786aaf72d875b79a..0a551d8f5d956d2879643092f41a81c4a77ee3d3 100644 (file)
@@ -1151,14 +1151,7 @@ stopped:
 
        /* reset the Rx prefetch unit */
        sky2_write32(hw, Y2_QADDR(rxq, PREF_UNIT_CTRL), PREF_UNIT_RST_SET);
-
-       /* Reset the RAM Buffer receive queue */
-       sky2_write8(hw, RB_ADDR(rxq, RB_CTRL), RB_RST_SET);
-
-       /* Reset Rx MAC FIFO */
-       sky2_write8(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), GMF_RST_SET);
-
-       sky2_read8(hw, B0_CTST);
+       mmiowb();
 }
 
 /* Clean out receive buffer area, assumes receiver hardware stopped */
@@ -1495,6 +1488,8 @@ static int sky2_up(struct net_device *dev)
        sky2_set_vlan_mode(hw, port, sky2->vlgrp != NULL);
 #endif
 
+       sky2->restarting = 0;
+
        err = sky2_rx_start(sky2);
        if (err)
                goto err_out;
@@ -1507,6 +1502,9 @@ static int sky2_up(struct net_device *dev)
 
        sky2_set_multicast(dev);
 
+       /* wake queue incase we are restarting */
+       netif_wake_queue(dev);
+
        if (netif_msg_ifup(sky2))
                printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
        return 0;
@@ -1540,6 +1538,8 @@ static inline int tx_dist(unsigned tail, unsigned head)
 /* Number of list elements available for next tx */
 static inline int tx_avail(const struct sky2_port *sky2)
 {
+       if (unlikely(sky2->restarting))
+               return 0;
        return sky2->tx_pending - tx_dist(sky2->tx_cons, sky2->tx_prod);
 }
 
@@ -1825,11 +1825,9 @@ static int sky2_down(struct net_device *dev)
        if (netif_msg_ifdown(sky2))
                printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
 
-       /* Disable port IRQ */
-       imask = sky2_read32(hw, B0_IMSK);
-       imask &= ~portirq_msk[port];
-       sky2_write32(hw, B0_IMSK, imask);
-       sky2_read32(hw, B0_IMSK);
+       /* explicitly shut off tx incase we're restarting */
+       sky2->restarting = 1;
+       netif_tx_disable(dev);
 
        /* Force flow control off */
        sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
@@ -1870,8 +1868,6 @@ static int sky2_down(struct net_device *dev)
 
        sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET);
 
-       sky2_rx_stop(sky2);
-
        sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
        sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
 
@@ -1881,6 +1877,14 @@ static int sky2_down(struct net_device *dev)
        sky2_write32(hw, STAT_ISR_TIMER_CNT, 0);
        sky2_read8(hw, STAT_ISR_TIMER_CTRL);
 
+       sky2_rx_stop(sky2);
+
+       /* Disable port IRQ */
+       imask = sky2_read32(hw, B0_IMSK);
+       imask &= ~portirq_msk[port];
+       sky2_write32(hw, B0_IMSK, imask);
+       sky2_read32(hw, B0_IMSK);
+
        synchronize_irq(hw->pdev->irq);
        napi_synchronize(&hw->napi);
 
@@ -2366,7 +2370,7 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
 {
        struct sky2_port *sky2 = netdev_priv(dev);
 
-       if (netif_running(dev)) {
+       if (likely(netif_running(dev) && !sky2->restarting)) {
                netif_tx_lock(dev);
                sky2_tx_complete(sky2, last);
                netif_tx_unlock(dev);
@@ -2495,7 +2499,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
                        if (likely(status >> 16 == (status & 0xffff))) {
                                skb = sky2->rx_ring[sky2->rx_next].skb;
                                skb->ip_summed = CHECKSUM_COMPLETE;
-                               skb->csum = status & 0xffff;
+                               skb->csum = le16_to_cpu(status);
                        } else {
                                printk(KERN_NOTICE PFX "%s: hardware receive "
                                       "checksum problem (status = %#x)\n",
@@ -4290,6 +4294,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
        spin_lock_init(&sky2->phy_lock);
        sky2->tx_pending = TX_DEF_PENDING;
        sky2->rx_pending = RX_DEF_PENDING;
+       sky2->restarting = 0;
 
        hw->dev[port] = dev;
 
index b5549c9e5107e317bee3ca3914ad4851f5deb816..4486b066b43f5531f4c3abba31e04a50f7607534 100644 (file)
@@ -2051,6 +2051,7 @@ struct sky2_port {
        u8                   duplex;    /* DUPLEX_HALF, DUPLEX_FULL */
        u8                   rx_csum;
        u8                   wol;
+       u8                   restarting;
        enum flow_control    flow_mode;
        enum flow_control    flow_status;
 
index fdcbaf8dfa739618a5a8f25bc27f6c24222e8004..7567f510eff5c3f200c0d48a12238ac2bd39666a 100644 (file)
@@ -196,21 +196,23 @@ static void PRINT_PKT(u_char *buf, int length)
 /* this enables an interrupt in the interrupt mask register */
 #define SMC_ENABLE_INT(lp, x) do {                                     \
        unsigned char mask;                                             \
-       spin_lock_irq(&lp->lock);                                       \
+       unsigned long smc_enable_flags;                                 \
+       spin_lock_irqsave(&lp->lock, smc_enable_flags);                 \
        mask = SMC_GET_INT_MASK(lp);                                    \
        mask |= (x);                                                    \
        SMC_SET_INT_MASK(lp, mask);                                     \
-       spin_unlock_irq(&lp->lock);                                     \
+       spin_unlock_irqrestore(&lp->lock, smc_enable_flags);            \
 } while (0)
 
 /* this disables an interrupt from the interrupt mask register */
 #define SMC_DISABLE_INT(lp, x) do {                                    \
        unsigned char mask;                                             \
-       spin_lock_irq(&lp->lock);                                       \
+       unsigned long smc_disable_flags;                                \
+       spin_lock_irqsave(&lp->lock, smc_disable_flags);                \
        mask = SMC_GET_INT_MASK(lp);                                    \
        mask &= ~(x);                                                   \
        SMC_SET_INT_MASK(lp, mask);                                     \
-       spin_unlock_irq(&lp->lock);                                     \
+       spin_unlock_irqrestore(&lp->lock, smc_disable_flags);           \
 } while (0)
 
 /*
@@ -520,21 +522,21 @@ static inline void  smc_rcv(struct net_device *dev)
  * any other concurrent access and C would always interrupt B. But life
  * isn't that easy in a SMP world...
  */
-#define smc_special_trylock(lock)                                      \
+#define smc_special_trylock(lock, flags)                               \
 ({                                                                     \
        int __ret;                                                      \
-       local_irq_disable();                                            \
+       local_irq_save(flags);                                          \
        __ret = spin_trylock(lock);                                     \
        if (!__ret)                                                     \
-               local_irq_enable();                                     \
+               local_irq_restore(flags);                               \
        __ret;                                                          \
 })
-#define smc_special_lock(lock)         spin_lock_irq(lock)
-#define smc_special_unlock(lock)       spin_unlock_irq(lock)
+#define smc_special_lock(lock, flags)          spin_lock_irqsave(lock, flags)
+#define smc_special_unlock(lock, flags)        spin_unlock_irqrestore(lock, flags)
 #else
-#define smc_special_trylock(lock)      (1)
-#define smc_special_lock(lock)         do { } while (0)
-#define smc_special_unlock(lock)       do { } while (0)
+#define smc_special_trylock(lock, flags)       (1)
+#define smc_special_lock(lock, flags)          do { } while (0)
+#define smc_special_unlock(lock, flags)        do { } while (0)
 #endif
 
 /*
@@ -548,10 +550,11 @@ static void smc_hardware_send_pkt(unsigned long data)
        struct sk_buff *skb;
        unsigned int packet_no, len;
        unsigned char *buf;
+       unsigned long flags;
 
        DBG(3, "%s: %s\n", dev->name, __func__);
 
-       if (!smc_special_trylock(&lp->lock)) {
+       if (!smc_special_trylock(&lp->lock, flags)) {
                netif_stop_queue(dev);
                tasklet_schedule(&lp->tx_task);
                return;
@@ -559,7 +562,7 @@ static void smc_hardware_send_pkt(unsigned long data)
 
        skb = lp->pending_tx_skb;
        if (unlikely(!skb)) {
-               smc_special_unlock(&lp->lock);
+               smc_special_unlock(&lp->lock, flags);
                return;
        }
        lp->pending_tx_skb = NULL;
@@ -569,7 +572,7 @@ static void smc_hardware_send_pkt(unsigned long data)
                printk("%s: Memory allocation failed.\n", dev->name);
                dev->stats.tx_errors++;
                dev->stats.tx_fifo_errors++;
-               smc_special_unlock(&lp->lock);
+               smc_special_unlock(&lp->lock, flags);
                goto done;
        }
 
@@ -608,7 +611,7 @@ static void smc_hardware_send_pkt(unsigned long data)
 
        /* queue the packet for TX */
        SMC_SET_MMU_CMD(lp, MC_ENQUEUE);
-       smc_special_unlock(&lp->lock);
+       smc_special_unlock(&lp->lock, flags);
 
        dev->trans_start = jiffies;
        dev->stats.tx_packets++;
@@ -633,6 +636,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct smc_local *lp = netdev_priv(dev);
        void __iomem *ioaddr = lp->base;
        unsigned int numPages, poll_count, status;
+       unsigned long flags;
 
        DBG(3, "%s: %s\n", dev->name, __func__);
 
@@ -658,7 +662,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
                return 0;
        }
 
-       smc_special_lock(&lp->lock);
+       smc_special_lock(&lp->lock, flags);
 
        /* now, try to allocate the memory */
        SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages);
@@ -676,7 +680,7 @@ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
                }
        } while (--poll_count);
 
-       smc_special_unlock(&lp->lock);
+       smc_special_unlock(&lp->lock, flags);
 
        lp->pending_tx_skb = skb;
        if (!poll_count) {
@@ -1774,6 +1778,7 @@ static const struct net_device_ops smc_netdev_ops = {
        .ndo_start_xmit         = smc_hard_start_xmit,
        .ndo_tx_timeout         = smc_timeout,
        .ndo_set_multicast_list = smc_set_multicast_list,
+       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
index f1f773b17fe121fc09f68eb84325a01b304bd87f..57a159fac99fcc1308ae106e06aadb7602bfe496 100644 (file)
@@ -186,7 +186,8 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define SMC_outsb(a, r, p, l)  writesb((a) + (r), p, (l))
 #define SMC_IRQ_FLAGS          (-1)    /* from resource */
 
-#elif  defined(CONFIG_MACH_LOGICPD_PXA270)
+#elif  defined(CONFIG_MACH_LOGICPD_PXA270) \
+       || defined(CONFIG_MACH_NOMADIK_8815NHK)
 
 #define SMC_CAN_USE_8BIT       0
 #define SMC_CAN_USE_16BIT      1
index b60639bd181b998738185a5d6ceaa1f6059339ad..94b6d2658ddc016cea883126e276bbf4c0c936bf 100644 (file)
@@ -1779,6 +1779,7 @@ static const struct net_device_ops smsc911x_netdev_ops = {
        .ndo_get_stats          = smsc911x_get_stats,
        .ndo_set_multicast_list = smsc911x_set_multicast_list,
        .ndo_do_ioctl           = smsc911x_do_ioctl,
+       .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = smsc911x_set_mac_address,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1938,7 +1939,7 @@ static int __devexit smsc911x_drv_remove(struct platform_device *pdev)
        if (!res)
                res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-       release_mem_region(res->start, res->end - res->start);
+       release_mem_region(res->start, resource_size(res));
 
        iounmap(pdata->ioaddr);
 
@@ -1976,7 +1977,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
                retval = -ENODEV;
                goto out_0;
        }
-       res_size = res->end - res->start + 1;
+       res_size = resource_size(res);
 
        irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!irq_res) {
@@ -2104,7 +2105,7 @@ out_unmap_io_3:
 out_free_netdev_2:
        free_netdev(dev);
 out_release_io_1:
-       release_mem_region(res->start, res->end - res->start);
+       release_mem_region(res->start, resource_size(res));
 out_0:
        return retval;
 }
index 838cce8b8fff3969286408536ad92b06f36e6063..669253c7bd41f871800f4a50c1886cbf9efae007 100644 (file)
@@ -180,7 +180,7 @@ static int full_duplex[MAX_UNITS] = {0, };
 /* These identify the driver base version and may not be removed. */
 static const char version[] __devinitconst =
 KERN_INFO "starfire.c:v1.03 7/26/2000  Written by Donald Becker <becker@scyld.com>\n"
-KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
+" (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
index 545f81b34ad7ee7ba8e055e90135437e98bdc87b..d1521c3875b2d6dd41ca81fc152cdfc841762368 100644 (file)
@@ -1698,13 +1698,13 @@ static int netdev_close(struct net_device *dev)
 
 #ifdef __i386__
        if (netif_msg_hw(np)) {
-               printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n",
+               printk(KERN_DEBUG "  Tx ring at %8.8x:\n",
                           (int)(np->tx_ring_dma));
                for (i = 0; i < TX_RING_SIZE; i++)
-                       printk(" #%d desc. %4.4x %8.8x %8.8x.\n",
+                       printk(KERN_DEBUG " #%d desc. %4.4x %8.8x %8.8x.\n",
                                   i, np->tx_ring[i].status, np->tx_ring[i].frag[0].addr,
                                   np->tx_ring[i].frag[0].length);
-               printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n",
+               printk(KERN_DEBUG "  Rx ring %8.8x:\n",
                           (int)(np->rx_ring_dma));
                for (i = 0; i < /*RX_RING_SIZE*/4 ; i++) {
                        printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n",
index a82fb2aca4cb7d89fe52e8bb31dfe4b6eacac505..f1e5e4542c2a04084b419c990e67760e05253f82 100644 (file)
@@ -1016,7 +1016,9 @@ static const struct net_device_ops vnet_ops = {
        .ndo_open               = vnet_open,
        .ndo_stop               = vnet_close,
        .ndo_set_multicast_list = vnet_set_rx_mode,
+       .ndo_change_mtu         = eth_change_mtu,
        .ndo_set_mac_address    = vnet_set_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
        .ndo_tx_timeout         = vnet_tx_timeout,
        .ndo_change_mtu         = vnet_change_mtu,
        .ndo_start_xmit         = vnet_start_xmit,
index 9d896116cf761b6aea8a6b294a2da95fa07238f5..08a6c41c1599f067ac8c165ab4c9efab309170b2 100644 (file)
@@ -1912,7 +1912,7 @@ static int __init ibmtr_init(void)
 
        find_turbo_adapters(io);
 
-       for (i = 0; io[i] && (i < IBMTR_MAX_ADAPTERS); i++) {
+       for (i = 0; i < IBMTR_MAX_ADAPTERS && io[i]; i++) {
                struct net_device *dev;
                irq[i] = 0;
                mem[i] = 0;
index 0f78f99f9b20ca247573e46d7b78dd8c7566abb9..7030bd5e9848e1582160b4414365086bc22972ca 100644 (file)
@@ -1132,7 +1132,9 @@ static int tsi108_get_mac(struct net_device *dev)
        }
 
        if (!is_valid_ether_addr(dev->dev_addr)) {
-               printk("KERN_ERR: word1: %08x, word2: %08x\n", word1, word2);
+               printk(KERN_ERR
+                      "%s: Invalid MAC address. word1: %08x, word2: %08x\n",
+                      dev->name, word1, word2);
                return -EINVAL;
        }
 
@@ -1201,8 +1203,8 @@ static void tsi108_set_rx_mode(struct net_device *dev)
                                __set_bit(hash, &data->mc_hash[0]);
                        } else {
                                printk(KERN_ERR
-                                      "%s: got multicast address of length %d "
-                                      "instead of 6.\n", dev->name,
+               "%s: got multicast address of length %d instead of 6.\n",
+                                      dev->name,
                                       mc->dmi_addrlen);
                        }
 
index 81f054dbb88ddb2712bc6d60921f857c3920a05e..ef49744a508520124e2970538e880df4b48b8cae 100644 (file)
@@ -944,9 +944,10 @@ static void de_set_media (struct de_private *de)
                macmode &= ~FullDuplex;
 
        if (netif_msg_link(de)) {
-               printk(KERN_INFO "%s: set link %s\n"
-                      KERN_INFO "%s:    mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n"
-                      KERN_INFO "%s:    set mode 0x%x, set sia 0x%x,0x%x,0x%x\n",
+               printk(KERN_INFO
+                      "%s: set link %s\n"
+                      "%s:    mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n"
+                      "%s:    set mode 0x%x, set sia 0x%x,0x%x,0x%x\n",
                       de->dev->name, media_name[media],
                       de->dev->name, dr32(MacMode), dr32(SIAStatus),
                       dr32(CSR13), dr32(CSR14), dr32(CSR15),
index eb72d2e9ab3d1366f2347969d35ba31efc16630b..acfdccd445677053842cf04f7611f51b480febdc 100644 (file)
@@ -5059,7 +5059,7 @@ mii_get_phy(struct net_device *dev)
        if ((id == 0) || (id == 65535)) continue;  /* Valid ID? */
        for (j=0; j<limit; j++) {                  /* Search PHY table */
            if (id != phy_info[j].id) continue;    /* ID match? */
-           for (k=0; lp->phy[k].id && (k < DE4X5_MAX_PHY); k++);
+           for (k=0; k < DE4X5_MAX_PHY && lp->phy[k].id; k++);
            if (k < DE4X5_MAX_PHY) {
                memcpy((char *)&lp->phy[k],
                       (char *)&phy_info[j], sizeof(struct phy_table));
@@ -5072,7 +5072,7 @@ mii_get_phy(struct net_device *dev)
            break;
        }
        if ((j == limit) && (i < DE4X5_MAX_MII)) {
-           for (k=0; lp->phy[k].id && (k < DE4X5_MAX_PHY); k++);
+           for (k=0; k < DE4X5_MAX_PHY && lp->phy[k].id; k++);
            lp->phy[k].addr = i;
            lp->phy[k].id = id;
            lp->phy[k].spd.reg = GENERIC_REG;      /* ANLPA register         */
@@ -5091,7 +5091,7 @@ mii_get_phy(struct net_device *dev)
   purgatory:
     lp->active = 0;
     if (lp->phy[0].id) {                           /* Reset the PHY devices */
-       for (k=0; lp->phy[k].id && (k < DE4X5_MAX_PHY); k++) { /*For each PHY*/
+       for (k=0; k < DE4X5_MAX_PHY && lp->phy[k].id; k++) { /*For each PHY*/
            mii_wr(MII_CR_RST, MII_CR, lp->phy[k].addr, DE4X5_MII);
            while (mii_rd(MII_CR, lp->phy[k].addr, DE4X5_MII) & MII_CR_RST);
 
index 2abb5d3becc6d2d98ec7613b42c0f05b8b439352..4cf9a6588751eacadc2d798a7f14fba135ce7012 100644 (file)
@@ -570,16 +570,18 @@ static void tulip_tx_timeout(struct net_device *dev)
                                   (unsigned int)tp->rx_ring[i].buffer2,
                                   buf[0], buf[1], buf[2]);
                        for (j = 0; buf[j] != 0xee && j < 1600; j++)
-                               if (j < 100) printk(" %2.2x", buf[j]);
-                       printk(" j=%d.\n", j);
+                               if (j < 100)
+                                       printk(KERN_CONT " %2.2x", buf[j]);
+                       printk(KERN_CONT " j=%d.\n", j);
                }
                printk(KERN_DEBUG "  Rx ring %8.8x: ", (int)tp->rx_ring);
                for (i = 0; i < RX_RING_SIZE; i++)
-                       printk(" %8.8x", (unsigned int)tp->rx_ring[i].status);
-               printk("\n" KERN_DEBUG "  Tx ring %8.8x: ", (int)tp->tx_ring);
+                       printk(KERN_CONT " %8.8x",
+                              (unsigned int)tp->rx_ring[i].status);
+               printk(KERN_DEBUG "  Tx ring %8.8x: ", (int)tp->tx_ring);
                for (i = 0; i < TX_RING_SIZE; i++)
-                       printk(" %8.8x", (unsigned int)tp->tx_ring[i].status);
-               printk("\n");
+                       printk(KERN_CONT " %8.8x", (unsigned int)tp->tx_ring[i].status);
+               printk(KERN_CONT "\n");
        }
 #endif
 
@@ -650,8 +652,9 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
        int entry;
        u32 flag;
        dma_addr_t mapping;
+       unsigned long flags;
 
-       spin_lock_irq(&tp->lock);
+       spin_lock_irqsave(&tp->lock, flags);
 
        /* Calculate the next Tx descriptor entry. */
        entry = tp->cur_tx % TX_RING_SIZE;
@@ -686,7 +689,7 @@ tulip_start_xmit(struct sk_buff *skb, struct net_device *dev)
        /* Trigger an immediate transmit demand. */
        iowrite32(0, tp->base_addr + CSR1);
 
-       spin_unlock_irq(&tp->lock);
+       spin_unlock_irqrestore(&tp->lock, flags);
 
        dev->trans_start = jiffies;
 
index 842b1a2c40d4abed18d9d241c8759f1daaaae8be..0f15773dae528374dd94a36ebb4f73025af51eb2 100644 (file)
@@ -142,7 +142,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static const char version[] __initconst =
        KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) "
        DRV_RELDATE "  Donald Becker <becker@scyld.com>\n"
-       KERN_INFO "  http://www.scyld.com/network/drivers.html\n";
+       "  http://www.scyld.com/network/drivers.html\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Winbond W89c840 Ethernet driver");
@@ -939,7 +939,7 @@ static void tx_timeout(struct net_device *dev)
                printk(KERN_DEBUG "  Rx ring %p: ", np->rx_ring);
                for (i = 0; i < RX_RING_SIZE; i++)
                        printk(" %8.8x", (unsigned int)np->rx_ring[i].status);
-               printk("\n"KERN_DEBUG"  Tx ring %p: ", np->tx_ring);
+               printk(KERN_DEBUG"  Tx ring %p: ", np->tx_ring);
                for (i = 0; i < TX_RING_SIZE; i++)
                        printk(" %8.8x", np->tx_ring[i].status);
                printk("\n");
@@ -1520,7 +1520,7 @@ static int netdev_close(struct net_device *dev)
                        printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x.\n",
                                   i, np->tx_ring[i].length,
                                   np->tx_ring[i].status, np->tx_ring[i].buffer1);
-               printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n",
+               printk(KERN_DEBUG "  Rx ring %8.8x:\n",
                           (int)np->rx_ring);
                for (i = 0; i < RX_RING_SIZE; i++) {
                        printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n",
index 11a0ba47b67782d920f3bf5cb36d3e24d4874b63..42b6c6319bc29824fe4e2061ee882759cfeb05c1 100644 (file)
@@ -486,12 +486,14 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
 {
        struct tun_file *tfile = file->private_data;
        struct tun_struct *tun = __tun_get(tfile);
-       struct sock *sk = tun->sk;
+       struct sock *sk;
        unsigned int mask = 0;
 
        if (!tun)
                return POLLERR;
 
+       sk = tun->sk;
+
        DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);
 
        poll_wait(file, &tun->socket.wait, wait);
@@ -1046,20 +1048,15 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
        return err;
 }
 
-static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr)
+static int tun_get_iff(struct net *net, struct tun_struct *tun,
+                      struct ifreq *ifr)
 {
-       struct tun_struct *tun = tun_get(file);
-
-       if (!tun)
-               return -EBADFD;
-
        DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name);
 
        strcpy(ifr->ifr_name, tun->dev->name);
 
        ifr->ifr_flags = tun_flags(tun);
 
-       tun_put(tun);
        return 0;
 }
 
@@ -1103,8 +1100,8 @@ static int set_offload(struct net_device *dev, unsigned long arg)
        return 0;
 }
 
-static int tun_chr_ioctl(struct inode *inode, struct file *file,
-                        unsigned int cmd, unsigned long arg)
+static long tun_chr_ioctl(struct file *file, unsigned int cmd,
+                         unsigned long arg)
 {
        struct tun_file *tfile = file->private_data;
        struct tun_struct *tun;
@@ -1126,34 +1123,32 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
                                (unsigned int __user*)argp);
        }
 
+       rtnl_lock();
+
        tun = __tun_get(tfile);
        if (cmd == TUNSETIFF && !tun) {
-               int err;
-
                ifr.ifr_name[IFNAMSIZ-1] = '\0';
 
-               rtnl_lock();
-               err = tun_set_iff(tfile->net, file, &ifr);
-               rtnl_unlock();
+               ret = tun_set_iff(tfile->net, file, &ifr);
 
-               if (err)
-                       return err;
+               if (ret)
+                       goto unlock;
 
                if (copy_to_user(argp, &ifr, sizeof(ifr)))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               goto unlock;
        }
 
-
+       ret = -EBADFD;
        if (!tun)
-               return -EBADFD;
+               goto unlock;
 
        DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd);
 
        ret = 0;
        switch (cmd) {
        case TUNGETIFF:
-               ret = tun_get_iff(current->nsproxy->net_ns, file, &ifr);
+               ret = tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
                if (ret)
                        break;
 
@@ -1199,7 +1194,6 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
 
        case TUNSETLINK:
                /* Only allow setting the type when the interface is down */
-               rtnl_lock();
                if (tun->dev->flags & IFF_UP) {
                        DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
                                tun->dev->name);
@@ -1209,7 +1203,6 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
                        DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
                        ret = 0;
                }
-               rtnl_unlock();
                break;
 
 #ifdef TUN_DEBUG
@@ -1218,9 +1211,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
                break;
 #endif
        case TUNSETOFFLOAD:
-               rtnl_lock();
                ret = set_offload(tun->dev, arg);
-               rtnl_unlock();
                break;
 
        case TUNSETTXFILTER:
@@ -1228,9 +1219,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
                ret = -EINVAL;
                if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
                        break;
-               rtnl_lock();
                ret = update_filter(&tun->txflt, (void __user *)arg);
-               rtnl_unlock();
                break;
 
        case SIOCGIFHWADDR:
@@ -1246,9 +1235,7 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
                DBG(KERN_DEBUG "%s: set hw address: %pM\n",
                        tun->dev->name, ifr.ifr_hwaddr.sa_data);
 
-               rtnl_lock();
                ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
-               rtnl_unlock();
                break;
 
        case TUNGETSNDBUF:
@@ -1271,7 +1258,10 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
                break;
        };
 
-       tun_put(tun);
+unlock:
+       rtnl_unlock();
+       if (tun)
+               tun_put(tun);
        return ret;
 }
 
@@ -1324,20 +1314,22 @@ static int tun_chr_close(struct inode *inode, struct file *file)
        struct tun_file *tfile = file->private_data;
        struct tun_struct *tun;
 
-
-       rtnl_lock();
        tun = __tun_get(tfile);
        if (tun) {
-               DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name);
+               struct net_device *dev = tun->dev;
+
+               DBG(KERN_INFO "%s: tun_chr_close\n", dev->name);
 
                __tun_detach(tun);
 
                /* If desireable, unregister the netdevice. */
-               if (!(tun->flags & TUN_PERSIST))
-                       unregister_netdevice(tun->dev);
-
+               if (!(tun->flags & TUN_PERSIST)) {
+                       rtnl_lock();
+                       if (dev->reg_state == NETREG_REGISTERED)
+                               unregister_netdevice(dev);
+                       rtnl_unlock();
+               }
        }
-       rtnl_unlock();
 
        tun = tfile->tun;
        if (tun)
@@ -1357,7 +1349,7 @@ static const struct file_operations tun_fops = {
        .write = do_sync_write,
        .aio_write = tun_chr_aio_write,
        .poll   = tun_chr_poll,
-       .ioctl  = tun_chr_ioctl,
+       .unlocked_ioctl = tun_chr_ioctl,
        .open   = tun_chr_open,
        .release = tun_chr_close,
        .fasync = tun_chr_fasync
index 40c6eba775ce89c026f218ff27f97445f4b7fe02..8a7b8c7bd7810a49baed432f3aba916dca16cf84 100644 (file)
@@ -1590,13 +1590,13 @@ static int init_phy(struct net_device *dev)
        priv->oldspeed = 0;
        priv->oldduplex = -1;
 
-       if (!ug_info->phy_node)
-               return 0;
-
        phydev = of_phy_connect(dev, ug_info->phy_node, &adjust_link, 0,
                                priv->phy_interface);
+       if (!phydev)
+               phydev = of_phy_connect_fixed_link(dev, &adjust_link,
+                                                  priv->phy_interface);
        if (!phydev) {
-               printk("%s: Could not attach to PHY\n", dev->name);
+               dev_err(&dev->dev, "Could not attach to PHY\n");
                return -ENODEV;
        }
 
@@ -3111,10 +3111,11 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
        u8 __iomem *bd;                 /* BD pointer */
        u32 bd_status;
        u8 txQ = 0;
+       unsigned long flags;
 
        ugeth_vdbg("%s: IN", __func__);
 
-       spin_lock_irq(&ugeth->lock);
+       spin_lock_irqsave(&ugeth->lock, flags);
 
        dev->stats.tx_bytes += skb->len;
 
@@ -3171,7 +3172,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
        uccf = ugeth->uccf;
        out_be16(uccf->p_utodr, UCC_FAST_TOD);
 #endif
-       spin_unlock_irq(&ugeth->lock);
+       spin_unlock_irqrestore(&ugeth->lock, flags);
 
        return 0;
 }
@@ -3608,9 +3609,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
        struct ucc_geth_private *ugeth = NULL;
        struct ucc_geth_info *ug_info;
        struct resource res;
-       struct device_node *phy;
        int err, ucc_num, max_speed = 0;
-       const u32 *fixed_link;
        const unsigned int *prop;
        const char *sprop;
        const void *mac_addr;
@@ -3708,15 +3707,8 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
 
        ug_info->uf_info.regs = res.start;
        ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
-       fixed_link = of_get_property(np, "fixed-link", NULL);
-       if (fixed_link) {
-               phy = NULL;
-       } else {
-               phy = of_parse_phandle(np, "phy-handle", 0);
-               if (phy == NULL)
-                       return -ENODEV;
-       }
-       ug_info->phy_node = phy;
+
+       ug_info->phy_node = of_parse_phandle(np, "phy-handle", 0);
 
        /* Find the TBI PHY node.  If it's not there, we don't support SGMII */
        ug_info->tbi_node = of_parse_phandle(np, "tbi-handle", 0);
@@ -3725,7 +3717,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
        prop = of_get_property(np, "phy-connection-type", NULL);
        if (!prop) {
                /* handle interface property present in old trees */
-               prop = of_get_property(phy, "interface", NULL);
+               prop = of_get_property(ug_info->phy_node, "interface", NULL);
                if (prop != NULL) {
                        phy_interface = enet_to_phy_interface[*prop];
                        max_speed = enet_to_speed[*prop];
index a906d3998131a512b0f125f3f8892cf38c3bdaf5..c47237c2d638ef97dc3a2d10186c0cdf55e9c452 100644 (file)
@@ -369,4 +369,12 @@ config USB_NET_INT51X1
          (Powerline Communications) solution with an Intellon
          INT51x1/INT5200 chip, like the "devolo dLan duo".
 
+config USB_CDC_PHONET
+       tristate "CDC Phonet support"
+       depends on PHONET
+       help
+         Choose this option to support the Phonet interface to a Nokia
+         cellular modem, as found on most Nokia handsets with the
+         "PC suite" USB profile.
+
 endmenu
index b870b0b1cbe0a1280ad7900a05c148417ff7729f..e17afb78f37220df2c8c6a13eb420aa14280fd09 100644 (file)
@@ -21,4 +21,5 @@ obj-$(CONFIG_USB_NET_ZAURUS)  += zaurus.o
 obj-$(CONFIG_USB_NET_MCS7830)  += mcs7830.o
 obj-$(CONFIG_USB_USBNET)       += usbnet.o
 obj-$(CONFIG_USB_NET_INT51X1)  += int51x1.o
+obj-$(CONFIG_USB_CDC_PHONET)   += cdc-phonet.o
 
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
new file mode 100644 (file)
index 0000000..792af72
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+ * phonet.c -- USB CDC Phonet host driver
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * Author: Rémi Denis-Courmont
+ *
+ * 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 the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/cdc.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/if_phonet.h>
+
+#define PN_MEDIA_USB   0x1B
+
+static const unsigned rxq_size = 17;
+
+struct usbpn_dev {
+       struct net_device       *dev;
+
+       struct usb_interface    *intf, *data_intf;
+       struct usb_device       *usb;
+       unsigned int            tx_pipe, rx_pipe;
+       u8 active_setting;
+       u8 disconnected;
+
+       unsigned                tx_queue;
+       spinlock_t              tx_lock;
+
+       spinlock_t              rx_lock;
+       struct sk_buff          *rx_skb;
+       struct urb              *urbs[0];
+};
+
+static void tx_complete(struct urb *req);
+static void rx_complete(struct urb *req);
+
+/*
+ * Network device callbacks
+ */
+static int usbpn_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       struct usbpn_dev *pnd = netdev_priv(dev);
+       struct urb *req = NULL;
+       unsigned long flags;
+       int err;
+
+       if (skb->protocol != htons(ETH_P_PHONET))
+               goto drop;
+
+       req = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!req)
+               goto drop;
+       usb_fill_bulk_urb(req, pnd->usb, pnd->tx_pipe, skb->data, skb->len,
+                               tx_complete, skb);
+       req->transfer_flags = URB_ZERO_PACKET;
+       err = usb_submit_urb(req, GFP_ATOMIC);
+       if (err) {
+               usb_free_urb(req);
+               goto drop;
+       }
+
+       spin_lock_irqsave(&pnd->tx_lock, flags);
+       pnd->tx_queue++;
+       if (pnd->tx_queue >= dev->tx_queue_len)
+               netif_stop_queue(dev);
+       spin_unlock_irqrestore(&pnd->tx_lock, flags);
+       return 0;
+
+drop:
+       dev_kfree_skb(skb);
+       dev->stats.tx_dropped++;
+       return 0;
+}
+
+static void tx_complete(struct urb *req)
+{
+       struct sk_buff *skb = req->context;
+       struct net_device *dev = skb->dev;
+       struct usbpn_dev *pnd = netdev_priv(dev);
+
+       switch (req->status) {
+       case 0:
+               dev->stats.tx_bytes += skb->len;
+               break;
+
+       case -ENOENT:
+       case -ECONNRESET:
+       case -ESHUTDOWN:
+               dev->stats.tx_aborted_errors++;
+       default:
+               dev->stats.tx_errors++;
+               dev_dbg(&dev->dev, "TX error (%d)\n", req->status);
+       }
+       dev->stats.tx_packets++;
+
+       spin_lock(&pnd->tx_lock);
+       pnd->tx_queue--;
+       netif_wake_queue(dev);
+       spin_unlock(&pnd->tx_lock);
+
+       dev_kfree_skb_any(skb);
+       usb_free_urb(req);
+}
+
+static int rx_submit(struct usbpn_dev *pnd, struct urb *req, gfp_t gfp_flags)
+{
+       struct net_device *dev = pnd->dev;
+       struct page *page;
+       int err;
+
+       page = __netdev_alloc_page(dev, gfp_flags);
+       if (!page)
+               return -ENOMEM;
+
+       usb_fill_bulk_urb(req, pnd->usb, pnd->rx_pipe, page_address(page),
+                               PAGE_SIZE, rx_complete, dev);
+       req->transfer_flags = 0;
+       err = usb_submit_urb(req, gfp_flags);
+       if (unlikely(err)) {
+               dev_dbg(&dev->dev, "RX submit error (%d)\n", err);
+               netdev_free_page(dev, page);
+       }
+       return err;
+}
+
+static void rx_complete(struct urb *req)
+{
+       struct net_device *dev = req->context;
+       struct usbpn_dev *pnd = netdev_priv(dev);
+       struct page *page = virt_to_page(req->transfer_buffer);
+       struct sk_buff *skb;
+       unsigned long flags;
+
+       switch (req->status) {
+       case 0:
+               spin_lock_irqsave(&pnd->rx_lock, flags);
+               skb = pnd->rx_skb;
+               if (!skb) {
+                       skb = pnd->rx_skb = netdev_alloc_skb(dev, 12);
+                       if (likely(skb)) {
+                               /* Can't use pskb_pull() on page in IRQ */
+                               memcpy(skb_put(skb, 1), page_address(page), 1);
+                               skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
+                                               page, 1, req->actual_length);
+                               page = NULL;
+                       }
+               } else {
+                       skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
+                                       page, 0, req->actual_length);
+                       page = NULL;
+               }
+               if (req->actual_length < PAGE_SIZE)
+                       pnd->rx_skb = NULL; /* Last fragment */
+               else
+                       skb = NULL;
+               spin_unlock_irqrestore(&pnd->rx_lock, flags);
+               if (skb) {
+                       skb->protocol = htons(ETH_P_PHONET);
+                       skb_reset_mac_header(skb);
+                       __skb_pull(skb, 1);
+                       skb->dev = dev;
+                       dev->stats.rx_packets++;
+                       dev->stats.rx_bytes += skb->len;
+
+                       netif_rx(skb);
+               }
+               goto resubmit;
+
+       case -ENOENT:
+       case -ECONNRESET:
+       case -ESHUTDOWN:
+               req = NULL;
+               break;
+
+       case -EOVERFLOW:
+               dev->stats.rx_over_errors++;
+               dev_dbg(&dev->dev, "RX overflow\n");
+               break;
+
+       case -EILSEQ:
+               dev->stats.rx_crc_errors++;
+               break;
+       }
+
+       dev->stats.rx_errors++;
+resubmit:
+       if (page)
+               netdev_free_page(dev, page);
+       if (req)
+               rx_submit(pnd, req, GFP_ATOMIC);
+}
+
+static int usbpn_close(struct net_device *dev);
+
+static int usbpn_open(struct net_device *dev)
+{
+       struct usbpn_dev *pnd = netdev_priv(dev);
+       int err;
+       unsigned i;
+       unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber;
+
+       err = usb_set_interface(pnd->usb, num, pnd->active_setting);
+       if (err)
+               return err;
+
+       for (i = 0; i < rxq_size; i++) {
+               struct urb *req = usb_alloc_urb(0, GFP_KERNEL);
+
+               if (!req || rx_submit(pnd, req, GFP_KERNEL)) {
+                       usbpn_close(dev);
+                       return -ENOMEM;
+               }
+               pnd->urbs[i] = req;
+       }
+
+       netif_wake_queue(dev);
+       return 0;
+}
+
+static int usbpn_close(struct net_device *dev)
+{
+       struct usbpn_dev *pnd = netdev_priv(dev);
+       unsigned i;
+       unsigned num = pnd->data_intf->cur_altsetting->desc.bInterfaceNumber;
+
+       netif_stop_queue(dev);
+
+       for (i = 0; i < rxq_size; i++) {
+               struct urb *req = pnd->urbs[i];
+
+               if (!req)
+                       continue;
+               usb_kill_urb(req);
+               usb_free_urb(req);
+               pnd->urbs[i] = NULL;
+       }
+
+       return usb_set_interface(pnd->usb, num, !pnd->active_setting);
+}
+
+static int usbpn_set_mtu(struct net_device *dev, int new_mtu)
+{
+       if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU))
+               return -EINVAL;
+
+       dev->mtu = new_mtu;
+       return 0;
+}
+
+static const struct net_device_ops usbpn_ops = {
+       .ndo_open       = usbpn_open,
+       .ndo_stop       = usbpn_close,
+       .ndo_start_xmit = usbpn_xmit,
+       .ndo_change_mtu = usbpn_set_mtu,
+};
+
+static void usbpn_setup(struct net_device *dev)
+{
+       dev->features           = 0;
+       dev->netdev_ops         = &usbpn_ops,
+       dev->header_ops         = &phonet_header_ops;
+       dev->type               = ARPHRD_PHONET;
+       dev->flags              = IFF_POINTOPOINT | IFF_NOARP;
+       dev->mtu                = PHONET_MAX_MTU;
+       dev->hard_header_len    = 1;
+       dev->dev_addr[0]        = PN_MEDIA_USB;
+       dev->addr_len           = 1;
+       dev->tx_queue_len       = 3;
+
+       dev->destructor         = free_netdev;
+}
+
+/*
+ * USB driver callbacks
+ */
+static struct usb_device_id usbpn_ids[] = {
+       {
+               .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+                       | USB_DEVICE_ID_MATCH_INT_CLASS
+                       | USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+               .idVendor = 0x0421, /* Nokia */
+               .bInterfaceClass = USB_CLASS_COMM,
+               .bInterfaceSubClass = 0xFE,
+       },
+       { },
+};
+
+MODULE_DEVICE_TABLE(usb, usbpn_ids);
+
+static struct usb_driver usbpn_driver;
+
+int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+       static const char ifname[] = "usbpn%d";
+       const struct usb_cdc_union_desc *union_header = NULL;
+       const struct usb_cdc_header_desc *phonet_header = NULL;
+       const struct usb_host_interface *data_desc;
+       struct usb_interface *data_intf;
+       struct usb_device *usbdev = interface_to_usbdev(intf);
+       struct net_device *dev;
+       struct usbpn_dev *pnd;
+       u8 *data;
+       int len, err;
+
+       data = intf->altsetting->extra;
+       len = intf->altsetting->extralen;
+       while (len >= 3) {
+               u8 dlen = data[0];
+               if (dlen < 3)
+                       return -EINVAL;
+
+               /* bDescriptorType */
+               if (data[1] == USB_DT_CS_INTERFACE) {
+                       /* bDescriptorSubType */
+                       switch (data[2]) {
+                       case USB_CDC_UNION_TYPE:
+                               if (union_header || dlen < 5)
+                                       break;
+                               union_header =
+                                       (struct usb_cdc_union_desc *)data;
+                               break;
+                       case 0xAB:
+                               if (phonet_header || dlen < 5)
+                                       break;
+                               phonet_header =
+                                       (struct usb_cdc_header_desc *)data;
+                               break;
+                       }
+               }
+               data += dlen;
+               len -= dlen;
+       }
+
+       if (!union_header || !phonet_header)
+               return -EINVAL;
+
+       data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0);
+       if (data_intf == NULL)
+               return -ENODEV;
+       /* Data interface has one inactive and one active setting */
+       if (data_intf->num_altsetting != 2)
+               return -EINVAL;
+       if (data_intf->altsetting[0].desc.bNumEndpoints == 0
+        && data_intf->altsetting[1].desc.bNumEndpoints == 2)
+               data_desc = data_intf->altsetting + 1;
+       else
+       if (data_intf->altsetting[0].desc.bNumEndpoints == 2
+        && data_intf->altsetting[1].desc.bNumEndpoints == 0)
+               data_desc = data_intf->altsetting;
+       else
+               return -EINVAL;
+
+       dev = alloc_netdev(sizeof(*pnd) + sizeof(pnd->urbs[0]) * rxq_size,
+                               ifname, usbpn_setup);
+       if (!dev)
+               return -ENOMEM;
+
+       pnd = netdev_priv(dev);
+       SET_NETDEV_DEV(dev, &intf->dev);
+       netif_stop_queue(dev);
+
+       pnd->dev = dev;
+       pnd->usb = usb_get_dev(usbdev);
+       pnd->intf = intf;
+       pnd->data_intf = data_intf;
+       spin_lock_init(&pnd->tx_lock);
+       spin_lock_init(&pnd->rx_lock);
+       /* Endpoints */
+       if (usb_pipein(data_desc->endpoint[0].desc.bEndpointAddress)) {
+               pnd->rx_pipe = usb_rcvbulkpipe(usbdev,
+                       data_desc->endpoint[0].desc.bEndpointAddress);
+               pnd->tx_pipe = usb_sndbulkpipe(usbdev,
+                       data_desc->endpoint[1].desc.bEndpointAddress);
+       } else {
+               pnd->rx_pipe = usb_rcvbulkpipe(usbdev,
+                       data_desc->endpoint[1].desc.bEndpointAddress);
+               pnd->tx_pipe = usb_sndbulkpipe(usbdev,
+                       data_desc->endpoint[0].desc.bEndpointAddress);
+       }
+       pnd->active_setting = data_desc - data_intf->altsetting;
+
+       err = usb_driver_claim_interface(&usbpn_driver, data_intf, pnd);
+       if (err)
+               goto out;
+
+       /* Force inactive mode until the network device is brought UP */
+       usb_set_interface(usbdev, union_header->bSlaveInterface0,
+                               !pnd->active_setting);
+       usb_set_intfdata(intf, pnd);
+
+       err = register_netdev(dev);
+       if (err) {
+               usb_driver_release_interface(&usbpn_driver, data_intf);
+               goto out;
+       }
+
+       dev_dbg(&dev->dev, "USB CDC Phonet device found\n");
+       return 0;
+
+out:
+       usb_set_intfdata(intf, NULL);
+       free_netdev(dev);
+       return err;
+}
+
+static void usbpn_disconnect(struct usb_interface *intf)
+{
+       struct usbpn_dev *pnd = usb_get_intfdata(intf);
+       struct usb_device *usb = pnd->usb;
+
+       if (pnd->disconnected)
+               return;
+
+       pnd->disconnected = 1;
+       usb_driver_release_interface(&usbpn_driver,
+                       (pnd->intf == intf) ? pnd->data_intf : pnd->intf);
+       unregister_netdev(pnd->dev);
+       usb_put_dev(usb);
+}
+
+static struct usb_driver usbpn_driver = {
+       .name =         "cdc_phonet",
+       .probe =        usbpn_probe,
+       .disconnect =   usbpn_disconnect,
+       .id_table =     usbpn_ids,
+};
+
+static int __init usbpn_init(void)
+{
+       return usb_register(&usbpn_driver);
+}
+
+static void __exit usbpn_exit(void)
+{
+       usb_deregister(&usbpn_driver);
+}
+
+module_init(usbpn_init);
+module_exit(usbpn_exit);
+
+MODULE_AUTHOR("Remi Denis-Courmont");
+MODULE_DESCRIPTION("USB CDC Phonet host interface");
+MODULE_LICENSE("GPL");
index 80e01778dd3bae3bd4c8c52456188520d620870d..45cebfb302cf438e769f0865decbf9f86a0f90b8 100644 (file)
@@ -311,7 +311,7 @@ static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                         *      bmCRC = 0       : CRC = 0xDEADBEEF
                         */
                        if (header & BIT(14))
-                               crc2 = ~crc32_le(~0, skb2->data, len);
+                               crc2 = ~crc32_le(~0, skb2->data, skb2->len);
                        else
                                crc2 = 0xdeadbeef;
 
@@ -319,7 +319,7 @@ static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                                return crc == crc2;
 
                        if (unlikely(crc != crc2)) {
-                               dev->stats.rx_errors++;
+                               dev->net->stats.rx_errors++;
                                dev_kfree_skb_any(skb2);
                        } else
                                usbnet_skb_return(dev, skb2);
index 7ae82446b93aed59f3dd646f5df5767ab3feb74f..1d3730d6690fc90c640ac87bc655f04b19ad5eff 100644 (file)
@@ -513,11 +513,11 @@ static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        len = (skb->data[1] | (skb->data[2] << 8)) - 4;
 
        if (unlikely(status & 0xbf)) {
-               if (status & 0x01) dev->stats.rx_fifo_errors++;
-               if (status & 0x02) dev->stats.rx_crc_errors++;
-               if (status & 0x04) dev->stats.rx_frame_errors++;
-               if (status & 0x20) dev->stats.rx_missed_errors++;
-               if (status & 0x90) dev->stats.rx_length_errors++;
+               if (status & 0x01) dev->net->stats.rx_fifo_errors++;
+               if (status & 0x02) dev->net->stats.rx_crc_errors++;
+               if (status & 0x04) dev->net->stats.rx_frame_errors++;
+               if (status & 0x20) dev->net->stats.rx_missed_errors++;
+               if (status & 0x90) dev->net->stats.rx_length_errors++;
                return 0;
        }
 
index e0131478971829902dd2f8e836f7b17d0d74aeda..1f9ec29fce5042fc3a17f16f4a1c0708b9e6e50c 100644 (file)
@@ -999,6 +999,9 @@ static const struct net_device_ops kaweth_netdev_ops = {
        .ndo_tx_timeout =               kaweth_tx_timeout,
        .ndo_set_multicast_list =       kaweth_set_rx_mode,
        .ndo_get_stats =                kaweth_netdev_stats,
+       .ndo_change_mtu =               eth_change_mtu,
+       .ndo_set_mac_address =          eth_mac_addr,
+       .ndo_validate_addr =            eth_validate_addr,
 };
 
 static int kaweth_probe(
index 034e8a73ca6b487dc7ab32e02ba11d77d71ab72e..aeb1ab03a9ee650e8aa7c732eac56b7e2585b86d 100644 (file)
@@ -433,7 +433,7 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                dbg("rx framesize %d range %d..%d mtu %d", skb->len,
                        net->hard_header_len, dev->hard_mtu, net->mtu);
 #endif
-               dev->stats.rx_frame_errors++;
+               dev->net->stats.rx_frame_errors++;
                nc_ensure_sync(dev);
                return 0;
        }
@@ -442,12 +442,12 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        hdr_len = le16_to_cpup(&header->hdr_len);
        packet_len = le16_to_cpup(&header->packet_len);
        if (FRAMED_SIZE(packet_len) > NC_MAX_PACKET) {
-               dev->stats.rx_frame_errors++;
+               dev->net->stats.rx_frame_errors++;
                dbg("packet too big, %d", packet_len);
                nc_ensure_sync(dev);
                return 0;
        } else if (hdr_len < MIN_HEADER) {
-               dev->stats.rx_frame_errors++;
+               dev->net->stats.rx_frame_errors++;
                dbg("header too short, %d", hdr_len);
                nc_ensure_sync(dev);
                return 0;
@@ -465,21 +465,21 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 
        if ((packet_len & 0x01) == 0) {
                if (skb->data [packet_len] != PAD_BYTE) {
-                       dev->stats.rx_frame_errors++;
+                       dev->net->stats.rx_frame_errors++;
                        dbg("bad pad");
                        return 0;
                }
                skb_trim(skb, skb->len - 1);
        }
        if (skb->len != packet_len) {
-               dev->stats.rx_frame_errors++;
+               dev->net->stats.rx_frame_errors++;
                dbg("bad packet len %d (expected %d)",
                        skb->len, packet_len);
                nc_ensure_sync(dev);
                return 0;
        }
        if (header->packet_id != get_unaligned(&trailer->packet_id)) {
-               dev->stats.rx_fifo_errors++;
+               dev->net->stats.rx_fifo_errors++;
                dbg("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
                        le16_to_cpu(header->packet_id),
                        le16_to_cpu(trailer->packet_id));
index 73acbd244aa106493cbdf7c3474937ee44e370f1..631d269ac980a8bb75647875dd1770241a48f5ba 100644 (file)
@@ -1493,6 +1493,9 @@ static const struct net_device_ops pegasus_netdev_ops = {
        .ndo_set_multicast_list =       pegasus_set_multicast,
        .ndo_get_stats =                pegasus_netdev_stats,
        .ndo_tx_timeout =               pegasus_tx_timeout,
+       .ndo_change_mtu =               eth_change_mtu,
+       .ndo_set_mac_address =          eth_mac_addr,
+       .ndo_validate_addr =            eth_validate_addr,
 };
 
 static struct usb_driver pegasus_driver = {
index c7467823cd1ca975349ec5ddfdac2ed293d7beac..f968c834ff63581bf73cdceec371352a5e44fa29 100644 (file)
@@ -250,6 +250,8 @@ PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904,
                DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "IO DATA USB ET/TX-S", VENDOR_IODATA, 0x0913,
                DEFAULT_GPIO_RESET | PEGASUS_II )
+PEGASUS_DEV( "IO DATA USB ETX-US2", VENDOR_IODATA, 0x092a,
+               DEFAULT_GPIO_RESET | PEGASUS_II )
 PEGASUS_DEV( "Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a,
                DEFAULT_GPIO_RESET)
 PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002,
index 1bf243ef950e264e4a11ec86c900812db31e6a99..2232232b79899dab8b6ce2f621742961fb26f647 100644 (file)
@@ -487,7 +487,7 @@ int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                if (unlikely(hdr->msg_type != RNDIS_MSG_PACKET
                                || skb->len < msg_len
                                || (data_offset + data_len + 8) > msg_len)) {
-                       dev->stats.rx_frame_errors++;
+                       dev->net->stats.rx_frame_errors++;
                        devdbg(dev, "bad rndis message %d/%d/%d/%d, len %d",
                                le32_to_cpu(hdr->msg_type),
                                msg_len, data_offset, data_len, skb->len);
index 89a91f8c22dea051009a1a2c513f28fa9a9b600f..fe045896406bdbf3bffa7525621b31b535a265d5 100644 (file)
@@ -1108,18 +1108,18 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                if (unlikely(header & RX_STS_ES_)) {
                        if (netif_msg_rx_err(dev))
                                devdbg(dev, "Error header=0x%08x", header);
-                       dev->stats.rx_errors++;
-                       dev->stats.rx_dropped++;
+                       dev->net->stats.rx_errors++;
+                       dev->net->stats.rx_dropped++;
 
                        if (header & RX_STS_CRC_) {
-                               dev->stats.rx_crc_errors++;
+                               dev->net->stats.rx_crc_errors++;
                        } else {
                                if (header & (RX_STS_TL_ | RX_STS_RF_))
-                                       dev->stats.rx_frame_errors++;
+                                       dev->net->stats.rx_frame_errors++;
 
                                if ((header & RX_STS_LE_) &&
                                        (!(header & RX_STS_FT_)))
-                                       dev->stats.rx_length_errors++;
+                                       dev->net->stats.rx_length_errors++;
                        }
                } else {
                        /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */
index 22c0585a03198f75ea73b3974d394fc984a4ecc1..edfd9e10ceba28fcdc6454dd9c7f386a6ac9f6ac 100644 (file)
@@ -234,8 +234,8 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
        int     status;
 
        skb->protocol = eth_type_trans (skb, dev->net);
-       dev->stats.rx_packets++;
-       dev->stats.rx_bytes += skb->len;
+       dev->net->stats.rx_packets++;
+       dev->net->stats.rx_bytes += skb->len;
 
        if (netif_msg_rx_status (dev))
                devdbg (dev, "< rx, len %zu, type 0x%x",
@@ -397,7 +397,7 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
                if (netif_msg_rx_err (dev))
                        devdbg (dev, "drop");
 error:
-               dev->stats.rx_errors++;
+               dev->net->stats.rx_errors++;
                skb_queue_tail (&dev->done, skb);
        }
 }
@@ -420,8 +420,8 @@ static void rx_complete (struct urb *urb)
        case 0:
                if (skb->len < dev->net->hard_header_len) {
                        entry->state = rx_cleanup;
-                       dev->stats.rx_errors++;
-                       dev->stats.rx_length_errors++;
+                       dev->net->stats.rx_errors++;
+                       dev->net->stats.rx_length_errors++;
                        if (netif_msg_rx_err (dev))
                                devdbg (dev, "rx length %d", skb->len);
                }
@@ -433,7 +433,7 @@ static void rx_complete (struct urb *urb)
         * storm, recovering as needed.
         */
        case -EPIPE:
-               dev->stats.rx_errors++;
+               dev->net->stats.rx_errors++;
                usbnet_defer_kevent (dev, EVENT_RX_HALT);
                // FALLTHROUGH
 
@@ -451,7 +451,7 @@ static void rx_complete (struct urb *urb)
        case -EPROTO:
        case -ETIME:
        case -EILSEQ:
-               dev->stats.rx_errors++;
+               dev->net->stats.rx_errors++;
                if (!timer_pending (&dev->delay)) {
                        mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
                        if (netif_msg_link (dev))
@@ -465,12 +465,12 @@ block:
 
        /* data overrun ... flush fifo? */
        case -EOVERFLOW:
-               dev->stats.rx_over_errors++;
+               dev->net->stats.rx_over_errors++;
                // FALLTHROUGH
 
        default:
                entry->state = rx_cleanup;
-               dev->stats.rx_errors++;
+               dev->net->stats.rx_errors++;
                if (netif_msg_rx_err (dev))
                        devdbg (dev, "rx status %d", urb_status);
                break;
@@ -583,8 +583,8 @@ int usbnet_stop (struct net_device *net)
 
        if (netif_msg_ifdown (dev))
                devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
-                       dev->stats.rx_packets, dev->stats.tx_packets,
-                       dev->stats.rx_errors, dev->stats.tx_errors
+                       net->stats.rx_packets, net->stats.tx_packets,
+                       net->stats.rx_errors, net->stats.tx_errors
                        );
 
        // ensure there are no more active urbs
@@ -891,10 +891,10 @@ static void tx_complete (struct urb *urb)
        struct usbnet           *dev = entry->dev;
 
        if (urb->status == 0) {
-               dev->stats.tx_packets++;
-               dev->stats.tx_bytes += entry->length;
+               dev->net->stats.tx_packets++;
+               dev->net->stats.tx_bytes += entry->length;
        } else {
-               dev->stats.tx_errors++;
+               dev->net->stats.tx_errors++;
 
                switch (urb->status) {
                case -EPIPE:
@@ -1020,7 +1020,7 @@ int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
                        devdbg (dev, "drop, code %d", retval);
 drop:
                retval = NET_XMIT_SUCCESS;
-               dev->stats.tx_dropped++;
+               dev->net->stats.tx_dropped++;
                if (skb)
                        dev_kfree_skb_any (skb);
                usb_free_urb (urb);
index 87197dd9c78847b1eec6497ea331df660841bf83..1097c72e44d5ba3fbfa8c3930e0ee5872ea2b452 100644 (file)
@@ -208,11 +208,14 @@ rx_drop:
 
 static struct net_device_stats *veth_get_stats(struct net_device *dev)
 {
-       struct veth_priv *priv = netdev_priv(dev);
-       struct net_device_stats *dev_stats = &dev->stats;
-       unsigned int cpu;
+       struct veth_priv *priv;
+       struct net_device_stats *dev_stats;
+       int cpu;
        struct veth_net_stats *stats;
 
+       priv = netdev_priv(dev);
+       dev_stats = &dev->stats;
+
        dev_stats->rx_packets = 0;
        dev_stats->tx_packets = 0;
        dev_stats->rx_bytes = 0;
@@ -220,17 +223,16 @@ static struct net_device_stats *veth_get_stats(struct net_device *dev)
        dev_stats->tx_dropped = 0;
        dev_stats->rx_dropped = 0;
 
-       if (priv->stats)
-               for_each_online_cpu(cpu) {
-                       stats = per_cpu_ptr(priv->stats, cpu);
+       for_each_online_cpu(cpu) {
+               stats = per_cpu_ptr(priv->stats, cpu);
 
-                       dev_stats->rx_packets += stats->rx_packets;
-                       dev_stats->tx_packets += stats->tx_packets;
-                       dev_stats->rx_bytes += stats->rx_bytes;
-                       dev_stats->tx_bytes += stats->tx_bytes;
-                       dev_stats->tx_dropped += stats->tx_dropped;
-                       dev_stats->rx_dropped += stats->rx_dropped;
-               }
+               dev_stats->rx_packets += stats->rx_packets;
+               dev_stats->tx_packets += stats->tx_packets;
+               dev_stats->rx_bytes += stats->rx_bytes;
+               dev_stats->tx_bytes += stats->tx_bytes;
+               dev_stats->tx_dropped += stats->tx_dropped;
+               dev_stats->rx_dropped += stats->rx_dropped;
+       }
 
        return dev_stats;
 }
@@ -257,8 +259,6 @@ static int veth_close(struct net_device *dev)
        netif_carrier_off(dev);
        netif_carrier_off(priv->peer);
 
-       free_percpu(priv->stats);
-       priv->stats = NULL;
        return 0;
 }
 
@@ -289,6 +289,15 @@ static int veth_dev_init(struct net_device *dev)
        return 0;
 }
 
+static void veth_dev_free(struct net_device *dev)
+{
+       struct veth_priv *priv;
+
+       priv = netdev_priv(dev);
+       free_percpu(priv->stats);
+       free_netdev(dev);
+}
+
 static const struct net_device_ops veth_netdev_ops = {
        .ndo_init            = veth_dev_init,
        .ndo_open            = veth_open,
@@ -306,7 +315,7 @@ static void veth_setup(struct net_device *dev)
        dev->netdev_ops = &veth_netdev_ops;
        dev->ethtool_ops = &veth_ethtool_ops;
        dev->features |= NETIF_F_LLTX;
-       dev->destructor = free_netdev;
+       dev->destructor = veth_dev_free;
 }
 
 /*
index d3489a3c4c03b28907035181134c20ccb44b9233..934f7671650a8dd3aa0c049fc85001177c3542b7 100644 (file)
@@ -621,6 +621,7 @@ static const struct net_device_ops rhine_netdev_ops = {
        .ndo_start_xmit          = rhine_start_tx,
        .ndo_get_stats           = rhine_get_stats,
        .ndo_set_multicast_list  = rhine_set_rx_mode,
+       .ndo_change_mtu          = eth_change_mtu,
        .ndo_validate_addr       = eth_validate_addr,
        .ndo_set_mac_address     = eth_mac_addr,
        .ndo_do_ioctl            = netdev_ioctl,
@@ -1217,6 +1218,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
        struct rhine_private *rp = netdev_priv(dev);
        void __iomem *ioaddr = rp->base;
        unsigned entry;
+       unsigned long flags;
 
        /* Caution: the write order is important here, set the field
           with the "ownership" bits last. */
@@ -1260,7 +1262,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
                cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
 
        /* lock eth irq */
-       spin_lock_irq(&rp->lock);
+       spin_lock_irqsave(&rp->lock, flags);
        wmb();
        rp->tx_ring[entry].tx_status = cpu_to_le32(DescOwn);
        wmb();
@@ -1279,7 +1281,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev)
 
        dev->trans_start = jiffies;
 
-       spin_unlock_irq(&rp->lock);
+       spin_unlock_irqrestore(&rp->lock, flags);
 
        if (debug > 4) {
                printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n",
index 3ba35956327a37a4cb74046c39e18762f6659ccd..cee08a1e497a1f28340fe8d7314a10464638c46a 100644 (file)
@@ -1778,7 +1778,7 @@ static void velocity_error(struct velocity_info *vptr, int status)
                         *       mode
                         */
                        if (vptr->rev_id < REV_ID_VT3216_A0) {
-                               if (vptr->mii_status | VELOCITY_DUPLEX_FULL)
+                               if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
                                        BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);
                                else
                                        BYTE_REG_BITS_OFF(TCR_TB2BDIS, &regs->TCR);
index 2a6e81d5b579aa9032ae633bb80b6444bcf1ae40..bbedf03a2124c496090c82409d6b58d23c26465e 100644 (file)
@@ -70,6 +70,9 @@ struct virtnet_info
        struct sk_buff_head recv;
        struct sk_buff_head send;
 
+       /* Work struct for refilling if we run low on memory. */
+       struct delayed_work refill;
+
        /* Chain pages by the private ptr. */
        struct page *pages;
 };
@@ -273,19 +276,22 @@ drop:
        dev_kfree_skb(skb);
 }
 
-static void try_fill_recv_maxbufs(struct virtnet_info *vi)
+static bool try_fill_recv_maxbufs(struct virtnet_info *vi, gfp_t gfp)
 {
        struct sk_buff *skb;
        struct scatterlist sg[2+MAX_SKB_FRAGS];
        int num, err, i;
+       bool oom = false;
 
        sg_init_table(sg, 2+MAX_SKB_FRAGS);
        for (;;) {
                struct virtio_net_hdr *hdr;
 
                skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN + NET_IP_ALIGN);
-               if (unlikely(!skb))
+               if (unlikely(!skb)) {
+                       oom = true;
                        break;
+               }
 
                skb_reserve(skb, NET_IP_ALIGN);
                skb_put(skb, MAX_PACKET_LEN);
@@ -296,7 +302,7 @@ static void try_fill_recv_maxbufs(struct virtnet_info *vi)
                if (vi->big_packets) {
                        for (i = 0; i < MAX_SKB_FRAGS; i++) {
                                skb_frag_t *f = &skb_shinfo(skb)->frags[i];
-                               f->page = get_a_page(vi, GFP_ATOMIC);
+                               f->page = get_a_page(vi, gfp);
                                if (!f->page)
                                        break;
 
@@ -325,31 +331,35 @@ static void try_fill_recv_maxbufs(struct virtnet_info *vi)
        if (unlikely(vi->num > vi->max))
                vi->max = vi->num;
        vi->rvq->vq_ops->kick(vi->rvq);
+       return !oom;
 }
 
-static void try_fill_recv(struct virtnet_info *vi)
+/* Returns false if we couldn't fill entirely (OOM). */
+static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
 {
        struct sk_buff *skb;
        struct scatterlist sg[1];
        int err;
+       bool oom = false;
 
-       if (!vi->mergeable_rx_bufs) {
-               try_fill_recv_maxbufs(vi);
-               return;
-       }
+       if (!vi->mergeable_rx_bufs)
+               return try_fill_recv_maxbufs(vi, gfp);
 
        for (;;) {
                skb_frag_t *f;
 
                skb = netdev_alloc_skb(vi->dev, GOOD_COPY_LEN + NET_IP_ALIGN);
-               if (unlikely(!skb))
+               if (unlikely(!skb)) {
+                       oom = true;
                        break;
+               }
 
                skb_reserve(skb, NET_IP_ALIGN);
 
                f = &skb_shinfo(skb)->frags[0];
-               f->page = get_a_page(vi, GFP_ATOMIC);
+               f->page = get_a_page(vi, gfp);
                if (!f->page) {
+                       oom = true;
                        kfree_skb(skb);
                        break;
                }
@@ -373,6 +383,7 @@ static void try_fill_recv(struct virtnet_info *vi)
        if (unlikely(vi->num > vi->max))
                vi->max = vi->num;
        vi->rvq->vq_ops->kick(vi->rvq);
+       return !oom;
 }
 
 static void skb_recv_done(struct virtqueue *rvq)
@@ -385,6 +396,23 @@ static void skb_recv_done(struct virtqueue *rvq)
        }
 }
 
+static void refill_work(struct work_struct *work)
+{
+       struct virtnet_info *vi;
+       bool still_empty;
+
+       vi = container_of(work, struct virtnet_info, refill.work);
+       napi_disable(&vi->napi);
+       try_fill_recv(vi, GFP_KERNEL);
+       still_empty = (vi->num == 0);
+       napi_enable(&vi->napi);
+
+       /* In theory, this can happen: if we don't get any buffers in
+        * we will *never* try to fill again. */
+       if (still_empty)
+               schedule_delayed_work(&vi->refill, HZ/2);
+}
+
 static int virtnet_poll(struct napi_struct *napi, int budget)
 {
        struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi);
@@ -400,10 +428,10 @@ again:
                received++;
        }
 
-       /* FIXME: If we oom and completely run out of inbufs, we need
-        * to start a timer trying to fill more. */
-       if (vi->num < vi->max / 2)
-               try_fill_recv(vi);
+       if (vi->num < vi->max / 2) {
+               if (!try_fill_recv(vi, GFP_ATOMIC))
+                       schedule_delayed_work(&vi->refill, 0);
+       }
 
        /* Out of packets? */
        if (received < budget) {
@@ -893,6 +921,7 @@ static int virtnet_probe(struct virtio_device *vdev)
        vi->vdev = vdev;
        vdev->priv = vi;
        vi->pages = NULL;
+       INIT_DELAYED_WORK(&vi->refill, refill_work);
 
        /* If they give us a callback when all buffers are done, we don't need
         * the timer. */
@@ -941,7 +970,7 @@ static int virtnet_probe(struct virtio_device *vdev)
        }
 
        /* Last of all, set up some receive buffers. */
-       try_fill_recv(vi);
+       try_fill_recv(vi, GFP_KERNEL);
 
        /* If we didn't even get one input buffer, we're useless. */
        if (vi->num == 0) {
@@ -958,6 +987,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 
 unregister:
        unregister_netdev(dev);
+       cancel_delayed_work_sync(&vi->refill);
 free_vqs:
        vdev->config->del_vqs(vdev);
 free:
@@ -986,6 +1016,7 @@ static void virtnet_remove(struct virtio_device *vdev)
        BUG_ON(vi->num != 0);
 
        unregister_netdev(vi->dev);
+       cancel_delayed_work_sync(&vi->refill);
 
        vdev->config->del_vqs(vi->vdev);
 
index 223238de475cdf2ed8802334dfa8addca693f90f..1ea1ef6c3b96205ed787361d884ad786d4cdd404 100644 (file)
@@ -584,8 +584,9 @@ static void sca_dump_rings(struct net_device *dev)
               sca_in(DSR_RX(phy_node(port)), card) & DSR_DE ? "" : "in");
        for (cnt = 0; cnt < port_to_card(port)->rx_ring_buffers; cnt++)
                printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
+       printk(KERN_CONT "\n");
 
-       printk("\n" KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
+       printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
               "last=%u %sactive",
               sca_inw(get_dmac_tx(port) + CDAL, card),
               sca_inw(get_dmac_tx(port) + EDAL, card),
index 497b003d72392a1ba87968ba3ea8fc47b077f610..f099c34a3ae24ddec276db15ecfa976ae895f40e 100644 (file)
@@ -529,8 +529,9 @@ static void sca_dump_rings(struct net_device *dev)
               sca_in(DSR_RX(port->chan), card) & DSR_DE ? "" : "in");
        for (cnt = 0; cnt < port->card->rx_ring_buffers; cnt++)
                printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
+       printk(KERN_CONT "\n");
 
-       printk("\n" KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
+       printk(KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
               "last=%u %sactive",
               sca_inl(get_dmac_tx(port) + CDAL, card),
               sca_inl(get_dmac_tx(port) + EDAL, card),
index 3fb9dbc88a1aaa277ba631f4c09a19026cdce11d..d14e95a08d66825347721951c480fda1c2967a79 100644 (file)
@@ -326,11 +326,9 @@ sbni_pci_probe( struct net_device  *dev )
                }
 
                if (pci_irq_line <= 0 || pci_irq_line >= nr_irqs)
-                       printk( KERN_WARNING "  WARNING: The PCI BIOS assigned "
-                               "this PCI card to IRQ %d, which is unlikely "
-                               "to work!.\n"
-                               KERN_WARNING " You should use the PCI BIOS "
-                               "setup to assign a valid IRQ line.\n",
+                       printk( KERN_WARNING
+       "  WARNING: The PCI BIOS assigned this PCI card to IRQ %d, which is unlikely to work!.\n"
+       " You should use the PCI BIOS setup to assign a valid IRQ line.\n",
                                pci_irq_line );
 
                /* avoiding re-enable dual adapters */
index c70604f0329edf19e8577d1c4342e5655f020b69..8ce5e4cee168ad12d3fb2e6c091dc486c0df6486 100644 (file)
@@ -5918,20 +5918,19 @@ static int airo_set_essid(struct net_device *dev,
        readSsidRid(local, &SSID_rid);
 
        /* Check if we asked for `any' */
-       if(dwrq->flags == 0) {
+       if (dwrq->flags == 0) {
                /* Just send an empty SSID list */
                memset(&SSID_rid, 0, sizeof(SSID_rid));
        } else {
-               int     index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+               unsigned index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 
                /* Check the size of the string */
-               if(dwrq->length > IW_ESSID_MAX_SIZE) {
+               if (dwrq->length > IW_ESSID_MAX_SIZE)
                        return -E2BIG ;
-               }
+
                /* Check if index is valid */
-               if((index < 0) || (index >= 4)) {
+               if (index >= ARRAY_SIZE(SSID_rid.ssids))
                        return -EINVAL;
-               }
 
                /* Set the SSID */
                memset(SSID_rid.ssids[index].ssid, 0,
@@ -6819,7 +6818,7 @@ static int airo_set_txpow(struct net_device *dev,
                return -EINVAL;
        }
        clear_bit (FLAG_RADIO_OFF, &local->flags);
-       for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++)
+       for (i = 0; i < 8 && cap_rid.txPowerLevels[i]; i++)
                if (v == cap_rid.txPowerLevels[i]) {
                        readConfigRid(local, 1);
                        local->config.txPower = v;
index d26e7b4853156dda0cfcaa597ddbb4eb580817df..eb0337c49546b6e976589a8719d996d8acd17a5c 100644 (file)
@@ -1,5 +1,6 @@
 config ATH_COMMON
        tristate "Atheros Wireless Cards"
+       depends on WLAN_80211
        depends on ATH5K || ATH9K || AR9170_USB
 
 source "drivers/net/wireless/ath/ath5k/Kconfig"
index 9d38cf60a0db2bd8ee1197d99ea6854769aa7357..88c3d8573869dbfab02b3738a26fed16d38d80ee 100644 (file)
@@ -1967,13 +1967,14 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue,
        int ret;
 
        mutex_lock(&ar->mutex);
-       if ((param) && !(queue > __AR9170_NUM_TXQ)) {
+       if (queue < __AR9170_NUM_TXQ) {
                memcpy(&ar->edcf[ar9170_qos_hwmap[queue]],
                       param, sizeof(*param));
 
                ret = ar9170_set_qos(ar);
-       } else
+       } else {
                ret = -EINVAL;
+       }
 
        mutex_unlock(&ar->mutex);
        return ret;
index 754b1f8d8da944155e3a2669499327749de491c9..007eb85fc67e27a4f6b11b9cf94129f142bf3b81 100644 (file)
@@ -598,11 +598,15 @@ static int ar9170_usb_request_firmware(struct ar9170_usb *aru)
 
        err = request_firmware(&aru->init_values, "ar9170-1.fw",
                               &aru->udev->dev);
+       if (err) {
+               dev_err(&aru->udev->dev, "file with init values not found.\n");
+               return err;
+       }
 
        err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev);
        if (err) {
                release_firmware(aru->init_values);
-               dev_err(&aru->udev->dev, "file with init values not found.\n");
+               dev_err(&aru->udev->dev, "firmware file not found.\n");
                return err;
        }
 
index ea045151f95325202b2674159afbcef12eb0ca9b..029c1bc7468ff17edfa5ba95e63ddb395e820643 100644 (file)
@@ -2970,6 +2970,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        if (modparam_nohwcrypt)
                return -EOPNOTSUPP;
 
+       if (sc->opmode == NL80211_IFTYPE_AP)
+               return -EOPNOTSUPP;
+
        switch (key->alg) {
        case ALG_WEP:
        case ALG_TKIP:
index 1aeafb511ddd8715207a74b5fece0a4d32cfb13e..aad259b4c1979c01f698a8354bb6c6d8374fb2c0 100644 (file)
@@ -478,6 +478,18 @@ void ath9k_ani_reset(struct ath_hw *ah)
                        "Reset ANI state opmode %u\n", ah->opmode);
                ah->stats.ast_ani_reset++;
 
+               if (ah->opmode == NL80211_IFTYPE_AP) {
+                       /*
+                        * ath9k_hw_ani_control() will only process items set on
+                        * ah->ani_function
+                        */
+                       if (IS_CHAN_2GHZ(chan))
+                               ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
+                                                   ATH9K_ANI_FIRSTEP_LEVEL);
+                       else
+                               ah->ani_function = 0;
+               }
+
                ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
                ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
                ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
index a2fda702b620e5ae191570c96920448b4945e462..ce0e86c36a82fc9ce3540fb19f9a6b33fa1e5ac9 100644 (file)
@@ -460,7 +460,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
                integer = swab32(eep->modalHeader.antCtrlCommon);
                eep->modalHeader.antCtrlCommon = integer;
 
-               for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+               for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
                        integer = swab32(eep->modalHeader.antCtrlChain[i]);
                        eep->modalHeader.antCtrlChain[i] = integer;
                }
@@ -914,7 +914,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
                        ctlMode, numCtlModes, isHt40CtlMode,
                        (pCtlMode[ctlMode] & EXT_ADDITIVE));
 
-               for (i = 0; (i < AR5416_NUM_CTLS) &&
+               for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) &&
                                pEepData->ctlIndex[i]; i++) {
                        DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
                                "  LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
index b61a071788a50f98347ddaa7f74b778791372c4c..4ccf48e396dfd1529f4114fec7ae9c2d8829efbf 100644 (file)
@@ -355,7 +355,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
                }
 
                if (bf_next == NULL) {
-                       INIT_LIST_HEAD(&bf_head);
+                       /*
+                        * Make sure the last desc is reclaimed if it
+                        * not a holding desc.
+                        */
+                       if (!bf_last->bf_stale)
+                               list_move_tail(&bf->list, &bf_head);
+                       else
+                               INIT_LIST_HEAD(&bf_head);
                } else {
                        ASSERT(!list_empty(bf_q));
                        list_move_tail(&bf->list, &bf_head);
index eef370bd12117643562f4b80b03c6e55b92b79f9..bf3d25ba7be1ffe6c5fe6b65f08ac59326ca4caf 100644 (file)
@@ -474,6 +474,21 @@ ath_regd_init_wiphy(struct ath_regulatory *reg,
        return 0;
 }
 
+/*
+ * Some users have reported their EEPROM programmed with
+ * 0x8000 set, this is not a supported regulatory domain
+ * but since we have more than one user with it we need
+ * a solution for them. We default to 0x64, which is the
+ * default Atheros world regulatory domain.
+ */
+static void ath_regd_sanitize(struct ath_regulatory *reg)
+{
+       if (reg->current_rd != COUNTRY_ERD_FLAG)
+               return;
+       printk(KERN_DEBUG "ath: EEPROM regdomain sanitized\n");
+       reg->current_rd = 0x64;
+}
+
 int
 ath_regd_init(struct ath_regulatory *reg,
              struct wiphy *wiphy,
@@ -486,6 +501,8 @@ ath_regd_init(struct ath_regulatory *reg,
        if (!reg)
                return -EINVAL;
 
+       ath_regd_sanitize(reg);
+
        printk(KERN_DEBUG "ath: EEPROM regdomain: 0x%0x\n", reg->current_rd);
 
        if (!ath_regd_is_eeprom_valid(reg)) {
index f580c2812d91846d611c552295e9722fe09aa06f..40448067e4ccaff3276420d462ca4a8b232dca13 100644 (file)
@@ -648,6 +648,7 @@ struct b43_wl {
        u8 nr_devs;
 
        bool radiotap_enabled;
+       bool radio_enabled;
 
        /* The beacon we are currently using (AP or IBSS mode).
         * This beacon stuff is protected by the irq_lock. */
index 6456afebdba10d3268d6184a76695f253bce135b..e71c8d9cd706ee6b8340d295b86a20817f577d07 100644 (file)
@@ -3497,8 +3497,8 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
        if (phy->ops->set_rx_antenna)
                phy->ops->set_rx_antenna(dev, antenna);
 
-       if (!!conf->radio_enabled != phy->radio_on) {
-               if (conf->radio_enabled) {
+       if (wl->radio_enabled != phy->radio_on) {
+               if (wl->radio_enabled) {
                        b43_software_rfkill(dev, false);
                        b43info(dev->wl, "Radio turned on by software\n");
                        if (!dev->radio_hw_enable) {
@@ -4339,6 +4339,7 @@ static int b43_op_start(struct ieee80211_hw *hw)
        wl->beacon0_uploaded = 0;
        wl->beacon1_uploaded = 0;
        wl->beacon_templates_virgin = 1;
+       wl->radio_enabled = 1;
 
        mutex_lock(&wl->mutex);
 
@@ -4378,6 +4379,7 @@ static void b43_op_stop(struct ieee80211_hw *hw)
        if (b43_status(dev) >= B43_STAT_STARTED)
                b43_wireless_core_stop(dev);
        b43_wireless_core_exit(dev);
+       wl->radio_enabled = 0;
        mutex_unlock(&wl->mutex);
 
        cancel_work_sync(&(wl->txpower_adjust_work));
@@ -4560,6 +4562,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
                B43_WARN_ON(1);
 
        dev->phy.gmode = have_2ghz_phy;
+       dev->phy.radio_on = 1;
        tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
        b43_wireless_core_reset(dev, tmp);
 
index 3cfc30307a27d33f48ed8bbffc3e2da13a2cc686..6c3a74964ab888585e0466424290415fcdf653e0 100644 (file)
@@ -35,6 +35,7 @@
 
 static /*const */ struct pcmcia_device_id b43_pcmcia_tbl[] = {
        PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448),
+       PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476),
        PCMCIA_DEVICE_NULL,
 };
 
index 77fda148ac4684b904e996095b1e7c68d3fa9469..038baa8869e233e038ca97b2919d0954f485d5ec 100644 (file)
@@ -607,6 +607,7 @@ struct b43legacy_wl {
        u8 nr_devs;
 
        bool radiotap_enabled;
+       bool radio_enabled;
 
        /* The beacon we are currently using (AP or IBSS mode).
         * This beacon stuff is protected by the irq_lock. */
index e5136fb65dddb066f3d6ab65b0671bf8386c3b97..c4973c1942bfdda4b5878b46e5120cc12d8c71bc 100644 (file)
@@ -2689,8 +2689,8 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
        /* Antennas for RX and management frame TX. */
        b43legacy_mgmtframe_txantenna(dev, antenna_tx);
 
-       if (!!conf->radio_enabled != phy->radio_on) {
-               if (conf->radio_enabled) {
+       if (wl->radio_enabled != phy->radio_on) {
+               if (wl->radio_enabled) {
                        b43legacy_radio_turn_on(dev);
                        b43legacyinfo(dev->wl, "Radio turned on by software\n");
                        if (!dev->radio_hw_enable)
@@ -3441,6 +3441,7 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
        wl->beacon0_uploaded = 0;
        wl->beacon1_uploaded = 0;
        wl->beacon_templates_virgin = 1;
+       wl->radio_enabled = 1;
 
        mutex_lock(&wl->mutex);
 
@@ -3479,6 +3480,7 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw)
        if (b43legacy_status(dev) >= B43legacy_STAT_STARTED)
                b43legacy_wireless_core_stop(dev);
        b43legacy_wireless_core_exit(dev);
+       wl->radio_enabled = 0;
        mutex_unlock(&wl->mutex);
 }
 
@@ -3620,6 +3622,7 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev)
                have_bphy = 1;
 
        dev->phy.gmode = (have_gphy || have_bphy);
+       dev->phy.radio_on = 1;
        tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0;
        b43legacy_wireless_core_reset(dev, tmp);
 
index 44c29b3f67285ab608d3bf254db3498be3854962..f593fbbb4e525c08c82513005b58e42be55e712b 100644 (file)
@@ -2874,45 +2874,27 @@ static int ipw_fw_dma_add_command_block(struct ipw_priv *priv,
        return 0;
 }
 
-static int ipw_fw_dma_add_buffer(struct ipw_priv *priv,
-                                u32 src_phys, u32 dest_address, u32 length)
+static int ipw_fw_dma_add_buffer(struct ipw_priv *priv, dma_addr_t *src_address,
+                                int nr, u32 dest_address, u32 len)
 {
-       u32 bytes_left = length;
-       u32 src_offset = 0;
-       u32 dest_offset = 0;
-       int status = 0;
+       int ret, i;
+       u32 size;
+
        IPW_DEBUG_FW(">> \n");
-       IPW_DEBUG_FW_INFO("src_phys=0x%x dest_address=0x%x length=0x%x\n",
-                         src_phys, dest_address, length);
-       while (bytes_left > CB_MAX_LENGTH) {
-               status = ipw_fw_dma_add_command_block(priv,
-                                                     src_phys + src_offset,
-                                                     dest_address +
-                                                     dest_offset,
-                                                     CB_MAX_LENGTH, 0, 0);
-               if (status) {
+       IPW_DEBUG_FW_INFO("nr=%d dest_address=0x%x len=0x%x\n",
+                         nr, dest_address, len);
+
+       for (i = 0; i < nr; i++) {
+               size = min_t(u32, len - i * CB_MAX_LENGTH, CB_MAX_LENGTH);
+               ret = ipw_fw_dma_add_command_block(priv, src_address[i],
+                                                  dest_address +
+                                                  i * CB_MAX_LENGTH, size,
+                                                  0, 0);
+               if (ret) {
                        IPW_DEBUG_FW_INFO(": Failed\n");
                        return -1;
                } else
                        IPW_DEBUG_FW_INFO(": Added new cb\n");
-
-               src_offset += CB_MAX_LENGTH;
-               dest_offset += CB_MAX_LENGTH;
-               bytes_left -= CB_MAX_LENGTH;
-       }
-
-       /* add the buffer tail */
-       if (bytes_left > 0) {
-               status =
-                   ipw_fw_dma_add_command_block(priv, src_phys + src_offset,
-                                                dest_address + dest_offset,
-                                                bytes_left, 0, 0);
-               if (status) {
-                       IPW_DEBUG_FW_INFO(": Failed on the buffer tail\n");
-                       return -1;
-               } else
-                       IPW_DEBUG_FW_INFO
-                           (": Adding new cb - the buffer tail\n");
        }
 
        IPW_DEBUG_FW("<< \n");
@@ -3160,59 +3142,91 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
 
 static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len)
 {
-       int rc = -1;
+       int ret = -1;
        int offset = 0;
        struct fw_chunk *chunk;
-       dma_addr_t shared_phys;
-       u8 *shared_virt;
+       int total_nr = 0;
+       int i;
+       struct pci_pool *pool;
+       u32 *virts[CB_NUMBER_OF_ELEMENTS_SMALL];
+       dma_addr_t phys[CB_NUMBER_OF_ELEMENTS_SMALL];
 
        IPW_DEBUG_TRACE("<< : \n");
-       shared_virt = pci_alloc_consistent(priv->pci_dev, len, &shared_phys);
 
-       if (!shared_virt)
+       pool = pci_pool_create("ipw2200", priv->pci_dev, CB_MAX_LENGTH, 0, 0);
+       if (!pool) {
+               IPW_ERROR("pci_pool_create failed\n");
                return -ENOMEM;
-
-       memmove(shared_virt, data, len);
+       }
 
        /* Start the Dma */
-       rc = ipw_fw_dma_enable(priv);
+       ret = ipw_fw_dma_enable(priv);
 
        /* the DMA is already ready this would be a bug. */
        BUG_ON(priv->sram_desc.last_cb_index > 0);
 
        do {
+               u32 chunk_len;
+               u8 *start;
+               int size;
+               int nr = 0;
+
                chunk = (struct fw_chunk *)(data + offset);
                offset += sizeof(struct fw_chunk);
+               chunk_len = le32_to_cpu(chunk->length);
+               start = data + offset;
+
+               nr = (chunk_len + CB_MAX_LENGTH - 1) / CB_MAX_LENGTH;
+               for (i = 0; i < nr; i++) {
+                       virts[total_nr] = pci_pool_alloc(pool, GFP_KERNEL,
+                                                        &phys[total_nr]);
+                       if (!virts[total_nr]) {
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+                       size = min_t(u32, chunk_len - i * CB_MAX_LENGTH,
+                                    CB_MAX_LENGTH);
+                       memcpy(virts[total_nr], start, size);
+                       start += size;
+                       total_nr++;
+                       /* We don't support fw chunk larger than 64*8K */
+                       BUG_ON(total_nr > CB_NUMBER_OF_ELEMENTS_SMALL);
+               }
+
                /* build DMA packet and queue up for sending */
                /* dma to chunk->address, the chunk->length bytes from data +
                 * offeset*/
                /* Dma loading */
-               rc = ipw_fw_dma_add_buffer(priv, shared_phys + offset,
-                                          le32_to_cpu(chunk->address),
-                                          le32_to_cpu(chunk->length));
-               if (rc) {
+               ret = ipw_fw_dma_add_buffer(priv, &phys[total_nr - nr],
+                                           nr, le32_to_cpu(chunk->address),
+                                           chunk_len);
+               if (ret) {
                        IPW_DEBUG_INFO("dmaAddBuffer Failed\n");
                        goto out;
                }
 
-               offset += le32_to_cpu(chunk->length);
+               offset += chunk_len;
        } while (offset < len);
 
        /* Run the DMA and wait for the answer */
-       rc = ipw_fw_dma_kick(priv);
-       if (rc) {
+       ret = ipw_fw_dma_kick(priv);
+       if (ret) {
                IPW_ERROR("dmaKick Failed\n");
                goto out;
        }
 
-       rc = ipw_fw_dma_wait(priv);
-       if (rc) {
+       ret = ipw_fw_dma_wait(priv);
+       if (ret) {
                IPW_ERROR("dmaWaitSync Failed\n");
                goto out;
        }
-      out:
-       pci_free_consistent(priv->pci_dev, len, shared_virt, shared_phys);
-       return rc;
+ out:
+       for (i = 0; i < total_nr; i++)
+               pci_pool_free(pool, virts[i], phys[i]);
+
+       pci_pool_destroy(pool);
+
+       return ret;
 }
 
 /* stop nic */
@@ -6226,7 +6240,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv,
                        };
 
                        u8 channel;
-                       while (channel_index < IPW_SCAN_CHANNELS) {
+                       while (channel_index < IPW_SCAN_CHANNELS - 1) {
                                channel =
                                    priv->speed_scan[priv->speed_scan_pos];
                                if (channel == 0) {
index fbb3a573463e29c882d9576d442ae75dba1e4e93..2de6471d4be9f943a36d99d837f8839f48fafa6a 100644 (file)
@@ -112,7 +112,7 @@ enum iwl3945_antenna {
 #define IWL_TX_FIFO_NONE       7
 
 /* Minimum number of queues. MAX_NUM is defined in hw specific files */
-#define IWL_MIN_NUM_QUEUES     4
+#define IWL39_MIN_NUM_QUEUES   4
 
 #define IEEE80211_DATA_LEN              2304
 #define IEEE80211_4ADDR_LEN             30
index 6d1519e1f011ad9f565a9256b3a6175dc54bb424..355f50ea7fef26ae07e42851e12c0203e26a3464 100644 (file)
@@ -2675,12 +2675,10 @@ static ssize_t show_power_level(struct device *d,
                                struct device_attribute *attr, char *buf)
 {
        struct iwl_priv *priv = dev_get_drvdata(d);
-       int mode = priv->power_data.user_power_setting;
        int level = priv->power_data.power_mode;
        char *p = buf;
 
-       p += sprintf(p, "INDEX:%d\t", level);
-       p += sprintf(p, "USER:%d\n", mode);
+       p += sprintf(p, "%d\n", level);
        return p - buf + 1;
 }
 
index 6ab07165ea28af4a226cbf7d29d6b9d58b6fa8fe..18b135f510e5dc86f5a08d1e5fa5881de5c85e65 100644 (file)
@@ -1332,6 +1332,9 @@ int iwl_setup_mac(struct iwl_priv *priv)
 
        hw->wiphy->custom_regulatory = true;
 
+       /* Firmware does not support this */
+       hw->wiphy->disable_beacon_hints = true;
+
        hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
        /* we create the 802.11 header and a zero-length SSID element */
        hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
index 11e08c068917441bcdead648fe23ef1352def143..ca00cc8ad4c77d96c7e5a4edaf5eeed1f8ea8414 100644 (file)
@@ -308,18 +308,18 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
                return -ENODATA;
        }
 
+       ptr = priv->eeprom;
+       if (!ptr) {
+               IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
+               return -ENOMEM;
+       }
+
        /* 4 characters for byte 0xYY */
        buf = kzalloc(buf_size, GFP_KERNEL);
        if (!buf) {
                IWL_ERR(priv, "Can not allocate Buffer\n");
                return -ENOMEM;
        }
-
-       ptr = priv->eeprom;
-       if (!ptr) {
-               IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
-               return -ENOMEM;
-       }
        pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n",
                        (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
                        ? "OTP" : "EEPROM");
index e2d620f0b6e866eb327ae531969b040c201d8b37..650e20af20fa8c07b83524cfb67997f06c9289d5 100644 (file)
@@ -258,8 +258,10 @@ struct iwl_channel_info {
 #define IWL_TX_FIFO_HCCA_2     6
 #define IWL_TX_FIFO_NONE       7
 
-/* Minimum number of queues. MAX_NUM is defined in hw specific files */
-#define IWL_MIN_NUM_QUEUES     4
+/* Minimum number of queues. MAX_NUM is defined in hw specific files.
+ * Set the minimum to accommodate the 4 standard TX queues, 1 command
+ * queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */
+#define IWL_MIN_NUM_QUEUES     10
 
 /* Power management (not Tx power) structures */
 
index 2addf735b1934e3ac3a34c34848b733e3f469fbd..ffd5c61a75532d94d0a4d6f49dc2ebe76a4a5320 100644 (file)
@@ -566,6 +566,8 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
        unsigned long flags;
 
        spin_lock_irqsave(&priv->sta_lock, flags);
+       IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
+                     keyconf->keyidx);
 
        if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table))
                IWL_ERR(priv, "index %d not used in uCode key table.\n",
@@ -573,6 +575,11 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
 
        priv->default_wep_key--;
        memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0]));
+       if (iwl_is_rfkill(priv)) {
+               IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n");
+               spin_unlock_irqrestore(&priv->sta_lock, flags);
+               return 0;
+       }
        ret = iwl_send_static_wepkey_cmd(priv, 1);
        IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
                      keyconf->keyidx, ret);
@@ -853,6 +860,11 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
        priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
        priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 
+       if (iwl_is_rfkill(priv)) {
+               IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled. \n");
+               spin_unlock_irqrestore(&priv->sta_lock, flags);
+               return 0;
+       }
        ret =  iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
        spin_unlock_irqrestore(&priv->sta_lock, flags);
        return ret;
index 85ae7a62109cd29475ce2b89e68468b05d25c484..2e89040e63be69c156786bfb09fbc7c8812fc1fa 100644 (file)
@@ -720,8 +720,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                goto drop_unlock;
        }
 
-       spin_unlock_irqrestore(&priv->lock, flags);
-
        hdr_len = ieee80211_hdrlen(fc);
 
        /* Find (or create) index into station table for destination station */
@@ -729,7 +727,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        if (sta_id == IWL_INVALID_STATION) {
                IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
                               hdr->addr1);
-               goto drop;
+               goto drop_unlock;
        }
 
        IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
@@ -750,14 +748,17 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                        txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
                        swq_id = iwl_virtual_agg_queue_num(swq_id, txq_id);
                }
-               priv->stations[sta_id].tid[tid].tfds_in_queue++;
        }
 
        txq = &priv->txq[txq_id];
        q = &txq->q;
        txq->swq_id = swq_id;
 
-       spin_lock_irqsave(&priv->lock, flags);
+       if (unlikely(iwl_queue_space(q) < q->high_mark))
+               goto drop_unlock;
+
+       if (ieee80211_is_data_qos(fc))
+               priv->stations[sta_id].tid[tid].tfds_in_queue++;
 
        /* Set up driver data for this TFD */
        memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
@@ -872,7 +873,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
        iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
 
        /* Set up entry for this TFD in Tx byte-count array */
-       priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq,
+       if (info->flags & IEEE80211_TX_CTL_AMPDU)
+               priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq,
                                                     le16_to_cpu(tx_cmd->len));
 
        pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
@@ -901,7 +903,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
 drop_unlock:
        spin_unlock_irqrestore(&priv->lock, flags);
-drop:
        return -1;
 }
 EXPORT_SYMBOL(iwl_tx_skb);
@@ -1170,6 +1171,8 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
                IWL_ERR(priv, "Start AGG on invalid station\n");
                return -ENXIO;
        }
+       if (unlikely(tid >= MAX_TID_COUNT))
+               return -EINVAL;
 
        if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) {
                IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n");
index cb9bd4c8f25e3bdbb24d4f8cbc10164515fa5cb1..523843369ca2477154b7274404b719bbd15510ed 100644 (file)
@@ -3643,12 +3643,10 @@ static ssize_t show_power_level(struct device *d,
                                struct device_attribute *attr, char *buf)
 {
        struct iwl_priv *priv = dev_get_drvdata(d);
-       int mode = priv->power_data.user_power_setting;
        int level = priv->power_data.power_mode;
        char *p = buf;
 
-       p += sprintf(p, "INDEX:%d\t", level);
-       p += sprintf(p, "USER:%d\n", mode);
+       p += sprintf(p, "%d\n", level);
        return p - buf + 1;
 }
 
@@ -3970,6 +3968,9 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
 
        hw->wiphy->custom_regulatory = true;
 
+       /* Firmware does not support this */
+       hw->wiphy->disable_beacon_hints = true;
+
        hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
        /* we create the 802.11 header and a zero-length SSID element */
        hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
@@ -4020,10 +4021,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        SET_IEEE80211_DEV(hw, &pdev->dev);
 
        if ((iwl3945_mod_params.num_of_queues > IWL39_MAX_NUM_QUEUES) ||
-            (iwl3945_mod_params.num_of_queues < IWL_MIN_NUM_QUEUES)) {
+            (iwl3945_mod_params.num_of_queues < IWL39_MIN_NUM_QUEUES)) {
                IWL_ERR(priv,
                        "invalid queues_num, should be between %d and %d\n",
-                       IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES);
+                       IWL39_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES);
                err = -EINVAL;
                goto out_ieee80211_free_hw;
        }
index 1eccb6df46dd948664d75470172532b60211e6d4..030401d367d30aa7b82a894464fc2d973556fcef 100644 (file)
@@ -4,6 +4,15 @@ config IWM
        depends on CFG80211
        select WIRELESS_EXT
        select FW_LOADER
+       help
+         The Intel Wireless Multicomm 3200 hardware is a combo
+         card with GPS, Bluetooth, WiMax and 802.11 radios. It
+         runs over SDIO and is typically found on Moorestown
+         based platform. This driver takes care of the 802.11
+         part, which is a fullmac one.
+
+         If you choose to build it as a module, it'll be called
+         iwmc3200wifi.ko.
 
 config IWM_DEBUG
        bool "Enable full debugging output in iwmc3200wifi"
index 834a7f544e5d761d57e60de5abc72d509e06ade2..e2334d1235993812b35d1c2e39bc68fcb46d331f 100644 (file)
@@ -220,6 +220,7 @@ int iwm_store_rxiq_calib_result(struct iwm_priv *iwm)
        eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ);
        if (IS_ERR(eeprom_rxiq)) {
                IWM_ERR(iwm, "Couldn't access EEPROM RX IQ entry\n");
+               kfree(rxiq);
                return PTR_ERR(eeprom_rxiq);
        }
 
index aaa20c6885c8774c4e2af9e30164034456fb16f4..bf294e41753b02917ab1bd95db1c76c780df4061 100644 (file)
@@ -106,10 +106,8 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev,
        int ret = 0;
 
        wdev = iwm_wdev_alloc(sizeof_bus, dev);
-       if (!wdev) {
-               dev_err(dev, "no memory for wireless device instance\n");
-               return ERR_PTR(-ENOMEM);
-       }
+       if (IS_ERR(wdev))
+               return wdev;
 
        iwm = wdev_to_iwm(wdev);
        iwm->bus_ops = if_ops;
@@ -151,8 +149,8 @@ void iwm_if_free(struct iwm_priv *iwm)
                return;
 
        free_netdev(iwm_to_ndev(iwm));
-       iwm_wdev_free(iwm);
        iwm_priv_deinit(iwm);
+       iwm_wdev_free(iwm);
 }
 
 int iwm_if_add(struct iwm_priv *iwm)
index 9a5408e7d94a1a3949fc35a5a12b0e206631d28d..5c6968101f0d1ce8dea7d50802175e1d940827b5 100644 (file)
@@ -47,7 +47,7 @@ static u8 lbs_region_2_code(u8 *region)
 {
        u8 i;
 
-       for (i = 0; region[i] && i < COUNTRY_CODE_LEN; i++)
+       for (i = 0; i < COUNTRY_CODE_LEN && region[i]; i++)
                region[i] = toupper(region[i]);
 
        for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
index 01db705a38ec6da97629512949cec0b584c11b64..685098148e10e137a2cf14d47d491fc7a4973975 100644 (file)
@@ -135,8 +135,14 @@ int lbs_update_hw_spec(struct lbs_private *priv)
        /* Clamp region code to 8-bit since FW spec indicates that it should
         * only ever be 8-bit, even though the field size is 16-bit.  Some firmware
         * returns non-zero high 8 bits here.
+        *
+        * Firmware version 4.0.102 used in CF8381 has region code shifted.  We
+        * need to check for this problem and handle it properly.
         */
-       priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
+       if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V4)
+               priv->regioncode = (le16_to_cpu(cmd.regioncode) >> 8) & 0xFF;
+       else
+               priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
 
        for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
                /* use the region code to search for the index */
index 48da157d6cdab3141ad95c3a2ae842ae3c2cae74..72f3479a4d702ff8f1ec90955f2e6a0dc14cee26 100644 (file)
@@ -234,6 +234,8 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
 /** Mesh enable bit in FW capability */
 #define MESH_CAPINFO_ENABLE_MASK                       (1<<16)
 
+/** FW definition from Marvell v4 */
+#define MRVL_FW_V4                                     (0x04)
 /** FW definition from Marvell v5 */
 #define MRVL_FW_V5                                     (0x05)
 /** FW definition from Marvell v10 */
index 0a2e29140addb5ba9375259573912f22cc34e054..c8a1998d4744270021931124e7650a93bd3dea5b 100644 (file)
@@ -56,8 +56,8 @@ struct rxpd {
                        u8 bss_type;
                        /* BSS number */
                        u8 bss_num;
-               } bss;
-       } u;
+               } __attribute__ ((packed)) bss;
+       } __attribute__ ((packed)) u;
 
        /* SNR */
        u8 snr;
index 601b54249677412cd5f797be38311dbfcfdf20b4..6c95af3023ccf366897726c5fa460a3d5933d72f 100644 (file)
@@ -5,6 +5,7 @@
   *  for sending scan commands to the firmware.
   */
 #include <linux/types.h>
+#include <linux/kernel.h>
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 #include <asm/unaligned.h>
@@ -876,7 +877,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
        iwe.u.bitrate.disabled = 0;
        iwe.u.bitrate.value = 0;
 
-       for (j = 0; bss->rates[j] && (j < sizeof(bss->rates)); j++) {
+       for (j = 0; j < ARRAY_SIZE(bss->rates) && bss->rates[j]; j++) {
                /* Bit rate given in 500 kb/s units */
                iwe.u.bitrate.value = bss->rates[j] * 500000;
                current_val = iwe_stream_add_value(info, start, current_val,
index e789c6e9938cb60e62a918b2f5e2083af7251591..7916ca3f84c8892420bcca591c9c3c122386a213 100644 (file)
@@ -418,6 +418,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
                        continue;
 
                if (!data2->started || !hwsim_ps_rx_ok(data2, skb) ||
+                   !data->channel || !data2->channel ||
                    data->channel->center_freq != data2->channel->center_freq ||
                    !(data->group & data2->group))
                        continue;
@@ -708,7 +709,7 @@ static const struct ieee80211_ops mac80211_hwsim_ops =
 static void mac80211_hwsim_free(void)
 {
        struct list_head tmplist, *i, *tmp;
-       struct mac80211_hwsim_data *data;
+       struct mac80211_hwsim_data *data, *tmpdata;
 
        INIT_LIST_HEAD(&tmplist);
 
@@ -717,7 +718,7 @@ static void mac80211_hwsim_free(void)
                list_move(i, &tmplist);
        spin_unlock_bh(&hwsim_radio_lock);
 
-       list_for_each_entry(data, &tmplist, list) {
+       list_for_each_entry_safe(data, tmpdata, &tmplist, list) {
                debugfs_remove(data->debugfs_group);
                debugfs_remove(data->debugfs_ps);
                debugfs_remove(data->debugfs);
@@ -1166,8 +1167,8 @@ static void __exit exit_mac80211_hwsim(void)
 {
        printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n");
 
-       unregister_netdev(hwsim_mon);
        mac80211_hwsim_free();
+       unregister_netdev(hwsim_mon);
 }
 
 
index a263d5c84c0874857b8ee02243cff89bc9e8eee6..83967afe0821681ca7140c08fac2d47bd3d4419e 100644 (file)
@@ -261,7 +261,7 @@ struct mwl8k_vif {
         */
 };
 
-#define MWL8K_VIF(_vif) (struct mwl8k_vif *)(&((_vif)->drv_priv))
+#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
 
 static const struct ieee80211_channel mwl8k_channels[] = {
        { .center_freq = 2412, .hw_value = 1, },
@@ -1012,6 +1012,8 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
                rmb();
 
                skb = rxq->rx_skb[rxq->rx_head];
+               if (skb == NULL)
+                       break;
                rxq->rx_skb[rxq->rx_head] = NULL;
 
                rxq->rx_head = (rxq->rx_head + 1) % MWL8K_RX_DESCS;
@@ -1591,6 +1593,9 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
        timeout = wait_for_completion_timeout(&cmd_wait,
                                msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS));
 
+       pci_unmap_single(priv->pdev, dma_addr, dma_size,
+                                       PCI_DMA_BIDIRECTIONAL);
+
        result = &cmd->result;
        if (!timeout) {
                spin_lock_irq(&priv->fw_lock);
@@ -1610,8 +1615,6 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
                               *result);
        }
 
-       pci_unmap_single(priv->pdev, dma_addr, dma_size,
-                                       PCI_DMA_BIDIRECTIONAL);
        return rc;
 }
 
@@ -1654,18 +1657,18 @@ static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw)
        memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr));
        cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
        cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rx_desc_dma);
-       cmd->num_tx_queues = MWL8K_TX_QUEUES;
+       cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES);
        for (i = 0; i < MWL8K_TX_QUEUES; i++)
                cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].tx_desc_dma);
-       cmd->num_tx_desc_per_queue = MWL8K_TX_DESCS;
-       cmd->total_rx_desc = MWL8K_RX_DESCS;
+       cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS);
+       cmd->total_rx_desc = cpu_to_le32(MWL8K_RX_DESCS);
 
        rc = mwl8k_post_cmd(hw, &cmd->header);
 
        if (!rc) {
                SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr);
                priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
-               priv->fw_rev = cmd->fw_rev;
+               priv->fw_rev = le32_to_cpu(cmd->fw_rev);
                priv->hw_rev = cmd->hw_rev;
                priv->region_code = le16_to_cpu(cmd->region_code);
        }
@@ -3216,15 +3219,19 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt)
        struct dev_addr_list *mclist = worker->mclist;
 
        struct mwl8k_priv *priv = hw->priv;
-       struct mwl8k_vif *mv_vif;
        int rc = 0;
 
        if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
                if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
                        rc = mwl8k_cmd_set_pre_scan(hw);
                else {
-                       mv_vif = MWL8K_VIF(priv->vif);
-                       rc = mwl8k_cmd_set_post_scan(hw, mv_vif->bssid);
+                       u8 *bssid;
+
+                       bssid = "\x00\x00\x00\x00\x00\x00";
+                       if (priv->vif != NULL)
+                               bssid = MWL8K_VIF(priv->vif)->bssid;
+
+                       rc = mwl8k_cmd_set_post_scan(hw, bssid);
                }
        }
 
@@ -3726,6 +3733,8 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev)
 
        ieee80211_stop_queues(hw);
 
+       ieee80211_unregister_hw(hw);
+
        /* Remove tx reclaim tasklet */
        tasklet_kill(&priv->tx_reclaim_task);
 
@@ -3739,8 +3748,6 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev)
        for (i = 0; i < MWL8K_TX_QUEUES; i++)
                mwl8k_txq_reclaim(hw, i, 1);
 
-       ieee80211_unregister_hw(hw);
-
        for (i = 0; i < MWL8K_TX_QUEUES; i++)
                mwl8k_txq_deinit(hw, i);
 
index 632fac86a3085ee33713a1fb2f718e50527da053..b3946272c72e75ed4c3fcfebe644c8404a46d19e 100644 (file)
@@ -70,7 +70,7 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
        int err = 0;
        u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE];
 
-       if ((key < 0) || (key > 4))
+       if ((key < 0) || (key >= 4))
                return -EINVAL;
 
        err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
index 345593c4accbe3c2f007acd9836e66a9ff8375e0..a370e510f19f8e3800f8f30d55eda1587032bbf6 100644 (file)
@@ -2521,6 +2521,8 @@ static const struct net_device_ops orinoco_netdev_ops = {
        .ndo_start_xmit         = orinoco_xmit,
        .ndo_set_multicast_list = orinoco_set_multicast_list,
        .ndo_change_mtu         = orinoco_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
        .ndo_tx_timeout         = orinoco_tx_timeout,
        .ndo_get_stats          = orinoco_get_stats,
 };
@@ -2555,7 +2557,6 @@ struct net_device
        priv->wireless_data.spy_data = &priv->spy_data;
        dev->wireless_data = &priv->wireless_data;
 #endif
-       /* we use the default eth_mac_addr for setting the MAC addr */
 
        /* Reserve space in skb for the SNAP header */
        dev->hard_header_len += ENCAPS_OVERHEAD;
index b618bd14583f9489143de1e1654dad3a290c2598..22ca122bd798c7d37ae3a7da4476b64dbacde233 100644 (file)
@@ -823,30 +823,30 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
        struct p54_tx_info *range;
        unsigned long flags;
 
-       if (unlikely(!skb || !dev || skb_queue_empty(&priv->tx_queue)))
+       if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue)))
                return;
 
-       /* There used to be a check here to see if the SKB was on the
-        * TX queue or not.  This can never happen because all SKBs we
-        * see here successfully went through p54_assign_address()
-        * which means the SKB is on the ->tx_queue.
+       /*
+        * don't try to free an already unlinked skb
         */
+       if (unlikely((!skb->next) || (!skb->prev)))
+               return;
 
        spin_lock_irqsave(&priv->tx_queue.lock, flags);
        info = IEEE80211_SKB_CB(skb);
        range = (void *)info->rate_driver_data;
-       if (!skb_queue_is_first(&priv->tx_queue, skb)) {
+       if (skb->prev != (struct sk_buff *)&priv->tx_queue) {
                struct ieee80211_tx_info *ni;
                struct p54_tx_info *mr;
 
-               ni = IEEE80211_SKB_CB(skb_queue_prev(&priv->tx_queue, skb));
+               ni = IEEE80211_SKB_CB(skb->prev);
                mr = (struct p54_tx_info *)ni->rate_driver_data;
        }
-       if (!skb_queue_is_last(&priv->tx_queue, skb)) {
+       if (skb->next != (struct sk_buff *)&priv->tx_queue) {
                struct ieee80211_tx_info *ni;
                struct p54_tx_info *mr;
 
-               ni = IEEE80211_SKB_CB(skb_queue_next(&priv->tx_queue, skb));
+               ni = IEEE80211_SKB_CB(skb->next);
                mr = (struct p54_tx_info *)ni->rate_driver_data;
        }
        __skb_unlink(skb, &priv->tx_queue);
@@ -864,13 +864,15 @@ static struct sk_buff *p54_find_tx_entry(struct ieee80211_hw *dev,
        unsigned long flags;
 
        spin_lock_irqsave(&priv->tx_queue.lock, flags);
-       skb_queue_walk(&priv->tx_queue, entry) {
+       entry = priv->tx_queue.next;
+       while (entry != (struct sk_buff *)&priv->tx_queue) {
                struct p54_hdr *hdr = (struct p54_hdr *) entry->data;
 
                if (hdr->req_id == req_id) {
                        spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
                        return entry;
                }
+               entry = entry->next;
        }
        spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
        return NULL;
@@ -888,33 +890,36 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
        int count, idx;
 
        spin_lock_irqsave(&priv->tx_queue.lock, flags);
-       skb_queue_walk(&priv->tx_queue, entry) {
+       entry = (struct sk_buff *) priv->tx_queue.next;
+       while (entry != (struct sk_buff *)&priv->tx_queue) {
                struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
                struct p54_hdr *entry_hdr;
                struct p54_tx_data *entry_data;
                unsigned int pad = 0, frame_len;
 
                range = (void *)info->rate_driver_data;
-               if (range->start_addr != addr)
+               if (range->start_addr != addr) {
+                       entry = entry->next;
                        continue;
+               }
 
-               if (!skb_queue_is_last(&priv->tx_queue, entry)) {
+               if (entry->next != (struct sk_buff *)&priv->tx_queue) {
                        struct ieee80211_tx_info *ni;
                        struct p54_tx_info *mr;
 
-                       ni = IEEE80211_SKB_CB(skb_queue_next(&priv->tx_queue,
-                                                            entry));
+                       ni = IEEE80211_SKB_CB(entry->next);
                        mr = (struct p54_tx_info *)ni->rate_driver_data;
                }
 
                __skb_unlink(entry, &priv->tx_queue);
-               spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
 
                frame_len = entry->len;
                entry_hdr = (struct p54_hdr *) entry->data;
                entry_data = (struct p54_tx_data *) entry_hdr->data;
-               priv->tx_stats[entry_data->hw_queue].len--;
+               if (priv->tx_stats[entry_data->hw_queue].len)
+                       priv->tx_stats[entry_data->hw_queue].len--;
                priv->stats.dot11ACKFailureCount += payload->tries - 1;
+               spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
 
                /*
                 * Frames in P54_QUEUE_FWSCAN and P54_QUEUE_BEACON are
@@ -1164,21 +1169,23 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
                }
        }
 
-       skb_queue_walk(&priv->tx_queue, entry) {
+       entry = priv->tx_queue.next;
+       while (left--) {
                u32 hole_size;
                info = IEEE80211_SKB_CB(entry);
                range = (void *)info->rate_driver_data;
                hole_size = range->start_addr - last_addr;
                if (!target_skb && hole_size >= len) {
-                       target_skb = skb_queue_prev(&priv->tx_queue, entry);
+                       target_skb = entry->prev;
                        hole_size -= len;
                        target_addr = last_addr;
                }
                largest_hole = max(largest_hole, hole_size);
                last_addr = range->end_addr;
+               entry = entry->next;
        }
        if (!target_skb && priv->rx_end - last_addr >= len) {
-               target_skb = skb_peek_tail(&priv->tx_queue);
+               target_skb = priv->tx_queue.prev;
                largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
                if (!skb_queue_empty(&priv->tx_queue)) {
                        info = IEEE80211_SKB_CB(target_skb);
@@ -2084,6 +2091,7 @@ out:
 static void p54_stop(struct ieee80211_hw *dev)
 {
        struct p54_common *priv = dev->priv;
+       struct sk_buff *skb;
 
        mutex_lock(&priv->conf_mutex);
        priv->mode = NL80211_IFTYPE_UNSPECIFIED;
@@ -2098,7 +2106,8 @@ static void p54_stop(struct ieee80211_hw *dev)
                p54_tx_cancel(dev, priv->cached_beacon);
 
        priv->stop(dev);
-       skb_queue_purge(&priv->tx_queue);
+       while ((skb = skb_dequeue(&priv->tx_queue)))
+               kfree_skb(skb);
        priv->cached_beacon = NULL;
        priv->tsf_high32 = priv->tsf_low32 = 0;
        mutex_unlock(&priv->conf_mutex);
index 83116baeb110082b2f94e3bb40186f8e98f97ad8..72c7dbd39d0ad48cfa1309229931bc69b33824ef 100644 (file)
@@ -635,7 +635,7 @@ static int __devinit p54spi_probe(struct spi_device *spi)
 
        hw = p54_init_common(sizeof(*priv));
        if (!hw) {
-               dev_err(&priv->spi->dev, "could not alloc ieee80211_hw");
+               dev_err(&spi->dev, "could not alloc ieee80211_hw");
                return -ENOMEM;
        }
 
index b10b0383dfa5ecaa9b6970fc51f36e80bb0a57be..698b11b1cadbb28fd09155f767063d30dc9c3e71 100644 (file)
@@ -2427,11 +2427,10 @@ static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)
 
 #ifdef PCMCIA_DEBUG
        if (pc_debug > 3) {
-               int i;
-               printk(KERN_DEBUG "skb->data before untranslate");
-               for (i = 0; i < 64; i++)
-                       printk("%02x ", skb->data[i]);
-               printk("\n" KERN_DEBUG
+               print_hex_dump(KERN_DEBUG, "skb->data before untranslate: ",
+                              DUMP_PREFIX_NONE, 16, 1,
+                              skb->data, 64, true);
+               printk(KERN_DEBUG
                       "type = %08x, xsap = %02x%02x%02x, org = %02x02x02x\n",
                       ntohs(type), psnap->dsap, psnap->ssap, psnap->ctrl,
                       psnap->org[0], psnap->org[1], psnap->org[2]);
index 66daf68ff0ee9e35de4d0933413198432381cfbf..ce75426764a1538124eec73f20c3cac2859c06e0 100644 (file)
@@ -1550,7 +1550,9 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
        rt2500usb_register_read(rt2x00dev, MAC_CSR0, &reg);
        rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
 
-       if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0)) {
+       if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0) ||
+           rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
+
                ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
                return -ENODEV;
        }
index a498dde024e1b58c55555e00d349a5cc28846218..49c9e2c1433d98cc82c16346242fc68eb0548897 100644 (file)
@@ -849,13 +849,15 @@ struct rt2x00_dev {
 static inline void rt2x00_rf_read(struct rt2x00_dev *rt2x00dev,
                                  const unsigned int word, u32 *data)
 {
-       *data = rt2x00dev->rf[word];
+       BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32));
+       *data = rt2x00dev->rf[word - 1];
 }
 
 static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev,
                                   const unsigned int word, u32 data)
 {
-       rt2x00dev->rf[word] = data;
+       BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32));
+       rt2x00dev->rf[word - 1] = data;
 }
 
 /*
index 294250e294dd548bb295c620e6d52c799f03021f..87a95588a8e3c69793ee6c437a3ba242427eed07 100644 (file)
@@ -869,6 +869,9 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
        priv->aifsn[3] = 3; /* AIFSN[AC_BE] */
        rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0);
 
+       /* ENEDCA flag must always be set, transmit issues? */
+       rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_ENEDCA);
+
        return 0;
 }
 
@@ -1173,13 +1176,16 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev,
                        rtl818x_iowrite8(priv, &priv->map->BSSID[i],
                                         info->bssid[i]);
 
+               if (priv->is_rtl8187b)
+                       reg = RTL818X_MSR_ENEDCA;
+               else
+                       reg = 0;
+
                if (is_valid_ether_addr(info->bssid)) {
-                       reg = RTL818X_MSR_INFRA;
-                       if (priv->is_rtl8187b)
-                               reg |= RTL818X_MSR_ENEDCA;
+                       reg |= RTL818X_MSR_INFRA;
                        rtl818x_iowrite8(priv, &priv->map->MSR, reg);
                } else {
-                       reg = RTL818X_MSR_NO_LINK;
+                       reg |= RTL818X_MSR_NO_LINK;
                        rtl818x_iowrite8(priv, &priv->map->MSR, reg);
                }
 
index b4425359224348c59f15fdb6a9a3031bc232406d..cf9f899fe0e65dc876637db60d87e1e6013a49e7 100644 (file)
@@ -208,11 +208,12 @@ void rtl8187_leds_exit(struct ieee80211_hw *dev)
 {
        struct rtl8187_priv *priv = dev->priv;
 
-       rtl8187_unregister_led(&priv->led_tx);
        /* turn the LED off before exiting */
        queue_delayed_work(dev->workqueue, &priv->led_off, 0);
        cancel_delayed_work_sync(&priv->led_off);
+       cancel_delayed_work_sync(&priv->led_on);
        rtl8187_unregister_led(&priv->led_rx);
+       rtl8187_unregister_led(&priv->led_tx);
 }
 #endif /* def CONFIG_RTL8187_LED */
 
index 6af706408ac08bf252a4a97105af0379734db621..c6d300666ad8b2126d629fe9aa7b4ce413afe718 100644 (file)
@@ -3556,17 +3556,8 @@ wv_82593_config(struct net_device *      dev)
   cfblk.rcvstop = TRUE;        /* Enable Receive Stop Register */
 
 #ifdef DEBUG_I82593_SHOW
-  {
-    u_char *c = (u_char *) &cfblk;
-    int i;
-    printk(KERN_DEBUG "wavelan_cs: config block:");
-    for(i = 0; i < sizeof(struct i82593_conf_block); i++,c++)
-      {
-       if((i % 16) == 0) printk("\n" KERN_DEBUG);
-       printk("%02x ", *c);
-      }
-    printk("\n");
-  }
+  print_hex_dump(KERN_DEBUG, "wavelan_cs: config block: ", DUMP_PREFIX_NONE,
+                16, 1, &cfblk, sizeof(struct i82593_conf_block), false);
 #endif
 
   /* Copy the config block to the i82593 */
index 40b07b988224a4eee002a91c970fe1b5500f8ce2..3bd3c779fff337ab480b357ff8302d7facca25bd 100644 (file)
@@ -698,7 +698,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
                        && !mac->pass_ctrl)
                return 0;
 
-       fc = *(__le16 *)buffer;
+       fc = get_unaligned((__le16*)buffer);
        need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc);
 
        skb = dev_alloc_skb(length + (need_padding ? 2 : 0));
index 14a19baff2144c512a9e28bb34c94584af9c1b06..0e6e44689cc61f863b9a25f936ab19d4ec943e6d 100644 (file)
@@ -38,7 +38,6 @@ static struct usb_device_id usb_ids[] = {
        /* ZD1211 */
        { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 },
        { USB_DEVICE(0x0ace, 0xa211), .driver_info = DEVICE_ZD1211 },
-       { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 },
        { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 },
        { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
        { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 },
@@ -61,6 +60,7 @@ static struct usb_device_id usb_ids[] = {
        { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 },
        { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 },
        /* ZD1211B */
+       { USB_DEVICE(0x054c, 0x0257), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
@@ -87,6 +87,7 @@ static struct usb_device_id usb_ids[] = {
        { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B },
        { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B },
+       { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211B },
        /* "Driverless" devices that need ejecting */
        { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER },
        { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER },
index 3c7a5053f1da7ec054c81b9169ceb8109b7a19a1..c2fd6187773f1df97fab29504ca8dbca85a54193 100644 (file)
@@ -109,7 +109,7 @@ static int gx_fix;
 /* These identify the driver base version and may not be removed. */
 static const char version[] __devinitconst =
   KERN_INFO DRV_NAME ".c:v1.05  1/09/2001  Written by Donald Becker <becker@scyld.com>\n"
-  KERN_INFO "  (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n";
+  "  (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver");
@@ -346,7 +346,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int yellowfin_open(struct net_device *dev);
 static void yellowfin_timer(unsigned long data);
 static void yellowfin_tx_timeout(struct net_device *dev);
-static void yellowfin_init_ring(struct net_device *dev);
+static int yellowfin_init_ring(struct net_device *dev);
 static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t yellowfin_interrupt(int irq, void *dev_instance);
 static int yellowfin_rx(struct net_device *dev);
@@ -573,19 +573,24 @@ static int yellowfin_open(struct net_device *dev)
 {
        struct yellowfin_private *yp = netdev_priv(dev);
        void __iomem *ioaddr = yp->base;
-       int i;
+       int i, ret;
 
        /* Reset the chip. */
        iowrite32(0x80000000, ioaddr + DMACtrl);
 
-       i = request_irq(dev->irq, &yellowfin_interrupt, IRQF_SHARED, dev->name, dev);
-       if (i) return i;
+       ret = request_irq(dev->irq, &yellowfin_interrupt, IRQF_SHARED, dev->name, dev);
+       if (ret)
+               return ret;
 
        if (yellowfin_debug > 1)
                printk(KERN_DEBUG "%s: yellowfin_open() irq %d.\n",
                           dev->name, dev->irq);
 
-       yellowfin_init_ring(dev);
+       ret = yellowfin_init_ring(dev);
+       if (ret) {
+               free_irq(dev->irq, dev);
+               return ret;
+       }
 
        iowrite32(yp->rx_ring_dma, ioaddr + RxPtr);
        iowrite32(yp->tx_ring_dma, ioaddr + TxPtr);
@@ -700,12 +705,15 @@ static void yellowfin_tx_timeout(struct net_device *dev)
                int i;
                printk(KERN_WARNING "  Rx ring %p: ", yp->rx_ring);
                for (i = 0; i < RX_RING_SIZE; i++)
-                       printk(" %8.8x", yp->rx_ring[i].result_status);
-               printk("\n"KERN_WARNING"  Tx ring %p: ", yp->tx_ring);
+                       printk(KERN_CONT " %8.8x",
+                              yp->rx_ring[i].result_status);
+               printk(KERN_CONT "\n");
+               printk(KERN_WARNING"  Tx ring %p: ", yp->tx_ring);
                for (i = 0; i < TX_RING_SIZE; i++)
-                       printk(" %4.4x /%8.8x", yp->tx_status[i].tx_errs,
-                                  yp->tx_ring[i].result_status);
-               printk("\n");
+                       printk(KERN_CONT " %4.4x /%8.8x",
+                              yp->tx_status[i].tx_errs,
+                              yp->tx_ring[i].result_status);
+               printk(KERN_CONT "\n");
        }
 
        /* If the hardware is found to hang regularly, we will update the code
@@ -722,10 +730,10 @@ static void yellowfin_tx_timeout(struct net_device *dev)
 }
 
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void yellowfin_init_ring(struct net_device *dev)
+static int yellowfin_init_ring(struct net_device *dev)
 {
        struct yellowfin_private *yp = netdev_priv(dev);
-       int i;
+       int i, j;
 
        yp->tx_full = 0;
        yp->cur_rx = yp->cur_tx = 0;
@@ -750,6 +758,11 @@ static void yellowfin_init_ring(struct net_device *dev)
                yp->rx_ring[i].addr = cpu_to_le32(pci_map_single(yp->pci_dev,
                        skb->data, yp->rx_buf_sz, PCI_DMA_FROMDEVICE));
        }
+       if (i != RX_RING_SIZE) {
+               for (j = 0; j < i; j++)
+                       dev_kfree_skb(yp->rx_skbuff[j]);
+               return -ENOMEM;
+       }
        yp->rx_ring[i-1].dbdma_cmd = cpu_to_le32(CMD_STOP);
        yp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
 
@@ -766,8 +779,6 @@ static void yellowfin_init_ring(struct net_device *dev)
        yp->tx_ring[--i].dbdma_cmd = cpu_to_le32(CMD_STOP | BRANCH_ALWAYS);
 #else
 {
-       int j;
-
        /* Tx ring needs a pair of descriptors, the second for the status. */
        for (i = 0; i < TX_RING_SIZE; i++) {
                j = 2*i;
@@ -802,7 +813,7 @@ static void yellowfin_init_ring(struct net_device *dev)
 }
 #endif
        yp->tx_tail_desc = &yp->tx_status[0];
-       return;
+       return 0;
 }
 
 static int yellowfin_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -1216,20 +1227,20 @@ static int yellowfin_close(struct net_device *dev)
 
 #if defined(__i386__)
        if (yellowfin_debug > 2) {
-               printk("\n"KERN_DEBUG"  Tx ring at %8.8llx:\n",
+               printk(KERN_DEBUG"  Tx ring at %8.8llx:\n",
                                (unsigned long long)yp->tx_ring_dma);
                for (i = 0; i < TX_RING_SIZE*2; i++)
-                       printk(" %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n",
+                       printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n",
                                   ioread32(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ',
                                   i, yp->tx_ring[i].dbdma_cmd, yp->tx_ring[i].addr,
                                   yp->tx_ring[i].branch_addr, yp->tx_ring[i].result_status);
                printk(KERN_DEBUG "  Tx status %p:\n", yp->tx_status);
                for (i = 0; i < TX_RING_SIZE; i++)
-                       printk("   #%d status %4.4x %4.4x %4.4x %4.4x.\n",
+                       printk(KERN_DEBUG "   #%d status %4.4x %4.4x %4.4x %4.4x.\n",
                                   i, yp->tx_status[i].tx_cnt, yp->tx_status[i].tx_errs,
                                   yp->tx_status[i].total_tx_cnt, yp->tx_status[i].paused);
 
-               printk("\n"KERN_DEBUG "  Rx ring %8.8llx:\n",
+               printk(KERN_DEBUG "  Rx ring %8.8llx:\n",
                                (unsigned long long)yp->rx_ring_dma);
                for (i = 0; i < RX_RING_SIZE; i++) {
                        printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x\n",
index 37c84e3b8be083426a89e1e68686dbb0ad569764..81c753a617ab93ab793b724428c9c0c97646da84 100644 (file)
@@ -120,6 +120,9 @@ static int __devinit zorro8390_init_one(struct zorro_dev *z,
     for (i = ARRAY_SIZE(cards)-1; i >= 0; i--)
        if (z->id == cards[i].id)
            break;
+    if (i < 0)
+        return -ENODEV;
+
     board = z->resource.start;
     ioaddr = board+cards[i].offset;
     dev = alloc_ei_netdev();
index aee967d7f760cec514a65d0d0853062b50bca0a2..bacaa536fd515aef951f8f0e8b4d1e4625d839ab 100644 (file)
@@ -9,6 +9,10 @@
  * out of the OpenFirmware device tree and using it to populate an mii_bus.
  */
 
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/netdevice.h>
+#include <linux/err.h>
 #include <linux/phy.h>
 #include <linux/of.h>
 #include <linux/of_mdio.h>
@@ -137,3 +141,41 @@ struct phy_device *of_phy_connect(struct net_device *dev,
        return phy_connect_direct(dev, phy, hndlr, flags, iface) ? NULL : phy;
 }
 EXPORT_SYMBOL(of_phy_connect);
+
+/**
+ * of_phy_connect_fixed_link - Parse fixed-link property and return a dummy phy
+ * @dev: pointer to net_device claiming the phy
+ * @hndlr: Link state callback for the network device
+ * @iface: PHY data interface type
+ *
+ * This function is a temporary stop-gap and will be removed soon.  It is
+ * only to support the fs_enet, ucc_geth and gianfar Ethernet drivers.  Do
+ * not call this function from new drivers.
+ */
+struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
+                                            void (*hndlr)(struct net_device *),
+                                            phy_interface_t iface)
+{
+       struct device_node *net_np;
+       char bus_id[MII_BUS_ID_SIZE + 3];
+       struct phy_device *phy;
+       const u32 *phy_id;
+       int sz;
+
+       if (!dev->dev.parent)
+               return NULL;
+
+       net_np = dev_archdata_get_node(&dev->dev.parent->archdata);
+       if (!net_np)
+               return NULL;
+
+       phy_id = of_get_property(net_np, "fixed-link", &sz);
+       if (!phy_id || sz < sizeof(*phy_id))
+               return NULL;
+
+       sprintf(bus_id, PHY_ID_FMT, "0", phy_id[0]);
+
+       phy = phy_connect(dev, bus_id, hndlr, 0, iface);
+       return IS_ERR(phy) ? NULL : phy;
+}
+EXPORT_SYMBOL(of_phy_connect_fixed_link);
index e1f6ce03705ed915d94b77f1dde0a687e07e08f8..3c2270a8300c40833bcf0900968635e2b166abc6 100644 (file)
@@ -33,6 +33,7 @@ void oprofile_reset_stats(void)
        atomic_set(&oprofile_stats.sample_lost_no_mm, 0);
        atomic_set(&oprofile_stats.sample_lost_no_mapping, 0);
        atomic_set(&oprofile_stats.event_lost_overflow, 0);
+       atomic_set(&oprofile_stats.bt_lost_no_mapping, 0);
 }
 
 
index 5d610cbcfe80cf294a676c38a18bce5dbdd9af4b..a45b0c0d574e2d909c2180b6fa752d9100e770f6 100644 (file)
@@ -70,7 +70,6 @@
 #undef CCIO_COLLECT_STATS
 #endif
 
-#include <linux/proc_fs.h>
 #include <asm/runway.h>                /* for proc_runway_root */
 
 #ifdef DEBUG_CCIO_INIT
@@ -1134,7 +1133,7 @@ static const struct file_operations ccio_proc_bitmap_fops = {
        .llseek = seq_lseek,
        .release = single_release,
 };
-#endif
+#endif /* CONFIG_PROC_FS */
 
 /**
  * ccio_find_ioc - Find the ioc in the ioc_list
@@ -1568,14 +1567,15 @@ static int __init ccio_probe(struct parisc_device *dev)
        /* if this fails, no I/O cards will work, so may as well bug */
        BUG_ON(dev->dev.platform_data == NULL);
        HBA_DATA(dev->dev.platform_data)->iommu = ioc;
-       
+
+#ifdef CONFIG_PROC_FS
        if (ioc_count == 0) {
                proc_create(MODULE_NAME, 0, proc_runway_root,
                            &ccio_proc_info_fops);
                proc_create(MODULE_NAME"-bitmap", 0, proc_runway_root,
                            &ccio_proc_bitmap_fops);
        }
-
+#endif
        ioc_count++;
 
        parisc_has_iommu();
index 52ae0b1d470ccd24ee39a32fd04d29ac86722d44..d69bde6a234305638cf8943857f4e93d7f1d6f4b 100644 (file)
@@ -353,7 +353,7 @@ static unsigned int dino_startup_irq(unsigned int irq)
        return 0;
 }
 
-static struct hw_interrupt_type dino_interrupt_type = {
+static struct irq_chip dino_interrupt_type = {
        .typename       = "GSC-PCI",
        .startup        = dino_startup_irq,
        .shutdown       = dino_disable_irq,
@@ -614,7 +614,7 @@ dino_fixup_bus(struct pci_bus *bus)
                            dev_name(&bus->self->dev), i,
                            bus->self->resource[i].start,
                            bus->self->resource[i].end);
-                       pci_assign_resource(bus->self, i);
+                       WARN_ON(pci_assign_resource(bus->self, i));
                        DBG("DEBUG %s after assign %d [0x%lx,0x%lx]\n",
                            dev_name(&bus->self->dev), i,
                            bus->self->resource[i].start,
@@ -1019,22 +1019,22 @@ static int __init dino_probe(struct parisc_device *dev)
        ** It's not used to avoid chicken/egg problems
        ** with configuration accessor functions.
        */
-       bus = pci_scan_bus_parented(&dev->dev, dino_current_bus,
-                                   &dino_cfg_ops, NULL);
+       dino_dev->hba.hba_bus = bus = pci_scan_bus_parented(&dev->dev,
+                        dino_current_bus, &dino_cfg_ops, NULL);
+
        if(bus) {
-               pci_bus_add_devices(bus);
                /* This code *depends* on scanning being single threaded
                 * if it isn't, this global bus number count will fail
                 */
                dino_current_bus = bus->subordinate + 1;
                pci_bus_assign_resources(bus);
+               pci_bus_add_devices(bus);
        } else {
-               printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n",
+               printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (duplicate bus number %d?)\n",
                       dev_name(&dev->dev), dino_current_bus);
                /* increment the bus number in case of duplicates */
                dino_current_bus++;
        }
-       dino_dev->hba.hba_bus = bus;
        return 0;
 }
 
index 5b89f404e668876f53da1f0278523763e3512e16..51220749cb656805fa98a52117e799eeedee8944 100644 (file)
@@ -188,7 +188,7 @@ static unsigned int eisa_startup_irq(unsigned int irq)
        return 0;
 }
 
-static struct hw_interrupt_type eisa_interrupt_type = {
+static struct irq_chip eisa_interrupt_type = {
        .typename =     "EISA",
        .startup =      eisa_startup_irq,
        .shutdown =     eisa_disable_irq,
index 685d94e69d44e2b0791d0546736bef20c5d22806..8c0b26e9b98a0857f022e009dba200783a45c876 100644 (file)
@@ -55,7 +55,7 @@ static ssize_t eisa_eeprom_read(struct file * file,
        ssize_t ret;
        int i;
        
-       if (*ppos >= HPEE_MAX_LENGTH)
+       if (*ppos < 0 || *ppos >= HPEE_MAX_LENGTH)
                return 0;
        
        count = *ppos + count < HPEE_MAX_LENGTH ? count : HPEE_MAX_LENGTH - *ppos;
index c709ecc2b7f71626622f9c6f834b4c2160e374b0..0be1d50645ab0f3fde6f47b2c65b72e81ecfc316 100644 (file)
@@ -101,7 +101,7 @@ static int configure_memory(const unsigned char *buf,
                        printk("memory %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end);
                        result = request_resource(mem_parent, res);
                        if (result < 0) {
-                               printk("\n" KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n");
+                               printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n");
                                return result;
                        }
                }
@@ -191,7 +191,7 @@ static int configure_port(const unsigned char *buf, struct resource *io_parent,
                        printk("ioports %lx-%lx ", (unsigned long)res->start, (unsigned long)res->end);
                        result = request_resource(io_parent, res);
                        if (result < 0) {
-                               printk("\n" KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n");
+                               printk(KERN_ERR "EISA Enumerator: failed to claim EISA Bus address space!\n");
                                return result;
                        }
                }
@@ -224,7 +224,7 @@ static int configure_port_init(const unsigned char *buf)
                 case HPEE_PORT_INIT_WIDTH_BYTE:
                        s=1;
                        if (c & HPEE_PORT_INIT_MASK) {
-                               printk("\n" KERN_WARNING "port_init: unverified mask attribute\n");
+                               printk(KERN_WARNING "port_init: unverified mask attribute\n");
                                outb((inb(get_16(buf+len+1) & 
                                          get_8(buf+len+3)) | 
                                      get_8(buf+len+4)), get_16(buf+len+1));
@@ -249,7 +249,7 @@ static int configure_port_init(const unsigned char *buf)
                 case HPEE_PORT_INIT_WIDTH_DWORD:
                        s=4;
                        if (c & HPEE_PORT_INIT_MASK) {
-                               printk("\n" KERN_WARNING "port_init: unverified mask attribute\n");
+                               printk(KERN_WARNING "port_init: unverified mask attribute\n");
                                outl((inl(get_16(buf+len+1) &
                                          get_32(buf+len+3)) |
                                      get_32(buf+len+7)), get_16(buf+len+1));
@@ -259,7 +259,7 @@ static int configure_port_init(const unsigned char *buf)
 
                        break;
                 default:
-                       printk("\n" KERN_ERR "Invalid port init word %02x\n", c);
+                       printk(KERN_ERR "Invalid port init word %02x\n", c);
                        return 0;
                }
                
@@ -297,7 +297,7 @@ static int configure_type_string(const unsigned char *buf)
        /* just skip past the type field */
        len = get_8(buf);
        if (len > 80) {
-               printk("\n" KERN_ERR "eisa_enumerator: type info field too long (%d, max is 80)\n", len);
+               printk(KERN_ERR "eisa_enumerator: type info field too long (%d, max is 80)\n", len);
        }
        
        return 1+len;
@@ -398,7 +398,7 @@ static int parse_slot_config(int slot,
                }
                
                if (p0 + function_len < pos) {
-                       printk("\n" KERN_ERR "eisa_enumerator: function %d length mis-match "
+                       printk(KERN_ERR "eisa_enumerator: function %d length mis-match "
                               "got %d, expected %d\n",
                               num_func, pos-p0, function_len);
                        res=-1;
index d336329176962461cb160016ad7aba736d3e232e..647adc9f85adf1118f7b294a89cac45200344b6c 100644 (file)
@@ -148,7 +148,7 @@ static unsigned int gsc_asic_startup_irq(unsigned int irq)
        return 0;
 }
 
-static struct hw_interrupt_type gsc_asic_interrupt_type = {
+static struct irq_chip gsc_asic_interrupt_type = {
        .typename =     "GSC-ASIC",
        .startup =      gsc_asic_startup_irq,
        .shutdown =     gsc_asic_disable_irq,
@@ -158,7 +158,7 @@ static struct hw_interrupt_type gsc_asic_interrupt_type = {
        .end =          no_end_irq,
 };
 
-int gsc_assign_irq(struct hw_interrupt_type *type, void *data)
+int gsc_assign_irq(struct irq_chip *type, void *data)
 {
        static int irq = GSC_IRQ_BASE;
        struct irq_desc *desc;
index 762a1babad604a318a9f5a22bfb7d467bc760e93..b9d7bfb68e24d057e89e726ce0852250e90d4a85 100644 (file)
@@ -38,7 +38,7 @@ struct gsc_asic {
 int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic);
 int gsc_alloc_irq(struct gsc_irq *dev);                        /* dev needs an irq */
 int gsc_claim_irq(struct gsc_irq *dev, int irq);       /* dev needs this irq */
-int gsc_assign_irq(struct hw_interrupt_type *type, void *data);
+int gsc_assign_irq(struct irq_chip *type, void *data);
 int gsc_find_local_irq(unsigned int irq, int *global_irq, int limit);
 void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl,
                void (*choose)(struct parisc_device *child, void *ctrl));
index 13856415b4326aace5ceacec61962e94e59f0306..815db175d4275839aa95d85c5d123c975572c3ab 100644 (file)
@@ -62,7 +62,8 @@ static int hppb_probe(struct parisc_device *dev)
                }
                card = card->next;
        }
-        printk(KERN_INFO "Found GeckoBoa at 0x%x\n", dev->hpa.start);
+       printk(KERN_INFO "Found GeckoBoa at 0x%llx\n",
+                       (unsigned long long) dev->hpa.start);
 
        card->hpa = dev->hpa.start;
        card->mmio_region.name = "HP-PB Bus";
@@ -73,8 +74,10 @@ static int hppb_probe(struct parisc_device *dev)
 
        status = ccio_request_resource(dev, &card->mmio_region);
        if(status < 0) {
-               printk(KERN_ERR "%s: failed to claim HP-PB bus space (%08x, %08x)\n",
-                       __FILE__, card->mmio_region.start, card->mmio_region.end);
+               printk(KERN_ERR "%s: failed to claim HP-PB "
+                       "bus space (0x%08llx, 0x%08llx)\n",
+                       __FILE__, (unsigned long long) card->mmio_region.start,
+                       (unsigned long long) card->mmio_region.end);
        }
 
         return 0;
index 4a9cc92d4d1867469dcae3efed4c468b251ff7f8..88e333553212c33d4c38985040c95f4fb23249b1 100644 (file)
@@ -729,7 +729,7 @@ static int iosapic_set_affinity_irq(unsigned int irq,
 }
 #endif
 
-static struct hw_interrupt_type iosapic_interrupt_type = {
+static struct irq_chip iosapic_interrupt_type = {
        .typename =     "IO-SAPIC-level",
        .startup =      iosapic_startup_irq,
        .shutdown =     iosapic_disable_irq,
index 59fbbf12836579a9d4d729993186af88b79701d8..3aeb3279c92ab976d62fad84223442e441225963 100644 (file)
@@ -980,28 +980,38 @@ static void
 lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
 {
        unsigned long bytecnt;
-       pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;     /* PA_VIEW */
-       pdc_pat_cell_mod_maddr_block_t io_pdc_cell;     /* IO_VIEW */
        long io_count;
        long status;    /* PDC return status */
        long pa_count;
+       pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell;    /* PA_VIEW */
+       pdc_pat_cell_mod_maddr_block_t *io_pdc_cell;    /* IO_VIEW */
        int i;
 
+       pa_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL);
+       if (!pa_pdc_cell)
+               return;
+
+       io_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL);
+       if (!io_pdc_cell) {
+               kfree(pa_pdc_cell);
+               return;
+       }
+
        /* return cell module (IO view) */
        status = pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index,
-                               PA_VIEW, pa_pdc_cell);
-       pa_count = pa_pdc_cell.mod[1];
+                               PA_VIEW, pa_pdc_cell);
+       pa_count = pa_pdc_cell->mod[1];
 
        status |= pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index,
-                               IO_VIEW, &io_pdc_cell);
-       io_count = io_pdc_cell.mod[1];
+                               IO_VIEW, io_pdc_cell);
+       io_count = io_pdc_cell->mod[1];
 
        /* We've already done this once for device discovery...*/
        if (status != PDC_OK) {
                panic("pdc_pat_cell_module() call failed for LBA!\n");
        }
 
-       if (PAT_GET_ENTITY(pa_pdc_cell.mod_info) != PAT_ENTITY_LBA) {
+       if (PAT_GET_ENTITY(pa_pdc_cell->mod_info) != PAT_ENTITY_LBA) {
                panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n");
        }
 
@@ -1016,8 +1026,8 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
                } *p, *io;
                struct resource *r;
 
-               p = (void *) &(pa_pdc_cell.mod[2+i*3]);
-               io = (void *) &(io_pdc_cell.mod[2+i*3]);
+               p = (void *) &(pa_pdc_cell->mod[2+i*3]);
+               io = (void *) &(io_pdc_cell->mod[2+i*3]);
 
                /* Convert the PAT range data to PCI "struct resource" */
                switch(p->type & 0xff) {
@@ -1096,6 +1106,9 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
                        break;
                }
        }
+
+       kfree(pa_pdc_cell);
+       kfree(io_pdc_cell);
 }
 #else
 /* keep compiler from complaining about missing declarations */
@@ -1509,10 +1522,6 @@ lba_driver_probe(struct parisc_device *dev)
        lba_bus = lba_dev->hba.hba_bus =
                pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start,
                                cfg_ops, NULL);
-       if (lba_bus) {
-               lba_next_bus = lba_bus->subordinate + 1;
-               pci_bus_add_devices(lba_bus);
-       }
 
        /* This is in lieu of calling pci_assign_unassigned_resources() */
        if (is_pdc_pat()) {
@@ -1533,7 +1542,6 @@ lba_driver_probe(struct parisc_device *dev)
        }
        pci_enable_bridges(lba_bus);
 
-
        /*
        ** Once PCI register ops has walked the bus, access to config
        ** space is restricted. Avoids master aborts on config cycles.
@@ -1543,6 +1551,11 @@ lba_driver_probe(struct parisc_device *dev)
                lba_dev->flags |= LBA_FLAG_SKIP_PROBE;
        }
 
+       if (lba_bus) {
+               lba_next_bus = lba_bus->subordinate + 1;
+               pci_bus_add_devices(lba_bus);
+       }
+
        /* Whew! Finally done! Tell services we got this one covered. */
        return 0;
 }
index f9f9a5f1bbd0f9d74c5f505c4dea7f7a1ac6c129..13a64bc081b6762d873204c3ddd0cbe7c35d074c 100644 (file)
@@ -370,7 +370,7 @@ pdcspath_layer_read(struct pdcspath_entry *entry, char *buf)
        if (!i) /* entry is not ready */
                return -ENODATA;
        
-       for (i = 0; devpath->layers[i] && (likely(i < 6)); i++)
+       for (i = 0; i < 6 && devpath->layers[i]; i++)
                out += sprintf(out, "%u ", devpath->layers[i]);
 
        out += sprintf(out, "\n");
index d46dd57450acd151d4d97a7d7016e54cedab1f54..123d8fe3427d0a1286f8ebd5d1cf684d13969993 100644 (file)
@@ -2057,6 +2057,7 @@ void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r)
                r->start = (base & ~1UL) | PCI_F_EXTEND;
                size = ~ READ_REG32(reg + LMMIO_DIRECT0_MASK);
                r->end = r->start + size;
+               r->flags = IORESOURCE_MEM;
        }
 }
 
@@ -2093,4 +2094,5 @@ void sba_distributed_lmmio(struct parisc_device *pci_hba, struct resource *r )
        size = (~READ_REG32(sba->sba_hpa + LMMIO_DIST_MASK)) / ROPES_PER_IOC;
        r->start += rope * (size + 1);  /* adjust base for this rope */
        r->end = r->start + size;
+       r->flags = IORESOURCE_MEM;
 }
index 33e5ade774ca01c98004bcafdfd1820f939a4b34..675f04e6597a5d664f6f535f670be1f5c9855c9e 100644 (file)
@@ -325,7 +325,7 @@ static unsigned int superio_startup_irq(unsigned int irq)
        return 0;
 }
 
-static struct hw_interrupt_type superio_interrupt_type = {
+static struct irq_chip superio_interrupt_type = {
        .typename =     SUPERIO,
        .startup =      superio_startup_irq,
        .shutdown =     superio_disable_irq,
@@ -434,8 +434,8 @@ static void __init superio_parport_init(void)
                        0 /*base_hi*/,
                        PAR_IRQ, 
                        PARPORT_DMA_NONE /* dma */,
-                       NULL /*struct pci_dev* */),
-                       0 /* shared irq flags */ )
+                       NULL /*struct pci_dev* */,
+                       0 /* shared irq flags */))
 
                printk(KERN_WARNING PFX "Probing parallel port failed.\n");
 #endif /* CONFIG_PARPORT_PC */
index 1032d5fdbd423ce8736d72e85f8f6d3edbcd6eed..2597145a066e391fa988ecbbf44921f2f249ef1d 100644 (file)
@@ -2907,6 +2907,7 @@ enum parport_pc_pci_cards {
        netmos_9755,
        netmos_9805,
        netmos_9815,
+       netmos_9901,
        quatech_sppxp100,
 };
 
@@ -2987,7 +2988,7 @@ static struct parport_pc_pci {
        /* netmos_9755 */               { 2, { { 0, 1 }, { 2, 3 },} },
        /* netmos_9805 */               { 1, { { 0, -1 }, } },
        /* netmos_9815 */               { 2, { { 0, -1 }, { 2, -1 }, } },
-
+       /* netmos_9901 */               { 1, { { 0, -1 }, } },
        /* quatech_sppxp100 */          { 1, { { 0, 1 }, } },
 };
 
@@ -3089,6 +3090,8 @@ static const struct pci_device_id parport_pc_pci_tbl[] = {
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 },
        { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 },
+       { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
+         0xA000, 0x2000, 0, 0, netmos_9901 },
        /* Quatech SPPXP-100 Parallel port PCI ExpressCard */
        { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100,
          PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 },
index a5b9f6ae507bb5cf23ab4cf614e97c1fa7e2c6d3..d703e73fffa7cc5cf334dbd003c7334a9bec42b1 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/pci_hotplug.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
 #include <asm/atomic.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
index 2fa47af992a8281ff1bfb43d5fd0e7c0c7bf2111..0ff689afa757bb1aa21df038623c4a63c41364f7 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/wait.h>
-#include <linux/smp_lock.h>
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
 #include <linux/kthread.h>
index 8450f4a6568a852a288b75a62436e913b71e7ef8..e6089bdb6e5bddbc2b08e09c9419d26056e543e7 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/workqueue.h>
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
+#include <linux/smp_lock.h>
 #include <linux/debugfs.h>
 #include "cpqphp.h"
 
index 844580489d4da56d63dc7015b2320206661a63d4..5c5043f239cf560fb33fad276f47972f7ffd65f4 100644 (file)
@@ -555,6 +555,8 @@ static struct hotplug_slot *get_slot_from_name (const char *name)
  * @slot: pointer to the &struct hotplug_slot to register
  * @devnr: device number
  * @name: name registered with kobject core
+ * @owner: caller module owner
+ * @mod_name: caller module name
  *
  * Registers a hotplug slot with the pci hotplug subsystem, which will allow
  * userspace interaction to the slot.
index ff4034502d240355b9e5dfd4c02b226606ba2f52..8aab8edf123eeecfc5d0bc5d79ae63a1685e6c0e 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/smp_lock.h>
 #include <linux/pci.h>
 #include <linux/workqueue.h>
 #include "../pci.h"
index a4494d78e7c2355eaeb27ede4098b65a7b1aaf8e..8aebe1e9d3d6ae21c664f998a4192194547b7afe 100644 (file)
@@ -90,11 +90,10 @@ static struct hotplug_slot_ops sn_hotplug_slot_ops = {
 
 static DEFINE_MUTEX(sn_hotplug_mutex);
 
-static ssize_t path_show (struct hotplug_slot *bss_hotplug_slot,
-                         char *buf)
+static ssize_t path_show(struct pci_slot *pci_slot, char *buf)
 {
        int retval = -ENOENT;
-       struct slot *slot = bss_hotplug_slot->private;
+       struct slot *slot = pci_slot->hotplug->private;
 
        if (!slot)
                return retval;
@@ -103,7 +102,7 @@ static ssize_t path_show (struct hotplug_slot *bss_hotplug_slot,
        return retval;
 }
 
-static struct hotplug_slot_attribute sn_slot_path_attr = __ATTR_RO(path);
+static struct pci_slot_attribute sn_slot_path_attr = __ATTR_RO(path);
 
 static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
 {
index e53eacd75c8daf5d6096947ef646a75162fb6bf1..2314ad7ee5fef4544ab2159cd7e253ed6e1d3889 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/sysdev.h>
 #include <asm/cacheflush.h>
 #include <asm/iommu.h>
-#include <asm/e820.h>
 #include "pci.h"
 
 #define ROOT_SIZE              VTD_PAGE_SIZE
 #define MAX_AGAW_WIDTH 64
 
 #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1)
+#define DOMAIN_MAX_PFN(gaw)  ((((u64)1) << (gaw-VTD_PAGE_SHIFT)) - 1)
 
 #define IOVA_PFN(addr)         ((addr) >> PAGE_SHIFT)
 #define DMA_32BIT_PFN          IOVA_PFN(DMA_BIT_MASK(32))
 #define DMA_64BIT_PFN          IOVA_PFN(DMA_BIT_MASK(64))
 
-#ifndef PHYSICAL_PAGE_MASK
-#define PHYSICAL_PAGE_MASK PAGE_MASK
-#endif
+
+/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
+   are never going to work. */
+static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn)
+{
+       return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT);
+}
+
+static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn)
+{
+       return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT);
+}
+static inline unsigned long page_to_dma_pfn(struct page *pg)
+{
+       return mm_to_dma_pfn(page_to_pfn(pg));
+}
+static inline unsigned long virt_to_dma_pfn(void *p)
+{
+       return page_to_dma_pfn(virt_to_page(p));
+}
 
 /* global iommu list, set NULL for ignored DMAR units */
 static struct intel_iommu **g_iommus;
@@ -205,12 +222,17 @@ static inline void dma_set_pte_prot(struct dma_pte *pte, unsigned long prot)
 
 static inline u64 dma_pte_addr(struct dma_pte *pte)
 {
-       return (pte->val & VTD_PAGE_MASK);
+#ifdef CONFIG_64BIT
+       return pte->val & VTD_PAGE_MASK;
+#else
+       /* Must have a full atomic 64-bit read */
+       return  __cmpxchg64(pte, 0ULL, 0ULL) & VTD_PAGE_MASK;
+#endif
 }
 
-static inline void dma_set_pte_addr(struct dma_pte *pte, u64 addr)
+static inline void dma_set_pte_pfn(struct dma_pte *pte, unsigned long pfn)
 {
-       pte->val |= (addr & VTD_PAGE_MASK);
+       pte->val |= (uint64_t)pfn << VTD_PAGE_SHIFT;
 }
 
 static inline bool dma_pte_present(struct dma_pte *pte)
@@ -218,6 +240,11 @@ static inline bool dma_pte_present(struct dma_pte *pte)
        return (pte->val & 3) != 0;
 }
 
+static inline int first_pte_in_page(struct dma_pte *pte)
+{
+       return !((unsigned long)pte & ~VTD_PAGE_MASK);
+}
+
 /*
  * This domain is a statically identity mapping domain.
  *     1. This domain creats a static 1:1 mapping to all usable memory.
@@ -245,7 +272,6 @@ struct dmar_domain {
        struct iova_domain iovad;       /* iova's that belong to this domain */
 
        struct dma_pte  *pgd;           /* virtual address */
-       spinlock_t      mapping_lock;   /* page table lock */
        int             gaw;            /* max guest address width */
 
        /* adjusted guest address width, 0 is level 2 30-bit */
@@ -649,80 +675,78 @@ static inline int width_to_agaw(int width)
 
 static inline unsigned int level_to_offset_bits(int level)
 {
-       return (12 + (level - 1) * LEVEL_STRIDE);
+       return (level - 1) * LEVEL_STRIDE;
 }
 
-static inline int address_level_offset(u64 addr, int level)
+static inline int pfn_level_offset(unsigned long pfn, int level)
 {
-       return ((addr >> level_to_offset_bits(level)) & LEVEL_MASK);
+       return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
 }
 
-static inline u64 level_mask(int level)
+static inline unsigned long level_mask(int level)
 {
-       return ((u64)-1 << level_to_offset_bits(level));
+       return -1UL << level_to_offset_bits(level);
 }
 
-static inline u64 level_size(int level)
+static inline unsigned long level_size(int level)
 {
-       return ((u64)1 << level_to_offset_bits(level));
+       return 1UL << level_to_offset_bits(level);
 }
 
-static inline u64 align_to_level(u64 addr, int level)
+static inline unsigned long align_to_level(unsigned long pfn, int level)
 {
-       return ((addr + level_size(level) - 1) & level_mask(level));
+       return (pfn + level_size(level) - 1) & level_mask(level);
 }
 
-static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr)
+static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
+                                     unsigned long pfn)
 {
-       int addr_width = agaw_to_width(domain->agaw);
+       int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
        struct dma_pte *parent, *pte = NULL;
        int level = agaw_to_level(domain->agaw);
        int offset;
-       unsigned long flags;
 
        BUG_ON(!domain->pgd);
-
-       addr &= (((u64)1) << addr_width) - 1;
+       BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width);
        parent = domain->pgd;
 
-       spin_lock_irqsave(&domain->mapping_lock, flags);
        while (level > 0) {
                void *tmp_page;
 
-               offset = address_level_offset(addr, level);
+               offset = pfn_level_offset(pfn, level);
                pte = &parent[offset];
                if (level == 1)
                        break;
 
                if (!dma_pte_present(pte)) {
+                       uint64_t pteval;
+
                        tmp_page = alloc_pgtable_page();
 
-                       if (!tmp_page) {
-                               spin_unlock_irqrestore(&domain->mapping_lock,
-                                       flags);
+                       if (!tmp_page)
                                return NULL;
+
+                       domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
+                       pteval = (virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE;
+                       if (cmpxchg64(&pte->val, 0ULL, pteval)) {
+                               /* Someone else set it while we were thinking; use theirs. */
+                               free_pgtable_page(tmp_page);
+                       } else {
+                               dma_pte_addr(pte);
+                               domain_flush_cache(domain, pte, sizeof(*pte));
                        }
-                       domain_flush_cache(domain, tmp_page, PAGE_SIZE);
-                       dma_set_pte_addr(pte, virt_to_phys(tmp_page));
-                       /*
-                        * high level table always sets r/w, last level page
-                        * table control read/write
-                        */
-                       dma_set_pte_readable(pte);
-                       dma_set_pte_writable(pte);
-                       domain_flush_cache(domain, pte, sizeof(*pte));
                }
                parent = phys_to_virt(dma_pte_addr(pte));
                level--;
        }
 
-       spin_unlock_irqrestore(&domain->mapping_lock, flags);
        return pte;
 }
 
 /* return address's pte at specific level */
-static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr,
-               int level)
+static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
+                                        unsigned long pfn,
+                                        int level)
 {
        struct dma_pte *parent, *pte = NULL;
        int total = agaw_to_level(domain->agaw);
@@ -730,7 +754,7 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr,
 
        parent = domain->pgd;
        while (level <= total) {
-               offset = address_level_offset(addr, total);
+               offset = pfn_level_offset(pfn, total);
                pte = &parent[offset];
                if (level == total)
                        return pte;
@@ -743,74 +767,82 @@ static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr,
        return NULL;
 }
 
-/* clear one page's page table */
-static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr)
-{
-       struct dma_pte *pte = NULL;
-
-       /* get last level pte */
-       pte = dma_addr_level_pte(domain, addr, 1);
-
-       if (pte) {
-               dma_clear_pte(pte);
-               domain_flush_cache(domain, pte, sizeof(*pte));
-       }
-}
-
 /* clear last level pte, a tlb flush should be followed */
-static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end)
+static void dma_pte_clear_range(struct dmar_domain *domain,
+                               unsigned long start_pfn,
+                               unsigned long last_pfn)
 {
-       int addr_width = agaw_to_width(domain->agaw);
-       int npages;
+       int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
+       struct dma_pte *first_pte, *pte;
 
-       start &= (((u64)1) << addr_width) - 1;
-       end &= (((u64)1) << addr_width) - 1;
-       /* in case it's partial page */
-       start &= PAGE_MASK;
-       end = PAGE_ALIGN(end);
-       npages = (end - start) / VTD_PAGE_SIZE;
+       BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
+       BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
 
-       /* we don't need lock here, nobody else touches the iova range */
-       while (npages--) {
-               dma_pte_clear_one(domain, start);
-               start += VTD_PAGE_SIZE;
+       /* we don't need lock here; nobody else touches the iova range */
+       while (start_pfn <= last_pfn) {
+               first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1);
+               if (!pte) {
+                       start_pfn = align_to_level(start_pfn + 1, 2);
+                       continue;
+               }
+               do { 
+                       dma_clear_pte(pte);
+                       start_pfn++;
+                       pte++;
+               } while (start_pfn <= last_pfn && !first_pte_in_page(pte));
+
+               domain_flush_cache(domain, first_pte,
+                                  (void *)pte - (void *)first_pte);
        }
 }
 
 /* free page table pages. last level pte should already be cleared */
 static void dma_pte_free_pagetable(struct dmar_domain *domain,
-       u64 start, u64 end)
+                                  unsigned long start_pfn,
+                                  unsigned long last_pfn)
 {
-       int addr_width = agaw_to_width(domain->agaw);
-       struct dma_pte *pte;
+       int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
+       struct dma_pte *first_pte, *pte;
        int total = agaw_to_level(domain->agaw);
        int level;
-       u64 tmp;
+       unsigned long tmp;
 
-       start &= (((u64)1) << addr_width) - 1;
-       end &= (((u64)1) << addr_width) - 1;
+       BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width);
+       BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width);
 
-       /* we don't need lock here, nobody else touches the iova range */
+       /* We don't need lock here; nobody else touches the iova range */
        level = 2;
        while (level <= total) {
-               tmp = align_to_level(start, level);
-               if (tmp >= end || (tmp + level_size(level) > end))
+               tmp = align_to_level(start_pfn, level);
+
+               /* If we can't even clear one PTE at this level, we're done */
+               if (tmp + level_size(level) - 1 > last_pfn)
                        return;
 
-               while (tmp < end) {
-                       pte = dma_addr_level_pte(domain, tmp, level);
-                       if (pte) {
-                               free_pgtable_page(
-                                       phys_to_virt(dma_pte_addr(pte)));
-                               dma_clear_pte(pte);
-                               domain_flush_cache(domain, pte, sizeof(*pte));
+               while (tmp + level_size(level) - 1 <= last_pfn) {
+                       first_pte = pte = dma_pfn_level_pte(domain, tmp, level);
+                       if (!pte) {
+                               tmp = align_to_level(tmp + 1, level + 1);
+                               continue;
                        }
-                       tmp += level_size(level);
+                       do {
+                               if (dma_pte_present(pte)) {
+                                       free_pgtable_page(phys_to_virt(dma_pte_addr(pte)));
+                                       dma_clear_pte(pte);
+                               }
+                               pte++;
+                               tmp += level_size(level);
+                       } while (!first_pte_in_page(pte) &&
+                                tmp + level_size(level) - 1 <= last_pfn);
+
+                       domain_flush_cache(domain, first_pte,
+                                          (void *)pte - (void *)first_pte);
+                       
                }
                level++;
        }
        /* free pgd */
-       if (start == 0 && end >= ((((u64)1) << addr_width) - 1)) {
+       if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
                free_pgtable_page(domain->pgd);
                domain->pgd = NULL;
        }
@@ -1036,11 +1068,11 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
 }
 
 static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
-                                 u64 addr, unsigned int pages)
+                                 unsigned long pfn, unsigned int pages)
 {
        unsigned int mask = ilog2(__roundup_pow_of_two(pages));
+       uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
 
-       BUG_ON(addr & (~VTD_PAGE_MASK));
        BUG_ON(pages == 0);
 
        /*
@@ -1055,7 +1087,12 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did,
        else
                iommu->flush.flush_iotlb(iommu, did, addr, mask,
                                                DMA_TLB_PSI_FLUSH);
-       if (did)
+
+       /*
+        * In caching mode, domain ID 0 is reserved for non-present to present
+        * mapping flush. Device IOTLB doesn't need to be flushed in this case.
+        */
+       if (!cap_caching_mode(iommu->cap) || did)
                iommu_flush_dev_iotlb(iommu->domains[did], addr, mask);
 }
 
@@ -1280,7 +1317,6 @@ static void dmar_init_reserved_ranges(void)
        struct pci_dev *pdev = NULL;
        struct iova *iova;
        int i;
-       u64 addr, size;
 
        init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN);
 
@@ -1303,12 +1339,9 @@ static void dmar_init_reserved_ranges(void)
                        r = &pdev->resource[i];
                        if (!r->flags || !(r->flags & IORESOURCE_MEM))
                                continue;
-                       addr = r->start;
-                       addr &= PHYSICAL_PAGE_MASK;
-                       size = r->end - addr;
-                       size = PAGE_ALIGN(size);
-                       iova = reserve_iova(&reserved_iova_list, IOVA_PFN(addr),
-                               IOVA_PFN(size + addr) - 1);
+                       iova = reserve_iova(&reserved_iova_list,
+                                           IOVA_PFN(r->start),
+                                           IOVA_PFN(r->end));
                        if (!iova)
                                printk(KERN_ERR "Reserve iova failed\n");
                }
@@ -1342,7 +1375,6 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
        unsigned long sagaw;
 
        init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
-       spin_lock_init(&domain->mapping_lock);
        spin_lock_init(&domain->iommu_lock);
 
        domain_reserve_special_ranges(domain);
@@ -1389,7 +1421,6 @@ static void domain_exit(struct dmar_domain *domain)
 {
        struct dmar_drhd_unit *drhd;
        struct intel_iommu *iommu;
-       u64 end;
 
        /* Domain 0 is reserved, so dont process it */
        if (!domain)
@@ -1398,14 +1429,12 @@ static void domain_exit(struct dmar_domain *domain)
        domain_remove_dev_info(domain);
        /* destroy iovas */
        put_iova_domain(&domain->iovad);
-       end = DOMAIN_MAX_ADDR(domain->gaw);
-       end = end & (~PAGE_MASK);
 
        /* clear ptes */
-       dma_pte_clear_range(domain, 0, end);
+       dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
 
        /* free page tables */
-       dma_pte_free_pagetable(domain, 0, end);
+       dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
 
        for_each_active_iommu(iommu, drhd)
                if (test_bit(iommu->seq_id, &domain->iommu_bmp))
@@ -1476,7 +1505,6 @@ static int domain_context_mapping_one(struct dmar_domain *domain, int segment,
                        }
 
                        set_bit(num, iommu->domain_ids);
-                       set_bit(iommu->seq_id, &domain->iommu_bmp);
                        iommu->domains[num] = domain;
                        id = num;
                }
@@ -1619,42 +1647,94 @@ static int domain_context_mapped(struct pci_dev *pdev)
                                             tmp->devfn);
 }
 
-static int
-domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova,
-                       u64 hpa, size_t size, int prot)
+/* Returns a number of VTD pages, but aligned to MM page size */
+static inline unsigned long aligned_nrpages(unsigned long host_addr,
+                                           size_t size)
 {
-       u64 start_pfn, end_pfn;
-       struct dma_pte *pte;
-       int index;
-       int addr_width = agaw_to_width(domain->agaw);
+       host_addr &= ~PAGE_MASK;
+       return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT;
+}
 
-       hpa &= (((u64)1) << addr_width) - 1;
+static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
+                           struct scatterlist *sg, unsigned long phys_pfn,
+                           unsigned long nr_pages, int prot)
+{
+       struct dma_pte *first_pte = NULL, *pte = NULL;
+       phys_addr_t uninitialized_var(pteval);
+       int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
+       unsigned long sg_res;
+
+       BUG_ON(addr_width < BITS_PER_LONG && (iov_pfn + nr_pages - 1) >> addr_width);
 
        if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
                return -EINVAL;
-       iova &= PAGE_MASK;
-       start_pfn = ((u64)hpa) >> VTD_PAGE_SHIFT;
-       end_pfn = (VTD_PAGE_ALIGN(((u64)hpa) + size)) >> VTD_PAGE_SHIFT;
-       index = 0;
-       while (start_pfn < end_pfn) {
-               pte = addr_to_dma_pte(domain, iova + VTD_PAGE_SIZE * index);
-               if (!pte)
-                       return -ENOMEM;
+
+       prot &= DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP;
+
+       if (sg)
+               sg_res = 0;
+       else {
+               sg_res = nr_pages + 1;
+               pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | prot;
+       }
+
+       while (nr_pages--) {
+               uint64_t tmp;
+
+               if (!sg_res) {
+                       sg_res = aligned_nrpages(sg->offset, sg->length);
+                       sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset;
+                       sg->dma_length = sg->length;
+                       pteval = page_to_phys(sg_page(sg)) | prot;
+               }
+               if (!pte) {
+                       first_pte = pte = pfn_to_dma_pte(domain, iov_pfn);
+                       if (!pte)
+                               return -ENOMEM;
+               }
                /* We don't need lock here, nobody else
                 * touches the iova range
                 */
-               BUG_ON(dma_pte_addr(pte));
-               dma_set_pte_addr(pte, start_pfn << VTD_PAGE_SHIFT);
-               dma_set_pte_prot(pte, prot);
-               if (prot & DMA_PTE_SNP)
-                       dma_set_pte_snp(pte);
-               domain_flush_cache(domain, pte, sizeof(*pte));
-               start_pfn++;
-               index++;
+               tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
+               if (tmp) {
+                       static int dumps = 5;
+                       printk(KERN_CRIT "ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
+                              iov_pfn, tmp, (unsigned long long)pteval);
+                       if (dumps) {
+                               dumps--;
+                               debug_dma_dump_mappings(NULL);
+                       }
+                       WARN_ON(1);
+               }
+               pte++;
+               if (!nr_pages || first_pte_in_page(pte)) {
+                       domain_flush_cache(domain, first_pte,
+                                          (void *)pte - (void *)first_pte);
+                       pte = NULL;
+               }
+               iov_pfn++;
+               pteval += VTD_PAGE_SIZE;
+               sg_res--;
+               if (!sg_res)
+                       sg = sg_next(sg);
        }
        return 0;
 }
 
+static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
+                                   struct scatterlist *sg, unsigned long nr_pages,
+                                   int prot)
+{
+       return __domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
+}
+
+static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
+                                    unsigned long phys_pfn, unsigned long nr_pages,
+                                    int prot)
+{
+       return __domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
+}
+
 static void iommu_detach_dev(struct intel_iommu *iommu, u8 bus, u8 devfn)
 {
        if (!iommu)
@@ -1845,58 +1925,61 @@ error:
 
 static int iommu_identity_mapping;
 
+static int iommu_domain_identity_map(struct dmar_domain *domain,
+                                    unsigned long long start,
+                                    unsigned long long end)
+{
+       unsigned long first_vpfn = start >> VTD_PAGE_SHIFT;
+       unsigned long last_vpfn = end >> VTD_PAGE_SHIFT;
+
+       if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn),
+                         dma_to_mm_pfn(last_vpfn))) {
+               printk(KERN_ERR "IOMMU: reserve iova failed\n");
+               return -ENOMEM;
+       }
+
+       pr_debug("Mapping reserved region %llx-%llx for domain %d\n",
+                start, end, domain->id);
+       /*
+        * RMRR range might have overlap with physical memory range,
+        * clear it first
+        */
+       dma_pte_clear_range(domain, first_vpfn, last_vpfn);
+
+       return domain_pfn_mapping(domain, first_vpfn, first_vpfn,
+                                 last_vpfn - first_vpfn + 1,
+                                 DMA_PTE_READ|DMA_PTE_WRITE);
+}
+
 static int iommu_prepare_identity_map(struct pci_dev *pdev,
                                      unsigned long long start,
                                      unsigned long long end)
 {
        struct dmar_domain *domain;
-       unsigned long size;
-       unsigned long long base;
        int ret;
 
        printk(KERN_INFO
-               "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
-               pci_name(pdev), start, end);
-       if (iommu_identity_mapping)
-               domain = si_domain;
-       else
-               /* page table init */
-               domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
+              "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n",
+              pci_name(pdev), start, end);
+
+       domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
        if (!domain)
                return -ENOMEM;
 
-       /* The address might not be aligned */
-       base = start & PAGE_MASK;
-       size = end - base;
-       size = PAGE_ALIGN(size);
-       if (!reserve_iova(&domain->iovad, IOVA_PFN(base),
-                       IOVA_PFN(base + size) - 1)) {
-               printk(KERN_ERR "IOMMU: reserve iova failed\n");
-               ret = -ENOMEM;
-               goto error;
-       }
-
-       pr_debug("Mapping reserved region %lx@%llx for %s\n",
-               size, base, pci_name(pdev));
-       /*
-        * RMRR range might have overlap with physical memory range,
-        * clear it first
-        */
-       dma_pte_clear_range(domain, base, base + size);
-
-       ret = domain_page_mapping(domain, base, base, size,
-               DMA_PTE_READ|DMA_PTE_WRITE);
+       ret = iommu_domain_identity_map(domain, start, end);
        if (ret)
                goto error;
 
        /* context entry init */
        ret = domain_context_mapping(domain, pdev, CONTEXT_TT_MULTI_LEVEL);
-       if (!ret)
-               return 0;
-error:
+       if (ret)
+               goto error;
+
+       return 0;
+
+ error:
        domain_exit(domain);
        return ret;
-
 }
 
 static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
@@ -1908,64 +1991,6 @@ static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr,
                rmrr->end_address + 1);
 }
 
-#ifdef CONFIG_DMAR_GFX_WA
-struct iommu_prepare_data {
-       struct pci_dev *pdev;
-       int ret;
-};
-
-static int __init iommu_prepare_work_fn(unsigned long start_pfn,
-                                        unsigned long end_pfn, void *datax)
-{
-       struct iommu_prepare_data *data;
-
-       data = (struct iommu_prepare_data *)datax;
-
-       data->ret = iommu_prepare_identity_map(data->pdev,
-                               start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);
-       return data->ret;
-
-}
-
-static int __init iommu_prepare_with_active_regions(struct pci_dev *pdev)
-{
-       int nid;
-       struct iommu_prepare_data data;
-
-       data.pdev = pdev;
-       data.ret = 0;
-
-       for_each_online_node(nid) {
-               work_with_active_regions(nid, iommu_prepare_work_fn, &data);
-               if (data.ret)
-                       return data.ret;
-       }
-       return data.ret;
-}
-
-static void __init iommu_prepare_gfx_mapping(void)
-{
-       struct pci_dev *pdev = NULL;
-       int ret;
-
-       for_each_pci_dev(pdev) {
-               if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO ||
-                               !IS_GFX_DEVICE(pdev))
-                       continue;
-               printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n",
-                       pci_name(pdev));
-               ret = iommu_prepare_with_active_regions(pdev);
-               if (ret)
-                       printk(KERN_ERR "IOMMU: mapping reserved region failed\n");
-       }
-}
-#else /* !CONFIG_DMAR_GFX_WA */
-static inline void iommu_prepare_gfx_mapping(void)
-{
-       return;
-}
-#endif
-
 #ifdef CONFIG_DMAR_FLOPPY_WA
 static inline void iommu_prepare_isa(void)
 {
@@ -1976,12 +2001,12 @@ static inline void iommu_prepare_isa(void)
        if (!pdev)
                return;
 
-       printk(KERN_INFO "IOMMU: Prepare 0-16M unity mapping for LPC\n");
+       printk(KERN_INFO "IOMMU: Prepare 0-16MiB unity mapping for LPC\n");
        ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024);
 
        if (ret)
-               printk(KERN_ERR "IOMMU: Failed to create 0-64M identity map, "
-                       "floppy might not work\n");
+               printk(KERN_ERR "IOMMU: Failed to create 0-16MiB identity map; "
+                      "floppy might not work\n");
 
 }
 #else
@@ -2009,16 +2034,30 @@ static int __init init_context_pass_through(void)
 }
 
 static int md_domain_init(struct dmar_domain *domain, int guest_width);
+
+static int __init si_domain_work_fn(unsigned long start_pfn,
+                                   unsigned long end_pfn, void *datax)
+{
+       int *ret = datax;
+
+       *ret = iommu_domain_identity_map(si_domain,
+                                        (uint64_t)start_pfn << PAGE_SHIFT,
+                                        (uint64_t)end_pfn << PAGE_SHIFT);
+       return *ret;
+
+}
+
 static int si_domain_init(void)
 {
        struct dmar_drhd_unit *drhd;
        struct intel_iommu *iommu;
-       int ret = 0;
+       int nid, ret = 0;
 
        si_domain = alloc_domain();
        if (!si_domain)
                return -EFAULT;
 
+       pr_debug("Identity mapping domain is domain %d\n", si_domain->id);
 
        for_each_active_iommu(iommu, drhd) {
                ret = iommu_attach_domain(si_domain, iommu);
@@ -2035,6 +2074,12 @@ static int si_domain_init(void)
 
        si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY;
 
+       for_each_online_node(nid) {
+               work_with_active_regions(nid, si_domain_work_fn, &ret);
+               if (ret)
+                       return ret;
+       }
+
        return 0;
 }
 
@@ -2079,9 +2124,49 @@ static int domain_add_dev_info(struct dmar_domain *domain,
        return 0;
 }
 
+static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
+{
+       if (iommu_identity_mapping == 2)
+               return IS_GFX_DEVICE(pdev);
+
+       /*
+        * We want to start off with all devices in the 1:1 domain, and
+        * take them out later if we find they can't access all of memory.
+        *
+        * However, we can't do this for PCI devices behind bridges,
+        * because all PCI devices behind the same bridge will end up
+        * with the same source-id on their transactions.
+        *
+        * Practically speaking, we can't change things around for these
+        * devices at run-time, because we can't be sure there'll be no
+        * DMA transactions in flight for any of their siblings.
+        * 
+        * So PCI devices (unless they're on the root bus) as well as
+        * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
+        * the 1:1 domain, just in _case_ one of their siblings turns out
+        * not to be able to map all of memory.
+        */
+       if (!pdev->is_pcie) {
+               if (!pci_is_root_bus(pdev->bus))
+                       return 0;
+               if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
+                       return 0;
+       } else if (pdev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
+               return 0;
+
+       /* 
+        * At boot time, we don't yet know if devices will be 64-bit capable.
+        * Assume that they will -- if they turn out not to be, then we can 
+        * take them out of the 1:1 domain later.
+        */
+       if (!startup)
+               return pdev->dma_mask > DMA_BIT_MASK(32);
+
+       return 1;
+}
+
 static int iommu_prepare_static_identity_mapping(void)
 {
-       int i;
        struct pci_dev *pdev = NULL;
        int ret;
 
@@ -2089,23 +2174,19 @@ static int iommu_prepare_static_identity_mapping(void)
        if (ret)
                return -EFAULT;
 
-       printk(KERN_INFO "IOMMU: Setting identity map:\n");
        for_each_pci_dev(pdev) {
-               for (i = 0; i < e820.nr_map; i++) {
-                       struct e820entry *ei = &e820.map[i];
-
-                       if (ei->type == E820_RAM) {
-                               ret = iommu_prepare_identity_map(pdev,
-                                       ei->addr, ei->addr + ei->size);
-                               if (ret)  {
-                                       printk(KERN_INFO "1:1 mapping to one domain failed.\n");
-                                       return -EFAULT;
-                               }
-                       }
+               if (iommu_should_identity_map(pdev, 1)) {
+                       printk(KERN_INFO "IOMMU: identity mapping for device %s\n",
+                              pci_name(pdev));
+
+                       ret = domain_context_mapping(si_domain, pdev,
+                                                    CONTEXT_TT_MULTI_LEVEL);
+                       if (ret)
+                               return ret;
+                       ret = domain_add_dev_info(si_domain, pdev);
+                       if (ret)
+                               return ret;
                }
-               ret = domain_add_dev_info(si_domain, pdev);
-               if (ret)
-                       return ret;
        }
 
        return 0;
@@ -2260,6 +2341,10 @@ int __init init_dmars(void)
         * identity mapping if iommu_identity_mapping is set.
         */
        if (!iommu_pass_through) {
+#ifdef CONFIG_DMAR_BROKEN_GFX_WA
+               if (!iommu_identity_mapping)
+                       iommu_identity_mapping = 2;
+#endif
                if (iommu_identity_mapping)
                        iommu_prepare_static_identity_mapping();
                /*
@@ -2293,8 +2378,6 @@ int __init init_dmars(void)
                        }
                }
 
-               iommu_prepare_gfx_mapping();
-
                iommu_prepare_isa();
        }
 
@@ -2339,50 +2422,32 @@ error:
        return ret;
 }
 
-static inline u64 aligned_size(u64 host_addr, size_t size)
-{
-       u64 addr;
-       addr = (host_addr & (~PAGE_MASK)) + size;
-       return PAGE_ALIGN(addr);
-}
-
-struct iova *
-iommu_alloc_iova(struct dmar_domain *domain, size_t size, u64 end)
-{
-       struct iova *piova;
-
-       /* Make sure it's in range */
-       end = min_t(u64, DOMAIN_MAX_ADDR(domain->gaw), end);
-       if (!size || (IOVA_START_ADDR + size > end))
-               return NULL;
-
-       piova = alloc_iova(&domain->iovad,
-                       size >> PAGE_SHIFT, IOVA_PFN(end), 1);
-       return piova;
-}
-
-static struct iova *
-__intel_alloc_iova(struct device *dev, struct dmar_domain *domain,
-                  size_t size, u64 dma_mask)
+/* This takes a number of _MM_ pages, not VTD pages */
+static struct iova *intel_alloc_iova(struct device *dev,
+                                    struct dmar_domain *domain,
+                                    unsigned long nrpages, uint64_t dma_mask)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct iova *iova = NULL;
 
-       if (dma_mask <= DMA_BIT_MASK(32) || dmar_forcedac)
-               iova = iommu_alloc_iova(domain, size, dma_mask);
-       else {
+       /* Restrict dma_mask to the width that the iommu can handle */
+       dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask);
+
+       if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
                /*
                 * First try to allocate an io virtual address in
                 * DMA_BIT_MASK(32) and if that fails then try allocating
                 * from higher range
                 */
-               iova = iommu_alloc_iova(domain, size, DMA_BIT_MASK(32));
-               if (!iova)
-                       iova = iommu_alloc_iova(domain, size, dma_mask);
-       }
-
-       if (!iova) {
-               printk(KERN_ERR"Allocating iova for %s failed", pci_name(pdev));
+               iova = alloc_iova(&domain->iovad, nrpages,
+                                 IOVA_PFN(DMA_BIT_MASK(32)), 1);
+               if (iova)
+                       return iova;
+       }
+       iova = alloc_iova(&domain->iovad, nrpages, IOVA_PFN(dma_mask), 1);
+       if (unlikely(!iova)) {
+               printk(KERN_ERR "Allocating %ld-page iova for %s failed",
+                      nrpages, pci_name(pdev));
                return NULL;
        }
 
@@ -2424,16 +2489,24 @@ static int iommu_dummy(struct pci_dev *pdev)
 }
 
 /* Check if the pdev needs to go through non-identity map and unmap process.*/
-static int iommu_no_mapping(struct pci_dev *pdev)
+static int iommu_no_mapping(struct device *dev)
 {
+       struct pci_dev *pdev;
        int found;
 
+       if (unlikely(dev->bus != &pci_bus_type))
+               return 1;
+
+       pdev = to_pci_dev(dev);
+       if (iommu_dummy(pdev))
+               return 1;
+
        if (!iommu_identity_mapping)
-               return iommu_dummy(pdev);
+               return 0;
 
        found = identity_mapping(pdev);
        if (found) {
-               if (pdev->dma_mask > DMA_BIT_MASK(32))
+               if (iommu_should_identity_map(pdev, 0))
                        return 1;
                else {
                        /*
@@ -2450,9 +2523,12 @@ static int iommu_no_mapping(struct pci_dev *pdev)
                 * In case of a detached 64 bit DMA device from vm, the device
                 * is put into si_domain for identity mapping.
                 */
-               if (pdev->dma_mask > DMA_BIT_MASK(32)) {
+               if (iommu_should_identity_map(pdev, 0)) {
                        int ret;
                        ret = domain_add_dev_info(si_domain, pdev);
+                       if (ret)
+                               return 0;
+                       ret = domain_context_mapping(si_domain, pdev, CONTEXT_TT_MULTI_LEVEL);
                        if (!ret) {
                                printk(KERN_INFO "64bit %s uses identity mapping\n",
                                       pci_name(pdev));
@@ -2461,7 +2537,7 @@ static int iommu_no_mapping(struct pci_dev *pdev)
                }
        }
 
-       return iommu_dummy(pdev);
+       return 0;
 }
 
 static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
@@ -2474,10 +2550,11 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
        int prot = 0;
        int ret;
        struct intel_iommu *iommu;
+       unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
 
        BUG_ON(dir == DMA_NONE);
 
-       if (iommu_no_mapping(pdev))
+       if (iommu_no_mapping(hwdev))
                return paddr;
 
        domain = get_valid_domain_for_dev(pdev);
@@ -2485,14 +2562,13 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
                return 0;
 
        iommu = domain_get_iommu(domain);
-       size = aligned_size((u64)paddr, size);
+       size = aligned_nrpages(paddr, size);
 
-       iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask);
+       iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size),
+                               pdev->dma_mask);
        if (!iova)
                goto error;
 
-       start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT;
-
        /*
         * Check if DMAR supports zero-length reads on write only
         * mappings..
@@ -2508,20 +2584,20 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
         * might have two guest_addr mapping to the same host paddr, but this
         * is not a big problem
         */
-       ret = domain_page_mapping(domain, start_paddr,
-                                 ((u64)paddr) & PHYSICAL_PAGE_MASK,
-                                 size, prot);
+       ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova->pfn_lo),
+                                mm_to_dma_pfn(paddr_pfn), size, prot);
        if (ret)
                goto error;
 
        /* it's a non-present to present mapping. Only flush if caching mode */
        if (cap_caching_mode(iommu->cap))
-               iommu_flush_iotlb_psi(iommu, 0, start_paddr,
-                                     size >> VTD_PAGE_SHIFT);
+               iommu_flush_iotlb_psi(iommu, 0, mm_to_dma_pfn(iova->pfn_lo), size);
        else
                iommu_flush_write_buffer(iommu);
 
-       return start_paddr + ((u64)paddr & (~PAGE_MASK));
+       start_paddr = (phys_addr_t)iova->pfn_lo << PAGE_SHIFT;
+       start_paddr += paddr & ~PAGE_MASK;
+       return start_paddr;
 
 error:
        if (iova)
@@ -2614,11 +2690,11 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct dmar_domain *domain;
-       unsigned long start_addr;
+       unsigned long start_pfn, last_pfn;
        struct iova *iova;
        struct intel_iommu *iommu;
 
-       if (iommu_no_mapping(pdev))
+       if (iommu_no_mapping(dev))
                return;
 
        domain = find_domain(pdev);
@@ -2627,22 +2703,25 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
        iommu = domain_get_iommu(domain);
 
        iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr));
-       if (!iova)
+       if (WARN_ONCE(!iova, "Driver unmaps unmatched page at PFN %llx\n",
+                     (unsigned long long)dev_addr))
                return;
 
-       start_addr = iova->pfn_lo << PAGE_SHIFT;
-       size = aligned_size((u64)dev_addr, size);
+       start_pfn = mm_to_dma_pfn(iova->pfn_lo);
+       last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
 
-       pr_debug("Device %s unmapping: %zx@%llx\n",
-               pci_name(pdev), size, (unsigned long long)start_addr);
+       pr_debug("Device %s unmapping: pfn %lx-%lx\n",
+                pci_name(pdev), start_pfn, last_pfn);
 
        /*  clear the whole page */
-       dma_pte_clear_range(domain, start_addr, start_addr + size);
+       dma_pte_clear_range(domain, start_pfn, last_pfn);
+
        /* free page tables */
-       dma_pte_free_pagetable(domain, start_addr, start_addr + size);
+       dma_pte_free_pagetable(domain, start_pfn, last_pfn);
+
        if (intel_iommu_strict) {
-               iommu_flush_iotlb_psi(iommu, domain->id, start_addr,
-                                     size >> VTD_PAGE_SHIFT);
+               iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
+                                     last_pfn - start_pfn + 1);
                /* free iova */
                __free_iova(&domain->iovad, iova);
        } else {
@@ -2700,17 +2779,13 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
                           int nelems, enum dma_data_direction dir,
                           struct dma_attrs *attrs)
 {
-       int i;
        struct pci_dev *pdev = to_pci_dev(hwdev);
        struct dmar_domain *domain;
-       unsigned long start_addr;
+       unsigned long start_pfn, last_pfn;
        struct iova *iova;
-       size_t size = 0;
-       phys_addr_t addr;
-       struct scatterlist *sg;
        struct intel_iommu *iommu;
 
-       if (iommu_no_mapping(pdev))
+       if (iommu_no_mapping(hwdev))
                return;
 
        domain = find_domain(pdev);
@@ -2719,22 +2794,21 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist,
        iommu = domain_get_iommu(domain);
 
        iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address));
-       if (!iova)
+       if (WARN_ONCE(!iova, "Driver unmaps unmatched sglist at PFN %llx\n",
+                     (unsigned long long)sglist[0].dma_address))
                return;
-       for_each_sg(sglist, sg, nelems, i) {
-               addr = page_to_phys(sg_page(sg)) + sg->offset;
-               size += aligned_size((u64)addr, sg->length);
-       }
 
-       start_addr = iova->pfn_lo << PAGE_SHIFT;
+       start_pfn = mm_to_dma_pfn(iova->pfn_lo);
+       last_pfn = mm_to_dma_pfn(iova->pfn_hi + 1) - 1;
 
        /*  clear the whole page */
-       dma_pte_clear_range(domain, start_addr, start_addr + size);
+       dma_pte_clear_range(domain, start_pfn, last_pfn);
+
        /* free page tables */
-       dma_pte_free_pagetable(domain, start_addr, start_addr + size);
+       dma_pte_free_pagetable(domain, start_pfn, last_pfn);
 
-       iommu_flush_iotlb_psi(iommu, domain->id, start_addr,
-                             size >> VTD_PAGE_SHIFT);
+       iommu_flush_iotlb_psi(iommu, domain->id, start_pfn,
+                             (last_pfn - start_pfn + 1));
 
        /* free iova */
        __free_iova(&domain->iovad, iova);
@@ -2757,21 +2831,20 @@ static int intel_nontranslate_map_sg(struct device *hddev,
 static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int nelems,
                        enum dma_data_direction dir, struct dma_attrs *attrs)
 {
-       phys_addr_t addr;
        int i;
        struct pci_dev *pdev = to_pci_dev(hwdev);
        struct dmar_domain *domain;
        size_t size = 0;
        int prot = 0;
-       size_t offset = 0;
+       size_t offset_pfn = 0;
        struct iova *iova = NULL;
        int ret;
        struct scatterlist *sg;
-       unsigned long start_addr;
+       unsigned long start_vpfn;
        struct intel_iommu *iommu;
 
        BUG_ON(dir == DMA_NONE);
-       if (iommu_no_mapping(pdev))
+       if (iommu_no_mapping(hwdev))
                return intel_nontranslate_map_sg(hwdev, sglist, nelems, dir);
 
        domain = get_valid_domain_for_dev(pdev);
@@ -2780,12 +2853,11 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne
 
        iommu = domain_get_iommu(domain);
 
-       for_each_sg(sglist, sg, nelems, i) {
-               addr = page_to_phys(sg_page(sg)) + sg->offset;
-               size += aligned_size((u64)addr, sg->length);
-       }
+       for_each_sg(sglist, sg, nelems, i)
+               size += aligned_nrpages(sg->offset, sg->length);
 
-       iova = __intel_alloc_iova(hwdev, domain, size, pdev->dma_mask);
+       iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size),
+                               pdev->dma_mask);
        if (!iova) {
                sglist->dma_length = 0;
                return 0;
@@ -2801,35 +2873,24 @@ static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, int ne
        if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
                prot |= DMA_PTE_WRITE;
 
-       start_addr = iova->pfn_lo << PAGE_SHIFT;
-       offset = 0;
-       for_each_sg(sglist, sg, nelems, i) {
-               addr = page_to_phys(sg_page(sg)) + sg->offset;
-               size = aligned_size((u64)addr, sg->length);
-               ret = domain_page_mapping(domain, start_addr + offset,
-                                         ((u64)addr) & PHYSICAL_PAGE_MASK,
-                                         size, prot);
-               if (ret) {
-                       /*  clear the page */
-                       dma_pte_clear_range(domain, start_addr,
-                                 start_addr + offset);
-                       /* free page tables */
-                       dma_pte_free_pagetable(domain, start_addr,
-                                 start_addr + offset);
-                       /* free iova */
-                       __free_iova(&domain->iovad, iova);
-                       return 0;
-               }
-               sg->dma_address = start_addr + offset +
-                               ((u64)addr & (~PAGE_MASK));
-               sg->dma_length = sg->length;
-               offset += size;
+       start_vpfn = mm_to_dma_pfn(iova->pfn_lo);
+
+       ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
+       if (unlikely(ret)) {
+               /*  clear the page */
+               dma_pte_clear_range(domain, start_vpfn,
+                                   start_vpfn + size - 1);
+               /* free page tables */
+               dma_pte_free_pagetable(domain, start_vpfn,
+                                      start_vpfn + size - 1);
+               /* free iova */
+               __free_iova(&domain->iovad, iova);
+               return 0;
        }
 
        /* it's a non-present to present mapping. Only flush if caching mode */
        if (cap_caching_mode(iommu->cap))
-               iommu_flush_iotlb_psi(iommu, 0, start_addr,
-                                     offset >> VTD_PAGE_SHIFT);
+               iommu_flush_iotlb_psi(iommu, 0, start_vpfn, offset_pfn);
        else
                iommu_flush_write_buffer(iommu);
 
@@ -3334,7 +3395,6 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width)
        int adjust_width;
 
        init_iova_domain(&domain->iovad, DMA_32BIT_PFN);
-       spin_lock_init(&domain->mapping_lock);
        spin_lock_init(&domain->iommu_lock);
 
        domain_reserve_special_ranges(domain);
@@ -3348,6 +3408,7 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width)
 
        domain->iommu_count = 0;
        domain->iommu_coherency = 0;
+       domain->iommu_snooping = 0;
        domain->max_addr = 0;
 
        /* always allocate the top pgd */
@@ -3388,8 +3449,6 @@ static void iommu_free_vm_domain(struct dmar_domain *domain)
 
 static void vm_domain_exit(struct dmar_domain *domain)
 {
-       u64 end;
-
        /* Domain 0 is reserved, so dont process it */
        if (!domain)
                return;
@@ -3397,14 +3456,12 @@ static void vm_domain_exit(struct dmar_domain *domain)
        vm_domain_remove_all_dev_info(domain);
        /* destroy iovas */
        put_iova_domain(&domain->iovad);
-       end = DOMAIN_MAX_ADDR(domain->gaw);
-       end = end & (~VTD_PAGE_MASK);
 
        /* clear ptes */
-       dma_pte_clear_range(domain, 0, end);
+       dma_pte_clear_range(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
 
        /* free page tables */
-       dma_pte_free_pagetable(domain, 0, end);
+       dma_pte_free_pagetable(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
 
        iommu_free_vm_domain(domain);
        free_domain_mem(domain);
@@ -3513,7 +3570,7 @@ static int intel_iommu_map_range(struct iommu_domain *domain,
        if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
                prot |= DMA_PTE_SNP;
 
-       max_addr = (iova & VTD_PAGE_MASK) + VTD_PAGE_ALIGN(size);
+       max_addr = iova + size;
        if (dmar_domain->max_addr < max_addr) {
                int min_agaw;
                u64 end;
@@ -3531,8 +3588,11 @@ static int intel_iommu_map_range(struct iommu_domain *domain,
                }
                dmar_domain->max_addr = max_addr;
        }
-
-       ret = domain_page_mapping(dmar_domain, iova, hpa, size, prot);
+       /* Round up size to next multiple of PAGE_SIZE, if it and
+          the low bits of hpa would take us onto the next page */
+       size = aligned_nrpages(hpa, size);
+       ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
+                                hpa >> VTD_PAGE_SHIFT, size, prot);
        return ret;
 }
 
@@ -3540,15 +3600,15 @@ static void intel_iommu_unmap_range(struct iommu_domain *domain,
                                    unsigned long iova, size_t size)
 {
        struct dmar_domain *dmar_domain = domain->priv;
-       dma_addr_t base;
 
-       /* The address might not be aligned */
-       base = iova & VTD_PAGE_MASK;
-       size = VTD_PAGE_ALIGN(size);
-       dma_pte_clear_range(dmar_domain, base, base + size);
+       if (!size)
+               return;
+
+       dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT,
+                           (iova + size - 1) >> VTD_PAGE_SHIFT);
 
-       if (dmar_domain->max_addr == base + size)
-               dmar_domain->max_addr = base;
+       if (dmar_domain->max_addr == iova + size)
+               dmar_domain->max_addr = iova;
 }
 
 static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
@@ -3558,7 +3618,7 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
        struct dma_pte *pte;
        u64 phys = 0;
 
-       pte = addr_to_dma_pte(dmar_domain, iova);
+       pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT);
        if (pte)
                phys = dma_pte_addr(pte);
 
index e3a87210e947cdce8d57ded76c63cfb2ba07e788..e03fe98f06193c1c6a1fa22cbf6db92a0dbd2c6a 100644 (file)
@@ -597,6 +597,29 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno,
                4 * (resno - PCI_IOV_RESOURCES);
 }
 
+/**
+ * pci_sriov_resource_alignment - get resource alignment for VF BAR
+ * @dev: the PCI device
+ * @resno: the resource number
+ *
+ * Returns the alignment of the VF BAR found in the SR-IOV capability.
+ * This is not the same as the resource size which is defined as
+ * the VF BAR size multiplied by the number of VFs.  The alignment
+ * is just the VF BAR size.
+ */
+int pci_sriov_resource_alignment(struct pci_dev *dev, int resno)
+{
+       struct resource tmp;
+       enum pci_bar_type type;
+       int reg = pci_iov_resource_bar(dev, resno, &type);
+       
+       if (!reg)
+               return 0;
+
+        __pci_read_base(dev, type, &tmp, reg);
+       return resource_alignment(&tmp);
+}
+
 /**
  * pci_restore_iov_state - restore the state of the IOV capability
  * @dev: the PCI device
index 2287116e9822472a1ef879bd6facfbd30920b087..46dd440e2315d2ec7beaf096c00fae5c3c11df1a 100644 (file)
@@ -1,9 +1,19 @@
 /*
- * Copyright (c) 2006, Intel Corporation.
+ * Copyright © 2006-2009, Intel Corporation.
  *
- * This file is released under the GPLv2.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
  *
- * Copyright (C) 2006-2008 Intel Corporation
  * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
  */
 
@@ -123,7 +133,15 @@ move_left:
        /* Insert the new_iova into domain rbtree by holding writer lock */
        /* Add new node and rebalance tree. */
        {
-               struct rb_node **entry = &((prev)), *parent = NULL;
+               struct rb_node **entry, *parent = NULL;
+
+               /* If we have 'prev', it's a valid place to start the
+                  insertion. Otherwise, start from the root. */
+               if (prev)
+                       entry = &prev;
+               else
+                       entry = &iovad->rbroot.rb_node;
+
                /* Figure out where to put new node */
                while (*entry) {
                        struct iova *this = container_of(*entry,
index d9f06fbfa0bf8fd56051d5f1bd2252fdc52377f8..d986afb7032bbaf5ad70a32c59e67701b741e8e6 100644 (file)
@@ -127,17 +127,23 @@ static inline __attribute_const__ u32 msi_enabled_mask(u16 control)
  * reliably as devices without an INTx disable bit will then generate a
  * level IRQ which will never be cleared.
  */
-static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
+static u32 __msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
 {
        u32 mask_bits = desc->masked;
 
        if (!desc->msi_attrib.maskbit)
-               return;
+               return 0;
 
        mask_bits &= ~mask;
        mask_bits |= flag;
        pci_write_config_dword(desc->dev, desc->mask_pos, mask_bits);
-       desc->masked = mask_bits;
+
+       return mask_bits;
+}
+
+static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
+{
+       desc->masked = __msi_mask_irq(desc, mask, flag);
 }
 
 /*
@@ -147,15 +153,21 @@ static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
  * file.  This saves a few milliseconds when initialising devices with lots
  * of MSI-X interrupts.
  */
-static void msix_mask_irq(struct msi_desc *desc, u32 flag)
+static u32 __msix_mask_irq(struct msi_desc *desc, u32 flag)
 {
        u32 mask_bits = desc->masked;
        unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
-                                       PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
+                                               PCI_MSIX_ENTRY_VECTOR_CTRL;
        mask_bits &= ~1;
        mask_bits |= flag;
        writel(mask_bits, desc->mask_base + offset);
-       desc->masked = mask_bits;
+
+       return mask_bits;
+}
+
+static void msix_mask_irq(struct msi_desc *desc, u32 flag)
+{
+       desc->masked = __msix_mask_irq(desc, flag);
 }
 
 static void msi_set_mask_bit(unsigned irq, u32 flag)
@@ -188,9 +200,9 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
                void __iomem *base = entry->mask_base +
                        entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
 
-               msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
-               msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
-               msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET);
+               msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR);
+               msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR);
+               msg->data = readl(base + PCI_MSIX_ENTRY_DATA);
        } else {
                struct pci_dev *dev = entry->dev;
                int pos = entry->msi_attrib.pos;
@@ -225,11 +237,9 @@ void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
                base = entry->mask_base +
                        entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
 
-               writel(msg->address_lo,
-                       base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
-               writel(msg->address_hi,
-                       base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
-               writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET);
+               writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR);
+               writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR);
+               writel(msg->data, base + PCI_MSIX_ENTRY_DATA);
        } else {
                struct pci_dev *dev = entry->dev;
                int pos = entry->msi_attrib.pos;
@@ -385,6 +395,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
        /* Configure MSI capability structure */
        ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI);
        if (ret) {
+               msi_mask_irq(entry, mask, ~mask);
                msi_free_irqs(dev);
                return ret;
        }
@@ -439,8 +450,14 @@ static int msix_capability_init(struct pci_dev *dev,
 
        for (i = 0; i < nvec; i++) {
                entry = alloc_msi_entry(dev);
-               if (!entry)
-                       break;
+               if (!entry) {
+                       if (!i)
+                               iounmap(base);
+                       else
+                               msi_free_irqs(dev);
+                       /* No enough memory. Don't try again */
+                       return -ENOMEM;
+               }
 
                j = entries[i].entry;
                entry->msi_attrib.is_msix = 1;
@@ -487,7 +504,7 @@ static int msix_capability_init(struct pci_dev *dev,
                set_irq_msi(entry->irq, entry);
                j = entries[i].entry;
                entry->masked = readl(base + j * PCI_MSIX_ENTRY_SIZE +
-                                       PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
+                                               PCI_MSIX_ENTRY_VECTOR_CTRL);
                msix_mask_irq(entry, 1);
                i++;
        }
@@ -611,9 +628,11 @@ void pci_msi_shutdown(struct pci_dev *dev)
        pci_intx_for_msi(dev, 1);
        dev->msi_enabled = 0;
 
+       /* Return the device with MSI unmasked as initial states */
        pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &ctrl);
        mask = msi_capable_mask(ctrl);
-       msi_mask_irq(desc, mask, ~mask);
+       /* Keep cached state to be restored */
+       __msi_mask_irq(desc, mask, ~mask);
 
        /* Restore dev->irq to its default pin-assertion irq */
        dev->irq = desc->msi_attrib.default_irq;
@@ -653,7 +672,6 @@ static int msi_free_irqs(struct pci_dev* dev)
 
        list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) {
                if (entry->msi_attrib.is_msix) {
-                       msix_mask_irq(entry, 1);
                        if (list_is_last(&entry->list, &dev->msi_list))
                                iounmap(entry->mask_base);
                }
@@ -741,9 +759,17 @@ static void msix_free_all_irqs(struct pci_dev *dev)
 
 void pci_msix_shutdown(struct pci_dev* dev)
 {
+       struct msi_desc *entry;
+
        if (!pci_msi_enable || !dev || !dev->msix_enabled)
                return;
 
+       /* Return the device with MSI-X masked as initial states */
+       list_for_each_entry(entry, &dev->msi_list, list) {
+               /* Keep cached states to be restored */
+               __msix_mask_irq(entry, 1);
+       }
+
        msix_set_enable(dev, 0);
        pci_intx_for_msi(dev, 1);
        dev->msix_enabled = 0;
index a0662842550bcb91c008272ba7194f5b97e35388..de27c1cb5a2bb8be30a3003ca47c45eac37c9d2a 100644 (file)
@@ -6,11 +6,11 @@
 #ifndef MSI_H
 #define MSI_H
 
-#define PCI_MSIX_ENTRY_SIZE                    16
-#define  PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET      0
-#define  PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET      4
-#define  PCI_MSIX_ENTRY_DATA_OFFSET            8
-#define  PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET     12
+#define PCI_MSIX_ENTRY_SIZE            16
+#define  PCI_MSIX_ENTRY_LOWER_ADDR     0
+#define  PCI_MSIX_ENTRY_UPPER_ADDR     4
+#define  PCI_MSIX_ENTRY_DATA           8
+#define  PCI_MSIX_ENTRY_VECTOR_CTRL    12
 
 #define msi_control_reg(base)          (base + PCI_MSI_FLAGS)
 #define msi_lower_address_reg(base)    (base + PCI_MSI_ADDRESS_LO)
index d76c4c85367e4368963c9d71092bdaaad6888ce3..f99bc7f089f1ab8c0839775c58f2cabc487e37cf 100644 (file)
@@ -508,7 +508,7 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev)
                        return error;
        }
 
-       return pci_dev->state_saved ? pci_restore_state(pci_dev) : 0;
+       return pci_restore_state(pci_dev);
 }
 
 static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
index 6c93af5ced186bd9a18faaea77fb0d160d37aba8..7b70312181d78a28cdfba11639c673626ee8eed6 100644 (file)
@@ -846,6 +846,8 @@ pci_restore_state(struct pci_dev *dev)
        int i;
        u32 val;
 
+       if (!dev->state_saved)
+               return 0;
        /* PCI Express register must be restored first */
        pci_restore_pcie_state(dev);
 
@@ -1517,11 +1519,20 @@ void pci_enable_ari(struct pci_dev *dev)
  *
  * Perform INTx swizzling for a device behind one level of bridge.  This is
  * required by section 9.1 of the PCI-to-PCI bridge specification for devices
- * behind bridges on add-in cards.
+ * behind bridges on add-in cards.  For devices with ARI enabled, the slot
+ * number is always 0 (see the Implementation Note in section 2.2.8.1 of
+ * the PCI Express Base Specification, Revision 2.1)
  */
 u8 pci_swizzle_interrupt_pin(struct pci_dev *dev, u8 pin)
 {
-       return (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1;
+       int slot;
+
+       if (pci_ari_enabled(dev->bus))
+               slot = 0;
+       else
+               slot = PCI_SLOT(dev->devfn);
+
+       return (((pin - 1) + slot) % 4) + 1;
 }
 
 int
@@ -2171,7 +2182,7 @@ static int pci_parent_bus_reset(struct pci_dev *dev, int probe)
        u16 ctrl;
        struct pci_dev *pdev;
 
-       if (dev->subordinate)
+       if (pci_is_root_bus(dev->bus) || dev->subordinate || !dev->bus->self)
                return -ENOTTY;
 
        list_for_each_entry(pdev, &dev->bus->devices, bus_list)
index f73bcbedf37c492344d92bed0ef5840db33ecbcc..5ff4d25bf0e938f28904f22b46b5c6505239af8e 100644 (file)
@@ -243,6 +243,7 @@ extern int pci_iov_init(struct pci_dev *dev);
 extern void pci_iov_release(struct pci_dev *dev);
 extern int pci_iov_resource_bar(struct pci_dev *dev, int resno,
                                enum pci_bar_type *type);
+extern int pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
 extern void pci_restore_iov_state(struct pci_dev *dev);
 extern int pci_iov_bus_range(struct pci_bus *bus);
 
@@ -298,4 +299,16 @@ static inline int pci_ats_enabled(struct pci_dev *dev)
 }
 #endif /* CONFIG_PCI_IOV */
 
+static inline int pci_resource_alignment(struct pci_dev *dev,
+                                        struct resource *res)
+{
+#ifdef CONFIG_PCI_IOV
+       int resno = res - dev->resource;
+
+       if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
+               return pci_sriov_resource_alignment(dev, resno);
+#endif
+       return resource_alignment(res);
+}
+
 #endif /* DRIVERS_PCI_H */
index ece97df4df6d1e8ccfceb32ee240c1d74c4af05d..a928d8ab6bda2a95f3fce746617778c53163585d 100644 (file)
@@ -106,7 +106,7 @@ void pcie_set_ecrc_checking(struct pci_dev *dev)
                disable_ecrc_checking(dev);
                break;
        case ECRC_POLICY_ON:
-               enable_ecrc_checking(dev);;
+               enable_ecrc_checking(dev);
                break;
        default:
                return;
index 56552d74abea1506e9d40df04f7ea0c0e3b3ab5b..06b96562396230e3c52dc6f6067fdf39e66597d1 100644 (file)
@@ -1058,6 +1058,11 @@ static void __devinit quirk_no_ata_d3(struct pci_dev *pdev)
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_ANY_ID, quirk_no_ata_d3);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, PCI_ANY_ID, quirk_no_ata_d3);
+/* ALi loses some register settings that we cannot then restore */
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, PCI_ANY_ID, quirk_no_ata_d3);
+/* VIA comes back fine but we need to keep it alive or ACPI GTM failures
+   occur when mode detecting */
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_no_ata_d3);
 
 /* This was originally an Alpha specific thing, but it really fits here.
  * The i82375 PCI/EISA bridge appears as non-classified. Fix that.
index b636e245445defa08b1b7a03d38d204388d6b717..7c443b4583ab67162dd97718636cb30cfbc93b8f 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/ioport.h>
 #include <linux/cache.h>
 #include <linux/slab.h>
-
+#include "pci.h"
 
 static void pbus_assign_resources_sorted(const struct pci_bus *bus)
 {
@@ -384,7 +384,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
                                continue;
                        r_size = resource_size(r);
                        /* For bridges size != alignment */
-                       align = resource_alignment(r);
+                       align = pci_resource_alignment(dev, r);
                        order = __ffs(align) - 20;
                        if (order > 11) {
                                dev_warn(&dev->dev, "BAR %d bad alignment %llx: "
index b711fb7181e241f1a744482d8151fd6ca9beb290..88cdd1a937d6bd3a91180690d9f4e60df92201f8 100644 (file)
@@ -100,16 +100,16 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
 {
        struct resource *res = &dev->resource[resource];
        struct resource *root;
-       char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge";
        int err;
 
        root = pci_find_parent_resource(dev, res);
 
        err = -EINVAL;
        if (root != NULL)
-               err = insert_resource(root, res);
+               err = request_resource(root, res);
 
        if (err) {
+               const char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge";
                dev_err(&dev->dev, "BAR %d: %s of %s %pR\n",
                        resource,
                        root ? "address space collision on" :
@@ -144,7 +144,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
 
        size = resource_size(res);
        min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
-       align = resource_alignment(res);
+       align = pci_resource_alignment(dev, res);
 
        /* First, try exact prefetching match.. */
        ret = pci_bus_alloc_resource(bus, res, size, align, min,
@@ -178,7 +178,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
        struct pci_bus *bus;
        int ret;
 
-       align = resource_alignment(res);
+       align = pci_resource_alignment(dev, res);
        if (!align) {
                dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus "
                        "alignment) %pR flags %#lx\n",
@@ -259,7 +259,7 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
                if (!(r->flags) || r->parent)
                        continue;
 
-               r_align = resource_alignment(r);
+               r_align = pci_resource_alignment(dev, r);
                if (!r_align) {
                        dev_warn(&dev->dev, "BAR %d: bogus alignment "
                                "%pR flags %#lx\n",
@@ -271,7 +271,7 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
                        struct resource_list *ln = list->next;
 
                        if (ln)
-                               align = resource_alignment(ln->res);
+                               align = pci_resource_alignment(ln->dev, ln->res);
 
                        if (r_align > align) {
                                tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
index eddb0748b0ea365b9acd4d5898a5547326bf5231..8c02b6c53bdbd483ce6161bc92ba83f0352bae51 100644 (file)
@@ -311,7 +311,7 @@ EXPORT_SYMBOL_GPL(pci_destroy_slot);
 #include <linux/pci_hotplug.h>
 /**
  * pci_hp_create_link - create symbolic link to the hotplug driver module.
- * @slot: struct pci_slot
+ * @pci_slot: struct pci_slot
  *
  * Helper function for pci_hotplug_core.c to create symbolic link to
  * the hotplug driver module.
@@ -334,7 +334,7 @@ EXPORT_SYMBOL_GPL(pci_hp_create_module_link);
 
 /**
  * pci_hp_remove_link - remove symbolic link to the hotplug driver module.
- * @slot: struct pci_slot
+ * @pci_slot: struct pci_slot
  *
  * Helper function for pci_hotplug_core.c to remove symbolic link to
  * the hotplug driver module.
index ec22284eed307ccf565eb83df55f960876f57cd4..e1c1ec5408934204c35025122cd5b64d6a14080e 100644 (file)
@@ -9,7 +9,6 @@
 
 #include <linux/errno.h>
 #include <linux/pci.h>
-#include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <asm/uaccess.h>
 #include "pci.h"
index 9ad97ea836e8a0fc6ccb4f0721f387fae44f5d68..8eb04230fec7a475c24bc012285dd86089b986ce 100644 (file)
@@ -472,7 +472,8 @@ static int __init init_tcic(void)
     init_timer(&poll_timer);
 
     /* Build interrupt mask */
-    printk(", %d sockets\n" KERN_INFO "  irq list (", sockets);
+    printk(KERN_CONT ", %d sockets\n", sockets);
+    printk(KERN_INFO "  irq list (");
     if (irq_list_count == 0)
        mask = irq_mask;
     else
index 659421d0ca46aeab37fac76aefdee41cc6a5562d..d4ad50d737b060392fdf2c82bc80a211a57f5be1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * vrc4171_card.c, NEC VRC4171 Card Controller driver for Socket Services.
  *
- * Copyright (C) 2003-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -32,7 +32,7 @@
 #include "i82365.h"
 
 MODULE_DESCRIPTION("NEC VRC4171 Card Controllers driver for Socket Services");
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
 MODULE_LICENSE("GPL");
 
 #define CARD_MAX_SLOTS         2
index 812f038e9bdaeea761c66dc978b583bc571bf9b0..9b3c15827e5c763208a82b212eb7ab6cc2e9919f 100644 (file)
@@ -6,7 +6,7 @@
  *     NEC VRC4173 CARDU driver for Socket Services
  *     (This device doesn't support CardBus. it is supporting only 16bit PC Card.)
  *
- * Copyright 2002,2003 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright 2002,2003 Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms of the GNU General Public License as published by the
@@ -41,7 +41,7 @@
 #include "vrc4173_cardu.h"
 
 MODULE_DESCRIPTION("NEC VRC4173 CARDU driver for Socket Services");
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
 MODULE_LICENSE("GPL");
 
 static int vrc4173_cardu_slots;
index 7d77c74120c1cb646fef6af93b80aa35bc964c01..a7d96018ed8d4c471a493b62dc732dd9d79e1d19 100644 (file)
@@ -5,7 +5,7 @@
  * BRIEF MODULE DESCRIPTION
  *     Include file for NEC VRC4173 CARDU.
  *
- * Copyright 2002 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ * Copyright 2002 Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms of the GNU General Public License as published by the
index 7232fe7104aa140c20b2b97b9a6bdc5717044747..77c6097ced80e5db1ba7926e95391e81f74895c0 100644 (file)
@@ -277,31 +277,6 @@ config THINKPAD_ACPI_UNSAFE_LEDS
          Say N here, unless you are building a kernel for your own
          use, and need to control the important firmware LEDs.
 
-config THINKPAD_ACPI_DOCK
-       bool "Legacy Docking Station Support"
-       depends on THINKPAD_ACPI
-       depends on ACPI_DOCK=n
-       default n
-       ---help---
-         Allows the thinkpad_acpi driver to handle docking station events.
-         This support was made obsolete by the generic ACPI docking station
-         support (CONFIG_ACPI_DOCK).  It will allow locking and removing the
-         laptop from the docking station, but will not properly connect PCI
-         devices.
-
-         If you are not sure, say N here.
-
-config THINKPAD_ACPI_BAY
-       bool "Legacy Removable Bay Support"
-       depends on THINKPAD_ACPI
-       default y
-       ---help---
-         Allows the thinkpad_acpi driver to handle removable bays.  It will
-         electrically disable the device in the bay, and also generate
-         notifications when the bay lever is ejected or inserted.
-
-         If you are not sure, say Y here.
-
 config THINKPAD_ACPI_VIDEO
        bool "Video output control support"
        depends on THINKPAD_ACPI
@@ -355,6 +330,7 @@ config EEEPC_LAPTOP
        depends on INPUT
        depends on EXPERIMENTAL
        depends on RFKILL || RFKILL = n
+       depends on HOTPLUG_PCI
        select BACKLIGHT_CLASS_DEVICE
        select HWMON
        ---help---
index be2fd6f916390af3b0de060b5726bc7cec676974..fb45f5ee8df12a79c49e68ca88736f31920e5d80 100644 (file)
@@ -973,7 +973,7 @@ static int acer_rfkill_set(void *data, bool blocked)
 {
        acpi_status status;
        u32 cap = (unsigned long)data;
-       status = set_u32(!!blocked, cap);
+       status = set_u32(!blocked, cap);
        if (ACPI_FAILURE(status))
                return -ENODEV;
        return 0;
index 4207b26ff990634d3a75d35394f20b4c80afba21..222ffb892f2299852d7e3d77dc109bdd412ca6e5 100644 (file)
@@ -16,6 +16,8 @@
  *  GNU General Public License for more details.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -31,6 +33,7 @@
 #include <linux/input.h>
 #include <linux/rfkill.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.h>
 
 #define EEEPC_LAPTOP_VERSION   "0.1"
 
 #define EEEPC_HOTK_DEVICE_NAME "Hotkey"
 #define EEEPC_HOTK_HID         "ASUS010"
 
-#define EEEPC_LOG      EEEPC_HOTK_FILE ": "
-#define EEEPC_ERR      KERN_ERR        EEEPC_LOG
-#define EEEPC_WARNING  KERN_WARNING    EEEPC_LOG
-#define EEEPC_NOTICE   KERN_NOTICE     EEEPC_LOG
-#define EEEPC_INFO     KERN_INFO       EEEPC_LOG
 
 /*
  * Definitions for Asus EeePC
@@ -141,8 +139,11 @@ struct eeepc_hotk {
        u16 event_count[128];           /* count for each event */
        struct input_dev *inputdev;
        u16 *keycode_map;
-       struct rfkill *eeepc_wlan_rfkill;
-       struct rfkill *eeepc_bluetooth_rfkill;
+       struct rfkill *wlan_rfkill;
+       struct rfkill *bluetooth_rfkill;
+       struct rfkill *wwan3g_rfkill;
+       struct hotplug_slot *hotplug_slot;
+       struct work_struct hotplug_work;
 };
 
 /* The actual device the driver binds to */
@@ -213,6 +214,15 @@ static struct acpi_driver eeepc_hotk_driver = {
        },
 };
 
+/* PCI hotplug ops */
+static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value);
+
+static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
+       .owner = THIS_MODULE,
+       .get_adapter_status = eeepc_get_adapter_status,
+       .get_power_status = eeepc_get_adapter_status,
+};
+
 /* The backlight device /sys/class/backlight */
 static struct backlight_device *eeepc_backlight_device;
 
@@ -274,20 +284,20 @@ static int set_acpi(int cm, int value)
                if (method == NULL)
                        return -ENODEV;
                if (write_acpi_int(ehotk->handle, method, value, NULL))
-                       printk(EEEPC_WARNING "Error writing %s\n", method);
+                       pr_warning("Error writing %s\n", method);
        }
        return 0;
 }
 
 static int get_acpi(int cm)
 {
-       int value = -1;
+       int value = -ENODEV;
        if ((ehotk->cm_supported & (0x1 << cm))) {
                const char *method = cm_getv[cm];
                if (method == NULL)
                        return -ENODEV;
                if (read_acpi_int(ehotk->handle, method, &value))
-                       printk(EEEPC_WARNING "Error reading %s\n", method);
+                       pr_warning("Error reading %s\n", method);
        }
        return value;
 }
@@ -359,13 +369,19 @@ static ssize_t store_sys_acpi(int cm, const char *buf, size_t count)
 
        rv = parse_arg(buf, count, &value);
        if (rv > 0)
-               set_acpi(cm, value);
+               value = set_acpi(cm, value);
+       if (value < 0)
+               return value;
        return rv;
 }
 
 static ssize_t show_sys_acpi(int cm, char *buf)
 {
-       return sprintf(buf, "%d\n", get_acpi(cm));
+       int value = get_acpi(cm);
+
+       if (value < 0)
+               return value;
+       return sprintf(buf, "%d\n", value);
 }
 
 #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm)                           \
@@ -539,6 +555,28 @@ static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
        return -EINVAL;
 }
 
+static void cmsg_quirk(int cm, const char *name)
+{
+       int dummy;
+
+       /* Some BIOSes do not report cm although it is avaliable.
+          Check if cm_getv[cm] works and, if yes, assume cm should be set. */
+       if (!(ehotk->cm_supported & (1 << cm))
+           && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) {
+               pr_info("%s (%x) not reported by BIOS,"
+                       " enabling anyway\n", name, 1 << cm);
+               ehotk->cm_supported |= 1 << cm;
+       }
+}
+
+static void cmsg_quirks(void)
+{
+       cmsg_quirk(CM_ASL_LID, "LID");
+       cmsg_quirk(CM_ASL_TYPE, "TYPE");
+       cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER");
+       cmsg_quirk(CM_ASL_TPD, "TPD");
+}
+
 static int eeepc_hotk_check(void)
 {
        const struct key_entry *key;
@@ -551,26 +589,24 @@ static int eeepc_hotk_check(void)
        if (ehotk->device->status.present) {
                if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
                                    &buffer)) {
-                       printk(EEEPC_ERR "Hotkey initialization failed\n");
+                       pr_err("Hotkey initialization failed\n");
                        return -ENODEV;
                } else {
-                       printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n",
-                              ehotk->init_flag);
+                       pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag);
                }
                /* get control methods supported */
                if (read_acpi_int(ehotk->handle, "CMSG"
                                   , &ehotk->cm_supported)) {
-                       printk(EEEPC_ERR
-                              "Get control methods supported failed\n");
+                       pr_err("Get control methods supported failed\n");
                        return -ENODEV;
                } else {
-                       printk(EEEPC_INFO
-                              "Get control methods supported: 0x%x\n",
-                              ehotk->cm_supported);
+                       cmsg_quirks();
+                       pr_info("Get control methods supported: 0x%x\n",
+                               ehotk->cm_supported);
                }
                ehotk->inputdev = input_allocate_device();
                if (!ehotk->inputdev) {
-                       printk(EEEPC_INFO "Unable to allocate input device\n");
+                       pr_info("Unable to allocate input device\n");
                        return 0;
                }
                ehotk->inputdev->name = "Asus EeePC extra buttons";
@@ -589,12 +625,12 @@ static int eeepc_hotk_check(void)
                }
                result = input_register_device(ehotk->inputdev);
                if (result) {
-                       printk(EEEPC_INFO "Unable to register input device\n");
+                       pr_info("Unable to register input device\n");
                        input_free_device(ehotk->inputdev);
                        return 0;
                }
        } else {
-               printk(EEEPC_ERR "Hotkey device not present, aborting\n");
+               pr_err("Hotkey device not present, aborting\n");
                return -EINVAL;
        }
        return 0;
@@ -612,14 +648,27 @@ static int notify_brn(void)
        return -1;
 }
 
-static void eeepc_rfkill_hotplug(void)
+static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
+                                   u8 *value)
+{
+       int val = get_acpi(CM_ASL_WLAN);
+
+       if (val == 1 || val == 0)
+               *value = val;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static void eeepc_hotplug_work(struct work_struct *work)
 {
        struct pci_dev *dev;
        struct pci_bus *bus = pci_find_bus(0, 1);
        bool blocked;
 
        if (!bus) {
-               printk(EEEPC_WARNING "Unable to find PCI bus 1?\n");
+               pr_warning("Unable to find PCI bus 1?\n");
                return;
        }
 
@@ -635,7 +684,7 @@ static void eeepc_rfkill_hotplug(void)
                if (dev) {
                        pci_bus_assign_resources(bus);
                        if (pci_bus_add_device(dev))
-                               printk(EEEPC_ERR "Unable to hotplug wifi\n");
+                               pr_err("Unable to hotplug wifi\n");
                }
        } else {
                dev = pci_get_slot(bus, 0);
@@ -645,7 +694,7 @@ static void eeepc_rfkill_hotplug(void)
                }
        }
 
-       rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked);
+       rfkill_set_sw_state(ehotk->wlan_rfkill, blocked);
 }
 
 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
@@ -653,7 +702,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
        if (event != ACPI_NOTIFY_BUS_CHECK)
                return;
 
-       eeepc_rfkill_hotplug();
+       schedule_work(&ehotk->hotplug_work);
 }
 
 static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
@@ -718,8 +767,7 @@ static int eeepc_register_rfkill_notifier(char *node)
                                                     eeepc_rfkill_notify,
                                                     NULL);
                if (ACPI_FAILURE(status))
-                       printk(EEEPC_WARNING
-                              "Failed to register notify on %s\n", node);
+                       pr_warning("Failed to register notify on %s\n", node);
        } else
                return -ENODEV;
 
@@ -738,19 +786,66 @@ static void eeepc_unregister_rfkill_notifier(char *node)
                                                     ACPI_SYSTEM_NOTIFY,
                                                     eeepc_rfkill_notify);
                if (ACPI_FAILURE(status))
-                       printk(EEEPC_ERR
-                              "Error removing rfkill notify handler %s\n",
+                       pr_err("Error removing rfkill notify handler %s\n",
                                node);
        }
 }
 
+static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
+{
+       kfree(hotplug_slot->info);
+       kfree(hotplug_slot);
+}
+
+static int eeepc_setup_pci_hotplug(void)
+{
+       int ret = -ENOMEM;
+       struct pci_bus *bus = pci_find_bus(0, 1);
+
+       if (!bus) {
+               pr_err("Unable to find wifi PCI bus\n");
+               return -ENODEV;
+       }
+
+       ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
+       if (!ehotk->hotplug_slot)
+               goto error_slot;
+
+       ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
+                                           GFP_KERNEL);
+       if (!ehotk->hotplug_slot->info)
+               goto error_info;
+
+       ehotk->hotplug_slot->private = ehotk;
+       ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
+       ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
+       eeepc_get_adapter_status(ehotk->hotplug_slot,
+                                &ehotk->hotplug_slot->info->adapter_status);
+
+       ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi");
+       if (ret) {
+               pr_err("Unable to register hotplug slot - %d\n", ret);
+               goto error_register;
+       }
+
+       return 0;
+
+error_register:
+       kfree(ehotk->hotplug_slot->info);
+error_info:
+       kfree(ehotk->hotplug_slot);
+       ehotk->hotplug_slot = NULL;
+error_slot:
+       return ret;
+}
+
 static int eeepc_hotk_add(struct acpi_device *device)
 {
        int result;
 
        if (!device)
                 return -EINVAL;
-       printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n");
+       pr_notice(EEEPC_HOTK_NAME "\n");
        ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
        if (!ehotk)
                return -ENOMEM;
@@ -764,53 +859,8 @@ static int eeepc_hotk_add(struct acpi_device *device)
        if (result)
                goto ehotk_fail;
 
-       eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
-       eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
-
-       if (get_acpi(CM_ASL_WLAN) != -1) {
-               ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan",
-                                                       &device->dev,
-                                                       RFKILL_TYPE_WLAN,
-                                                       &eeepc_rfkill_ops,
-                                                       (void *)CM_ASL_WLAN);
-
-               if (!ehotk->eeepc_wlan_rfkill)
-                       goto wlan_fail;
-
-               rfkill_init_sw_state(ehotk->eeepc_wlan_rfkill,
-                                    get_acpi(CM_ASL_WLAN) != 1);
-               result = rfkill_register(ehotk->eeepc_wlan_rfkill);
-               if (result)
-                       goto wlan_fail;
-       }
-
-       if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
-               ehotk->eeepc_bluetooth_rfkill =
-                       rfkill_alloc("eeepc-bluetooth",
-                                    &device->dev,
-                                    RFKILL_TYPE_BLUETOOTH,
-                                    &eeepc_rfkill_ops,
-                                    (void *)CM_ASL_BLUETOOTH);
-
-               if (!ehotk->eeepc_bluetooth_rfkill)
-                       goto bluetooth_fail;
-
-               rfkill_init_sw_state(ehotk->eeepc_bluetooth_rfkill,
-                                    get_acpi(CM_ASL_BLUETOOTH) != 1);
-               result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
-               if (result)
-                       goto bluetooth_fail;
-       }
-
        return 0;
 
- bluetooth_fail:
-       rfkill_destroy(ehotk->eeepc_bluetooth_rfkill);
-       rfkill_unregister(ehotk->eeepc_wlan_rfkill);
- wlan_fail:
-       rfkill_destroy(ehotk->eeepc_wlan_rfkill);
-       eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
-       eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
  ehotk_fail:
        kfree(ehotk);
        ehotk = NULL;
@@ -823,16 +873,13 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type)
        if (!device || !acpi_driver_data(device))
                 return -EINVAL;
 
-       eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
-       eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
-
        kfree(ehotk);
        return 0;
 }
 
 static int eeepc_hotk_resume(struct acpi_device *device)
 {
-       if (ehotk->eeepc_wlan_rfkill) {
+       if (ehotk->wlan_rfkill) {
                bool wlan;
 
                /* Workaround - it seems that _PTS disables the wireless
@@ -844,14 +891,13 @@ static int eeepc_hotk_resume(struct acpi_device *device)
                wlan = get_acpi(CM_ASL_WLAN);
                set_acpi(CM_ASL_WLAN, wlan);
 
-               rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill,
-                                   wlan != 1);
+               rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1);
 
-               eeepc_rfkill_hotplug();
+               schedule_work(&ehotk->hotplug_work);
        }
 
-       if (ehotk->eeepc_bluetooth_rfkill)
-               rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill,
+       if (ehotk->bluetooth_rfkill)
+               rfkill_set_sw_state(ehotk->bluetooth_rfkill,
                                    get_acpi(CM_ASL_BLUETOOTH) != 1);
 
        return 0;
@@ -973,10 +1019,16 @@ static void eeepc_backlight_exit(void)
 
 static void eeepc_rfkill_exit(void)
 {
-       if (ehotk->eeepc_wlan_rfkill)
-               rfkill_unregister(ehotk->eeepc_wlan_rfkill);
-       if (ehotk->eeepc_bluetooth_rfkill)
-               rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
+       eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
+       eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
+       if (ehotk->wlan_rfkill)
+               rfkill_unregister(ehotk->wlan_rfkill);
+       if (ehotk->bluetooth_rfkill)
+               rfkill_unregister(ehotk->bluetooth_rfkill);
+       if (ehotk->wwan3g_rfkill)
+               rfkill_unregister(ehotk->wwan3g_rfkill);
+       if (ehotk->hotplug_slot)
+               pci_hp_deregister(ehotk->hotplug_slot);
 }
 
 static void eeepc_input_exit(void)
@@ -1011,6 +1063,77 @@ static void __exit eeepc_laptop_exit(void)
        platform_driver_unregister(&platform_driver);
 }
 
+static int eeepc_new_rfkill(struct rfkill **rfkill,
+                           const char *name, struct device *dev,
+                           enum rfkill_type type, int cm)
+{
+       int result;
+
+       result = get_acpi(cm);
+       if (result < 0)
+               return result;
+
+       *rfkill = rfkill_alloc(name, dev, type,
+                              &eeepc_rfkill_ops, (void *)(unsigned long)cm);
+
+       if (!*rfkill)
+               return -EINVAL;
+
+       rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1);
+       result = rfkill_register(*rfkill);
+       if (result) {
+               rfkill_destroy(*rfkill);
+               *rfkill = NULL;
+               return result;
+       }
+       return 0;
+}
+
+
+static int eeepc_rfkill_init(struct device *dev)
+{
+       int result = 0;
+
+       INIT_WORK(&ehotk->hotplug_work, eeepc_hotplug_work);
+
+       eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
+       eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
+
+       result = eeepc_new_rfkill(&ehotk->wlan_rfkill,
+                                 "eeepc-wlan", dev,
+                                 RFKILL_TYPE_WLAN, CM_ASL_WLAN);
+
+       if (result && result != -ENODEV)
+               goto exit;
+
+       result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill,
+                                 "eeepc-bluetooth", dev,
+                                 RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH);
+
+       if (result && result != -ENODEV)
+               goto exit;
+
+       result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill,
+                                 "eeepc-wwan3g", dev,
+                                 RFKILL_TYPE_WWAN, CM_ASL_3G);
+
+       if (result && result != -ENODEV)
+               goto exit;
+
+       result = eeepc_setup_pci_hotplug();
+       /*
+        * If we get -EBUSY then something else is handling the PCI hotplug -
+        * don't fail in this case
+        */
+       if (result == -EBUSY)
+               result = 0;
+
+exit:
+       if (result && result != -ENODEV)
+               eeepc_rfkill_exit();
+       return result;
+}
+
 static int eeepc_backlight_init(struct device *dev)
 {
        struct backlight_device *bd;
@@ -1018,8 +1141,7 @@ static int eeepc_backlight_init(struct device *dev)
        bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
                                       NULL, &eeepcbl_ops);
        if (IS_ERR(bd)) {
-               printk(EEEPC_ERR
-                      "Could not register eeepc backlight device\n");
+               pr_err("Could not register eeepc backlight device\n");
                eeepc_backlight_device = NULL;
                return PTR_ERR(bd);
        }
@@ -1038,8 +1160,7 @@ static int eeepc_hwmon_init(struct device *dev)
 
        hwmon = hwmon_device_register(dev);
        if (IS_ERR(hwmon)) {
-               printk(EEEPC_ERR
-                      "Could not register eeepc hwmon device\n");
+               pr_err("Could not register eeepc hwmon device\n");
                eeepc_hwmon_device = NULL;
                return PTR_ERR(hwmon);
        }
@@ -1065,19 +1186,6 @@ static int __init eeepc_laptop_init(void)
                acpi_bus_unregister_driver(&eeepc_hotk_driver);
                return -ENODEV;
        }
-       dev = acpi_get_physical_device(ehotk->device->handle);
-
-       if (!acpi_video_backlight_support()) {
-               result = eeepc_backlight_init(dev);
-               if (result)
-                       goto fail_backlight;
-       } else
-               printk(EEEPC_INFO "Backlight controlled by ACPI video "
-                      "driver\n");
-
-       result = eeepc_hwmon_init(dev);
-       if (result)
-               goto fail_hwmon;
 
        eeepc_enable_camera();
 
@@ -1097,7 +1205,33 @@ static int __init eeepc_laptop_init(void)
                                    &platform_attribute_group);
        if (result)
                goto fail_sysfs;
+
+       dev = &platform_device->dev;
+
+       if (!acpi_video_backlight_support()) {
+               result = eeepc_backlight_init(dev);
+               if (result)
+                       goto fail_backlight;
+       } else
+               pr_info("Backlight controlled by ACPI video "
+                       "driver\n");
+
+       result = eeepc_hwmon_init(dev);
+       if (result)
+               goto fail_hwmon;
+
+       result = eeepc_rfkill_init(dev);
+       if (result)
+               goto fail_rfkill;
+
        return 0;
+fail_rfkill:
+       eeepc_hwmon_exit();
+fail_hwmon:
+       eeepc_backlight_exit();
+fail_backlight:
+       sysfs_remove_group(&platform_device->dev.kobj,
+                          &platform_attribute_group);
 fail_sysfs:
        platform_device_del(platform_device);
 fail_platform_device2:
@@ -1105,12 +1239,7 @@ fail_platform_device2:
 fail_platform_device1:
        platform_driver_unregister(&platform_driver);
 fail_platform_driver:
-       eeepc_hwmon_exit();
-fail_hwmon:
-       eeepc_backlight_exit();
-fail_backlight:
        eeepc_input_exit();
-       eeepc_rfkill_exit();
        return result;
 }
 
index 4ac2311c00afe9fae55fcf1334522a564fd943e5..a2ad53e15874ebcbba5b82ba73e4bb3b7f32529e 100644 (file)
@@ -171,7 +171,7 @@ static int hp_wmi_tablet_state(void)
 static int hp_wmi_set_block(void *data, bool blocked)
 {
        unsigned long b = (unsigned long) data;
-       int query = BIT(b + 8) | ((!!blocked) << b);
+       int query = BIT(b + 8) | ((!blocked) << b);
 
        return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query);
 }
@@ -520,11 +520,13 @@ static int hp_wmi_resume_handler(struct platform_device *device)
         * the input layer will only actually pass it on if the state
         * changed.
         */
-
-       input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state());
-       input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
-                           hp_wmi_tablet_state());
-       input_sync(hp_wmi_input_dev);
+       if (hp_wmi_input_dev) {
+               input_report_switch(hp_wmi_input_dev, SW_DOCK,
+                                   hp_wmi_dock_state());
+               input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
+                                   hp_wmi_tablet_state());
+               input_sync(hp_wmi_input_dev);
+       }
 
        return 0;
 }
index a463fd72c49560a7c5d7fe2f8744a614519f7f34..e85600852502e0a0c6b99b1681ed0213806e8420 100644 (file)
@@ -239,12 +239,6 @@ struct ibm_init_struct {
 };
 
 static struct {
-#ifdef CONFIG_THINKPAD_ACPI_BAY
-       u32 bay_status:1;
-       u32 bay_eject:1;
-       u32 bay_status2:1;
-       u32 bay_eject2:1;
-#endif
        u32 bluetooth:1;
        u32 hotkey:1;
        u32 hotkey_mask:1;
@@ -589,18 +583,6 @@ static int acpi_ec_write(int i, u8 v)
        return 1;
 }
 
-#if defined(CONFIG_THINKPAD_ACPI_DOCK) || defined(CONFIG_THINKPAD_ACPI_BAY)
-static int _sta(acpi_handle handle)
-{
-       int status;
-
-       if (!handle || !acpi_evalf(handle, &status, "_STA", "d"))
-               status = 0;
-
-       return status;
-}
-#endif
-
 static int issue_thinkpad_cmos_command(int cmos_cmd)
 {
        if (!cmos_handle)
@@ -784,6 +766,8 @@ static int dispatch_procfs_write(struct file *file,
 
        if (!ibm || !ibm->write)
                return -EINVAL;
+       if (count > PAGE_SIZE - 2)
+               return -EINVAL;
 
        kernbuf = kmalloc(count + 2, GFP_KERNEL);
        if (!kernbuf)
@@ -4441,293 +4425,6 @@ static struct ibm_struct light_driver_data = {
        .exit = light_exit,
 };
 
-/*************************************************************************
- * Dock subdriver
- */
-
-#ifdef CONFIG_THINKPAD_ACPI_DOCK
-
-static void dock_notify(struct ibm_struct *ibm, u32 event);
-static int dock_read(char *p);
-static int dock_write(char *buf);
-
-TPACPI_HANDLE(dock, root, "\\_SB.GDCK",        /* X30, X31, X40 */
-          "\\_SB.PCI0.DOCK",   /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */
-          "\\_SB.PCI0.PCI1.DOCK",      /* all others */
-          "\\_SB.PCI.ISA.SLCE",        /* 570 */
-    );                         /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */
-
-/* don't list other alternatives as we install a notify handler on the 570 */
-TPACPI_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */
-
-static const struct acpi_device_id ibm_pci_device_ids[] = {
-       {PCI_ROOT_HID_STRING, 0},
-       {"", 0},
-};
-
-static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = {
-       {
-        .notify = dock_notify,
-        .handle = &dock_handle,
-        .type = ACPI_SYSTEM_NOTIFY,
-       },
-       {
-       /* THIS ONE MUST NEVER BE USED FOR DRIVER AUTOLOADING.
-        * We just use it to get notifications of dock hotplug
-        * in very old thinkpads */
-        .hid = ibm_pci_device_ids,
-        .notify = dock_notify,
-        .handle = &pci_handle,
-        .type = ACPI_SYSTEM_NOTIFY,
-       },
-};
-
-static struct ibm_struct dock_driver_data[2] = {
-       {
-        .name = "dock",
-        .read = dock_read,
-        .write = dock_write,
-        .acpi = &ibm_dock_acpidriver[0],
-       },
-       {
-        .name = "dock",
-        .acpi = &ibm_dock_acpidriver[1],
-       },
-};
-
-#define dock_docked() (_sta(dock_handle) & 1)
-
-static int __init dock_init(struct ibm_init_struct *iibm)
-{
-       vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver\n");
-
-       TPACPI_ACPIHANDLE_INIT(dock);
-
-       vdbg_printk(TPACPI_DBG_INIT, "dock is %s\n",
-               str_supported(dock_handle != NULL));
-
-       return (dock_handle)? 0 : 1;
-}
-
-static int __init dock_init2(struct ibm_init_struct *iibm)
-{
-       int dock2_needed;
-
-       vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver part 2\n");
-
-       if (dock_driver_data[0].flags.acpi_driver_registered &&
-           dock_driver_data[0].flags.acpi_notify_installed) {
-               TPACPI_ACPIHANDLE_INIT(pci);
-               dock2_needed = (pci_handle != NULL);
-               vdbg_printk(TPACPI_DBG_INIT,
-                           "dock PCI handler for the TP 570 is %s\n",
-                           str_supported(dock2_needed));
-       } else {
-               vdbg_printk(TPACPI_DBG_INIT,
-               "dock subdriver part 2 not required\n");
-               dock2_needed = 0;
-       }
-
-       return (dock2_needed)? 0 : 1;
-}
-
-static void dock_notify(struct ibm_struct *ibm, u32 event)
-{
-       int docked = dock_docked();
-       int pci = ibm->acpi->hid && ibm->acpi->device &&
-               acpi_match_device_ids(ibm->acpi->device, ibm_pci_device_ids);
-       int data;
-
-       if (event == 1 && !pci) /* 570 */
-               data = 1;       /* button */
-       else if (event == 1 && pci)     /* 570 */
-               data = 3;       /* dock */
-       else if (event == 3 && docked)
-               data = 1;       /* button */
-       else if (event == 3 && !docked)
-               data = 2;       /* undock */
-       else if (event == 0 && docked)
-               data = 3;       /* dock */
-       else {
-               printk(TPACPI_ERR "unknown dock event %d, status %d\n",
-                      event, _sta(dock_handle));
-               data = 0;       /* unknown */
-       }
-       acpi_bus_generate_proc_event(ibm->acpi->device, event, data);
-       acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
-                                         dev_name(&ibm->acpi->device->dev),
-                                         event, data);
-}
-
-static int dock_read(char *p)
-{
-       int len = 0;
-       int docked = dock_docked();
-
-       if (!dock_handle)
-               len += sprintf(p + len, "status:\t\tnot supported\n");
-       else if (!docked)
-               len += sprintf(p + len, "status:\t\tundocked\n");
-       else {
-               len += sprintf(p + len, "status:\t\tdocked\n");
-               len += sprintf(p + len, "commands:\tdock, undock\n");
-       }
-
-       return len;
-}
-
-static int dock_write(char *buf)
-{
-       char *cmd;
-
-       if (!dock_docked())
-               return -ENODEV;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (strlencmp(cmd, "undock") == 0) {
-                       if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0) ||
-                           !acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1))
-                               return -EIO;
-               } else if (strlencmp(cmd, "dock") == 0) {
-                       if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 1))
-                               return -EIO;
-               } else
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-#endif /* CONFIG_THINKPAD_ACPI_DOCK */
-
-/*************************************************************************
- * Bay subdriver
- */
-
-#ifdef CONFIG_THINKPAD_ACPI_BAY
-
-TPACPI_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST",    /* 570 */
-          "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */
-          "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */
-          "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */
-          );                           /* A21e, R30, R31 */
-TPACPI_HANDLE(bay_ej, bay, "_EJ3",     /* 600e/x, A2xm/p, A3x */
-          "_EJ0",              /* all others */
-          );                   /* 570,A21e,G4x,R30,R31,R32,R40e,R50e */
-TPACPI_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */
-          "\\_SB.PCI0.IDE0.IDEP.IDPS", /* 600e/x, 770e, 770x */
-          );                           /* all others */
-TPACPI_HANDLE(bay2_ej, bay2, "_EJ3",   /* 600e/x, 770e, A3x */
-          "_EJ0",                      /* 770x */
-          );                           /* all others */
-
-static int __init bay_init(struct ibm_init_struct *iibm)
-{
-       vdbg_printk(TPACPI_DBG_INIT, "initializing bay subdriver\n");
-
-       TPACPI_ACPIHANDLE_INIT(bay);
-       if (bay_handle)
-               TPACPI_ACPIHANDLE_INIT(bay_ej);
-       TPACPI_ACPIHANDLE_INIT(bay2);
-       if (bay2_handle)
-               TPACPI_ACPIHANDLE_INIT(bay2_ej);
-
-       tp_features.bay_status = bay_handle &&
-               acpi_evalf(bay_handle, NULL, "_STA", "qv");
-       tp_features.bay_status2 = bay2_handle &&
-               acpi_evalf(bay2_handle, NULL, "_STA", "qv");
-
-       tp_features.bay_eject = bay_handle && bay_ej_handle &&
-               (strlencmp(bay_ej_path, "_EJ0") == 0 || experimental);
-       tp_features.bay_eject2 = bay2_handle && bay2_ej_handle &&
-               (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental);
-
-       vdbg_printk(TPACPI_DBG_INIT,
-               "bay 1: status %s, eject %s; bay 2: status %s, eject %s\n",
-               str_supported(tp_features.bay_status),
-               str_supported(tp_features.bay_eject),
-               str_supported(tp_features.bay_status2),
-               str_supported(tp_features.bay_eject2));
-
-       return (tp_features.bay_status || tp_features.bay_eject ||
-               tp_features.bay_status2 || tp_features.bay_eject2)? 0 : 1;
-}
-
-static void bay_notify(struct ibm_struct *ibm, u32 event)
-{
-       acpi_bus_generate_proc_event(ibm->acpi->device, event, 0);
-       acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
-                                         dev_name(&ibm->acpi->device->dev),
-                                         event, 0);
-}
-
-#define bay_occupied(b) (_sta(b##_handle) & 1)
-
-static int bay_read(char *p)
-{
-       int len = 0;
-       int occupied = bay_occupied(bay);
-       int occupied2 = bay_occupied(bay2);
-       int eject, eject2;
-
-       len += sprintf(p + len, "status:\t\t%s\n",
-               tp_features.bay_status ?
-                       (occupied ? "occupied" : "unoccupied") :
-                               "not supported");
-       if (tp_features.bay_status2)
-               len += sprintf(p + len, "status2:\t%s\n", occupied2 ?
-                              "occupied" : "unoccupied");
-
-       eject = tp_features.bay_eject && occupied;
-       eject2 = tp_features.bay_eject2 && occupied2;
-
-       if (eject && eject2)
-               len += sprintf(p + len, "commands:\teject, eject2\n");
-       else if (eject)
-               len += sprintf(p + len, "commands:\teject\n");
-       else if (eject2)
-               len += sprintf(p + len, "commands:\teject2\n");
-
-       return len;
-}
-
-static int bay_write(char *buf)
-{
-       char *cmd;
-
-       if (!tp_features.bay_eject && !tp_features.bay_eject2)
-               return -ENODEV;
-
-       while ((cmd = next_cmd(&buf))) {
-               if (tp_features.bay_eject && strlencmp(cmd, "eject") == 0) {
-                       if (!acpi_evalf(bay_ej_handle, NULL, NULL, "vd", 1))
-                               return -EIO;
-               } else if (tp_features.bay_eject2 &&
-                          strlencmp(cmd, "eject2") == 0) {
-                       if (!acpi_evalf(bay2_ej_handle, NULL, NULL, "vd", 1))
-                               return -EIO;
-               } else
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-static struct tp_acpi_drv_struct ibm_bay_acpidriver = {
-       .notify = bay_notify,
-       .handle = &bay_handle,
-       .type = ACPI_SYSTEM_NOTIFY,
-};
-
-static struct ibm_struct bay_driver_data = {
-       .name = "bay",
-       .read = bay_read,
-       .write = bay_write,
-       .acpi = &ibm_bay_acpidriver,
-};
-
-#endif /* CONFIG_THINKPAD_ACPI_BAY */
-
 /*************************************************************************
  * CMOS subdriver
  */
@@ -5945,14 +5642,48 @@ static struct backlight_ops ibm_backlight_data = {
 
 /* --------------------------------------------------------------------- */
 
+/*
+ * These are only useful for models that have only one possibility
+ * of GPU.  If the BIOS model handles both ATI and Intel, don't use
+ * these quirks.
+ */
+#define TPACPI_BRGHT_Q_NOEC    0x0001  /* Must NOT use EC HBRV */
+#define TPACPI_BRGHT_Q_EC      0x0002  /* Should or must use EC HBRV */
+#define TPACPI_BRGHT_Q_ASK     0x8000  /* Ask for user report */
+
+static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
+       /* Models with ATI GPUs known to require ECNVRAM mode */
+       TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC),      /* T43/p ATI */
+
+       /* Models with ATI GPUs (waiting confirmation) */
+       TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
+       TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
+       TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
+       TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
+
+       /* Models with Intel Extreme Graphics 2 (waiting confirmation) */
+       TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
+       TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
+       TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC),
+
+       /* Models with Intel GMA900 */
+       TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC),    /* T43, R52 */
+       TPACPI_Q_IBM('7', '4', TPACPI_BRGHT_Q_NOEC),    /* X41 */
+       TPACPI_Q_IBM('7', '5', TPACPI_BRGHT_Q_NOEC),    /* X41 Tablet */
+};
+
 static int __init brightness_init(struct ibm_init_struct *iibm)
 {
        int b;
+       unsigned long quirks;
 
        vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n");
 
        mutex_init(&brightness_mutex);
 
+       quirks = tpacpi_check_quirks(brightness_quirk_table,
+                               ARRAY_SIZE(brightness_quirk_table));
+
        /*
         * We always attempt to detect acpi support, so as to switch
         * Lenovo Vista BIOS to ACPI brightness mode even if we are not
@@ -6009,23 +5740,13 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
        /* TPACPI_BRGHT_MODE_AUTO not implemented yet, just use default */
        if (brightness_mode == TPACPI_BRGHT_MODE_AUTO ||
            brightness_mode == TPACPI_BRGHT_MODE_MAX) {
-               if (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) {
-                       /*
-                        * IBM models that define HBRV probably have
-                        * EC-based backlight level control
-                        */
-                       if (acpi_evalf(ec_handle, NULL, "HBRV", "qd"))
-                               /* T40-T43, R50-R52, R50e, R51e, X31-X41 */
-                               brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM;
-                       else
-                               /* all other IBM ThinkPads */
-                               brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP;
-               } else
-                       /* All Lenovo ThinkPads */
+               if (quirks & TPACPI_BRGHT_Q_EC)
+                       brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM;
+               else
                        brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP;
 
                dbg_printk(TPACPI_DBG_BRGHT,
-                          "selected brightness_mode=%d\n",
+                          "driver auto-selected brightness_mode=%d\n",
                           brightness_mode);
        }
 
@@ -6052,6 +5773,15 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
        vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
                        "brightness is supported\n");
 
+       if (quirks & TPACPI_BRGHT_Q_ASK) {
+               printk(TPACPI_NOTICE
+                       "brightness: will use unverified default: "
+                       "brightness_mode=%d\n", brightness_mode);
+               printk(TPACPI_NOTICE
+                       "brightness: please report to %s whether it works well "
+                       "or not on your ThinkPad\n", TPACPI_MAIL);
+       }
+
        ibm_backlight_device->props.max_brightness =
                                (tp_features.bright_16levels)? 15 : 7;
        ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
@@ -7854,22 +7584,6 @@ static struct ibm_init_struct ibms_init[] __initdata = {
                .init = light_init,
                .data = &light_driver_data,
        },
-#ifdef CONFIG_THINKPAD_ACPI_DOCK
-       {
-               .init = dock_init,
-               .data = &dock_driver_data[0],
-       },
-       {
-               .init = dock_init2,
-               .data = &dock_driver_data[1],
-       },
-#endif
-#ifdef CONFIG_THINKPAD_ACPI_BAY
-       {
-               .init = bay_init,
-               .data = &bay_driver_data,
-       },
-#endif
        {
                .init = cmos_init,
                .data = &cmos_driver_data,
@@ -7968,12 +7682,6 @@ TPACPI_PARAM(hotkey);
 TPACPI_PARAM(bluetooth);
 TPACPI_PARAM(video);
 TPACPI_PARAM(light);
-#ifdef CONFIG_THINKPAD_ACPI_DOCK
-TPACPI_PARAM(dock);
-#endif
-#ifdef CONFIG_THINKPAD_ACPI_BAY
-TPACPI_PARAM(bay);
-#endif /* CONFIG_THINKPAD_ACPI_BAY */
 TPACPI_PARAM(cmos);
 TPACPI_PARAM(led);
 TPACPI_PARAM(beep);
index 81d31ea507d116e3186384d7a0a394d00dc0e3ae..51c0a8bee4144ff800ff200e463315590e2d729a 100644 (file)
@@ -335,6 +335,7 @@ static void bt_rfkill_poll(struct rfkill *rfkill, void *data)
        if (hci_result != HCI_SUCCESS) {
                /* Can't do anything useful */
                mutex_unlock(&dev->mutex);
+               return;
        }
 
        new_rfk_state = value;
index 043b208d971d58b9841d1eac1592ec0620cbd85b..f215a59191925f01893c5c65802c0f80b61eee43 100644 (file)
@@ -270,7 +270,7 @@ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
        acpi_status status;
        struct acpi_object_list input;
        union acpi_object params[3];
-       char method[4] = "WM";
+       char method[5] = "WM";
 
        if (!find_guid(guid_string, &wblock))
                return AE_ERROR;
@@ -328,8 +328,8 @@ struct acpi_buffer *out)
        acpi_status status, wc_status = AE_ERROR;
        struct acpi_object_list input, wc_input;
        union acpi_object wc_params[1], wq_params[1];
-       char method[4];
-       char wc_method[4] = "WC";
+       char method[5];
+       char wc_method[5] = "WC";
 
        if (!guid_string || !out)
                return AE_BAD_PARAMETER;
@@ -410,7 +410,7 @@ const struct acpi_buffer *in)
        acpi_handle handle;
        struct acpi_object_list input;
        union acpi_object params[2];
-       char method[4] = "WS";
+       char method[5] = "WS";
 
        if (!guid_string || !in)
                return AE_BAD_DATA;
index 7eda34838bfe979e22bff2939237c8c9847671cc..bdbc4f73fcdced7466406874737a373185aaf167 100644 (file)
@@ -43,6 +43,13 @@ config BATTERY_DS2760
        help
          Say Y here to enable support for batteries with ds2760 chip.
 
+config BATTERY_DS2782
+       tristate "DS2782 standalone gas-gauge"
+       depends on I2C
+       help
+         Say Y here to enable support for the DS2782 standalone battery
+         gas-gauge.
+
 config BATTERY_PMU
        tristate "Apple PMU battery"
        depends on PPC32 && ADB_PMU
index daf3179689aaecb61611604f526d2f6e090c6b00..380d17c9ae2983dc34ab84e68e244eefaf78ca48 100644 (file)
@@ -19,6 +19,7 @@ obj-$(CONFIG_APM_POWER)               += apm_power.o
 obj-$(CONFIG_WM8350_POWER)     += wm8350_power.o
 
 obj-$(CONFIG_BATTERY_DS2760)   += ds2760_battery.o
+obj-$(CONFIG_BATTERY_DS2782)   += ds2782_battery.o
 obj-$(CONFIG_BATTERY_PMU)      += pmu_battery.o
 obj-$(CONFIG_BATTERY_OLPC)     += olpc_battery.o
 obj-$(CONFIG_BATTERY_TOSA)     += tosa_battery.o
diff --git a/drivers/power/ds2782_battery.c b/drivers/power/ds2782_battery.c
new file mode 100644 (file)
index 0000000..da14f37
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * I2C client/driver for the Maxim/Dallas DS2782 Stand-Alone Fuel Gauge IC
+ *
+ * Copyright (C) 2009 Bluewater Systems Ltd
+ *
+ * Author: Ryan Mallon <ryan@bluewatersys.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/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/swab.h>
+#include <linux/i2c.h>
+#include <linux/idr.h>
+#include <linux/power_supply.h>
+
+#define DS2782_REG_RARC                0x06    /* Remaining active relative capacity */
+
+#define DS2782_REG_VOLT_MSB    0x0c
+#define DS2782_REG_TEMP_MSB    0x0a
+#define DS2782_REG_CURRENT_MSB 0x0e
+
+/* EEPROM Block */
+#define DS2782_REG_RSNSP       0x69    /* Sense resistor value */
+
+/* Current unit measurement in uA for a 1 milli-ohm sense resistor */
+#define DS2782_CURRENT_UNITS   1563
+
+#define to_ds2782_info(x) container_of(x, struct ds2782_info, battery)
+
+struct ds2782_info {
+       struct i2c_client       *client;
+       struct power_supply     battery;
+       int                     id;
+};
+
+static DEFINE_IDR(battery_id);
+static DEFINE_MUTEX(battery_lock);
+
+static inline int ds2782_read_reg(struct ds2782_info *info, int reg, u8 *val)
+{
+       int ret;
+
+       ret = i2c_smbus_read_byte_data(info->client, reg);
+       if (ret < 0) {
+               dev_err(&info->client->dev, "register read failed\n");
+               return ret;
+       }
+
+       *val = ret;
+       return 0;
+}
+
+static inline int ds2782_read_reg16(struct ds2782_info *info, int reg_msb,
+                                   s16 *val)
+{
+       int ret;
+
+       ret = swab16(i2c_smbus_read_word_data(info->client, reg_msb));
+       if (ret < 0) {
+               dev_err(&info->client->dev, "register read failed\n");
+               return ret;
+       }
+
+       *val = ret;
+       return 0;
+}
+
+static int ds2782_get_temp(struct ds2782_info *info, int *temp)
+{
+       s16 raw;
+       int err;
+
+       /*
+        * Temperature is measured in units of 0.125 degrees celcius, the
+        * power_supply class measures temperature in tenths of degrees
+        * celsius. The temperature value is stored as a 10 bit number, plus
+        * sign in the upper bits of a 16 bit register.
+        */
+       err = ds2782_read_reg16(info, DS2782_REG_TEMP_MSB, &raw);
+       if (err)
+               return err;
+       *temp = ((raw / 32) * 125) / 100;
+       return 0;
+}
+
+static int ds2782_get_current(struct ds2782_info *info, int *current_uA)
+{
+       int sense_res;
+       int err;
+       u8 sense_res_raw;
+       s16 raw;
+
+       /*
+        * The units of measurement for current are dependent on the value of
+        * the sense resistor.
+        */
+       err = ds2782_read_reg(info, DS2782_REG_RSNSP, &sense_res_raw);
+       if (err)
+               return err;
+       if (sense_res_raw == 0) {
+               dev_err(&info->client->dev, "sense resistor value is 0\n");
+               return -ENXIO;
+       }
+       sense_res = 1000 / sense_res_raw;
+
+       dev_dbg(&info->client->dev, "sense resistor = %d milli-ohms\n",
+               sense_res);
+       err = ds2782_read_reg16(info, DS2782_REG_CURRENT_MSB, &raw);
+       if (err)
+               return err;
+       *current_uA = raw * (DS2782_CURRENT_UNITS / sense_res);
+       return 0;
+}
+
+static int ds2782_get_voltage(struct ds2782_info *info, int *voltage_uA)
+{
+       s16 raw;
+       int err;
+
+       /*
+        * Voltage is measured in units of 4.88mV. The voltage is stored as
+        * a 10-bit number plus sign, in the upper bits of a 16-bit register
+        */
+       err = ds2782_read_reg16(info, DS2782_REG_VOLT_MSB, &raw);
+       if (err)
+               return err;
+       *voltage_uA = (raw / 32) * 4800;
+       return 0;
+}
+
+static int ds2782_get_capacity(struct ds2782_info *info, int *capacity)
+{
+       int err;
+       u8 raw;
+
+       err = ds2782_read_reg(info, DS2782_REG_RARC, &raw);
+       if (err)
+               return err;
+       *capacity = raw;
+       return raw;
+}
+
+static int ds2782_get_status(struct ds2782_info *info, int *status)
+{
+       int err;
+       int current_uA;
+       int capacity;
+
+       err = ds2782_get_current(info, &current_uA);
+       if (err)
+               return err;
+
+       err = ds2782_get_capacity(info, &capacity);
+       if (err)
+               return err;
+
+       if (capacity == 100)
+               *status = POWER_SUPPLY_STATUS_FULL;
+       else if (current_uA == 0)
+               *status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+       else if (current_uA < 0)
+               *status = POWER_SUPPLY_STATUS_DISCHARGING;
+       else
+               *status = POWER_SUPPLY_STATUS_CHARGING;
+
+       return 0;
+}
+
+static int ds2782_battery_get_property(struct power_supply *psy,
+                                      enum power_supply_property prop,
+                                      union power_supply_propval *val)
+{
+       struct ds2782_info *info = to_ds2782_info(psy);
+       int ret;
+
+       switch (prop) {
+       case POWER_SUPPLY_PROP_STATUS:
+               ret = ds2782_get_status(info, &val->intval);
+               break;
+
+       case POWER_SUPPLY_PROP_CAPACITY:
+               ret = ds2782_get_capacity(info, &val->intval);
+               break;
+
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               ret = ds2782_get_voltage(info, &val->intval);
+               break;
+
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+               ret = ds2782_get_current(info, &val->intval);
+               break;
+
+       case POWER_SUPPLY_PROP_TEMP:
+               ret = ds2782_get_temp(info, &val->intval);
+               break;
+
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static enum power_supply_property ds2782_battery_props[] = {
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_CAPACITY,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_CURRENT_NOW,
+       POWER_SUPPLY_PROP_TEMP,
+};
+
+static void ds2782_power_supply_init(struct power_supply *battery)
+{
+       battery->type                   = POWER_SUPPLY_TYPE_BATTERY;
+       battery->properties             = ds2782_battery_props;
+       battery->num_properties         = ARRAY_SIZE(ds2782_battery_props);
+       battery->get_property           = ds2782_battery_get_property;
+       battery->external_power_changed = NULL;
+}
+
+static int ds2782_battery_remove(struct i2c_client *client)
+{
+       struct ds2782_info *info = i2c_get_clientdata(client);
+
+       power_supply_unregister(&info->battery);
+       kfree(info->battery.name);
+
+       mutex_lock(&battery_lock);
+       idr_remove(&battery_id, info->id);
+       mutex_unlock(&battery_lock);
+
+       i2c_set_clientdata(client, info);
+
+       kfree(info);
+       return 0;
+}
+
+static int ds2782_battery_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
+{
+       struct ds2782_info *info;
+       int ret;
+       int num;
+
+       /* Get an ID for this battery */
+       ret = idr_pre_get(&battery_id, GFP_KERNEL);
+       if (ret == 0) {
+               ret = -ENOMEM;
+               goto fail_id;
+       }
+
+       mutex_lock(&battery_lock);
+       ret = idr_get_new(&battery_id, client, &num);
+       mutex_unlock(&battery_lock);
+       if (ret < 0)
+               goto fail_id;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info) {
+               ret = -ENOMEM;
+               goto fail_info;
+       }
+
+       info->battery.name = kasprintf(GFP_KERNEL, "ds2782-%d", num);
+       if (!info->battery.name) {
+               ret = -ENOMEM;
+               goto fail_name;
+       }
+
+       i2c_set_clientdata(client, info);
+       info->client = client;
+       ds2782_power_supply_init(&info->battery);
+
+       ret = power_supply_register(&client->dev, &info->battery);
+       if (ret) {
+               dev_err(&client->dev, "failed to register battery\n");
+               goto fail_register;
+       }
+
+       return 0;
+
+fail_register:
+       kfree(info->battery.name);
+fail_name:
+       i2c_set_clientdata(client, info);
+       kfree(info);
+fail_info:
+       mutex_lock(&battery_lock);
+       idr_remove(&battery_id, num);
+       mutex_unlock(&battery_lock);
+fail_id:
+       return ret;
+}
+
+static const struct i2c_device_id ds2782_id[] = {
+       {"ds2782", 0},
+       {},
+};
+
+static struct i2c_driver ds2782_battery_driver = {
+       .driver         = {
+               .name   = "ds2782-battery",
+       },
+       .probe          = ds2782_battery_probe,
+       .remove         = ds2782_battery_remove,
+       .id_table       = ds2782_id,
+};
+
+static int __init ds2782_init(void)
+{
+       return i2c_add_driver(&ds2782_battery_driver);
+}
+module_init(ds2782_init);
+
+static void __exit ds2782_exit(void)
+{
+       i2c_del_driver(&ds2782_battery_driver);
+}
+module_exit(ds2782_exit);
+
+MODULE_AUTHOR("Ryan Mallon <ryan@bluewatersys.com>");
+MODULE_DESCRIPTION("Maxim/Dallas DS2782 Stand-Alone Fuel Gauage IC driver");
+MODULE_LICENSE("GPL");
index 5fbca2681baaeb112ef0ae789ddd6aabb2a63156..58e419299cd6cdba020042ac9991556803282617 100644 (file)
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
@@ -35,6 +36,7 @@
 #define BAT_STAT_AC            0x10
 #define BAT_STAT_CHARGING      0x20
 #define BAT_STAT_DISCHARGING   0x40
+#define BAT_STAT_TRICKLE       0x80
 
 #define BAT_ERR_INFOFAIL       0x02
 #define BAT_ERR_OVERVOLTAGE    0x04
@@ -89,7 +91,7 @@ static char bat_serial[17]; /* Ick */
 static int olpc_bat_get_status(union power_supply_propval *val, uint8_t ec_byte)
 {
        if (olpc_platform_info.ecver > 0x44) {
-               if (ec_byte & BAT_STAT_CHARGING)
+               if (ec_byte & (BAT_STAT_CHARGING | BAT_STAT_TRICKLE))
                        val->intval = POWER_SUPPLY_STATUS_CHARGING;
                else if (ec_byte & BAT_STAT_DISCHARGING)
                        val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
@@ -219,7 +221,8 @@ static int olpc_bat_get_property(struct power_supply *psy,
           It doesn't matter though -- the EC will return the last-known
           information, and it's as if we just ran that _little_ bit faster
           and managed to read it out before the battery went away. */
-       if (!(ec_byte & BAT_STAT_PRESENT) && psp != POWER_SUPPLY_PROP_PRESENT)
+       if (!(ec_byte & (BAT_STAT_PRESENT | BAT_STAT_TRICKLE)) &&
+                       psp != POWER_SUPPLY_PROP_PRESENT)
                return -ENODEV;
 
        switch (psp) {
@@ -229,7 +232,8 @@ static int olpc_bat_get_property(struct power_supply *psy,
                        return ret;
                break;
        case POWER_SUPPLY_PROP_PRESENT:
-               val->intval = !!(ec_byte & BAT_STAT_PRESENT);
+               val->intval = !!(ec_byte & (BAT_STAT_PRESENT |
+                                           BAT_STAT_TRICKLE));
                break;
 
        case POWER_SUPPLY_PROP_HEALTH:
@@ -334,21 +338,21 @@ static ssize_t olpc_bat_eeprom_read(struct kobject *kobj,
                struct bin_attribute *attr, char *buf, loff_t off, size_t count)
 {
        uint8_t ec_byte;
-       int ret, end;
+       int ret;
+       int i;
 
        if (off >= EEPROM_SIZE)
                return 0;
        if (off + count > EEPROM_SIZE)
                count = EEPROM_SIZE - off;
 
-       end = EEPROM_START + off + count;
-       for (ec_byte = EEPROM_START + off; ec_byte < end; ec_byte++) {
-               ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1,
-                               &buf[ec_byte - EEPROM_START], 1);
+       for (i = 0; i < count; i++) {
+               ec_byte = EEPROM_START + off + i;
+               ret = olpc_ec_cmd(EC_BAT_EEPROM, &ec_byte, 1, &buf[i], 1);
                if (ret) {
-                       printk(KERN_ERR "olpc-battery:  EC command "
-                                       "EC_BAT_EEPROM @ 0x%x failed -"
-                                       " %d!\n", ec_byte, ret);
+                       pr_err("olpc-battery: "
+                              "EC_BAT_EEPROM cmd @ 0x%x failed - %d!\n",
+                              ec_byte, ret);
                        return -EIO;
                }
        }
index 8bde92126d34794e6cd58e55f1d715216c92819b..b787335a8419352fa4cef23af9fccd2fd4f508ac 100644 (file)
@@ -33,14 +33,14 @@ static enum power_supply_property *prop;
 
 static unsigned long wm97xx_read_bat(struct power_supply *bat_ps)
 {
-       return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data,
+       return wm97xx_read_aux_adc(dev_get_drvdata(bat_ps->dev->parent),
                                        pdata->batt_aux) * pdata->batt_mult /
                                        pdata->batt_div;
 }
 
 static unsigned long wm97xx_read_temp(struct power_supply *bat_ps)
 {
-       return wm97xx_read_aux_adc(bat_ps->dev->parent->driver_data,
+       return wm97xx_read_aux_adc(dev_get_drvdata(bat_ps->dev->parent),
                                        pdata->temp_aux) * pdata->temp_mult /
                                        pdata->temp_div;
 }
index ac8cc8cea1e386425a8df7847f57f5737d447b11..fea17e7805e9d5e846998c16d965711628e4bc8b 100644 (file)
@@ -244,7 +244,7 @@ int pps_register_cdev(struct pps_device *pps)
        }
        pps->dev = device_create(pps_class, pps->info.dev, pps->devno, NULL,
                                                        "pps%d", pps->id);
-       if (err)
+       if (IS_ERR(pps->dev))
                goto del_cdev;
        dev_set_drvdata(pps->dev, pps);
 
index aafd3e6ebb0dfa92725f63798de226d5bf20ac72..a118eb0f1e6729029be1a4fdb61aea52634ed260 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Blackfin On-Chip Real Time Clock Driver
- *  Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789]
+ *  Supports BF51x/BF52x/BF53[123]/BF53[467]/BF54x
  *
- * Copyright 2004-2008 Analog Devices Inc.
+ * Copyright 2004-2009 Analog Devices Inc.
  *
  * Enter bugs at http://blackfin.uclinux.org/
  *
@@ -363,7 +363,7 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev)
        struct bfin_rtc *rtc;
        struct device *dev = &pdev->dev;
        int ret = 0;
-       unsigned long timeout;
+       unsigned long timeout = jiffies + HZ;
 
        dev_dbg_stamp(dev);
 
@@ -374,32 +374,32 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, rtc);
        device_init_wakeup(dev, 1);
 
+       /* Register our RTC with the RTC framework */
+       rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops,
+                                               THIS_MODULE);
+       if (unlikely(IS_ERR(rtc->rtc_dev))) {
+               ret = PTR_ERR(rtc->rtc_dev);
+               goto err;
+       }
+
        /* Grab the IRQ and init the hardware */
        ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev);
        if (unlikely(ret))
-               goto err;
+               goto err_reg;
        /* sometimes the bootloader touched things, but the write complete was not
         * enabled, so let's just do a quick timeout here since the IRQ will not fire ...
         */
-       timeout = jiffies + HZ;
        while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING)
                if (time_after(jiffies, timeout))
                        break;
        bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE);
        bfin_write_RTC_SWCNT(0);
 
-       /* Register our RTC with the RTC framework */
-       rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, THIS_MODULE);
-       if (unlikely(IS_ERR(rtc->rtc_dev))) {
-               ret = PTR_ERR(rtc->rtc_dev);
-               goto err_irq;
-       }
-
        return 0;
 
- err_irq:
-       free_irq(IRQ_RTC, dev);
- err:
+err_reg:
+       rtc_device_unregister(rtc->rtc_dev);
+err:
        kfree(rtc);
        return ret;
 }
index 23e10b6263d6f12b36791a5015c7958009b7b5d3..f7a4701bf863695d567340451f4b98a13ce6e14b 100644 (file)
@@ -1174,23 +1174,34 @@ static struct platform_driver cmos_platform_driver = {
        }
 };
 
+#ifdef CONFIG_PNP
+static bool pnp_driver_registered;
+#endif
+static bool platform_driver_registered;
+
 static int __init cmos_init(void)
 {
        int retval = 0;
 
 #ifdef CONFIG_PNP
-       pnp_register_driver(&cmos_pnp_driver);
+       retval = pnp_register_driver(&cmos_pnp_driver);
+       if (retval == 0)
+               pnp_driver_registered = true;
 #endif
 
-       if (!cmos_rtc.dev)
+       if (!cmos_rtc.dev) {
                retval = platform_driver_probe(&cmos_platform_driver,
                                               cmos_platform_probe);
+               if (retval == 0)
+                       platform_driver_registered = true;
+       }
 
        if (retval == 0)
                return 0;
 
 #ifdef CONFIG_PNP
-       pnp_unregister_driver(&cmos_pnp_driver);
+       if (pnp_driver_registered)
+               pnp_unregister_driver(&cmos_pnp_driver);
 #endif
        return retval;
 }
@@ -1199,9 +1210,11 @@ module_init(cmos_init);
 static void __exit cmos_exit(void)
 {
 #ifdef CONFIG_PNP
-       pnp_unregister_driver(&cmos_pnp_driver);
+       if (pnp_driver_registered)
+               pnp_unregister_driver(&cmos_pnp_driver);
 #endif
-       platform_driver_unregister(&cmos_platform_driver);
+       if (platform_driver_registered)
+               platform_driver_unregister(&cmos_platform_driver);
 }
 module_exit(cmos_exit);
 
index 32b27739ec2a4567acd1d2cb2e38535c385d4f27..713f7bf5afb330c508b5d2482804f97ed0083470 100644 (file)
@@ -283,7 +283,7 @@ static void ds1374_work(struct work_struct *work)
 
        stat = i2c_smbus_read_byte_data(client, DS1374_REG_SR);
        if (stat < 0)
-               return;
+               goto unlock;
 
        if (stat & DS1374_REG_SR_AF) {
                stat &= ~DS1374_REG_SR_AF;
@@ -302,7 +302,7 @@ static void ds1374_work(struct work_struct *work)
 out:
        if (!ds1374->exiting)
                enable_irq(client->irq);
-
+unlock:
        mutex_unlock(&ds1374->mutex);
 }
 
index f11297aff854a3bf680d84c382581083e853df5d..2c839d0d21bd2011a82514b31807d2d3d6b591fc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for NEC VR4100 series Real Time Clock unit.
  *
- *  Copyright (C) 2003-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2003-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@linux-mips.org>");
 MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
 MODULE_LICENSE("GPL v2");
 
index 749836668655980c0111be468bbdb8c3edd70e98..3f62dd50bbbe0afeef786877c1de7234ff80662d 100644 (file)
@@ -2135,9 +2135,9 @@ static int dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
        struct dasd_device *base;
 
        block = bdev->bd_disk->private_data;
-       base = block->base;
        if (!block)
                return -ENODEV;
+       base = block->base;
 
        if (!base->discipline ||
            !base->discipline->fill_geometry)
index f8b1f04f26b8ec248c0b69260f9e79d0a44ee8ec..c11770f5b368fe21dabef1ea826a280207176187 100644 (file)
@@ -1696,8 +1696,7 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device,
                DBF_DEV_EVENT(DBF_ERR, device, "%s",
                            "unsolicited interrupt received "
                            "(sense available)");
-               device->discipline->dump_sense_dbf(device, NULL, irb,
-                                                  "unsolicited");
+               device->discipline->dump_sense_dbf(device, irb, "unsolicited");
        }
 
        dasd_schedule_device_bh(device);
@@ -2941,42 +2940,20 @@ dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page)
 }
 
 static void
-dasd_eckd_dump_sense_dbf(struct dasd_device *device, struct dasd_ccw_req *req,
-                        struct irb *irb, char *reason)
+dasd_eckd_dump_sense_dbf(struct dasd_device *device, struct irb *irb,
+                        char *reason)
 {
        u64 *sense;
-       int sl;
-       struct tsb *tsb;
 
-       sense = NULL;
-       tsb = NULL;
-       if (req && scsw_is_tm(&req->irb.scsw)) {
-               if (irb->scsw.tm.tcw)
-                       tsb = tcw_get_tsb(
-                               (struct tcw *)(unsigned long)irb->scsw.tm.tcw);
-               if (tsb && (irb->scsw.tm.fcxs == 0x01)) {
-                       switch (tsb->flags & 0x07) {
-                       case 1: /* tsa_iostat */
-                               sense = (u64 *)tsb->tsa.iostat.sense;
-                       break;
-                       case 2: /* ts_ddpc */
-                               sense = (u64 *)tsb->tsa.ddpc.sense;
-                       break;
-                       case 3: /* tsa_intrg */
-                       break;
-                       }
-               }
-       } else {
-               if (irb->esw.esw0.erw.cons)
-                       sense = (u64 *)irb->ecw;
-       }
+       sense = (u64 *) dasd_get_sense(irb);
        if (sense) {
-               for (sl = 0; sl < 4; sl++) {
-                       DBF_DEV_EVENT(DBF_EMERG, device,
-                                     "%s: %016llx %016llx %016llx %016llx",
-                                     reason, sense[0], sense[1], sense[2],
-                                     sense[3]);
-               }
+               DBF_DEV_EVENT(DBF_EMERG, device,
+                             "%s: %s %02x%02x%02x %016llx %016llx %016llx "
+                             "%016llx", reason,
+                             scsw_is_tm(&irb->scsw) ? "t" : "c",
+                             scsw_cc(&irb->scsw), scsw_cstat(&irb->scsw),
+                             scsw_dstat(&irb->scsw), sense[0], sense[1],
+                             sense[2], sense[3]);
        } else {
                DBF_DEV_EVENT(DBF_EMERG, device, "%s",
                              "SORRY - NO VALID SENSE AVAILABLE\n");
index d970ce2814bedf9af63b5a74e1eb8ff967641820..cb8f9cef742903bc25d6a2402e90d82506c2e446 100644 (file)
@@ -172,7 +172,7 @@ dasd_log_sense_dbf(struct dasd_ccw_req *cqr, struct irb *irb)
        device = cqr->startdev;
        /* dump sense data to s390 debugfeature*/
        if (device->discipline && device->discipline->dump_sense_dbf)
-               device->discipline->dump_sense_dbf(device, cqr, irb, "log");
+               device->discipline->dump_sense_dbf(device, irb, "log");
 }
 EXPORT_SYMBOL(dasd_log_sense_dbf);
 
index e21ee735f92673c4df91fb91a4c788f0b1d97b46..31849ad5e59fe6ddb84dbbb2ce2692165565b2a8 100644 (file)
@@ -241,7 +241,7 @@ static void dasd_fba_handle_unsolicited_interrupt(struct dasd_device *device,
        /* check for unsolicited interrupts */
        DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                    "unsolicited interrupt received");
-       device->discipline->dump_sense_dbf(device, NULL, irb, "unsolicited");
+       device->discipline->dump_sense_dbf(device, irb, "unsolicited");
        dasd_schedule_device_bh(device);
        return;
 };
@@ -444,17 +444,20 @@ dasd_fba_fill_info(struct dasd_device * device,
 }
 
 static void
-dasd_fba_dump_sense_dbf(struct dasd_device *device, struct dasd_ccw_req *req,
-                        struct irb *irb, char *reason)
+dasd_fba_dump_sense_dbf(struct dasd_device *device, struct irb *irb,
+                       char *reason)
 {
-       int sl;
-       if (irb->esw.esw0.erw.cons) {
-               for (sl = 0; sl < 4; sl++) {
-                       DBF_DEV_EVENT(DBF_EMERG, device,
-                                     "%s: %08x %08x %08x %08x",
-                                     reason, irb->ecw[8 * 0], irb->ecw[8 * 1],
-                                     irb->ecw[8 * 2], irb->ecw[8 * 3]);
-               }
+       u64 *sense;
+
+       sense = (u64 *) dasd_get_sense(irb);
+       if (sense) {
+               DBF_DEV_EVENT(DBF_EMERG, device,
+                             "%s: %s %02x%02x%02x %016llx %016llx %016llx "
+                             "%016llx", reason,
+                             scsw_is_tm(&irb->scsw) ? "t" : "c",
+                             scsw_cc(&irb->scsw), scsw_cstat(&irb->scsw),
+                             scsw_dstat(&irb->scsw), sense[0], sense[1],
+                             sense[2], sense[3]);
        } else {
                DBF_DEV_EVENT(DBF_EMERG, device, "%s",
                              "SORRY - NO VALID SENSE AVAILABLE\n");
index fd63b2f2bda9baeaefb4e0edefb2bd2407c4c913..b699ca356ac55077d287591e31225eb0a6fdea58 100644 (file)
@@ -284,8 +284,7 @@ struct dasd_discipline {
        dasd_erp_fn_t(*erp_postaction) (struct dasd_ccw_req *);
        void (*dump_sense) (struct dasd_device *, struct dasd_ccw_req *,
                            struct irb *);
-       void (*dump_sense_dbf) (struct dasd_device *, struct dasd_ccw_req *,
-                           struct irb *, char *);
+       void (*dump_sense_dbf) (struct dasd_device *, struct irb *, char *);
 
        void (*handle_unsolicited_interrupt) (struct dasd_device *,
                                              struct irb *);
index 4ce3f72ee1c13e2485e9a781b389f0eda2fd1c08..df918ef27965ccb6513e32635af8bb41bba561e0 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/blkpg.h>
+#include <linux/smp_lock.h>
 
 #include <asm/ccwdev.h>
 #include <asm/cmb.h>
index 016f9e9d259186e14351168b682b168fb25ab58b..d34617682a6295172a2c0d5d5fa47e258e4d2b23 100644 (file)
@@ -964,7 +964,8 @@ static int dcssblk_freeze(struct device *dev)
                        break;
        }
        if (rc)
-               pr_err("Suspend failed because device %s is writeable.\n",
+               pr_err("Suspending the system failed because DCSS device %s "
+                      "is writable\n",
                       dev_info->segment_name);
        return rc;
 }
@@ -987,8 +988,8 @@ static int dcssblk_restore(struct device *dev)
                                goto out_panic;
                        }
                        if (start != entry->start || end != entry->end) {
-                               pr_err("Mismatch of start / end address after "
-                                      "resuming device %s\n",
+                               pr_err("The address range of DCSS %s changed "
+                                      "while the system was suspended\n",
                                       entry->segment_name);
                                goto out_panic;
                        }
index 2e9e1ecd6d82b2d1f03181d4237d04ff37dedab6..db442cd6621ec9d838325c15c2f47cbb102992a1 100644 (file)
@@ -443,7 +443,7 @@ fail:
  */
 static void xpram_resume_error(const char *message)
 {
-       pr_err("Resume error: %s\n", message);
+       pr_err("Resuming the system failed: %s\n", message);
        panic("xpram resume error\n");
 }
 
index 7892550d793280298175061811a59f2bb07b9256..3234e90bd7f99b6bc632c9844e53e4e479f0aae2 100644 (file)
@@ -320,7 +320,7 @@ static int mon_open(struct inode *inode, struct file *filp)
                goto out_path;
        }
        filp->private_data = monpriv;
-       dev_set_drvdata(&monreader_device, monpriv);
+       dev_set_drvdata(monreader_device, monpriv);
        unlock_kernel();
        return nonseekable_open(inode, filp);
 
@@ -463,7 +463,7 @@ static struct miscdevice mon_dev = {
  *****************************************************************************/
 static int monreader_freeze(struct device *dev)
 {
-       struct mon_private *monpriv = dev_get_drvdata(&dev);
+       struct mon_private *monpriv = dev_get_drvdata(dev);
        int rc;
 
        if (!monpriv)
index 85f491ea929c0da0df28ee54676949354f51b7b0..7a7bfc947d97eb3b502ccb39ee4fd21f751bdb5e 100644 (file)
@@ -92,5 +92,10 @@ void sclp_set_columns(struct sclp_buffer *, unsigned short);
 void sclp_set_htab(struct sclp_buffer *, unsigned short);
 int sclp_chars_in_buffer(struct sclp_buffer *);
 
+#ifdef CONFIG_SCLP_CONSOLE
 void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event);
+#else
+static inline void sclp_console_pm_event(enum sclp_pm_event sclp_pm_event) { }
+#endif
+
 #endif /* __SCLP_RW_H__ */
index cb7854c10c0479585d1879f9c0a3fe8a90a713a1..f2bc287b69e4e4c1c5c35f01ddb500d2ca63aed9 100644 (file)
@@ -250,14 +250,14 @@ static int vmwdt_resume(void)
 static int vmwdt_suspend(void)
 {
        if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open)) {
-               pr_err("The watchdog is in use. "
-                       "This prevents hibernation or suspend.\n");
+               pr_err("The system cannot be suspended while the watchdog"
+                       " is in use\n");
                return NOTIFY_BAD;
        }
        if (test_bit(VMWDT_RUNNING, &vmwdt_is_open)) {
                clear_bit(VMWDT_OPEN, &vmwdt_is_open);
-               pr_err("The watchdog is running. "
-                       "This prevents hibernation or suspend.\n");
+               pr_err("The system cannot be suspended while the watchdog"
+                       " is running\n");
                return NOTIFY_BAD;
        }
        return NOTIFY_DONE;
index 3c57c1a18bb8772db79a73159a98244ae4c89972..d593bc76afe316478374f99e970a37f469cebbf9 100644 (file)
@@ -772,10 +772,8 @@ static struct ccw_device * io_subchannel_create_ccwdev(struct subchannel *sch)
        cdev = io_subchannel_allocate_dev(sch);
        if (!IS_ERR(cdev)) {
                ret = io_subchannel_initialize_dev(sch, cdev);
-               if (ret) {
-                       kfree(cdev);
+               if (ret)
                        cdev = ERR_PTR(ret);
-               }
        }
        return cdev;
 }
index 727a809636d8a63ce93b1271175c3f520ac4455b..ed3dcdea7fe10cb7b521f7ccdb78a1bb5bfc86cc 100644 (file)
@@ -1145,12 +1145,17 @@ ap_config_timeout(unsigned long ptr)
  */
 static inline void ap_schedule_poll_timer(void)
 {
+       ktime_t hr_time;
        if (ap_using_interrupts() || ap_suspend_flag)
                return;
        if (hrtimer_is_queued(&ap_poll_timer))
                return;
-       hrtimer_start(&ap_poll_timer, ktime_set(0, poll_timeout),
-                     HRTIMER_MODE_ABS);
+       if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
+               hr_time = ktime_set(0, poll_timeout);
+               hrtimer_forward_now(&ap_poll_timer, hr_time);
+               hrtimer_restart(&ap_poll_timer);
+       }
+       return;
 }
 
 /**
index 8030e25152fb90e1f4f389c0494f31b82b1d9592..c75d6f35cb5f64d05e88ac8b423d7cb03e2977e6 100644 (file)
@@ -553,40 +553,35 @@ static void _zfcp_erp_unit_reopen_all(struct zfcp_port *port, int clear,
                _zfcp_erp_unit_reopen(unit, clear, id, ref);
 }
 
-static void zfcp_erp_strategy_followup_actions(struct zfcp_erp_action *act)
+static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act)
 {
-       struct zfcp_adapter *adapter = act->adapter;
-       struct zfcp_port *port = act->port;
-       struct zfcp_unit *unit = act->unit;
-       u32 status = act->status;
-
-       /* initiate follow-up actions depending on success of finished action */
        switch (act->action) {
-
        case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
-               if (status == ZFCP_ERP_SUCCEEDED)
-                       _zfcp_erp_port_reopen_all(adapter, 0, "ersfa_1", NULL);
-               else
-                       _zfcp_erp_adapter_reopen(adapter, 0, "ersfa_2", NULL);
+               _zfcp_erp_adapter_reopen(act->adapter, 0, "ersff_1", NULL);
                break;
-
        case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
-               if (status == ZFCP_ERP_SUCCEEDED)
-                       _zfcp_erp_port_reopen(port, 0, "ersfa_3", NULL);
-               else
-                       _zfcp_erp_adapter_reopen(adapter, 0, "ersfa_4", NULL);
+               _zfcp_erp_port_forced_reopen(act->port, 0, "ersff_2", NULL);
                break;
-
        case ZFCP_ERP_ACTION_REOPEN_PORT:
-               if (status == ZFCP_ERP_SUCCEEDED)
-                       _zfcp_erp_unit_reopen_all(port, 0, "ersfa_5", NULL);
-               else
-                       _zfcp_erp_port_forced_reopen(port, 0, "ersfa_6", NULL);
+               _zfcp_erp_port_reopen(act->port, 0, "ersff_3", NULL);
                break;
-
        case ZFCP_ERP_ACTION_REOPEN_UNIT:
-               if (status != ZFCP_ERP_SUCCEEDED)
-                       _zfcp_erp_port_reopen(unit->port, 0, "ersfa_7", NULL);
+               _zfcp_erp_unit_reopen(act->unit, 0, "ersff_4", NULL);
+               break;
+       }
+}
+
+static void zfcp_erp_strategy_followup_success(struct zfcp_erp_action *act)
+{
+       switch (act->action) {
+       case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
+               _zfcp_erp_port_reopen_all(act->adapter, 0, "ersfs_1", NULL);
+               break;
+       case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
+               _zfcp_erp_port_reopen(act->port, 0, "ersfs_2", NULL);
+               break;
+       case ZFCP_ERP_ACTION_REOPEN_PORT:
+               _zfcp_erp_unit_reopen_all(act->port, 0, "ersfs_3", NULL);
                break;
        }
 }
@@ -801,7 +796,7 @@ static int zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action)
                        return ZFCP_ERP_FAILED;
 
        case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
-               if (status & ZFCP_STATUS_PORT_PHYS_OPEN)
+               if (!(status & ZFCP_STATUS_PORT_PHYS_OPEN))
                        return ZFCP_ERP_SUCCEEDED;
        }
        return ZFCP_ERP_FAILED;
@@ -853,11 +848,17 @@ void zfcp_erp_port_strategy_open_lookup(struct work_struct *work)
                                              gid_pn_work);
 
        retval = zfcp_fc_ns_gid_pn(&port->erp_action);
-       if (retval == -ENOMEM)
-               zfcp_erp_notify(&port->erp_action, ZFCP_ERP_NOMEM);
-       port->erp_action.step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
-       if (retval)
-               zfcp_erp_notify(&port->erp_action, ZFCP_ERP_FAILED);
+       if (!retval) {
+               port->erp_action.step = ZFCP_ERP_STEP_NAMESERVER_LOOKUP;
+               goto out;
+       }
+       if (retval == -ENOMEM) {
+               zfcp_erp_notify(&port->erp_action, ZFCP_STATUS_ERP_LOWMEM);
+               goto out;
+       }
+       /* all other error condtions */
+       zfcp_erp_notify(&port->erp_action, 0);
+out:
        zfcp_port_put(port);
 }
 
@@ -1289,7 +1290,10 @@ static int zfcp_erp_strategy(struct zfcp_erp_action *erp_action)
        retval = zfcp_erp_strategy_statechange(erp_action, retval);
        if (retval == ZFCP_ERP_EXIT)
                goto unlock;
-       zfcp_erp_strategy_followup_actions(erp_action);
+       if (retval == ZFCP_ERP_SUCCEEDED)
+               zfcp_erp_strategy_followup_success(erp_action);
+       if (retval == ZFCP_ERP_FAILED)
+               zfcp_erp_strategy_followup_failed(erp_action);
 
  unlock:
        write_unlock(&adapter->erp_lock);
index 2f0705d76b7202095066be064232205b0373fb4e..47daebfa7e59af2f7b17e91184182199ed7bb26f 100644 (file)
@@ -79,11 +79,9 @@ static int zfcp_wka_port_get(struct zfcp_wka_port *wka_port)
 
        mutex_unlock(&wka_port->mutex);
 
-       wait_event_timeout(
-               wka_port->completion_wq,
-               wka_port->status == ZFCP_WKA_PORT_ONLINE ||
-               wka_port->status == ZFCP_WKA_PORT_OFFLINE,
-               HZ >> 1);
+       wait_event(wka_port->completion_wq,
+                  wka_port->status == ZFCP_WKA_PORT_ONLINE ||
+                  wka_port->status == ZFCP_WKA_PORT_OFFLINE);
 
        if (wka_port->status == ZFCP_WKA_PORT_ONLINE) {
                atomic_inc(&wka_port->refcount);
index c57658f3d34f60a9f8c49bb57ccb7c157b9ddb8b..47795fbf081fdc823ec92dc35e00aaee84aec218 100644 (file)
@@ -670,8 +670,11 @@ static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter)
                               zfcp_fsf_sbal_check(adapter), 5 * HZ);
        if (ret > 0)
                return 0;
-       if (!ret)
+       if (!ret) {
                atomic_inc(&adapter->qdio_outb_full);
+               /* assume hanging outbound queue, try queue recovery */
+               zfcp_erp_adapter_reopen(adapter, 0, "fsrsg_1", NULL);
+       }
 
        spin_lock_bh(&adapter->req_q_lock);
        return -EIO;
@@ -722,7 +725,7 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter,
                req = zfcp_fsf_alloc_qtcb(pool);
 
        if (unlikely(!req))
-               return ERR_PTR(-EIO);
+               return ERR_PTR(-ENOMEM);
 
        if (adapter->req_no == 0)
                adapter->req_no++;
@@ -1010,6 +1013,23 @@ skip_fsfstatus:
                send_ct->handler(send_ct->handler_data);
 }
 
+static void zfcp_fsf_setup_ct_els_unchained(struct qdio_buffer_element *sbale,
+                                           struct scatterlist *sg_req,
+                                           struct scatterlist *sg_resp)
+{
+       sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
+       sbale[2].addr   = sg_virt(sg_req);
+       sbale[2].length = sg_req->length;
+       sbale[3].addr   = sg_virt(sg_resp);
+       sbale[3].length = sg_resp->length;
+       sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
+}
+
+static int zfcp_fsf_one_sbal(struct scatterlist *sg)
+{
+       return sg_is_last(sg) && sg->length <= PAGE_SIZE;
+}
+
 static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
                                       struct scatterlist *sg_req,
                                       struct scatterlist *sg_resp,
@@ -1020,30 +1040,30 @@ static int zfcp_fsf_setup_ct_els_sbals(struct zfcp_fsf_req *req,
        int bytes;
 
        if (!(feat & FSF_FEATURE_ELS_CT_CHAINED_SBALS)) {
-               if (sg_req->length > PAGE_SIZE || sg_resp->length > PAGE_SIZE ||
-                   !sg_is_last(sg_req) || !sg_is_last(sg_resp))
+               if (!zfcp_fsf_one_sbal(sg_req) || !zfcp_fsf_one_sbal(sg_resp))
                        return -EOPNOTSUPP;
 
-               sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ;
-               sbale[2].addr   = sg_virt(sg_req);
-               sbale[2].length = sg_req->length;
-               sbale[3].addr   = sg_virt(sg_resp);
-               sbale[3].length = sg_resp->length;
-               sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY;
+               zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
+               return 0;
+       }
+
+       /* use single, unchained SBAL if it can hold the request */
+       if (zfcp_fsf_one_sbal(sg_req) && zfcp_fsf_one_sbal(sg_resp)) {
+               zfcp_fsf_setup_ct_els_unchained(sbale, sg_req, sg_resp);
                return 0;
        }
 
        bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ,
                                        sg_req, max_sbals);
        if (bytes <= 0)
-               return -ENOMEM;
+               return -EIO;
        req->qtcb->bottom.support.req_buf_length = bytes;
        req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL;
 
        bytes = zfcp_qdio_sbals_from_sg(req, SBAL_FLAGS0_TYPE_WRITE_READ,
                                        sg_resp, max_sbals);
        if (bytes <= 0)
-               return -ENOMEM;
+               return -EIO;
        req->qtcb->bottom.support.resp_buf_length = bytes;
 
        return 0;
@@ -1607,10 +1627,10 @@ static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req)
        case FSF_ACCESS_DENIED:
                wka_port->status = ZFCP_WKA_PORT_OFFLINE;
                break;
-       case FSF_PORT_ALREADY_OPEN:
-               break;
        case FSF_GOOD:
                wka_port->handle = header->port_handle;
+               /* fall through */
+       case FSF_PORT_ALREADY_OPEN:
                wka_port->status = ZFCP_WKA_PORT_ONLINE;
        }
 out:
@@ -1731,15 +1751,16 @@ static void zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *req)
                zfcp_fsf_access_denied_port(req, port);
                break;
        case FSF_PORT_BOXED:
-               zfcp_erp_port_boxed(port, "fscpph2", req);
-               req->status |= ZFCP_STATUS_FSFREQ_ERROR |
-                              ZFCP_STATUS_FSFREQ_RETRY;
                /* can't use generic zfcp_erp_modify_port_status because
                 * ZFCP_STATUS_COMMON_OPEN must not be reset for the port */
                atomic_clear_mask(ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
                list_for_each_entry(unit, &port->unit_list_head, list)
                        atomic_clear_mask(ZFCP_STATUS_COMMON_OPEN,
                                          &unit->status);
+               zfcp_erp_port_boxed(port, "fscpph2", req);
+               req->status |= ZFCP_STATUS_FSFREQ_ERROR |
+                              ZFCP_STATUS_FSFREQ_RETRY;
+
                break;
        case FSF_ADAPTER_STATUS_AVAILABLE:
                switch (header->fsf_status_qual.word[0]) {
@@ -2541,7 +2562,6 @@ struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
        bytes = zfcp_qdio_sbals_from_sg(req, direction, fsf_cfdc->sg,
                                        FSF_MAX_SBALS_PER_REQ);
        if (bytes != ZFCP_CFDC_MAX_SIZE) {
-               retval = -ENOMEM;
                zfcp_fsf_req_free(req);
                goto out;
        }
index 967ede73f4c57c3ffcbbc12455dd851c7638d744..6925a17846825109225e7530705505b5151cc477 100644 (file)
@@ -167,20 +167,21 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
        struct zfcp_unit *unit = scpnt->device->hostdata;
        struct zfcp_fsf_req *old_req, *abrt_req;
        unsigned long flags;
-       unsigned long old_req_id = (unsigned long) scpnt->host_scribble;
+       unsigned long old_reqid = (unsigned long) scpnt->host_scribble;
        int retval = SUCCESS;
        int retry = 3;
+       char *dbf_tag;
 
        /* avoid race condition between late normal completion and abort */
        write_lock_irqsave(&adapter->abort_lock, flags);
 
        spin_lock(&adapter->req_list_lock);
-       old_req = zfcp_reqlist_find(adapter, old_req_id);
+       old_req = zfcp_reqlist_find(adapter, old_reqid);
        spin_unlock(&adapter->req_list_lock);
        if (!old_req) {
                write_unlock_irqrestore(&adapter->abort_lock, flags);
                zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL,
-                                         old_req_id);
+                                         old_reqid);
                return FAILED; /* completion could be in progress */
        }
        old_req->data = NULL;
@@ -189,7 +190,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
        write_unlock_irqrestore(&adapter->abort_lock, flags);
 
        while (retry--) {
-               abrt_req = zfcp_fsf_abort_fcp_command(old_req_id, unit);
+               abrt_req = zfcp_fsf_abort_fcp_command(old_reqid, unit);
                if (abrt_req)
                        break;
 
@@ -197,7 +198,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
                if (!(atomic_read(&adapter->status) &
                      ZFCP_STATUS_COMMON_RUNNING)) {
                        zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,
-                                                 old_req_id);
+                                                 old_reqid);
                        return SUCCESS;
                }
        }
@@ -208,13 +209,14 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
                   abrt_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
 
        if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED)
-               zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, abrt_req, 0);
+               dbf_tag = "okay";
        else if (abrt_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED)
-               zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, abrt_req, 0);
+               dbf_tag = "lte2";
        else {
-               zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, abrt_req, 0);
+               dbf_tag = "fail";
                retval = FAILED;
        }
+       zfcp_scsi_dbf_event_abort(dbf_tag, adapter, scpnt, abrt_req, old_reqid);
        zfcp_fsf_req_free(abrt_req);
        return retval;
 }
@@ -534,6 +536,9 @@ static void zfcp_scsi_rport_register(struct zfcp_port *port)
        struct fc_rport_identifiers ids;
        struct fc_rport *rport;
 
+       if (port->rport)
+               return;
+
        ids.node_name = port->wwnn;
        ids.port_name = port->wwpn;
        ids.port_id = port->d_id;
@@ -557,8 +562,10 @@ static void zfcp_scsi_rport_block(struct zfcp_port *port)
 {
        struct fc_rport *rport = port->rport;
 
-       if (rport)
+       if (rport) {
                fc_remote_port_delete(rport);
+               port->rport = NULL;
+       }
 }
 
 void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
index 3e51e64d11081393fe62c849cc7af3ffe7fd6394..0fe5cce818cb48ce69968734f2a90c64267ab5f6 100644 (file)
@@ -494,9 +494,14 @@ static ssize_t zfcp_sysfs_adapter_q_full_show(struct device *dev,
        struct Scsi_Host *scsi_host = class_to_shost(dev);
        struct zfcp_adapter *adapter =
                (struct zfcp_adapter *) scsi_host->hostdata[0];
+       u64 util;
+
+       spin_lock_bh(&adapter->qdio_stat_lock);
+       util = adapter->req_q_util;
+       spin_unlock_bh(&adapter->qdio_stat_lock);
 
        return sprintf(buf, "%d %llu\n", atomic_read(&adapter->qdio_outb_full),
-                      (unsigned long long)adapter->req_q_util);
+                      (unsigned long long)util);
 }
 static DEVICE_ATTR(queue_full, S_IRUGO, zfcp_sysfs_adapter_q_full_show, NULL);
 
index 15dab96d05e31328108b89dabc53ee4b2b5aa573..7c815d3327f754e095212dfc608a64f514547429 100644 (file)
@@ -537,8 +537,12 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp)
        }
        if (temp_index != 0 && fan_index != 0) {
                kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld");
-               if (IS_ERR(kenvctrld_task))
-                       return PTR_ERR(kenvctrld_task);
+               if (IS_ERR(kenvctrld_task)) {
+                       int err = PTR_ERR(kenvctrld_task);
+
+                       kenvctrld_task = NULL;
+                       return err;
+               }
        }
 
        return 0;
@@ -561,7 +565,8 @@ void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp)
        struct bbc_cpu_temperature *tp, *tpos;
        struct bbc_fan_control *fp, *fpos;
 
-       kthread_stop(kenvctrld_task);
+       if (kenvctrld_task)
+               kthread_stop(kenvctrld_task);
 
        list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) {
                list_del(&tp->bp_list);
index 0471f88004836df15f2da6b3bba4ead0489e4439..4240b05aef6d191f8c7f5782ac2c51b07a403de3 100644 (file)
@@ -2826,8 +2826,7 @@ int NCR5380_abort(Scsi_Cmnd *cmd)
         */
 
        local_irq_restore(flags);
-       printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n"
-              KERN_INFO "        before abortion\n", HOSTNO);
+       printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully before abortion\n", HOSTNO);
 
        /* Maybe it is sufficient just to release the ST-DMA lock... (if
         * possible at all) At least, we should check if the lock could be
index 25a2032bfa2615c466de3dc9bcc1f2fbd56e0ec6..70d060b7ff4f6e36ed4d090a030baf7c7da1ece9 100644 (file)
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/cxgb3
+EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3
 
 cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o cxgb3i_ddp.o
 obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o
index 74369a3f963b66bdbdbaa0b71bdd6f848a074048..c399f485aa7d1228c415c703c85ceddafcbdc0cf 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/inet.h>
 #include <linux/crypto.h>
+#include <linux/if_vlan.h>
 #include <net/dst.h>
 #include <net/tcp.h>
 #include <scsi/scsi_cmnd.h>
@@ -184,6 +185,9 @@ static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
        struct cxgb3i_adapter *snic;
        int i;
 
+       if (ndev->priv_flags & IFF_802_1Q_VLAN)
+               ndev = vlan_dev_real_dev(ndev);
+
        read_lock(&cxgb3i_snic_rwlock);
        list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
                for (i = 0; i < snic->hba_cnt; i++) {
index a84072865fc2615a7a9fcce47c48b94fe05f4592..2c266c01dc5ad2848abc5df36bd3b05b1afa5f5f 100644 (file)
@@ -473,16 +473,16 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
         * limitation for the device.  Try 40-bit first, and
         * fail to 32-bit.
         */
-       err = pci_set_dma_mask(pdev, DMA_40BIT_MASK);
+       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(40));
        if (err) {
-               err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+               err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
                if (err) {
                        shost_printk(KERN_ERR, fnic->lport->host,
                                     "No usable DMA configuration "
                                     "aborting\n");
                        goto err_out_release_regions;
                }
-               err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
                if (err) {
                        shost_printk(KERN_ERR, fnic->lport->host,
                                     "Unable to obtain 32-bit DMA "
@@ -490,7 +490,7 @@ static int __devinit fnic_probe(struct pci_dev *pdev,
                        goto err_out_release_regions;
                }
        } else {
-               err = pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK);
+               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40));
                if (err) {
                        shost_printk(KERN_ERR, fnic->lport->host,
                                     "Unable to obtain 40-bit DMA "
index eabf365028568437be0fbd3acbe81abf9dc932c6..bfc996971b814009ac996b295414eacc668c5fe9 100644 (file)
@@ -245,7 +245,7 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
                                          struct vnic_wq_copy *wq,
                                          struct fnic_io_req *io_req,
                                          struct scsi_cmnd *sc,
-                                         u32 sg_count)
+                                         int sg_count)
 {
        struct scatterlist *sg;
        struct fc_rport *rport = starget_to_rport(scsi_target(sc->device));
@@ -260,9 +260,6 @@ static inline int fnic_queue_wq_copy_desc(struct fnic *fnic,
        char msg[2];
 
        if (sg_count) {
-               BUG_ON(sg_count < 0);
-               BUG_ON(sg_count > FNIC_MAX_SG_DESC_CNT);
-
                /* For each SGE, create a device desc entry */
                desc = io_req->sgl_list;
                for_each_sg(scsi_sglist(sc), sg, sg_count, i) {
@@ -344,7 +341,7 @@ int fnic_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
        struct fnic *fnic;
        struct vnic_wq_copy *wq;
        int ret;
-       u32 sg_count;
+       int sg_count;
        unsigned long flags;
        unsigned long ptr;
 
index 869a11bdccbdf3cf63773b2bebc1ff1358d623a8..9928704e235f4f1d5d35c48fd877781297f78a50 100644 (file)
@@ -1095,9 +1095,14 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct)
                                MAX_INDIRECT_BUFS);
                        hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS;
                }
+
+               if (hostdata->madapter_info.os_type == 3) {
+                       enable_fast_fail(hostdata);
+                       return;
+               }
        }
 
-       enable_fast_fail(hostdata);
+       send_srp_login(hostdata);
 }
 
 /**
index 2bc22be5f84944277edc2d7c8b3248a74a4d76e9..145ab9ba55ea0804a3b6c061f9f090c0670b1d6a 100644 (file)
@@ -415,9 +415,9 @@ static void fc_exch_timeout(struct work_struct *work)
        e_stat = ep->esb_stat;
        if (e_stat & ESB_ST_COMPLETE) {
                ep->esb_stat = e_stat & ~ESB_ST_REC_QUAL;
+               spin_unlock_bh(&ep->ex_lock);
                if (e_stat & ESB_ST_REC_QUAL)
                        fc_exch_rrq(ep);
-               spin_unlock_bh(&ep->ex_lock);
                goto done;
        } else {
                resp = ep->resp;
@@ -1624,14 +1624,14 @@ static void fc_exch_rrq(struct fc_exch *ep)
        struct fc_lport *lp;
        struct fc_els_rrq *rrq;
        struct fc_frame *fp;
-       struct fc_seq *rrq_sp;
        u32 did;
 
        lp = ep->lp;
 
        fp = fc_frame_alloc(lp, sizeof(*rrq));
        if (!fp)
-               return;
+               goto retry;
+
        rrq = fc_frame_payload_get(fp, sizeof(*rrq));
        memset(rrq, 0, sizeof(*rrq));
        rrq->rrq_cmd = ELS_RRQ;
@@ -1647,13 +1647,20 @@ static void fc_exch_rrq(struct fc_exch *ep)
                       fc_host_port_id(lp->host), FC_TYPE_ELS,
                       FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
 
-       rrq_sp = fc_exch_seq_send(lp, fp, fc_exch_rrq_resp, NULL, ep,
-                                 lp->e_d_tov);
-       if (!rrq_sp) {
-               ep->esb_stat |= ESB_ST_REC_QUAL;
-               fc_exch_timer_set_locked(ep, ep->r_a_tov);
+       if (fc_exch_seq_send(lp, fp, fc_exch_rrq_resp, NULL, ep, lp->e_d_tov))
+               return;
+
+retry:
+       spin_lock_bh(&ep->ex_lock);
+       if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE)) {
+               spin_unlock_bh(&ep->ex_lock);
+               /* drop hold for rec qual */
+               fc_exch_release(ep);
                return;
        }
+       ep->esb_stat |= ESB_ST_REC_QUAL;
+       fc_exch_timer_set_locked(ep, ep->r_a_tov);
+       spin_unlock_bh(&ep->ex_lock);
 }
 
 
index 716cc344c5dfb5253eb5436cd0e19e5fbaa82b66..a751f6230c2258f4e7870391b96330d08e209e5a 100644 (file)
@@ -1974,10 +1974,10 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
                 * good and have never sent us a successful tmf response
                 * then sent more data for the cmd.
                 */
-               spin_lock(&session->lock);
+               spin_lock_bh(&session->lock);
                fail_scsi_task(task, DID_ABORT);
                conn->tmf_state = TMF_INITIAL;
-               spin_unlock(&session->lock);
+               spin_unlock_bh(&session->lock);
                iscsi_start_tx(conn);
                goto success_unlocked;
        case TMF_TIMEDOUT:
index 54fa1e42dc4d2dfba29cdf52afd52d909af67139..b3381959acce19ee167c183ccd7b2b9354203c1b 100644 (file)
@@ -766,6 +766,7 @@ static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id)
                if (!memcmp(phy->attached_sas_addr, ephy->attached_sas_addr,
                            SAS_ADDR_SIZE) && ephy->port) {
                        sas_port_add_phy(ephy->port, phy->phy);
+                       phy->port = ephy->port;
                        phy->phy_state = PHY_DEVICE_DISCOVERED;
                        return 0;
                }
@@ -945,11 +946,21 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id)
                        if (ex->ex_phy[i].phy_state == PHY_VACANT ||
                            ex->ex_phy[i].phy_state == PHY_NOT_PRESENT)
                                continue;
-
+                       /*
+                        * Due to races, the phy might not get added to the
+                        * wide port, so we add the phy to the wide port here.
+                        */
                        if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) ==
-                           SAS_ADDR(child->sas_addr))
+                           SAS_ADDR(child->sas_addr)) {
                                ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED;
+                               res = sas_ex_join_wide_port(dev, i);
+                               if (!res)
+                                       SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n",
+                                                   i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr));
+
+                       }
                }
+               res = 0;
        }
 
        return res;
@@ -1598,7 +1609,7 @@ static int sas_get_phy_attached_sas_addr(struct domain_device *dev,
 }
 
 static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id,
-                             int from_phy)
+                             int from_phy, bool update)
 {
        struct expander_device *ex = &dev->ex_dev;
        int res = 0;
@@ -1611,7 +1622,9 @@ static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id,
                if (res)
                        goto out;
                else if (phy_change_count != ex->ex_phy[i].phy_change_count) {
-                       ex->ex_phy[i].phy_change_count = phy_change_count;
+                       if (update)
+                               ex->ex_phy[i].phy_change_count =
+                                       phy_change_count;
                        *phy_id = i;
                        return 0;
                }
@@ -1653,31 +1666,52 @@ out:
        kfree(rg_req);
        return res;
 }
+/**
+ * sas_find_bcast_dev -  find the device issue BROADCAST(CHANGE).
+ * @dev:domain device to be detect.
+ * @src_dev: the device which originated BROADCAST(CHANGE).
+ *
+ * Add self-configuration expander suport. Suppose two expander cascading,
+ * when the first level expander is self-configuring, hotplug the disks in
+ * second level expander, BROADCAST(CHANGE) will not only be originated
+ * in the second level expander, but also be originated in the first level
+ * expander (see SAS protocol SAS 2r-14, 7.11 for detail), it is to say,
+ * expander changed count in two level expanders will all increment at least
+ * once, but the phy which chang count has changed is the source device which
+ * we concerned.
+ */
 
 static int sas_find_bcast_dev(struct domain_device *dev,
                              struct domain_device **src_dev)
 {
        struct expander_device *ex = &dev->ex_dev;
        int ex_change_count = -1;
+       int phy_id = -1;
        int res;
+       struct domain_device *ch;
 
        res = sas_get_ex_change_count(dev, &ex_change_count);
        if (res)
                goto out;
-       if (ex_change_count != -1 &&
-           ex_change_count != ex->ex_change_count) {
-               *src_dev = dev;
-               ex->ex_change_count = ex_change_count;
-       } else {
-               struct domain_device *ch;
-
-               list_for_each_entry(ch, &ex->children, siblings) {
-                       if (ch->dev_type == EDGE_DEV ||
-                           ch->dev_type == FANOUT_DEV) {
-                               res = sas_find_bcast_dev(ch, src_dev);
-                               if (src_dev)
-                                       return res;
-                       }
+       if (ex_change_count != -1 && ex_change_count != ex->ex_change_count) {
+               /* Just detect if this expander phys phy change count changed,
+               * in order to determine if this expander originate BROADCAST,
+               * and do not update phy change count field in our structure.
+               */
+               res = sas_find_bcast_phy(dev, &phy_id, 0, false);
+               if (phy_id != -1) {
+                       *src_dev = dev;
+                       ex->ex_change_count = ex_change_count;
+                       SAS_DPRINTK("Expander phy change count has changed\n");
+                       return res;
+               } else
+                       SAS_DPRINTK("Expander phys DID NOT change\n");
+       }
+       list_for_each_entry(ch, &ex->children, siblings) {
+               if (ch->dev_type == EDGE_DEV || ch->dev_type == FANOUT_DEV) {
+                       res = sas_find_bcast_dev(ch, src_dev);
+                       if (src_dev)
+                               return res;
                }
        }
 out:
@@ -1700,24 +1734,26 @@ static void sas_unregister_ex_tree(struct domain_device *dev)
 }
 
 static void sas_unregister_devs_sas_addr(struct domain_device *parent,
-                                        int phy_id)
+                                        int phy_id, bool last)
 {
        struct expander_device *ex_dev = &parent->ex_dev;
        struct ex_phy *phy = &ex_dev->ex_phy[phy_id];
        struct domain_device *child, *n;
-
-       list_for_each_entry_safe(child, n, &ex_dev->children, siblings) {
-               if (SAS_ADDR(child->sas_addr) ==
-                   SAS_ADDR(phy->attached_sas_addr)) {
-                       if (child->dev_type == EDGE_DEV ||
-                           child->dev_type == FANOUT_DEV)
-                               sas_unregister_ex_tree(child);
-                       else
-                               sas_unregister_dev(child);
-                       break;
+       if (last) {
+               list_for_each_entry_safe(child, n,
+                       &ex_dev->children, siblings) {
+                       if (SAS_ADDR(child->sas_addr) ==
+                           SAS_ADDR(phy->attached_sas_addr)) {
+                               if (child->dev_type == EDGE_DEV ||
+                                   child->dev_type == FANOUT_DEV)
+                                       sas_unregister_ex_tree(child);
+                               else
+                                       sas_unregister_dev(child);
+                               break;
+                       }
                }
+               sas_disable_routing(parent, phy->attached_sas_addr);
        }
-       sas_disable_routing(parent, phy->attached_sas_addr);
        memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
        sas_port_delete_phy(phy->port, phy->phy);
        if (phy->port->num_phys == 0)
@@ -1770,15 +1806,31 @@ static int sas_discover_new(struct domain_device *dev, int phy_id)
 {
        struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id];
        struct domain_device *child;
-       int res;
+       bool found = false;
+       int res, i;
 
        SAS_DPRINTK("ex %016llx phy%d new device attached\n",
                    SAS_ADDR(dev->sas_addr), phy_id);
        res = sas_ex_phy_discover(dev, phy_id);
        if (res)
                goto out;
+       /* to support the wide port inserted */
+       for (i = 0; i < dev->ex_dev.num_phys; i++) {
+               struct ex_phy *ex_phy_temp = &dev->ex_dev.ex_phy[i];
+               if (i == phy_id)
+                       continue;
+               if (SAS_ADDR(ex_phy_temp->attached_sas_addr) ==
+                   SAS_ADDR(ex_phy->attached_sas_addr)) {
+                       found = true;
+                       break;
+               }
+       }
+       if (found) {
+               sas_ex_join_wide_port(dev, phy_id);
+               return 0;
+       }
        res = sas_ex_discover_devices(dev, phy_id);
-       if (res)
+       if (!res)
                goto out;
        list_for_each_entry(child, &dev->ex_dev.children, siblings) {
                if (SAS_ADDR(child->sas_addr) ==
@@ -1793,7 +1845,7 @@ out:
        return res;
 }
 
-static int sas_rediscover_dev(struct domain_device *dev, int phy_id)
+static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last)
 {
        struct expander_device *ex = &dev->ex_dev;
        struct ex_phy *phy = &ex->ex_phy[phy_id];
@@ -1804,11 +1856,11 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id)
        switch (res) {
        case SMP_RESP_NO_PHY:
                phy->phy_state = PHY_NOT_PRESENT;
-               sas_unregister_devs_sas_addr(dev, phy_id);
+               sas_unregister_devs_sas_addr(dev, phy_id, last);
                goto out; break;
        case SMP_RESP_PHY_VACANT:
                phy->phy_state = PHY_VACANT;
-               sas_unregister_devs_sas_addr(dev, phy_id);
+               sas_unregister_devs_sas_addr(dev, phy_id, last);
                goto out; break;
        case SMP_RESP_FUNC_ACC:
                break;
@@ -1816,7 +1868,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id)
 
        if (SAS_ADDR(attached_sas_addr) == 0) {
                phy->phy_state = PHY_EMPTY;
-               sas_unregister_devs_sas_addr(dev, phy_id);
+               sas_unregister_devs_sas_addr(dev, phy_id, last);
        } else if (SAS_ADDR(attached_sas_addr) ==
                   SAS_ADDR(phy->attached_sas_addr)) {
                SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter\n",
@@ -1828,12 +1880,27 @@ out:
        return res;
 }
 
+/**
+ * sas_rediscover - revalidate the domain.
+ * @dev:domain device to be detect.
+ * @phy_id: the phy id will be detected.
+ *
+ * NOTE: this process _must_ quit (return) as soon as any connection
+ * errors are encountered.  Connection recovery is done elsewhere.
+ * Discover process only interrogates devices in order to discover the
+ * domain.For plugging out, we un-register the device only when it is
+ * the last phy in the port, for other phys in this port, we just delete it
+ * from the port.For inserting, we do discovery when it is the
+ * first phy,for other phys in this port, we add it to the port to
+ * forming the wide-port.
+ */
 static int sas_rediscover(struct domain_device *dev, const int phy_id)
 {
        struct expander_device *ex = &dev->ex_dev;
        struct ex_phy *changed_phy = &ex->ex_phy[phy_id];
        int res = 0;
        int i;
+       bool last = true;       /* is this the last phy of the port */
 
        SAS_DPRINTK("ex %016llx phy%d originated BROADCAST(CHANGE)\n",
                    SAS_ADDR(dev->sas_addr), phy_id);
@@ -1848,13 +1915,13 @@ static int sas_rediscover(struct domain_device *dev, const int phy_id)
                            SAS_ADDR(changed_phy->attached_sas_addr)) {
                                SAS_DPRINTK("phy%d part of wide port with "
                                            "phy%d\n", phy_id, i);
-                               goto out;
+                               last = false;
+                               break;
                        }
                }
-               res = sas_rediscover_dev(dev, phy_id);
+               res = sas_rediscover_dev(dev, phy_id, last);
        } else
                res = sas_discover_new(dev, phy_id);
-out:
        return res;
 }
 
@@ -1881,7 +1948,7 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev)
 
                do {
                        phy_id = -1;
-                       res = sas_find_bcast_phy(dev, &phy_id, i);
+                       res = sas_find_bcast_phy(dev, &phy_id, i, true);
                        if (phy_id == -1)
                                break;
                        res = sas_rediscover(dev, phy_id);
index e6ac59c023f199393b10eed05bb086f34a12fee4..fe8b74c706d21d4449887070133db3294d1b50ac 100644 (file)
@@ -56,7 +56,7 @@ static void sas_form_port(struct asd_sas_phy *phy)
                }
        }
 
-       /* find a port */
+       /* see if the phy should be part of a wide port */
        spin_lock_irqsave(&sas_ha->phy_port_lock, flags);
        for (i = 0; i < sas_ha->num_phys; i++) {
                port = sas_ha->sas_port[i];
@@ -69,12 +69,23 @@ static void sas_form_port(struct asd_sas_phy *phy)
                        SAS_DPRINTK("phy%d matched wide port%d\n", phy->id,
                                    port->id);
                        break;
-               } else if (*(u64 *) port->sas_addr == 0 && port->num_phys==0) {
-                       memcpy(port->sas_addr, phy->sas_addr, SAS_ADDR_SIZE);
-                       break;
                }
                spin_unlock(&port->phy_list_lock);
        }
+       /* The phy does not match any existing port, create a new one */
+       if (i == sas_ha->num_phys) {
+               for (i = 0; i < sas_ha->num_phys; i++) {
+                       port = sas_ha->sas_port[i];
+                       spin_lock(&port->phy_list_lock);
+                       if (*(u64 *)port->sas_addr == 0
+                               && port->num_phys == 0) {
+                               memcpy(port->sas_addr, phy->sas_addr,
+                                       SAS_ADDR_SIZE);
+                               break;
+                       }
+                       spin_unlock(&port->phy_list_lock);
+               }
+       }
 
        if (i >= sas_ha->num_phys) {
                printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n",
index b12ad7c7c6736908419987896a2402898ba2620e..18735b39b3d39c8547e27b8037fbef033a0df76a 100644 (file)
@@ -75,8 +75,9 @@ static int mac53c94_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *
                int i;
                printk(KERN_DEBUG "mac53c94_queue %p: command is", cmd);
                for (i = 0; i < cmd->cmd_len; ++i)
-                       printk(" %.2x", cmd->cmnd[i]);
-               printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n",
+                       printk(KERN_CONT " %.2x", cmd->cmnd[i]);
+               printk(KERN_CONT "\n");
+               printk(KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n",
                       scsi_sg_count(cmd), scsi_bufflen(cmd), scsi_sglist(cmd));
        }
 #endif
index f3da592f7bccc204fc08d901e9fabbd2c1eb6ee7..35a13867495ee3c5c0b2ddd6e72b7433887f5c11 100644 (file)
@@ -119,6 +119,64 @@ _base_fault_reset_work(struct work_struct *work)
        spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
 }
 
+/**
+ * mpt2sas_base_start_watchdog - start the fault_reset_work_q
+ * @ioc: pointer to scsi command object
+ * Context: sleep.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc)
+{
+       unsigned long    flags;
+
+       if (ioc->fault_reset_work_q)
+               return;
+
+       /* initialize fault polling */
+       INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
+       snprintf(ioc->fault_reset_work_q_name,
+           sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
+       ioc->fault_reset_work_q =
+               create_singlethread_workqueue(ioc->fault_reset_work_q_name);
+       if (!ioc->fault_reset_work_q) {
+               printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n",
+                   ioc->name, __func__, __LINE__);
+                       return;
+       }
+       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+       if (ioc->fault_reset_work_q)
+               queue_delayed_work(ioc->fault_reset_work_q,
+                   &ioc->fault_reset_work,
+                   msecs_to_jiffies(FAULT_POLLING_INTERVAL));
+       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+}
+
+/**
+ * mpt2sas_base_stop_watchdog - stop the fault_reset_work_q
+ * @ioc: pointer to scsi command object
+ * Context: sleep.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc)
+{
+       unsigned long    flags;
+       struct workqueue_struct *wq;
+
+       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+       wq = ioc->fault_reset_work_q;
+       ioc->fault_reset_work_q = NULL;
+       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       if (wq) {
+               if (!cancel_delayed_work(&ioc->fault_reset_work))
+                       flush_workqueue(wq);
+               destroy_workqueue(wq);
+       }
+}
+
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 /**
  * _base_sas_ioc_info - verbose translation of the ioc status
@@ -440,6 +498,10 @@ _base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info)
        if (sas_loginfo.dw.bus_type != 3 /*SAS*/)
                return;
 
+       /* each nexus loss loginfo */
+       if (log_info == 0x31170000)
+               return;
+
        /* eat the loginfos associated with task aborts */
        if (ioc->ignore_loginfos && (log_info == 30050000 || log_info ==
            0x31140000 || log_info == 0x31130000))
@@ -1109,7 +1171,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
                }
        }
 
-       pci_set_drvdata(pdev, ioc->shost);
        _base_mask_interrupts(ioc);
        r = _base_enable_msix(ioc);
        if (r)
@@ -1132,7 +1193,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
        ioc->pci_irq = -1;
        pci_release_selected_regions(ioc->pdev, ioc->bars);
        pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
        return r;
 }
 
@@ -3191,7 +3251,6 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc)
        ioc->chip_phys = 0;
        pci_release_selected_regions(ioc->pdev, ioc->bars);
        pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
        return;
 }
 
@@ -3205,7 +3264,6 @@ int
 mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
 {
        int r, i;
-       unsigned long    flags;
 
        dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
            __func__));
@@ -3214,6 +3272,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
        if (r)
                return r;
 
+       pci_set_drvdata(ioc->pdev, ioc->shost);
        r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
        if (r)
                goto out_free_resources;
@@ -3288,23 +3347,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
        if (r)
                goto out_free_resources;
 
-       /* initialize fault polling */
-       INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
-       snprintf(ioc->fault_reset_work_q_name,
-           sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
-       ioc->fault_reset_work_q =
-               create_singlethread_workqueue(ioc->fault_reset_work_q_name);
-       if (!ioc->fault_reset_work_q) {
-               printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n",
-                   ioc->name, __func__, __LINE__);
-                       goto out_free_resources;
-       }
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       if (ioc->fault_reset_work_q)
-               queue_delayed_work(ioc->fault_reset_work_q,
-                   &ioc->fault_reset_work,
-                   msecs_to_jiffies(FAULT_POLLING_INTERVAL));
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+       mpt2sas_base_start_watchdog(ioc);
        return 0;
 
  out_free_resources:
@@ -3312,6 +3355,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
        ioc->remove_host = 1;
        mpt2sas_base_free_resources(ioc);
        _base_release_memory_pools(ioc);
+       pci_set_drvdata(ioc->pdev, NULL);
        kfree(ioc->tm_cmds.reply);
        kfree(ioc->transport_cmds.reply);
        kfree(ioc->config_cmds.reply);
@@ -3337,22 +3381,14 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
 void
 mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)
 {
-       unsigned long    flags;
-       struct workqueue_struct *wq;
 
        dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
            __func__));
 
-       spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
-       wq = ioc->fault_reset_work_q;
-       ioc->fault_reset_work_q = NULL;
-       spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
-       if (!cancel_delayed_work(&ioc->fault_reset_work))
-               flush_workqueue(wq);
-       destroy_workqueue(wq);
-
+       mpt2sas_base_stop_watchdog(ioc);
        mpt2sas_base_free_resources(ioc);
        _base_release_memory_pools(ioc);
+       pci_set_drvdata(ioc->pdev, NULL);
        kfree(ioc->pfacts);
        kfree(ioc->ctl_cmds.reply);
        kfree(ioc->base_cmds.reply);
index 286c185fa9e40a5b7347de0dc99b06c4d2f0e617..acdcff150a35015d391ae80b8b3eeb8d6f14f5c1 100644 (file)
 #define MPT2SAS_DRIVER_NAME            "mpt2sas"
 #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
 #define MPT2SAS_DESCRIPTION    "LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION         "01.100.03.00"
+#define MPT2SAS_DRIVER_VERSION         "01.100.04.00"
 #define MPT2SAS_MAJOR_VERSION          01
 #define MPT2SAS_MINOR_VERSION          100
-#define MPT2SAS_BUILD_VERSION          03
+#define MPT2SAS_BUILD_VERSION          04
 #define MPT2SAS_RELEASE_VERSION                00
 
 /*
@@ -673,6 +673,8 @@ typedef void (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
 
 /* base shared API */
 extern struct list_head mpt2sas_ioc_list;
+void mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc);
+void mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc);
 
 int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc);
 void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc);
index 58cfb97846f7e292a5c30a34b1e44c7cce876824..6ddee161beb36aae9d2357c0f7c9926db189079b 100644 (file)
@@ -236,17 +236,25 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
        Mpi2ConfigRequest_t *config_request;
        int r;
        u8 retry_count;
-       u8 issue_reset;
+       u8 issue_host_reset = 0;
        u16 wait_state_count;
 
+       mutex_lock(&ioc->config_cmds.mutex);
        if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) {
                printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n",
                    ioc->name, __func__);
+               mutex_unlock(&ioc->config_cmds.mutex);
                return -EAGAIN;
        }
        retry_count = 0;
 
  retry_config:
+       if (retry_count) {
+               if (retry_count > 2) /* attempt only 2 retries */
+                       return -EFAULT;
+               printk(MPT2SAS_INFO_FMT "%s: attempting retry (%d)\n",
+                   ioc->name, __func__, retry_count);
+       }
        wait_state_count = 0;
        ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
        while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
@@ -254,8 +262,8 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
                        printk(MPT2SAS_ERR_FMT
                            "%s: failed due to ioc not operational\n",
                            ioc->name, __func__);
-                       ioc->config_cmds.status = MPT2_CMD_NOT_USED;
-                       return -EFAULT;
+                       r = -EFAULT;
+                       goto out;
                }
                ssleep(1);
                ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
@@ -271,8 +279,8 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
        if (!smid) {
                printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
                    ioc->name, __func__);
-               ioc->config_cmds.status = MPT2_CMD_NOT_USED;
-               return -EAGAIN;
+               r = -EAGAIN;
+               goto out;
        }
 
        r = 0;
@@ -292,9 +300,15 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
                    ioc->name, __func__);
                _debug_dump_mf(mpi_request,
                    sizeof(Mpi2ConfigRequest_t)/4);
-               if (!(ioc->config_cmds.status & MPT2_CMD_RESET))
-                       issue_reset = 1;
-               goto issue_host_reset;
+               retry_count++;
+               if (ioc->config_cmds.smid == smid)
+                       mpt2sas_base_free_smid(ioc, smid);
+               if ((ioc->shost_recovery) ||
+                   (ioc->config_cmds.status & MPT2_CMD_RESET))
+                       goto retry_config;
+               issue_host_reset = 1;
+               r = -EFAULT;
+               goto out;
        }
        if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID)
                memcpy(mpi_reply, ioc->config_cmds.reply,
@@ -302,21 +316,13 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
        if (retry_count)
                printk(MPT2SAS_INFO_FMT "%s: retry completed!!\n",
                    ioc->name, __func__);
+out:
        ioc->config_cmds.status = MPT2_CMD_NOT_USED;
-       return r;
-
- issue_host_reset:
-       if (issue_reset)
+       mutex_unlock(&ioc->config_cmds.mutex);
+       if (issue_host_reset)
                mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
                    FORCE_BIG_HAMMER);
-       ioc->config_cmds.status = MPT2_CMD_NOT_USED;
-       if (!retry_count) {
-               printk(MPT2SAS_INFO_FMT "%s: attempting retry\n",
-                   ioc->name, __func__);
-               retry_count++;
-               goto retry_config;
-       }
-       return -EFAULT;
+       return r;
 }
 
 /**
@@ -375,7 +381,6 @@ mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sizeof(Mpi2ManufacturingPage0_t));
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -417,7 +422,6 @@ mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -438,7 +442,6 @@ mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc,
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sizeof(Mpi2BiosPage2_t));
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -480,7 +483,6 @@ mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc,
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -501,7 +503,6 @@ mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sizeof(Mpi2BiosPage3_t));
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -543,7 +544,6 @@ mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -564,7 +564,6 @@ mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc,
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sizeof(Mpi2IOUnitPage0_t));
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -606,7 +605,6 @@ mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc,
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -627,7 +625,6 @@ mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sizeof(Mpi2IOUnitPage1_t));
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -669,7 +666,6 @@ mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -690,7 +686,6 @@ mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
@@ -732,7 +727,6 @@ mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -753,7 +747,6 @@ mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc,
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sizeof(Mpi2IOCPage8_t));
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -795,7 +788,6 @@ mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc,
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -818,7 +810,6 @@ mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sizeof(Mpi2SasDevicePage0_t));
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -863,7 +854,6 @@ mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -886,7 +876,6 @@ mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sizeof(Mpi2SasDevicePage1_t));
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -931,7 +920,6 @@ mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -953,7 +941,6 @@ mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys)
        Mpi2ConfigReply_t mpi_reply;
        Mpi2SasIOUnitPage0_t config_page;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
        mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
@@ -1002,7 +989,6 @@ mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys)
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -1026,8 +1012,6 @@ mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
        Mpi2ConfigRequest_t mpi_request;
        int r;
        struct config_request mem;
-
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sz);
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1070,7 +1054,6 @@ mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -1095,7 +1078,6 @@ mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sz);
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1138,7 +1120,6 @@ mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -1161,7 +1142,6 @@ mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sizeof(Mpi2ExpanderPage0_t));
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1206,7 +1186,6 @@ mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -1230,7 +1209,6 @@ mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sizeof(Mpi2ExpanderPage1_t));
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1277,7 +1255,6 @@ mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -1300,7 +1277,6 @@ mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sizeof(Mpi2SasEnclosurePage0_t));
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1345,7 +1321,6 @@ mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -1367,7 +1342,6 @@ mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sizeof(Mpi2SasPhyPage0_t));
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1413,7 +1387,6 @@ mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -1435,7 +1408,6 @@ mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sizeof(Mpi2SasPhyPage1_t));
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1481,7 +1453,6 @@ mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -1505,7 +1476,6 @@ mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc,
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(config_page, 0, sizeof(Mpi2RaidVolPage1_t));
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1548,7 +1518,6 @@ mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc,
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -1572,7 +1541,6 @@ mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle,
        struct config_request mem;
        u16 ioc_status;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        *num_pds = 0;
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1620,7 +1588,6 @@ mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle,
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -1645,7 +1612,6 @@ mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc,
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        memset(config_page, 0, sz);
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1687,7 +1653,6 @@ mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc,
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -1711,7 +1676,6 @@ mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
        int r;
        struct config_request mem;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        memset(config_page, 0, sizeof(Mpi2RaidPhysDiskPage0_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1754,7 +1718,6 @@ mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
@@ -1778,7 +1741,6 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
        struct config_request mem;
        u16 ioc_status;
 
-       mutex_lock(&ioc->config_cmds.mutex);
        *volume_handle = 0;
        memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
        mpi_request.Function = MPI2_FUNCTION_CONFIG;
@@ -1842,7 +1804,6 @@ mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
                _config_free_config_dma_memory(ioc, &mem);
 
  out:
-       mutex_unlock(&ioc->config_cmds.mutex);
        return r;
 }
 
index 2a01a5f2a84dddc4d105d5ef88030abe1adc21ab..2e9a4445596f4a8e5707d74fb770aceeaa7b908d 100644 (file)
@@ -2767,6 +2767,10 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
        char *desc_ioc_state = NULL;
        char *desc_scsi_status = NULL;
        char *desc_scsi_state = ioc->tmp_string;
+       u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
+
+       if (log_info == 0x31170000)
+               return;
 
        switch (ioc_status) {
        case MPI2_IOCSTATUS_SUCCESS:
@@ -3426,7 +3430,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
        __le64 sas_address;
        int i;
        unsigned long flags;
-       struct _sas_port *mpt2sas_port;
+       struct _sas_port *mpt2sas_port = NULL;
        int rc = 0;
 
        if (!handle)
@@ -3518,12 +3522,20 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
                    &expander_pg1, i, handle))) {
                        printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
                            ioc->name, __FILE__, __LINE__, __func__);
-                       continue;
+                       rc = -1;
+                       goto out_fail;
                }
                sas_expander->phy[i].handle = handle;
                sas_expander->phy[i].phy_id = i;
-               mpt2sas_transport_add_expander_phy(ioc, &sas_expander->phy[i],
-                   expander_pg1, sas_expander->parent_dev);
+
+               if ((mpt2sas_transport_add_expander_phy(ioc,
+                   &sas_expander->phy[i], expander_pg1,
+                   sas_expander->parent_dev))) {
+                       printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+                           ioc->name, __FILE__, __LINE__, __func__);
+                       rc = -1;
+                       goto out_fail;
+               }
        }
 
        if (sas_expander->enclosure_handle) {
@@ -3540,8 +3552,9 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
 
  out_fail:
 
-       if (sas_expander)
-               kfree(sas_expander->phy);
+       if (mpt2sas_port)
+               mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
+                   sas_expander->parent_handle);
        kfree(sas_expander);
        return rc;
 }
@@ -3663,12 +3676,11 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd)
        sas_device->hidden_raid_component = is_pd;
 
        /* get enclosure_logical_id */
-       if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply, &enclosure_pg0,
-          MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
-          sas_device->enclosure_handle))) {
+       if (sas_device->enclosure_handle && !(mpt2sas_config_get_enclosure_pg0(
+          ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
+          sas_device->enclosure_handle)))
                sas_device->enclosure_logical_id =
                    le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
-       }
 
        /* get device name */
        sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
@@ -4250,12 +4262,6 @@ _scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc,
        u16 handle = le16_to_cpu(element->VolDevHandle);
        int rc;
 
-#if 0 /* RAID_HACKS */
-       if (le32_to_cpu(event_data->Flags) &
-           MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
-               return;
-#endif
-
        mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
        if (!wwid) {
                printk(MPT2SAS_ERR_FMT
@@ -4310,12 +4316,6 @@ _scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc,
        unsigned long flags;
        struct MPT2SAS_TARGET *sas_target_priv_data;
 
-#if 0 /* RAID_HACKS */
-       if (le32_to_cpu(event_data->Flags) &
-           MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
-               return;
-#endif
-
        spin_lock_irqsave(&ioc->raid_device_lock, flags);
        raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
        spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
@@ -4428,14 +4428,38 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc,
        struct _sas_device *sas_device;
        unsigned long flags;
        u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
+       Mpi2ConfigReply_t mpi_reply;
+       Mpi2SasDevicePage0_t sas_device_pg0;
+       u32 ioc_status;
 
        spin_lock_irqsave(&ioc->sas_device_lock, flags);
        sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
-       if (sas_device)
+       if (sas_device) {
                sas_device->hidden_raid_component = 1;
-       else
-               _scsih_add_device(ioc, handle, 0, 1);
+               return;
+       }
+
+       if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+           MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
+               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return;
+       }
+
+       ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+           MPI2_IOCSTATUS_MASK;
+       if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+               printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+                   ioc->name, __FILE__, __LINE__, __func__);
+               return;
+       }
+
+       _scsih_link_change(ioc,
+           le16_to_cpu(sas_device_pg0.ParentDevHandle),
+           handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
+
+       _scsih_add_device(ioc, handle, 0, 1);
 }
 
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
@@ -4535,12 +4559,15 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
 {
        Mpi2EventIrConfigElement_t *element;
        int i;
+       u8 foreign_config;
 
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
        if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
                _scsih_sas_ir_config_change_event_debug(ioc, event_data);
 
 #endif
+       foreign_config = (le32_to_cpu(event_data->Flags) &
+           MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
 
        element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
        for (i = 0; i < event_data->NumElements; i++, element++) {
@@ -4548,11 +4575,13 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
                switch (element->ReasonCode) {
                case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
                case MPI2_EVENT_IR_CHANGE_RC_ADDED:
-                       _scsih_sas_volume_add(ioc, element);
+                       if (!foreign_config)
+                               _scsih_sas_volume_add(ioc, element);
                        break;
                case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
                case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
-                       _scsih_sas_volume_delete(ioc, element);
+                       if (!foreign_config)
+                               _scsih_sas_volume_delete(ioc, element);
                        break;
                case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
                        _scsih_sas_pd_hide(ioc, element);
@@ -4671,6 +4700,9 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
        u32 state;
        struct _sas_device *sas_device;
        unsigned long flags;
+       Mpi2ConfigReply_t mpi_reply;
+       Mpi2SasDevicePage0_t sas_device_pg0;
+       u32 ioc_status;
 
        if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
                return;
@@ -4687,22 +4719,40 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
        spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
 
        switch (state) {
-#if 0
-       case MPI2_RAID_PD_STATE_OFFLINE:
-               if (sas_device)
-                       _scsih_remove_device(ioc, handle);
-               break;
-#endif
        case MPI2_RAID_PD_STATE_ONLINE:
        case MPI2_RAID_PD_STATE_DEGRADED:
        case MPI2_RAID_PD_STATE_REBUILDING:
        case MPI2_RAID_PD_STATE_OPTIMAL:
-               if (sas_device)
+               if (sas_device) {
                        sas_device->hidden_raid_component = 1;
-               else
-                       _scsih_add_device(ioc, handle, 0, 1);
+                       return;
+               }
+
+               if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
+                   &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
+                   handle))) {
+                       printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+                           ioc->name, __FILE__, __LINE__, __func__);
+                       return;
+               }
+
+               ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+                   MPI2_IOCSTATUS_MASK;
+               if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+                       printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+                           ioc->name, __FILE__, __LINE__, __func__);
+                       return;
+               }
+
+               _scsih_link_change(ioc,
+                   le16_to_cpu(sas_device_pg0.ParentDevHandle),
+                   handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
+
+               _scsih_add_device(ioc, handle, 0, 1);
+
                break;
 
+       case MPI2_RAID_PD_STATE_OFFLINE:
        case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
        case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
        case MPI2_RAID_PD_STATE_HOT_SPARE:
@@ -5774,6 +5824,7 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state)
        struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
        u32 device_state;
 
+       mpt2sas_base_stop_watchdog(ioc);
        flush_scheduled_work();
        scsi_block_requests(shost);
        device_state = pci_choose_state(pdev, state);
@@ -5816,6 +5867,7 @@ _scsih_resume(struct pci_dev *pdev)
 
        mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET);
        scsi_unblock_requests(shost);
+       mpt2sas_base_start_watchdog(ioc);
        return 0;
 }
 #endif /* CONFIG_PM */
index 650bcef08f2a4d080f5e325a7fd82766179aeb7b..cd78c501803a733759f768e049860f6acdd68f21 100644 (file)
@@ -9,7 +9,6 @@
 
 #include <linux/moduleparam.h>
 #include <linux/vmalloc.h>
-#include <linux/smp_lock.h>
 #include <linux/list.h>
 
 #include <scsi/scsi_tcq.h>
index fcc184cd066d505d09f12b61a6d16be30a9761b4..cbceb0ebabf7c41888ec091ab77f61e1c9b20f48 100644 (file)
@@ -15,19 +15,18 @@ void qla4xxx_dump_buffer(void *b, uint32_t size)
        uint32_t cnt;
        uint8_t *c = b;
 
-       printk(" 0   1   2   3   4   5   6   7   8   9  Ah  Bh  Ch  Dh  Eh  "
+       printk(" 0   1   2   3   4   5   6   7   8   9  Ah  Bh  Ch  Dh  Eh  "
               "Fh\n");
        printk("------------------------------------------------------------"
               "--\n");
-       for (cnt = 0; cnt < size; cnt++, c++) {
-               printk(KERN_DEBUG "%02x", *c);
-               if (!(cnt % 16))
-                       printk(KERN_DEBUG "\n");
+       for (cnt = 0; cnt < size; c++) {
+               printk(KERN_INFO "%02x", *c);
+               if (!(++cnt % 16))
+                       printk(KERN_INFO "\n");
 
                else
-                       printk(KERN_DEBUG "  ");
+                       printk(KERN_INFO "  ");
        }
-       if (cnt % 16)
-               printk(KERN_DEBUG "\n");
+       printk(KERN_INFO "\n");
 }
 
index b586f27c3bd4a32f0baa1e629eccbde2eb7ec32b..81b5f29254e296ba68db569df740021fba8113db 100644 (file)
 #define MAX_SRBS               MAX_CMDS_TO_RISC
 #define MBOX_AEN_REG_COUNT     5
 #define MAX_INIT_RETRIES       5
-#define IOCB_HIWAT_CUSHION     16
 
 /*
  * Buffer sizes
@@ -184,6 +183,11 @@ struct srb {
        uint16_t cc_stat;
        u_long r_start;         /* Time we recieve a cmd from OS */
        u_long u_start;         /* Time when we handed the cmd to F/W */
+
+       /* Used for extended sense / status continuation */
+       uint8_t *req_sense_ptr;
+       uint16_t req_sense_len;
+       uint16_t reserved2;
 };
 
 /*
@@ -302,7 +306,6 @@ struct scsi_qla_host {
        uint32_t tot_ddbs;
 
        uint16_t        iocb_cnt;
-       uint16_t        iocb_hiwat;
 
        /* SRB cache. */
 #define SRB_MIN_REQ    128
@@ -436,6 +439,8 @@ struct scsi_qla_host {
        /* Map ddb_list entry by FW ddb index */
        struct ddb_entry *fw_ddb_index_map[MAX_DDB_ENTRIES];
 
+       /* Saved srb for status continuation entry processing */
+       struct srb *status_srb;
 };
 
 static inline int is_qla4010(struct scsi_qla_host *ha)
index 1b667a70cffaac586c33f0781ad77569fc22e527..9cd7a608df389455c7ada50263c68a4ac090e2bc 100644 (file)
@@ -572,6 +572,7 @@ struct conn_event_log_entry {
  *************************************************************************/
 #define IOCB_MAX_CDB_LEN           16  /* Bytes in a CBD */
 #define IOCB_MAX_SENSEDATA_LEN     32  /* Bytes of sense data */
+#define IOCB_MAX_EXT_SENSEDATA_LEN  60  /* Bytes of extended sense data */
 
 /* IOCB header structure */
 struct qla4_header {
@@ -733,6 +734,12 @@ struct status_entry {
 
 };
 
+/* Status Continuation entry */
+struct status_cont_entry {
+       struct qla4_header hdr; /* 00-03 */
+       uint8_t ext_sense_data[IOCB_MAX_EXT_SENSEDATA_LEN]; /* 04-63 */
+};
+
 struct passthru0 {
        struct qla4_header hdr;                /* 00-03 */
        uint32_t handle;        /* 04-07 */
index 912a67494adff6928cc52f760d34b2da89149e6e..e0c32159749c5b61aa5d57abe1050212d0e6fc40 100644 (file)
 #include "ql4_dbg.h"
 #include "ql4_inline.h"
 
-
 #include <scsi/scsi_tcq.h>
 
+static int
+qla4xxx_space_in_req_ring(struct scsi_qla_host *ha, uint16_t req_cnt)
+{
+       uint16_t cnt;
+
+       /* Calculate number of free request entries. */
+       if ((req_cnt + 2) >= ha->req_q_count) {
+               cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out);
+               if (ha->request_in < cnt)
+                       ha->req_q_count = cnt - ha->request_in;
+               else
+                       ha->req_q_count = REQUEST_QUEUE_DEPTH -
+                                               (ha->request_in - cnt);
+       }
+
+       /* Check if room for request in request ring. */
+       if ((req_cnt + 2) < ha->req_q_count)
+               return 1;
+       else
+               return 0;
+}
+
+static void qla4xxx_advance_req_ring_ptr(struct scsi_qla_host *ha)
+{
+       /* Advance request queue pointer */
+       if (ha->request_in == (REQUEST_QUEUE_DEPTH - 1)) {
+               ha->request_in = 0;
+               ha->request_ptr = ha->request_ring;
+       } else {
+               ha->request_in++;
+               ha->request_ptr++;
+       }
+}
+
 /**
  * qla4xxx_get_req_pkt - returns a valid entry in request queue.
  * @ha: Pointer to host adapter structure.
 static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
                               struct queue_entry **queue_entry)
 {
-       uint16_t request_in;
-       uint8_t status = QLA_SUCCESS;
-
-       *queue_entry = ha->request_ptr;
+       uint16_t req_cnt = 1;
 
-       /* get the latest request_in and request_out index */
-       request_in = ha->request_in;
-       ha->request_out = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out);
-
-       /* Advance request queue pointer and check for queue full */
-       if (request_in == (REQUEST_QUEUE_DEPTH - 1)) {
-               request_in = 0;
-               ha->request_ptr = ha->request_ring;
-       } else {
-               request_in++;
-               ha->request_ptr++;
-       }
-
-       /* request queue is full, try again later */
-       if ((ha->iocb_cnt + 1) >= ha->iocb_hiwat) {
-               /* restore request pointer */
-               ha->request_ptr = *queue_entry;
-               status = QLA_ERROR;
-       } else {
-               ha->request_in = request_in;
+       if (qla4xxx_space_in_req_ring(ha, req_cnt)) {
+               *queue_entry = ha->request_ptr;
                memset(*queue_entry, 0, sizeof(**queue_entry));
+
+               qla4xxx_advance_req_ring_ptr(ha);
+               ha->req_q_count -= req_cnt;
+               return QLA_SUCCESS;
        }
 
-       return status;
+       return QLA_ERROR;
 }
 
 /**
@@ -100,21 +116,14 @@ exit_send_marker:
        return status;
 }
 
-static struct continuation_t1_entry* qla4xxx_alloc_cont_entry(
-       struct scsi_qla_host *ha)
+static struct continuation_t1_entry *
+qla4xxx_alloc_cont_entry(struct scsi_qla_host *ha)
 {
        struct continuation_t1_entry *cont_entry;
 
        cont_entry = (struct continuation_t1_entry *)ha->request_ptr;
 
-       /* Advance request queue pointer */
-       if (ha->request_in == (REQUEST_QUEUE_DEPTH - 1)) {
-               ha->request_in = 0;
-               ha->request_ptr = ha->request_ring;
-       } else {
-               ha->request_in++;
-               ha->request_ptr++;
-       }
+       qla4xxx_advance_req_ring_ptr(ha);
 
        /* Load packet defaults */
        cont_entry->hdr.entryType = ET_CONTINUE;
@@ -197,13 +206,10 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
        struct scsi_cmnd *cmd = srb->cmd;
        struct ddb_entry *ddb_entry;
        struct command_t3_entry *cmd_entry;
-
        int nseg;
        uint16_t tot_dsds;
        uint16_t req_cnt;
-
        unsigned long flags;
-       uint16_t cnt;
        uint32_t index;
        char tag[2];
 
@@ -217,6 +223,19 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
 
        index = (uint32_t)cmd->request->tag;
 
+       /*
+        * Check to see if adapter is online before placing request on
+        * request queue.  If a reset occurs and a request is in the queue,
+        * the firmware will still attempt to process the request, retrieving
+        * garbage for pointers.
+        */
+       if (!test_bit(AF_ONLINE, &ha->flags)) {
+               DEBUG2(printk("scsi%ld: %s: Adapter OFFLINE! "
+                             "Do not issue command.\n",
+                             ha->host_no, __func__));
+               goto queuing_error;
+       }
+
        /* Calculate the number of request entries needed. */
        nseg = scsi_dma_map(cmd);
        if (nseg < 0)
@@ -224,17 +243,7 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
        tot_dsds = nseg;
 
        req_cnt = qla4xxx_calc_request_entries(tot_dsds);
-
-       if (ha->req_q_count < (req_cnt + 2)) {
-               cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out);
-               if (ha->request_in < cnt)
-                       ha->req_q_count = cnt - ha->request_in;
-               else
-                       ha->req_q_count = REQUEST_QUEUE_DEPTH -
-                               (ha->request_in - cnt);
-       }
-
-       if (ha->req_q_count < (req_cnt + 2))
+       if (!qla4xxx_space_in_req_ring(ha, req_cnt))
                goto queuing_error;
 
        /* total iocbs active */
@@ -286,32 +295,10 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb)
                        break;
                }
 
-
-       /* Advance request queue pointer */
-       ha->request_in++;
-       if (ha->request_in == REQUEST_QUEUE_DEPTH) {
-               ha->request_in = 0;
-               ha->request_ptr = ha->request_ring;
-       } else
-               ha->request_ptr++;
-
-
+       qla4xxx_advance_req_ring_ptr(ha);
        qla4xxx_build_scsi_iocbs(srb, cmd_entry, tot_dsds);
        wmb();
 
-       /*
-        * Check to see if adapter is online before placing request on
-        * request queue.  If a reset occurs and a request is in the queue,
-        * the firmware will still attempt to process the request, retrieving
-        * garbage for pointers.
-        */
-       if (!test_bit(AF_ONLINE, &ha->flags)) {
-               DEBUG2(printk("scsi%ld: %s: Adapter OFFLINE! "
-                             "Do not issue command.\n",
-                             ha->host_no, __func__));
-               goto queuing_error;
-       }
-
        srb->cmd->host_scribble = (unsigned char *)srb;
 
        /* update counters */
index 799120fcb9be20a43901482781afd7dfbbd29884..8025ee16588e5a9f7104cf82fc80d4531fe01b70 100644 (file)
 #include "ql4_dbg.h"
 #include "ql4_inline.h"
 
+/**
+ * qla4xxx_copy_sense - copy sense data        into cmd sense buffer
+ * @ha: Pointer to host adapter structure.
+ * @sts_entry: Pointer to status entry structure.
+ * @srb: Pointer to srb structure.
+ **/
+static void qla4xxx_copy_sense(struct scsi_qla_host *ha,
+                               struct status_entry *sts_entry,
+                               struct srb *srb)
+{
+       struct scsi_cmnd *cmd = srb->cmd;
+       uint16_t sense_len;
+
+       memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+       sense_len = le16_to_cpu(sts_entry->senseDataByteCnt);
+       if (sense_len == 0)
+               return;
+
+       /* Save total available sense length,
+        * not to exceed cmd's sense buffer size */
+       sense_len = min_t(uint16_t, sense_len, SCSI_SENSE_BUFFERSIZE);
+       srb->req_sense_ptr = cmd->sense_buffer;
+       srb->req_sense_len = sense_len;
+
+       /* Copy sense from sts_entry pkt */
+       sense_len = min_t(uint16_t, sense_len, IOCB_MAX_SENSEDATA_LEN);
+       memcpy(cmd->sense_buffer, sts_entry->senseData, sense_len);
+
+       DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: %s: sense key = %x, "
+               "ASL= %02x, ASC/ASCQ = %02x/%02x\n", ha->host_no,
+               cmd->device->channel, cmd->device->id,
+               cmd->device->lun, __func__,
+               sts_entry->senseData[2] & 0x0f,
+               sts_entry->senseData[7],
+               sts_entry->senseData[12],
+               sts_entry->senseData[13]));
+
+       DEBUG5(qla4xxx_dump_buffer(cmd->sense_buffer, sense_len));
+       srb->flags |= SRB_GOT_SENSE;
+
+       /* Update srb, in case a sts_cont pkt follows */
+       srb->req_sense_ptr += sense_len;
+       srb->req_sense_len -= sense_len;
+       if (srb->req_sense_len != 0)
+               ha->status_srb = srb;
+       else
+               ha->status_srb = NULL;
+}
+
+/**
+ * qla4xxx_status_cont_entry - Process a Status Continuations entry.
+ * @ha: SCSI driver HA context
+ * @sts_cont: Entry pointer
+ *
+ * Extended sense data.
+ */
+static void
+qla4xxx_status_cont_entry(struct scsi_qla_host *ha,
+                         struct status_cont_entry *sts_cont)
+{
+       struct srb *srb = ha->status_srb;
+       struct scsi_cmnd *cmd;
+       uint8_t sense_len;
+
+       if (srb == NULL)
+               return;
+
+       cmd = srb->cmd;
+       if (cmd == NULL) {
+               DEBUG2(printk(KERN_INFO "scsi%ld: %s: Cmd already returned "
+                       "back to OS srb=%p srb->state:%d\n", ha->host_no,
+                       __func__, srb, srb->state));
+               ha->status_srb = NULL;
+               return;
+       }
+
+       /* Copy sense data. */
+       sense_len = min_t(uint16_t, srb->req_sense_len,
+                         IOCB_MAX_EXT_SENSEDATA_LEN);
+       memcpy(srb->req_sense_ptr, sts_cont->ext_sense_data, sense_len);
+       DEBUG5(qla4xxx_dump_buffer(srb->req_sense_ptr, sense_len));
+
+       srb->req_sense_ptr += sense_len;
+       srb->req_sense_len -= sense_len;
+
+       /* Place command on done queue. */
+       if (srb->req_sense_len == 0) {
+               qla4xxx_srb_compl(ha, srb);
+               ha->status_srb = NULL;
+       }
+}
+
 /**
  * qla4xxx_status_entry - processes status IOCBs
  * @ha: Pointer to host adapter structure.
@@ -23,7 +115,6 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
        struct srb *srb;
        struct ddb_entry *ddb_entry;
        uint32_t residual;
-       uint16_t sensebytecnt;
 
        srb = qla4xxx_del_from_active_array(ha, le32_to_cpu(sts_entry->handle));
        if (!srb) {
@@ -92,24 +183,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
                        break;
 
                /* Copy Sense Data into sense buffer. */
-               memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
-
-               sensebytecnt = le16_to_cpu(sts_entry->senseDataByteCnt);
-               if (sensebytecnt == 0)
-                       break;
-
-               memcpy(cmd->sense_buffer, sts_entry->senseData,
-                      min_t(uint16_t, sensebytecnt, SCSI_SENSE_BUFFERSIZE));
-
-               DEBUG2(printk("scsi%ld:%d:%d:%d: %s: sense key = %x, "
-                             "ASC/ASCQ = %02x/%02x\n", ha->host_no,
-                             cmd->device->channel, cmd->device->id,
-                             cmd->device->lun, __func__,
-                             sts_entry->senseData[2] & 0x0f,
-                             sts_entry->senseData[12],
-                             sts_entry->senseData[13]));
-
-               srb->flags |= SRB_GOT_SENSE;
+               qla4xxx_copy_sense(ha, sts_entry, srb);
                break;
 
        case SCS_INCOMPLETE:
@@ -176,23 +250,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
                                break;
 
                        /* Copy Sense Data into sense buffer. */
-                       memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
-
-                       sensebytecnt =
-                               le16_to_cpu(sts_entry->senseDataByteCnt);
-                       if (sensebytecnt == 0)
-                               break;
-
-                       memcpy(cmd->sense_buffer, sts_entry->senseData,
-                              min_t(uint16_t, sensebytecnt, SCSI_SENSE_BUFFERSIZE));
-
-                       DEBUG2(printk("scsi%ld:%d:%d:%d: %s: sense key = %x, "
-                                     "ASC/ASCQ = %02x/%02x\n", ha->host_no,
-                                     cmd->device->channel, cmd->device->id,
-                                     cmd->device->lun, __func__,
-                                     sts_entry->senseData[2] & 0x0f,
-                                     sts_entry->senseData[12],
-                                     sts_entry->senseData[13]));
+                       qla4xxx_copy_sense(ha, sts_entry, srb);
                } else {
                        /*
                         * If RISC reports underrun and target does not
@@ -268,9 +326,10 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha,
 
 status_entry_exit:
 
-       /* complete the request */
+       /* complete the request, if not waiting for status_continuation pkt */
        srb->cc_stat = sts_entry->completionStatus;
-       qla4xxx_srb_compl(ha, srb);
+       if (ha->status_srb == NULL)
+               qla4xxx_srb_compl(ha, srb);
 }
 
 /**
@@ -305,10 +364,7 @@ static void qla4xxx_process_response_queue(struct scsi_qla_host * ha)
                /* process entry */
                switch (sts_entry->hdr.entryType) {
                case ET_STATUS:
-                       /*
-                        * Common status - Single completion posted in single
-                        * IOSB.
-                        */
+                       /* Common status */
                        qla4xxx_status_entry(ha, sts_entry);
                        break;
 
@@ -316,9 +372,8 @@ static void qla4xxx_process_response_queue(struct scsi_qla_host * ha)
                        break;
 
                case ET_STATUS_CONTINUATION:
-                       /* Just throw away the status continuation entries */
-                       DEBUG2(printk("scsi%ld: %s: Status Continuation entry "
-                                     "- ignoring\n", ha->host_no, __func__));
+                       qla4xxx_status_cont_entry(ha,
+                               (struct status_cont_entry *) sts_entry);
                        break;
 
                case ET_COMMAND:
index 051b0f5e8c8e88cc53494ac9d1922af9e2150541..09d6d4b76f39536512b3578142b26a1a0f27bcf8 100644 (file)
@@ -385,16 +385,6 @@ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha)
                              mbox_sts[0]));
                return QLA_ERROR;
        }
-
-       /* High-water mark of IOCBs */
-       ha->iocb_hiwat = mbox_sts[2];
-       if (ha->iocb_hiwat > IOCB_HIWAT_CUSHION)
-               ha->iocb_hiwat -= IOCB_HIWAT_CUSHION;
-       else
-               dev_info(&ha->pdev->dev, "WARNING!!!  You have less than %d "
-                          "firmware IOCBs available (%d).\n",
-                          IOCB_HIWAT_CUSHION, ha->iocb_hiwat);
-
        return QLA_SUCCESS;
 }
 
index ec9da6ce8489ceedf36ab7efe8bd59c56cebfc45..40e3cafb3a9c54e44e813f738a01eec9c060498a 100644 (file)
@@ -66,6 +66,7 @@ static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess,
 static int qla4xxx_host_get_param(struct Scsi_Host *shost,
                                  enum iscsi_host_param param, char *buf);
 static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
+static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc);
 
 /*
  * SCSI host template entry points
@@ -89,6 +90,7 @@ static struct scsi_host_template qla4xxx_driver_template = {
        .eh_device_reset_handler = qla4xxx_eh_device_reset,
        .eh_target_reset_handler = qla4xxx_eh_target_reset,
        .eh_host_reset_handler  = qla4xxx_eh_host_reset,
+       .eh_timed_out           = qla4xxx_eh_cmd_timed_out,
 
        .slave_configure        = qla4xxx_slave_configure,
        .slave_alloc            = qla4xxx_slave_alloc,
@@ -124,6 +126,21 @@ static struct iscsi_transport qla4xxx_iscsi_transport = {
 
 static struct scsi_transport_template *qla4xxx_scsi_transport;
 
+static enum blk_eh_timer_return qla4xxx_eh_cmd_timed_out(struct scsi_cmnd *sc)
+{
+       struct iscsi_cls_session *session;
+       struct ddb_entry *ddb_entry;
+
+       session = starget_to_session(scsi_target(sc->device));
+       ddb_entry = session->dd_data;
+
+       /* if we are not logged in then the LLD is going to clean up the cmd */
+       if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)
+               return BLK_EH_RESET_TIMER;
+       else
+               return BLK_EH_NOT_HANDLED;
+}
+
 static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session)
 {
        struct ddb_entry *ddb_entry = session->dd_data;
@@ -904,18 +921,17 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha,
        /* Flush any pending ddb changed AENs */
        qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
 
+       qla4xxx_flush_active_srbs(ha);
+
        /* Reset the firmware.  If successful, function
         * returns with ISP interrupts enabled.
         */
-       if (status == QLA_SUCCESS) {
-               DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n",
-                             ha->host_no, __func__));
-               qla4xxx_flush_active_srbs(ha);
-               if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS)
-                       status = qla4xxx_soft_reset(ha);
-               else
-                       status = QLA_ERROR;
-       }
+       DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n",
+                     ha->host_no, __func__));
+       if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS)
+               status = qla4xxx_soft_reset(ha);
+       else
+               status = QLA_ERROR;
 
        /* Flush any pending ddb changed AENs */
        qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
@@ -1527,11 +1543,9 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
 {
        struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
        struct ddb_entry *ddb_entry = cmd->device->hostdata;
-       struct srb *sp;
        int ret = FAILED, stat;
 
-       sp = (struct srb *) cmd->SCp.ptr;
-       if (!sp || !ddb_entry)
+       if (!ddb_entry)
                return ret;
 
        dev_info(&ha->pdev->dev,
@@ -1644,7 +1658,7 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd)
        ha = (struct scsi_qla_host *) cmd->device->host->hostdata;
 
        dev_info(&ha->pdev->dev,
-                  "scsi(%ld:%d:%d:%d): ADAPTER RESET ISSUED.\n", ha->host_no,
+                  "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no,
                   cmd->device->channel, cmd->device->id, cmd->device->lun);
 
        if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) {
index ab984cb89cea53f14ee4c0cf6ab34dce1c48b82f..6980cb279c81cead66de9339bfb4f5fe4c23a289 100644 (file)
@@ -5,5 +5,5 @@
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
 
-#define QLA4XXX_DRIVER_VERSION "5.01.00-k8"
+#define QLA4XXX_DRIVER_VERSION "5.01.00-k9"
 
index 2eee9e6e4fe8f975eb580329cd4814244b482a0b..292c02f810d04a4bc7d66f27a77209a302fe5e14 100644 (file)
@@ -3670,13 +3670,14 @@ static void
 fc_bsg_goose_queue(struct fc_rport *rport)
 {
        int flagset;
+       unsigned long flags;
 
        if (!rport->rqst_q)
                return;
 
        get_device(&rport->dev);
 
-       spin_lock(rport->rqst_q->queue_lock);
+       spin_lock_irqsave(rport->rqst_q->queue_lock, flags);
        flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) &&
                  !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags);
        if (flagset)
@@ -3684,7 +3685,7 @@ fc_bsg_goose_queue(struct fc_rport *rport)
        __blk_run_queue(rport->rqst_q);
        if (flagset)
                queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q);
-       spin_unlock(rport->rqst_q->queue_lock);
+       spin_unlock_irqrestore(rport->rqst_q->queue_lock, flags);
 
        put_device(&rport->dev);
 }
index 783e33c65eb7c354a5e6613f2653c0b95517f51c..b47240ca4b19ad81f3ff72fbd0a15781c50ed5c8 100644 (file)
@@ -990,7 +990,7 @@ int iscsi_offload_mesg(struct Scsi_Host *shost,
        struct iscsi_uevent *ev;
        int len = NLMSG_SPACE(sizeof(*ev) + data_size);
 
-       skb = alloc_skb(len, GFP_NOIO);
+       skb = alloc_skb(len, GFP_ATOMIC);
        if (!skb) {
                printk(KERN_ERR "can not deliver iscsi offload message:OOM\n");
                return -ENOMEM;
@@ -1012,7 +1012,7 @@ int iscsi_offload_mesg(struct Scsi_Host *shost,
 
        memcpy((char *)ev + sizeof(*ev), data, data_size);
 
-       return iscsi_multicast_skb(skb, ISCSI_NL_GRP_UIP, GFP_NOIO);
+       return iscsi_multicast_skb(skb, ISCSI_NL_GRP_UIP, GFP_ATOMIC);
 }
 EXPORT_SYMBOL_GPL(iscsi_offload_mesg);
 
index 5616cd780ff3504420363d0c42b24af0274218c6..b7b9fec67a98fc4f130bf2a1e0c51a2d0c66c445 100644 (file)
@@ -1840,6 +1840,18 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
        kfree(buffer);
 }
 
+static int sd_try_extended_inquiry(struct scsi_device *sdp)
+{
+       /*
+        * Although VPD inquiries can go to SCSI-2 type devices,
+        * some USB ones crash on receiving them, and the pages
+        * we currently ask for are for SPC-3 and beyond
+        */
+       if (sdp->scsi_level > SCSI_SPC_2)
+               return 1;
+       return 0;
+}
+
 /**
  *     sd_revalidate_disk - called the first time a new disk is seen,
  *     performs disk spin up, read_capacity, etc.
@@ -1877,8 +1889,12 @@ static int sd_revalidate_disk(struct gendisk *disk)
         */
        if (sdkp->media_present) {
                sd_read_capacity(sdkp, buffer);
-               sd_read_block_limits(sdkp);
-               sd_read_block_characteristics(sdkp);
+
+               if (sd_try_extended_inquiry(sdp)) {
+                       sd_read_block_limits(sdkp);
+                       sd_read_block_characteristics(sdkp);
+               }
+
                sd_read_write_protect_flag(sdkp, buffer);
                sd_read_cache_type(sdkp, buffer);
                sd_read_app_tag_own(sdkp, buffer);
index 8201387b4daa29c374cc850107f8b3d6d21ae0dd..9230402c45afcbe0c1a06188b83c99a3f39a104b 100644 (file)
@@ -210,13 +210,11 @@ static void sg_put_dev(Sg_device *sdp);
 static int sg_allow_access(struct file *filp, unsigned char *cmd)
 {
        struct sg_fd *sfp = (struct sg_fd *)filp->private_data;
-       struct request_queue *q = sfp->parentdp->device->request_queue;
 
        if (sfp->parentdp->device->type == TYPE_SCANNER)
                return 0;
 
-       return blk_verify_command(&q->cmd_filter,
-                                 cmd, filp->f_mode & FMODE_WRITE);
+       return blk_verify_command(cmd, filp->f_mode & FMODE_WRITE);
 }
 
 static int
@@ -621,7 +619,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
                if (strcmp(current->comm, cmd) && printk_ratelimit()) {
                        printk(KERN_WARNING
                               "sg_write: data in/out %d/%d bytes for SCSI command 0x%x--"
-                              "guessing data in;\n" KERN_WARNING "   "
+                              "guessing data in;\n   "
                               "program %s not setting count and/or reply_len properly\n",
                               old_hdr.reply_len - (int)SZ_SG_HEADER,
                               input_size, (unsigned int) cmnd[0],
@@ -1658,6 +1656,10 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd)
                md->nr_entries = req_schp->k_use_sg;
                md->offset = 0;
                md->null_mapped = hp->dxferp ? 0 : 1;
+               if (dxfer_dir == SG_DXFER_TO_FROM_DEV)
+                       md->from_user = 1;
+               else
+                       md->from_user = 0;
        }
 
        if (iov_count) {
index bcaba86060abe0787936bff42143776ec81a712e..75da6e58ce550ecd03031cb05ee4d8a8b9290ba1 100644 (file)
@@ -2860,8 +2860,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd)
  */
 
     local_irq_restore(flags);
-    printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n"
-           KERN_INFO "        before abortion\n", HOSTNO); 
+    printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully before abortion\n", HOSTNO); 
 
     return SCSI_ABORT_NOT_RUNNING;
 }
index 97f3158fa7b546700ab670f3373598c5895cb546..27e84e4b1fa98857d571f3abafdfe9f4b03cf7ad 100644 (file)
@@ -134,7 +134,7 @@ zalon_probe(struct parisc_device *dev)
 
        host = ncr_attach(&zalon7xx_template, unit, &device);
        if (!host)
-               goto fail;
+               return -ENODEV;
 
        if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) {
          dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ",
index a07015d646ddad5eb6743c5fa1e1bb281694d051..e7108e75653da8a75326d420133b1e471a68c655 100644 (file)
@@ -60,11 +60,12 @@ struct serial_private {
 
 static void moan_device(const char *str, struct pci_dev *dev)
 {
-       printk(KERN_WARNING "%s: %s\n"
-              KERN_WARNING "Please send the output of lspci -vv, this\n"
-              KERN_WARNING "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
-              KERN_WARNING "manufacturer and name of serial board or\n"
-              KERN_WARNING "modem board to rmk+serial@arm.linux.org.uk.\n",
+       printk(KERN_WARNING
+              "%s: %s\n"
+              "Please send the output of lspci -vv, this\n"
+              "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
+              "manufacturer and name of serial board or\n"
+              "modem board to rmk+serial@arm.linux.org.uk.\n",
               pci_name(dev), str, dev->vendor, dev->device,
               dev->subsystem_vendor, dev->subsystem_device);
 }
@@ -759,6 +760,8 @@ static int pci_netmos_init(struct pci_dev *dev)
        /* subdevice 0x00PS means <P> parallel, <S> serial */
        unsigned int num_serial = dev->subsystem_device & 0xf;
 
+       if (dev->device == PCI_DEVICE_ID_NETMOS_9901)
+               return 0;
        if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
                        dev->subsystem_device == 0x0299)
                return 0;
@@ -3557,6 +3560,10 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_VENDOR_ID_IBM, 0x0299,
                0, 0, pbn_b0_bt_2_115200 },
 
+       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
+               0xA000, 0x1000,
+               0, 0, pbn_b0_1_115200 },
+
        /*
         * These entries match devices with class COMMUNICATION_SERIAL,
         * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
index 037c1e0b7c4c5bd137c0720ccaa3210716c09435..6553833c12db1e45f427cb65fe7d95e396310a6d 100644 (file)
@@ -527,7 +527,7 @@ config SERIAL_S3C24A0
 
 config SERIAL_S3C6400
        tristate "Samsung S3C6400/S3C6410 Serial port support"
-       depends on SERIAL_SAMSUNG && (CPU_S3C600 || CPU_S3C6410)
+       depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410)
        default y
        help
          Serial port support for the Samsung S3C6400 and S3C6410
index 338b15c0a548e9f2d6d630d1ea3eb52954abff0a..607d43a31048d8a7f7c5c479d85c80848d0b2e3a 100644 (file)
@@ -1551,6 +1551,7 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
        if (ret)
                goto err_add_port;
 
+#ifdef CONFIG_SERIAL_ATMEL_CONSOLE
        if (atmel_is_console_port(&port->uart)
                        && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) {
                /*
@@ -1559,6 +1560,7 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
                 */
                clk_disable(port->clk);
        }
+#endif
 
        device_init_wakeup(&pdev->dev, 1);
        platform_set_drvdata(pdev, port);
index 34b4ae0fe76041f4eda4132e1a81a54784652557..c108b1a0ce988de4fd91d905d7b26fc205c00e7d 100644 (file)
@@ -236,7 +236,6 @@ static int sport_startup(struct uart_port *port)
        int retval;
 
        pr_debug("%s enter\n", __func__);
-       memset(buffer, 20, '\0');
        snprintf(buffer, 20, "%s rx", up->name);
        retval = request_irq(up->rx_irq, sport_uart_rx_irq, IRQF_SAMPLE_RANDOM, buffer, up);
        if (retval) {
index 141c0a3333ad3c8ac8140b5c52b5588a21daf6b2..a9802e76b5fabbd91f44adedb16708fda49f289b 100644 (file)
@@ -132,7 +132,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
        memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
            L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
        if (is_con) {
-               mem_addr = alloc_bootmem(memsz);
+               mem_addr = kzalloc(memsz, GFP_NOWAIT);
                dma_addr = virt_to_bus(mem_addr);
        }
        else
index 698048f64f5e9aa0ef49d51578460978815b1dc6..f7c24baa141673a03084e3951b80d345c205d3c6 100644 (file)
@@ -730,7 +730,6 @@ static int __devexit msm_serial_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver msm_platform_driver = {
-       .probe = msm_serial_probe,
        .remove = msm_serial_remove,
        .driver = {
                .name = "msm_serial",
index fb00ed5296e6f5bb6aa42ddb5d366cd1088afe90..fed1a9a1ffb4e7db9aedae7ff0b498ed933e27f7 100644 (file)
@@ -76,7 +76,7 @@ static int s3c2400_serial_probe(struct platform_device *dev)
        return s3c24xx_serial_probe(dev, &s3c2400_uart_inf);
 }
 
-static struct platform_driver s3c2400_serial_drv = {
+static struct platform_driver s3c2400_serial_driver = {
        .probe          = s3c2400_serial_probe,
        .remove         = __devexit_p(s3c24xx_serial_remove),
        .driver         = {
@@ -85,16 +85,16 @@ static struct platform_driver s3c2400_serial_drv = {
        },
 };
 
-s3c24xx_console_init(&s3c2400_serial_drv, &s3c2400_uart_inf);
+s3c24xx_console_init(&s3c2400_serial_driver, &s3c2400_uart_inf);
 
 static inline int s3c2400_serial_init(void)
 {
-       return s3c24xx_serial_init(&s3c2400_serial_drv, &s3c2400_uart_inf);
+       return s3c24xx_serial_init(&s3c2400_serial_driver, &s3c2400_uart_inf);
 }
 
 static inline void s3c2400_serial_exit(void)
 {
-       platform_driver_unregister(&s3c2400_serial_drv);
+       platform_driver_unregister(&s3c2400_serial_driver);
 }
 
 module_init(s3c2400_serial_init);
index b5d7cbcba2ae23b6c171ccdbe5ef664d71f12b6f..c99f0821cae32d06cea9e387e795cca1ebdecbd0 100644 (file)
@@ -88,7 +88,7 @@ static int s3c2410_serial_probe(struct platform_device *dev)
        return s3c24xx_serial_probe(dev, &s3c2410_uart_inf);
 }
 
-static struct platform_driver s3c2410_serial_drv = {
+static struct platform_driver s3c2410_serial_driver = {
        .probe          = s3c2410_serial_probe,
        .remove         = __devexit_p(s3c24xx_serial_remove),
        .driver         = {
@@ -97,16 +97,16 @@ static struct platform_driver s3c2410_serial_drv = {
        },
 };
 
-s3c24xx_console_init(&s3c2410_serial_drv, &s3c2410_uart_inf);
+s3c24xx_console_init(&s3c2410_serial_driver, &s3c2410_uart_inf);
 
 static int __init s3c2410_serial_init(void)
 {
-       return s3c24xx_serial_init(&s3c2410_serial_drv, &s3c2410_uart_inf);
+       return s3c24xx_serial_init(&s3c2410_serial_driver, &s3c2410_uart_inf);
 }
 
 static void __exit s3c2410_serial_exit(void)
 {
-       platform_driver_unregister(&s3c2410_serial_drv);
+       platform_driver_unregister(&s3c2410_serial_driver);
 }
 
 module_init(s3c2410_serial_init);
index 11dcb90bdfefaa8fa5f6d391f01c8ba0298465e7..6e057d8809d3dbbe2095dfebeb335195f7ad5719 100644 (file)
@@ -121,7 +121,7 @@ static int s3c2412_serial_probe(struct platform_device *dev)
        return s3c24xx_serial_probe(dev, &s3c2412_uart_inf);
 }
 
-static struct platform_driver s3c2412_serial_drv = {
+static struct platform_driver s3c2412_serial_driver = {
        .probe          = s3c2412_serial_probe,
        .remove         = __devexit_p(s3c24xx_serial_remove),
        .driver         = {
@@ -130,16 +130,16 @@ static struct platform_driver s3c2412_serial_drv = {
        },
 };
 
-s3c24xx_console_init(&s3c2412_serial_drv, &s3c2412_uart_inf);
+s3c24xx_console_init(&s3c2412_serial_driver, &s3c2412_uart_inf);
 
 static inline int s3c2412_serial_init(void)
 {
-       return s3c24xx_serial_init(&s3c2412_serial_drv, &s3c2412_uart_inf);
+       return s3c24xx_serial_init(&s3c2412_serial_driver, &s3c2412_uart_inf);
 }
 
 static inline void s3c2412_serial_exit(void)
 {
-       platform_driver_unregister(&s3c2412_serial_drv);
+       platform_driver_unregister(&s3c2412_serial_driver);
 }
 
 module_init(s3c2412_serial_init);
index 06c5b0cc47a3c23b991e31bbd694bcc9d1277ba3..69ff5d340f044ac9735f525c772041e8680eade2 100644 (file)
@@ -151,7 +151,7 @@ static int s3c2440_serial_probe(struct platform_device *dev)
        return s3c24xx_serial_probe(dev, &s3c2440_uart_inf);
 }
 
-static struct platform_driver s3c2440_serial_drv = {
+static struct platform_driver s3c2440_serial_driver = {
        .probe          = s3c2440_serial_probe,
        .remove         = __devexit_p(s3c24xx_serial_remove),
        .driver         = {
@@ -160,16 +160,16 @@ static struct platform_driver s3c2440_serial_drv = {
        },
 };
 
-s3c24xx_console_init(&s3c2440_serial_drv, &s3c2440_uart_inf);
+s3c24xx_console_init(&s3c2440_serial_driver, &s3c2440_uart_inf);
 
 static int __init s3c2440_serial_init(void)
 {
-       return s3c24xx_serial_init(&s3c2440_serial_drv, &s3c2440_uart_inf);
+       return s3c24xx_serial_init(&s3c2440_serial_driver, &s3c2440_uart_inf);
 }
 
 static void __exit s3c2440_serial_exit(void)
 {
-       platform_driver_unregister(&s3c2440_serial_drv);
+       platform_driver_unregister(&s3c2440_serial_driver);
 }
 
 module_init(s3c2440_serial_init);
index 786a067d62aceed1710c5e5a5884d10803951d31..26c49e18bdd123034ebdc771a918791632c33341 100644 (file)
@@ -92,7 +92,7 @@ static int s3c24a0_serial_probe(struct platform_device *dev)
        return s3c24xx_serial_probe(dev, &s3c24a0_uart_inf);
 }
 
-static struct platform_driver s3c24a0_serial_drv = {
+static struct platform_driver s3c24a0_serial_driver = {
        .probe          = s3c24a0_serial_probe,
        .remove         = __devexit_p(s3c24xx_serial_remove),
        .driver         = {
@@ -101,16 +101,16 @@ static struct platform_driver s3c24a0_serial_drv = {
        },
 };
 
-s3c24xx_console_init(&s3c24a0_serial_drv, &s3c24a0_uart_inf);
+s3c24xx_console_init(&s3c24a0_serial_driver, &s3c24a0_uart_inf);
 
 static int __init s3c24a0_serial_init(void)
 {
-       return s3c24xx_serial_init(&s3c24a0_serial_drv, &s3c24a0_uart_inf);
+       return s3c24xx_serial_init(&s3c24a0_serial_driver, &s3c24a0_uart_inf);
 }
 
 static void __exit s3c24a0_serial_exit(void)
 {
-       platform_driver_unregister(&s3c24a0_serial_drv);
+       platform_driver_unregister(&s3c24a0_serial_driver);
 }
 
 module_init(s3c24a0_serial_init);
index 48f1a3781f0de5f3af388665c4b3575d9fdadcc5..4be92ab50058284f0cf823bf4ed4ab10b5c80be9 100644 (file)
@@ -122,7 +122,7 @@ static int s3c6400_serial_probe(struct platform_device *dev)
        return s3c24xx_serial_probe(dev, &s3c6400_uart_inf);
 }
 
-static struct platform_driver s3c6400_serial_drv = {
+static struct platform_driver s3c6400_serial_driver = {
        .probe          = s3c6400_serial_probe,
        .remove         = __devexit_p(s3c24xx_serial_remove),
        .driver         = {
@@ -131,16 +131,16 @@ static struct platform_driver s3c6400_serial_drv = {
        },
 };
 
-s3c24xx_console_init(&s3c6400_serial_drv, &s3c6400_uart_inf);
+s3c24xx_console_init(&s3c6400_serial_driver, &s3c6400_uart_inf);
 
 static int __init s3c6400_serial_init(void)
 {
-       return s3c24xx_serial_init(&s3c6400_serial_drv, &s3c6400_uart_inf);
+       return s3c24xx_serial_init(&s3c6400_serial_driver, &s3c6400_uart_inf);
 }
 
 static void __exit s3c6400_serial_exit(void)
 {
-       platform_driver_unregister(&s3c6400_serial_drv);
+       platform_driver_unregister(&s3c6400_serial_driver);
 }
 
 module_init(s3c6400_serial_init);
index 998e89dc5aaf2db56eda9f18c1060ea8c9189555..e0665630e4dada82de5e3e816beaf0cb2c637b7c 100644 (file)
@@ -549,7 +549,7 @@ static struct uart_port ks8695uart_ports[SERIAL_KS8695_NR] = {
                .mapbase        = KS8695_UART_VA,
                .iotype         = SERIAL_IO_MEM,
                .irq            = KS8695_IRQ_UART_TX,
-               .uartclk        = CLOCK_TICK_RATE * 16,
+               .uartclk        = KS8695_CLOCK_RATE * 16,
                .fifosize       = 16,
                .ops            = &ks8695uart_pops,
                .flags          = ASYNC_BOOT_AUTOCONF,
index 66f52674ca0cb6872cfd580571b29d485dd59a44..8e2feb563347151d220ed23155074dc5e0f0c761 100644 (file)
@@ -707,24 +707,25 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr)
 
 static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
 {
-       unsigned short ssr_status, scr_status;
+       unsigned short ssr_status, scr_status, err_enabled;
        struct uart_port *port = ptr;
        irqreturn_t ret = IRQ_NONE;
 
        ssr_status = sci_in(port, SCxSR);
        scr_status = sci_in(port, SCSCR);
+       err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE);
 
        /* Tx Interrupt */
-       if ((ssr_status & 0x0020) && (scr_status & SCI_CTRL_FLAGS_TIE))
+       if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCI_CTRL_FLAGS_TIE))
                ret = sci_tx_interrupt(irq, ptr);
        /* Rx Interrupt */
-       if ((ssr_status & 0x0002) && (scr_status & SCI_CTRL_FLAGS_RIE))
+       if ((ssr_status & SCxSR_RDxF(port)) && (scr_status & SCI_CTRL_FLAGS_RIE))
                ret = sci_rx_interrupt(irq, ptr);
        /* Error Interrupt */
-       if ((ssr_status & 0x0080) && (scr_status & SCI_CTRL_FLAGS_REIE))
+       if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled)
                ret = sci_er_interrupt(irq, ptr);
        /* Break Interrupt */
-       if ((ssr_status & 0x0010) && (scr_status & SCI_CTRL_FLAGS_REIE))
+       if ((ssr_status & SCxSR_BRK(port)) && err_enabled)
                ret = sci_br_interrupt(irq, ptr);
 
        return ret;
index 0573f3b5175e463f1675e4d4bdd5b0dceb17c47c..dac550e57c29c192e60ec351f191adad98e2f4da 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Driver for NEC VR4100 series Serial Interface Unit.
  *
- *  Copyright (C) 2004-2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2004-2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  Based on drivers/serial/8250.c, by Russell King.
  *
index eee4b6e0af2ccaa6ce592217ee11287a6c5aab41..9b80ad36dbbad224c28d89475d0f91e8794d826b 100644 (file)
@@ -59,6 +59,8 @@
 
 /* per-register bitmasks: */
 
+#define OMAP2_MCSPI_SYSCONFIG_SMARTIDLE        (2 << 3)
+#define OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP        (1 << 2)
 #define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE (1 << 0)
 #define OMAP2_MCSPI_SYSCONFIG_SOFTRESET        (1 << 1)
 
@@ -90,6 +92,7 @@
 
 #define OMAP2_MCSPI_CHCTRL_EN          (1 << 0)
 
+#define OMAP2_MCSPI_WAKEUPENABLE_WKEN  (1 << 0)
 
 /* We have 2 DMA channels per CS, one for RX and one for TX */
 struct omap2_mcspi_dma {
@@ -269,7 +272,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
 
        if (rx != NULL) {
                omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel,
-                               data_type, element_count, 1,
+                               data_type, element_count - 1, 1,
                                OMAP_DMA_SYNC_ELEMENT,
                                mcspi_dma->dma_rx_sync_dev, 1);
 
@@ -300,6 +303,25 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
        if (rx != NULL) {
                wait_for_completion(&mcspi_dma->dma_rx_completion);
                dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE);
+               omap2_mcspi_set_enable(spi, 0);
+               if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
+                               & OMAP2_MCSPI_CHSTAT_RXS)) {
+                       u32 w;
+
+                       w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0);
+                       if (word_len <= 8)
+                               ((u8 *)xfer->rx_buf)[element_count - 1] = w;
+                       else if (word_len <= 16)
+                               ((u16 *)xfer->rx_buf)[element_count - 1] = w;
+                       else /* word_len <= 32 */
+                               ((u32 *)xfer->rx_buf)[element_count - 1] = w;
+               } else {
+                       dev_err(&spi->dev, "DMA RX last word empty");
+                       count -= (word_len <= 8)  ? 1 :
+                                (word_len <= 16) ? 2 :
+                              /* word_len <= 32 */ 4;
+               }
+               omap2_mcspi_set_enable(spi, 1);
        }
        return count;
 }
@@ -873,8 +895,12 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
        } while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE));
 
        mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
-                       /* (3 << 8) | (2 << 3) | */
-                       OMAP2_MCSPI_SYSCONFIG_AUTOIDLE);
+                       OMAP2_MCSPI_SYSCONFIG_AUTOIDLE |
+                       OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP |
+                       OMAP2_MCSPI_SYSCONFIG_SMARTIDLE);
+
+       mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE,
+                       OMAP2_MCSPI_WAKEUPENABLE_WKEN);
 
        omap2_mcspi_set_master_mode(master);
 
index aa90ddb370662b7d13b787febb0fa8f569b3bad0..8980a5640bd9d16021367720b77690d783dfac3b 100644 (file)
@@ -514,6 +514,8 @@ static int __init uwire_probe(struct platform_device *pdev)
        /* the spi->mode bits understood by this driver: */
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
+       master->flags = SPI_MASTER_HALF_DUPLEX;
+
        master->bus_num = 2;    /* "official" */
        master->num_chipselect = 4;
        master->setup = uwire_setup;
index 2a5abc08e8571d49143aa9287785aed1201156aa..f1db395dd88981ca4bf7f2e8777c8e9f2c6cceee 100644 (file)
@@ -258,6 +258,11 @@ static void bitbang_work(struct work_struct *work)
        struct spi_bitbang      *bitbang =
                container_of(work, struct spi_bitbang, work);
        unsigned long           flags;
+       int                     do_setup = -1;
+       int                     (*setup_transfer)(struct spi_device *,
+                                       struct spi_transfer *);
+
+       setup_transfer = bitbang->setup_transfer;
 
        spin_lock_irqsave(&bitbang->lock, flags);
        bitbang->busy = 1;
@@ -269,8 +274,6 @@ static void bitbang_work(struct work_struct *work)
                unsigned                tmp;
                unsigned                cs_change;
                int                     status;
-               int                     (*setup_transfer)(struct spi_device *,
-                                               struct spi_transfer *);
 
                m = container_of(bitbang->queue.next, struct spi_message,
                                queue);
@@ -287,19 +290,19 @@ static void bitbang_work(struct work_struct *work)
                tmp = 0;
                cs_change = 1;
                status = 0;
-               setup_transfer = NULL;
 
                list_for_each_entry (t, &m->transfers, transfer_list) {
 
-                       /* override or restore speed and wordsize */
-                       if (t->speed_hz || t->bits_per_word) {
-                               setup_transfer = bitbang->setup_transfer;
+                       /* override speed or wordsize? */
+                       if (t->speed_hz || t->bits_per_word)
+                               do_setup = 1;
+
+                       /* init (-1) or override (1) transfer params */
+                       if (do_setup != 0) {
                                if (!setup_transfer) {
                                        status = -ENOPROTOOPT;
                                        break;
                                }
-                       }
-                       if (setup_transfer) {
                                status = setup_transfer(spi, t);
                                if (status < 0)
                                        break;
@@ -363,9 +366,10 @@ static void bitbang_work(struct work_struct *work)
                m->status = status;
                m->complete(m->context);
 
-               /* restore speed and wordsize */
-               if (setup_transfer)
+               /* restore speed and wordsize if it was overridden */
+               if (do_setup == 1)
                        setup_transfer(spi, NULL);
+               do_setup = 0;
 
                /* normally deactivate chipselect ... unless no error and
                 * cs_change has hinted that the next message will probably
index e0d44af4745ad946e0c8aab75dce100610938acd..3f3119d760db71fc653b75e77615ce8069b7c300 100644 (file)
@@ -111,29 +111,32 @@ static int s3c24xx_spi_setupxfer(struct spi_device *spi,
        unsigned int bpw;
        unsigned int hz;
        unsigned int div;
+       unsigned long clk;
 
        bpw = t ? t->bits_per_word : spi->bits_per_word;
        hz  = t ? t->speed_hz : spi->max_speed_hz;
 
+       if (!bpw)
+               bpw = 8;
+
+       if (!hz)
+               hz = spi->max_speed_hz;
+
        if (bpw != 8) {
                dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
                return -EINVAL;
        }
 
-       div = clk_get_rate(hw->clk) / hz;
-
-       /* is clk = pclk / (2 * (pre+1)), or is it
-        *    clk = (pclk * 2) / ( pre + 1) */
-
-       div /= 2;
-
-       if (div > 0)
-               div -= 1;
+       clk = clk_get_rate(hw->clk);
+       div = DIV_ROUND_UP(clk, hz * 2) - 1;
 
        if (div > 255)
                div = 255;
 
-       dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", div, hz);
+       dev_dbg(&spi->dev, "setting pre-scaler to %d (wanted %d, got %ld)\n",
+               div, hz, clk / (2 * (div + 1)));
+
+
        writeb(div, hw->regs + S3C2410_SPPRE);
 
        spin_lock(&hw->bitbang.lock);
index 5d869c4d3eb2a2e3dd9f46ae3ebf1cfbd333e61f..606e7a40a8da85d415b7d69efe65664528b681bd 100644 (file)
@@ -58,15 +58,20 @@ static unsigned long        minors[N_SPI_MINORS / BITS_PER_LONG];
 
 
 /* Bit masks for spi_device.mode management.  Note that incorrect
- * settings for CS_HIGH and 3WIRE can cause *lots* of trouble for other
- * devices on a shared bus:  CS_HIGH, because this device will be
- * active when it shouldn't be;  3WIRE, because when active it won't
- * behave as it should.
+ * settings for some settings can cause *lots* of trouble for other
+ * devices on a shared bus:
  *
- * REVISIT should changing those two modes be privileged?
+ *  - CS_HIGH ... this device will be active when it shouldn't be
+ *  - 3WIRE ... when active, it won't behave as it should
+ *  - NO_CS ... there will be no explicit message boundaries; this
+ *     is completely incompatible with the shared bus model
+ *  - READY ... transfers may proceed when they shouldn't.
+ *
+ * REVISIT should changing those flags be privileged?
  */
 #define SPI_MODE_MASK          (SPI_CPHA | SPI_CPOL | SPI_CS_HIGH \
-                               | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP)
+                               | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP \
+                               | SPI_NO_CS | SPI_READY)
 
 struct spidev_data {
        dev_t                   devt;
index 3fd3e3b412b6598d0c32a70bc691ced97769a596..3c6feed46f6ea48b12d3083e1d95f1c33921029e 100644 (file)
@@ -49,29 +49,54 @@ static const u32 ipsflag_irq_shift[] = {
 
 static inline u32 ssb_irqflag(struct ssb_device *dev)
 {
-       return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
+       u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
+       if (tpsflag)
+               return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
+       else
+               /* not irq supported */
+               return 0x3f;
+}
+
+static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag)
+{
+       struct ssb_bus *bus = rdev->bus;
+       int i;
+       for (i = 0; i < bus->nr_devices; i++) {
+               struct ssb_device *dev;
+               dev = &(bus->devices[i]);
+               if (ssb_irqflag(dev) == irqflag)
+                       return dev;
+       }
+       return NULL;
 }
 
 /* Get the MIPS IRQ assignment for a specified device.
  * If unassigned, 0 is returned.
+ * If disabled, 5 is returned.
+ * If not supported, 6 is returned.
  */
 unsigned int ssb_mips_irq(struct ssb_device *dev)
 {
        struct ssb_bus *bus = dev->bus;
+       struct ssb_device *mdev = bus->mipscore.dev;
        u32 irqflag;
        u32 ipsflag;
        u32 tmp;
        unsigned int irq;
 
        irqflag = ssb_irqflag(dev);
+       if (irqflag == 0x3f)
+               return 6;
        ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG);
        for (irq = 1; irq <= 4; irq++) {
                tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]);
                if (tmp == irqflag)
                        break;
        }
-       if (irq == 5)
-               irq = 0;
+       if (irq == 5) {
+               if ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))
+                       irq = 0;
+       }
 
        return irq;
 }
@@ -97,25 +122,56 @@ static void set_irq(struct ssb_device *dev, unsigned int irq)
        struct ssb_device *mdev = bus->mipscore.dev;
        u32 irqflag = ssb_irqflag(dev);
 
+       BUG_ON(oldirq == 6);
+
        dev->irq = irq + 2;
 
-       ssb_dprintk(KERN_INFO PFX
-                   "set_irq: core 0x%04x, irq %d => %d\n",
-                   dev->id.coreid, oldirq, irq);
        /* clear the old irq */
        if (oldirq == 0)
                ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC)));
-       else
+       else if (oldirq != 5)
                clear_irq(bus, oldirq);
 
        /* assign the new one */
        if (irq == 0) {
                ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC)));
        } else {
+               u32 ipsflag = ssb_read32(mdev, SSB_IPSFLAG);
+               if ((ipsflag & ipsflag_irq_mask[irq]) != ipsflag_irq_mask[irq]) {
+                       u32 oldipsflag = (ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq];
+                       struct ssb_device *olddev = find_device(dev, oldipsflag);
+                       if (olddev)
+                               set_irq(olddev, 0);
+               }
                irqflag <<= ipsflag_irq_shift[irq];
-               irqflag |= (ssb_read32(mdev, SSB_IPSFLAG) & ~ipsflag_irq_mask[irq]);
+               irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]);
                ssb_write32(mdev, SSB_IPSFLAG, irqflag);
        }
+       ssb_dprintk(KERN_INFO PFX
+                   "set_irq: core 0x%04x, irq %d => %d\n",
+                   dev->id.coreid, oldirq+2, irq+2);
+}
+
+static void print_irq(struct ssb_device *dev, unsigned int irq)
+{
+       int i;
+       static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
+       ssb_dprintk(KERN_INFO PFX
+               "core 0x%04x, irq :", dev->id.coreid);
+       for (i = 0; i <= 6; i++) {
+               ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" ");
+       }
+       ssb_dprintk("\n");
+}
+
+static void dump_irq(struct ssb_bus *bus)
+{
+       int i;
+       for (i = 0; i < bus->nr_devices; i++) {
+               struct ssb_device *dev;
+               dev = &(bus->devices[i]);
+               print_irq(dev, ssb_mips_irq(dev));
+       }
 }
 
 static void ssb_mips_serial_init(struct ssb_mipscore *mcore)
@@ -197,16 +253,23 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
 
        /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */
        for (irq = 2, i = 0; i < bus->nr_devices; i++) {
+               int mips_irq;
                dev = &(bus->devices[i]);
-               dev->irq = ssb_mips_irq(dev) + 2;
+               mips_irq = ssb_mips_irq(dev);
+               if (mips_irq > 4)
+                       dev->irq = 0;
+               else
+                       dev->irq = mips_irq + 2;
+               if (dev->irq > 5)
+                       continue;
                switch (dev->id.coreid) {
                case SSB_DEV_USB11_HOST:
                        /* shouldn't need a separate irq line for non-4710, most of them have a proper
                         * external usb controller on the pci */
                        if ((bus->chip_id == 0x4710) && (irq <= 4)) {
                                set_irq(dev, irq++);
-                               break;
                        }
+                       break;
                        /* fallthrough */
                case SSB_DEV_PCI:
                case SSB_DEV_ETHERNET:
@@ -220,6 +283,8 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
                        }
                }
        }
+       ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n");
+       dump_irq(bus);
 
        ssb_mips_serial_init(mcore);
        ssb_mips_flash_detect(mcore);
index fbfadbac67e887d190ac1c93b87d957cf90146fa..100e7a5c5ea1f3a48991845ba1e1cf06758e462c 100644 (file)
@@ -583,7 +583,7 @@ static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom)
                        ssb_printk(".");
                err = ssb_pcmcia_sprom_write(bus, i, sprom[i]);
                if (err) {
-                       ssb_printk("\n" KERN_NOTICE PFX
+                       ssb_printk(KERN_NOTICE PFX
                                   "Failed to write to SPROM.\n");
                        failed = 1;
                        break;
@@ -591,7 +591,7 @@ static int ssb_pcmcia_sprom_write_all(struct ssb_bus *bus, const u16 *sprom)
        }
        err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS);
        if (err) {
-               ssb_printk("\n" KERN_NOTICE PFX
+               ssb_printk(KERN_NOTICE PFX
                           "Could not disable SPROM write access.\n");
                failed = 1;
        }
@@ -678,7 +678,8 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
                        sprom->board_rev = tuple.TupleData[1];
                        break;
                case SSB_PCMCIA_CIS_PA:
-                       GOTO_ERROR_ON(tuple.TupleDataLen != 9,
+                       GOTO_ERROR_ON((tuple.TupleDataLen != 9) &&
+                                     (tuple.TupleDataLen != 10),
                                      "pa tpl size");
                        sprom->pa0b0 = tuple.TupleData[1] |
                                 ((u16)tuple.TupleData[2] << 8);
@@ -718,7 +719,8 @@ int ssb_pcmcia_get_invariants(struct ssb_bus *bus,
                        sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1];
                        break;
                case SSB_PCMCIA_CIS_BFLAGS:
-                       GOTO_ERROR_ON(tuple.TupleDataLen != 3,
+                       GOTO_ERROR_ON((tuple.TupleDataLen != 3) &&
+                                     (tuple.TupleDataLen != 5),
                                      "bfl tpl size");
                        sprom->boardflags_lo = tuple.TupleData[1] |
                                         ((u16)tuple.TupleData[2] << 8);
index 348bf61a8fec96a2f8daa0389ae6578d47a9c0dd..975ecddbce30b48a4b20ed5ac955a48d7f224405 100644 (file)
@@ -103,8 +103,6 @@ source "drivers/staging/pohmelfs/Kconfig"
 
 source "drivers/staging/stlc45xx/Kconfig"
 
-source "drivers/staging/uc2322/Kconfig"
-
 source "drivers/staging/b3dfg/Kconfig"
 
 source "drivers/staging/phison/Kconfig"
index 8d61d7b4debfb78c1279ceac0c4379ac10b6a94d..2241ae1b21ee1ad47927386c6c5e4e2af4f83f4f 100644 (file)
@@ -34,7 +34,6 @@ obj-$(CONFIG_ANDROID)         += android/
 obj-$(CONFIG_DST)              += dst/
 obj-$(CONFIG_POHMELFS)         += pohmelfs/
 obj-$(CONFIG_STLC45XX)         += stlc45xx/
-obj-$(CONFIG_USB_SERIAL_ATEN2011)      += uc2322/
 obj-$(CONFIG_B3DFG)            += b3dfg/
 obj-$(CONFIG_IDE_PHISON)       += phison/
 obj-$(CONFIG_PLAN9AUTH)                += p9auth/
index fe72240f5a9e3bf9af573286cbce6810950db00e..f934393f39597c7ee1fc2baebf503b90222d636c 100644 (file)
@@ -96,19 +96,21 @@ static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask)
 
        read_lock(&tasklist_lock);
        for_each_process(p) {
+               struct mm_struct *mm;
                int oom_adj;
 
                task_lock(p);
-               if (!p->mm) {
+               mm = p->mm;
+               if (!mm) {
                        task_unlock(p);
                        continue;
                }
-               oom_adj = p->oomkilladj;
+               oom_adj = mm->oom_adj;
                if (oom_adj < min_adj) {
                        task_unlock(p);
                        continue;
                }
-               tasksize = get_mm_rss(p->mm);
+               tasksize = get_mm_rss(mm);
                task_unlock(p);
                if (tasksize <= 0)
                        continue;
index 524231047de5cfe5a8f56a53de320e6e7d8c0b91..9e6573cf97d3864a0490a9f4296404cba94046e6 100644 (file)
@@ -1,5 +1,6 @@
 config B3DFG
        tristate "Brontes 3d Frame Framegrabber"
+       depends on PCI
        default n
        ---help---
          This driver provides support for the Brontes 3d Framegrabber
index baf83c6a9412418be67392cb9dfc4a4425e26143..e3c3adc282e2592376a1fe5bca9b68a5d7e18096 100644 (file)
@@ -45,6 +45,8 @@ Devices: [JR3] PCI force sensor board (jr3_pci)
 #include <linux/delay.h>
 #include <linux/ctype.h>
 #include <linux/firmware.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
 #include "comedi_pci.h"
 #include "jr3_pci.h"
 
index 92121cf8c45cddb758a108febd5bd878c8757b92..5d9bab352c1d549806e36e1fca4520385ef8eb26 100644 (file)
@@ -111,9 +111,13 @@ static const struct s626_board s626_boards[] = {
 #define PCI_VENDOR_ID_S626 0x1131
 #define PCI_DEVICE_ID_S626 0x7146
 
+/*
+ * For devices with vendor:device id == 0x1131:0x7146 you must specify
+ * also subvendor:subdevice ids, because otherwise it will conflict with
+ * Philips SAA7146 media/dvb based cards.
+ */
 static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = {
-       {PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-               0},
+       {PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, 0x6000, 0x0272, 0, 0, 0},
        {0}
 };
 
@@ -499,25 +503,26 @@ static int s626_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        resource_size_t resourceStart;
        dma_addr_t appdma;
        struct comedi_subdevice *s;
-       struct pci_dev *pdev;
+       const struct pci_device_id *ids;
+       struct pci_dev *pdev = NULL;
 
        if (alloc_private(dev, sizeof(struct s626_private)) < 0)
                return -ENOMEM;
 
-       for (pdev = pci_get_device(PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626,
-                       NULL); pdev != NULL;
-               pdev = pci_get_device(PCI_VENDOR_ID_S626,
-                       PCI_DEVICE_ID_S626, pdev)) {
-               if (it->options[0] || it->options[1]) {
-                       if (pdev->bus->number == it->options[0] &&
-                               PCI_SLOT(pdev->devfn) == it->options[1]) {
+       for (i = 0; i < (ARRAY_SIZE(s626_pci_table) - 1) && !pdev; i++) {
+               ids = &s626_pci_table[i];
+               do {
+                       pdev = pci_get_subsys(ids->vendor, ids->device, ids->subvendor,
+                                             ids->subdevice, pdev);
+
+                       if ((it->options[0] || it->options[1]) && pdev) {
                                /* matches requested bus/slot */
+                               if (pdev->bus->number == it->options[0] &&
+                                   PCI_SLOT(pdev->devfn) == it->options[1])
+                                       break;
+                       } else
                                break;
-                       }
-               } else {
-                       /* no bus/slot specified */
-                       break;
-               }
+               } while (1);
        }
        devpriv->pdev = pdev;
 
index a5e4acab089e034c5ddd1faba37df5313526c6d1..bb22347af60e8f2ecd852ed68ffb0ef9c95899ee 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 #include <linux/usb.h>
 #include <dvb-usb.h>
 
index ae8d588d3a2774d67f94440a48cb40d360a597c7..c7206f8bcd9388ca1b72d9b17754318e11f28149 100644 (file)
@@ -1,5 +1,6 @@
 config HECI
        tristate "Intel Management Engine Interface (MEI) Support"
+       depends on PCI
        ---help---
          The Intel Management Engine Interface (Intel MEI) driver allows
          applications to access the Active Management Technology
index 6ec25203089c84f7a467327b322e324d98fcee00..d6ce39823de673378daae4696e17dcbe63210761 100644 (file)
@@ -7,4 +7,4 @@ TODO:
        - possible comedi merge
 
 Please send cleanup patches to Greg Kroah-Hartman <greg@kroah.com>
-and CC: David Kiliani <mail@davidkiliani.de>
+and CC: David Kiliani <mail@davidkiliani.de> and Meilhaus Support <support@meilhaus.de>
index 1cdfe69585ea666d63b8e16175f2705c1529461b..04e2f92c0f6293292d55d5a56822a936d0a4ba52 100644 (file)
@@ -444,8 +444,7 @@ static void piusb_write_bulk_callback(struct urb *urb)
                        __func__, status);
 
        pdx->pendingWrite = 0;
-       usb_buffer_free(urb->dev, urb->transfer_buffer_length,
-                       urb->transfer_buffer, urb->transfer_dma);
+       kfree(urb->transfer_buffer);
 }
 
 int piusb_output(struct ioctl_struct *io, unsigned char *uBuf, int len,
@@ -457,9 +456,7 @@ int piusb_output(struct ioctl_struct *io, unsigned char *uBuf, int len,
 
        urb = usb_alloc_urb(0, GFP_KERNEL);
        if (urb != NULL) {
-               kbuf =
-                   usb_buffer_alloc(pdx->udev, len, GFP_KERNEL,
-                                    &urb->transfer_dma);
+               kbuf = kmalloc(len, GFP_KERNEL);
                if (!kbuf) {
                        dev_err(&pdx->udev->dev, "buffer_alloc failed\n");
                        return -ENOMEM;
@@ -470,7 +467,6 @@ int piusb_output(struct ioctl_struct *io, unsigned char *uBuf, int len,
                }
                usb_fill_bulk_urb(urb, pdx->udev, pdx->hEP[io->endpoint], kbuf,
                                  len, piusb_write_bulk_callback, pdx);
-               urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
                err = usb_submit_urb(urb, GFP_KERNEL);
                if (err) {
                        dev_err(&pdx->udev->dev,
@@ -641,7 +637,7 @@ static int MapUserBuffer(struct ioctl_struct *io, struct device_extension *pdx)
        numPagesRequired =
            ((uaddr & ~PAGE_MASK) + count + ~PAGE_MASK) >> PAGE_SHIFT;
        dbg("Number of pages needed = %d", numPagesRequired);
-       maplist_p = vmalloc(numPagesRequired * sizeof(struct page));
+       maplist_p = vmalloc(numPagesRequired * sizeof(struct page *));
        if (!maplist_p) {
                dbg("Can't Allocate Memory for maplist_p");
                return -ENOMEM;
@@ -712,9 +708,7 @@ static int MapUserBuffer(struct ioctl_struct *io, struct device_extension *pdx)
                usb_fill_bulk_urb(pdx->PixelUrb[frameInfo][i],
                                  pdx->udev,
                                  epAddr,
-                                 (dma_addr_t *) sg_dma_address(&pdx->
-                                                               sgl[frameInfo]
-                                                               [i]),
+                                 NULL, // non-DMA HC? buy a better hardware
                                  sg_dma_len(&pdx->sgl[frameInfo][i]),
                                  piusb_readPIXEL_callback, (void *)pdx);
                pdx->PixelUrb[frameInfo][i]->transfer_dma =
@@ -722,6 +716,8 @@ static int MapUserBuffer(struct ioctl_struct *io, struct device_extension *pdx)
                pdx->PixelUrb[frameInfo][i]->transfer_flags =
                    URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT;
        }
+       if (i == 0)
+               return -EINVAL;
        /* only interrupt when last URB completes */
        pdx->PixelUrb[frameInfo][--i]->transfer_flags &= ~URB_NO_INTERRUPT;
        pdx->pendedPixelUrbs[frameInfo] =
index 85175c1824328f58d3aa652de7240bdd6ab5bf2b..25b53ac3f8204f9484e002beaedf77db6d5acb3e 100644 (file)
@@ -43,9 +43,6 @@
 #include "rtmp_type.h"
 #include <linux/module.h>
 #include <linux/kernel.h>
-#if !defined(RT2860) && !defined(RT30xx)
-#include <linux/kthread.h>
-#endif
 
 #include <linux/spinlock.h>
 #include <linux/init.h>
@@ -166,9 +163,7 @@ typedef int (*HARD_START_XMIT_FUNC)(struct sk_buff *skb, struct net_device *net_
 
 #ifndef RT30xx
 typedef        struct pid *    THREAD_PID;
-#ifdef RT2860
 #define        THREAD_PID_INIT_VALUE   NULL
-#endif
 #define        GET_PID(_v)     find_get_pid(_v)
 #define        GET_PID_NUMBER(_v)      pid_nr(_v)
 #define CHECK_PID_LEGALITY(_pid)       if (pid_nr(_pid) >= 0)
@@ -188,12 +183,12 @@ struct os_cookie {
        dma_addr_t                              pAd_pa;
 #endif
 #ifdef RT2870
-       struct usb_device       *pUsb_Dev;
+       struct usb_device               *pUsb_Dev;
 
 #ifndef RT30xx
-       struct task_struct      *MLMEThr_task;
-       struct task_struct      *RTUSBCmdThr_task;
-       struct task_struct      *TimerQThr_task;
+       THREAD_PID                              MLMEThr_pid;
+       THREAD_PID                              RTUSBCmdThr_pid;
+       THREAD_PID                              TimerQThr_pid;
 #endif
 #ifdef RT30xx
        struct pid      *MLMEThr_pid;
index dd01c64fbf61fd09432cc6d0452213239d4801eb..a4e8696ca39c4dba233fb9851af7146a2cc88ab7 100644 (file)
@@ -235,7 +235,7 @@ INT MlmeThread(
        DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
 
 #ifndef RT30xx
-       pObj->MLMEThr_task = NULL;
+       pObj->MLMEThr_pid = THREAD_PID_INIT_VALUE;
 #endif
 #ifdef RT30xx
        pObj->MLMEThr_pid = NULL;
@@ -348,7 +348,7 @@ INT RTUSBCmdThread(
        DBGPRINT(RT_DEBUG_TRACE,( "<---RTUSBCmdThread\n"));
 
 #ifndef RT30xx
-       pObj->RTUSBCmdThr_task = NULL;
+       pObj->RTUSBCmdThr_pid = THREAD_PID_INIT_VALUE;
 #endif
 #ifdef RT30xx
        pObj->RTUSBCmdThr_pid = NULL;
@@ -447,7 +447,7 @@ INT TimerQThread(
        DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__func__));
 
 #ifndef RT30xx
-       pObj->TimerQThr_task = NULL;
+       pObj->TimerQThr_pid = THREAD_PID_INIT_VALUE;
 #endif
 #ifdef RT30xx
        pObj->TimerQThr_pid = NULL;
@@ -883,46 +883,69 @@ VOID RT28xxThreadTerminate(
 
        // Terminate Threads
 #ifndef RT30xx
-       BUG_ON(pObj->TimerQThr_task == NULL);
-       CHECK_PID_LEGALITY(task_pid(pObj->TimerQThr_task))
+       CHECK_PID_LEGALITY(pObj->TimerQThr_pid)
        {
                POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
 
-               printk(KERN_DEBUG "Terminate the TimerQThr pid=%d!\n",
-                       pid_nr(task_pid(pObj->TimerQThr_task)));
+               printk("Terminate the TimerQThr_pid=%d!\n", GET_PID_NUMBER(pObj->TimerQThr_pid));
                mb();
                pAd->TimerFunc_kill = 1;
                mb();
-               kthread_stop(pObj->TimerQThr_task);
-               pObj->TimerQThr_task = NULL;
+               ret = KILL_THREAD_PID(pObj->TimerQThr_pid, SIGTERM, 1);
+               if (ret)
+               {
+                       printk(KERN_WARNING "%s: unable to stop TimerQThread, pid=%d, ret=%d!\n",
+                                       pAd->net_dev->name, GET_PID_NUMBER(pObj->TimerQThr_pid), ret);
+               }
+               else
+               {
+                       wait_for_completion(&pAd->TimerQComplete);
+                       pObj->TimerQThr_pid = THREAD_PID_INIT_VALUE;
+               }
        }
 
-       BUG_ON(pObj->MLMEThr_task == NULL);
-       CHECK_PID_LEGALITY(task_pid(pObj->MLMEThr_task))
+       CHECK_PID_LEGALITY(pObj->MLMEThr_pid)
        {
-               printk(KERN_DEBUG "Terminate the MLMEThr pid=%d!\n",
-                       pid_nr(task_pid(pObj->MLMEThr_task)));
+               printk("Terminate the MLMEThr_pid=%d!\n", GET_PID_NUMBER(pObj->MLMEThr_pid));
                mb();
                pAd->mlme_kill = 1;
                //RT28XX_MLME_HANDLER(pAd);
                mb();
-               kthread_stop(pObj->MLMEThr_task);
-               pObj->MLMEThr_task = NULL;
+               ret = KILL_THREAD_PID(pObj->MLMEThr_pid, SIGTERM, 1);
+               if (ret)
+               {
+                       printk (KERN_WARNING "%s: unable to Mlme thread, pid=%d, ret=%d!\n",
+                                       pAd->net_dev->name, GET_PID_NUMBER(pObj->MLMEThr_pid), ret);
+               }
+               else
+               {
+                       //wait_for_completion (&pAd->notify);
+                       wait_for_completion (&pAd->mlmeComplete);
+                       pObj->MLMEThr_pid = THREAD_PID_INIT_VALUE;
+               }
        }
 
-       BUG_ON(pObj->RTUSBCmdThr_task == NULL);
-       CHECK_PID_LEGALITY(task_pid(pObj->RTUSBCmdThr_task))
+       CHECK_PID_LEGALITY(pObj->RTUSBCmdThr_pid)
        {
-               printk(KERN_DEBUG "Terminate the RTUSBCmdThr pid=%d!\n",
-                       pid_nr(task_pid(pObj->RTUSBCmdThr_task)));
+               printk("Terminate the RTUSBCmdThr_pid=%d!\n", GET_PID_NUMBER(pObj->RTUSBCmdThr_pid));
                mb();
                NdisAcquireSpinLock(&pAd->CmdQLock);
                pAd->CmdQ.CmdQState = RT2870_THREAD_STOPED;
                NdisReleaseSpinLock(&pAd->CmdQLock);
                mb();
                //RTUSBCMDUp(pAd);
-               kthread_stop(pObj->RTUSBCmdThr_task);
-               pObj->RTUSBCmdThr_task = NULL;
+               ret = KILL_THREAD_PID(pObj->RTUSBCmdThr_pid, SIGTERM, 1);
+               if (ret)
+               {
+                       printk(KERN_WARNING "%s: unable to RTUSBCmd thread, pid=%d, ret=%d!\n",
+                                       pAd->net_dev->name, GET_PID_NUMBER(pObj->RTUSBCmdThr_pid), ret);
+               }
+               else
+               {
+                       //wait_for_completion (&pAd->notify);
+                       wait_for_completion (&pAd->CmdQComplete);
+                       pObj->RTUSBCmdThr_pid = THREAD_PID_INIT_VALUE;
+               }
        }
 #endif
 #ifdef RT30xx
@@ -1045,7 +1068,7 @@ BOOLEAN RT28XXChipsetCheck(
                        dev_p->descriptor.idProduct == rtusb_usb_id[i].idProduct)
                {
 #ifndef RT30xx
-                       printk(KERN_DEBUG "rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
+                       printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
 #endif
 #ifdef RT30xx
                        printk("rt2870: idVendor = 0x%x, idProduct = 0x%x\n",
index 0f4c8af97e47f5c5b06f4f4b80ebbddcc7ed81b9..80909e9ab5aea5469dd2b60a29f35e8edef7b93f 100644 (file)
@@ -700,8 +700,8 @@ NDIS_STATUS AdapterBlockAllocateMemory(
        usb_dev = pObj->pUsb_Dev;
 
 #ifndef RT30xx
-       pObj->MLMEThr_task              = NULL;
-       pObj->RTUSBCmdThr_task  = NULL;
+       pObj->MLMEThr_pid               = THREAD_PID_INIT_VALUE;
+       pObj->RTUSBCmdThr_pid   = THREAD_PID_INIT_VALUE;
 #endif
 #ifdef RT30xx
        pObj->MLMEThr_pid       = NULL;
@@ -743,7 +743,7 @@ NDIS_STATUS  CreateThreads(
        PRTMP_ADAPTER pAd = net_dev->ml_priv;
        POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
 #ifndef RT30xx
-       struct task_struct *tsk;
+       pid_t pid_number = -1;
 #endif
 #ifdef RT30xx
        pid_t pid_number;
@@ -762,10 +762,10 @@ NDIS_STATUS        CreateThreads(
 
        // Creat MLME Thread
 #ifndef RT30xx
-       pObj->MLMEThr_task = NULL;
-       tsk = kthread_run(MlmeThread, pAd, "%s", pAd->net_dev->name);
-
-       if (IS_ERR(tsk)) {
+       pObj->MLMEThr_pid= THREAD_PID_INIT_VALUE;
+       pid_number = kernel_thread(MlmeThread, pAd, CLONE_VM);
+       if (pid_number < 0)
+       {
 #endif
 #ifdef RT30xx
        pObj->MLMEThr_pid = NULL;
@@ -778,7 +778,7 @@ NDIS_STATUS  CreateThreads(
        }
 
 #ifndef RT30xx
-       pObj->MLMEThr_task = tsk;
+       pObj->MLMEThr_pid = GET_PID(pid_number);
 #endif
 #ifdef RT30xx
        pObj->MLMEThr_pid = find_get_pid(pid_number);
@@ -788,10 +788,9 @@ NDIS_STATUS         CreateThreads(
 
        // Creat Command Thread
 #ifndef RT30xx
-       pObj->RTUSBCmdThr_task = NULL;
-       tsk = kthread_run(RTUSBCmdThread, pAd, "%s", pAd->net_dev->name);
-
-       if (IS_ERR(tsk) < 0)
+       pObj->RTUSBCmdThr_pid= THREAD_PID_INIT_VALUE;
+       pid_number = kernel_thread(RTUSBCmdThread, pAd, CLONE_VM);
+       if (pid_number < 0)
 #endif
 #ifdef RT30xx
        pObj->RTUSBCmdThr_pid = NULL;
@@ -804,7 +803,7 @@ NDIS_STATUS  CreateThreads(
        }
 
 #ifndef RT30xx
-       pObj->RTUSBCmdThr_task = tsk;
+       pObj->RTUSBCmdThr_pid = GET_PID(pid_number);
 #endif
 #ifdef RT30xx
        pObj->RTUSBCmdThr_pid = find_get_pid(pid_number);
@@ -812,9 +811,9 @@ NDIS_STATUS  CreateThreads(
        wait_for_completion(&(pAd->CmdQComplete));
 
 #ifndef RT30xx
-       pObj->TimerQThr_task = NULL;
-       tsk = kthread_run(TimerQThread, pAd, "%s", pAd->net_dev->name);
-       if (IS_ERR(tsk) < 0)
+       pObj->TimerQThr_pid= THREAD_PID_INIT_VALUE;
+       pid_number = kernel_thread(TimerQThread, pAd, CLONE_VM);
+       if (pid_number < 0)
 #endif
 #ifdef RT30xx
        pObj->TimerQThr_pid = NULL;
@@ -826,7 +825,7 @@ NDIS_STATUS  CreateThreads(
                return NDIS_STATUS_FAILURE;
        }
 #ifndef RT30xx
-       pObj->TimerQThr_task = tsk;
+       pObj->TimerQThr_pid = GET_PID(pid_number);
 #endif
 #ifdef RT30xx
        pObj->TimerQThr_pid = find_get_pid(pid_number);
index fd1b0c18f2a007633a733807e76cb8e2620c9a13..704b5c2d5091a1327492f509c16e2b4d4a798075 100644 (file)
@@ -984,8 +984,7 @@ NDIS_STATUS RTUSBEnqueueCmdFromNdis(
        POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
 
 #ifndef RT30xx
-       BUG_ON(pObj->RTUSBCmdThr_task == NULL);
-       CHECK_PID_LEGALITY(task_pid(pObj->RTUSBCmdThr_task))
+       CHECK_PID_LEGALITY(pObj->RTUSBCmdThr_pid)
 #endif
 #ifdef RT30xx
        if (pObj->RTUSBCmdThr_pid < 0)
index 5e5b3f2b7eb1e757975763c64409058ebf345015..2b8872b2fd9dcf116522cd90efe206e9f9ae51ff 100644 (file)
@@ -79,6 +79,7 @@
 {      \
        {USB_DEVICE(0x148F,0x2770)}, /* Ralink */               \
        {USB_DEVICE(0x1737,0x0071)}, /* Linksys WUSB600N */     \
+       {USB_DEVICE(0x1737,0x0070)}, /* Linksys */      \
        {USB_DEVICE(0x148F,0x2870)}, /* Ralink */               \
        {USB_DEVICE(0x148F,0x3070)}, /* Ralink */               \
        {USB_DEVICE(0x0B05,0x1731)}, /* Asus */                 \
        {USB_DEVICE(0x0DF6,0x002C)}, /* Sitecom */              \
        {USB_DEVICE(0x0DF6,0x002D)}, /* Sitecom */              \
        {USB_DEVICE(0x0DF6,0x0039)}, /* Sitecom */              \
+       {USB_DEVICE(0x0DF6,0x003F)}, /* Sitecom WL-608 */       \
        {USB_DEVICE(0x14B2,0x3C06)}, /* Conceptronic */         \
        {USB_DEVICE(0x14B2,0x3C28)}, /* Conceptronic */         \
        {USB_DEVICE(0x2019,0xED06)}, /* Planex Communications, Inc. */          \
+       {USB_DEVICE(0x2019,0xED14)}, /* Planex Communications, Inc. */          \
        {USB_DEVICE(0x2019,0xAB25)}, /* Planex Communications, Inc. RT3070 */           \
        {USB_DEVICE(0x07D1,0x3C09)}, /* D-Link */               \
        {USB_DEVICE(0x07D1,0x3C11)}, /* D-Link */               \
        {USB_DEVICE(0x14B2,0x3C07)}, /* AL */                   \
        {USB_DEVICE(0x14B2,0x3C12)}, /* AL */           \
        {USB_DEVICE(0x050D,0x8053)}, /* Belkin */               \
+       {USB_DEVICE(0x050D,0x815C)}, /* Belkin */               \
        {USB_DEVICE(0x14B2,0x3C23)}, /* Airlink */              \
        {USB_DEVICE(0x14B2,0x3C27)}, /* Airlink */              \
        {USB_DEVICE(0x07AA,0x002F)}, /* Corega */               \
@@ -586,16 +590,14 @@ VOID RTUSBBulkRxComplete(purbb_t pUrb, struct pt_regs *pt_regs);
 #define RTUSBMlmeUp(pAd)               \
 {                                                                  \
        POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;  \
-       BUG_ON(pObj->MLMEThr_task == NULL);                 \
-       CHECK_PID_LEGALITY(task_pid(pObj->MLMEThr_task))                    \
+       CHECK_PID_LEGALITY(pObj->MLMEThr_pid)               \
         up(&(pAd->mlme_semaphore)); \
 }
 
 #define RTUSBCMDUp(pAd)                        \
 {                                                                          \
        POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;  \
-       BUG_ON(pObj->RTUSBCmdThr_task == NULL);     \
-       CHECK_PID_LEGALITY(task_pid(pObj->RTUSBCmdThr_task))        \
+       CHECK_PID_LEGALITY(pObj->RTUSBCmdThr_pid)           \
            up(&(pAd->RTUSBCmd_semaphore)); \
 }
 #endif
index 93af37e2d31a0b453031ffff3c79f852f6d79022..54b4b718f84a5f09fa2cd3a491f423d781276bc7 100644 (file)
@@ -461,19 +461,19 @@ int ieee80211_wx_get_name(struct ieee80211_device *ieee,
                             struct iw_request_info *info,
                             union iwreq_data *wrqu, char *extra)
 {
-       strcpy(wrqu->name, "802.11");
+       strlcpy(wrqu->name, "802.11", IFNAMSIZ);
        if(ieee->modulation & IEEE80211_CCK_MODULATION){
-               strcat(wrqu->name, "b");
+               strlcat(wrqu->name, "b", IFNAMSIZ);
                if(ieee->modulation & IEEE80211_OFDM_MODULATION)
-                       strcat(wrqu->name, "/g");
+                       strlcat(wrqu->name, "/g", IFNAMSIZ);
        }else if(ieee->modulation & IEEE80211_OFDM_MODULATION)
-               strcat(wrqu->name, "g");
+               strlcat(wrqu->name, "g", IFNAMSIZ);
 
        if((ieee->state == IEEE80211_LINKED) ||
                (ieee->state == IEEE80211_LINKED_SCANNING))
-               strcat(wrqu->name," linked");
+               strlcat(wrqu->name,"  link", IFNAMSIZ);
        else if(ieee->state != IEEE80211_NOLINK)
-               strcat(wrqu->name," link..");
+               strlcat(wrqu->name," .....", IFNAMSIZ);
 
 
        return 0;
index 4b5552c5926e33c79309c73610d70bb453f30be2..770f41280f21d5412a93761b2ea8522b88fce4f9 100644 (file)
@@ -1,6 +1,6 @@
 config RTL8192SU
        tristate "RealTek RTL8192SU Wireless LAN NIC driver"
        depends on PCI
-       depends on WIRELESS_EXT && COMPAT_NET_DEV_OPS
+       depends on WIRELESS_EXT
        default N
        ---help---
index 0edb09a536f999bfefe40ef4b40c98329804e90d..ea9739318037e847f21dc955785d3fbb29529ec0 100644 (file)
@@ -2645,7 +2645,7 @@ extern int ieee80211_encrypt_fragment(
        struct sk_buff *frag,
        int hdr_len);
 
-extern int ieee80211_xmit(struct sk_buff *skb,
+extern int rtl8192_ieee80211_xmit(struct sk_buff *skb,
                          struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 
index 720bfcbfadc1dbdd805c2ffed373b986910d6fce..5e3a2cbed2b1324dbd883c7457780e34c824bf1c 100644 (file)
@@ -2645,7 +2645,7 @@ extern int ieee80211_encrypt_fragment(
        struct sk_buff *frag,
        int hdr_len);
 
-extern int ieee80211_xmit(struct sk_buff *skb,
+extern int rtl8192_ieee80211_xmit(struct sk_buff *skb,
                          struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 
index f408b4583b82981a1626a909e8505e76fc0e1349..759032db4a3482fd03fdfc2f3c1f49aa152c03ae 100644 (file)
@@ -118,7 +118,6 @@ struct net_device *alloc_ieee80211(int sizeof_priv)
 #else
        ieee = (struct ieee80211_device *)dev->priv;
 #endif
-       dev->hard_start_xmit = ieee80211_xmit;
 
        memset(ieee, 0, sizeof(struct ieee80211_device)+sizeof_priv);
        ieee->dev = dev;
index 1f50c46dcb90636d765ebf879d0d39e61fe15473..191dc3fbbe32e09d1efbf3f3a66fee78c68703c8 100644 (file)
@@ -548,21 +548,21 @@ int ieee80211_wx_get_name(struct ieee80211_device *ieee,
                             struct iw_request_info *info,
                             union iwreq_data *wrqu, char *extra)
 {
-       strcpy(wrqu->name, "802.11");
+       strlcpy(wrqu->name, "802.11", IFNAMSIZ);
        if(ieee->modulation & IEEE80211_CCK_MODULATION){
-               strcat(wrqu->name, "b");
+               strlcat(wrqu->name, "b", IFNAMSIZ);
                if(ieee->modulation & IEEE80211_OFDM_MODULATION)
-                       strcat(wrqu->name, "/g");
+                       strlcat(wrqu->name, "/g", IFNAMSIZ);
        }else if(ieee->modulation & IEEE80211_OFDM_MODULATION)
-               strcat(wrqu->name, "g");
+               strlcat(wrqu->name, "g", IFNAMSIZ);
        if (ieee->mode & (IEEE_N_24G | IEEE_N_5G))
-               strcat(wrqu->name, "/n");
+               strlcat(wrqu->name, "/n", IFNAMSIZ);
 
        if((ieee->state == IEEE80211_LINKED) ||
                (ieee->state == IEEE80211_LINKED_SCANNING))
-               strcat(wrqu->name," linked");
+               strlcat(wrqu->name, "  link", IFNAMSIZ);
        else if(ieee->state != IEEE80211_NOLINK)
-               strcat(wrqu->name," link..");
+               strlcat(wrqu->name, " .....", IFNAMSIZ);
 
 
        return 0;
index 7294572b990f7fecf9c0f43df3f50a2f6528bcdd..cba12b84be5c1dab2c767f0fa4ff496a9ed41478 100644 (file)
@@ -618,7 +618,7 @@ void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u
        }
 }
 
-int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
+int rtl8192_ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
        struct ieee80211_device *ieee = netdev_priv(dev);
@@ -943,5 +943,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
        return 1;
 
 }
+EXPORT_SYMBOL(rtl8192_ieee80211_xmit);
 
 EXPORT_SYMBOL(ieee80211_txb_free);
index f1423d714496ac97ce40b193cb2a573d4897ebf6..70f81a8f12913b7e2ccda789331f2343fc28eda5 100644 (file)
@@ -12132,6 +12132,19 @@ static void HalUsbSetQueuePipeMapping8192SUsb(struct usb_interface *intf, struct
 }
 #endif
 
+static const struct net_device_ops rtl8192_netdev_ops = {
+       .ndo_open               = rtl8192_open,
+       .ndo_stop               = rtl8192_close,
+       .ndo_get_stats          = rtl8192_stats,
+       .ndo_tx_timeout         = tx_timeout,
+       .ndo_do_ioctl           = rtl8192_ioctl,
+       .ndo_set_multicast_list = r8192_set_multicast,
+       .ndo_set_mac_address    = r8192_set_mac_adr,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_start_xmit         = rtl8192_ieee80211_xmit,
+};
+
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
 static int __devinit rtl8192_usb_probe(struct usb_interface *intf,
                         const struct usb_device_id *id)
@@ -12186,15 +12199,7 @@ static void * __devinit rtl8192_usb_probe(struct usb_device *udev,
        priv->ops = &rtl8192u_ops;
 #endif
 
-       dev->open = rtl8192_open;
-       dev->stop = rtl8192_close;
-       //dev->hard_start_xmit = rtl8192_8023_hard_start_xmit;
-       dev->tx_timeout = tx_timeout;
-       //dev->wireless_handlers = &r8192_wx_handlers_def;
-       dev->do_ioctl = rtl8192_ioctl;
-       dev->set_multicast_list = r8192_set_multicast;
-       dev->set_mac_address = r8192_set_mac_adr;
-       dev->get_stats = rtl8192_stats;
+       dev->netdev_ops = &rtl8192_netdev_ops;
 
          //DMESG("Oops: i'm coming\n");
 #if WIRELESS_EXT >= 12
index 92c95aa36638077cea8b5328b4aafcda480c33bf..b1531a8d0cde12d0ee656d074ce45452fb834ac7 100644 (file)
@@ -35,7 +35,9 @@ int rtl8192U_suspend(struct usb_interface *intf, pm_message_t state)
                      return 0;
                 }
 
-               dev->stop(dev);
+               if (dev->netdev_ops->ndo_stop)
+                       dev->netdev_ops->ndo_stop(dev);
+
                mdelay(10);
 
                netif_device_detach(dev);
@@ -61,7 +63,9 @@ int rtl8192U_resume (struct usb_interface *intf)
                }
 
                netif_device_attach(dev);
-               dev->open(dev);
+
+               if (dev->netdev_ops->ndo_open)
+                       dev->netdev_ops->ndo_open(dev);
        }
 
         return 0;
index 90b29b564631656711694df46111dff8c4e8cda0..0fdf8c6dc648a69eaeeac311b1e24a3cb51d85e9 100644 (file)
@@ -360,18 +360,18 @@ static void qt_read_bulk_callback(struct urb *urb)
        if (port_paranoia_check(port, __func__) != 0) {
                dbg("%s - port_paranoia_check, exiting\n", __func__);
                qt_port->ReadBulkStopped = 1;
-               return;
+               goto exit;
        }
 
        if (!serial) {
                dbg("%s - bad serial pointer, exiting\n", __func__);
-               return;
+               goto exit;
        }
        if (qt_port->closePending == 1) {
                /* Were closing , stop reading */
                dbg("%s - (qt_port->closepending == 1\n", __func__);
                qt_port->ReadBulkStopped = 1;
-               return;
+               goto exit;
        }
 
        /*
@@ -381,7 +381,7 @@ static void qt_read_bulk_callback(struct urb *urb)
         */
        if (qt_port->RxHolding == 1) {
                qt_port->ReadBulkStopped = 1;
-               return;
+               goto exit;
        }
 
        if (urb->status) {
@@ -389,7 +389,7 @@ static void qt_read_bulk_callback(struct urb *urb)
 
                dbg("%s - nonzero read bulk status received: %d\n",
                    __func__, urb->status);
-               return;
+               goto exit;
        }
 
        if (tty && RxCount) {
@@ -463,6 +463,8 @@ static void qt_read_bulk_callback(struct urb *urb)
        }
 
        schedule_work(&port->work);
+exit:
+       tty_kref_put(tty);
 }
 
 /*
@@ -736,6 +738,11 @@ static int qt_startup(struct usb_serial *serial)
                if (!qt_port) {
                        dbg("%s: kmalloc for quatech_port (%d) failed!.",
                            __func__, i);
+                       for(--i; i >= 0; i--) {
+                               port = serial->port[i];
+                               kfree(usb_get_serial_port_data(port));
+                               usb_set_serial_port_data(port, NULL);
+                       }
                        return -ENOMEM;
                }
                spin_lock_init(&qt_port->lock);
@@ -866,7 +873,7 @@ static void qt_release(struct usb_serial *serial)
 
 }
 
-int qt_open(struct tty_struct *tty,
+static int qt_open(struct tty_struct *tty,
            struct usb_serial_port *port, struct file *filp)
 {
        struct usb_serial *serial;
@@ -1041,17 +1048,19 @@ static void qt_block_until_empty(struct tty_struct *tty,
        }
 }
 
-static void qt_close(struct tty_struct *tty, struct usb_serial_port *port,
-                    struct file *filp)
+static void qt_close(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
        struct quatech_port *qt_port;
        struct quatech_port *port0;
+       struct tty_struct *tty;
        int status;
        unsigned int index;
        status = 0;
 
        dbg("%s - port %d\n", __func__, port->number);
+
+       tty = tty_port_tty_get(&port->port);
        index = tty->index - serial->minor;
 
        qt_port = qt_get_port_private(port);
@@ -1066,6 +1075,7 @@ static void qt_close(struct tty_struct *tty, struct usb_serial_port *port,
        /* wait up to for transmitter to empty */
        if (serial->dev)
                qt_block_until_empty(tty, qt_port);
+       tty_kref_put(tty);
 
        /* Close uart channel */
        status = qt_close_channel(serial, index);
index cfdaac9b747edbc15cc3c0c0746772815b6ddd9c..a137c78fac0982ee293860344bc172b757fb7ead 100644 (file)
@@ -2235,24 +2235,6 @@ static void stlc45xx_op_remove_interface(struct ieee80211_hw *hw,
        stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
 }
 
-static int stlc45xx_op_config_interface(struct ieee80211_hw *hw,
-                                       struct ieee80211_vif *vif,
-                                       struct ieee80211_if_conf *conf)
-{
-       struct stlc45xx *stlc = hw->priv;
-
-       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
-       mutex_lock(&stlc->mutex);
-
-       memcpy(stlc->bssid, conf->bssid, ETH_ALEN);
-       stlc45xx_tx_setup(stlc);
-
-       mutex_unlock(&stlc->mutex);
-
-       return 0;
-}
-
 static int stlc45xx_op_config(struct ieee80211_hw *hw, u32 changed)
 {
        struct stlc45xx *stlc = hw->priv;
@@ -2295,6 +2277,14 @@ static void stlc45xx_op_bss_info_changed(struct ieee80211_hw *hw,
 {
        struct stlc45xx *stlc = hw->priv;
 
+       stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
+       mutex_lock(&stlc->mutex);
+
+       memcpy(stlc->bssid, info->bssid, ETH_ALEN);
+       stlc45xx_tx_setup(stlc);
+
+       mutex_unlock(&stlc->mutex);
+
        if (changed & BSS_CHANGED_ASSOC) {
                stlc->associated = info->assoc;
                if (info->assoc)
@@ -2357,7 +2347,6 @@ static const struct ieee80211_ops stlc45xx_ops = {
        .add_interface = stlc45xx_op_add_interface,
        .remove_interface = stlc45xx_op_remove_interface,
        .config = stlc45xx_op_config,
-       .config_interface = stlc45xx_op_config_interface,
        .configure_filter = stlc45xx_op_configure_filter,
        .tx = stlc45xx_op_tx,
        .bss_info_changed = stlc45xx_op_bss_info_changed,
diff --git a/drivers/staging/uc2322/Kconfig b/drivers/staging/uc2322/Kconfig
deleted file mode 100644 (file)
index 2e0c6e7..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-config USB_SERIAL_ATEN2011
-       tristate "ATEN 2011 USB to serial device support"
-       depends on USB_SERIAL
-       default N
-       ---help---
-         Say Y here if you want to use a ATEN 2011 dual port USB to serial
-         adapter.
-
-         To compile this driver as a module, choose M here: the module will be
-         called aten2011.
diff --git a/drivers/staging/uc2322/Makefile b/drivers/staging/uc2322/Makefile
deleted file mode 100644 (file)
index 49c18d6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_USB_SERIAL_ATEN2011)      += aten2011.o
diff --git a/drivers/staging/uc2322/TODO b/drivers/staging/uc2322/TODO
deleted file mode 100644 (file)
index c189a64..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-TODO:
-       - checkpatch.pl cleanups
-       - remove dead and useless code (auditing the tty ioctls to
-         verify that they really are correct and needed.)
-
-Please send any patches to Greg Kroah-Hartman <greg@kroah.com> and
-Russell Lang <gsview@ghostgum.com.au>.
diff --git a/drivers/staging/uc2322/aten2011.c b/drivers/staging/uc2322/aten2011.c
deleted file mode 100644 (file)
index 39d0926..0000000
+++ /dev/null
@@ -1,2430 +0,0 @@
-/*
- * Aten 2011 USB serial driver for 4 port devices
- *
- * Copyright (C) 2000 Inside Out Networks
- * Copyright (C) 2001-2002, 2009 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (C) 2009 Novell 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/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/module.h>
-#include <linux/serial.h>
-#include <linux/uaccess.h>
-#include <linux/usb.h>
-#include <linux/usb/serial.h>
-
-
-#define ZLP_REG1               0x3A    /* Zero_Flag_Reg1 58 */
-#define ZLP_REG2               0x3B    /* Zero_Flag_Reg2 59 */
-#define ZLP_REG3               0x3C    /* Zero_Flag_Reg3 60 */
-#define ZLP_REG4               0x3D    /* Zero_Flag_Reg4 61 */
-#define ZLP_REG5               0x3E    /* Zero_Flag_Reg5 62 */
-
-/* Interrupt Rotinue Defines   */
-#define SERIAL_IIR_RLS         0x06
-#define SERIAL_IIR_RDA         0x04
-#define SERIAL_IIR_CTI         0x0c
-#define SERIAL_IIR_THR         0x02
-#define SERIAL_IIR_MS          0x00
-
-/* Emulation of the bit mask on the LINE STATUS REGISTER.  */
-#define SERIAL_LSR_DR          0x0001
-#define SERIAL_LSR_OE          0x0002
-#define SERIAL_LSR_PE          0x0004
-#define SERIAL_LSR_FE          0x0008
-#define SERIAL_LSR_BI          0x0010
-#define SERIAL_LSR_THRE                0x0020
-#define SERIAL_LSR_TEMT                0x0040
-#define SERIAL_LSR_FIFOERR     0x0080
-
-/* MSR bit defines(place holders) */
-#define ATEN_MSR_DELTA_CTS     0x10
-#define ATEN_MSR_DELTA_DSR     0x20
-#define ATEN_MSR_DELTA_RI      0x40
-#define ATEN_MSR_DELTA_CD      0x80
-
-/* Serial Port register Address */
-#define RECEIVE_BUFFER_REGISTER                ((__u16)(0x00))
-#define TRANSMIT_HOLDING_REGISTER      ((__u16)(0x00))
-#define INTERRUPT_ENABLE_REGISTER      ((__u16)(0x01))
-#define INTERRUPT_IDENT_REGISTER       ((__u16)(0x02))
-#define FIFO_CONTROL_REGISTER          ((__u16)(0x02))
-#define LINE_CONTROL_REGISTER          ((__u16)(0x03))
-#define MODEM_CONTROL_REGISTER         ((__u16)(0x04))
-#define LINE_STATUS_REGISTER           ((__u16)(0x05))
-#define MODEM_STATUS_REGISTER          ((__u16)(0x06))
-#define SCRATCH_PAD_REGISTER           ((__u16)(0x07))
-#define DIVISOR_LATCH_LSB              ((__u16)(0x00))
-#define DIVISOR_LATCH_MSB              ((__u16)(0x01))
-
-#define SP1_REGISTER                   ((__u16)(0x00))
-#define CONTROL1_REGISTER              ((__u16)(0x01))
-#define CLK_MULTI_REGISTER             ((__u16)(0x02))
-#define CLK_START_VALUE_REGISTER       ((__u16)(0x03))
-#define DCR1_REGISTER                  ((__u16)(0x04))
-#define GPIO_REGISTER                  ((__u16)(0x07))
-
-#define SERIAL_LCR_DLAB                        ((__u16)(0x0080))
-
-/*
- * URB POOL related defines
- */
-#define NUM_URBS                       16      /* URB Count */
-#define URB_TRANSFER_BUFFER_SIZE       32      /* URB Size  */
-
-#define USB_VENDOR_ID_ATENINTL         0x0557
-#define ATENINTL_DEVICE_ID_2011                0x2011
-#define ATENINTL_DEVICE_ID_7820                0x7820
-
-static struct usb_device_id id_table[] = {
-       { USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_2011) },
-       { USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_7820) },
-       { } /* terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-/* This structure holds all of the local port information */
-struct ATENINTL_port {
-       int             port_num;          /*Actual port number in the device(1,2,etc)*/
-       __u8            bulk_out_endpoint;      /* the bulk out endpoint handle */
-       unsigned char   *bulk_out_buffer;       /* buffer used for the bulk out endpoint */
-       struct urb      *write_urb;             /* write URB for this port */
-       __u8            bulk_in_endpoint;       /* the bulk in endpoint handle */
-       unsigned char   *bulk_in_buffer;        /* the buffer we use for the bulk in endpoint */
-       struct urb      *read_urb;              /* read URB for this port */
-       __u8            shadowLCR;              /* last LCR value received */
-       __u8            shadowMCR;              /* last MCR value received */
-       char            open;
-       char            chaseResponsePending;
-       wait_queue_head_t       wait_chase;             /* for handling sleeping while waiting for chase to finish */
-       wait_queue_head_t       wait_command;           /* for handling sleeping while waiting for command to finish */
-       struct async_icount     icount;
-       struct usb_serial_port  *port;                  /* loop back to the owner of this object */
-       /*Offsets*/
-       __u8            SpRegOffset;
-       __u8            ControlRegOffset;
-       __u8            DcrRegOffset;
-       /* for processing control URBS in interrupt context */
-       struct urb      *control_urb;
-       char            *ctrl_buf;
-       int             MsrLsr;
-
-       struct urb      *write_urb_pool[NUM_URBS];
-       /* we pass a pointer to this as the arguement sent to cypress_set_termios old_termios */
-       struct ktermios tmp_termios;        /* stores the old termios settings */
-       spinlock_t      lock;                   /* private lock */
-};
-
-/* This structure holds all of the individual serial device information */
-struct ATENINTL_serial {
-       __u8            interrupt_in_endpoint;          /* the interrupt endpoint handle */
-       unsigned char   *interrupt_in_buffer;           /* the buffer we use for the interrupt endpoint */
-       struct urb      *interrupt_read_urb;    /* our interrupt urb */
-       __u8            bulk_in_endpoint;       /* the bulk in endpoint handle */
-       unsigned char   *bulk_in_buffer;                /* the buffer we use for the bulk in endpoint */
-       struct urb      *read_urb;              /* our bulk read urb */
-       __u8            bulk_out_endpoint;      /* the bulk out endpoint handle */
-       struct usb_serial       *serial;        /* loop back to the owner of this object */
-       int     ATEN2011_spectrum_2or4ports;    /* this says the number of ports in the device */
-       /* Indicates about the no.of opened ports of an individual USB-serial adapater. */
-       unsigned int    NoOfOpenPorts;
-       /* a flag for Status endpoint polling */
-       unsigned char   status_polling_started;
-};
-
-static void ATEN2011_set_termios(struct tty_struct *tty,
-                                struct usb_serial_port *port,
-                                struct ktermios *old_termios);
-static void ATEN2011_change_port_settings(struct tty_struct *tty,
-                                         struct ATENINTL_port *ATEN2011_port,
-                                         struct ktermios *old_termios);
-
-/*************************************
- * Bit definitions for each register *
- *************************************/
-#define LCR_BITS_5             0x00    /* 5 bits/char */
-#define LCR_BITS_6             0x01    /* 6 bits/char */
-#define LCR_BITS_7             0x02    /* 7 bits/char */
-#define LCR_BITS_8             0x03    /* 8 bits/char */
-#define LCR_BITS_MASK          0x03    /* Mask for bits/char field */
-
-#define LCR_STOP_1             0x00    /* 1 stop bit */
-#define LCR_STOP_1_5           0x04    /* 1.5 stop bits (if 5   bits/char) */
-#define LCR_STOP_2             0x04    /* 2 stop bits   (if 6-8 bits/char) */
-#define LCR_STOP_MASK          0x04    /* Mask for stop bits field */
-
-#define LCR_PAR_NONE           0x00    /* No parity */
-#define LCR_PAR_ODD            0x08    /* Odd parity */
-#define LCR_PAR_EVEN           0x18    /* Even parity */
-#define LCR_PAR_MARK           0x28    /* Force parity bit to 1 */
-#define LCR_PAR_SPACE          0x38    /* Force parity bit to 0 */
-#define LCR_PAR_MASK           0x38    /* Mask for parity field */
-
-#define LCR_SET_BREAK          0x40    /* Set Break condition */
-#define LCR_DL_ENABLE          0x80    /* Enable access to divisor latch */
-
-#define MCR_DTR                        0x01    /* Assert DTR */
-#define MCR_RTS                        0x02    /* Assert RTS */
-#define MCR_OUT1               0x04    /* Loopback only: Sets state of RI */
-#define MCR_MASTER_IE          0x08    /* Enable interrupt outputs */
-#define MCR_LOOPBACK           0x10    /* Set internal (digital) loopback mode */
-#define MCR_XON_ANY            0x20    /* Enable any char to exit XOFF mode */
-
-#define ATEN2011_MSR_CTS       0x10    /* Current state of CTS */
-#define ATEN2011_MSR_DSR       0x20    /* Current state of DSR */
-#define ATEN2011_MSR_RI                0x40    /* Current state of RI */
-#define ATEN2011_MSR_CD                0x80    /* Current state of CD */
-
-
-static int debug;
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "2.0"
-#define DRIVER_DESC "ATENINTL 2011 USB Serial Adapter"
-
-/*
- * Defines used for sending commands to port
- */
-
-#define ATEN_WDR_TIMEOUT       (50)    /* default urb timeout */
-
-/* Requests */
-#define ATEN_RD_RTYPE          0xC0
-#define ATEN_WR_RTYPE          0x40
-#define ATEN_RDREQ             0x0D
-#define ATEN_WRREQ             0x0E
-#define ATEN_CTRL_TIMEOUT      500
-#define VENDOR_READ_LENGTH     (0x01)
-
-/* set to 1 for RS485 mode and 0 for RS232 mode */
-/* FIXME make this somehow dynamic and not build time specific */
-static int RS485mode;
-
-static int set_reg_sync(struct usb_serial_port *port, __u16 reg, __u16 val)
-{
-       struct usb_device *dev = port->serial->dev;
-       val = val & 0x00ff;
-
-       dbg("%s: is %x, value %x", __func__, reg, val);
-
-       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ATEN_WRREQ,
-                              ATEN_WR_RTYPE, val, reg, NULL, 0,
-                              ATEN_WDR_TIMEOUT);
-}
-
-static int get_reg_sync(struct usb_serial_port *port, __u16 reg, __u16 *val)
-{
-       struct usb_device *dev = port->serial->dev;
-       int ret;
-
-       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ATEN_RDREQ,
-                             ATEN_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH,
-                             ATEN_WDR_TIMEOUT);
-       dbg("%s: offset is %x, return val %x", __func__, reg, *val);
-       *val = (*val) & 0x00ff;
-       return ret;
-}
-
-static int set_uart_reg(struct usb_serial_port *port, __u16 reg, __u16 val)
-{
-       struct usb_device *dev = port->serial->dev;
-       struct ATENINTL_serial *a_serial;
-       __u16 minor;
-
-       a_serial = usb_get_serial_data(port->serial);
-       minor = port->serial->minor;
-       if (minor == SERIAL_TTY_NO_MINOR)
-               minor = 0;
-       val = val & 0x00ff;
-
-       /*
-        * For the UART control registers,
-        * the application number need to be Or'ed
-        */
-       if (a_serial->ATEN2011_spectrum_2or4ports == 4)
-               val |= (((__u16)port->number - minor) + 1) << 8;
-       else {
-               if (((__u16) port->number - minor) == 0)
-                       val |= (((__u16)port->number - minor) + 1) << 8;
-               else
-                       val |= (((__u16)port->number - minor) + 2) << 8;
-       }
-       dbg("%s: application number is %x", __func__, val);
-
-       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ATEN_WRREQ,
-                              ATEN_WR_RTYPE, val, reg, NULL, 0,
-                              ATEN_WDR_TIMEOUT);
-}
-
-static int get_uart_reg(struct usb_serial_port *port, __u16 reg, __u16 *val)
-{
-       struct usb_device *dev = port->serial->dev;
-       int ret = 0;
-       __u16 wval;
-       struct ATENINTL_serial *a_serial;
-       __u16 minor = port->serial->minor;
-
-       a_serial = usb_get_serial_data(port->serial);
-       if (minor == SERIAL_TTY_NO_MINOR)
-               minor = 0;
-
-       /* wval is same as application number */
-       if (a_serial->ATEN2011_spectrum_2or4ports == 4)
-               wval = (((__u16)port->number - minor) + 1) << 8;
-       else {
-               if (((__u16) port->number - minor) == 0)
-                       wval = (((__u16) port->number - minor) + 1) << 8;
-               else
-                       wval = (((__u16) port->number - minor) + 2) << 8;
-       }
-       dbg("%s: application number is %x", __func__, wval);
-       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ATEN_RDREQ,
-                             ATEN_RD_RTYPE, wval, reg, val, VENDOR_READ_LENGTH,
-                             ATEN_WDR_TIMEOUT);
-       *val = (*val) & 0x00ff;
-       return ret;
-}
-
-static int handle_newMsr(struct ATENINTL_port *port, __u8 newMsr)
-{
-       struct ATENINTL_port *ATEN2011_port;
-       struct async_icount *icount;
-       ATEN2011_port = port;
-       icount = &ATEN2011_port->icount;
-       if (newMsr &
-           (ATEN_MSR_DELTA_CTS | ATEN_MSR_DELTA_DSR | ATEN_MSR_DELTA_RI |
-            ATEN_MSR_DELTA_CD)) {
-               icount = &ATEN2011_port->icount;
-
-               /* update input line counters */
-               if (newMsr & ATEN_MSR_DELTA_CTS)
-                       icount->cts++;
-               if (newMsr & ATEN_MSR_DELTA_DSR)
-                       icount->dsr++;
-               if (newMsr & ATEN_MSR_DELTA_CD)
-                       icount->dcd++;
-               if (newMsr & ATEN_MSR_DELTA_RI)
-                       icount->rng++;
-       }
-
-       return 0;
-}
-
-static int handle_newLsr(struct ATENINTL_port *port, __u8 newLsr)
-{
-       struct async_icount *icount;
-
-       dbg("%s - %02x", __func__, newLsr);
-
-       if (newLsr & SERIAL_LSR_BI) {
-               /*
-                * Parity and Framing errors only count if they occur exclusive
-                * of a break being received.
-                */
-               newLsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI);
-       }
-
-       /* update input line counters */
-       icount = &port->icount;
-       if (newLsr & SERIAL_LSR_BI)
-               icount->brk++;
-       if (newLsr & SERIAL_LSR_OE)
-               icount->overrun++;
-       if (newLsr & SERIAL_LSR_PE)
-               icount->parity++;
-       if (newLsr & SERIAL_LSR_FE)
-               icount->frame++;
-
-       return 0;
-}
-
-static void ATEN2011_control_callback(struct urb *urb)
-{
-       unsigned char *data;
-       struct ATENINTL_port *ATEN2011_port;
-       __u8 regval = 0x0;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __func__,
-                   urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __func__,
-                   urb->status);
-               goto exit;
-       }
-
-       ATEN2011_port = (struct ATENINTL_port *)urb->context;
-
-       dbg("%s urb buffer size is %d", __func__, urb->actual_length);
-       dbg("%s ATEN2011_port->MsrLsr is %d port %d", __func__,
-               ATEN2011_port->MsrLsr, ATEN2011_port->port_num);
-       data = urb->transfer_buffer;
-       regval = (__u8) data[0];
-       dbg("%s data is %x", __func__, regval);
-       if (ATEN2011_port->MsrLsr == 0)
-               handle_newMsr(ATEN2011_port, regval);
-       else if (ATEN2011_port->MsrLsr == 1)
-               handle_newLsr(ATEN2011_port, regval);
-
-exit:
-       return;
-}
-
-static int ATEN2011_get_reg(struct ATENINTL_port *ATEN, __u16 Wval, __u16 reg,
-                           __u16 *val)
-{
-       struct usb_device *dev = ATEN->port->serial->dev;
-       struct usb_ctrlrequest *dr = NULL;
-       unsigned char *buffer = NULL;
-       int ret = 0;
-       buffer = (__u8 *) ATEN->ctrl_buf;
-
-       dr = (void *)(buffer + 2);
-       dr->bRequestType = ATEN_RD_RTYPE;
-       dr->bRequest = ATEN_RDREQ;
-       dr->wValue = cpu_to_le16(Wval);
-       dr->wIndex = cpu_to_le16(reg);
-       dr->wLength = cpu_to_le16(2);
-
-       usb_fill_control_urb(ATEN->control_urb, dev, usb_rcvctrlpipe(dev, 0),
-                            (unsigned char *)dr, buffer, 2,
-                            ATEN2011_control_callback, ATEN);
-       ATEN->control_urb->transfer_buffer_length = 2;
-       ret = usb_submit_urb(ATEN->control_urb, GFP_ATOMIC);
-       return ret;
-}
-
-static void ATEN2011_interrupt_callback(struct urb *urb)
-{
-       int result;
-       int length;
-       struct ATENINTL_port *ATEN2011_port;
-       struct ATENINTL_serial *ATEN2011_serial;
-       struct usb_serial *serial;
-       __u16 Data;
-       unsigned char *data;
-       __u8 sp[5], st;
-       int i;
-       __u16 wval;
-       int minor;
-
-       dbg("%s", " : Entering");
-
-       ATEN2011_serial = (struct ATENINTL_serial *)urb->context;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __func__,
-                   urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __func__,
-                   urb->status);
-               goto exit;
-       }
-       length = urb->actual_length;
-       data = urb->transfer_buffer;
-
-       serial = ATEN2011_serial->serial;
-
-       /* ATENINTL get 5 bytes
-        * Byte 1 IIR Port 1 (port.number is 0)
-        * Byte 2 IIR Port 2 (port.number is 1)
-        * Byte 3 IIR Port 3 (port.number is 2)
-        * Byte 4 IIR Port 4 (port.number is 3)
-        * Byte 5 FIFO status for both */
-
-       if (length && length > 5) {
-               dbg("%s", "Wrong data !!!");
-               return;
-       }
-
-       /* MATRIX */
-       if (ATEN2011_serial->ATEN2011_spectrum_2or4ports == 4) {
-               sp[0] = (__u8) data[0];
-               sp[1] = (__u8) data[1];
-               sp[2] = (__u8) data[2];
-               sp[3] = (__u8) data[3];
-               st = (__u8) data[4];
-       } else {
-               sp[0] = (__u8) data[0];
-               sp[1] = (__u8) data[2];
-               /* sp[2]=(__u8)data[2]; */
-               /* sp[3]=(__u8)data[3]; */
-               st = (__u8) data[4];
-
-       }
-       for (i = 0; i < serial->num_ports; i++) {
-               ATEN2011_port = usb_get_serial_port_data(serial->port[i]);
-               minor = serial->minor;
-               if (minor == SERIAL_TTY_NO_MINOR)
-                       minor = 0;
-               if ((ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2)
-                   && (i != 0))
-                       wval =
-                           (((__u16) serial->port[i]->number -
-                             (__u16) (minor)) + 2) << 8;
-               else
-                       wval =
-                           (((__u16) serial->port[i]->number -
-                             (__u16) (minor)) + 1) << 8;
-               if (ATEN2011_port->open != 0) {
-                       if (sp[i] & 0x01) {
-                               dbg("SP%d No Interrupt !!!", i);
-                       } else {
-                               switch (sp[i] & 0x0f) {
-                               case SERIAL_IIR_RLS:
-                                       dbg("Serial Port %d: Receiver status error or address bit detected in 9-bit mode", i);
-                                       ATEN2011_port->MsrLsr = 1;
-                                       ATEN2011_get_reg(ATEN2011_port, wval,
-                                                        LINE_STATUS_REGISTER,
-                                                        &Data);
-                                       break;
-                               case SERIAL_IIR_MS:
-                                       dbg("Serial Port %d: Modem status change", i);
-                                       ATEN2011_port->MsrLsr = 0;
-                                       ATEN2011_get_reg(ATEN2011_port, wval,
-                                                        MODEM_STATUS_REGISTER,
-                                                        &Data);
-                                       break;
-                               }
-                       }
-               }
-
-       }
-exit:
-       if (ATEN2011_serial->status_polling_started == 0)
-               return;
-
-       result = usb_submit_urb(urb, GFP_ATOMIC);
-       if (result) {
-               dev_err(&urb->dev->dev,
-                       "%s - Error %d submitting interrupt urb\n",
-                       __func__, result);
-       }
-
-       return;
-}
-
-static void ATEN2011_bulk_in_callback(struct urb *urb)
-{
-       int status;
-       unsigned char *data;
-       struct usb_serial *serial;
-       struct usb_serial_port *port;
-       struct ATENINTL_serial *ATEN2011_serial;
-       struct ATENINTL_port *ATEN2011_port;
-       struct tty_struct *tty;
-
-       if (urb->status) {
-               dbg("nonzero read bulk status received: %d", urb->status);
-               return;
-       }
-
-       ATEN2011_port = (struct ATENINTL_port *)urb->context;
-
-       port = (struct usb_serial_port *)ATEN2011_port->port;
-       serial = port->serial;
-
-       dbg("%s", "Entering...");
-
-       data = urb->transfer_buffer;
-       ATEN2011_serial = usb_get_serial_data(serial);
-
-       if (urb->actual_length) {
-               tty = tty_port_tty_get(&ATEN2011_port->port->port);
-               if (tty) {
-                       tty_buffer_request_room(tty, urb->actual_length);
-                       tty_insert_flip_string(tty, data, urb->actual_length);
-                       tty_flip_buffer_push(tty);
-                       tty_kref_put(tty);
-               }
-
-               ATEN2011_port->icount.rx += urb->actual_length;
-               dbg("ATEN2011_port->icount.rx is %d:",
-                       ATEN2011_port->icount.rx);
-       }
-
-       if (!ATEN2011_port->read_urb) {
-               dbg("%s", "URB KILLED !!!");
-               return;
-       }
-
-       if (ATEN2011_port->read_urb->status != -EINPROGRESS) {
-               ATEN2011_port->read_urb->dev = serial->dev;
-
-               status = usb_submit_urb(ATEN2011_port->read_urb, GFP_ATOMIC);
-               if (status)
-                       dbg("usb_submit_urb(read bulk) failed, status = %d", status);
-       }
-}
-
-static void ATEN2011_bulk_out_data_callback(struct urb *urb)
-{
-       struct ATENINTL_port *ATEN2011_port;
-       struct tty_struct *tty;
-
-       if (urb->status) {
-               dbg("nonzero write bulk status received:%d", urb->status);
-               return;
-       }
-
-       ATEN2011_port = (struct ATENINTL_port *)urb->context;
-
-       dbg("%s", "Entering .........");
-
-       tty = tty_port_tty_get(&ATEN2011_port->port->port);
-
-       if (tty && ATEN2011_port->open)
-               /* tell the tty driver that something has changed */
-               tty_wakeup(tty);
-
-       /* schedule_work(&ATEN2011_port->port->work); */
-       tty_kref_put(tty);
-
-}
-
-#ifdef ATENSerialProbe
-static int ATEN2011_serial_probe(struct usb_serial *serial,
-                                const struct usb_device_id *id)
-{
-
-       /*need to implement the mode_reg reading and updating\
-          structures usb_serial_ device_type\
-          (i.e num_ports, num_bulkin,bulkout etc) */
-       /* Also we can update the changes  attach */
-       return 1;
-}
-#endif
-
-static int ATEN2011_open(struct tty_struct *tty, struct usb_serial_port *port,
-                        struct file *filp)
-{
-       int response;
-       int j;
-       struct usb_serial *serial;
-       struct urb *urb;
-       __u16 Data;
-       int status;
-       struct ATENINTL_serial *ATEN2011_serial;
-       struct ATENINTL_port *ATEN2011_port;
-       struct ktermios tmp_termios;
-       int minor;
-
-       serial = port->serial;
-
-       ATEN2011_port = usb_get_serial_port_data(port);
-
-       if (ATEN2011_port == NULL)
-               return -ENODEV;
-
-       ATEN2011_serial = usb_get_serial_data(serial);
-       if (ATEN2011_serial == NULL)
-               return -ENODEV;
-
-       /* increment the number of opened ports counter here */
-       ATEN2011_serial->NoOfOpenPorts++;
-
-       usb_clear_halt(serial->dev, port->write_urb->pipe);
-       usb_clear_halt(serial->dev, port->read_urb->pipe);
-
-       /* Initialising the write urb pool */
-       for (j = 0; j < NUM_URBS; ++j) {
-               urb = usb_alloc_urb(0, GFP_ATOMIC);
-               ATEN2011_port->write_urb_pool[j] = urb;
-
-               if (urb == NULL) {
-                       err("No more urbs???");
-                       continue;
-               }
-
-               urb->transfer_buffer = NULL;
-               urb->transfer_buffer =
-                   kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
-               if (!urb->transfer_buffer) {
-                       err("%s-out of memory for urb buffers.", __func__);
-                       continue;
-               }
-       }
-
-/*****************************************************************************
- * Initialize ATEN2011 -- Write Init values to corresponding Registers
- *
- * Register Index
- * 1 : IER
- * 2 : FCR
- * 3 : LCR
- * 4 : MCR
- *
- * 0x08 : SP1/2 Control Reg
- *****************************************************************************/
-
-/* NEED to check the fallowing Block */
-
-       Data = 0x0;
-       status = get_reg_sync(port, ATEN2011_port->SpRegOffset, &Data);
-       if (status < 0) {
-               dbg("Reading Spreg failed");
-               return -1;
-       }
-       Data |= 0x80;
-       status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data);
-       if (status < 0) {
-               dbg("writing Spreg failed");
-               return -1;
-       }
-
-       Data &= ~0x80;
-       status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data);
-       if (status < 0) {
-               dbg("writing Spreg failed");
-               return -1;
-       }
-
-/* End of block to be checked */
-/**************************CHECK***************************/
-
-       if (RS485mode == 0)
-               Data = 0xC0;
-       else
-               Data = 0x00;
-       status = set_uart_reg(port, SCRATCH_PAD_REGISTER, Data);
-       if (status < 0) {
-               dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x", status);
-               return -1;
-       } else
-               dbg("SCRATCH_PAD_REGISTER Writing success status%d", status);
-
-/**************************CHECK***************************/
-
-       Data = 0x0;
-       status = get_reg_sync(port, ATEN2011_port->ControlRegOffset, &Data);
-       if (status < 0) {
-               dbg("Reading Controlreg failed");
-               return -1;
-       }
-       Data |= 0x08;           /* Driver done bit */
-       Data |= 0x20;           /* rx_disable */
-       status = 0;
-       status =
-           set_reg_sync(port, ATEN2011_port->ControlRegOffset, Data);
-       if (status < 0) {
-               dbg("writing Controlreg failed");
-               return -1;
-       }
-       /*
-        * do register settings here
-        * Set all regs to the device default values.
-        * First Disable all interrupts.
-        */
-
-       Data = 0x00;
-       status = set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
-       if (status < 0) {
-               dbg("disableing interrupts failed");
-               return -1;
-       }
-       /* Set FIFO_CONTROL_REGISTER to the default value */
-       Data = 0x00;
-       status = set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
-       if (status < 0) {
-               dbg("Writing FIFO_CONTROL_REGISTER  failed");
-               return -1;
-       }
-
-       Data = 0xcf;            /* chk */
-       status = set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
-       if (status < 0) {
-               dbg("Writing FIFO_CONTROL_REGISTER  failed");
-               return -1;
-       }
-
-       Data = 0x03;            /* LCR_BITS_8 */
-       status = set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
-       ATEN2011_port->shadowLCR = Data;
-
-       Data = 0x0b;            /* MCR_DTR|MCR_RTS|MCR_MASTER_IE */
-       status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
-       ATEN2011_port->shadowMCR = Data;
-
-#ifdef Check
-       Data = 0x00;
-       status = get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
-       ATEN2011_port->shadowLCR = Data;
-
-       Data |= SERIAL_LCR_DLAB;        /* data latch enable in LCR 0x80 */
-       status = set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
-
-       Data = 0x0c;
-       status = set_uart_reg(port, DIVISOR_LATCH_LSB, Data);
-
-       Data = 0x0;
-       status = set_uart_reg(port, DIVISOR_LATCH_MSB, Data);
-
-       Data = 0x00;
-       status = get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
-
-/*      Data = ATEN2011_port->shadowLCR; */    /* data latch disable */
-       Data = Data & ~SERIAL_LCR_DLAB;
-       status = set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
-       ATEN2011_port->shadowLCR = Data;
-#endif
-       /* clearing Bulkin and Bulkout Fifo */
-       Data = 0x0;
-       status = get_reg_sync(port, ATEN2011_port->SpRegOffset, &Data);
-
-       Data = Data | 0x0c;
-       status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data);
-
-       Data = Data & ~0x0c;
-       status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data);
-       /* Finally enable all interrupts */
-       Data = 0x0;
-       Data = 0x0c;
-       status = set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
-
-       /* clearing rx_disable */
-       Data = 0x0;
-       status = get_reg_sync(port, ATEN2011_port->ControlRegOffset, &Data);
-       Data = Data & ~0x20;
-       status = set_reg_sync(port, ATEN2011_port->ControlRegOffset, Data);
-
-       /* rx_negate */
-       Data = 0x0;
-       status = get_reg_sync(port, ATEN2011_port->ControlRegOffset, &Data);
-       Data = Data | 0x10;
-       status = 0;
-       status = set_reg_sync(port, ATEN2011_port->ControlRegOffset, Data);
-
-       /*
-        * Check to see if we've set up our endpoint info yet
-        * (can't set it up in ATEN2011_startup as the structures
-        * were not set up at that time.)
-        */
-       if (ATEN2011_serial->NoOfOpenPorts == 1) {
-               /* start the status polling here */
-               ATEN2011_serial->status_polling_started = 1;
-               /* If not yet set, Set here */
-               ATEN2011_serial->interrupt_in_buffer =
-                   serial->port[0]->interrupt_in_buffer;
-               ATEN2011_serial->interrupt_in_endpoint =
-                   serial->port[0]->interrupt_in_endpointAddress;
-               ATEN2011_serial->interrupt_read_urb =
-                   serial->port[0]->interrupt_in_urb;
-
-               /* set up interrupt urb */
-               usb_fill_int_urb(ATEN2011_serial->interrupt_read_urb,
-                                serial->dev,
-                                usb_rcvintpipe(serial->dev,
-                                               ATEN2011_serial->
-                                               interrupt_in_endpoint),
-                                ATEN2011_serial->interrupt_in_buffer,
-                                ATEN2011_serial->interrupt_read_urb->
-                                transfer_buffer_length,
-                                ATEN2011_interrupt_callback, ATEN2011_serial,
-                                ATEN2011_serial->interrupt_read_urb->interval);
-
-               /* start interrupt read for ATEN2011               *
-                * will continue as long as ATEN2011 is connected  */
-
-               response =
-                   usb_submit_urb(ATEN2011_serial->interrupt_read_urb,
-                                  GFP_KERNEL);
-               if (response) {
-                       dbg("%s - Error %d submitting interrupt urb",
-                               __func__, response);
-               }
-
-       }
-
-       /*
-        * See if we've set up our endpoint info yet
-        * (can't set it up in ATEN2011_startup as the
-        * structures were not set up at that time.)
-        */
-
-       dbg("port number is %d", port->number);
-       dbg("serial number is %d", port->serial->minor);
-       dbg("Bulkin endpoint is %d", port->bulk_in_endpointAddress);
-       dbg("BulkOut endpoint is %d", port->bulk_out_endpointAddress);
-       dbg("Interrupt endpoint is %d",
-               port->interrupt_in_endpointAddress);
-       dbg("port's number in the device is %d", ATEN2011_port->port_num);
-       ATEN2011_port->bulk_in_buffer = port->bulk_in_buffer;
-       ATEN2011_port->bulk_in_endpoint = port->bulk_in_endpointAddress;
-       ATEN2011_port->read_urb = port->read_urb;
-       ATEN2011_port->bulk_out_endpoint = port->bulk_out_endpointAddress;
-
-       minor = port->serial->minor;
-       if (minor == SERIAL_TTY_NO_MINOR)
-               minor = 0;
-
-       /* set up our bulk in urb */
-       if ((ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2)
-           && (((__u16) port->number - (__u16) (minor)) != 0)) {
-               usb_fill_bulk_urb(ATEN2011_port->read_urb, serial->dev,
-                                 usb_rcvbulkpipe(serial->dev,
-                                                 (port->
-                                                  bulk_in_endpointAddress +
-                                                  2)), port->bulk_in_buffer,
-                                 ATEN2011_port->read_urb->
-                                 transfer_buffer_length,
-                                 ATEN2011_bulk_in_callback, ATEN2011_port);
-       } else
-               usb_fill_bulk_urb(ATEN2011_port->read_urb,
-                                 serial->dev,
-                                 usb_rcvbulkpipe(serial->dev,
-                                                 port->
-                                                 bulk_in_endpointAddress),
-                                 port->bulk_in_buffer,
-                                 ATEN2011_port->read_urb->
-                                 transfer_buffer_length,
-                                 ATEN2011_bulk_in_callback, ATEN2011_port);
-
-       dbg("ATEN2011_open: bulkin endpoint is %d",
-               port->bulk_in_endpointAddress);
-       response = usb_submit_urb(ATEN2011_port->read_urb, GFP_KERNEL);
-       if (response) {
-               err("%s - Error %d submitting control urb", __func__,
-                   response);
-       }
-
-       /* initialize our wait queues */
-       init_waitqueue_head(&ATEN2011_port->wait_chase);
-       init_waitqueue_head(&ATEN2011_port->wait_command);
-
-       /* initialize our icount structure */
-       memset(&(ATEN2011_port->icount), 0x00, sizeof(ATEN2011_port->icount));
-
-       /* initialize our port settings */
-       ATEN2011_port->shadowMCR = MCR_MASTER_IE;       /* Must set to enable ints! */
-       ATEN2011_port->chaseResponsePending = 0;
-       /* send a open port command */
-       ATEN2011_port->open = 1;
-       /* ATEN2011_change_port_settings(ATEN2011_port,old_termios); */
-       /* Setup termios */
-       ATEN2011_set_termios(tty, port, &tmp_termios);
-       ATEN2011_port->icount.tx = 0;
-       ATEN2011_port->icount.rx = 0;
-
-       dbg("usb_serial serial:%x       ATEN2011_port:%x\nATEN2011_serial:%x      usb_serial_port port:%x",
-            (unsigned int)serial, (unsigned int)ATEN2011_port,
-            (unsigned int)ATEN2011_serial, (unsigned int)port);
-
-       return 0;
-
-}
-
-static int ATEN2011_chars_in_buffer(struct tty_struct *tty)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       int i;
-       int chars = 0;
-       struct ATENINTL_port *ATEN2011_port;
-
-       /* dbg("%s"," ATEN2011_chars_in_buffer:entering ..........."); */
-
-       ATEN2011_port = usb_get_serial_port_data(port);
-       if (ATEN2011_port == NULL) {
-               dbg("%s", "ATEN2011_break:leaving ...........");
-               return -1;
-       }
-
-       for (i = 0; i < NUM_URBS; ++i)
-               if (ATEN2011_port->write_urb_pool[i]->status == -EINPROGRESS)
-                       chars += URB_TRANSFER_BUFFER_SIZE;
-
-       dbg("%s - returns %d", __func__, chars);
-       return chars;
-
-}
-
-static void ATEN2011_block_until_tx_empty(struct tty_struct *tty,
-                                         struct ATENINTL_port *ATEN2011_port)
-{
-       int timeout = HZ / 10;
-       int wait = 30;
-       int count;
-
-       while (1) {
-               count = ATEN2011_chars_in_buffer(tty);
-
-               /* Check for Buffer status */
-               if (count <= 0)
-                       return;
-
-               /* Block the thread for a while */
-               interruptible_sleep_on_timeout(&ATEN2011_port->wait_chase,
-                                              timeout);
-
-               /* No activity.. count down section */
-               wait--;
-               if (wait == 0) {
-                       dbg("%s - TIMEOUT", __func__);
-                       return;
-               } else {
-                       /* Reset timout value back to seconds */
-                       wait = 30;
-               }
-       }
-}
-
-static void ATEN2011_close(struct tty_struct *tty, struct usb_serial_port *port,
-                          struct file *filp)
-{
-       struct usb_serial *serial;
-       struct ATENINTL_serial *ATEN2011_serial;
-       struct ATENINTL_port *ATEN2011_port;
-       int no_urbs;
-       __u16 Data;
-
-       dbg("%s", "ATEN2011_close:entering...");
-       serial = port->serial;
-
-       /* take the Adpater and port's private data */
-       ATEN2011_serial = usb_get_serial_data(serial);
-       ATEN2011_port = usb_get_serial_port_data(port);
-       if ((ATEN2011_serial == NULL) || (ATEN2011_port == NULL))
-               return;
-
-       if (serial->dev) {
-               /* flush and block(wait) until tx is empty */
-               ATEN2011_block_until_tx_empty(tty, ATEN2011_port);
-       }
-       /* kill the ports URB's */
-       for (no_urbs = 0; no_urbs < NUM_URBS; no_urbs++)
-               usb_kill_urb(ATEN2011_port->write_urb_pool[no_urbs]);
-       /* Freeing Write URBs */
-       for (no_urbs = 0; no_urbs < NUM_URBS; ++no_urbs) {
-               kfree(ATEN2011_port->write_urb_pool[no_urbs]->transfer_buffer);
-               usb_free_urb(ATEN2011_port->write_urb_pool[no_urbs]);
-       }
-       /* While closing port, shutdown all bulk read, write  *
-        * and interrupt read if they exists                  */
-       if (serial->dev) {
-               if (ATEN2011_port->write_urb) {
-                       dbg("%s", "Shutdown bulk write");
-                       usb_kill_urb(ATEN2011_port->write_urb);
-               }
-               if (ATEN2011_port->read_urb) {
-                       dbg("%s", "Shutdown bulk read");
-                       usb_kill_urb(ATEN2011_port->read_urb);
-               }
-               if ((&ATEN2011_port->control_urb)) {
-                       dbg("%s", "Shutdown control read");
-                       /* usb_kill_urb (ATEN2011_port->control_urb); */
-
-               }
-       }
-       /* if(ATEN2011_port->ctrl_buf != NULL) */
-               /* kfree(ATEN2011_port->ctrl_buf); */
-       /* decrement the no.of open ports counter of an individual USB-serial adapter. */
-       ATEN2011_serial->NoOfOpenPorts--;
-       dbg("NoOfOpenPorts in close%d:in port%d",
-               ATEN2011_serial->NoOfOpenPorts, port->number);
-       if (ATEN2011_serial->NoOfOpenPorts == 0) {
-               /* stop the stus polling here */
-               ATEN2011_serial->status_polling_started = 0;
-               if (ATEN2011_serial->interrupt_read_urb) {
-                       dbg("%s", "Shutdown interrupt_read_urb");
-                       /* ATEN2011_serial->interrupt_in_buffer=NULL; */
-                       /* usb_kill_urb (ATEN2011_serial->interrupt_read_urb); */
-               }
-       }
-       if (ATEN2011_port->write_urb) {
-               /* if this urb had a transfer buffer already (old tx) free it */
-               kfree(ATEN2011_port->write_urb->transfer_buffer);
-               usb_free_urb(ATEN2011_port->write_urb);
-       }
-
-       /* clear the MCR & IER */
-       Data = 0x00;
-       set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
-       Data = 0x00;
-       set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
-
-       ATEN2011_port->open = 0;
-       dbg("%s", "Leaving ............");
-
-}
-
-static void ATEN2011_block_until_chase_response(struct tty_struct *tty,
-                                               struct ATENINTL_port
-                                               *ATEN2011_port)
-{
-       int timeout = 1 * HZ;
-       int wait = 10;
-       int count;
-
-       while (1) {
-               count = ATEN2011_chars_in_buffer(tty);
-
-               /* Check for Buffer status */
-               if (count <= 0) {
-                       ATEN2011_port->chaseResponsePending = 0;
-                       return;
-               }
-
-               /* Block the thread for a while */
-               interruptible_sleep_on_timeout(&ATEN2011_port->wait_chase,
-                                              timeout);
-               /* No activity.. count down section */
-               wait--;
-               if (wait == 0) {
-                       dbg("%s - TIMEOUT", __func__);
-                       return;
-               } else {
-                       /* Reset timout value back to seconds */
-                       wait = 10;
-               }
-       }
-
-}
-
-static void ATEN2011_break(struct tty_struct *tty, int break_state)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       unsigned char data;
-       struct usb_serial *serial;
-       struct ATENINTL_serial *ATEN2011_serial;
-       struct ATENINTL_port *ATEN2011_port;
-
-       dbg("%s", "Entering ...........");
-       dbg("ATEN2011_break: Start");
-
-       serial = port->serial;
-
-       ATEN2011_serial = usb_get_serial_data(serial);
-       ATEN2011_port = usb_get_serial_port_data(port);
-
-       if ((ATEN2011_serial == NULL) || (ATEN2011_port == NULL))
-               return;
-
-       /* flush and chase */
-       ATEN2011_port->chaseResponsePending = 1;
-
-       if (serial->dev) {
-               /* flush and block until tx is empty */
-               ATEN2011_block_until_chase_response(tty, ATEN2011_port);
-       }
-
-       if (break_state == -1)
-               data = ATEN2011_port->shadowLCR | LCR_SET_BREAK;
-       else
-               data = ATEN2011_port->shadowLCR & ~LCR_SET_BREAK;
-
-       ATEN2011_port->shadowLCR = data;
-       dbg("ATEN2011_break ATEN2011_port->shadowLCR is %x",
-               ATEN2011_port->shadowLCR);
-       set_uart_reg(port, LINE_CONTROL_REGISTER, ATEN2011_port->shadowLCR);
-
-       return;
-}
-
-static int ATEN2011_write_room(struct tty_struct *tty)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       int i;
-       int room = 0;
-       struct ATENINTL_port *ATEN2011_port;
-
-       ATEN2011_port = usb_get_serial_port_data(port);
-       if (ATEN2011_port == NULL) {
-               dbg("%s", "ATEN2011_break:leaving ...........");
-               return -1;
-       }
-
-       for (i = 0; i < NUM_URBS; ++i)
-               if (ATEN2011_port->write_urb_pool[i]->status != -EINPROGRESS)
-                       room += URB_TRANSFER_BUFFER_SIZE;
-
-       dbg("%s - returns %d", __func__, room);
-       return room;
-
-}
-
-static int ATEN2011_write(struct tty_struct *tty, struct usb_serial_port *port,
-                         const unsigned char *data, int count)
-{
-       int status;
-       int i;
-       int bytes_sent = 0;
-       int transfer_size;
-       int minor;
-
-       struct ATENINTL_port *ATEN2011_port;
-       struct usb_serial *serial;
-       struct ATENINTL_serial *ATEN2011_serial;
-       struct urb *urb;
-       const unsigned char *current_position = data;
-       unsigned char *data1;
-       dbg("%s", "entering ...........");
-
-       serial = port->serial;
-
-       ATEN2011_port = usb_get_serial_port_data(port);
-       if (ATEN2011_port == NULL) {
-               dbg("%s", "ATEN2011_port is NULL");
-               return -1;
-       }
-
-       ATEN2011_serial = usb_get_serial_data(serial);
-       if (ATEN2011_serial == NULL) {
-               dbg("%s", "ATEN2011_serial is NULL");
-               return -1;
-       }
-
-       /* try to find a free urb in the list */
-       urb = NULL;
-
-       for (i = 0; i < NUM_URBS; ++i) {
-               if (ATEN2011_port->write_urb_pool[i]->status != -EINPROGRESS) {
-                       urb = ATEN2011_port->write_urb_pool[i];
-                       dbg("URB:%d", i);
-                       break;
-               }
-       }
-
-       if (urb == NULL) {
-               dbg("%s - no more free urbs", __func__);
-               goto exit;
-       }
-
-       if (urb->transfer_buffer == NULL) {
-               urb->transfer_buffer =
-                   kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
-
-               if (urb->transfer_buffer == NULL) {
-                       err("%s no more kernel memory...", __func__);
-                       goto exit;
-               }
-       }
-       transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
-
-       memcpy(urb->transfer_buffer, current_position, transfer_size);
-       /* usb_serial_debug_data (__FILE__, __func__, transfer_size, urb->transfer_buffer); */
-
-       /* fill urb with data and submit  */
-       minor = port->serial->minor;
-       if (minor == SERIAL_TTY_NO_MINOR)
-               minor = 0;
-       if ((ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2)
-           && (((__u16) port->number - (__u16) (minor)) != 0)) {
-               usb_fill_bulk_urb(urb, ATEN2011_serial->serial->dev,
-                                 usb_sndbulkpipe(ATEN2011_serial->serial->dev,
-                                                 (port->
-                                                  bulk_out_endpointAddress) +
-                                                 2), urb->transfer_buffer,
-                                 transfer_size,
-                                 ATEN2011_bulk_out_data_callback,
-                                 ATEN2011_port);
-       } else
-
-               usb_fill_bulk_urb(urb,
-                                 ATEN2011_serial->serial->dev,
-                                 usb_sndbulkpipe(ATEN2011_serial->serial->dev,
-                                                 port->
-                                                 bulk_out_endpointAddress),
-                                 urb->transfer_buffer, transfer_size,
-                                 ATEN2011_bulk_out_data_callback,
-                                 ATEN2011_port);
-
-       data1 = urb->transfer_buffer;
-       dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress);
-       /* for(i=0;i < urb->actual_length;i++) */
-               /* dbg("Data is %c ",data1[i]); */
-
-       /* send it down the pipe */
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-
-       if (status) {
-               err("%s - usb_submit_urb(write bulk) failed with status = %d",
-                   __func__, status);
-               bytes_sent = status;
-               goto exit;
-       }
-       bytes_sent = transfer_size;
-       ATEN2011_port->icount.tx += transfer_size;
-       dbg("ATEN2011_port->icount.tx is %d:", ATEN2011_port->icount.tx);
-
-exit:
-       return bytes_sent;
-}
-
-static void ATEN2011_throttle(struct tty_struct *tty)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct ATENINTL_port *ATEN2011_port;
-       int status;
-
-       dbg("- port %d", port->number);
-
-       ATEN2011_port = usb_get_serial_port_data(port);
-
-       if (ATEN2011_port == NULL)
-               return;
-
-       if (!ATEN2011_port->open) {
-               dbg("%s", "port not opened");
-               return;
-       }
-
-       dbg("%s", "Entering .......... ");
-
-       if (!tty) {
-               dbg("%s - no tty available", __func__);
-               return;
-       }
-
-       /* if we are implementing XON/XOFF, send the stop character */
-       if (I_IXOFF(tty)) {
-               unsigned char stop_char = STOP_CHAR(tty);
-               status = ATEN2011_write(tty, port, &stop_char, 1);
-               if (status <= 0)
-                       return;
-       }
-
-       /* if we are implementing RTS/CTS, toggle that line */
-       if (tty->termios->c_cflag & CRTSCTS) {
-               ATEN2011_port->shadowMCR &= ~MCR_RTS;
-               status = set_uart_reg(port, MODEM_CONTROL_REGISTER,
-                                     ATEN2011_port->shadowMCR);
-               if (status < 0)
-                       return;
-       }
-
-       return;
-}
-
-static void ATEN2011_unthrottle(struct tty_struct *tty)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       int status;
-       struct ATENINTL_port *ATEN2011_port = usb_get_serial_port_data(port);
-
-       if (ATEN2011_port == NULL)
-               return;
-
-       if (!ATEN2011_port->open) {
-               dbg("%s - port not opened", __func__);
-               return;
-       }
-
-       dbg("%s", "Entering .......... ");
-
-       if (!tty) {
-               dbg("%s - no tty available", __func__);
-               return;
-       }
-
-       /* if we are implementing XON/XOFF, send the start character */
-       if (I_IXOFF(tty)) {
-               unsigned char start_char = START_CHAR(tty);
-               status = ATEN2011_write(tty, port, &start_char, 1);
-               if (status <= 0)
-                       return;
-       }
-
-       /* if we are implementing RTS/CTS, toggle that line */
-       if (tty->termios->c_cflag & CRTSCTS) {
-               ATEN2011_port->shadowMCR |= MCR_RTS;
-               status = set_uart_reg(port, MODEM_CONTROL_REGISTER,
-                                     ATEN2011_port->shadowMCR);
-               if (status < 0)
-                       return;
-       }
-
-       return;
-}
-
-static int ATEN2011_tiocmget(struct tty_struct *tty, struct file *file)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct ATENINTL_port *ATEN2011_port;
-       unsigned int result;
-       __u16 msr;
-       __u16 mcr;
-       /* unsigned int mcr; */
-       int status = 0;
-       ATEN2011_port = usb_get_serial_port_data(port);
-
-       dbg("%s - port %d", __func__, port->number);
-
-       if (ATEN2011_port == NULL)
-               return -ENODEV;
-
-       status = get_uart_reg(port, MODEM_STATUS_REGISTER, &msr);
-       status = get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr);
-       /* mcr = ATEN2011_port->shadowMCR; */
-       /* COMMENT2: the Fallowing three line are commented for updating only MSR values */
-       result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)
-           | ((mcr & MCR_RTS) ? TIOCM_RTS : 0)
-           | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0)
-           | ((msr & ATEN2011_MSR_CTS) ? TIOCM_CTS : 0)
-           | ((msr & ATEN2011_MSR_CD) ? TIOCM_CAR : 0)
-           | ((msr & ATEN2011_MSR_RI) ? TIOCM_RI : 0)
-           | ((msr & ATEN2011_MSR_DSR) ? TIOCM_DSR : 0);
-
-       dbg("%s - 0x%04X", __func__, result);
-
-       return result;
-}
-
-static int ATEN2011_tiocmset(struct tty_struct *tty, struct file *file,
-                            unsigned int set, unsigned int clear)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct ATENINTL_port *ATEN2011_port;
-       unsigned int mcr;
-       unsigned int status;
-
-       dbg("%s - port %d", __func__, port->number);
-
-       ATEN2011_port = usb_get_serial_port_data(port);
-
-       if (ATEN2011_port == NULL)
-               return -ENODEV;
-
-       mcr = ATEN2011_port->shadowMCR;
-       if (clear & TIOCM_RTS)
-               mcr &= ~MCR_RTS;
-       if (clear & TIOCM_DTR)
-               mcr &= ~MCR_DTR;
-       if (clear & TIOCM_LOOP)
-               mcr &= ~MCR_LOOPBACK;
-
-       if (set & TIOCM_RTS)
-               mcr |= MCR_RTS;
-       if (set & TIOCM_DTR)
-               mcr |= MCR_DTR;
-       if (set & TIOCM_LOOP)
-               mcr |= MCR_LOOPBACK;
-
-       ATEN2011_port->shadowMCR = mcr;
-
-       status = set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr);
-       if (status < 0) {
-               dbg("setting MODEM_CONTROL_REGISTER Failed");
-               return -1;
-       }
-
-       return 0;
-}
-
-static void ATEN2011_set_termios(struct tty_struct *tty,
-                                struct usb_serial_port *port,
-                                struct ktermios *old_termios)
-{
-       int status;
-       unsigned int cflag;
-       struct usb_serial *serial;
-       struct ATENINTL_port *ATEN2011_port;
-
-       dbg("ATEN2011_set_termios: START");
-
-       serial = port->serial;
-
-       ATEN2011_port = usb_get_serial_port_data(port);
-
-       if (ATEN2011_port == NULL)
-               return;
-
-       if (!ATEN2011_port->open) {
-               dbg("%s - port not opened", __func__);
-               return;
-       }
-
-       dbg("%s", "setting termios - ");
-
-       cflag = tty->termios->c_cflag;
-
-       dbg("%s - cflag %08x iflag %08x", __func__,
-           tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
-
-       if (old_termios) {
-               dbg("%s - old clfag %08x old iflag %08x", __func__,
-                   old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
-       }
-
-       dbg("%s - port %d", __func__, port->number);
-
-       /* change the port settings to the new ones specified */
-
-       ATEN2011_change_port_settings(tty, ATEN2011_port, old_termios);
-
-       if (!ATEN2011_port->read_urb) {
-               dbg("%s", "URB KILLED !!!!!");
-               return;
-       }
-
-       if (ATEN2011_port->read_urb->status != -EINPROGRESS) {
-               ATEN2011_port->read_urb->dev = serial->dev;
-               status = usb_submit_urb(ATEN2011_port->read_urb, GFP_ATOMIC);
-               if (status) {
-                       dbg
-                           (" usb_submit_urb(read bulk) failed, status = %d",
-                            status);
-               }
-       }
-       return;
-}
-
-static int get_lsr_info(struct tty_struct *tty,
-                       struct ATENINTL_port *ATEN2011_port,
-                       unsigned int __user *value)
-{
-       int count;
-       unsigned int result = 0;
-
-       count = ATEN2011_chars_in_buffer(tty);
-       if (count == 0) {
-               dbg("%s -- Empty", __func__);
-               result = TIOCSER_TEMT;
-       }
-
-       if (copy_to_user(value, &result, sizeof(int)))
-               return -EFAULT;
-       return 0;
-}
-
-static int get_number_bytes_avail(struct tty_struct *tty,
-                                 struct ATENINTL_port *ATEN2011_port,
-                                 unsigned int __user *value)
-{
-       unsigned int result = 0;
-
-       if (!tty)
-               return -ENOIOCTLCMD;
-
-       result = tty->read_cnt;
-
-       dbg("%s(%d) = %d", __func__, ATEN2011_port->port->number, result);
-       if (copy_to_user(value, &result, sizeof(int)))
-               return -EFAULT;
-
-       return -ENOIOCTLCMD;
-}
-
-static int set_modem_info(struct ATENINTL_port *ATEN2011_port, unsigned int cmd,
-                         unsigned int __user *value)
-{
-       unsigned int mcr;
-       unsigned int arg;
-       __u16 Data;
-       int status;
-       struct usb_serial_port *port;
-
-       if (ATEN2011_port == NULL)
-               return -1;
-
-       port = (struct usb_serial_port *)ATEN2011_port->port;
-
-       mcr = ATEN2011_port->shadowMCR;
-
-       if (copy_from_user(&arg, value, sizeof(int)))
-               return -EFAULT;
-
-       switch (cmd) {
-       case TIOCMBIS:
-               if (arg & TIOCM_RTS)
-                       mcr |= MCR_RTS;
-               if (arg & TIOCM_DTR)
-                       mcr |= MCR_RTS;
-               if (arg & TIOCM_LOOP)
-                       mcr |= MCR_LOOPBACK;
-               break;
-
-       case TIOCMBIC:
-               if (arg & TIOCM_RTS)
-                       mcr &= ~MCR_RTS;
-               if (arg & TIOCM_DTR)
-                       mcr &= ~MCR_RTS;
-               if (arg & TIOCM_LOOP)
-                       mcr &= ~MCR_LOOPBACK;
-               break;
-
-       case TIOCMSET:
-               /* turn off the RTS and DTR and LOOPBACK
-                * and then only turn on what was asked to */
-               mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK);
-               mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);
-               mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);
-               mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0);
-               break;
-       }
-
-       ATEN2011_port->shadowMCR = mcr;
-
-       Data = ATEN2011_port->shadowMCR;
-       status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
-       if (status < 0) {
-               dbg("setting MODEM_CONTROL_REGISTER Failed");
-               return -1;
-       }
-
-       return 0;
-}
-
-static int get_modem_info(struct ATENINTL_port *ATEN2011_port,
-                         unsigned int __user *value)
-{
-       unsigned int result = 0;
-       __u16 msr;
-       unsigned int mcr = ATEN2011_port->shadowMCR;
-       int status;
-
-       status = get_uart_reg(ATEN2011_port->port, MODEM_STATUS_REGISTER, &msr);
-       result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)      /* 0x002 */
-           |((mcr & MCR_RTS) ? TIOCM_RTS : 0)  /* 0x004 */
-           |((msr & ATEN2011_MSR_CTS) ? TIOCM_CTS : 0) /* 0x020 */
-           |((msr & ATEN2011_MSR_CD) ? TIOCM_CAR : 0)  /* 0x040 */
-           |((msr & ATEN2011_MSR_RI) ? TIOCM_RI : 0)   /* 0x080 */
-           |((msr & ATEN2011_MSR_DSR) ? TIOCM_DSR : 0);        /* 0x100 */
-
-       dbg("%s -- %x", __func__, result);
-
-       if (copy_to_user(value, &result, sizeof(int)))
-               return -EFAULT;
-       return 0;
-}
-
-static int get_serial_info(struct ATENINTL_port *ATEN2011_port,
-                          struct serial_struct __user *retinfo)
-{
-       struct serial_struct tmp;
-
-       if (ATEN2011_port == NULL)
-               return -1;
-
-       if (!retinfo)
-               return -EFAULT;
-
-       memset(&tmp, 0, sizeof(tmp));
-
-       tmp.type = PORT_16550A;
-       tmp.line = ATEN2011_port->port->serial->minor;
-       if (tmp.line == SERIAL_TTY_NO_MINOR)
-               tmp.line = 0;
-       tmp.port = ATEN2011_port->port->number;
-       tmp.irq = 0;
-       tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
-       tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
-       tmp.baud_base = 9600;
-       tmp.close_delay = 5 * HZ;
-       tmp.closing_wait = 30 * HZ;
-
-       if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-               return -EFAULT;
-       return 0;
-}
-
-static int ATEN2011_ioctl(struct tty_struct *tty, struct file *file,
-                         unsigned int cmd, unsigned long arg)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct ATENINTL_port *ATEN2011_port;
-       struct async_icount cnow;
-       struct async_icount cprev;
-       struct serial_icounter_struct icount;
-       int ATENret = 0;
-       unsigned int __user *user_arg = (unsigned int __user *)arg;
-
-       ATEN2011_port = usb_get_serial_port_data(port);
-
-       if (ATEN2011_port == NULL)
-               return -1;
-
-       dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
-
-       switch (cmd) {
-               /* return number of bytes available */
-
-       case TIOCINQ:
-               dbg("%s (%d) TIOCINQ", __func__, port->number);
-               return get_number_bytes_avail(tty, ATEN2011_port, user_arg);
-               break;
-
-       case TIOCOUTQ:
-               dbg("%s (%d) TIOCOUTQ", __func__, port->number);
-               return put_user(ATEN2011_chars_in_buffer(tty), user_arg);
-               break;
-
-       case TIOCSERGETLSR:
-               dbg("%s (%d) TIOCSERGETLSR", __func__, port->number);
-               return get_lsr_info(tty, ATEN2011_port, user_arg);
-               return 0;
-
-       case TIOCMBIS:
-       case TIOCMBIC:
-       case TIOCMSET:
-               dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __func__,
-                   port->number);
-               ATENret = set_modem_info(ATEN2011_port, cmd, user_arg);
-               return ATENret;
-
-       case TIOCMGET:
-               dbg("%s (%d) TIOCMGET", __func__, port->number);
-               return get_modem_info(ATEN2011_port, user_arg);
-
-       case TIOCGSERIAL:
-               dbg("%s (%d) TIOCGSERIAL", __func__, port->number);
-               return get_serial_info(ATEN2011_port,
-                                      (struct serial_struct __user *)arg);
-
-       case TIOCSSERIAL:
-               dbg("%s (%d) TIOCSSERIAL", __func__, port->number);
-               break;
-
-       case TIOCMIWAIT:
-               dbg("%s (%d) TIOCMIWAIT", __func__, port->number);
-               cprev = ATEN2011_port->icount;
-               while (1) {
-                       /* see if a signal did it */
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-                       cnow = ATEN2011_port->icount;
-                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-                               return -EIO;    /* no change => error */
-                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-                           ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
-                           ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-                               return 0;
-                       }
-                       cprev = cnow;
-               }
-               /* NOTREACHED */
-               break;
-
-       case TIOCGICOUNT:
-               cnow = ATEN2011_port->icount;
-               icount.cts = cnow.cts;
-               icount.dsr = cnow.dsr;
-               icount.rng = cnow.rng;
-               icount.dcd = cnow.dcd;
-               icount.rx = cnow.rx;
-               icount.tx = cnow.tx;
-               icount.frame = cnow.frame;
-               icount.overrun = cnow.overrun;
-               icount.parity = cnow.parity;
-               icount.brk = cnow.brk;
-               icount.buf_overrun = cnow.buf_overrun;
-
-               dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__,
-                   port->number, icount.rx, icount.tx);
-               if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
-                       return -EFAULT;
-               return 0;
-
-       default:
-               break;
-       }
-
-       return -ENOIOCTLCMD;
-}
-
-static int ATEN2011_calc_baud_rate_divisor(int baudRate, int *divisor,
-                                          __u16 *clk_sel_val)
-{
-       dbg("%s - %d", __func__, baudRate);
-
-       if (baudRate <= 115200) {
-               *divisor = 115200 / baudRate;
-               *clk_sel_val = 0x0;
-       }
-       if ((baudRate > 115200) && (baudRate <= 230400)) {
-               *divisor = 230400 / baudRate;
-               *clk_sel_val = 0x10;
-       } else if ((baudRate > 230400) && (baudRate <= 403200)) {
-               *divisor = 403200 / baudRate;
-               *clk_sel_val = 0x20;
-       } else if ((baudRate > 403200) && (baudRate <= 460800)) {
-               *divisor = 460800 / baudRate;
-               *clk_sel_val = 0x30;
-       } else if ((baudRate > 460800) && (baudRate <= 806400)) {
-               *divisor = 806400 / baudRate;
-               *clk_sel_val = 0x40;
-       } else if ((baudRate > 806400) && (baudRate <= 921600)) {
-               *divisor = 921600 / baudRate;
-               *clk_sel_val = 0x50;
-       } else if ((baudRate > 921600) && (baudRate <= 1572864)) {
-               *divisor = 1572864 / baudRate;
-               *clk_sel_val = 0x60;
-       } else if ((baudRate > 1572864) && (baudRate <= 3145728)) {
-               *divisor = 3145728 / baudRate;
-               *clk_sel_val = 0x70;
-       }
-       return 0;
-}
-
-static int ATEN2011_send_cmd_write_baud_rate(struct ATENINTL_port
-                                            *ATEN2011_port, int baudRate)
-{
-       int divisor = 0;
-       int status;
-       __u16 Data;
-       unsigned char number;
-       __u16 clk_sel_val;
-       struct usb_serial_port *port;
-       int minor;
-
-       if (ATEN2011_port == NULL)
-               return -1;
-
-       port = (struct usb_serial_port *)ATEN2011_port->port;
-
-       dbg("%s", "Entering .......... ");
-
-       minor = ATEN2011_port->port->serial->minor;
-       if (minor == SERIAL_TTY_NO_MINOR)
-               minor = 0;
-       number = ATEN2011_port->port->number - minor;
-
-       dbg("%s - port = %d, baud = %d", __func__,
-           ATEN2011_port->port->number, baudRate);
-       /* reset clk_uart_sel in spregOffset */
-       if (baudRate > 115200) {
-#ifdef HW_flow_control
-               /*
-                * NOTE: need to see the pther register to modify
-                * setting h/w flow control bit to 1;
-                */
-               /* Data = ATEN2011_port->shadowMCR; */
-               Data = 0x2b;
-               ATEN2011_port->shadowMCR = Data;
-               status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
-               if (status < 0) {
-                       dbg("Writing spreg failed in set_serial_baud");
-                       return -1;
-               }
-#endif
-
-       } else {
-#ifdef HW_flow_control
-               /* setting h/w flow control bit to 0; */
-               /* Data = ATEN2011_port->shadowMCR; */
-               Data = 0xb;
-               ATEN2011_port->shadowMCR = Data;
-               status = set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
-               if (status < 0) {
-                       dbg("Writing spreg failed in set_serial_baud");
-                       return -1;
-               }
-#endif
-
-       }
-
-       if (1)                  /* baudRate <= 115200) */ {
-               clk_sel_val = 0x0;
-               Data = 0x0;
-               status =
-                   ATEN2011_calc_baud_rate_divisor(baudRate, &divisor,
-                                                   &clk_sel_val);
-               status = get_reg_sync(port, ATEN2011_port->SpRegOffset, &Data);
-               if (status < 0) {
-                       dbg("reading spreg failed in set_serial_baud");
-                       return -1;
-               }
-               Data = (Data & 0x8f) | clk_sel_val;
-               status = set_reg_sync(port, ATEN2011_port->SpRegOffset, Data);
-               if (status < 0) {
-                       dbg("Writing spreg failed in set_serial_baud");
-                       return -1;
-               }
-               /* Calculate the Divisor */
-
-               if (status) {
-                       err("%s - bad baud rate", __func__);
-                       dbg("%s", "bad baud rate");
-                       return status;
-               }
-               /* Enable access to divisor latch */
-               Data = ATEN2011_port->shadowLCR | SERIAL_LCR_DLAB;
-               ATEN2011_port->shadowLCR = Data;
-               set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
-
-               /* Write the divisor */
-               Data = (unsigned char)(divisor & 0xff);
-               dbg("set_serial_baud Value to write DLL is %x", Data);
-               set_uart_reg(port, DIVISOR_LATCH_LSB, Data);
-
-               Data = (unsigned char)((divisor & 0xff00) >> 8);
-               dbg("set_serial_baud Value to write DLM is %x", Data);
-               set_uart_reg(port, DIVISOR_LATCH_MSB, Data);
-
-               /* Disable access to divisor latch */
-               Data = ATEN2011_port->shadowLCR & ~SERIAL_LCR_DLAB;
-               ATEN2011_port->shadowLCR = Data;
-               set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
-
-       }
-
-       return status;
-}
-
-static void ATEN2011_change_port_settings(struct tty_struct *tty,
-                                         struct ATENINTL_port *ATEN2011_port,
-                                         struct ktermios *old_termios)
-{
-       int baud;
-       unsigned cflag;
-       unsigned iflag;
-       __u8 lData;
-       __u8 lParity;
-       __u8 lStop;
-       int status;
-       __u16 Data;
-       struct usb_serial_port *port;
-       struct usb_serial *serial;
-
-       if (ATEN2011_port == NULL)
-               return;
-
-       port = (struct usb_serial_port *)ATEN2011_port->port;
-
-       serial = port->serial;
-
-       dbg("%s - port %d", __func__, ATEN2011_port->port->number);
-
-       if (!ATEN2011_port->open) {
-               dbg("%s - port not opened", __func__);
-               return;
-       }
-
-       if ((!tty) || (!tty->termios)) {
-               dbg("%s - no tty structures", __func__);
-               return;
-       }
-
-       dbg("%s", "Entering .......... ");
-
-       lData = LCR_BITS_8;
-       lStop = LCR_STOP_1;
-       lParity = LCR_PAR_NONE;
-
-       cflag = tty->termios->c_cflag;
-       iflag = tty->termios->c_iflag;
-
-       /* Change the number of bits */
-
-       /* COMMENT1: the below Line"if(cflag & CSIZE)" is added for the errors we get for serial loop data test i.e serial_loopback.pl -v */
-       /* if(cflag & CSIZE) */
-       {
-               switch (cflag & CSIZE) {
-               case CS5:
-                       lData = LCR_BITS_5;
-                       break;
-
-               case CS6:
-                       lData = LCR_BITS_6;
-                       break;
-
-               case CS7:
-                       lData = LCR_BITS_7;
-                       break;
-               default:
-               case CS8:
-                       lData = LCR_BITS_8;
-                       break;
-               }
-       }
-       /* Change the Parity bit */
-       if (cflag & PARENB) {
-               if (cflag & PARODD) {
-                       lParity = LCR_PAR_ODD;
-                       dbg("%s - parity = odd", __func__);
-               } else {
-                       lParity = LCR_PAR_EVEN;
-                       dbg("%s - parity = even", __func__);
-               }
-
-       } else {
-               dbg("%s - parity = none", __func__);
-       }
-
-       if (cflag & CMSPAR)
-               lParity = lParity | 0x20;
-
-       /* Change the Stop bit */
-       if (cflag & CSTOPB) {
-               lStop = LCR_STOP_2;
-               dbg("%s - stop bits = 2", __func__);
-       } else {
-               lStop = LCR_STOP_1;
-               dbg("%s - stop bits = 1", __func__);
-       }
-
-       /* Update the LCR with the correct value */
-       ATEN2011_port->shadowLCR &=
-           ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
-       ATEN2011_port->shadowLCR |= (lData | lParity | lStop);
-
-       dbg
-           ("ATEN2011_change_port_settings ATEN2011_port->shadowLCR is %x",
-            ATEN2011_port->shadowLCR);
-       /* Disable Interrupts */
-       Data = 0x00;
-       set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
-
-       Data = 0x00;
-       set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
-
-       Data = 0xcf;
-       set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
-
-       /* Send the updated LCR value to the ATEN2011 */
-       Data = ATEN2011_port->shadowLCR;
-
-       set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
-
-       Data = 0x00b;
-       ATEN2011_port->shadowMCR = Data;
-       set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
-       Data = 0x00b;
-       set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
-
-       /* set up the MCR register and send it to the ATEN2011 */
-
-       ATEN2011_port->shadowMCR = MCR_MASTER_IE;
-       if (cflag & CBAUD)
-               ATEN2011_port->shadowMCR |= (MCR_DTR | MCR_RTS);
-
-       if (cflag & CRTSCTS)
-               ATEN2011_port->shadowMCR |= (MCR_XON_ANY);
-       else
-               ATEN2011_port->shadowMCR &= ~(MCR_XON_ANY);
-
-       Data = ATEN2011_port->shadowMCR;
-       set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
-
-       /* Determine divisor based on baud rate */
-       baud = tty_get_baud_rate(tty);
-
-       if (!baud) {
-               /* pick a default, any default... */
-               dbg("%s", "Picked default baud...");
-               baud = 9600;
-       }
-
-       dbg("%s - baud rate = %d", __func__, baud);
-       status = ATEN2011_send_cmd_write_baud_rate(ATEN2011_port, baud);
-
-       /* Enable Interrupts */
-       Data = 0x0c;
-       set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
-
-       if (ATEN2011_port->read_urb->status != -EINPROGRESS) {
-               ATEN2011_port->read_urb->dev = serial->dev;
-
-               status = usb_submit_urb(ATEN2011_port->read_urb, GFP_ATOMIC);
-
-               if (status) {
-                       dbg
-                           (" usb_submit_urb(read bulk) failed, status = %d",
-                            status);
-               }
-       }
-       dbg
-           ("ATEN2011_change_port_settings ATEN2011_port->shadowLCR is End %x",
-            ATEN2011_port->shadowLCR);
-
-       return;
-}
-
-static int ATEN2011_calc_num_ports(struct usb_serial *serial)
-{
-
-       __u16 Data = 0x00;
-       int ret = 0;
-       int ATEN2011_2or4ports;
-       ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
-                             ATEN_RDREQ, ATEN_RD_RTYPE, 0, GPIO_REGISTER,
-                             &Data, VENDOR_READ_LENGTH, ATEN_WDR_TIMEOUT);
-
-/* ghostgum: here is where the problem appears to bet */
-/* Which of the following are needed? */
-/* Greg used the serial->type->num_ports=2 */
-/* But the code in the ATEN2011_open relies on serial->num_ports=2 */
-       if ((Data & 0x01) == 0) {
-               ATEN2011_2or4ports = 2;
-               serial->type->num_ports = 2;
-               serial->num_ports = 2;
-       }
-       /* else if(serial->interface->cur_altsetting->desc.bNumEndpoints == 9) */
-       else {
-               ATEN2011_2or4ports = 4;
-               serial->type->num_ports = 4;
-               serial->num_ports = 4;
-
-       }
-
-       return ATEN2011_2or4ports;
-}
-
-static int ATEN2011_startup(struct usb_serial *serial)
-{
-       struct ATENINTL_serial *ATEN2011_serial;
-       struct ATENINTL_port *ATEN2011_port;
-       struct usb_device *dev;
-       int i, status;
-       int minor;
-
-       __u16 Data;
-       dbg("%s", " ATEN2011_startup :entering..........");
-
-       if (!serial) {
-               dbg("%s", "Invalid Handler");
-               return -1;
-       }
-
-       dev = serial->dev;
-
-       dbg("%s", "Entering...");
-
-       /* create our private serial structure */
-       ATEN2011_serial = kzalloc(sizeof(struct ATENINTL_serial), GFP_KERNEL);
-       if (ATEN2011_serial == NULL) {
-               err("%s - Out of memory", __func__);
-               return -ENOMEM;
-       }
-
-       /* resetting the private structure field values to zero */
-       memset(ATEN2011_serial, 0, sizeof(struct ATENINTL_serial));
-
-       ATEN2011_serial->serial = serial;
-       /* initilize status polling flag to 0 */
-       ATEN2011_serial->status_polling_started = 0;
-
-       usb_set_serial_data(serial, ATEN2011_serial);
-       ATEN2011_serial->ATEN2011_spectrum_2or4ports =
-           ATEN2011_calc_num_ports(serial);
-       /* we set up the pointers to the endpoints in the ATEN2011_open *
-        * function, as the structures aren't created yet.             */
-
-       /* set up port private structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               ATEN2011_port =
-                   kmalloc(sizeof(struct ATENINTL_port), GFP_KERNEL);
-               if (ATEN2011_port == NULL) {
-                       err("%s - Out of memory", __func__);
-                       usb_set_serial_data(serial, NULL);
-                       kfree(ATEN2011_serial);
-                       return -ENOMEM;
-               }
-               memset(ATEN2011_port, 0, sizeof(struct ATENINTL_port));
-
-               /*
-                * Initialize all port interrupt end point to port 0
-                * int endpoint. Our device has only one interrupt end point
-                * comman to all port
-                */
-               /* serial->port[i]->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress; */
-
-               ATEN2011_port->port = serial->port[i];
-               usb_set_serial_port_data(serial->port[i], ATEN2011_port);
-
-               minor = serial->port[i]->serial->minor;
-               if (minor == SERIAL_TTY_NO_MINOR)
-                       minor = 0;
-               ATEN2011_port->port_num =
-                   ((serial->port[i]->number - minor) + 1);
-
-               if (ATEN2011_port->port_num == 1) {
-                       ATEN2011_port->SpRegOffset = 0x0;
-                       ATEN2011_port->ControlRegOffset = 0x1;
-                       ATEN2011_port->DcrRegOffset = 0x4;
-               } else if ((ATEN2011_port->port_num == 2)
-                          && (ATEN2011_serial->ATEN2011_spectrum_2or4ports ==
-                              4)) {
-                       ATEN2011_port->SpRegOffset = 0x8;
-                       ATEN2011_port->ControlRegOffset = 0x9;
-                       ATEN2011_port->DcrRegOffset = 0x16;
-               } else if ((ATEN2011_port->port_num == 2)
-                          && (ATEN2011_serial->ATEN2011_spectrum_2or4ports ==
-                              2)) {
-                       ATEN2011_port->SpRegOffset = 0xa;
-                       ATEN2011_port->ControlRegOffset = 0xb;
-                       ATEN2011_port->DcrRegOffset = 0x19;
-               } else if ((ATEN2011_port->port_num == 3)
-                          && (ATEN2011_serial->ATEN2011_spectrum_2or4ports ==
-                              4)) {
-                       ATEN2011_port->SpRegOffset = 0xa;
-                       ATEN2011_port->ControlRegOffset = 0xb;
-                       ATEN2011_port->DcrRegOffset = 0x19;
-               } else if ((ATEN2011_port->port_num == 4)
-                          && (ATEN2011_serial->ATEN2011_spectrum_2or4ports ==
-                              4)) {
-                       ATEN2011_port->SpRegOffset = 0xc;
-                       ATEN2011_port->ControlRegOffset = 0xd;
-                       ATEN2011_port->DcrRegOffset = 0x1c;
-               }
-
-               usb_set_serial_port_data(serial->port[i], ATEN2011_port);
-
-               /* enable rx_disable bit in control register */
-
-               status = get_reg_sync(serial->port[i],
-                                     ATEN2011_port->ControlRegOffset, &Data);
-               if (status < 0) {
-                       dbg("Reading ControlReg failed status-0x%x",
-                               status);
-                       break;
-               } else
-                       dbg
-                           ("ControlReg Reading success val is %x, status%d",
-                            Data, status);
-               Data |= 0x08;   /* setting driver done bit */
-               Data |= 0x04;   /* sp1_bit to have cts change reflect in modem status reg */
-
-               /* Data |= 0x20; */     /* rx_disable bit */
-               status = set_reg_sync(serial->port[i],
-                                     ATEN2011_port->ControlRegOffset, Data);
-               if (status < 0) {
-                       dbg
-                           ("Writing ControlReg failed(rx_disable) status-0x%x",
-                            status);
-                       break;
-               } else
-                       dbg
-                           ("ControlReg Writing success(rx_disable) status%d",
-                            status);
-
-               /*
-                * Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
-                * and 0x24 in DCR3
-                */
-               Data = 0x01;
-               status = set_reg_sync(serial->port[i],
-                                     (__u16)(ATEN2011_port->DcrRegOffset + 0),
-                                     Data);
-               if (status < 0) {
-                       dbg("Writing DCR0 failed status-0x%x", status);
-                       break;
-               } else
-                       dbg("DCR0 Writing success status%d", status);
-
-               Data = 0x05;
-               status = set_reg_sync(serial->port[i],
-                                     (__u16)(ATEN2011_port->DcrRegOffset + 1),
-                                     Data);
-               if (status < 0) {
-                       dbg("Writing DCR1 failed status-0x%x", status);
-                       break;
-               } else
-                       dbg("DCR1 Writing success status%d", status);
-
-               Data = 0x24;
-               status = set_reg_sync(serial->port[i],
-                                     (__u16)(ATEN2011_port->DcrRegOffset + 2),
-                                     Data);
-               if (status < 0) {
-                       dbg("Writing DCR2 failed status-0x%x", status);
-                       break;
-               } else
-                       dbg("DCR2 Writing success status%d", status);
-
-               /* write values in clkstart0x0 and clkmulti 0x20 */
-               Data = 0x0;
-               status = set_reg_sync(serial->port[i], CLK_START_VALUE_REGISTER,
-                                     Data);
-               if (status < 0) {
-                       dbg
-                           ("Writing CLK_START_VALUE_REGISTER failed status-0x%x",
-                            status);
-                       break;
-               } else
-                       dbg
-                           ("CLK_START_VALUE_REGISTER Writing success status%d",
-                            status);
-
-               Data = 0x20;
-               status = set_reg_sync(serial->port[i], CLK_MULTI_REGISTER,
-                                     Data);
-               if (status < 0) {
-                       dbg
-                           ("Writing CLK_MULTI_REGISTER failed status-0x%x",
-                            status);
-                       break;
-               } else
-                       dbg("CLK_MULTI_REGISTER Writing success status%d",
-                               status);
-
-               /* Zero Length flag register */
-               if ((ATEN2011_port->port_num != 1)
-                   && (ATEN2011_serial->ATEN2011_spectrum_2or4ports == 2)) {
-
-                       Data = 0xff;
-                       status = set_reg_sync(serial->port[i],
-                                             (__u16)(ZLP_REG1 + ((__u16)ATEN2011_port->port_num)),
-                                             Data);
-                       dbg("ZLIP offset%x",
-                               (__u16) (ZLP_REG1 +
-                                        ((__u16) ATEN2011_port->port_num)));
-                       if (status < 0) {
-                               dbg
-                                   ("Writing ZLP_REG%d failed status-0x%x",
-                                    i + 2, status);
-                               break;
-                       } else
-                               dbg("ZLP_REG%d Writing success status%d",
-                                       i + 2, status);
-               } else {
-                       Data = 0xff;
-                       status = set_reg_sync(serial->port[i],
-                                             (__u16)(ZLP_REG1 + ((__u16)ATEN2011_port->port_num) - 0x1),
-                                             Data);
-                       dbg("ZLIP offset%x",
-                               (__u16) (ZLP_REG1 +
-                                        ((__u16) ATEN2011_port->port_num) -
-                                        0x1));
-                       if (status < 0) {
-                               dbg
-                                   ("Writing ZLP_REG%d failed status-0x%x",
-                                    i + 1, status);
-                               break;
-                       } else
-                               dbg("ZLP_REG%d Writing success status%d",
-                                       i + 1, status);
-
-               }
-               ATEN2011_port->control_urb = usb_alloc_urb(0, GFP_ATOMIC);
-               ATEN2011_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
-
-       }
-
-       /* Zero Length flag enable */
-       Data = 0x0f;
-       status = set_reg_sync(serial->port[0], ZLP_REG5, Data);
-       if (status < 0) {
-               dbg("Writing ZLP_REG5 failed status-0x%x", status);
-               return -1;
-       } else
-               dbg("ZLP_REG5 Writing success status%d", status);
-
-       /* setting configuration feature to one */
-       usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-                       (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5 * HZ);
-       return 0;
-}
-
-static void ATEN2011_release(struct usb_serial *serial)
-{
-       int i;
-       struct ATENINTL_port *ATEN2011_port;
-
-       /* check for the ports to be closed,close the ports and disconnect */
-
-       /* free private structure allocated for serial port  *
-        * stop reads and writes on all ports                */
-
-       for (i = 0; i < serial->num_ports; ++i) {
-               ATEN2011_port = usb_get_serial_port_data(serial->port[i]);
-               kfree(ATEN2011_port->ctrl_buf);
-               usb_kill_urb(ATEN2011_port->control_urb);
-               kfree(ATEN2011_port);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
-
-       /* free private structure allocated for serial device */
-
-       kfree(usb_get_serial_data(serial));
-       usb_set_serial_data(serial, NULL);
-}
-
-static struct usb_serial_driver aten_serial_driver = {
-       .driver = {
-               .owner =        THIS_MODULE,
-               .name =         "aten2011",
-               },
-       .description =          DRIVER_DESC,
-       .id_table =             id_table,
-       .open =                 ATEN2011_open,
-       .close =                ATEN2011_close,
-       .write =                ATEN2011_write,
-       .write_room =           ATEN2011_write_room,
-       .chars_in_buffer =      ATEN2011_chars_in_buffer,
-       .throttle =             ATEN2011_throttle,
-       .unthrottle =           ATEN2011_unthrottle,
-       .calc_num_ports =       ATEN2011_calc_num_ports,
-
-       .ioctl =                ATEN2011_ioctl,
-       .set_termios =          ATEN2011_set_termios,
-       .break_ctl =            ATEN2011_break,
-       .tiocmget =             ATEN2011_tiocmget,
-       .tiocmset =             ATEN2011_tiocmset,
-       .attach =               ATEN2011_startup,
-       .release =              ATEN2011_release,
-       .read_bulk_callback =   ATEN2011_bulk_in_callback,
-       .read_int_callback =    ATEN2011_interrupt_callback,
-};
-
-static struct usb_driver aten_driver = {
-       .name =         "aten2011",
-       .probe =        usb_serial_probe,
-       .disconnect =   usb_serial_disconnect,
-       .id_table =     id_table,
-};
-
-static int __init aten_init(void)
-{
-       int retval;
-
-       /* Register with the usb serial */
-       retval = usb_serial_register(&aten_serial_driver);
-       if (retval)
-               return retval;
-
-       printk(KERN_INFO KBUILD_MODNAME ":"
-              DRIVER_DESC " " DRIVER_VERSION "\n");
-
-       /* Register with the usb */
-       retval = usb_register(&aten_driver);
-       if (retval)
-               usb_serial_deregister(&aten_serial_driver);
-
-       return retval;
-}
-
-static void __exit aten_exit(void)
-{
-       usb_deregister(&aten_driver);
-       usb_serial_deregister(&aten_serial_driver);
-}
-
-module_init(aten_init);
-module_exit(aten_exit);
-
-/* Module information */
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
-MODULE_PARM_DESC(debug, "Debug enabled or not");
index 0ab9d15f3439085c4d39bd2d1e5ecab694657a86..f5416af1e902a8a447dcffbbcb47d928deff4e3a 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/mm.h>
 #include <linux/fb.h>
 #include <linux/mutex.h>
+#include <linux/vmalloc.h>
 
 #include "udlfb.h"
 
index 22f93dd0ba034ac741dcba70642fbf5272957070..251220dc885140479590224f80a9c0abcb5ee54a 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/smp_lock.h>
 #include <linux/file.h>
 #include <linux/tcp.h>
 #include <linux/in.h>
index a10ed27acbc2028ad1cf683f2fa3bd0d121286d2..f43ca416e4a88c4f989a31495181f4a6d155227b 100644 (file)
@@ -344,7 +344,7 @@ static CHIP_INFO chip_info_table[]= {
 };
 
 static struct pci_device_id device_id_table[] __devinitdata = {
-{ 0x1106, 0x3253, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (int)&chip_info_table[0]},
+{ 0x1106, 0x3253, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long)&chip_info_table[0]},
 { 0, }
 };
 #endif
@@ -369,7 +369,7 @@ static int  device_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 
 #ifdef CONFIG_PM
 static int device_notify_reboot(struct notifier_block *, unsigned long event, void *ptr);
-static int viawget_suspend(struct pci_dev *pcid, u32 state);
+static int viawget_suspend(struct pci_dev *pcid, pm_message_t state);
 static int viawget_resume(struct pci_dev *pcid);
 struct notifier_block device_notifier = {
         notifier_call:  device_notify_reboot,
@@ -3941,7 +3941,7 @@ device_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
         while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
             if(pci_dev_driver(pdev) == &device_driver) {
                 if (pci_get_drvdata(pdev))
-                    viawget_suspend(pdev, 3);
+                    viawget_suspend(pdev, PMSG_HIBERNATE);
             }
         }
     }
@@ -3949,7 +3949,7 @@ device_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
 }
 
 static int
-viawget_suspend(struct pci_dev *pcid, u32 state)
+viawget_suspend(struct pci_dev *pcid, pm_message_t state)
 {
     int power_status;   // to silence the compiler
 
@@ -3971,7 +3971,7 @@ viawget_suspend(struct pci_dev *pcid, u32 state)
     memset(pMgmt->abyCurrBSSID, 0, 6);
     pMgmt->eCurrState = WMAC_STATE_IDLE;
     pci_disable_device(pcid);
-    power_status = pci_set_power_state(pcid, state);
+    power_status = pci_set_power_state(pcid, pci_choose_state(pcid, state));
     spin_unlock_irq(&pDevice->lock);
     return 0;
 }
index a913efc69669a221d336006a35d5155000a6081a..40de151f27898a1e20b82f22d80ccbc9448be558 100644 (file)
 #include <linux/fs.h>          /* everything... */
 #include <linux/errno.h>       /* error codes */
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
index b52cc830c0b49c90ba097bdeadfc4140d9c29d8f..f3873f650bb43f7f68f79ee87a8c8cdf13784b3a 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/errno.h>
 #include <linux/phonedev.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
index 0a69672097a8195e3671e1d63b164c19fa0ababc..4e83c297ec9efdc191c084f913637b8aaa0e7d2f 100644 (file)
@@ -953,7 +953,12 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
 
        mutex_lock(&tz->lock);
 
-       tz->ops->get_temp(tz, &temp);
+       if (tz->ops->get_temp(tz, &temp)) {
+               /* get_temp failed - retry it later */
+               printk(KERN_WARNING PREFIX "failed to read out thermal zone "
+                      "%d\n", tz->id);
+               goto leave;
+       }
 
        for (count = 0; count < tz->trips; count++) {
                tz->ops->get_trip_type(tz, count, &trip_type);
@@ -1005,6 +1010,8 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
                                            THERMAL_TRIPS_NONE);
 
        tz->last_temperature = temp;
+
+      leave:
        if (tz->passive)
                thermal_zone_device_set_polling(tz, tz->passive_delay);
        else if (tz->polling_delay)
index 38bfdb0f666058061081e6035512843cb0eaa850..2bfc41ece0e1d2df04ab058f742e76fd7b7749e9 100644 (file)
@@ -462,11 +462,18 @@ urbs:
 
                rcv->buffer = buf;
 
-               usb_fill_bulk_urb(rcv->urb, acm->dev,
-                                 acm->rx_endpoint,
-                                 buf->base,
-                                 acm->readsize,
-                                 acm_read_bulk, rcv);
+               if (acm->is_int_ep)
+                       usb_fill_int_urb(rcv->urb, acm->dev,
+                                        acm->rx_endpoint,
+                                        buf->base,
+                                        acm->readsize,
+                                        acm_read_bulk, rcv, acm->bInterval);
+               else
+                       usb_fill_bulk_urb(rcv->urb, acm->dev,
+                                         acm->rx_endpoint,
+                                         buf->base,
+                                         acm->readsize,
+                                         acm_read_bulk, rcv);
                rcv->urb->transfer_dma = buf->dma;
                rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
@@ -550,7 +557,7 @@ static void acm_waker(struct work_struct *waker)
 static int acm_tty_open(struct tty_struct *tty, struct file *filp)
 {
        struct acm *acm;
-       int rv = -EINVAL;
+       int rv = -ENODEV;
        int i;
        dbg("Entering acm_tty_open.");
 
@@ -677,7 +684,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
 
        /* Perform the closing process and see if we need to do the hardware
           shutdown */
-       if (tty_port_close_start(&acm->port, tty, filp) == 0)
+       if (!acm || tty_port_close_start(&acm->port, tty, filp) == 0)
                return;
        acm_port_down(acm, 0);
        tty_port_close_end(&acm->port, tty);
@@ -740,7 +747,7 @@ static int acm_tty_chars_in_buffer(struct tty_struct *tty)
 {
        struct acm *acm = tty->driver_data;
        if (!ACM_READY(acm))
-               return -EINVAL;
+               return 0;
        /*
         * This is inaccurate (overcounts), but it works.
         */
@@ -1173,6 +1180,9 @@ made_compressed_probe:
        spin_lock_init(&acm->read_lock);
        mutex_init(&acm->mutex);
        acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress);
+       acm->is_int_ep = usb_endpoint_xfer_int(epread);
+       if (acm->is_int_ep)
+               acm->bInterval = epread->bInterval;
        tty_port_init(&acm->port);
        acm->port.ops = &acm_port_ops;
 
@@ -1227,9 +1237,14 @@ made_compressed_probe:
                        goto alloc_fail7;
                }
 
-               usb_fill_bulk_urb(snd->urb, usb_dev,
-                       usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
-                       NULL, acm->writesize, acm_write_bulk, snd);
+               if (usb_endpoint_xfer_int(epwrite))
+                       usb_fill_int_urb(snd->urb, usb_dev,
+                               usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+                               NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval);
+               else
+                       usb_fill_bulk_urb(snd->urb, usb_dev,
+                               usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+                               NULL, acm->writesize, acm_write_bulk, snd);
                snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
                snd->instance = acm;
        }
index 1602324808bafb510e374520b9eb0a264617dc02..c4a0ee8ffccfb3ae4203c8cac4d091d88177b478 100644 (file)
@@ -126,6 +126,8 @@ struct acm {
        unsigned int ctrl_caps;                         /* control capabilities from the class specific header */
        unsigned int susp_count;                        /* number of suspended interfaces */
        int combined_interfaces:1;                      /* control and data collapsed */
+       int is_int_ep:1;                                /* interrupt endpoints contrary to spec used */
+       u8 bInterval;
        struct acm_wb *delayed_wb;                      /* write queued for a device about to be woken */
 };
 
index 0fe434505ac44d8d6d9c066738b36dacdd0c62ac..ba589d4ca8bcb9e8783cc47bce18cab3faaa8301 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/bitops.h>
index 3703789d0d2af8a7459138adb5903c548e704425..b09a527f73411499e2ab712c0f4d1b6f7d2c1946 100644 (file)
@@ -751,7 +751,7 @@ static int get_capabilities(struct usbtmc_device_data *data)
 {
        struct device *dev = &data->usb_dev->dev;
        char *buffer;
-       int rv;
+       int rv = 0;
 
        buffer = kmalloc(0x18, GFP_KERNEL);
        if (!buffer)
@@ -763,7 +763,7 @@ static int get_capabilities(struct usbtmc_device_data *data)
                             0, 0, buffer, 0x18, USBTMC_TIMEOUT);
        if (rv < 0) {
                dev_err(dev, "usb_control_msg returned %d\n", rv);
-               return rv;
+               goto err_out;
        }
 
        dev_dbg(dev, "GET_CAPABILITIES returned %x\n", buffer[0]);
@@ -773,7 +773,8 @@ static int get_capabilities(struct usbtmc_device_data *data)
        dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]);
        if (buffer[0] != USBTMC_STATUS_SUCCESS) {
                dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]);
-               return -EPERM;
+               rv = -EPERM;
+               goto err_out;
        }
 
        data->capabilities.interface_capabilities = buffer[4];
@@ -781,8 +782,9 @@ static int get_capabilities(struct usbtmc_device_data *data)
        data->capabilities.usb488_interface_capabilities = buffer[14];
        data->capabilities.usb488_device_capabilities = buffer[15];
 
+err_out:
        kfree(buffer);
-       return 0;
+       return rv;
 }
 
 #define capability_attribute(name)                                     \
index 69280c35b5cbc6d93cc50c99d7f4a7f747c1fc99..ad925946f869ea1ed435851b1efebd0cf7d200b4 100644 (file)
@@ -28,7 +28,7 @@ comment "Miscellaneous USB options"
        depends on USB
 
 config USB_DEVICEFS
-       bool "USB device filesystem (DEPRECATED)" if EMBEDDED
+       bool "USB device filesystem (DEPRECATED)"
        depends on USB
        ---help---
          If you say Y here (and to "/proc file system support" in the "File
index 24dfb33f90cb0fbc2268572ee0ed90ecc15efbb5..a16c538d0132958ab330b6993267663d45d4c4ef 100644 (file)
@@ -80,38 +80,18 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
        int max_tx;
        int i;
 
-       /* Allocate space for the SS endpoint companion descriptor */
-       ep->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp),
-                       GFP_KERNEL);
-       if (!ep->ss_ep_comp)
-               return -ENOMEM;
        desc = (struct usb_ss_ep_comp_descriptor *) buffer;
        if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP) {
                dev_warn(ddev, "No SuperSpeed endpoint companion for config %d "
                                " interface %d altsetting %d ep %d: "
                                "using minimum values\n",
                                cfgno, inum, asnum, ep->desc.bEndpointAddress);
-               ep->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE;
-               ep->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
-               ep->ss_ep_comp->desc.bMaxBurst = 0;
-               /*
-                * Leave bmAttributes as zero, which will mean no streams for
-                * bulk, and isoc won't support multiple bursts of packets.
-                * With bursts of only one packet, and a Mult of 1, the max
-                * amount of data moved per endpoint service interval is one
-                * packet.
-                */
-               if (usb_endpoint_xfer_isoc(&ep->desc) ||
-                               usb_endpoint_xfer_int(&ep->desc))
-                       ep->ss_ep_comp->desc.wBytesPerInterval =
-                               ep->desc.wMaxPacketSize;
                /*
                 * The next descriptor is for an Endpoint or Interface,
                 * no extra descriptors to copy into the companion structure,
                 * and we didn't eat up any of the buffer.
                 */
-               retval = 0;
-               goto valid;
+               return 0;
        }
        memcpy(&ep->ss_ep_comp->desc, desc, USB_DT_SS_EP_COMP_SIZE);
        desc = &ep->ss_ep_comp->desc;
@@ -320,6 +300,28 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
                buffer += i;
                size -= i;
 
+               /* Allocate space for the SS endpoint companion descriptor */
+               endpoint->ss_ep_comp = kzalloc(sizeof(struct usb_host_ss_ep_comp),
+                               GFP_KERNEL);
+               if (!endpoint->ss_ep_comp)
+                       return -ENOMEM;
+
+               /* Fill in some default values (may be overwritten later) */
+               endpoint->ss_ep_comp->desc.bLength = USB_DT_SS_EP_COMP_SIZE;
+               endpoint->ss_ep_comp->desc.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
+               endpoint->ss_ep_comp->desc.bMaxBurst = 0;
+               /*
+                * Leave bmAttributes as zero, which will mean no streams for
+                * bulk, and isoc won't support multiple bursts of packets.
+                * With bursts of only one packet, and a Mult of 1, the max
+                * amount of data moved per endpoint service interval is one
+                * packet.
+                */
+               if (usb_endpoint_xfer_isoc(&endpoint->desc) ||
+                               usb_endpoint_xfer_int(&endpoint->desc))
+                       endpoint->ss_ep_comp->desc.wBytesPerInterval =
+                               endpoint->desc.wMaxPacketSize;
+
                if (size > 0) {
                        retval = usb_parse_ss_endpoint_companion(ddev, cfgno,
                                        inum, asnum, endpoint, num_ep, buffer,
@@ -329,6 +331,10 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
                                retval = buffer - buffer0;
                        }
                } else {
+                       dev_warn(ddev, "config %d interface %d altsetting %d "
+                               "endpoint 0x%X has no "
+                               "SuperSpeed companion descriptor\n",
+                               cfgno, inum, asnum, d->bEndpointAddress);
                        retval = buffer - buffer0;
                }
        } else {
index 73c108d117b4b3da95587c5366a4498a695a8e74..96f11715cd269b4cb8594c12c4c027ae50350af8 100644 (file)
@@ -136,17 +136,19 @@ static const struct class_info clas_info[] =
        {USB_CLASS_AUDIO,               "audio"},
        {USB_CLASS_COMM,                "comm."},
        {USB_CLASS_HID,                 "HID"},
-       {USB_CLASS_HUB,                 "hub"},
        {USB_CLASS_PHYSICAL,            "PID"},
+       {USB_CLASS_STILL_IMAGE,         "still"},
        {USB_CLASS_PRINTER,             "print"},
        {USB_CLASS_MASS_STORAGE,        "stor."},
+       {USB_CLASS_HUB,                 "hub"},
        {USB_CLASS_CDC_DATA,            "data"},
-       {USB_CLASS_APP_SPEC,            "app."},
-       {USB_CLASS_VENDOR_SPEC,         "vend."},
-       {USB_CLASS_STILL_IMAGE,         "still"},
        {USB_CLASS_CSCID,               "scard"},
        {USB_CLASS_CONTENT_SEC,         "c-sec"},
        {USB_CLASS_VIDEO,               "video"},
+       {USB_CLASS_WIRELESS_CONTROLLER, "wlcon"},
+       {USB_CLASS_MISC,                "misc"},
+       {USB_CLASS_APP_SPEC,            "app."},
+       {USB_CLASS_VENDOR_SPEC,         "vend."},
        {-1,                            "unk."}         /* leave as last */
 };
 
index 308609039c73e1bbf1252adee9f2e276cc73c852..4247eccf858c62c656cc58e91a40591eb3789786 100644 (file)
@@ -325,21 +325,34 @@ static void async_completed(struct urb *urb)
        struct async *as = urb->context;
        struct dev_state *ps = as->ps;
        struct siginfo sinfo;
+       struct pid *pid = NULL;
+       uid_t uid = 0;
+       uid_t euid = 0;
+       u32 secid = 0;
+       int signr;
 
        spin_lock(&ps->lock);
        list_move_tail(&as->asynclist, &ps->async_completed);
-       spin_unlock(&ps->lock);
        as->status = urb->status;
-       if (as->signr) {
+       signr = as->signr;
+       if (signr) {
                sinfo.si_signo = as->signr;
                sinfo.si_errno = as->status;
                sinfo.si_code = SI_ASYNCIO;
                sinfo.si_addr = as->userurb;
-               kill_pid_info_as_uid(as->signr, &sinfo, as->pid, as->uid,
-                                     as->euid, as->secid);
+               pid = as->pid;
+               uid = as->uid;
+               euid = as->euid;
+               secid = as->secid;
        }
        snoop(&urb->dev->dev, "urb complete\n");
        snoop_urb(urb, as->userurb);
+       spin_unlock(&ps->lock);
+
+       if (signr)
+               kill_pid_info_as_uid(sinfo.si_signo, &sinfo, pid, uid,
+                                     euid, secid);
+
        wake_up(&ps->wait);
 }
 
@@ -582,7 +595,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
        if (!ps)
                goto out;
 
-       ret = -ENOENT;
+       ret = -ENODEV;
 
        /* usbdev device-node */
        if (imajor(inode) == USB_DEVICE_MAJOR)
@@ -982,7 +995,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                                USBDEVFS_URB_ZERO_PACKET |
                                USBDEVFS_URB_NO_INTERRUPT))
                return -EINVAL;
-       if (!uurb->buffer)
+       if (uurb->buffer_length > 0 && !uurb->buffer)
                return -EINVAL;
        if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL &&
            (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
@@ -1038,11 +1051,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                        is_in = 0;
                        uurb->endpoint &= ~USB_DIR_IN;
                }
-               if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
-                               uurb->buffer, uurb->buffer_length)) {
-                       kfree(dr);
-                       return -EFAULT;
-               }
                snoop(&ps->dev->dev, "control urb: bRequest=%02x "
                        "bRrequestType=%02x wValue=%04x "
                        "wIndex=%04x wLength=%04x\n",
@@ -1062,9 +1070,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                uurb->number_of_packets = 0;
                if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
                        return -EINVAL;
-               if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
-                               uurb->buffer, uurb->buffer_length))
-                       return -EFAULT;
                snoop(&ps->dev->dev, "bulk urb\n");
                break;
 
@@ -1106,28 +1111,35 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                        return -EINVAL;
                if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
                        return -EINVAL;
-               if (!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
-                               uurb->buffer, uurb->buffer_length))
-                       return -EFAULT;
                snoop(&ps->dev->dev, "interrupt urb\n");
                break;
 
        default:
                return -EINVAL;
        }
-       as = alloc_async(uurb->number_of_packets);
-       if (!as) {
+       if (uurb->buffer_length > 0 &&
+                       !access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
+                               uurb->buffer, uurb->buffer_length)) {
                kfree(isopkt);
                kfree(dr);
-               return -ENOMEM;
+               return -EFAULT;
        }
-       as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL);
-       if (!as->urb->transfer_buffer) {
+       as = alloc_async(uurb->number_of_packets);
+       if (!as) {
                kfree(isopkt);
                kfree(dr);
-               free_async(as);
                return -ENOMEM;
        }
+       if (uurb->buffer_length > 0) {
+               as->urb->transfer_buffer = kmalloc(uurb->buffer_length,
+                               GFP_KERNEL);
+               if (!as->urb->transfer_buffer) {
+                       kfree(isopkt);
+                       kfree(dr);
+                       free_async(as);
+                       return -ENOMEM;
+               }
+       }
        as->urb->dev = ps->dev;
        as->urb->pipe = (uurb->type << 30) |
                        __create_pipe(ps->dev, uurb->endpoint & 0xf) |
@@ -1169,7 +1181,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
        kfree(isopkt);
        as->ps = ps;
        as->userurb = arg;
-       if (uurb->endpoint & USB_DIR_IN)
+       if (is_in && uurb->buffer_length > 0)
                as->userbuffer = uurb->buffer;
        else
                as->userbuffer = NULL;
@@ -1179,9 +1191,9 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
        as->uid = cred->uid;
        as->euid = cred->euid;
        security_task_getsecid(current, &as->secid);
-       if (!is_in) {
+       if (!is_in && uurb->buffer_length > 0) {
                if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
-                               as->urb->transfer_buffer_length)) {
+                               uurb->buffer_length)) {
                        free_async(as);
                        return -EFAULT;
                }
@@ -1231,22 +1243,22 @@ static int processcompl(struct async *as, void __user * __user *arg)
        if (as->userbuffer)
                if (copy_to_user(as->userbuffer, urb->transfer_buffer,
                                 urb->transfer_buffer_length))
-                       return -EFAULT;
+                       goto err_out;
        if (put_user(as->status, &userurb->status))
-               return -EFAULT;
+               goto err_out;
        if (put_user(urb->actual_length, &userurb->actual_length))
-               return -EFAULT;
+               goto err_out;
        if (put_user(urb->error_count, &userurb->error_count))
-               return -EFAULT;
+               goto err_out;
 
        if (usb_endpoint_xfer_isoc(&urb->ep->desc)) {
                for (i = 0; i < urb->number_of_packets; i++) {
                        if (put_user(urb->iso_frame_desc[i].actual_length,
                                     &userurb->iso_frame_desc[i].actual_length))
-                               return -EFAULT;
+                               goto err_out;
                        if (put_user(urb->iso_frame_desc[i].status,
                                     &userurb->iso_frame_desc[i].status))
-                               return -EFAULT;
+                               goto err_out;
                }
        }
 
@@ -1255,6 +1267,10 @@ static int processcompl(struct async *as, void __user * __user *arg)
        if (put_user(addr, (void __user * __user *)arg))
                return -EFAULT;
        return 0;
+
+err_out:
+       free_async(as);
+       return -EFAULT;
 }
 
 static struct async *reap_as(struct dev_state *ps)
@@ -1305,7 +1321,8 @@ static int get_urb32(struct usbdevfs_urb *kurb,
                     struct usbdevfs_urb32 __user *uurb)
 {
        __u32  uptr;
-       if (get_user(kurb->type, &uurb->type) ||
+       if (!access_ok(VERIFY_READ, uurb, sizeof(*uurb)) ||
+           __get_user(kurb->type, &uurb->type) ||
            __get_user(kurb->endpoint, &uurb->endpoint) ||
            __get_user(kurb->status, &uurb->status) ||
            __get_user(kurb->flags, &uurb->flags) ||
@@ -1520,8 +1537,9 @@ static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg)
        u32 udata;
 
        uioc = compat_ptr((long)arg);
-       if (get_user(ctrl.ifno, &uioc->ifno) ||
-           get_user(ctrl.ioctl_code, &uioc->ioctl_code) ||
+       if (!access_ok(VERIFY_READ, uioc, sizeof(*uioc)) ||
+           __get_user(ctrl.ifno, &uioc->ifno) ||
+           __get_user(ctrl.ioctl_code, &uioc->ioctl_code) ||
            __get_user(udata, &uioc->data))
                return -EFAULT;
        ctrl.data = compat_ptr(udata);
index ce3f453f02ef5efe5b5034f3bedfa5a062e0db25..95ccfa0b9fc52876f5166b3edea039409adf9a33 100644 (file)
@@ -648,7 +648,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd)
        struct urb      *urb;
        int             length;
        unsigned long   flags;
-       char            buffer[4];      /* Any root hubs with > 31 ports? */
+       char            buffer[6];      /* Any root hubs with > 31 ports? */
 
        if (unlikely(!hcd->rh_registered))
                return;
index d397ecfd5b178d881f97c72e51989bfccbe2a064..ec5c67ea07b745a95b92e8db88349abadc1bbca1 100644 (file)
@@ -227,6 +227,10 @@ struct hc_driver {
                /* has a port been handed over to a companion? */
        int     (*port_handed_over)(struct usb_hcd *, int);
 
+               /* CLEAR_TT_BUFFER completion callback */
+       void    (*clear_tt_buffer_complete)(struct usb_hcd *,
+                               struct usb_host_endpoint *);
+
        /* xHCI specific functions */
                /* Called by usb_alloc_dev to alloc HC device structures */
        int     (*alloc_dev)(struct usb_hcd *, struct usb_device *);
index 2af3b4f0605405dd723b1ccd4f853f7f85dc1848..71f86c60d83c3962cf8b7eabe1d709d2d87b7a76 100644 (file)
@@ -450,10 +450,10 @@ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt)
  * talking to TTs must queue control transfers (not just bulk and iso), so
  * both can talk to the same hub concurrently.
  */
-static void hub_tt_kevent (struct work_struct *work)
+static void hub_tt_work(struct work_struct *work)
 {
        struct usb_hub          *hub =
-               container_of(work, struct usb_hub, tt.kevent);
+               container_of(work, struct usb_hub, tt.clear_work);
        unsigned long           flags;
        int                     limit = 100;
 
@@ -462,6 +462,7 @@ static void hub_tt_kevent (struct work_struct *work)
                struct list_head        *next;
                struct usb_tt_clear     *clear;
                struct usb_device       *hdev = hub->hdev;
+               const struct hc_driver  *drv;
                int                     status;
 
                next = hub->tt.clear_list.next;
@@ -471,21 +472,25 @@ static void hub_tt_kevent (struct work_struct *work)
                /* drop lock so HCD can concurrently report other TT errors */
                spin_unlock_irqrestore (&hub->tt.lock, flags);
                status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt);
-               spin_lock_irqsave (&hub->tt.lock, flags);
-
                if (status)
                        dev_err (&hdev->dev,
                                "clear tt %d (%04x) error %d\n",
                                clear->tt, clear->devinfo, status);
+
+               /* Tell the HCD, even if the operation failed */
+               drv = clear->hcd->driver;
+               if (drv->clear_tt_buffer_complete)
+                       (drv->clear_tt_buffer_complete)(clear->hcd, clear->ep);
+
                kfree(clear);
+               spin_lock_irqsave(&hub->tt.lock, flags);
        }
        spin_unlock_irqrestore (&hub->tt.lock, flags);
 }
 
 /**
- * usb_hub_tt_clear_buffer - clear control/bulk TT state in high speed hub
- * @udev: the device whose split transaction failed
- * @pipe: identifies the endpoint of the failed transaction
+ * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub
+ * @urb: an URB associated with the failed or incomplete split transaction
  *
  * High speed HCDs use this to tell the hub driver that some split control or
  * bulk transaction failed in a way that requires clearing internal state of
@@ -495,8 +500,10 @@ static void hub_tt_kevent (struct work_struct *work)
  * It may not be possible for that hub to handle additional full (or low)
  * speed transactions until that state is fully cleared out.
  */
-void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
+int usb_hub_clear_tt_buffer(struct urb *urb)
 {
+       struct usb_device       *udev = urb->dev;
+       int                     pipe = urb->pipe;
        struct usb_tt           *tt = udev->tt;
        unsigned long           flags;
        struct usb_tt_clear     *clear;
@@ -508,7 +515,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
        if ((clear = kmalloc (sizeof *clear, GFP_ATOMIC)) == NULL) {
                dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n");
                /* FIXME recover somehow ... RESET_TT? */
-               return;
+               return -ENOMEM;
        }
 
        /* info that CLEAR_TT_BUFFER needs */
@@ -520,14 +527,19 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
                        : (USB_ENDPOINT_XFER_BULK << 11);
        if (usb_pipein (pipe))
                clear->devinfo |= 1 << 15;
-       
+
+       /* info for completion callback */
+       clear->hcd = bus_to_hcd(udev->bus);
+       clear->ep = urb->ep;
+
        /* tell keventd to clear state for this TT */
        spin_lock_irqsave (&tt->lock, flags);
        list_add_tail (&clear->clear_list, &tt->clear_list);
-       schedule_work (&tt->kevent);
+       schedule_work(&tt->clear_work);
        spin_unlock_irqrestore (&tt->lock, flags);
+       return 0;
 }
-EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer);
+EXPORT_SYMBOL_GPL(usb_hub_clear_tt_buffer);
 
 /* If do_delay is false, return the number of milliseconds the caller
  * needs to delay.
@@ -818,7 +830,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
        if (hub->has_indicators)
                cancel_delayed_work_sync(&hub->leds);
        if (hub->tt.hub)
-               cancel_work_sync(&hub->tt.kevent);
+               cancel_work_sync(&hub->tt.clear_work);
 }
 
 /* caller has locked the hub device */
@@ -935,7 +947,7 @@ static int hub_configure(struct usb_hub *hub,
 
        spin_lock_init (&hub->tt.lock);
        INIT_LIST_HEAD (&hub->tt.clear_list);
-       INIT_WORK (&hub->tt.kevent, hub_tt_kevent);
+       INIT_WORK(&hub->tt.clear_work, hub_tt_work);
        switch (hdev->descriptor.bDeviceProtocol) {
                case 0:
                        break;
index 889c0f32a40b729431f2dab51d13aead39f5f3e8..de8081f065edda76ae95a415b98c6db86a0d9a57 100644 (file)
@@ -188,16 +188,18 @@ struct usb_tt {
        /* for control/bulk error recovery (CLEAR_TT_BUFFER) */
        spinlock_t              lock;
        struct list_head        clear_list;     /* of usb_tt_clear */
-       struct work_struct                      kevent;
+       struct work_struct      clear_work;
 };
 
 struct usb_tt_clear {
        struct list_head        clear_list;
        unsigned                tt;
        u16                     devinfo;
+       struct usb_hcd          *hcd;
+       struct usb_host_endpoint        *ep;
 };
 
-extern void usb_hub_tt_clear_buffer(struct usb_device *dev, int pipe);
+extern int usb_hub_clear_tt_buffer(struct urb *urb);
 extern void usb_ep0_reinit(struct usb_device *);
 
 #endif /* __LINUX_HUB_H */
index 2bed83caacb1a0c714a2e05af21242bbb504dcad..9720e699f4729737cbdd90946f234e567fc0d874 100644 (file)
@@ -806,6 +806,48 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid,
        return rc;
 }
 
+static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf)
+{
+       int err;
+
+       if (dev->have_langid)
+               return 0;
+
+       if (dev->string_langid < 0)
+               return -EPIPE;
+
+       err = usb_string_sub(dev, 0, 0, tbuf);
+
+       /* If the string was reported but is malformed, default to english
+        * (0x0409) */
+       if (err == -ENODATA || (err > 0 && err < 4)) {
+               dev->string_langid = 0x0409;
+               dev->have_langid = 1;
+               dev_err(&dev->dev,
+                       "string descriptor 0 malformed (err = %d), "
+                       "defaulting to 0x%04x\n",
+                               err, dev->string_langid);
+               return 0;
+       }
+
+       /* In case of all other errors, we assume the device is not able to
+        * deal with strings at all. Set string_langid to -1 in order to
+        * prevent any string to be retrieved from the device */
+       if (err < 0) {
+               dev_err(&dev->dev, "string descriptor 0 read error: %d\n",
+                                       err);
+               dev->string_langid = -1;
+               return -EPIPE;
+       }
+
+       /* always use the first langid listed */
+       dev->string_langid = tbuf[2] | (tbuf[3] << 8);
+       dev->have_langid = 1;
+       dev_dbg(&dev->dev, "default language 0x%04x\n",
+                               dev->string_langid);
+       return 0;
+}
+
 /**
  * usb_string - returns UTF-8 version of a string descriptor
  * @dev: the device whose string descriptor is being retrieved
@@ -837,24 +879,9 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
        if (!tbuf)
                return -ENOMEM;
 
-       /* get langid for strings if it's not yet known */
-       if (!dev->have_langid) {
-               err = usb_string_sub(dev, 0, 0, tbuf);
-               if (err < 0) {
-                       dev_err(&dev->dev,
-                               "string descriptor 0 read error: %d\n",
-                               err);
-               } else if (err < 4) {
-                       dev_err(&dev->dev, "string descriptor 0 too short\n");
-               } else {
-                       dev->string_langid = tbuf[2] | (tbuf[3] << 8);
-                       /* always use the first langid listed */
-                       dev_dbg(&dev->dev, "default language 0x%04x\n",
-                               dev->string_langid);
-               }
-
-               dev->have_langid = 1;
-       }
+       err = usb_get_langid(dev, tbuf);
+       if (err < 0)
+               goto errout;
 
        err = usb_string_sub(dev, dev->string_langid, index, tbuf);
        if (err < 0)
index 5d1ddf485d1eb6d5d55e12a4eca7536e10a75838..7f8e83a954ac6881861bdc0d2e334ea85944db7a 100644 (file)
@@ -286,6 +286,27 @@ config USB_S3C_HSOTG
        default USB_GADGET
        select USB_GADGET_SELECTED
 
+config USB_GADGET_IMX
+       boolean "Freescale IMX USB Peripheral Controller"
+       depends on ARCH_MX1
+       help
+          Freescale's IMX series include an integrated full speed
+          USB 1.1 device controller.  The controller in the IMX series
+          is register-compatible.
+
+          It has Six fixed-function endpoints, as well as endpoint
+          zero (for control transfers).
+
+          Say "y" to link the driver statically, or "m" to build a
+          dynamically linked module called "imx_udc" and force all
+          gadget drivers to also be dynamically linked.
+
+config USB_IMX
+       tristate
+       depends on USB_GADGET_IMX
+       default USB_GADGET
+       select USB_GADGET_SELECTED
+
 config USB_GADGET_S3C2410
        boolean "S3C2410 USB Device Controller"
        depends on ARCH_S3C2410
@@ -321,27 +342,6 @@ config USB_GADGET_MUSB_HDRC
          This OTG-capable silicon IP is used in dual designs including
          the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin
 
-config USB_GADGET_IMX
-       boolean "Freescale IMX USB Peripheral Controller"
-       depends on ARCH_MX1
-       help
-          Freescale's IMX series include an integrated full speed
-          USB 1.1 device controller.  The controller in the IMX series
-          is register-compatible.
-
-          It has Six fixed-function endpoints, as well as endpoint
-          zero (for control transfers).
-
-          Say "y" to link the driver statically, or "m" to build a
-          dynamically linked module called "imx_udc" and force all
-          gadget drivers to also be dynamically linked.
-
-config USB_IMX
-       tristate
-       depends on USB_GADGET_IMX
-       default USB_GADGET
-       select USB_GADGET_SELECTED
-
 config USB_GADGET_M66592
        boolean "Renesas M66592 USB Peripheral Controller"
        select USB_GADGET_DUALSPEED
@@ -604,6 +604,7 @@ config USB_ZERO_HNPTEST
 config USB_AUDIO
        tristate "Audio Gadget (EXPERIMENTAL)"
        depends on SND
+       select SND_PCM
        help
          Gadget Audio is compatible with USB Audio Class specification 1.0.
          It will include at least one AudioControl interface, zero or more
index 826f3adde5d8a4ac0df29265d88cadd1ab541d05..77352ccc245e0ab3a456b22ce0ed6a8b2f7e411b 100644 (file)
@@ -48,7 +48,6 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index 94de7e864614961f322412d2855289041fdda22e..9f80f4e970bd00693cf3140483940eb46843cdef 100644 (file)
@@ -42,9 +42,9 @@
  * Instead:  allocate your own, using normal USB-IF procedures.
  */
 
-/* Thanks to NetChip Technologies for donating this product ID. */
-#define AUDIO_VENDOR_NUM               0x0525  /* NetChip */
-#define AUDIO_PRODUCT_NUM              0xa4a1  /* Linux-USB Audio Gadget */
+/* Thanks to Linux Foundation for donating this product ID. */
+#define AUDIO_VENDOR_NUM               0x1d6b  /* Linux Foundation */
+#define AUDIO_PRODUCT_NUM              0x0101  /* Linux-USB Audio Gadget */
 
 /*-------------------------------------------------------------------------*/
 
index d006dc652e025558e3157691b0f855b43452a6ad..bd102f5052ba67453c3a2dd30a2eefde46ce59ee 100644 (file)
@@ -293,15 +293,16 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
                /* CDC Subset */
                eth_config_driver.label = "CDC Subset/SAFE";
 
-               device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM),
-               device_desc.idProduct = cpu_to_le16(SIMPLE_PRODUCT_NUM),
-               device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
+               device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM);
+               device_desc.idProduct = cpu_to_le16(SIMPLE_PRODUCT_NUM);
+               if (!has_rndis())
+                       device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
        }
 
        if (has_rndis()) {
                /* RNDIS plus ECM-or-Subset */
-               device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM),
-               device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM),
+               device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM);
+               device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM);
                device_desc.bNumConfigurations = 2;
        }
 
index 6829d5961359278745a63d0f3ef73cb68c5164ab..a3913519fd5841cefc0718639af38b2bbf62ae40 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index 0ce4e2819847c13fb7548fcf910923495d4588ba..ed21e263f832f05d977aa4c4acd41881dd013002 100644 (file)
@@ -139,7 +139,7 @@ static int is_vbus_present(void)
 {
        struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
 
-       if (mach->gpio_vbus) {
+       if (gpio_is_valid(mach->gpio_vbus)) {
                int value = gpio_get_value(mach->gpio_vbus);
 
                if (mach->gpio_vbus_inverted)
@@ -158,7 +158,7 @@ static void pullup_off(void)
        struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
        int off_level = mach->gpio_pullup_inverted;
 
-       if (mach->gpio_pullup)
+       if (gpio_is_valid(mach->gpio_pullup))
                gpio_set_value(mach->gpio_pullup, off_level);
        else if (mach->udc_command)
                mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
@@ -169,7 +169,7 @@ static void pullup_on(void)
        struct pxa2xx_udc_mach_info             *mach = the_controller->mach;
        int on_level = !mach->gpio_pullup_inverted;
 
-       if (mach->gpio_pullup)
+       if (gpio_is_valid(mach->gpio_pullup))
                gpio_set_value(mach->gpio_pullup, on_level);
        else if (mach->udc_command)
                mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
@@ -1000,7 +1000,7 @@ static int pxa25x_udc_pullup(struct usb_gadget *_gadget, int is_active)
        udc = container_of(_gadget, struct pxa25x_udc, gadget);
 
        /* not all boards support pullup control */
-       if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
+       if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
                return -EOPNOTSUPP;
 
        udc->pullup = (is_active != 0);
@@ -1802,11 +1802,13 @@ pxa25x_udc_irq(int irq, void *_dev)
                                        USIR0 |= tmp;
                                        handled = 1;
                                }
+#ifndef        CONFIG_USB_PXA25X_SMALL
                                if (usir1 & tmp) {
                                        handle_ep(&dev->ep[i+8]);
                                        USIR1 |= tmp;
                                        handled = 1;
                                }
+#endif
                        }
                }
 
@@ -2160,7 +2162,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
        dev->dev = &pdev->dev;
        dev->mach = pdev->dev.platform_data;
 
-       if (dev->mach->gpio_vbus) {
+       if (gpio_is_valid(dev->mach->gpio_vbus)) {
                if ((retval = gpio_request(dev->mach->gpio_vbus,
                                "pxa25x_udc GPIO VBUS"))) {
                        dev_dbg(&pdev->dev,
@@ -2173,7 +2175,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
        } else
                vbus_irq = 0;
 
-       if (dev->mach->gpio_pullup) {
+       if (gpio_is_valid(dev->mach->gpio_pullup)) {
                if ((retval = gpio_request(dev->mach->gpio_pullup,
                                "pca25x_udc GPIO PULLUP"))) {
                        dev_dbg(&pdev->dev,
@@ -2256,10 +2258,10 @@ lubbock_fail0:
 #endif
        free_irq(irq, dev);
  err_irq1:
-       if (dev->mach->gpio_pullup)
+       if (gpio_is_valid(dev->mach->gpio_pullup))
                gpio_free(dev->mach->gpio_pullup);
  err_gpio_pullup:
-       if (dev->mach->gpio_vbus)
+       if (gpio_is_valid(dev->mach->gpio_vbus))
                gpio_free(dev->mach->gpio_vbus);
  err_gpio_vbus:
        clk_put(dev->clk);
@@ -2294,11 +2296,11 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
                free_irq(LUBBOCK_USB_IRQ, dev);
        }
 #endif
-       if (dev->mach->gpio_vbus) {
+       if (gpio_is_valid(dev->mach->gpio_vbus)) {
                free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev);
                gpio_free(dev->mach->gpio_vbus);
        }
-       if (dev->mach->gpio_pullup)
+       if (gpio_is_valid(dev->mach->gpio_pullup))
                gpio_free(dev->mach->gpio_pullup);
 
        clk_put(dev->clk);
@@ -2329,7 +2331,7 @@ static int pxa25x_udc_suspend(struct platform_device *dev, pm_message_t state)
        struct pxa25x_udc       *udc = platform_get_drvdata(dev);
        unsigned long flags;
 
-       if (!udc->mach->gpio_pullup && !udc->mach->udc_command)
+       if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command)
                WARNING("USB host won't detect disconnect!\n");
        udc->suspended = 1;
 
index 2b4660e08c4db367af0e6c5159855b675616eb9a..ca41b0b5afb352233e86c5ccbd45dace08f4431a 100644 (file)
@@ -442,6 +442,8 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 
        case OID_802_3_MAC_OPTIONS:
                pr_debug("%s: OID_802_3_MAC_OPTIONS\n", __func__);
+               *outbuf = cpu_to_le32(0);
+               retval = 0;
                break;
 
        /* ieee802.3 statistics OIDs (table 4-4) */
index 9a2b8920532d0ad0fa248a7ca073051d55be8405..a9b452fe622195ad832acdc78fba40759218f820 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index 1576a0520adf35ba813ef9ebd30cd8fb28f16e62..1a920c70b5a150f0a2670f8d170d579c582544ac 100644 (file)
@@ -181,26 +181,27 @@ config USB_OHCI_HCD_PPC_SOC
          Enables support for the USB controller on the MPC52xx or
          STB03xxx processor chip.  If unsure, say Y.
 
-config USB_OHCI_HCD_PPC_OF
-       bool "OHCI support for PPC USB controller on OF platform bus"
-       depends on USB_OHCI_HCD && PPC_OF
-       default y
-       ---help---
-         Enables support for the USB controller PowerPC present on the
-         OpenFirmware platform bus.
-
 config USB_OHCI_HCD_PPC_OF_BE
-       bool "Support big endian HC"
-       depends on USB_OHCI_HCD_PPC_OF
-       default y
+       bool "OHCI support for OF platform bus (big endian)"
+       depends on USB_OHCI_HCD && PPC_OF
        select USB_OHCI_BIG_ENDIAN_DESC
        select USB_OHCI_BIG_ENDIAN_MMIO
+       ---help---
+         Enables support for big-endian USB controllers present on the
+         OpenFirmware platform bus.
 
 config USB_OHCI_HCD_PPC_OF_LE
-       bool "Support little endian HC"
-       depends on USB_OHCI_HCD_PPC_OF
-       default n
+       bool "OHCI support for OF platform bus (little endian)"
+       depends on USB_OHCI_HCD && PPC_OF
        select USB_OHCI_LITTLE_ENDIAN
+       ---help---
+         Enables support for little-endian USB controllers present on the
+         OpenFirmware platform bus.
+
+config USB_OHCI_HCD_PPC_OF
+       bool
+       depends on USB_OHCI_HCD && PPC_OF
+       default USB_OHCI_HCD_PPC_OF_BE || USB_OHCI_HCD_PPC_OF_LE
 
 config USB_OHCI_HCD_PCI
        bool "OHCI support for PCI-bus USB controllers"
@@ -337,10 +338,10 @@ config USB_R8A66597_HCD
 
 config SUPERH_ON_CHIP_R8A66597
        boolean "Enable SuperH on-chip R8A66597 USB"
-       depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723)
+       depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7724)
        help
           This driver enables support for the on-chip R8A66597 in the
-          SH7366 and SH7723 processors.
+          SH7366, SH7723 and SH7724 processors.
 
 config USB_WHCI_HCD
        tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)"
index c3a778bd359c9b883bd6e361e78951818fd3a280..59d208d94d4e772d5b1a8cc6f8a009d94132625f 100644 (file)
@@ -113,6 +113,8 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
        .bus_resume             = ehci_bus_resume,
        .relinquish_port        = ehci_relinquish_port,
        .port_handed_over       = ehci_port_handed_over,
+
+       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
 };
 
 static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
index bf86809c5120795eac8521b68e2159d2fef37127..991174937db31ed5d829d6e1fdc0b3ea024e47bd 100644 (file)
@@ -325,6 +325,8 @@ static const struct hc_driver ehci_fsl_hc_driver = {
        .bus_resume = ehci_bus_resume,
        .relinquish_port = ehci_relinquish_port,
        .port_handed_over = ehci_port_handed_over,
+
+       .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
 };
 
 static int ehci_fsl_drv_probe(struct platform_device *pdev)
index 2b72473544d31d798034ed5aa92cb555384a8055..11c627ce60224754978bf495e40cd94496c3b7c7 100644 (file)
@@ -903,7 +903,8 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                        /* already started */
                        break;
                case QH_STATE_IDLE:
-                       WARN_ON(1);
+                       /* QH might be waiting for a Clear-TT-Buffer */
+                       qh_completions(ehci, qh);
                        break;
                }
                break;
@@ -1003,6 +1004,8 @@ idle_timeout:
                schedule_timeout_uninterruptible(1);
                goto rescan;
        case QH_STATE_IDLE:             /* fully unlinked */
+               if (qh->clearing_tt)
+                       goto idle_timeout;
                if (list_empty (&qh->qtd_list)) {
                        qh_put (qh);
                        break;
@@ -1030,12 +1033,14 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
        struct ehci_qh          *qh;
        int                     eptype = usb_endpoint_type(&ep->desc);
+       int                     epnum = usb_endpoint_num(&ep->desc);
+       int                     is_out = usb_endpoint_dir_out(&ep->desc);
+       unsigned long           flags;
 
        if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT)
                return;
 
- rescan:
-       spin_lock_irq(&ehci->lock);
+       spin_lock_irqsave(&ehci->lock, flags);
        qh = ep->hcpriv;
 
        /* For Bulk and Interrupt endpoints we maintain the toggle state
@@ -1044,29 +1049,24 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
         * the toggle bit in the QH.
         */
        if (qh) {
+               usb_settoggle(qh->dev, epnum, is_out, 0);
                if (!list_empty(&qh->qtd_list)) {
                        WARN_ONCE(1, "clear_halt for a busy endpoint\n");
-               } else if (qh->qh_state == QH_STATE_IDLE) {
-                       qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
-               } else {
-                       /* It's not safe to write into the overlay area
-                        * while the QH is active.  Unlink it first and
-                        * wait for the unlink to complete.
+               } else if (qh->qh_state == QH_STATE_LINKED) {
+
+                       /* The toggle value in the QH can't be updated
+                        * while the QH is active.  Unlink it now;
+                        * re-linking will call qh_refresh().
                         */
-                       if (qh->qh_state == QH_STATE_LINKED) {
-                               if (eptype == USB_ENDPOINT_XFER_BULK) {
-                                       unlink_async(ehci, qh);
-                               } else {
-                                       intr_deschedule(ehci, qh);
-                                       (void) qh_schedule(ehci, qh);
-                               }
+                       if (eptype == USB_ENDPOINT_XFER_BULK) {
+                               unlink_async(ehci, qh);
+                       } else {
+                               intr_deschedule(ehci, qh);
+                               (void) qh_schedule(ehci, qh);
                        }
-                       spin_unlock_irq(&ehci->lock);
-                       schedule_timeout_uninterruptible(1);
-                       goto rescan;
                }
        }
-       spin_unlock_irq(&ehci->lock);
+       spin_unlock_irqrestore(&ehci->lock, flags);
 }
 
 static int ehci_get_frame (struct usb_hcd *hcd)
index a44bb4a949543d797f336827edb8ac6fa088d8ac..89b7c70c6ed6f015077a6a0233b78b080f581043 100644 (file)
@@ -61,6 +61,8 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = {
 #endif
        .relinquish_port        = ehci_relinquish_port,
        .port_handed_over       = ehci_port_handed_over,
+
+       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
 };
 
 static int ixp4xx_ehci_probe(struct platform_device *pdev)
index 770dd9aba62a9f07aabd9863e59fc4acae6a81dd..1d283e1b2b8de543e56f4e695e333383ee5d116d 100644 (file)
@@ -105,6 +105,7 @@ static int ehci_orion_setup(struct usb_hcd *hcd)
        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
        int retval;
 
+       ehci_reset(ehci);
        retval = ehci_halt(ehci);
        if (retval)
                return retval;
@@ -118,7 +119,6 @@ static int ehci_orion_setup(struct usb_hcd *hcd)
 
        hcd->has_tt = 1;
 
-       ehci_reset(ehci);
        ehci_port_power(ehci, 0);
 
        return retval;
@@ -165,6 +165,8 @@ static const struct hc_driver ehci_orion_hc_driver = {
        .bus_resume = ehci_bus_resume,
        .relinquish_port = ehci_relinquish_port,
        .port_handed_over = ehci_port_handed_over,
+
+       .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
 };
 
 static void __init
index f3683e1da16134b3c20a6239b5edfd406af923aa..c2f1b7df918cd52ddd62385e3f02f5696d7f6f06 100644 (file)
@@ -404,6 +404,8 @@ static const struct hc_driver ehci_pci_hc_driver = {
        .bus_resume =           ehci_bus_resume,
        .relinquish_port =      ehci_relinquish_port,
        .port_handed_over =     ehci_port_handed_over,
+
+       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
 };
 
 /*-------------------------------------------------------------------------*/
index fbd272288fc2cf799ef1d075adea282dd01aa863..36f96da129f5c637208031ec04913be3f0cc6e67 100644 (file)
@@ -79,6 +79,8 @@ static const struct hc_driver ehci_ppc_of_hc_driver = {
 #endif
        .relinquish_port        = ehci_relinquish_port,
        .port_handed_over       = ehci_port_handed_over,
+
+       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
 };
 
 
index 93f7035d00a16ad1da984e9f1b81c521afa79cba..1dee33b9139e65d1f8714234c7ecde9e7b3d0d24 100644 (file)
@@ -75,6 +75,8 @@ static const struct hc_driver ps3_ehci_hc_driver = {
 #endif
        .relinquish_port        = ehci_relinquish_port,
        .port_handed_over       = ehci_port_handed_over,
+
+       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
 };
 
 static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev)
index 3192f683f8073293a6366b532ced3ff0dd5007f1..7673554fa64df28317e4edb9e97eecedd3272fc8 100644 (file)
@@ -93,6 +93,22 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
        qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
        qh->hw_alt_next = EHCI_LIST_END(ehci);
 
+       /* Except for control endpoints, we make hardware maintain data
+        * toggle (like OHCI) ... here (re)initialize the toggle in the QH,
+        * and set the pseudo-toggle in udev. Only usb_clear_halt() will
+        * ever clear it.
+        */
+       if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) {
+               unsigned        is_out, epnum;
+
+               is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8));
+               epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f;
+               if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
+                       qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE);
+                       usb_settoggle (qh->dev, epnum, is_out, 1);
+               }
+       }
+
        /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */
        wmb ();
        qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING);
@@ -123,6 +139,55 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 /*-------------------------------------------------------------------------*/
 
+static void qh_link_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
+
+static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd,
+               struct usb_host_endpoint *ep)
+{
+       struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
+       struct ehci_qh          *qh = ep->hcpriv;
+       unsigned long           flags;
+
+       spin_lock_irqsave(&ehci->lock, flags);
+       qh->clearing_tt = 0;
+       if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list)
+                       && HC_IS_RUNNING(hcd->state))
+               qh_link_async(ehci, qh);
+       spin_unlock_irqrestore(&ehci->lock, flags);
+}
+
+static void ehci_clear_tt_buffer(struct ehci_hcd *ehci, struct ehci_qh *qh,
+               struct urb *urb, u32 token)
+{
+
+       /* If an async split transaction gets an error or is unlinked,
+        * the TT buffer may be left in an indeterminate state.  We
+        * have to clear the TT buffer.
+        *
+        * Note: this routine is never called for Isochronous transfers.
+        */
+       if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) {
+#ifdef DEBUG
+               struct usb_device *tt = urb->dev->tt->hub;
+               dev_dbg(&tt->dev,
+                       "clear tt buffer port %d, a%d ep%d t%08x\n",
+                       urb->dev->ttport, urb->dev->devnum,
+                       usb_pipeendpoint(urb->pipe), token);
+#endif /* DEBUG */
+               if (!ehci_is_TDI(ehci)
+                               || urb->dev->tt->hub !=
+                                  ehci_to_hcd(ehci)->self.root_hub) {
+                       if (usb_hub_clear_tt_buffer(urb) == 0)
+                               qh->clearing_tt = 1;
+               } else {
+
+                       /* REVISIT ARC-derived cores don't clear the root
+                        * hub TT buffer in this way...
+                        */
+               }
+       }
+}
+
 static int qtd_copy_status (
        struct ehci_hcd *ehci,
        struct urb *urb,
@@ -149,6 +214,14 @@ static int qtd_copy_status (
                if (token & QTD_STS_BABBLE) {
                        /* FIXME "must" disable babbling device's port too */
                        status = -EOVERFLOW;
+               /* CERR nonzero + halt --> stall */
+               } else if (QTD_CERR(token)) {
+                       status = -EPIPE;
+
+               /* In theory, more than one of the following bits can be set
+                * since they are sticky and the transaction is retried.
+                * Which to test first is rather arbitrary.
+                */
                } else if (token & QTD_STS_MMF) {
                        /* fs/ls interrupt xfer missed the complete-split */
                        status = -EPROTO;
@@ -157,21 +230,15 @@ static int qtd_copy_status (
                                ? -ENOSR  /* hc couldn't read data */
                                : -ECOMM; /* hc couldn't write data */
                } else if (token & QTD_STS_XACT) {
-                       /* timeout, bad crc, wrong PID, etc; retried */
-                       if (QTD_CERR (token))
-                               status = -EPIPE;
-                       else {
-                               ehci_dbg (ehci, "devpath %s ep%d%s 3strikes\n",
-                                       urb->dev->devpath,
-                                       usb_pipeendpoint (urb->pipe),
-                                       usb_pipein (urb->pipe) ? "in" : "out");
-                               status = -EPROTO;
-                       }
-               /* CERR nonzero + no errors + halt --> stall */
-               } else if (QTD_CERR (token))
-                       status = -EPIPE;
-               else    /* unknown */
+                       /* timeout, bad CRC, wrong PID, etc */
+                       ehci_dbg(ehci, "devpath %s ep%d%s 3strikes\n",
+                               urb->dev->devpath,
+                               usb_pipeendpoint(urb->pipe),
+                               usb_pipein(urb->pipe) ? "in" : "out");
                        status = -EPROTO;
+               } else {        /* unknown */
+                       status = -EPROTO;
+               }
 
                ehci_vdbg (ehci,
                        "dev%d ep%d%s qtd token %08x --> status %d\n",
@@ -179,28 +246,6 @@ static int qtd_copy_status (
                        usb_pipeendpoint (urb->pipe),
                        usb_pipein (urb->pipe) ? "in" : "out",
                        token, status);
-
-               /* if async CSPLIT failed, try cleaning out the TT buffer */
-               if (status != -EPIPE
-                               && urb->dev->tt
-                               && !usb_pipeint(urb->pipe)
-                               && ((token & QTD_STS_MMF) != 0
-                                       || QTD_CERR(token) == 0)
-                               && (!ehci_is_TDI(ehci)
-                                       || urb->dev->tt->hub !=
-                                          ehci_to_hcd(ehci)->self.root_hub)) {
-#ifdef DEBUG
-                       struct usb_device *tt = urb->dev->tt->hub;
-                       dev_dbg (&tt->dev,
-                               "clear tt buffer port %d, a%d ep%d t%08x\n",
-                               urb->dev->ttport, urb->dev->devnum,
-                               usb_pipeendpoint (urb->pipe), token);
-#endif /* DEBUG */
-                       /* REVISIT ARC-derived cores don't clear the root
-                        * hub TT buffer in this way...
-                        */
-                       usb_hub_tt_clear_buffer (urb->dev, urb->pipe);
-               }
        }
 
        return status;
@@ -330,12 +375,11 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
                                 */
                                if ((token & QTD_STS_XACT) &&
                                                QTD_CERR(token) == 0 &&
-                                               --qh->xacterrs > 0 &&
+                                               ++qh->xacterrs < QH_XACTERR_MAX &&
                                                !urb->unlinked) {
                                        ehci_dbg(ehci,
        "detected XactErr len %zu/%zu retry %d\n",
-       qtd->length - QTD_LENGTH(token), qtd->length,
-       QH_XACTERR_MAX - qh->xacterrs);
+       qtd->length - QTD_LENGTH(token), qtd->length, qh->xacterrs);
 
                                        /* reset the token in the qtd and the
                                         * qh overlay (which still contains
@@ -391,9 +435,16 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
                        /* qh unlinked; token in overlay may be most current */
                        if (state == QH_STATE_IDLE
                                        && cpu_to_hc32(ehci, qtd->qtd_dma)
-                                               == qh->hw_current)
+                                               == qh->hw_current) {
                                token = hc32_to_cpu(ehci, qh->hw_token);
 
+                               /* An unlink may leave an incomplete
+                                * async transaction in the TT buffer.
+                                * We have to clear it.
+                                */
+                               ehci_clear_tt_buffer(ehci, qh, urb, token);
+                       }
+
                        /* force halt for unlinked or blocked qh, so we'll
                         * patch the qh later and so that completions can't
                         * activate it while we "know" it's stopped.
@@ -419,6 +470,13 @@ halt:
                                        && (qtd->hw_alt_next
                                                & EHCI_LIST_END(ehci)))
                                last_status = -EINPROGRESS;
+
+                       /* As part of low/full-speed endpoint-halt processing
+                        * we must clear the TT buffer (11.17.5).
+                        */
+                       if (unlikely(last_status != -EINPROGRESS &&
+                                       last_status != -EREMOTEIO))
+                               ehci_clear_tt_buffer(ehci, qh, urb, token);
                }
 
                /* if we're removing something not at the queue head,
@@ -435,7 +493,7 @@ halt:
                last = qtd;
 
                /* reinit the xacterr counter for the next qtd */
-               qh->xacterrs = QH_XACTERR_MAX;
+               qh->xacterrs = 0;
        }
 
        /* last urb's completion might still need calling */
@@ -834,6 +892,7 @@ done:
        qh->qh_state = QH_STATE_IDLE;
        qh->hw_info1 = cpu_to_hc32(ehci, info1);
        qh->hw_info2 = cpu_to_hc32(ehci, info2);
+       usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
        qh_refresh (ehci, qh);
        return qh;
 }
@@ -847,6 +906,10 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
        __hc32          dma = QH_NEXT(ehci, qh->qh_dma);
        struct ehci_qh  *head;
 
+       /* Don't link a QH if there's a Clear-TT-Buffer pending */
+       if (unlikely(qh->clearing_tt))
+               return;
+
        /* (re)start the async schedule? */
        head = ehci->async;
        timer_action_done (ehci, TIMER_ASYNC_OFF);
@@ -864,7 +927,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
                }
        }
 
-       /* clear halt and maybe recover from silicon quirk */
+       /* clear halt and/or toggle; and maybe recover from silicon quirk */
        if (qh->qh_state == QH_STATE_IDLE)
                qh_refresh (ehci, qh);
 
@@ -876,7 +939,8 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
        head->qh_next.qh = qh;
        head->hw_next = dma;
 
-       qh->xacterrs = QH_XACTERR_MAX;
+       qh_get(qh);
+       qh->xacterrs = 0;
        qh->qh_state = QH_STATE_LINKED;
        /* qtd completions reported later by interrupt */
 }
@@ -1016,7 +1080,7 @@ submit_async (
         * the HC and TT handle it when the TT has a buffer ready.
         */
        if (likely (qh->qh_state == QH_STATE_IDLE))
-               qh_link_async (ehci, qh_get (qh));
+               qh_link_async(ehci, qh);
  done:
        spin_unlock_irqrestore (&ehci->lock, flags);
        if (unlikely (qh == NULL))
@@ -1051,8 +1115,6 @@ static void end_unlink_async (struct ehci_hcd *ehci)
                        && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
                qh_link_async (ehci, qh);
        else {
-               qh_put (qh);            // refcount from async list
-
                /* it's not free to turn the async schedule on/off; leave it
                 * active but idle for a while once it empties.
                 */
@@ -1060,6 +1122,7 @@ static void end_unlink_async (struct ehci_hcd *ehci)
                                && ehci->async->qh_next.qh == NULL)
                        timer_action (ehci, TIMER_ASYNC_OFF);
        }
+       qh_put(qh);                     /* refcount from async list */
 
        if (next) {
                ehci->reclaim = NULL;
index 9d1babc7ff6553c64de8cec32fcfcff3f5ce5967..edd61ee90323ce99a5b8fe9eba5fec0c18b2fd23 100644 (file)
@@ -542,6 +542,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
                }
        }
        qh->qh_state = QH_STATE_LINKED;
+       qh->xacterrs = 0;
        qh_get (qh);
 
        /* update per-qh bandwidth for usbfs */
@@ -1619,11 +1620,14 @@ itd_complete (
                                desc->status = -EPROTO;
 
                        /* HC need not update length with this error */
-                       if (!(t & EHCI_ISOC_BABBLE))
-                               desc->actual_length = EHCI_ITD_LENGTH (t);
+                       if (!(t & EHCI_ISOC_BABBLE)) {
+                               desc->actual_length = EHCI_ITD_LENGTH(t);
+                               urb->actual_length += desc->actual_length;
+                       }
                } else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) {
                        desc->status = 0;
-                       desc->actual_length = EHCI_ITD_LENGTH (t);
+                       desc->actual_length = EHCI_ITD_LENGTH(t);
+                       urb->actual_length += desc->actual_length;
                } else {
                        /* URB was too late */
                        desc->status = -EXDEV;
@@ -2014,7 +2018,8 @@ sitd_complete (
                        desc->status = -EPROTO;
        } else {
                desc->status = 0;
-               desc->actual_length = desc->length - SITD_LENGTH (t);
+               desc->actual_length = desc->length - SITD_LENGTH(t);
+               urb->actual_length += desc->actual_length;
        }
        stream->depth -= stream->interval << 3;
 
index 90ad3395bb21f0f96923ab21431dc7c44165badb..2bfff30f4704f7521678239df30c07323e0d3e59 100644 (file)
@@ -354,7 +354,9 @@ struct ehci_qh {
        unsigned short          period;         /* polling interval */
        unsigned short          start;          /* where polling starts */
 #define NO_FRAME ((unsigned short)~0)                  /* pick new start */
+
        struct usb_device       *dev;           /* access to TT */
+       unsigned                clearing_tt:1;  /* Clear-TT-Buf in progress */
 } __attribute__ ((aligned (32)));
 
 /*-------------------------------------------------------------------------*/
index bb63b68ddb7745486e841f3bdb73b011d1be12da..62a226b616707a2dcb0ba7667f537f4d8bb7481c 100644 (file)
@@ -576,9 +576,7 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd)
                        out_be16(&usb->fhci->regs->usb_event,
                                 usb->saved_msk);
                } else if (usb->port_status == FHCI_PORT_DISABLED) {
-                       if (fhci_ioports_check_bus_state(fhci) == 1 &&
-                                       usb->port_status != FHCI_PORT_LOW &&
-                                       usb->port_status != FHCI_PORT_FULL)
+                       if (fhci_ioports_check_bus_state(fhci) == 1)
                                fhci_device_connected_interrupt(fhci);
                }
                usb_er &= ~USB_E_RESET_MASK;
@@ -605,9 +603,7 @@ irqreturn_t fhci_irq(struct usb_hcd *hcd)
        }
 
        if (usb_er & USB_E_IDLE_MASK) {
-               if (usb->port_status == FHCI_PORT_DISABLED &&
-                               usb->port_status != FHCI_PORT_LOW &&
-                               usb->port_status != FHCI_PORT_FULL) {
+               if (usb->port_status == FHCI_PORT_DISABLED) {
                        usb_er &= ~USB_E_RESET_MASK;
                        fhci_device_connected_interrupt(fhci);
                } else if (usb->port_status ==
index 3fa3a17027963af75a2d15d5c5da7990b7c5fc7f..d4feebfc63bd1b51088a9e22cc618db1eb0f092b 100644 (file)
@@ -361,7 +361,7 @@ static int __devexit isp1760_plat_remove(struct platform_device *pdev)
 
 static struct platform_driver isp1760_plat_driver = {
        .probe  = isp1760_plat_probe,
-       .remove = isp1760_plat_remove,
+       .remove = __devexit_p(isp1760_plat_remove),
        .driver = {
                .name   = "isp1760",
        },
index f3aaba35e912fba4e021e3a6fcf7dd1c22d1153f..83cbecd2a1ed7177029d8f52b7a512b959f9e2b1 100644 (file)
@@ -282,6 +282,7 @@ static int ohci_omap_init(struct usb_hcd *hcd)
 static void ohci_omap_stop(struct usb_hcd *hcd)
 {
        dev_dbg(hcd->self.controller, "stopping USB Controller\n");
+       ohci_stop(hcd);
        omap_ohci_clock_power(0);
 }
 
index 56976cc0352a9ae9e87a0a1cb681135410e0e581..e18f74946e6824a427bd5b3b0185ee79ffebcd35 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/timer.h>
index 2501c571f855263f21200265888d58602deac86f..705e34324156f069ce4d56f7e596732bbc2fcc93 100644 (file)
@@ -173,6 +173,7 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int
 {
        void *addr;
        u32 temp;
+       u64 temp_64;
 
        addr = &ir_set->irq_pending;
        temp = xhci_readl(xhci, addr);
@@ -200,25 +201,15 @@ void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int
                xhci_dbg(xhci, "  WARN: %p: ir_set.rsvd = 0x%x\n",
                                addr, (unsigned int)temp);
 
-       addr = &ir_set->erst_base[0];
-       temp = xhci_readl(xhci, addr);
-       xhci_dbg(xhci, "  %p: ir_set.erst_base[0] = 0x%x\n",
-                       addr, (unsigned int) temp);
-
-       addr = &ir_set->erst_base[1];
-       temp = xhci_readl(xhci, addr);
-       xhci_dbg(xhci, "  %p: ir_set.erst_base[1] = 0x%x\n",
-                       addr, (unsigned int) temp);
+       addr = &ir_set->erst_base;
+       temp_64 = xhci_read_64(xhci, addr);
+       xhci_dbg(xhci, "  %p: ir_set.erst_base = @%08llx\n",
+                       addr, temp_64);
 
-       addr = &ir_set->erst_dequeue[0];
-       temp = xhci_readl(xhci, addr);
-       xhci_dbg(xhci, "  %p: ir_set.erst_dequeue[0] = 0x%x\n",
-                       addr, (unsigned int) temp);
-
-       addr = &ir_set->erst_dequeue[1];
-       temp = xhci_readl(xhci, addr);
-       xhci_dbg(xhci, "  %p: ir_set.erst_dequeue[1] = 0x%x\n",
-                       addr, (unsigned int) temp);
+       addr = &ir_set->erst_dequeue;
+       temp_64 = xhci_read_64(xhci, addr);
+       xhci_dbg(xhci, "  %p: ir_set.erst_dequeue = @%08llx\n",
+                       addr, temp_64);
 }
 
 void xhci_print_run_regs(struct xhci_hcd *xhci)
@@ -268,8 +259,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
                xhci_dbg(xhci, "Link TRB:\n");
                xhci_print_trb_offsets(xhci, trb);
 
-               address = trb->link.segment_ptr[0] +
-                       (((u64) trb->link.segment_ptr[1]) << 32);
+               address = trb->link.segment_ptr;
                xhci_dbg(xhci, "Next ring segment DMA address = 0x%llx\n", address);
 
                xhci_dbg(xhci, "Interrupter target = 0x%x\n",
@@ -282,8 +272,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
                                (unsigned int) (trb->link.control & TRB_NO_SNOOP));
                break;
        case TRB_TYPE(TRB_TRANSFER):
-               address = trb->trans_event.buffer[0] +
-                       (((u64) trb->trans_event.buffer[1]) << 32);
+               address = trb->trans_event.buffer;
                /*
                 * FIXME: look at flags to figure out if it's an address or if
                 * the data is directly in the buffer field.
@@ -291,8 +280,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
                xhci_dbg(xhci, "DMA address or buffer contents= %llu\n", address);
                break;
        case TRB_TYPE(TRB_COMPLETION):
-               address = trb->event_cmd.cmd_trb[0] +
-                       (((u64) trb->event_cmd.cmd_trb[1]) << 32);
+               address = trb->event_cmd.cmd_trb;
                xhci_dbg(xhci, "Command TRB pointer = %llu\n", address);
                xhci_dbg(xhci, "Completion status = %u\n",
                                (unsigned int) GET_COMP_CODE(trb->event_cmd.status));
@@ -328,8 +316,8 @@ void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg)
        for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
                trb = &seg->trbs[i];
                xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", addr,
-                               (unsigned int) trb->link.segment_ptr[0],
-                               (unsigned int) trb->link.segment_ptr[1],
+                               lower_32_bits(trb->link.segment_ptr),
+                               upper_32_bits(trb->link.segment_ptr),
                                (unsigned int) trb->link.intr_target,
                                (unsigned int) trb->link.control);
                addr += sizeof(*trb);
@@ -386,8 +374,8 @@ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
                entry = &erst->entries[i];
                xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n",
                                (unsigned int) addr,
-                               (unsigned int) entry->seg_addr[0],
-                               (unsigned int) entry->seg_addr[1],
+                               lower_32_bits(entry->seg_addr),
+                               upper_32_bits(entry->seg_addr),
                                (unsigned int) entry->seg_size,
                                (unsigned int) entry->rsvd);
                addr += sizeof(*entry);
@@ -396,90 +384,147 @@ void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
 
 void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci)
 {
-       u32 val;
+       u64 val;
 
-       val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[0]);
-       xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = 0x%x\n", val);
-       val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[1]);
-       xhci_dbg(xhci, "// xHC command ring deq ptr high bits = 0x%x\n", val);
+       val = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
+       xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = @%08x\n",
+                       lower_32_bits(val));
+       xhci_dbg(xhci, "// xHC command ring deq ptr high bits = @%08x\n",
+                       upper_32_bits(val));
 }
 
-void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep)
+/* Print the last 32 bytes for 64-byte contexts */
+static void dbg_rsvd64(struct xhci_hcd *xhci, u64 *ctx, dma_addr_t dma)
+{
+       int i;
+       for (i = 0; i < 4; ++i) {
+               xhci_dbg(xhci, "@%p (virt) @%08llx "
+                        "(dma) %#08llx - rsvd64[%d]\n",
+                        &ctx[4 + i], (unsigned long long)dma,
+                        ctx[4 + i], i);
+               dma += 8;
+       }
+}
+
+void xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx)
 {
-       int i, j;
-       int last_ep_ctx = 31;
        /* Fields are 32 bits wide, DMA addresses are in bytes */
        int field_size = 32 / 8;
+       int i;
 
-       xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n",
-                       &ctx->drop_flags, (unsigned long long)dma,
-                       ctx->drop_flags);
-       dma += field_size;
-       xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n",
-                       &ctx->add_flags, (unsigned long long)dma,
-                       ctx->add_flags);
-       dma += field_size;
-       for (i = 0; i > 6; ++i) {
-               xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
-                               &ctx->rsvd[i], (unsigned long long)dma,
-                               ctx->rsvd[i], i);
-               dma += field_size;
-       }
+       struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
+       dma_addr_t dma = ctx->dma + ((unsigned long)slot_ctx - (unsigned long)ctx);
+       int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
 
        xhci_dbg(xhci, "Slot Context:\n");
        xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info\n",
-                       &ctx->slot.dev_info,
-                       (unsigned long long)dma, ctx->slot.dev_info);
+                       &slot_ctx->dev_info,
+                       (unsigned long long)dma, slot_ctx->dev_info);
        dma += field_size;
        xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info2\n",
-                       &ctx->slot.dev_info2,
-                       (unsigned long long)dma, ctx->slot.dev_info2);
+                       &slot_ctx->dev_info2,
+                       (unsigned long long)dma, slot_ctx->dev_info2);
        dma += field_size;
        xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tt_info\n",
-                       &ctx->slot.tt_info,
-                       (unsigned long long)dma, ctx->slot.tt_info);
+                       &slot_ctx->tt_info,
+                       (unsigned long long)dma, slot_ctx->tt_info);
        dma += field_size;
        xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_state\n",
-                       &ctx->slot.dev_state,
-                       (unsigned long long)dma, ctx->slot.dev_state);
+                       &slot_ctx->dev_state,
+                       (unsigned long long)dma, slot_ctx->dev_state);
        dma += field_size;
-       for (i = 0; i > 4; ++i) {
+       for (i = 0; i < 4; ++i) {
                xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
-                               &ctx->slot.reserved[i], (unsigned long long)dma,
-                               ctx->slot.reserved[i], i);
+                               &slot_ctx->reserved[i], (unsigned long long)dma,
+                               slot_ctx->reserved[i], i);
                dma += field_size;
        }
 
+       if (csz)
+               dbg_rsvd64(xhci, (u64 *)slot_ctx, dma);
+}
+
+void xhci_dbg_ep_ctx(struct xhci_hcd *xhci,
+                    struct xhci_container_ctx *ctx,
+                    unsigned int last_ep)
+{
+       int i, j;
+       int last_ep_ctx = 31;
+       /* Fields are 32 bits wide, DMA addresses are in bytes */
+       int field_size = 32 / 8;
+       int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
+
        if (last_ep < 31)
                last_ep_ctx = last_ep + 1;
        for (i = 0; i < last_ep_ctx; ++i) {
+               struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, ctx, i);
+               dma_addr_t dma = ctx->dma +
+                       ((unsigned long)ep_ctx - (unsigned long)ctx);
+
                xhci_dbg(xhci, "Endpoint %02d Context:\n", i);
                xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n",
-                               &ctx->ep[i].ep_info,
-                               (unsigned long long)dma, ctx->ep[i].ep_info);
+                               &ep_ctx->ep_info,
+                               (unsigned long long)dma, ep_ctx->ep_info);
                dma += field_size;
                xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info2\n",
-                               &ctx->ep[i].ep_info2,
-                               (unsigned long long)dma, ctx->ep[i].ep_info2);
-               dma += field_size;
-               xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - deq[0]\n",
-                               &ctx->ep[i].deq[0],
-                               (unsigned long long)dma, ctx->ep[i].deq[0]);
-               dma += field_size;
-               xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - deq[1]\n",
-                               &ctx->ep[i].deq[1],
-                               (unsigned long long)dma, ctx->ep[i].deq[1]);
+                               &ep_ctx->ep_info2,
+                               (unsigned long long)dma, ep_ctx->ep_info2);
                dma += field_size;
+               xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08llx - deq\n",
+                               &ep_ctx->deq,
+                               (unsigned long long)dma, ep_ctx->deq);
+               dma += 2*field_size;
                xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tx_info\n",
-                               &ctx->ep[i].tx_info,
-                               (unsigned long long)dma, ctx->ep[i].tx_info);
+                               &ep_ctx->tx_info,
+                               (unsigned long long)dma, ep_ctx->tx_info);
                dma += field_size;
                for (j = 0; j < 3; ++j) {
                        xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
-                                       &ctx->ep[i].reserved[j],
+                                       &ep_ctx->reserved[j],
                                        (unsigned long long)dma,
-                                       ctx->ep[i].reserved[j], j);
+                                       ep_ctx->reserved[j], j);
+                       dma += field_size;
+               }
+
+               if (csz)
+                       dbg_rsvd64(xhci, (u64 *)ep_ctx, dma);
+       }
+}
+
+void xhci_dbg_ctx(struct xhci_hcd *xhci,
+                 struct xhci_container_ctx *ctx,
+                 unsigned int last_ep)
+{
+       int i;
+       /* Fields are 32 bits wide, DMA addresses are in bytes */
+       int field_size = 32 / 8;
+       struct xhci_slot_ctx *slot_ctx;
+       dma_addr_t dma = ctx->dma;
+       int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
+
+       if (ctx->type == XHCI_CTX_TYPE_INPUT) {
+               struct xhci_input_control_ctx *ctrl_ctx =
+                       xhci_get_input_control_ctx(xhci, ctx);
+               xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n",
+                        &ctrl_ctx->drop_flags, (unsigned long long)dma,
+                        ctrl_ctx->drop_flags);
+               dma += field_size;
+               xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n",
+                        &ctrl_ctx->add_flags, (unsigned long long)dma,
+                        ctrl_ctx->add_flags);
+               dma += field_size;
+               for (i = 0; i < 6; ++i) {
+                       xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd2[%d]\n",
+                                &ctrl_ctx->rsvd2[i], (unsigned long long)dma,
+                                ctrl_ctx->rsvd2[i], i);
                        dma += field_size;
                }
+
+               if (csz)
+                       dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma);
        }
+
+       slot_ctx = xhci_get_slot_ctx(xhci, ctx);
+       xhci_dbg_slot_ctx(xhci, ctx);
+       xhci_dbg_ep_ctx(xhci, ctx, last_ep);
 }
index dba3e07ccd09a1098660fb5c4a17c921deefc483..816c39caca1cf6bf5e1ca9b4a9c8c5d03684fcf3 100644 (file)
@@ -103,7 +103,10 @@ int xhci_reset(struct xhci_hcd *xhci)
        u32 state;
 
        state = xhci_readl(xhci, &xhci->op_regs->status);
-       BUG_ON((state & STS_HALT) == 0);
+       if ((state & STS_HALT) == 0) {
+               xhci_warn(xhci, "Host controller not halted, aborting reset.\n");
+               return 0;
+       }
 
        xhci_dbg(xhci, "// Reset the HC\n");
        command = xhci_readl(xhci, &xhci->op_regs->command);
@@ -226,6 +229,7 @@ int xhci_init(struct usb_hcd *hcd)
 static void xhci_work(struct xhci_hcd *xhci)
 {
        u32 temp;
+       u64 temp_64;
 
        /*
         * Clear the op reg interrupt status first,
@@ -248,9 +252,9 @@ static void xhci_work(struct xhci_hcd *xhci)
        /* FIXME this should be a delayed service routine that clears the EHB */
        xhci_handle_event(xhci);
 
-       /* Clear the event handler busy flag; the event ring should be empty. */
-       temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]);
-       xhci_writel(xhci, temp & ~ERST_EHB, &xhci->ir_set->erst_dequeue[0]);
+       /* Clear the event handler busy flag (RW1C); the event ring should be empty. */
+       temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+       xhci_write_64(xhci, temp_64 | ERST_EHB, &xhci->ir_set->erst_dequeue);
        /* Flush posted writes -- FIXME is this necessary? */
        xhci_readl(xhci, &xhci->ir_set->irq_pending);
 }
@@ -266,19 +270,34 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
        u32 temp, temp2;
+       union xhci_trb *trb;
 
        spin_lock(&xhci->lock);
+       trb = xhci->event_ring->dequeue;
        /* Check if the xHC generated the interrupt, or the irq is shared */
        temp = xhci_readl(xhci, &xhci->op_regs->status);
        temp2 = xhci_readl(xhci, &xhci->ir_set->irq_pending);
+       if (temp == 0xffffffff && temp2 == 0xffffffff)
+               goto hw_died;
+
        if (!(temp & STS_EINT) && !ER_IRQ_PENDING(temp2)) {
                spin_unlock(&xhci->lock);
                return IRQ_NONE;
        }
+       xhci_dbg(xhci, "op reg status = %08x\n", temp);
+       xhci_dbg(xhci, "ir set irq_pending = %08x\n", temp2);
+       xhci_dbg(xhci, "Event ring dequeue ptr:\n");
+       xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n",
+                       (unsigned long long)xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb),
+                       lower_32_bits(trb->link.segment_ptr),
+                       upper_32_bits(trb->link.segment_ptr),
+                       (unsigned int) trb->link.intr_target,
+                       (unsigned int) trb->link.control);
 
        if (temp & STS_FATAL) {
                xhci_warn(xhci, "WARNING: Host System Error\n");
                xhci_halt(xhci);
+hw_died:
                xhci_to_hcd(xhci)->state = HC_STATE_HALT;
                spin_unlock(&xhci->lock);
                return -ESHUTDOWN;
@@ -295,6 +314,7 @@ void xhci_event_ring_work(unsigned long arg)
 {
        unsigned long flags;
        int temp;
+       u64 temp_64;
        struct xhci_hcd *xhci = (struct xhci_hcd *) arg;
        int i, j;
 
@@ -311,9 +331,9 @@ void xhci_event_ring_work(unsigned long arg)
        xhci_dbg(xhci, "Event ring:\n");
        xhci_debug_segment(xhci, xhci->event_ring->deq_seg);
        xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
-       temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]);
-       temp &= ERST_PTR_MASK;
-       xhci_dbg(xhci, "ERST deq = 0x%x\n", temp);
+       temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+       temp_64 &= ~ERST_PTR_MASK;
+       xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64);
        xhci_dbg(xhci, "Command ring:\n");
        xhci_debug_segment(xhci, xhci->cmd_ring->deq_seg);
        xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
@@ -356,6 +376,7 @@ void xhci_event_ring_work(unsigned long arg)
 int xhci_run(struct usb_hcd *hcd)
 {
        u32 temp;
+       u64 temp_64;
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
        void (*doorbell)(struct xhci_hcd *) = NULL;
 
@@ -382,6 +403,20 @@ int xhci_run(struct usb_hcd *hcd)
        add_timer(&xhci->event_ring_timer);
 #endif
 
+       xhci_dbg(xhci, "Command ring memory map follows:\n");
+       xhci_debug_ring(xhci, xhci->cmd_ring);
+       xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
+       xhci_dbg_cmd_ptrs(xhci);
+
+       xhci_dbg(xhci, "ERST memory map follows:\n");
+       xhci_dbg_erst(xhci, &xhci->erst);
+       xhci_dbg(xhci, "Event ring:\n");
+       xhci_debug_ring(xhci, xhci->event_ring);
+       xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
+       temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+       temp_64 &= ~ERST_PTR_MASK;
+       xhci_dbg(xhci, "ERST deq = 64'h%0lx\n", (long unsigned int) temp_64);
+
        xhci_dbg(xhci, "// Set the interrupt modulation register\n");
        temp = xhci_readl(xhci, &xhci->ir_set->irq_control);
        temp &= ~ER_IRQ_INTERVAL_MASK;
@@ -406,22 +441,6 @@ int xhci_run(struct usb_hcd *hcd)
        if (NUM_TEST_NOOPS > 0)
                doorbell = xhci_setup_one_noop(xhci);
 
-       xhci_dbg(xhci, "Command ring memory map follows:\n");
-       xhci_debug_ring(xhci, xhci->cmd_ring);
-       xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
-       xhci_dbg_cmd_ptrs(xhci);
-
-       xhci_dbg(xhci, "ERST memory map follows:\n");
-       xhci_dbg_erst(xhci, &xhci->erst);
-       xhci_dbg(xhci, "Event ring:\n");
-       xhci_debug_ring(xhci, xhci->event_ring);
-       xhci_dbg_ring_ptrs(xhci, xhci->event_ring);
-       temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]);
-       temp &= ERST_PTR_MASK;
-       xhci_dbg(xhci, "ERST deq = 0x%x\n", temp);
-       temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[1]);
-       xhci_dbg(xhci, "ERST deq upper = 0x%x\n", temp);
-
        temp = xhci_readl(xhci, &xhci->op_regs->command);
        temp |= (CMD_RUN);
        xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
@@ -601,10 +620,13 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
                goto exit;
        }
        if (usb_endpoint_xfer_control(&urb->ep->desc))
-               ret = xhci_queue_ctrl_tx(xhci, mem_flags, urb,
+               /* We have a spinlock and interrupts disabled, so we must pass
+                * atomic context to this function, which may allocate memory.
+                */
+               ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb,
                                slot_id, ep_index);
        else if (usb_endpoint_xfer_bulk(&urb->ep->desc))
-               ret = xhci_queue_bulk_tx(xhci, mem_flags, urb,
+               ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb,
                                slot_id, ep_index);
        else
                ret = -EINVAL;
@@ -661,8 +683,12 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                goto done;
 
        xhci_dbg(xhci, "Cancel URB %p\n", urb);
+       xhci_dbg(xhci, "Event ring:\n");
+       xhci_debug_ring(xhci, xhci->event_ring);
        ep_index = xhci_get_endpoint_index(&urb->ep->desc);
        ep_ring = xhci->devs[urb->dev->slot_id]->ep_rings[ep_index];
+       xhci_dbg(xhci, "Endpoint ring:\n");
+       xhci_debug_ring(xhci, ep_ring);
        td = (struct xhci_td *) urb->hcpriv;
 
        ep_ring->cancels_pending++;
@@ -696,7 +722,9 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
                struct usb_host_endpoint *ep)
 {
        struct xhci_hcd *xhci;
-       struct xhci_device_control *in_ctx;
+       struct xhci_container_ctx *in_ctx, *out_ctx;
+       struct xhci_input_control_ctx *ctrl_ctx;
+       struct xhci_slot_ctx *slot_ctx;
        unsigned int last_ctx;
        unsigned int ep_index;
        struct xhci_ep_ctx *ep_ctx;
@@ -724,31 +752,34 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        }
 
        in_ctx = xhci->devs[udev->slot_id]->in_ctx;
+       out_ctx = xhci->devs[udev->slot_id]->out_ctx;
+       ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
        ep_index = xhci_get_endpoint_index(&ep->desc);
-       ep_ctx = &xhci->devs[udev->slot_id]->out_ctx->ep[ep_index];
+       ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
        /* If the HC already knows the endpoint is disabled,
         * or the HCD has noted it is disabled, ignore this request
         */
        if ((ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED ||
-                       in_ctx->drop_flags & xhci_get_endpoint_flag(&ep->desc)) {
+                       ctrl_ctx->drop_flags & xhci_get_endpoint_flag(&ep->desc)) {
                xhci_warn(xhci, "xHCI %s called with disabled ep %p\n",
                                __func__, ep);
                return 0;
        }
 
-       in_ctx->drop_flags |= drop_flag;
-       new_drop_flags = in_ctx->drop_flags;
+       ctrl_ctx->drop_flags |= drop_flag;
+       new_drop_flags = ctrl_ctx->drop_flags;
 
-       in_ctx->add_flags = ~drop_flag;
-       new_add_flags = in_ctx->add_flags;
+       ctrl_ctx->add_flags = ~drop_flag;
+       new_add_flags = ctrl_ctx->add_flags;
 
-       last_ctx = xhci_last_valid_endpoint(in_ctx->add_flags);
+       last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags);
+       slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
        /* Update the last valid endpoint context, if we deleted the last one */
-       if ((in_ctx->slot.dev_info & LAST_CTX_MASK) > LAST_CTX(last_ctx)) {
-               in_ctx->slot.dev_info &= ~LAST_CTX_MASK;
-               in_ctx->slot.dev_info |= LAST_CTX(last_ctx);
+       if ((slot_ctx->dev_info & LAST_CTX_MASK) > LAST_CTX(last_ctx)) {
+               slot_ctx->dev_info &= ~LAST_CTX_MASK;
+               slot_ctx->dev_info |= LAST_CTX(last_ctx);
        }
-       new_slot_info = in_ctx->slot.dev_info;
+       new_slot_info = slot_ctx->dev_info;
 
        xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
 
@@ -778,17 +809,22 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
                struct usb_host_endpoint *ep)
 {
        struct xhci_hcd *xhci;
-       struct xhci_device_control *in_ctx;
+       struct xhci_container_ctx *in_ctx, *out_ctx;
        unsigned int ep_index;
        struct xhci_ep_ctx *ep_ctx;
+       struct xhci_slot_ctx *slot_ctx;
+       struct xhci_input_control_ctx *ctrl_ctx;
        u32 added_ctxs;
        unsigned int last_ctx;
        u32 new_add_flags, new_drop_flags, new_slot_info;
        int ret = 0;
 
        ret = xhci_check_args(hcd, udev, ep, 1, __func__);
-       if (ret <= 0)
+       if (ret <= 0) {
+               /* So we won't queue a reset ep command for a root hub */
+               ep->hcpriv = NULL;
                return ret;
+       }
        xhci = hcd_to_xhci(hcd);
 
        added_ctxs = xhci_get_endpoint_flag(&ep->desc);
@@ -810,12 +846,14 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        }
 
        in_ctx = xhci->devs[udev->slot_id]->in_ctx;
+       out_ctx = xhci->devs[udev->slot_id]->out_ctx;
+       ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
        ep_index = xhci_get_endpoint_index(&ep->desc);
-       ep_ctx = &xhci->devs[udev->slot_id]->out_ctx->ep[ep_index];
+       ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
        /* If the HCD has already noted the endpoint is enabled,
         * ignore this request.
         */
-       if (in_ctx->add_flags & xhci_get_endpoint_flag(&ep->desc)) {
+       if (ctrl_ctx->add_flags & xhci_get_endpoint_flag(&ep->desc)) {
                xhci_warn(xhci, "xHCI %s called with enabled ep %p\n",
                                __func__, ep);
                return 0;
@@ -833,8 +871,8 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
                return -ENOMEM;
        }
 
-       in_ctx->add_flags |= added_ctxs;
-       new_add_flags = in_ctx->add_flags;
+       ctrl_ctx->add_flags |= added_ctxs;
+       new_add_flags = ctrl_ctx->add_flags;
 
        /* If xhci_endpoint_disable() was called for this endpoint, but the
         * xHC hasn't been notified yet through the check_bandwidth() call,
@@ -842,14 +880,18 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
         * descriptors.  We must drop and re-add this endpoint, so we leave the
         * drop flags alone.
         */
-       new_drop_flags = in_ctx->drop_flags;
+       new_drop_flags = ctrl_ctx->drop_flags;
 
+       slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
        /* Update the last valid endpoint context, if we just added one past */
-       if ((in_ctx->slot.dev_info & LAST_CTX_MASK) < LAST_CTX(last_ctx)) {
-               in_ctx->slot.dev_info &= ~LAST_CTX_MASK;
-               in_ctx->slot.dev_info |= LAST_CTX(last_ctx);
+       if ((slot_ctx->dev_info & LAST_CTX_MASK) < LAST_CTX(last_ctx)) {
+               slot_ctx->dev_info &= ~LAST_CTX_MASK;
+               slot_ctx->dev_info |= LAST_CTX(last_ctx);
        }
-       new_slot_info = in_ctx->slot.dev_info;
+       new_slot_info = slot_ctx->dev_info;
+
+       /* Store the usb_device pointer for later use */
+       ep->hcpriv = udev;
 
        xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x, new slot info = %#x\n",
                        (unsigned int) ep->desc.bEndpointAddress,
@@ -860,9 +902,11 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        return 0;
 }
 
-static void xhci_zero_in_ctx(struct xhci_virt_device *virt_dev)
+static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev)
 {
+       struct xhci_input_control_ctx *ctrl_ctx;
        struct xhci_ep_ctx *ep_ctx;
+       struct xhci_slot_ctx *slot_ctx;
        int i;
 
        /* When a device's add flag and drop flag are zero, any subsequent
@@ -870,17 +914,18 @@ static void xhci_zero_in_ctx(struct xhci_virt_device *virt_dev)
         * untouched.  Make sure we don't leave any old state in the input
         * endpoint contexts.
         */
-       virt_dev->in_ctx->drop_flags = 0;
-       virt_dev->in_ctx->add_flags = 0;
-       virt_dev->in_ctx->slot.dev_info &= ~LAST_CTX_MASK;
+       ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
+       ctrl_ctx->drop_flags = 0;
+       ctrl_ctx->add_flags = 0;
+       slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
+       slot_ctx->dev_info &= ~LAST_CTX_MASK;
        /* Endpoint 0 is always valid */
-       virt_dev->in_ctx->slot.dev_info |= LAST_CTX(1);
+       slot_ctx->dev_info |= LAST_CTX(1);
        for (i = 1; i < 31; ++i) {
-               ep_ctx = &virt_dev->in_ctx->ep[i];
+               ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, i);
                ep_ctx->ep_info = 0;
                ep_ctx->ep_info2 = 0;
-               ep_ctx->deq[0] = 0;
-               ep_ctx->deq[1] = 0;
+               ep_ctx->deq = 0;
                ep_ctx->tx_info = 0;
        }
 }
@@ -903,6 +948,8 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
        unsigned long flags;
        struct xhci_hcd *xhci;
        struct xhci_virt_device *virt_dev;
+       struct xhci_input_control_ctx *ctrl_ctx;
+       struct xhci_slot_ctx *slot_ctx;
 
        ret = xhci_check_args(hcd, udev, NULL, 0, __func__);
        if (ret <= 0)
@@ -918,16 +965,18 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
        virt_dev = xhci->devs[udev->slot_id];
 
        /* See section 4.6.6 - A0 = 1; A1 = D0 = D1 = 0 */
-       virt_dev->in_ctx->add_flags |= SLOT_FLAG;
-       virt_dev->in_ctx->add_flags &= ~EP0_FLAG;
-       virt_dev->in_ctx->drop_flags &= ~SLOT_FLAG;
-       virt_dev->in_ctx->drop_flags &= ~EP0_FLAG;
+       ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
+       ctrl_ctx->add_flags |= SLOT_FLAG;
+       ctrl_ctx->add_flags &= ~EP0_FLAG;
+       ctrl_ctx->drop_flags &= ~SLOT_FLAG;
+       ctrl_ctx->drop_flags &= ~EP0_FLAG;
        xhci_dbg(xhci, "New Input Control Context:\n");
-       xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma,
-                       LAST_CTX_TO_EP_NUM(virt_dev->in_ctx->slot.dev_info));
+       slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
+       xhci_dbg_ctx(xhci, virt_dev->in_ctx,
+                       LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
 
        spin_lock_irqsave(&xhci->lock, flags);
-       ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx_dma,
+       ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx->dma,
                        udev->slot_id);
        if (ret < 0) {
                spin_unlock_irqrestore(&xhci->lock, flags);
@@ -982,10 +1031,10 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
        }
 
        xhci_dbg(xhci, "Output context after successful config ep cmd:\n");
-       xhci_dbg_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma,
-                       LAST_CTX_TO_EP_NUM(virt_dev->in_ctx->slot.dev_info));
+       xhci_dbg_ctx(xhci, virt_dev->out_ctx,
+                       LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
 
-       xhci_zero_in_ctx(virt_dev);
+       xhci_zero_in_ctx(xhci, virt_dev);
        /* Free any old rings */
        for (i = 1; i < 31; ++i) {
                if (virt_dev->new_ep_rings[i]) {
@@ -1023,7 +1072,67 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
                        virt_dev->new_ep_rings[i] = NULL;
                }
        }
-       xhci_zero_in_ctx(virt_dev);
+       xhci_zero_in_ctx(xhci, virt_dev);
+}
+
+/* Deal with stalled endpoints.  The core should have sent the control message
+ * to clear the halt condition.  However, we need to make the xHCI hardware
+ * reset its sequence number, since a device will expect a sequence number of
+ * zero after the halt condition is cleared.
+ * Context: in_interrupt
+ */
+void xhci_endpoint_reset(struct usb_hcd *hcd,
+               struct usb_host_endpoint *ep)
+{
+       struct xhci_hcd *xhci;
+       struct usb_device *udev;
+       unsigned int ep_index;
+       unsigned long flags;
+       int ret;
+       struct xhci_dequeue_state deq_state;
+       struct xhci_ring *ep_ring;
+
+       xhci = hcd_to_xhci(hcd);
+       udev = (struct usb_device *) ep->hcpriv;
+       /* Called with a root hub endpoint (or an endpoint that wasn't added
+        * with xhci_add_endpoint()
+        */
+       if (!ep->hcpriv)
+               return;
+       ep_index = xhci_get_endpoint_index(&ep->desc);
+       ep_ring = xhci->devs[udev->slot_id]->ep_rings[ep_index];
+       if (!ep_ring->stopped_td) {
+               xhci_dbg(xhci, "Endpoint 0x%x not halted, refusing to reset.\n",
+                               ep->desc.bEndpointAddress);
+               return;
+       }
+
+       xhci_dbg(xhci, "Queueing reset endpoint command\n");
+       spin_lock_irqsave(&xhci->lock, flags);
+       ret = xhci_queue_reset_ep(xhci, udev->slot_id, ep_index);
+       /*
+        * Can't change the ring dequeue pointer until it's transitioned to the
+        * stopped state, which is only upon a successful reset endpoint
+        * command.  Better hope that last command worked!
+        */
+       if (!ret) {
+               xhci_dbg(xhci, "Cleaning up stalled endpoint ring\n");
+               /* We need to move the HW's dequeue pointer past this TD,
+                * or it will attempt to resend it on the next doorbell ring.
+                */
+               xhci_find_new_dequeue_state(xhci, udev->slot_id,
+                               ep_index, ep_ring->stopped_td, &deq_state);
+               xhci_dbg(xhci, "Queueing new dequeue state\n");
+               xhci_queue_new_dequeue_state(xhci, ep_ring,
+                               udev->slot_id,
+                               ep_index, &deq_state);
+               kfree(ep_ring->stopped_td);
+               xhci_ring_cmd_db(xhci);
+       }
+       spin_unlock_irqrestore(&xhci->lock, flags);
+
+       if (ret)
+               xhci_warn(xhci, "FIXME allocate a new ring segment\n");
 }
 
 /*
@@ -1120,7 +1229,9 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
        struct xhci_virt_device *virt_dev;
        int ret = 0;
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-       u32 temp;
+       struct xhci_slot_ctx *slot_ctx;
+       struct xhci_input_control_ctx *ctrl_ctx;
+       u64 temp_64;
 
        if (!udev->slot_id) {
                xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id);
@@ -1133,10 +1244,12 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
        if (!udev->config)
                xhci_setup_addressable_virt_dev(xhci, udev);
        /* Otherwise, assume the core has the device configured how it wants */
+       xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
+       xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
 
        spin_lock_irqsave(&xhci->lock, flags);
-       ret = xhci_queue_address_device(xhci, virt_dev->in_ctx_dma,
-                       udev->slot_id);
+       ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma,
+                                       udev->slot_id);
        if (ret) {
                spin_unlock_irqrestore(&xhci->lock, flags);
                xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
@@ -1176,41 +1289,37 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
        default:
                xhci_err(xhci, "ERROR: unexpected command completion "
                                "code 0x%x.\n", virt_dev->cmd_status);
+               xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id);
+               xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2);
                ret = -EINVAL;
                break;
        }
        if (ret) {
                return ret;
        }
-       temp = xhci_readl(xhci, &xhci->op_regs->dcbaa_ptr[0]);
-       xhci_dbg(xhci, "Op regs DCBAA ptr[0] = %#08x\n", temp);
-       temp = xhci_readl(xhci, &xhci->op_regs->dcbaa_ptr[1]);
-       xhci_dbg(xhci, "Op regs DCBAA ptr[1] = %#08x\n", temp);
-       xhci_dbg(xhci, "Slot ID %d dcbaa entry[0] @%p = %#08x\n",
-                       udev->slot_id,
-                       &xhci->dcbaa->dev_context_ptrs[2*udev->slot_id],
-                       xhci->dcbaa->dev_context_ptrs[2*udev->slot_id]);
-       xhci_dbg(xhci, "Slot ID %d dcbaa entry[1] @%p = %#08x\n",
+       temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
+       xhci_dbg(xhci, "Op regs DCBAA ptr = %#016llx\n", temp_64);
+       xhci_dbg(xhci, "Slot ID %d dcbaa entry @%p = %#016llx\n",
                        udev->slot_id,
-                       &xhci->dcbaa->dev_context_ptrs[2*udev->slot_id+1],
-                       xhci->dcbaa->dev_context_ptrs[2*udev->slot_id+1]);
+                       &xhci->dcbaa->dev_context_ptrs[udev->slot_id],
+                       (unsigned long long)
+                               xhci->dcbaa->dev_context_ptrs[udev->slot_id]);
        xhci_dbg(xhci, "Output Context DMA address = %#08llx\n",
-                       (unsigned long long)virt_dev->out_ctx_dma);
+                       (unsigned long long)virt_dev->out_ctx->dma);
        xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
-       xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma, 2);
+       xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
        xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id);
-       xhci_dbg_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, 2);
+       xhci_dbg_ctx(xhci, virt_dev->out_ctx, 2);
        /*
         * USB core uses address 1 for the roothubs, so we add one to the
         * address given back to us by the HC.
         */
-       udev->devnum = (virt_dev->out_ctx->slot.dev_state & DEV_ADDR_MASK) + 1;
+       slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
+       udev->devnum = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
        /* Zero the input context control for later use */
-       virt_dev->in_ctx->add_flags = 0;
-       virt_dev->in_ctx->drop_flags = 0;
-       /* Mirror flags in the output context for future ep enable/disable */
-       virt_dev->out_ctx->add_flags = SLOT_FLAG | EP0_FLAG;
-       virt_dev->out_ctx->drop_flags = 0;
+       ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
+       ctrl_ctx->add_flags = 0;
+       ctrl_ctx->drop_flags = 0;
 
        xhci_dbg(xhci, "Device address = %d\n", udev->devnum);
        /* XXX Meh, not sure if anyone else but choose_address uses this. */
@@ -1252,7 +1361,6 @@ static int __init xhci_hcd_init(void)
        /* xhci_device_control has eight fields, and also
         * embeds one xhci_slot_ctx and 31 xhci_ep_ctx
         */
-       BUILD_BUG_ON(sizeof(struct xhci_device_control) != (8+8+8*31)*32/8);
        BUILD_BUG_ON(sizeof(struct xhci_stream_ctx) != 4*32/8);
        BUILD_BUG_ON(sizeof(union xhci_trb) != 4*32/8);
        BUILD_BUG_ON(sizeof(struct xhci_erst_entry) != 4*32/8);
index c8a72de1c5087c58a9fd7f5fba56d9073c1af040..e6b9a1c6002d3da5b43c65161cca881d18a8e214 100644 (file)
@@ -88,7 +88,7 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev,
                return;
        prev->next = next;
        if (link_trbs) {
-               prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr[0] = next->dma;
+               prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = next->dma;
 
                /* Set the last TRB in the segment to have a TRB type ID of Link TRB */
                val = prev->trbs[TRBS_PER_SEGMENT-1].link.control;
@@ -189,6 +189,63 @@ fail:
        return 0;
 }
 
+#define CTX_SIZE(_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32)
+
+struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci,
+                                                   int type, gfp_t flags)
+{
+       struct xhci_container_ctx *ctx = kzalloc(sizeof(*ctx), flags);
+       if (!ctx)
+               return NULL;
+
+       BUG_ON((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT));
+       ctx->type = type;
+       ctx->size = HCC_64BYTE_CONTEXT(xhci->hcc_params) ? 2048 : 1024;
+       if (type == XHCI_CTX_TYPE_INPUT)
+               ctx->size += CTX_SIZE(xhci->hcc_params);
+
+       ctx->bytes = dma_pool_alloc(xhci->device_pool, flags, &ctx->dma);
+       memset(ctx->bytes, 0, ctx->size);
+       return ctx;
+}
+
+void xhci_free_container_ctx(struct xhci_hcd *xhci,
+                            struct xhci_container_ctx *ctx)
+{
+       dma_pool_free(xhci->device_pool, ctx->bytes, ctx->dma);
+       kfree(ctx);
+}
+
+struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci,
+                                             struct xhci_container_ctx *ctx)
+{
+       BUG_ON(ctx->type != XHCI_CTX_TYPE_INPUT);
+       return (struct xhci_input_control_ctx *)ctx->bytes;
+}
+
+struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci,
+                                       struct xhci_container_ctx *ctx)
+{
+       if (ctx->type == XHCI_CTX_TYPE_DEVICE)
+               return (struct xhci_slot_ctx *)ctx->bytes;
+
+       return (struct xhci_slot_ctx *)
+               (ctx->bytes + CTX_SIZE(xhci->hcc_params));
+}
+
+struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci,
+                                   struct xhci_container_ctx *ctx,
+                                   unsigned int ep_index)
+{
+       /* increment ep index by offset of start of ep ctx array */
+       ep_index++;
+       if (ctx->type == XHCI_CTX_TYPE_INPUT)
+               ep_index++;
+
+       return (struct xhci_ep_ctx *)
+               (ctx->bytes + (ep_index * CTX_SIZE(xhci->hcc_params)));
+}
+
 /* All the xhci_tds in the ring's TD list should be freed at this point */
 void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
 {
@@ -200,8 +257,7 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
                return;
 
        dev = xhci->devs[slot_id];
-       xhci->dcbaa->dev_context_ptrs[2*slot_id] = 0;
-       xhci->dcbaa->dev_context_ptrs[2*slot_id + 1] = 0;
+       xhci->dcbaa->dev_context_ptrs[slot_id] = 0;
        if (!dev)
                return;
 
@@ -210,11 +266,10 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
                        xhci_ring_free(xhci, dev->ep_rings[i]);
 
        if (dev->in_ctx)
-               dma_pool_free(xhci->device_pool,
-                               dev->in_ctx, dev->in_ctx_dma);
+               xhci_free_container_ctx(xhci, dev->in_ctx);
        if (dev->out_ctx)
-               dma_pool_free(xhci->device_pool,
-                               dev->out_ctx, dev->out_ctx_dma);
+               xhci_free_container_ctx(xhci, dev->out_ctx);
+
        kfree(xhci->devs[slot_id]);
        xhci->devs[slot_id] = 0;
 }
@@ -222,7 +277,6 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
 int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
                struct usb_device *udev, gfp_t flags)
 {
-       dma_addr_t      dma;
        struct xhci_virt_device *dev;
 
        /* Slot ID 0 is reserved */
@@ -236,23 +290,21 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
                return 0;
        dev = xhci->devs[slot_id];
 
-       /* Allocate the (output) device context that will be used in the HC */
-       dev->out_ctx = dma_pool_alloc(xhci->device_pool, flags, &dma);
+       /* Allocate the (output) device context that will be used in the HC. */
+       dev->out_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_DEVICE, flags);
        if (!dev->out_ctx)
                goto fail;
-       dev->out_ctx_dma = dma;
+
        xhci_dbg(xhci, "Slot %d output ctx = 0x%llx (dma)\n", slot_id,
-                       (unsigned long long)dma);
-       memset(dev->out_ctx, 0, sizeof(*dev->out_ctx));
+                       (unsigned long long)dev->out_ctx->dma);
 
        /* Allocate the (input) device context for address device command */
-       dev->in_ctx = dma_pool_alloc(xhci->device_pool, flags, &dma);
+       dev->in_ctx = xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_INPUT, flags);
        if (!dev->in_ctx)
                goto fail;
-       dev->in_ctx_dma = dma;
+
        xhci_dbg(xhci, "Slot %d input ctx = 0x%llx (dma)\n", slot_id,
-                       (unsigned long long)dma);
-       memset(dev->in_ctx, 0, sizeof(*dev->in_ctx));
+                       (unsigned long long)dev->in_ctx->dma);
 
        /* Allocate endpoint 0 ring */
        dev->ep_rings[0] = xhci_ring_alloc(xhci, 1, true, flags);
@@ -261,17 +313,12 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
 
        init_completion(&dev->cmd_completion);
 
-       /*
-        * Point to output device context in dcbaa; skip the output control
-        * context, which is eight 32 bit fields (or 32 bytes long)
-        */
-       xhci->dcbaa->dev_context_ptrs[2*slot_id] =
-               (u32) dev->out_ctx_dma + (32);
+       /* Point to output device context in dcbaa. */
+       xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma;
        xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n",
                        slot_id,
-                       &xhci->dcbaa->dev_context_ptrs[2*slot_id],
-                       (unsigned long long)dev->out_ctx_dma);
-       xhci->dcbaa->dev_context_ptrs[2*slot_id + 1] = 0;
+                       &xhci->dcbaa->dev_context_ptrs[slot_id],
+                       (unsigned long long) xhci->dcbaa->dev_context_ptrs[slot_id]);
 
        return 1;
 fail:
@@ -285,6 +332,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
        struct xhci_virt_device *dev;
        struct xhci_ep_ctx      *ep0_ctx;
        struct usb_device       *top_dev;
+       struct xhci_slot_ctx    *slot_ctx;
+       struct xhci_input_control_ctx *ctrl_ctx;
 
        dev = xhci->devs[udev->slot_id];
        /* Slot ID 0 is reserved */
@@ -293,27 +342,29 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
                                udev->slot_id);
                return -EINVAL;
        }
-       ep0_ctx = &dev->in_ctx->ep[0];
+       ep0_ctx = xhci_get_ep_ctx(xhci, dev->in_ctx, 0);
+       ctrl_ctx = xhci_get_input_control_ctx(xhci, dev->in_ctx);
+       slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx);
 
        /* 2) New slot context and endpoint 0 context are valid*/
-       dev->in_ctx->add_flags = SLOT_FLAG | EP0_FLAG;
+       ctrl_ctx->add_flags = SLOT_FLAG | EP0_FLAG;
 
        /* 3) Only the control endpoint is valid - one endpoint context */
-       dev->in_ctx->slot.dev_info |= LAST_CTX(1);
+       slot_ctx->dev_info |= LAST_CTX(1);
 
        switch (udev->speed) {
        case USB_SPEED_SUPER:
-               dev->in_ctx->slot.dev_info |= (u32) udev->route;
-               dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_SS;
+               slot_ctx->dev_info |= (u32) udev->route;
+               slot_ctx->dev_info |= (u32) SLOT_SPEED_SS;
                break;
        case USB_SPEED_HIGH:
-               dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_HS;
+               slot_ctx->dev_info |= (u32) SLOT_SPEED_HS;
                break;
        case USB_SPEED_FULL:
-               dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_FS;
+               slot_ctx->dev_info |= (u32) SLOT_SPEED_FS;
                break;
        case USB_SPEED_LOW:
-               dev->in_ctx->slot.dev_info |= (u32) SLOT_SPEED_LS;
+               slot_ctx->dev_info |= (u32) SLOT_SPEED_LS;
                break;
        case USB_SPEED_VARIABLE:
                xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
@@ -327,7 +378,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
        for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
                        top_dev = top_dev->parent)
                /* Found device below root hub */;
-       dev->in_ctx->slot.dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum);
+       slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum);
        xhci_dbg(xhci, "Set root hub portnum to %d\n", top_dev->portnum);
 
        /* Is this a LS/FS device under a HS hub? */
@@ -337,8 +388,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
         */
        if ((udev->speed == USB_SPEED_LOW || udev->speed == USB_SPEED_FULL) &&
                        udev->tt) {
-               dev->in_ctx->slot.tt_info = udev->tt->hub->slot_id;
-               dev->in_ctx->slot.tt_info |= udev->ttport << 8;
+               slot_ctx->tt_info = udev->tt->hub->slot_id;
+               slot_ctx->tt_info |= udev->ttport << 8;
        }
        xhci_dbg(xhci, "udev->tt = %p\n", udev->tt);
        xhci_dbg(xhci, "udev->ttport = 0x%x\n", udev->ttport);
@@ -360,10 +411,9 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
        ep0_ctx->ep_info2 |= MAX_BURST(0);
        ep0_ctx->ep_info2 |= ERROR_COUNT(3);
 
-       ep0_ctx->deq[0] =
+       ep0_ctx->deq =
                dev->ep_rings[0]->first_seg->dma;
-       ep0_ctx->deq[0] |= dev->ep_rings[0]->cycle_state;
-       ep0_ctx->deq[1] = 0;
+       ep0_ctx->deq |= dev->ep_rings[0]->cycle_state;
 
        /* Steps 7 and 8 were done in xhci_alloc_virt_device() */
 
@@ -470,25 +520,26 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
        unsigned int max_burst;
 
        ep_index = xhci_get_endpoint_index(&ep->desc);
-       ep_ctx = &virt_dev->in_ctx->ep[ep_index];
+       ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
 
        /* Set up the endpoint ring */
        virt_dev->new_ep_rings[ep_index] = xhci_ring_alloc(xhci, 1, true, mem_flags);
        if (!virt_dev->new_ep_rings[ep_index])
                return -ENOMEM;
        ep_ring = virt_dev->new_ep_rings[ep_index];
-       ep_ctx->deq[0] = ep_ring->first_seg->dma | ep_ring->cycle_state;
-       ep_ctx->deq[1] = 0;
+       ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state;
 
        ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep);
 
        /* FIXME dig Mult and streams info out of ep companion desc */
 
-       /* Allow 3 retries for everything but isoc */
+       /* Allow 3 retries for everything but isoc;
+        * error count = 0 means infinite retries.
+        */
        if (!usb_endpoint_xfer_isoc(&ep->desc))
                ep_ctx->ep_info2 = ERROR_COUNT(3);
        else
-               ep_ctx->ep_info2 = ERROR_COUNT(0);
+               ep_ctx->ep_info2 = ERROR_COUNT(1);
 
        ep_ctx->ep_info2 |= xhci_get_endpoint_type(udev, ep);
 
@@ -498,7 +549,12 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
                max_packet = ep->desc.wMaxPacketSize;
                ep_ctx->ep_info2 |= MAX_PACKET(max_packet);
                /* dig out max burst from ep companion desc */
-               max_packet = ep->ss_ep_comp->desc.bMaxBurst;
+               if (!ep->ss_ep_comp) {
+                       xhci_warn(xhci, "WARN no SS endpoint companion descriptor.\n");
+                       max_packet = 0;
+               } else {
+                       max_packet = ep->ss_ep_comp->desc.bMaxBurst;
+               }
                ep_ctx->ep_info2 |= MAX_BURST(max_packet);
                break;
        case USB_SPEED_HIGH:
@@ -531,18 +587,114 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci,
        struct xhci_ep_ctx *ep_ctx;
 
        ep_index = xhci_get_endpoint_index(&ep->desc);
-       ep_ctx = &virt_dev->in_ctx->ep[ep_index];
+       ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
 
        ep_ctx->ep_info = 0;
        ep_ctx->ep_info2 = 0;
-       ep_ctx->deq[0] = 0;
-       ep_ctx->deq[1] = 0;
+       ep_ctx->deq = 0;
        ep_ctx->tx_info = 0;
        /* Don't free the endpoint ring until the set interface or configuration
         * request succeeds.
         */
 }
 
+/* Set up the scratchpad buffer array and scratchpad buffers, if needed. */
+static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
+{
+       int i;
+       struct device *dev = xhci_to_hcd(xhci)->self.controller;
+       int num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2);
+
+       xhci_dbg(xhci, "Allocating %d scratchpad buffers\n", num_sp);
+
+       if (!num_sp)
+               return 0;
+
+       xhci->scratchpad = kzalloc(sizeof(*xhci->scratchpad), flags);
+       if (!xhci->scratchpad)
+               goto fail_sp;
+
+       xhci->scratchpad->sp_array =
+               pci_alloc_consistent(to_pci_dev(dev),
+                                    num_sp * sizeof(u64),
+                                    &xhci->scratchpad->sp_dma);
+       if (!xhci->scratchpad->sp_array)
+               goto fail_sp2;
+
+       xhci->scratchpad->sp_buffers = kzalloc(sizeof(void *) * num_sp, flags);
+       if (!xhci->scratchpad->sp_buffers)
+               goto fail_sp3;
+
+       xhci->scratchpad->sp_dma_buffers =
+               kzalloc(sizeof(dma_addr_t) * num_sp, flags);
+
+       if (!xhci->scratchpad->sp_dma_buffers)
+               goto fail_sp4;
+
+       xhci->dcbaa->dev_context_ptrs[0] = xhci->scratchpad->sp_dma;
+       for (i = 0; i < num_sp; i++) {
+               dma_addr_t dma;
+               void *buf = pci_alloc_consistent(to_pci_dev(dev),
+                                                xhci->page_size, &dma);
+               if (!buf)
+                       goto fail_sp5;
+
+               xhci->scratchpad->sp_array[i] = dma;
+               xhci->scratchpad->sp_buffers[i] = buf;
+               xhci->scratchpad->sp_dma_buffers[i] = dma;
+       }
+
+       return 0;
+
+ fail_sp5:
+       for (i = i - 1; i >= 0; i--) {
+               pci_free_consistent(to_pci_dev(dev), xhci->page_size,
+                                   xhci->scratchpad->sp_buffers[i],
+                                   xhci->scratchpad->sp_dma_buffers[i]);
+       }
+       kfree(xhci->scratchpad->sp_dma_buffers);
+
+ fail_sp4:
+       kfree(xhci->scratchpad->sp_buffers);
+
+ fail_sp3:
+       pci_free_consistent(to_pci_dev(dev), num_sp * sizeof(u64),
+                           xhci->scratchpad->sp_array,
+                           xhci->scratchpad->sp_dma);
+
+ fail_sp2:
+       kfree(xhci->scratchpad);
+       xhci->scratchpad = NULL;
+
+ fail_sp:
+       return -ENOMEM;
+}
+
+static void scratchpad_free(struct xhci_hcd *xhci)
+{
+       int num_sp;
+       int i;
+       struct pci_dev  *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
+
+       if (!xhci->scratchpad)
+               return;
+
+       num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2);
+
+       for (i = 0; i < num_sp; i++) {
+               pci_free_consistent(pdev, xhci->page_size,
+                                   xhci->scratchpad->sp_buffers[i],
+                                   xhci->scratchpad->sp_dma_buffers[i]);
+       }
+       kfree(xhci->scratchpad->sp_dma_buffers);
+       kfree(xhci->scratchpad->sp_buffers);
+       pci_free_consistent(pdev, num_sp * sizeof(u64),
+                           xhci->scratchpad->sp_array,
+                           xhci->scratchpad->sp_dma);
+       kfree(xhci->scratchpad);
+       xhci->scratchpad = NULL;
+}
+
 void xhci_mem_cleanup(struct xhci_hcd *xhci)
 {
        struct pci_dev  *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
@@ -551,10 +703,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
 
        /* Free the Event Ring Segment Table and the actual Event Ring */
        xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
-       xhci_writel(xhci, 0, &xhci->ir_set->erst_base[0]);
-       xhci_writel(xhci, 0, &xhci->ir_set->erst_base[1]);
-       xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[0]);
-       xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[1]);
+       xhci_write_64(xhci, 0, &xhci->ir_set->erst_base);
+       xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue);
        size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
        if (xhci->erst.entries)
                pci_free_consistent(pdev, size,
@@ -566,8 +716,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        xhci->event_ring = NULL;
        xhci_dbg(xhci, "Freed event ring\n");
 
-       xhci_writel(xhci, 0, &xhci->op_regs->cmd_ring[0]);
-       xhci_writel(xhci, 0, &xhci->op_regs->cmd_ring[1]);
+       xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring);
        if (xhci->cmd_ring)
                xhci_ring_free(xhci, xhci->cmd_ring);
        xhci->cmd_ring = NULL;
@@ -586,8 +735,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        xhci->device_pool = NULL;
        xhci_dbg(xhci, "Freed device context pool\n");
 
-       xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[0]);
-       xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[1]);
+       xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr);
        if (xhci->dcbaa)
                pci_free_consistent(pdev, sizeof(*xhci->dcbaa),
                                xhci->dcbaa, xhci->dcbaa->dma);
@@ -595,6 +743,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
 
        xhci->page_size = 0;
        xhci->page_shift = 0;
+       scratchpad_free(xhci);
 }
 
 int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
@@ -602,6 +751,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
        dma_addr_t      dma;
        struct device   *dev = xhci_to_hcd(xhci)->self.controller;
        unsigned int    val, val2;
+       u64             val_64;
        struct xhci_segment     *seg;
        u32 page_size;
        int i;
@@ -647,8 +797,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
        xhci->dcbaa->dma = dma;
        xhci_dbg(xhci, "// Device context base array address = 0x%llx (DMA), %p (virt)\n",
                        (unsigned long long)xhci->dcbaa->dma, xhci->dcbaa);
-       xhci_writel(xhci, dma, &xhci->op_regs->dcbaa_ptr[0]);
-       xhci_writel(xhci, (u32) 0, &xhci->op_regs->dcbaa_ptr[1]);
+       xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr);
 
        /*
         * Initialize the ring segment pool.  The ring must be a contiguous
@@ -658,11 +807,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
         */
        xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
                        SEGMENT_SIZE, 64, xhci->page_size);
+
        /* See Table 46 and Note on Figure 55 */
-       /* FIXME support 64-byte contexts */
        xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev,
-                       sizeof(struct xhci_device_control),
-                       64, xhci->page_size);
+                       2112, 64, xhci->page_size);
        if (!xhci->segment_pool || !xhci->device_pool)
                goto fail;
 
@@ -675,14 +823,12 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
                        (unsigned long long)xhci->cmd_ring->first_seg->dma);
 
        /* Set the address in the Command Ring Control register */
-       val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[0]);
-       val = (val & ~CMD_RING_ADDR_MASK) |
-               (xhci->cmd_ring->first_seg->dma & CMD_RING_ADDR_MASK) |
+       val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
+       val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
+               (xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) |
                xhci->cmd_ring->cycle_state;
-       xhci_dbg(xhci, "// Setting command ring address low bits to 0x%x\n", val);
-       xhci_writel(xhci, val, &xhci->op_regs->cmd_ring[0]);
-       xhci_dbg(xhci, "// Setting command ring address high bits to 0x0\n");
-       xhci_writel(xhci, (u32) 0, &xhci->op_regs->cmd_ring[1]);
+       xhci_dbg(xhci, "// Setting command ring address to 0x%x\n", val);
+       xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
        xhci_dbg_cmd_ptrs(xhci);
 
        val = xhci_readl(xhci, &xhci->cap_regs->db_off);
@@ -722,8 +868,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
        /* set ring base address and size for each segment table entry */
        for (val = 0, seg = xhci->event_ring->first_seg; val < ERST_NUM_SEGS; val++) {
                struct xhci_erst_entry *entry = &xhci->erst.entries[val];
-               entry->seg_addr[0] = seg->dma;
-               entry->seg_addr[1] = 0;
+               entry->seg_addr = seg->dma;
                entry->seg_size = TRBS_PER_SEGMENT;
                entry->rsvd = 0;
                seg = seg->next;
@@ -741,11 +886,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
        /* set the segment table base address */
        xhci_dbg(xhci, "// Set ERST base address for ir_set 0 = 0x%llx\n",
                        (unsigned long long)xhci->erst.erst_dma_addr);
-       val = xhci_readl(xhci, &xhci->ir_set->erst_base[0]);
-       val &= ERST_PTR_MASK;
-       val |= (xhci->erst.erst_dma_addr & ~ERST_PTR_MASK);
-       xhci_writel(xhci, val, &xhci->ir_set->erst_base[0]);
-       xhci_writel(xhci, 0, &xhci->ir_set->erst_base[1]);
+       val_64 = xhci_read_64(xhci, &xhci->ir_set->erst_base);
+       val_64 &= ERST_PTR_MASK;
+       val_64 |= (xhci->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK);
+       xhci_write_64(xhci, val_64, &xhci->ir_set->erst_base);
 
        /* Set the event ring dequeue address */
        xhci_set_hc_event_deq(xhci);
@@ -761,7 +905,11 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
        for (i = 0; i < MAX_HC_SLOTS; ++i)
                xhci->devs[i] = 0;
 
+       if (scratchpad_alloc(xhci, flags))
+               goto fail;
+
        return 0;
+
 fail:
        xhci_warn(xhci, "Couldn't initialize memory\n");
        xhci_mem_cleanup(xhci);
index 1462709e26c0411cfc69d13b93641f2764eeb096..592fe7e623f7a0d8f863a5d72a67dae42c4ea7aa 100644 (file)
@@ -117,6 +117,7 @@ static const struct hc_driver xhci_pci_hc_driver = {
        .free_dev =             xhci_free_dev,
        .add_endpoint =         xhci_add_endpoint,
        .drop_endpoint =        xhci_drop_endpoint,
+       .endpoint_reset =       xhci_endpoint_reset,
        .check_bandwidth =      xhci_check_bandwidth,
        .reset_bandwidth =      xhci_reset_bandwidth,
        .address_device =       xhci_address_device,
index 02d81985c4544071b2abc9899a6661d802629b6b..aa88a067148bb70584bdaaaf9c56ccb39b32d3c3 100644 (file)
@@ -135,6 +135,7 @@ static void next_trb(struct xhci_hcd *xhci,
 static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
 {
        union xhci_trb *next = ++(ring->dequeue);
+       unsigned long long addr;
 
        ring->deq_updates++;
        /* Update the dequeue pointer further if that was a link TRB or we're at
@@ -152,6 +153,13 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
                ring->dequeue = ring->deq_seg->trbs;
                next = ring->dequeue;
        }
+       addr = (unsigned long long) xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue);
+       if (ring == xhci->event_ring)
+               xhci_dbg(xhci, "Event ring deq = 0x%llx (DMA)\n", addr);
+       else if (ring == xhci->cmd_ring)
+               xhci_dbg(xhci, "Command ring deq = 0x%llx (DMA)\n", addr);
+       else
+               xhci_dbg(xhci, "Ring deq = 0x%llx (DMA)\n", addr);
 }
 
 /*
@@ -171,6 +179,7 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
 {
        u32 chain;
        union xhci_trb *next;
+       unsigned long long addr;
 
        chain = ring->enqueue->generic.field[3] & TRB_CHAIN;
        next = ++(ring->enqueue);
@@ -204,6 +213,13 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
                ring->enqueue = ring->enq_seg->trbs;
                next = ring->enqueue;
        }
+       addr = (unsigned long long) xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue);
+       if (ring == xhci->event_ring)
+               xhci_dbg(xhci, "Event ring enq = 0x%llx (DMA)\n", addr);
+       else if (ring == xhci->cmd_ring)
+               xhci_dbg(xhci, "Command ring enq = 0x%llx (DMA)\n", addr);
+       else
+               xhci_dbg(xhci, "Ring enq = 0x%llx (DMA)\n", addr);
 }
 
 /*
@@ -237,7 +253,7 @@ static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
 
 void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
 {
-       u32 temp;
+       u64 temp;
        dma_addr_t deq;
 
        deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
@@ -246,13 +262,15 @@ void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
                xhci_warn(xhci, "WARN something wrong with SW event ring "
                                "dequeue ptr.\n");
        /* Update HC event ring dequeue pointer */
-       temp = xhci_readl(xhci, &xhci->ir_set->erst_dequeue[0]);
+       temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
        temp &= ERST_PTR_MASK;
-       if (!in_interrupt())
-               xhci_dbg(xhci, "// Write event ring dequeue pointer\n");
-       xhci_writel(xhci, 0, &xhci->ir_set->erst_dequeue[1]);
-       xhci_writel(xhci, (deq & ~ERST_PTR_MASK) | temp,
-                       &xhci->ir_set->erst_dequeue[0]);
+       /* Don't clear the EHB bit (which is RW1C) because
+        * there might be more events to service.
+        */
+       temp &= ~ERST_EHB;
+       xhci_dbg(xhci, "// Write event ring dequeue pointer, preserving EHB bit\n");
+       xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
+                       &xhci->ir_set->erst_dequeue);
 }
 
 /* Ring the host controller doorbell after placing a command on the ring */
@@ -279,7 +297,8 @@ static void ring_ep_doorbell(struct xhci_hcd *xhci,
        /* Don't ring the doorbell for this endpoint if there are pending
         * cancellations because the we don't want to interrupt processing.
         */
-       if (!ep_ring->cancels_pending && !(ep_ring->state & SET_DEQ_PENDING)) {
+       if (!ep_ring->cancels_pending && !(ep_ring->state & SET_DEQ_PENDING)
+                       && !(ep_ring->state & EP_HALTED)) {
                field = xhci_readl(xhci, db_addr) & DB_MASK;
                xhci_writel(xhci, field | EPI_TO_DB(ep_index), db_addr);
                /* Flush PCI posted writes - FIXME Matthew Wilcox says this
@@ -316,12 +335,6 @@ static struct xhci_segment *find_trb_seg(
        return cur_seg;
 }
 
-struct dequeue_state {
-       struct xhci_segment *new_deq_seg;
-       union xhci_trb *new_deq_ptr;
-       int new_cycle_state;
-};
-
 /*
  * Move the xHC's endpoint ring dequeue pointer past cur_td.
  * Record the new state of the xHC's endpoint ring dequeue segment,
@@ -336,24 +349,30 @@ struct dequeue_state {
  *  - Finally we move the dequeue state one TRB further, toggling the cycle bit
  *    if we've moved it past a link TRB with the toggle cycle bit set.
  */
-static void find_new_dequeue_state(struct xhci_hcd *xhci,
+void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
                unsigned int slot_id, unsigned int ep_index,
-               struct xhci_td *cur_td, struct dequeue_state *state)
+               struct xhci_td *cur_td, struct xhci_dequeue_state *state)
 {
        struct xhci_virt_device *dev = xhci->devs[slot_id];
        struct xhci_ring *ep_ring = dev->ep_rings[ep_index];
        struct xhci_generic_trb *trb;
+       struct xhci_ep_ctx *ep_ctx;
+       dma_addr_t addr;
 
        state->new_cycle_state = 0;
+       xhci_dbg(xhci, "Finding segment containing stopped TRB.\n");
        state->new_deq_seg = find_trb_seg(cur_td->start_seg,
                        ep_ring->stopped_trb,
                        &state->new_cycle_state);
        if (!state->new_deq_seg)
                BUG();
        /* Dig out the cycle state saved by the xHC during the stop ep cmd */
-       state->new_cycle_state = 0x1 & dev->out_ctx->ep[ep_index].deq[0];
+       xhci_dbg(xhci, "Finding endpoint context\n");
+       ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
+       state->new_cycle_state = 0x1 & ep_ctx->deq;
 
        state->new_deq_ptr = cur_td->last_trb;
+       xhci_dbg(xhci, "Finding segment containing last TRB in TD.\n");
        state->new_deq_seg = find_trb_seg(state->new_deq_seg,
                        state->new_deq_ptr,
                        &state->new_cycle_state);
@@ -367,6 +386,12 @@ static void find_new_dequeue_state(struct xhci_hcd *xhci,
        next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
 
        /* Don't update the ring cycle state for the producer (us). */
+       xhci_dbg(xhci, "New dequeue segment = %p (virtual)\n",
+                       state->new_deq_seg);
+       addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr);
+       xhci_dbg(xhci, "New dequeue pointer = 0x%llx (DMA)\n",
+                       (unsigned long long) addr);
+       xhci_dbg(xhci, "Setting dequeue pointer in internal ring state.\n");
        ep_ring->dequeue = state->new_deq_ptr;
        ep_ring->deq_seg = state->new_deq_seg;
 }
@@ -416,6 +441,30 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
                unsigned int ep_index, struct xhci_segment *deq_seg,
                union xhci_trb *deq_ptr, u32 cycle_state);
 
+void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
+               struct xhci_ring *ep_ring, unsigned int slot_id,
+               unsigned int ep_index, struct xhci_dequeue_state *deq_state)
+{
+       xhci_dbg(xhci, "Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), "
+                       "new deq ptr = %p (0x%llx dma), new cycle = %u\n",
+                       deq_state->new_deq_seg,
+                       (unsigned long long)deq_state->new_deq_seg->dma,
+                       deq_state->new_deq_ptr,
+                       (unsigned long long)xhci_trb_virt_to_dma(deq_state->new_deq_seg, deq_state->new_deq_ptr),
+                       deq_state->new_cycle_state);
+       queue_set_tr_deq(xhci, slot_id, ep_index,
+                       deq_state->new_deq_seg,
+                       deq_state->new_deq_ptr,
+                       (u32) deq_state->new_cycle_state);
+       /* Stop the TD queueing code from ringing the doorbell until
+        * this command completes.  The HC won't set the dequeue pointer
+        * if the ring is running, and ringing the doorbell starts the
+        * ring running.
+        */
+       ep_ring->state |= SET_DEQ_PENDING;
+       xhci_ring_cmd_db(xhci);
+}
+
 /*
  * When we get a command completion for a Stop Endpoint Command, we need to
  * unlink any cancelled TDs from the ring.  There are two ways to do that:
@@ -436,7 +485,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
        struct xhci_td *cur_td = 0;
        struct xhci_td *last_unlinked_td;
 
-       struct dequeue_state deq_state;
+       struct xhci_dequeue_state deq_state;
 #ifdef CONFIG_USB_HCD_STAT
        ktime_t stop_time = ktime_get();
 #endif
@@ -464,7 +513,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
                 * move the xHC endpoint ring dequeue pointer past this TD.
                 */
                if (cur_td == ep_ring->stopped_td)
-                       find_new_dequeue_state(xhci, slot_id, ep_index, cur_td,
+                       xhci_find_new_dequeue_state(xhci, slot_id, ep_index, cur_td,
                                        &deq_state);
                else
                        td_to_noop(xhci, ep_ring, cur_td);
@@ -480,24 +529,8 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
 
        /* If necessary, queue a Set Transfer Ring Dequeue Pointer command */
        if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
-               xhci_dbg(xhci, "Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), "
-                               "new deq ptr = %p (0x%llx dma), new cycle = %u\n",
-                               deq_state.new_deq_seg,
-                               (unsigned long long)deq_state.new_deq_seg->dma,
-                               deq_state.new_deq_ptr,
-                               (unsigned long long)xhci_trb_virt_to_dma(deq_state.new_deq_seg, deq_state.new_deq_ptr),
-                               deq_state.new_cycle_state);
-               queue_set_tr_deq(xhci, slot_id, ep_index,
-                               deq_state.new_deq_seg,
-                               deq_state.new_deq_ptr,
-                               (u32) deq_state.new_cycle_state);
-               /* Stop the TD queueing code from ringing the doorbell until
-                * this command completes.  The HC won't set the dequeue pointer
-                * if the ring is running, and ringing the doorbell starts the
-                * ring running.
-                */
-               ep_ring->state |= SET_DEQ_PENDING;
-               xhci_ring_cmd_db(xhci);
+               xhci_queue_new_dequeue_state(xhci, ep_ring,
+                               slot_id, ep_index, &deq_state);
        } else {
                /* Otherwise just ring the doorbell to restart the ring */
                ring_ep_doorbell(xhci, slot_id, ep_index);
@@ -551,11 +584,15 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
        unsigned int ep_index;
        struct xhci_ring *ep_ring;
        struct xhci_virt_device *dev;
+       struct xhci_ep_ctx *ep_ctx;
+       struct xhci_slot_ctx *slot_ctx;
 
        slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
        ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
        dev = xhci->devs[slot_id];
        ep_ring = dev->ep_rings[ep_index];
+       ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
+       slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
 
        if (GET_COMP_CODE(event->status) != COMP_SUCCESS) {
                unsigned int ep_state;
@@ -569,9 +606,9 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
                case COMP_CTX_STATE:
                        xhci_warn(xhci, "WARN Set TR Deq Ptr cmd failed due "
                                        "to incorrect slot or ep state.\n");
-                       ep_state = dev->out_ctx->ep[ep_index].ep_info;
+                       ep_state = ep_ctx->ep_info;
                        ep_state &= EP_STATE_MASK;
-                       slot_state = dev->out_ctx->slot.dev_state;
+                       slot_state = slot_ctx->dev_state;
                        slot_state = GET_SLOT_STATE(slot_state);
                        xhci_dbg(xhci, "Slot state = %u, EP state = %u\n",
                                        slot_state, ep_state);
@@ -593,16 +630,33 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
                 * cancelling URBs, which might not be an error...
                 */
        } else {
-               xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq[0] = 0x%x, "
-                               "deq[1] = 0x%x.\n",
-                               dev->out_ctx->ep[ep_index].deq[0],
-                               dev->out_ctx->ep[ep_index].deq[1]);
+               xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n",
+                               ep_ctx->deq);
        }
 
        ep_ring->state &= ~SET_DEQ_PENDING;
        ring_ep_doorbell(xhci, slot_id, ep_index);
 }
 
+static void handle_reset_ep_completion(struct xhci_hcd *xhci,
+               struct xhci_event_cmd *event,
+               union xhci_trb *trb)
+{
+       int slot_id;
+       unsigned int ep_index;
+
+       slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
+       ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
+       /* This command will only fail if the endpoint wasn't halted,
+        * but we don't care.
+        */
+       xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n",
+                       (unsigned int) GET_COMP_CODE(event->status));
+
+       /* Clear our internal halted state and restart the ring */
+       xhci->devs[slot_id]->ep_rings[ep_index]->state &= ~EP_HALTED;
+       ring_ep_doorbell(xhci, slot_id, ep_index);
+}
 
 static void handle_cmd_completion(struct xhci_hcd *xhci,
                struct xhci_event_cmd *event)
@@ -611,7 +665,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
        u64 cmd_dma;
        dma_addr_t cmd_dequeue_dma;
 
-       cmd_dma = (((u64) event->cmd_trb[1]) << 32) + event->cmd_trb[0];
+       cmd_dma = event->cmd_trb;
        cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
                        xhci->cmd_ring->dequeue);
        /* Is the command ring deq ptr out of sync with the deq seg ptr? */
@@ -653,6 +707,9 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
        case TRB_TYPE(TRB_CMD_NOOP):
                ++xhci->noops_handled;
                break;
+       case TRB_TYPE(TRB_RESET_EP):
+               handle_reset_ep_completion(xhci, event, xhci->cmd_ring->dequeue);
+               break;
        default:
                /* Skip over unknown commands on the event ring */
                xhci->error_bitmask |= 1 << 6;
@@ -756,7 +813,9 @@ static int handle_tx_event(struct xhci_hcd *xhci,
        union xhci_trb *event_trb;
        struct urb *urb = 0;
        int status = -EINPROGRESS;
+       struct xhci_ep_ctx *ep_ctx;
 
+       xhci_dbg(xhci, "In %s\n", __func__);
        xdev = xhci->devs[TRB_TO_SLOT_ID(event->flags)];
        if (!xdev) {
                xhci_err(xhci, "ERROR Transfer event pointed to bad slot\n");
@@ -765,17 +824,17 @@ static int handle_tx_event(struct xhci_hcd *xhci,
 
        /* Endpoint ID is 1 based, our index is zero based */
        ep_index = TRB_TO_EP_ID(event->flags) - 1;
+       xhci_dbg(xhci, "%s - ep index = %d\n", __func__, ep_index);
        ep_ring = xdev->ep_rings[ep_index];
-       if (!ep_ring || (xdev->out_ctx->ep[ep_index].ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) {
+       ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
+       if (!ep_ring || (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) {
                xhci_err(xhci, "ERROR Transfer event pointed to disabled endpoint\n");
                return -ENODEV;
        }
 
-       event_dma = event->buffer[0];
-       if (event->buffer[1] != 0)
-               xhci_warn(xhci, "WARN ignoring upper 32-bits of 64-bit TRB dma address\n");
-
+       event_dma = event->buffer;
        /* This TRB should be in the TD at the head of this ring's TD list */
+       xhci_dbg(xhci, "%s - checking for list empty\n", __func__);
        if (list_empty(&ep_ring->td_list)) {
                xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
                                TRB_TO_SLOT_ID(event->flags), ep_index);
@@ -785,11 +844,14 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                urb = NULL;
                goto cleanup;
        }
+       xhci_dbg(xhci, "%s - getting list entry\n", __func__);
        td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list);
 
        /* Is this a TRB in the currently executing TD? */
+       xhci_dbg(xhci, "%s - looking for TD\n", __func__);
        event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue,
                        td->last_trb, event_dma);
+       xhci_dbg(xhci, "%s - found event_seg = %p\n", __func__, event_seg);
        if (!event_seg) {
                /* HC is busted, give up! */
                xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not part of current TD\n");
@@ -798,10 +860,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
        event_trb = &event_seg->trbs[(event_dma - event_seg->dma) / sizeof(*event_trb)];
        xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
                        (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10);
-       xhci_dbg(xhci, "Offset 0x00 (buffer[0]) = 0x%x\n",
-                       (unsigned int) event->buffer[0]);
-       xhci_dbg(xhci, "Offset 0x04 (buffer[0]) = 0x%x\n",
-                       (unsigned int) event->buffer[1]);
+       xhci_dbg(xhci, "Offset 0x00 (buffer lo) = 0x%x\n",
+                       lower_32_bits(event->buffer));
+       xhci_dbg(xhci, "Offset 0x04 (buffer hi) = 0x%x\n",
+                       upper_32_bits(event->buffer));
        xhci_dbg(xhci, "Offset 0x08 (transfer length) = 0x%x\n",
                        (unsigned int) event->transfer_len);
        xhci_dbg(xhci, "Offset 0x0C (flags) = 0x%x\n",
@@ -823,6 +885,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                break;
        case COMP_STALL:
                xhci_warn(xhci, "WARN: Stalled endpoint\n");
+               ep_ring->state |= EP_HALTED;
                status = -EPIPE;
                break;
        case COMP_TRB_ERR:
@@ -833,6 +896,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                xhci_warn(xhci, "WARN: transfer error on endpoint\n");
                status = -EPROTO;
                break;
+       case COMP_BABBLE:
+               xhci_warn(xhci, "WARN: babble error on endpoint\n");
+               status = -EOVERFLOW;
+               break;
        case COMP_DB_ERR:
                xhci_warn(xhci, "WARN: HC couldn't access mem fast enough\n");
                status = -ENOSR;
@@ -874,15 +941,26 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                if (event_trb != ep_ring->dequeue) {
                        /* The event was for the status stage */
                        if (event_trb == td->last_trb) {
-                               td->urb->actual_length =
-                                       td->urb->transfer_buffer_length;
+                               if (td->urb->actual_length != 0) {
+                                       /* Don't overwrite a previously set error code */
+                                       if (status == -EINPROGRESS || status == 0)
+                                               /* Did we already see a short data stage? */
+                                               status = -EREMOTEIO;
+                               } else {
+                                       td->urb->actual_length =
+                                               td->urb->transfer_buffer_length;
+                               }
                        } else {
                        /* Maybe the event was for the data stage? */
-                               if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL)
+                               if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) {
                                        /* We didn't stop on a link TRB in the middle */
                                        td->urb->actual_length =
                                                td->urb->transfer_buffer_length -
                                                TRB_LEN(event->transfer_len);
+                                       xhci_dbg(xhci, "Waiting for status stage event\n");
+                                       urb = NULL;
+                                       goto cleanup;
+                               }
                        }
                }
        } else {
@@ -929,16 +1007,20 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                                                        TRB_LEN(event->transfer_len));
                                        td->urb->actual_length = 0;
                                }
-                               if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
-                                       status = -EREMOTEIO;
-                               else
-                                       status = 0;
+                               /* Don't overwrite a previously set error code */
+                               if (status == -EINPROGRESS) {
+                                       if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
+                                               status = -EREMOTEIO;
+                                       else
+                                               status = 0;
+                               }
                        } else {
                                td->urb->actual_length = td->urb->transfer_buffer_length;
                                /* Ignore a short packet completion if the
                                 * untransferred length was zero.
                                 */
-                               status = 0;
+                               if (status == -EREMOTEIO)
+                                       status = 0;
                        }
                } else {
                        /* Slow path - walk the list, starting from the dequeue
@@ -965,19 +1047,30 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                                        TRB_LEN(event->transfer_len);
                }
        }
-       /* The Endpoint Stop Command completion will take care of
-        * any stopped TDs.  A stopped TD may be restarted, so don't update the
-        * ring dequeue pointer or take this TD off any lists yet.
-        */
        if (GET_COMP_CODE(event->transfer_len) == COMP_STOP_INVAL ||
                        GET_COMP_CODE(event->transfer_len) == COMP_STOP) {
+               /* The Endpoint Stop Command completion will take care of any
+                * stopped TDs.  A stopped TD may be restarted, so don't update
+                * the ring dequeue pointer or take this TD off any lists yet.
+                */
                ep_ring->stopped_td = td;
                ep_ring->stopped_trb = event_trb;
        } else {
-               /* Update ring dequeue pointer */
-               while (ep_ring->dequeue != td->last_trb)
+               if (GET_COMP_CODE(event->transfer_len) == COMP_STALL) {
+                       /* The transfer is completed from the driver's
+                        * perspective, but we need to issue a set dequeue
+                        * command for this stalled endpoint to move the dequeue
+                        * pointer past the TD.  We can't do that here because
+                        * the halt condition must be cleared first.
+                        */
+                       ep_ring->stopped_td = td;
+                       ep_ring->stopped_trb = event_trb;
+               } else {
+                       /* Update ring dequeue pointer */
+                       while (ep_ring->dequeue != td->last_trb)
+                               inc_deq(xhci, ep_ring, false);
                        inc_deq(xhci, ep_ring, false);
-               inc_deq(xhci, ep_ring, false);
+               }
 
                /* Clean up the endpoint's TD list */
                urb = td->urb;
@@ -987,7 +1080,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                        list_del(&td->cancelled_td_list);
                        ep_ring->cancels_pending--;
                }
-               kfree(td);
+               /* Leave the TD around for the reset endpoint function to use */
+               if (GET_COMP_CODE(event->transfer_len) != COMP_STALL) {
+                       kfree(td);
+               }
                urb->hcpriv = NULL;
        }
 cleanup:
@@ -997,6 +1093,8 @@ cleanup:
        /* FIXME for multi-TD URBs (who have buffers bigger than 64MB) */
        if (urb) {
                usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb);
+               xhci_dbg(xhci, "Giveback URB %p, len = %d, status = %d\n",
+                               urb, td->urb->actual_length, status);
                spin_unlock(&xhci->lock);
                usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status);
                spin_lock(&xhci->lock);
@@ -1014,6 +1112,7 @@ void xhci_handle_event(struct xhci_hcd *xhci)
        int update_ptrs = 1;
        int ret;
 
+       xhci_dbg(xhci, "In %s\n", __func__);
        if (!xhci->event_ring || !xhci->event_ring->dequeue) {
                xhci->error_bitmask |= 1 << 1;
                return;
@@ -1026,18 +1125,25 @@ void xhci_handle_event(struct xhci_hcd *xhci)
                xhci->error_bitmask |= 1 << 2;
                return;
        }
+       xhci_dbg(xhci, "%s - OS owns TRB\n", __func__);
 
        /* FIXME: Handle more event types. */
        switch ((event->event_cmd.flags & TRB_TYPE_BITMASK)) {
        case TRB_TYPE(TRB_COMPLETION):
+               xhci_dbg(xhci, "%s - calling handle_cmd_completion\n", __func__);
                handle_cmd_completion(xhci, &event->event_cmd);
+               xhci_dbg(xhci, "%s - returned from handle_cmd_completion\n", __func__);
                break;
        case TRB_TYPE(TRB_PORT_STATUS):
+               xhci_dbg(xhci, "%s - calling handle_port_status\n", __func__);
                handle_port_status(xhci, event);
+               xhci_dbg(xhci, "%s - returned from handle_port_status\n", __func__);
                update_ptrs = 0;
                break;
        case TRB_TYPE(TRB_TRANSFER):
+               xhci_dbg(xhci, "%s - calling handle_tx_event\n", __func__);
                ret = handle_tx_event(xhci, &event->trans_event);
+               xhci_dbg(xhci, "%s - returned from handle_tx_event\n", __func__);
                if (ret < 0)
                        xhci->error_bitmask |= 1 << 9;
                else
@@ -1093,13 +1199,13 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
                 */
                xhci_warn(xhci, "WARN urb submitted to disabled ep\n");
                return -ENOENT;
-       case EP_STATE_HALTED:
        case EP_STATE_ERROR:
-               xhci_warn(xhci, "WARN waiting for halt or error on ep "
-                               "to be cleared\n");
+               xhci_warn(xhci, "WARN waiting for error on ep to be cleared\n");
                /* FIXME event handling code for error needs to clear it */
                /* XXX not sure if this should be -ENOENT or not */
                return -EINVAL;
+       case EP_STATE_HALTED:
+               xhci_dbg(xhci, "WARN halted endpoint, queueing URB anyway.\n");
        case EP_STATE_STOPPED:
        case EP_STATE_RUNNING:
                break;
@@ -1128,9 +1234,9 @@ static int prepare_transfer(struct xhci_hcd *xhci,
                gfp_t mem_flags)
 {
        int ret;
-
+       struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
        ret = prepare_ring(xhci, xdev->ep_rings[ep_index],
-                       xdev->out_ctx->ep[ep_index].ep_info & EP_STATE_MASK,
+                       ep_ctx->ep_info & EP_STATE_MASK,
                        num_trbs, mem_flags);
        if (ret)
                return ret;
@@ -1285,6 +1391,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        /* Queue the first TRB, even if it's zero-length */
        do {
                u32 field = 0;
+               u32 length_field = 0;
 
                /* Don't change the cycle bit of the first TRB until later */
                if (first_trb)
@@ -1314,10 +1421,13 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                                        (unsigned int) (addr + TRB_MAX_BUFF_SIZE) & ~(TRB_MAX_BUFF_SIZE - 1),
                                        (unsigned int) addr + trb_buff_len);
                }
+               length_field = TRB_LEN(trb_buff_len) |
+                       TD_REMAINDER(urb->transfer_buffer_length - running_total) |
+                       TRB_INTR_TARGET(0);
                queue_trb(xhci, ep_ring, false,
-                               (u32) addr,
-                               (u32) ((u64) addr >> 32),
-                               TRB_LEN(trb_buff_len) | TRB_INTR_TARGET(0),
+                               lower_32_bits(addr),
+                               upper_32_bits(addr),
+                               length_field,
                                /* We always want to know if the TRB was short,
                                 * or we won't get an event when it completes.
                                 * (Unless we use event data TRBs, which are a
@@ -1365,7 +1475,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        struct xhci_generic_trb *start_trb;
        bool first_trb;
        int start_cycle;
-       u32 field;
+       u32 field, length_field;
 
        int running_total, trb_buff_len, ret;
        u64 addr;
@@ -1443,10 +1553,13 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                        td->last_trb = ep_ring->enqueue;
                        field |= TRB_IOC;
                }
+               length_field = TRB_LEN(trb_buff_len) |
+                       TD_REMAINDER(urb->transfer_buffer_length - running_total) |
+                       TRB_INTR_TARGET(0);
                queue_trb(xhci, ep_ring, false,
-                               (u32) addr,
-                               (u32) ((u64) addr >> 32),
-                               TRB_LEN(trb_buff_len) | TRB_INTR_TARGET(0),
+                               lower_32_bits(addr),
+                               upper_32_bits(addr),
+                               length_field,
                                /* We always want to know if the TRB was short,
                                 * or we won't get an event when it completes.
                                 * (Unless we use event data TRBs, which are a
@@ -1478,7 +1591,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        struct usb_ctrlrequest *setup;
        struct xhci_generic_trb *start_trb;
        int start_cycle;
-       u32 field;
+       u32 field, length_field;
        struct xhci_td *td;
 
        ep_ring = xhci->devs[slot_id]->ep_rings[ep_index];
@@ -1528,13 +1641,16 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 
        /* If there's data, queue data TRBs */
        field = 0;
+       length_field = TRB_LEN(urb->transfer_buffer_length) |
+               TD_REMAINDER(urb->transfer_buffer_length) |
+               TRB_INTR_TARGET(0);
        if (urb->transfer_buffer_length > 0) {
                if (setup->bRequestType & USB_DIR_IN)
                        field |= TRB_DIR_IN;
                queue_trb(xhci, ep_ring, false,
                                lower_32_bits(urb->transfer_dma),
                                upper_32_bits(urb->transfer_dma),
-                               TRB_LEN(urb->transfer_buffer_length) | TRB_INTR_TARGET(0),
+                               length_field,
                                /* Event on short tx */
                                field | TRB_ISP | TRB_TYPE(TRB_DATA) | ep_ring->cycle_state);
        }
@@ -1603,7 +1719,8 @@ int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id)
 int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
                u32 slot_id)
 {
-       return queue_command(xhci, in_ctx_ptr, 0, 0,
+       return queue_command(xhci, lower_32_bits(in_ctx_ptr),
+                       upper_32_bits(in_ctx_ptr), 0,
                        TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id));
 }
 
@@ -1611,7 +1728,8 @@ int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
 int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
                u32 slot_id)
 {
-       return queue_command(xhci, in_ctx_ptr, 0, 0,
+       return queue_command(xhci, lower_32_bits(in_ctx_ptr),
+                       upper_32_bits(in_ctx_ptr), 0,
                        TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id));
 }
 
@@ -1639,10 +1757,23 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
        u32 type = TRB_TYPE(TRB_SET_DEQ);
 
        addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr);
-       if (addr == 0)
+       if (addr == 0) {
                xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n");
                xhci_warn(xhci, "WARN deq seg = %p, deq pt = %p\n",
                                deq_seg, deq_ptr);
-       return queue_command(xhci, (u32) addr | cycle_state, 0, 0,
+               return 0;
+       }
+       return queue_command(xhci, lower_32_bits(addr) | cycle_state,
+                       upper_32_bits(addr), 0,
                        trb_slot_id | trb_ep_index | type);
 }
+
+int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
+               unsigned int ep_index)
+{
+       u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
+       u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
+       u32 type = TRB_TYPE(TRB_RESET_EP);
+
+       return queue_command(xhci, 0, 0, 0, trb_slot_id | trb_ep_index | type);
+}
index 8936eeb5588b9d39a9625c2323285db4aa9dbfa9..d31d32206ba318fbf28ea23a105a0bfa81f82f92 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <linux/usb.h>
 #include <linux/timer.h>
+#include <linux/kernel.h>
 
 #include "../core/hcd.h"
 /* Code sharing between pci-quirks and xhci hcd */
  * xHCI register interface.
  * This corresponds to the eXtensible Host Controller Interface (xHCI)
  * Revision 0.95 specification
- *
- * Registers should always be accessed with double word or quad word accesses.
- *
- * Some xHCI implementations may support 64-bit address pointers.  Registers
- * with 64-bit address pointers should be written to with dword accesses by
- * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second.
- * xHCI implementations that do not support 64-bit address pointers will ignore
- * the high dword, and write order is irrelevant.
  */
 
 /**
@@ -96,6 +89,7 @@ struct xhci_cap_regs {
 #define HCS_ERST_MAX(p)                (((p) >> 4) & 0xf)
 /* bit 26 Scratchpad restore - for save/restore HW state - not used yet */
 /* bits 27:31 number of Scratchpad buffers SW must allocate for the HW */
+#define HCS_MAX_SCRATCHPAD(p)   (((p) >> 27) & 0x1f)
 
 /* HCSPARAMS3 - hcs_params3 - bitmasks */
 /* bits 0:7, Max U1 to U0 latency for the roothub ports */
@@ -166,10 +160,10 @@ struct xhci_op_regs {
        u32     reserved1;
        u32     reserved2;
        u32     dev_notification;
-       u32     cmd_ring[2];
+       u64     cmd_ring;
        /* rsvd: offset 0x20-2F */
        u32     reserved3[4];
-       u32     dcbaa_ptr[2];
+       u64     dcbaa_ptr;
        u32     config_reg;
        /* rsvd: offset 0x3C-3FF */
        u32     reserved4[241];
@@ -254,7 +248,7 @@ struct xhci_op_regs {
 #define CMD_RING_RUNNING       (1 << 3)
 /* bits 4:5 reserved and should be preserved */
 /* Command Ring pointer - bit mask for the lower 32 bits. */
-#define CMD_RING_ADDR_MASK     (0xffffffc0)
+#define CMD_RING_RSVD_BITS     (0x3f)
 
 /* CONFIG - Configure Register - config_reg bitmasks */
 /* bits 0:7 - maximum number of device slots enabled (NumSlotsEn) */
@@ -382,8 +376,8 @@ struct xhci_intr_reg {
        u32     irq_control;
        u32     erst_size;
        u32     rsvd;
-       u32     erst_base[2];
-       u32     erst_dequeue[2];
+       u64     erst_base;
+       u64     erst_dequeue;
 };
 
 /* irq_pending bitmasks */
@@ -452,6 +446,27 @@ struct xhci_doorbell_array {
 #define EPI_TO_DB(p)           (((p) + 1) & 0xff)
 
 
+/**
+ * struct xhci_container_ctx
+ * @type: Type of context.  Used to calculated offsets to contained contexts.
+ * @size: Size of the context data
+ * @bytes: The raw context data given to HW
+ * @dma: dma address of the bytes
+ *
+ * Represents either a Device or Input context.  Holds a pointer to the raw
+ * memory used for the context (bytes) and dma address of it (dma).
+ */
+struct xhci_container_ctx {
+       unsigned type;
+#define XHCI_CTX_TYPE_DEVICE  0x1
+#define XHCI_CTX_TYPE_INPUT   0x2
+
+       int size;
+
+       u8 *bytes;
+       dma_addr_t dma;
+};
+
 /**
  * struct xhci_slot_ctx
  * @dev_info:  Route string, device speed, hub info, and last valid endpoint
@@ -538,7 +553,7 @@ struct xhci_slot_ctx {
 struct xhci_ep_ctx {
        u32     ep_info;
        u32     ep_info2;
-       u32     deq[2];
+       u64     deq;
        u32     tx_info;
        /* offset 0x14 - 0x1f reserved for HC internal use */
        u32     reserved[3];
@@ -589,18 +604,16 @@ struct xhci_ep_ctx {
 
 
 /**
- * struct xhci_device_control
- * Input/Output context; see section 6.2.5.
+ * struct xhci_input_control_context
+ * Input control context; see section 6.2.5.
  *
  * @drop_context:      set the bit of the endpoint context you want to disable
  * @add_context:       set the bit of the endpoint context you want to enable
  */
-struct xhci_device_control {
+struct xhci_input_control_ctx {
        u32     drop_flags;
        u32     add_flags;
-       u32     rsvd[6];
-       struct xhci_slot_ctx    slot;
-       struct xhci_ep_ctx      ep[31];
+       u32     rsvd2[6];
 };
 
 /* drop context bitmasks */
@@ -608,7 +621,6 @@ struct xhci_device_control {
 /* add context bitmasks */
 #define        ADD_EP(x)       (0x1 << x)
 
-
 struct xhci_virt_device {
        /*
         * Commands to the hardware are passed an "input context" that
@@ -618,11 +630,10 @@ struct xhci_virt_device {
         * track of input and output contexts separately because
         * these commands might fail and we don't trust the hardware.
         */
-       struct xhci_device_control      *out_ctx;
-       dma_addr_t                      out_ctx_dma;
+       struct xhci_container_ctx       *out_ctx;
        /* Used for addressing devices and configuration changes */
-       struct xhci_device_control      *in_ctx;
-       dma_addr_t                      in_ctx_dma;
+       struct xhci_container_ctx       *in_ctx;
+
        /* FIXME when stream support is added */
        struct xhci_ring                *ep_rings[31];
        /* Temporary storage in case the configure endpoint command fails and we
@@ -641,7 +652,7 @@ struct xhci_virt_device {
  */
 struct xhci_device_context_array {
        /* 64-bit device addresses; we only write 32-bit addresses */
-       u32                     dev_context_ptrs[2*MAX_HC_SLOTS];
+       u64                     dev_context_ptrs[MAX_HC_SLOTS];
        /* private xHCD pointers */
        dma_addr_t      dma;
 };
@@ -654,7 +665,7 @@ struct xhci_device_context_array {
 
 struct xhci_stream_ctx {
        /* 64-bit stream ring address, cycle state, and stream type */
-       u32     stream_ring[2];
+       u64     stream_ring;
        /* offset 0x14 - 0x1f reserved for HC internal use */
        u32     reserved[2];
 };
@@ -662,7 +673,7 @@ struct xhci_stream_ctx {
 
 struct xhci_transfer_event {
        /* 64-bit buffer address, or immediate data */
-       u32     buffer[2];
+       u64     buffer;
        u32     transfer_len;
        /* This field is interpreted differently based on the type of TRB */
        u32     flags;
@@ -744,7 +755,7 @@ struct xhci_transfer_event {
 
 struct xhci_link_trb {
        /* 64-bit segment pointer*/
-       u32 segment_ptr[2];
+       u64 segment_ptr;
        u32 intr_target;
        u32 control;
 };
@@ -755,7 +766,7 @@ struct xhci_link_trb {
 /* Command completion event TRB */
 struct xhci_event_cmd {
        /* Pointer to command TRB, or the value passed by the event data trb */
-       u32 cmd_trb[2];
+       u64 cmd_trb;
        u32 status;
        u32 flags;
 };
@@ -848,8 +859,8 @@ union xhci_trb {
 #define TRB_CONFIG_EP          12
 /* Evaluate Context Command */
 #define TRB_EVAL_CONTEXT       13
-/* Reset Transfer Ring Command */
-#define TRB_RESET_RING         14
+/* Reset Endpoint Command */
+#define TRB_RESET_EP           14
 /* Stop Transfer Ring Command */
 #define TRB_STOP_RING          15
 /* Set Transfer Ring Dequeue Pointer Command */
@@ -929,6 +940,7 @@ struct xhci_ring {
        unsigned int            cancels_pending;
        unsigned int            state;
 #define SET_DEQ_PENDING                (1 << 0)
+#define EP_HALTED              (1 << 1)
        /* The TRB that was last reported in a stopped endpoint ring */
        union xhci_trb          *stopped_trb;
        struct xhci_td          *stopped_td;
@@ -940,9 +952,15 @@ struct xhci_ring {
        u32                     cycle_state;
 };
 
+struct xhci_dequeue_state {
+       struct xhci_segment *new_deq_seg;
+       union xhci_trb *new_deq_ptr;
+       int new_cycle_state;
+};
+
 struct xhci_erst_entry {
        /* 64-bit event ring segment address */
-       u32     seg_addr[2];
+       u64     seg_addr;
        u32     seg_size;
        /* Set to zero */
        u32     rsvd;
@@ -957,6 +975,13 @@ struct xhci_erst {
        unsigned int            erst_size;
 };
 
+struct xhci_scratchpad {
+       u64 *sp_array;
+       dma_addr_t sp_dma;
+       void **sp_buffers;
+       dma_addr_t *sp_dma_buffers;
+};
+
 /*
  * Each segment table entry is 4*32bits long.  1K seems like an ok size:
  * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table,
@@ -1011,6 +1036,9 @@ struct xhci_hcd {
        struct xhci_ring        *cmd_ring;
        struct xhci_ring        *event_ring;
        struct xhci_erst        erst;
+       /* Scratchpad */
+       struct xhci_scratchpad  *scratchpad;
+
        /* slot enabling and address device helpers */
        struct completion       addr_dev;
        int slot_id;
@@ -1071,13 +1099,43 @@ static inline unsigned int xhci_readl(const struct xhci_hcd *xhci,
 static inline void xhci_writel(struct xhci_hcd *xhci,
                const unsigned int val, __u32 __iomem *regs)
 {
-       if (!in_interrupt())
-               xhci_dbg(xhci,
-                        "`MEM_WRITE_DWORD(3'b000, 32'h%p, 32'h%0x, 4'hf);\n",
-                        regs, val);
+       xhci_dbg(xhci,
+                       "`MEM_WRITE_DWORD(3'b000, 32'h%p, 32'h%0x, 4'hf);\n",
+                       regs, val);
        writel(val, regs);
 }
 
+/*
+ * Registers should always be accessed with double word or quad word accesses.
+ *
+ * Some xHCI implementations may support 64-bit address pointers.  Registers
+ * with 64-bit address pointers should be written to with dword accesses by
+ * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second.
+ * xHCI implementations that do not support 64-bit address pointers will ignore
+ * the high dword, and write order is irrelevant.
+ */
+static inline u64 xhci_read_64(const struct xhci_hcd *xhci,
+               __u64 __iomem *regs)
+{
+       __u32 __iomem *ptr = (__u32 __iomem *) regs;
+       u64 val_lo = readl(ptr);
+       u64 val_hi = readl(ptr + 1);
+       return val_lo + (val_hi << 32);
+}
+static inline void xhci_write_64(struct xhci_hcd *xhci,
+               const u64 val, __u64 __iomem *regs)
+{
+       __u32 __iomem *ptr = (__u32 __iomem *) regs;
+       u32 val_lo = lower_32_bits(val);
+       u32 val_hi = upper_32_bits(val);
+
+       xhci_dbg(xhci,
+                       "`MEM_WRITE_DWORD(3'b000, 64'h%p, 64'h%0lx, 4'hf);\n",
+                       regs, (long unsigned int) val);
+       writel(val_lo, ptr);
+       writel(val_hi, ptr + 1);
+}
+
 /* xHCI debugging */
 void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num);
 void xhci_print_registers(struct xhci_hcd *xhci);
@@ -1090,7 +1148,7 @@ void xhci_debug_ring(struct xhci_hcd *xhci, struct xhci_ring *ring);
 void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst);
 void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci);
 void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring);
-void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_device_control *ctx, dma_addr_t dma, unsigned int last_ep);
+void xhci_dbg_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int last_ep);
 
 /* xHCI memory managment */
 void xhci_mem_cleanup(struct xhci_hcd *xhci);
@@ -1128,6 +1186,7 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags);
 int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
 int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
 int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep);
+void xhci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
 int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 
@@ -1148,10 +1207,23 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb,
                int slot_id, unsigned int ep_index);
 int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
                u32 slot_id);
+int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id,
+               unsigned int ep_index);
+void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
+               unsigned int slot_id, unsigned int ep_index,
+               struct xhci_td *cur_td, struct xhci_dequeue_state *state);
+void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
+               struct xhci_ring *ep_ring, unsigned int slot_id,
+               unsigned int ep_index, struct xhci_dequeue_state *deq_state);
 
 /* xHCI roothub code */
 int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
                char *buf, u16 wLength);
 int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
 
+/* xHCI contexts */
+struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx);
+struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx);
+struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int ep_index);
+
 #endif /* __LINUX_XHCI_HCD_H */
index a68d91a11bee32422dd1296ff539b7b036228b73..abe3aa67ed0033d59a6735d9d61e3ec97529ad01 100644 (file)
@@ -220,7 +220,7 @@ config USB_IOWARRIOR
 
 config USB_TEST
        tristate "USB testing driver"
-       depends on USB && USB_DEVICEFS
+       depends on USB
        help
          This driver is for testing host controller software.  It is used
          with specialized device firmware for regression and stress testing,
index 3c5fe5cee05abab286dcc2f00d6cc1f70b031e06..90e1a8dedfa91404f8ce1ac48b159818eead87b8 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/poll.h>
 #include <linux/usb/iowarrior.h>
 
index deb95bb49fd195d333a77152e21fef88f2d26ae3..d645f3899fe1c52a09599e90d241006337591381 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/random.h>
 #include <linux/poll.h>
index e0ff9ccd866baff21039a6dadbb920a08e866636..29092b8e59ceb7347a2f217282d7918eaf98cfe2 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
index f8d9045d668a15659fadf2af3fecf374623402f5..0f7a30b7d2d16e08f7c63ddc1711833d0667fc15 100644 (file)
@@ -1261,7 +1261,7 @@ static int mon_alloc_buff(struct mon_pgmap *map, int npages)
                        return -ENOMEM;
                }
                map[n].ptr = (unsigned char *) vaddr;
-               map[n].pg = virt_to_page(vaddr);
+               map[n].pg = virt_to_page((void *) vaddr);
        }
        return 0;
 }
index 70073b157f0ab7e875ab1fdad3bedaa4e97e5c8c..803adcb5ac1d3e358f481963b1c1d20e6d23e260 100644 (file)
@@ -12,6 +12,7 @@ config USB_MUSB_HDRC
        depends on !SUPERH
        select NOP_USB_XCEIV if ARCH_DAVINCI
        select TWL4030_USB if MACH_OMAP_3430SDP
+       select NOP_USB_XCEIV if MACH_OMAP3EVM
        select USB_OTG_UTILS
        tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
        help
index 8a39de3e6e471c9c8f8c7b72f5b515218cb816c4..59bf949e589b85a086be064ffb037a77bedc7e24 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <linux/slab.h>
 #include <linux/list.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/dmapool.h>
 
index 180d7daa4099d50231f81f92c8ce537ab72dcbcc..e16ff605c458aa5a5b29e224deec2033adb96851 100644 (file)
 #include <mach/hardware.h>
 #include <mach/memory.h>
 #include <mach/gpio.h>
+#include <mach/cputype.h>
 
 #include <asm/mach-types.h>
 
 #include "musb_core.h"
 
 #ifdef CONFIG_MACH_DAVINCI_EVM
-#define GPIO_nVBUS_DRV         87
+#define GPIO_nVBUS_DRV         144
 #endif
 
 #include "davinci.h"
@@ -329,7 +330,6 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
                        mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ);
                        WARNING("VBUS error workaround (delay coming)\n");
                } else if (is_host_enabled(musb) && drvvbus) {
-                       musb->is_active = 1;
                        MUSB_HST_MODE(musb);
                        musb->xceiv->default_a = 1;
                        musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
@@ -343,7 +343,9 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci)
                        portstate(musb->port1_status &= ~USB_PORT_STAT_POWER);
                }
 
-               /* NOTE:  this must complete poweron within 100 msec */
+               /* NOTE:  this must complete poweron within 100 msec
+                * (OTG_TIME_A_WAIT_VRISE) but we don't check for that.
+                */
                davinci_source_power(musb, drvvbus, 0);
                DBG(2, "VBUS %s (%s)%s, devctl %02x\n",
                                drvvbus ? "on" : "off",
@@ -411,6 +413,21 @@ int __init musb_platform_init(struct musb *musb)
                __raw_writel(phy_ctrl, USB_PHY_CTRL);
        }
 
+       /* On dm355, the default-A state machine needs DRVVBUS control.
+        * If we won't be a host, there's no need to turn it on.
+        */
+       if (cpu_is_davinci_dm355()) {
+               u32     deepsleep = __raw_readl(DM355_DEEPSLEEP);
+
+               if (is_host_enabled(musb)) {
+                       deepsleep &= ~DRVVBUS_OVERRIDE;
+               } else {
+                       deepsleep &= ~DRVVBUS_FORCE;
+                       deepsleep |= DRVVBUS_OVERRIDE;
+               }
+               __raw_writel(deepsleep, DM355_DEEPSLEEP);
+       }
+
        /* reset the controller */
        musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1);
 
@@ -437,6 +454,15 @@ int musb_platform_exit(struct musb *musb)
        if (is_host_enabled(musb))
                del_timer_sync(&otg_workaround);
 
+       /* force VBUS off */
+       if (cpu_is_davinci_dm355()) {
+               u32     deepsleep = __raw_readl(DM355_DEEPSLEEP);
+
+               deepsleep &= ~DRVVBUS_FORCE;
+               deepsleep |= DRVVBUS_OVERRIDE;
+               __raw_writel(deepsleep, DM355_DEEPSLEEP);
+       }
+
        davinci_source_power(musb, 0 /*off*/, 1);
 
        /* delay, to avoid problems with module reload */
index 554a414f65d1104cbbbeeaed2885f2a209faf42d..c7c1ca0494cda359096b1eeeb281a55b80f2c994 100644 (file)
@@ -1326,7 +1326,6 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
        int             i;
 
        /* log core options (read using indexed model) */
-       musb_ep_select(mbase, 0);
        reg = musb_read_configdata(mbase);
 
        strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8");
@@ -1990,7 +1989,7 @@ bad_config:
        if (status < 0)
                goto fail2;
 
-#ifdef CONFIG_USB_OTG
+#ifdef CONFIG_USB_MUSB_OTG
        setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb);
 #endif
 
index f3772ca3b2cf799569389870e60a159732f5ca70..381d648a36b8122e974b0f4c5e0001611d8f0e49 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/clk.h>
index 40ed50ecedff6ed84a72d4342616a6f07e36f362..7a6778675ad3a8d5a76d1f8de9477a8c48309d12 100644 (file)
@@ -407,7 +407,7 @@ stall:
                                        csr |= MUSB_RXCSR_P_SENDSTALL
                                                | MUSB_RXCSR_FLUSHFIFO
                                                | MUSB_RXCSR_CLRDATATOG
-                                               | MUSB_TXCSR_P_WZC_BITS;
+                                               | MUSB_RXCSR_P_WZC_BITS;
                                        musb_writew(regs, MUSB_RXCSR,
                                                        csr);
                                }
index 94a2a350a4141521e9e4d93426700ed3a31aaf6b..cf94511485f258a07d60186d43e3687fcf959a87 100644 (file)
@@ -373,7 +373,7 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb,
                musb_save_toggle(qh, is_in, urb);
                break;
        case USB_ENDPOINT_XFER_ISOC:
-               if (urb->error_count)
+               if (status == 0 && urb->error_count)
                        status = -EXDEV;
                break;
        }
@@ -2235,13 +2235,30 @@ static void musb_h_stop(struct usb_hcd *hcd)
 static int musb_bus_suspend(struct usb_hcd *hcd)
 {
        struct musb     *musb = hcd_to_musb(hcd);
+       u8              devctl;
 
-       if (musb->xceiv->state == OTG_STATE_A_SUSPEND)
+       if (!is_host_active(musb))
                return 0;
 
-       if (is_host_active(musb) && musb->is_active) {
-               WARNING("trying to suspend as %s is_active=%i\n",
-                       otg_state_string(musb), musb->is_active);
+       switch (musb->xceiv->state) {
+       case OTG_STATE_A_SUSPEND:
+               return 0;
+       case OTG_STATE_A_WAIT_VRISE:
+               /* ID could be grounded even if there's no device
+                * on the other end of the cable.  NOTE that the
+                * A_WAIT_VRISE timers are messy with MUSB...
+                */
+               devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+               if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
+                       musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
+               break;
+       default:
+               break;
+       }
+
+       if (musb->is_active) {
+               WARNING("trying to suspend as %s while active\n",
+                               otg_state_string(musb));
                return -EBUSY;
        } else
                return 0;
index de3b2f18db4469943b0e7ce3b437ff98d53e0022..fbfd3fd9ce1f876f4949b15b1de016e7877d1348 100644 (file)
@@ -323,6 +323,7 @@ static inline void  musb_write_rxfifoadd(void __iomem *mbase, u16 c_off)
 
 static inline u8 musb_read_configdata(void __iomem *mbase)
 {
+       musb_writeb(mbase, MUSB_INDEX, 0);
        return musb_readb(mbase, 0x10 + MUSB_CONFIGDATA);
 }
 
index 69feeec1628ce28bd8744ef5c6048d0b7a12746c..aa884d072f0b4c7202e5b421e52b0ca37a5163de 100644 (file)
@@ -59,18 +59,4 @@ config NOP_USB_XCEIV
         built-in with usb ip or which are autonomous and doesn't require any
         phy programming such as ISP1x04 etc.
 
-config USB_LANGWELL_OTG
-       tristate "Intel Langwell USB OTG dual-role support"
-       depends on USB && MRST
-       select USB_OTG
-       select USB_OTG_UTILS
-       help
-         Say Y here if you want to build Intel Langwell USB OTG
-         transciever driver in kernel. This driver implements role
-         switch between EHCI host driver and Langwell USB OTG
-         client driver.
-
-         To compile this driver as a module, choose M here: the
-         module will be called langwell_otg.
-
 endif # USB || OTG
index 6d1abdd3c0ac9cc1a2cd688dd9fda768ee2562a1..208167856529f26225807cd7edea4fb29a3640e9 100644 (file)
@@ -9,7 +9,6 @@ obj-$(CONFIG_USB_OTG_UTILS)     += otg.o
 obj-$(CONFIG_USB_GPIO_VBUS)    += gpio_vbus.o
 obj-$(CONFIG_ISP1301_OMAP)     += isp1301_omap.o
 obj-$(CONFIG_TWL4030_USB)      += twl4030-usb.o
-obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o
 obj-$(CONFIG_NOP_USB_XCEIV)    += nop-usb-xceiv.o
 
 ccflags-$(CONFIG_USB_DEBUG)    += -DDEBUG
diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c
deleted file mode 100644 (file)
index 6f628d0..0000000
+++ /dev/null
@@ -1,1915 +0,0 @@
-/*
- * Intel Langwell USB OTG transceiver driver
- * Copyright (C) 2008 - 2009, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/* This driver helps to switch Langwell OTG controller function between host
- * and peripheral. It works with EHCI driver and Langwell client controller
- * driver together.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/moduleparam.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb.h>
-#include <linux/usb/otg.h>
-#include <linux/notifier.h>
-#include <asm/ipc_defs.h>
-#include <linux/delay.h>
-#include "../core/hcd.h"
-
-#include <linux/usb/langwell_otg.h>
-
-#define        DRIVER_DESC             "Intel Langwell USB OTG transceiver driver"
-#define        DRIVER_VERSION          "3.0.0.32L.0002"
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-
-static const char driver_name[] = "langwell_otg";
-
-static int langwell_otg_probe(struct pci_dev *pdev,
-                       const struct pci_device_id *id);
-static void langwell_otg_remove(struct pci_dev *pdev);
-static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message);
-static int langwell_otg_resume(struct pci_dev *pdev);
-
-static int langwell_otg_set_host(struct otg_transceiver *otg,
-                               struct usb_bus *host);
-static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
-                               struct usb_gadget *gadget);
-static int langwell_otg_start_srp(struct otg_transceiver *otg);
-
-static const struct pci_device_id pci_ids[] = {{
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-       .class_mask =   ~0,
-       .vendor =       0x8086,
-       .device =       0x0811,
-       .subvendor =    PCI_ANY_ID,
-       .subdevice =    PCI_ANY_ID,
-}, { /* end: all zeroes */ }
-};
-
-static struct pci_driver otg_pci_driver = {
-       .name =         (char *) driver_name,
-       .id_table =     pci_ids,
-
-       .probe =        langwell_otg_probe,
-       .remove =       langwell_otg_remove,
-
-       .suspend =      langwell_otg_suspend,
-       .resume =       langwell_otg_resume,
-};
-
-static const char *state_string(enum usb_otg_state state)
-{
-       switch (state) {
-       case OTG_STATE_A_IDLE:
-               return "a_idle";
-       case OTG_STATE_A_WAIT_VRISE:
-               return "a_wait_vrise";
-       case OTG_STATE_A_WAIT_BCON:
-               return "a_wait_bcon";
-       case OTG_STATE_A_HOST:
-               return "a_host";
-       case OTG_STATE_A_SUSPEND:
-               return "a_suspend";
-       case OTG_STATE_A_PERIPHERAL:
-               return "a_peripheral";
-       case OTG_STATE_A_WAIT_VFALL:
-               return "a_wait_vfall";
-       case OTG_STATE_A_VBUS_ERR:
-               return "a_vbus_err";
-       case OTG_STATE_B_IDLE:
-               return "b_idle";
-       case OTG_STATE_B_SRP_INIT:
-               return "b_srp_init";
-       case OTG_STATE_B_PERIPHERAL:
-               return "b_peripheral";
-       case OTG_STATE_B_WAIT_ACON:
-               return "b_wait_acon";
-       case OTG_STATE_B_HOST:
-               return "b_host";
-       default:
-               return "UNDEFINED";
-       }
-}
-
-/* HSM timers */
-static inline struct langwell_otg_timer *otg_timer_initializer
-(void (*function)(unsigned long), unsigned long expires, unsigned long data)
-{
-       struct langwell_otg_timer *timer;
-       timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL);
-       timer->function = function;
-       timer->expires = expires;
-       timer->data = data;
-       return timer;
-}
-
-static struct langwell_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr,
-       *a_aidl_bdis_tmr, *b_ase0_brst_tmr, *b_se0_srp_tmr, *b_srp_res_tmr,
-       *b_bus_suspend_tmr;
-
-static struct list_head active_timers;
-
-static struct langwell_otg *the_transceiver;
-
-/* host/client notify transceiver when event affects HNP state */
-void langwell_update_transceiver()
-{
-       otg_dbg("transceiver driver is notified\n");
-       queue_work(the_transceiver->qwork, &the_transceiver->work);
-}
-EXPORT_SYMBOL(langwell_update_transceiver);
-
-static int langwell_otg_set_host(struct otg_transceiver *otg,
-                                       struct usb_bus *host)
-{
-       otg->host = host;
-
-       return 0;
-}
-
-static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
-                                       struct usb_gadget *gadget)
-{
-       otg->gadget = gadget;
-
-       return 0;
-}
-
-static int langwell_otg_set_power(struct otg_transceiver *otg,
-                               unsigned mA)
-{
-       return 0;
-}
-
-/* A-device drives vbus, controlled through PMIC CHRGCNTL register*/
-static void langwell_otg_drv_vbus(int on)
-{
-       struct ipc_pmic_reg_data        pmic_data = {0};
-       struct ipc_pmic_reg_data        battery_data;
-
-       /* Check if battery is attached or not */
-       battery_data.pmic_reg_data[0].register_address = 0xd2;
-       battery_data.ioc = 0;
-       battery_data.num_entries = 1;
-       if (ipc_pmic_register_read(&battery_data)) {
-               otg_dbg("Failed to read PMIC register 0xd2.\n");
-               return;
-       }
-
-       if ((battery_data.pmic_reg_data[0].value & 0x20) == 0) {
-               otg_dbg("no battery attached\n");
-               return;
-       }
-
-       /* Workaround for battery attachment issue */
-       if (battery_data.pmic_reg_data[0].value == 0x34) {
-               otg_dbg("battery \n");
-               return;
-       }
-
-       otg_dbg("battery attached\n");
-
-       pmic_data.ioc = 0;
-       pmic_data.pmic_reg_data[0].register_address = 0xD4;
-       pmic_data.num_entries = 1;
-       if (on)
-               pmic_data.pmic_reg_data[0].value = 0x20;
-       else
-               pmic_data.pmic_reg_data[0].value = 0xc0;
-
-       if (ipc_pmic_register_write(&pmic_data, TRUE))
-               otg_dbg("Failed to write PMIC.\n");
-
-}
-
-/* charge vbus or discharge vbus through a resistor to ground */
-static void langwell_otg_chrg_vbus(int on)
-{
-
-       u32     val;
-
-       val = readl(the_transceiver->regs + CI_OTGSC);
-
-       if (on)
-               writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC,
-                               the_transceiver->regs + CI_OTGSC);
-       else
-               writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD,
-                               the_transceiver->regs + CI_OTGSC);
-
-}
-
-/* Start SRP */
-static int langwell_otg_start_srp(struct otg_transceiver *otg)
-{
-       u32     val;
-
-       otg_dbg("Start SRP ->\n");
-
-       val = readl(the_transceiver->regs + CI_OTGSC);
-
-       writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP,
-               the_transceiver->regs + CI_OTGSC);
-
-       /* Check if the data plus is finished or not */
-       msleep(8);
-       val = readl(the_transceiver->regs + CI_OTGSC);
-       if (val & (OTGSC_HADP | OTGSC_DP))
-               otg_dbg("DataLine SRP Error\n");
-
-       /* FIXME: VBus SRP */
-
-       return 0;
-}
-
-
-/* stop SOF via bus_suspend */
-static void langwell_otg_loc_sof(int on)
-{
-       struct usb_hcd  *hcd;
-       int             err;
-
-       otg_dbg("loc_sof -> %d\n", on);
-
-       hcd = bus_to_hcd(the_transceiver->otg.host);
-       if (on)
-               err = hcd->driver->bus_resume(hcd);
-       else
-               err = hcd->driver->bus_suspend(hcd);
-
-       if (err)
-               otg_dbg("Failed to resume/suspend bus - %d\n", err);
-}
-
-static void langwell_otg_phy_low_power(int on)
-{
-       u32     val;
-
-       otg_dbg("phy low power mode-> %d\n", on);
-
-       val = readl(the_transceiver->regs + CI_HOSTPC1);
-       if (on)
-               writel(val | HOSTPC1_PHCD, the_transceiver->regs + CI_HOSTPC1);
-       else
-               writel(val & ~HOSTPC1_PHCD, the_transceiver->regs + CI_HOSTPC1);
-}
-
-/* Enable/Disable OTG interrupt */
-static void langwell_otg_intr(int on)
-{
-       u32 val;
-
-       otg_dbg("interrupt -> %d\n", on);
-
-       val = readl(the_transceiver->regs + CI_OTGSC);
-       if (on) {
-               val = val | (OTGSC_INTEN_MASK | OTGSC_IDPU);
-               writel(val, the_transceiver->regs + CI_OTGSC);
-       } else {
-               val = val & ~(OTGSC_INTEN_MASK | OTGSC_IDPU);
-               writel(val, the_transceiver->regs + CI_OTGSC);
-       }
-}
-
-/* set HAAR: Hardware Assist Auto-Reset */
-static void langwell_otg_HAAR(int on)
-{
-       u32     val;
-
-       otg_dbg("HAAR -> %d\n", on);
-
-       val = readl(the_transceiver->regs + CI_OTGSC);
-       if (on)
-               writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR,
-                               the_transceiver->regs + CI_OTGSC);
-       else
-               writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR,
-                               the_transceiver->regs + CI_OTGSC);
-}
-
-/* set HABA: Hardware Assist B-Disconnect to A-Connect */
-static void langwell_otg_HABA(int on)
-{
-       u32     val;
-
-       otg_dbg("HABA -> %d\n", on);
-
-       val = readl(the_transceiver->regs + CI_OTGSC);
-       if (on)
-               writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA,
-                               the_transceiver->regs + CI_OTGSC);
-       else
-               writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA,
-                               the_transceiver->regs + CI_OTGSC);
-}
-
-static int langwell_otg_check_se0_srp(int on)
-{
-       u32 val;
-
-       int delay_time = TB_SE0_SRP * 10; /* step is 100us */
-
-       otg_dbg("check_se0_srp -> \n");
-
-       do {
-               udelay(100);
-               if (!delay_time--)
-                       break;
-               val = readl(the_transceiver->regs + CI_PORTSC1);
-               val &= PORTSC_LS;
-       } while (!val);
-
-       otg_dbg("check_se0_srp <- \n");
-       return val;
-}
-
-/* The timeout callback function to set time out bit */
-static void set_tmout(unsigned long indicator)
-{
-       *(int *)indicator = 1;
-}
-
-void langwell_otg_nsf_msg(unsigned long indicator)
-{
-       switch (indicator) {
-       case 2:
-       case 4:
-       case 6:
-       case 7:
-               printk(KERN_ERR "OTG:NSF-%lu - deivce not responding\n",
-                               indicator);
-               break;
-       case 3:
-               printk(KERN_ERR "OTG:NSF-%lu - deivce not supported\n",
-                               indicator);
-               break;
-       default:
-               printk(KERN_ERR "Do not have this kind of NSF\n");
-               break;
-       }
-}
-
-/* Initialize timers */
-static void langwell_otg_init_timers(struct otg_hsm *hsm)
-{
-       /* HSM used timers */
-       a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE,
-                               (unsigned long)&hsm->a_wait_vrise_tmout);
-       a_wait_bcon_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_BCON,
-                               (unsigned long)&hsm->a_wait_bcon_tmout);
-       a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS,
-                               (unsigned long)&hsm->a_aidl_bdis_tmout);
-       b_ase0_brst_tmr = otg_timer_initializer(&set_tmout, TB_ASE0_BRST,
-                               (unsigned long)&hsm->b_ase0_brst_tmout);
-       b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP,
-                               (unsigned long)&hsm->b_se0_srp);
-       b_srp_res_tmr = otg_timer_initializer(&set_tmout, TB_SRP_RES,
-                               (unsigned long)&hsm->b_srp_res_tmout);
-       b_bus_suspend_tmr = otg_timer_initializer(&set_tmout, TB_BUS_SUSPEND,
-                               (unsigned long)&hsm->b_bus_suspend_tmout);
-}
-
-/* Free timers */
-static void langwell_otg_free_timers(void)
-{
-       kfree(a_wait_vrise_tmr);
-       kfree(a_wait_bcon_tmr);
-       kfree(a_aidl_bdis_tmr);
-       kfree(b_ase0_brst_tmr);
-       kfree(b_se0_srp_tmr);
-       kfree(b_srp_res_tmr);
-       kfree(b_bus_suspend_tmr);
-}
-
-/* Add timer to timer list */
-static void langwell_otg_add_timer(void *gtimer)
-{
-       struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
-       struct langwell_otg_timer *tmp_timer;
-       u32     val32;
-
-       /* Check if the timer is already in the active list,
-        * if so update timer count
-        */
-       list_for_each_entry(tmp_timer, &active_timers, list)
-               if (tmp_timer == timer) {
-                       timer->count = timer->expires;
-                       return;
-               }
-       timer->count = timer->expires;
-
-       if (list_empty(&active_timers)) {
-               val32 = readl(the_transceiver->regs + CI_OTGSC);
-               writel(val32 | OTGSC_1MSE, the_transceiver->regs + CI_OTGSC);
-       }
-
-       list_add_tail(&timer->list, &active_timers);
-}
-
-/* Remove timer from the timer list; clear timeout status */
-static void langwell_otg_del_timer(void *gtimer)
-{
-       struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
-       struct langwell_otg_timer *tmp_timer, *del_tmp;
-       u32 val32;
-
-       list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list)
-               if (tmp_timer == timer)
-                       list_del(&timer->list);
-
-       if (list_empty(&active_timers)) {
-               val32 = readl(the_transceiver->regs + CI_OTGSC);
-               writel(val32 & ~OTGSC_1MSE, the_transceiver->regs + CI_OTGSC);
-       }
-}
-
-/* Reduce timer count by 1, and find timeout conditions.*/
-static int langwell_otg_tick_timer(u32 *int_sts)
-{
-       struct langwell_otg_timer *tmp_timer, *del_tmp;
-       int expired = 0;
-
-       list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) {
-               tmp_timer->count--;
-               /* check if timer expires */
-               if (!tmp_timer->count) {
-                       list_del(&tmp_timer->list);
-                       tmp_timer->function(tmp_timer->data);
-                       expired = 1;
-               }
-       }
-
-       if (list_empty(&active_timers)) {
-               otg_dbg("tick timer: disable 1ms int\n");
-               *int_sts = *int_sts & ~OTGSC_1MSE;
-       }
-       return expired;
-}
-
-static void reset_otg(void)
-{
-       u32     val;
-       int     delay_time = 1000;
-
-       otg_dbg("reseting OTG controller ...\n");
-       val = readl(the_transceiver->regs + CI_USBCMD);
-       writel(val | USBCMD_RST, the_transceiver->regs + CI_USBCMD);
-       do {
-               udelay(100);
-               if (!delay_time--)
-                       otg_dbg("reset timeout\n");
-               val = readl(the_transceiver->regs + CI_USBCMD);
-               val &= USBCMD_RST;
-       } while (val != 0);
-       otg_dbg("reset done.\n");
-}
-
-static void set_host_mode(void)
-{
-       u32     val;
-
-       reset_otg();
-       val = readl(the_transceiver->regs + CI_USBMODE);
-       val = (val & (~USBMODE_CM)) | USBMODE_HOST;
-       writel(val, the_transceiver->regs + CI_USBMODE);
-}
-
-static void set_client_mode(void)
-{
-       u32     val;
-
-       reset_otg();
-       val = readl(the_transceiver->regs + CI_USBMODE);
-       val = (val & (~USBMODE_CM)) | USBMODE_DEVICE;
-       writel(val, the_transceiver->regs + CI_USBMODE);
-}
-
-static void init_hsm(void)
-{
-       struct langwell_otg     *langwell = the_transceiver;
-       u32                     val32;
-
-       /* read OTGSC after reset */
-       val32 = readl(langwell->regs + CI_OTGSC);
-       otg_dbg("%s: OTGSC init value = 0x%x\n", __func__, val32);
-
-       /* set init state */
-       if (val32 & OTGSC_ID) {
-               langwell->hsm.id = 1;
-               langwell->otg.default_a = 0;
-               set_client_mode();
-               langwell->otg.state = OTG_STATE_B_IDLE;
-               langwell_otg_drv_vbus(0);
-       } else {
-               langwell->hsm.id = 0;
-               langwell->otg.default_a = 1;
-               set_host_mode();
-               langwell->otg.state = OTG_STATE_A_IDLE;
-       }
-
-       /* set session indicator */
-       if (val32 & OTGSC_BSE)
-               langwell->hsm.b_sess_end = 1;
-       if (val32 & OTGSC_BSV)
-               langwell->hsm.b_sess_vld = 1;
-       if (val32 & OTGSC_ASV)
-               langwell->hsm.a_sess_vld = 1;
-       if (val32 & OTGSC_AVV)
-               langwell->hsm.a_vbus_vld = 1;
-
-       /* defautly power the bus */
-       langwell->hsm.a_bus_req = 1;
-       langwell->hsm.a_bus_drop = 0;
-       /* defautly don't request bus as B device */
-       langwell->hsm.b_bus_req = 0;
-       /* no system error */
-       langwell->hsm.a_clr_err = 0;
-}
-
-static irqreturn_t otg_dummy_irq(int irq, void *_dev)
-{
-       void __iomem    *reg_base = _dev;
-       u32     val;
-       u32     int_mask = 0;
-
-       val = readl(reg_base + CI_USBMODE);
-       if ((val & USBMODE_CM) != USBMODE_DEVICE)
-               return IRQ_NONE;
-
-       val = readl(reg_base + CI_USBSTS);
-       int_mask = val & INTR_DUMMY_MASK;
-
-       if (int_mask == 0)
-               return IRQ_NONE;
-
-       /* clear hsm.b_conn here since host driver can't detect it
-       *  otg_dummy_irq called means B-disconnect happened.
-       */
-       if (the_transceiver->hsm.b_conn) {
-               the_transceiver->hsm.b_conn = 0;
-               if (spin_trylock(&the_transceiver->wq_lock)) {
-                       queue_work(the_transceiver->qwork,
-                               &the_transceiver->work);
-                       spin_unlock(&the_transceiver->wq_lock);
-               }
-       }
-       /* Clear interrupts */
-       writel(int_mask, reg_base + CI_USBSTS);
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t otg_irq(int irq, void *_dev)
-{
-       struct  langwell_otg *langwell = _dev;
-       u32     int_sts, int_en;
-       u32     int_mask = 0;
-       int     flag = 0;
-
-       int_sts = readl(langwell->regs + CI_OTGSC);
-       int_en = (int_sts & OTGSC_INTEN_MASK) >> 8;
-       int_mask = int_sts & int_en;
-       if (int_mask == 0)
-               return IRQ_NONE;
-
-       if (int_mask & OTGSC_IDIS) {
-               otg_dbg("%s: id change int\n", __func__);
-               langwell->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0;
-               flag = 1;
-       }
-       if (int_mask & OTGSC_DPIS) {
-               otg_dbg("%s: data pulse int\n", __func__);
-               langwell->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0;
-               flag = 1;
-       }
-       if (int_mask & OTGSC_BSEIS) {
-               otg_dbg("%s: b session end int\n", __func__);
-               langwell->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0;
-               flag = 1;
-       }
-       if (int_mask & OTGSC_BSVIS) {
-               otg_dbg("%s: b session valid int\n", __func__);
-               langwell->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0;
-               flag = 1;
-       }
-       if (int_mask & OTGSC_ASVIS) {
-               otg_dbg("%s: a session valid int\n", __func__);
-               langwell->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0;
-               flag = 1;
-       }
-       if (int_mask & OTGSC_AVVIS) {
-               otg_dbg("%s: a vbus valid int\n", __func__);
-               langwell->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0;
-               flag = 1;
-       }
-
-       if (int_mask & OTGSC_1MSS) {
-               /* need to schedule otg_work if any timer is expired */
-               if (langwell_otg_tick_timer(&int_sts))
-                       flag = 1;
-       }
-
-       writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask,
-                       langwell->regs + CI_OTGSC);
-       if (flag)
-               queue_work(langwell->qwork, &langwell->work);
-
-       return IRQ_HANDLED;
-}
-
-static void langwell_otg_work(struct work_struct *work)
-{
-       struct langwell_otg *langwell = container_of(work,
-                                       struct langwell_otg, work);
-       int     retval;
-
-       otg_dbg("%s: old state = %s\n", __func__,
-                       state_string(langwell->otg.state));
-
-       switch (langwell->otg.state) {
-       case OTG_STATE_UNDEFINED:
-       case OTG_STATE_B_IDLE:
-               if (!langwell->hsm.id) {
-                       langwell_otg_del_timer(b_srp_res_tmr);
-                       langwell->otg.default_a = 1;
-                       langwell->hsm.a_srp_det = 0;
-
-                       langwell_otg_chrg_vbus(0);
-                       langwell_otg_drv_vbus(0);
-
-                       set_host_mode();
-                       langwell->otg.state = OTG_STATE_A_IDLE;
-                       queue_work(langwell->qwork, &langwell->work);
-               } else if (langwell->hsm.b_srp_res_tmout) {
-                       langwell->hsm.b_srp_res_tmout = 0;
-                       langwell->hsm.b_bus_req = 0;
-                       langwell_otg_nsf_msg(6);
-               } else if (langwell->hsm.b_sess_vld) {
-                       langwell_otg_del_timer(b_srp_res_tmr);
-                       langwell->hsm.b_sess_end = 0;
-                       langwell->hsm.a_bus_suspend = 0;
-
-                       langwell_otg_chrg_vbus(0);
-                       if (langwell->client_ops) {
-                               langwell->client_ops->resume(langwell->pdev);
-                               langwell->otg.state = OTG_STATE_B_PERIPHERAL;
-                       } else
-                               otg_dbg("client driver not loaded.\n");
-
-               } else if (langwell->hsm.b_bus_req &&
-                               (langwell->hsm.b_sess_end)) {
-                       /* workaround for b_se0_srp detection */
-                       retval = langwell_otg_check_se0_srp(0);
-                       if (retval) {
-                               langwell->hsm.b_bus_req = 0;
-                               otg_dbg("LS is not SE0, try again later\n");
-                       } else {
-                               /* Start SRP */
-                               langwell_otg_start_srp(&langwell->otg);
-                               langwell_otg_add_timer(b_srp_res_tmr);
-                       }
-               }
-               break;
-       case OTG_STATE_B_SRP_INIT:
-               if (!langwell->hsm.id) {
-                       langwell->otg.default_a = 1;
-                       langwell->hsm.a_srp_det = 0;
-
-                       langwell_otg_drv_vbus(0);
-                       langwell_otg_chrg_vbus(0);
-
-                       langwell->otg.state = OTG_STATE_A_IDLE;
-                       queue_work(langwell->qwork, &langwell->work);
-               } else if (langwell->hsm.b_sess_vld) {
-                       langwell_otg_chrg_vbus(0);
-                       if (langwell->client_ops) {
-                               langwell->client_ops->resume(langwell->pdev);
-                               langwell->otg.state = OTG_STATE_B_PERIPHERAL;
-                       } else
-                               otg_dbg("client driver not loaded.\n");
-               }
-               break;
-       case OTG_STATE_B_PERIPHERAL:
-               if (!langwell->hsm.id) {
-                       langwell->otg.default_a = 1;
-                       langwell->hsm.a_srp_det = 0;
-
-                       langwell_otg_drv_vbus(0);
-                       langwell_otg_chrg_vbus(0);
-                       set_host_mode();
-
-                       if (langwell->client_ops) {
-                               langwell->client_ops->suspend(langwell->pdev,
-                                       PMSG_FREEZE);
-                       } else
-                               otg_dbg("client driver has been removed.\n");
-
-                       langwell->otg.state = OTG_STATE_A_IDLE;
-                       queue_work(langwell->qwork, &langwell->work);
-               } else if (!langwell->hsm.b_sess_vld) {
-                       langwell->hsm.b_hnp_enable = 0;
-
-                       if (langwell->client_ops) {
-                               langwell->client_ops->suspend(langwell->pdev,
-                                       PMSG_FREEZE);
-                       } else
-                               otg_dbg("client driver has been removed.\n");
-
-                       langwell->otg.state = OTG_STATE_B_IDLE;
-               } else if (langwell->hsm.b_bus_req && langwell->hsm.b_hnp_enable
-                       && langwell->hsm.a_bus_suspend) {
-
-                       if (langwell->client_ops) {
-                               langwell->client_ops->suspend(langwell->pdev,
-                                       PMSG_FREEZE);
-                       } else
-                               otg_dbg("client driver has been removed.\n");
-
-                       langwell_otg_HAAR(1);
-                       langwell->hsm.a_conn = 0;
-
-                       if (langwell->host_ops) {
-                               langwell->host_ops->probe(langwell->pdev,
-                                       langwell->host_ops->id_table);
-                               langwell->otg.state = OTG_STATE_B_WAIT_ACON;
-                       } else
-                               otg_dbg("host driver not loaded.\n");
-
-                       langwell->hsm.a_bus_resume = 0;
-                       langwell->hsm.b_ase0_brst_tmout = 0;
-                       langwell_otg_add_timer(b_ase0_brst_tmr);
-               }
-               break;
-
-       case OTG_STATE_B_WAIT_ACON:
-               if (!langwell->hsm.id) {
-                       langwell_otg_del_timer(b_ase0_brst_tmr);
-                       langwell->otg.default_a = 1;
-                       langwell->hsm.a_srp_det = 0;
-
-                       langwell_otg_drv_vbus(0);
-                       langwell_otg_chrg_vbus(0);
-                       set_host_mode();
-
-                       langwell_otg_HAAR(0);
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-                       langwell->otg.state = OTG_STATE_A_IDLE;
-                       queue_work(langwell->qwork, &langwell->work);
-               } else if (!langwell->hsm.b_sess_vld) {
-                       langwell_otg_del_timer(b_ase0_brst_tmr);
-                       langwell->hsm.b_hnp_enable = 0;
-                       langwell->hsm.b_bus_req = 0;
-                       langwell_otg_chrg_vbus(0);
-                       langwell_otg_HAAR(0);
-
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-                       langwell->otg.state = OTG_STATE_B_IDLE;
-               } else if (langwell->hsm.a_conn) {
-                       langwell_otg_del_timer(b_ase0_brst_tmr);
-                       langwell_otg_HAAR(0);
-                       langwell->otg.state = OTG_STATE_B_HOST;
-                       queue_work(langwell->qwork, &langwell->work);
-               } else if (langwell->hsm.a_bus_resume ||
-                               langwell->hsm.b_ase0_brst_tmout) {
-                       langwell_otg_del_timer(b_ase0_brst_tmr);
-                       langwell_otg_HAAR(0);
-                       langwell_otg_nsf_msg(7);
-
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-
-                       langwell->hsm.a_bus_suspend = 0;
-                       langwell->hsm.b_bus_req = 0;
-
-                       if (langwell->client_ops)
-                               langwell->client_ops->resume(langwell->pdev);
-                       else
-                               otg_dbg("client driver not loaded.\n");
-
-                       langwell->otg.state = OTG_STATE_B_PERIPHERAL;
-               }
-               break;
-
-       case OTG_STATE_B_HOST:
-               if (!langwell->hsm.id) {
-                       langwell->otg.default_a = 1;
-                       langwell->hsm.a_srp_det = 0;
-
-                       langwell_otg_drv_vbus(0);
-                       langwell_otg_chrg_vbus(0);
-                       set_host_mode();
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-                       langwell->otg.state = OTG_STATE_A_IDLE;
-                       queue_work(langwell->qwork, &langwell->work);
-               } else if (!langwell->hsm.b_sess_vld) {
-                       langwell->hsm.b_hnp_enable = 0;
-                       langwell->hsm.b_bus_req = 0;
-                       langwell_otg_chrg_vbus(0);
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-                       langwell->otg.state = OTG_STATE_B_IDLE;
-               } else if ((!langwell->hsm.b_bus_req) ||
-                               (!langwell->hsm.a_conn)) {
-                       langwell->hsm.b_bus_req = 0;
-                       langwell_otg_loc_sof(0);
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-
-                       langwell->hsm.a_bus_suspend = 0;
-
-                       if (langwell->client_ops)
-                               langwell->client_ops->resume(langwell->pdev);
-                       else
-                               otg_dbg("client driver not loaded.\n");
-
-                       langwell->otg.state = OTG_STATE_B_PERIPHERAL;
-               }
-               break;
-
-       case OTG_STATE_A_IDLE:
-               langwell->otg.default_a = 1;
-               if (langwell->hsm.id) {
-                       langwell->otg.default_a = 0;
-                       langwell->hsm.b_bus_req = 0;
-                       langwell_otg_drv_vbus(0);
-                       langwell_otg_chrg_vbus(0);
-
-                       langwell->otg.state = OTG_STATE_B_IDLE;
-                       queue_work(langwell->qwork, &langwell->work);
-               } else if (langwell->hsm.a_sess_vld) {
-                       langwell_otg_drv_vbus(1);
-                       langwell->hsm.a_srp_det = 1;
-                       langwell->hsm.a_wait_vrise_tmout = 0;
-                       langwell_otg_add_timer(a_wait_vrise_tmr);
-                       langwell->otg.state = OTG_STATE_A_WAIT_VRISE;
-                       queue_work(langwell->qwork, &langwell->work);
-               } else if (!langwell->hsm.a_bus_drop &&
-                       (langwell->hsm.a_srp_det || langwell->hsm.a_bus_req)) {
-                       langwell_otg_drv_vbus(1);
-                       langwell->hsm.a_wait_vrise_tmout = 0;
-                       langwell_otg_add_timer(a_wait_vrise_tmr);
-                       langwell->otg.state = OTG_STATE_A_WAIT_VRISE;
-                       queue_work(langwell->qwork, &langwell->work);
-               }
-               break;
-       case OTG_STATE_A_WAIT_VRISE:
-               if (langwell->hsm.id) {
-                       langwell_otg_del_timer(a_wait_vrise_tmr);
-                       langwell->hsm.b_bus_req = 0;
-                       langwell->otg.default_a = 0;
-                       langwell_otg_drv_vbus(0);
-                       langwell->otg.state = OTG_STATE_B_IDLE;
-               } else if (langwell->hsm.a_vbus_vld) {
-                       langwell_otg_del_timer(a_wait_vrise_tmr);
-                       if (langwell->host_ops)
-                               langwell->host_ops->probe(langwell->pdev,
-                                               langwell->host_ops->id_table);
-                       else
-                               otg_dbg("host driver not loaded.\n");
-                       langwell->hsm.b_conn = 0;
-                       langwell->hsm.a_set_b_hnp_en = 0;
-                       langwell->hsm.a_wait_bcon_tmout = 0;
-                       langwell_otg_add_timer(a_wait_bcon_tmr);
-                       langwell->otg.state = OTG_STATE_A_WAIT_BCON;
-               } else if (langwell->hsm.a_wait_vrise_tmout) {
-                       if (langwell->hsm.a_vbus_vld) {
-                               if (langwell->host_ops)
-                                       langwell->host_ops->probe(
-                                               langwell->pdev,
-                                               langwell->host_ops->id_table);
-                               else
-                                       otg_dbg("host driver not loaded.\n");
-                               langwell->hsm.b_conn = 0;
-                               langwell->hsm.a_set_b_hnp_en = 0;
-                               langwell->hsm.a_wait_bcon_tmout = 0;
-                               langwell_otg_add_timer(a_wait_bcon_tmr);
-                               langwell->otg.state = OTG_STATE_A_WAIT_BCON;
-                       } else {
-                               langwell_otg_drv_vbus(0);
-                               langwell->otg.state = OTG_STATE_A_VBUS_ERR;
-                       }
-               }
-               break;
-       case OTG_STATE_A_WAIT_BCON:
-               if (langwell->hsm.id) {
-                       langwell_otg_del_timer(a_wait_bcon_tmr);
-
-                       langwell->otg.default_a = 0;
-                       langwell->hsm.b_bus_req = 0;
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-                       langwell_otg_drv_vbus(0);
-                       langwell->otg.state = OTG_STATE_B_IDLE;
-                       queue_work(langwell->qwork, &langwell->work);
-               } else if (!langwell->hsm.a_vbus_vld) {
-                       langwell_otg_del_timer(a_wait_bcon_tmr);
-
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-                       langwell_otg_drv_vbus(0);
-                       langwell->otg.state = OTG_STATE_A_VBUS_ERR;
-               } else if (langwell->hsm.a_bus_drop ||
-                               (langwell->hsm.a_wait_bcon_tmout &&
-                               !langwell->hsm.a_bus_req)) {
-                       langwell_otg_del_timer(a_wait_bcon_tmr);
-
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-                       langwell_otg_drv_vbus(0);
-                       langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
-               } else if (langwell->hsm.b_conn) {
-                       langwell_otg_del_timer(a_wait_bcon_tmr);
-
-                       langwell->hsm.a_suspend_req = 0;
-                       langwell->otg.state = OTG_STATE_A_HOST;
-                       if (!langwell->hsm.a_bus_req &&
-                               langwell->hsm.a_set_b_hnp_en) {
-                               /* It is not safe enough to do a fast
-                                * transistion from A_WAIT_BCON to
-                                * A_SUSPEND */
-                               msleep(10000);
-                               if (langwell->hsm.a_bus_req)
-                                       break;
-
-                               if (request_irq(langwell->pdev->irq,
-                                       otg_dummy_irq, IRQF_SHARED,
-                                       driver_name, langwell->regs) != 0) {
-                                       otg_dbg("request interrupt %d fail\n",
-                                       langwell->pdev->irq);
-                               }
-
-                               langwell_otg_HABA(1);
-                               langwell->hsm.b_bus_resume = 0;
-                               langwell->hsm.a_aidl_bdis_tmout = 0;
-                               langwell_otg_add_timer(a_aidl_bdis_tmr);
-
-                               langwell_otg_loc_sof(0);
-                               langwell->otg.state = OTG_STATE_A_SUSPEND;
-                       } else if (!langwell->hsm.a_bus_req &&
-                               !langwell->hsm.a_set_b_hnp_en) {
-                               struct pci_dev *pdev = langwell->pdev;
-                               if (langwell->host_ops)
-                                       langwell->host_ops->remove(pdev);
-                               else
-                                       otg_dbg("host driver removed.\n");
-                               langwell_otg_drv_vbus(0);
-                               langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
-                       }
-               }
-               break;
-       case OTG_STATE_A_HOST:
-               if (langwell->hsm.id) {
-                       langwell->otg.default_a = 0;
-                       langwell->hsm.b_bus_req = 0;
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-                       langwell_otg_drv_vbus(0);
-                       langwell->otg.state = OTG_STATE_B_IDLE;
-                       queue_work(langwell->qwork, &langwell->work);
-               } else if (langwell->hsm.a_bus_drop ||
-               (!langwell->hsm.a_set_b_hnp_en && !langwell->hsm.a_bus_req)) {
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-                       langwell_otg_drv_vbus(0);
-                       langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
-               } else if (!langwell->hsm.a_vbus_vld) {
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-                       langwell_otg_drv_vbus(0);
-                       langwell->otg.state = OTG_STATE_A_VBUS_ERR;
-               } else if (langwell->hsm.a_set_b_hnp_en
-                               && !langwell->hsm.a_bus_req) {
-                       /* Set HABA to enable hardware assistance to signal
-                        *  A-connect after receiver B-disconnect. Hardware
-                        *  will then set client mode and enable URE, SLE and
-                        *  PCE after the assistance. otg_dummy_irq is used to
-                        *  clean these ints when client driver is not resumed.
-                        */
-                       if (request_irq(langwell->pdev->irq,
-                               otg_dummy_irq, IRQF_SHARED, driver_name,
-                               langwell->regs) != 0) {
-                               otg_dbg("request interrupt %d failed\n",
-                                               langwell->pdev->irq);
-                       }
-
-                       /* set HABA */
-                       langwell_otg_HABA(1);
-                       langwell->hsm.b_bus_resume = 0;
-                       langwell->hsm.a_aidl_bdis_tmout = 0;
-                       langwell_otg_add_timer(a_aidl_bdis_tmr);
-                       langwell_otg_loc_sof(0);
-                       langwell->otg.state = OTG_STATE_A_SUSPEND;
-               } else if (!langwell->hsm.b_conn || !langwell->hsm.a_bus_req) {
-                       langwell->hsm.a_wait_bcon_tmout = 0;
-                       langwell->hsm.a_set_b_hnp_en = 0;
-                       langwell_otg_add_timer(a_wait_bcon_tmr);
-                       langwell->otg.state = OTG_STATE_A_WAIT_BCON;
-               }
-               break;
-       case OTG_STATE_A_SUSPEND:
-               if (langwell->hsm.id) {
-                       langwell_otg_del_timer(a_aidl_bdis_tmr);
-                       langwell_otg_HABA(0);
-                       free_irq(langwell->pdev->irq, langwell->regs);
-                       langwell->otg.default_a = 0;
-                       langwell->hsm.b_bus_req = 0;
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-                       langwell_otg_drv_vbus(0);
-                       langwell->otg.state = OTG_STATE_B_IDLE;
-                       queue_work(langwell->qwork, &langwell->work);
-               } else if (langwell->hsm.a_bus_req ||
-                               langwell->hsm.b_bus_resume) {
-                       langwell_otg_del_timer(a_aidl_bdis_tmr);
-                       langwell_otg_HABA(0);
-                       free_irq(langwell->pdev->irq, langwell->regs);
-                       langwell->hsm.a_suspend_req = 0;
-                       langwell_otg_loc_sof(1);
-                       langwell->otg.state = OTG_STATE_A_HOST;
-               } else if (langwell->hsm.a_aidl_bdis_tmout ||
-                               langwell->hsm.a_bus_drop) {
-                       langwell_otg_del_timer(a_aidl_bdis_tmr);
-                       langwell_otg_HABA(0);
-                       free_irq(langwell->pdev->irq, langwell->regs);
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-                       langwell_otg_drv_vbus(0);
-                       langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
-               } else if (!langwell->hsm.b_conn &&
-                               langwell->hsm.a_set_b_hnp_en) {
-                       langwell_otg_del_timer(a_aidl_bdis_tmr);
-                       langwell_otg_HABA(0);
-                       free_irq(langwell->pdev->irq, langwell->regs);
-
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-
-                       langwell->hsm.b_bus_suspend = 0;
-                       langwell->hsm.b_bus_suspend_vld = 0;
-                       langwell->hsm.b_bus_suspend_tmout = 0;
-
-                       /* msleep(200); */
-                       if (langwell->client_ops)
-                               langwell->client_ops->resume(langwell->pdev);
-                       else
-                               otg_dbg("client driver not loaded.\n");
-
-                       langwell_otg_add_timer(b_bus_suspend_tmr);
-                       langwell->otg.state = OTG_STATE_A_PERIPHERAL;
-                       break;
-               } else if (!langwell->hsm.a_vbus_vld) {
-                       langwell_otg_del_timer(a_aidl_bdis_tmr);
-                       langwell_otg_HABA(0);
-                       free_irq(langwell->pdev->irq, langwell->regs);
-                       if (langwell->host_ops)
-                               langwell->host_ops->remove(langwell->pdev);
-                       else
-                               otg_dbg("host driver has been removed.\n");
-                       langwell_otg_drv_vbus(0);
-                       langwell->otg.state = OTG_STATE_A_VBUS_ERR;
-               }
-               break;
-       case OTG_STATE_A_PERIPHERAL:
-               if (langwell->hsm.id) {
-                       langwell_otg_del_timer(b_bus_suspend_tmr);
-                       langwell->otg.default_a = 0;
-                       langwell->hsm.b_bus_req = 0;
-                       if (langwell->client_ops)
-                               langwell->client_ops->suspend(langwell->pdev,
-                                       PMSG_FREEZE);
-                       else
-                               otg_dbg("client driver has been removed.\n");
-                       langwell_otg_drv_vbus(0);
-                       langwell->otg.state = OTG_STATE_B_IDLE;
-                       queue_work(langwell->qwork, &langwell->work);
-               } else if (!langwell->hsm.a_vbus_vld) {
-                       langwell_otg_del_timer(b_bus_suspend_tmr);
-                       if (langwell->client_ops)
-                               langwell->client_ops->suspend(langwell->pdev,
-                                       PMSG_FREEZE);
-                       else
-                               otg_dbg("client driver has been removed.\n");
-                       langwell_otg_drv_vbus(0);
-                       langwell->otg.state = OTG_STATE_A_VBUS_ERR;
-               } else if (langwell->hsm.a_bus_drop) {
-                       langwell_otg_del_timer(b_bus_suspend_tmr);
-                       if (langwell->client_ops)
-                               langwell->client_ops->suspend(langwell->pdev,
-                                       PMSG_FREEZE);
-                       else
-                               otg_dbg("client driver has been removed.\n");
-                       langwell_otg_drv_vbus(0);
-                       langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
-               } else if (langwell->hsm.b_bus_suspend) {
-                       langwell_otg_del_timer(b_bus_suspend_tmr);
-                       if (langwell->client_ops)
-                               langwell->client_ops->suspend(langwell->pdev,
-                                       PMSG_FREEZE);
-                       else
-                               otg_dbg("client driver has been removed.\n");
-
-                       if (langwell->host_ops)
-                               langwell->host_ops->probe(langwell->pdev,
-                                               langwell->host_ops->id_table);
-                       else
-                               otg_dbg("host driver not loaded.\n");
-                       langwell->hsm.a_set_b_hnp_en = 0;
-                       langwell->hsm.a_wait_bcon_tmout = 0;
-                       langwell_otg_add_timer(a_wait_bcon_tmr);
-                       langwell->otg.state = OTG_STATE_A_WAIT_BCON;
-               } else if (langwell->hsm.b_bus_suspend_tmout) {
-                       u32     val;
-                       val = readl(langwell->regs + CI_PORTSC1);
-                       if (!(val & PORTSC_SUSP))
-                               break;
-                       if (langwell->client_ops)
-                               langwell->client_ops->suspend(langwell->pdev,
-                                               PMSG_FREEZE);
-                       else
-                               otg_dbg("client driver has been removed.\n");
-                       if (langwell->host_ops)
-                               langwell->host_ops->probe(langwell->pdev,
-                                               langwell->host_ops->id_table);
-                       else
-                               otg_dbg("host driver not loaded.\n");
-                       langwell->hsm.a_set_b_hnp_en = 0;
-                       langwell->hsm.a_wait_bcon_tmout = 0;
-                       langwell_otg_add_timer(a_wait_bcon_tmr);
-                       langwell->otg.state = OTG_STATE_A_WAIT_BCON;
-               }
-               break;
-       case OTG_STATE_A_VBUS_ERR:
-               if (langwell->hsm.id) {
-                       langwell->otg.default_a = 0;
-                       langwell->hsm.a_clr_err = 0;
-                       langwell->hsm.a_srp_det = 0;
-                       langwell->otg.state = OTG_STATE_B_IDLE;
-                       queue_work(langwell->qwork, &langwell->work);
-               } else if (langwell->hsm.a_clr_err) {
-                       langwell->hsm.a_clr_err = 0;
-                       langwell->hsm.a_srp_det = 0;
-                       reset_otg();
-                       init_hsm();
-                       if (langwell->otg.state == OTG_STATE_A_IDLE)
-                               queue_work(langwell->qwork, &langwell->work);
-               }
-               break;
-       case OTG_STATE_A_WAIT_VFALL:
-               if (langwell->hsm.id) {
-                       langwell->otg.default_a = 0;
-                       langwell->otg.state = OTG_STATE_B_IDLE;
-                       queue_work(langwell->qwork, &langwell->work);
-               } else if (langwell->hsm.a_bus_req) {
-                       langwell_otg_drv_vbus(1);
-                       langwell->hsm.a_wait_vrise_tmout = 0;
-                       langwell_otg_add_timer(a_wait_vrise_tmr);
-                       langwell->otg.state = OTG_STATE_A_WAIT_VRISE;
-               } else if (!langwell->hsm.a_sess_vld) {
-                       langwell->hsm.a_srp_det = 0;
-                       langwell_otg_drv_vbus(0);
-                       set_host_mode();
-                       langwell->otg.state = OTG_STATE_A_IDLE;
-               }
-               break;
-       default:
-               ;
-       }
-
-       otg_dbg("%s: new state = %s\n", __func__,
-                       state_string(langwell->otg.state));
-}
-
-       static ssize_t
-show_registers(struct device *_dev, struct device_attribute *attr, char *buf)
-{
-       struct langwell_otg *langwell;
-       char *next;
-       unsigned size;
-       unsigned t;
-
-       langwell = the_transceiver;
-       next = buf;
-       size = PAGE_SIZE;
-
-       t = scnprintf(next, size,
-               "\n"
-               "USBCMD = 0x%08x \n"
-               "USBSTS = 0x%08x \n"
-               "USBINTR = 0x%08x \n"
-               "ASYNCLISTADDR = 0x%08x \n"
-               "PORTSC1 = 0x%08x \n"
-               "HOSTPC1 = 0x%08x \n"
-               "OTGSC = 0x%08x \n"
-               "USBMODE = 0x%08x \n",
-               readl(langwell->regs + 0x30),
-               readl(langwell->regs + 0x34),
-               readl(langwell->regs + 0x38),
-               readl(langwell->regs + 0x48),
-               readl(langwell->regs + 0x74),
-               readl(langwell->regs + 0xb4),
-               readl(langwell->regs + 0xf4),
-               readl(langwell->regs + 0xf8)
-               );
-       size -= t;
-       next += t;
-
-       return PAGE_SIZE - size;
-}
-static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL);
-
-static ssize_t
-show_hsm(struct device *_dev, struct device_attribute *attr, char *buf)
-{
-       struct langwell_otg *langwell;
-       char *next;
-       unsigned size;
-       unsigned t;
-
-       langwell = the_transceiver;
-       next = buf;
-       size = PAGE_SIZE;
-
-       t = scnprintf(next, size,
-               "\n"
-               "current state = %s\n"
-               "a_bus_resume = \t%d\n"
-               "a_bus_suspend = \t%d\n"
-               "a_conn = \t%d\n"
-               "a_sess_vld = \t%d\n"
-               "a_srp_det = \t%d\n"
-               "a_vbus_vld = \t%d\n"
-               "b_bus_resume = \t%d\n"
-               "b_bus_suspend = \t%d\n"
-               "b_conn = \t%d\n"
-               "b_se0_srp = \t%d\n"
-               "b_sess_end = \t%d\n"
-               "b_sess_vld = \t%d\n"
-               "id = \t%d\n"
-               "a_set_b_hnp_en = \t%d\n"
-               "b_srp_done = \t%d\n"
-               "b_hnp_enable = \t%d\n"
-               "a_wait_vrise_tmout = \t%d\n"
-               "a_wait_bcon_tmout = \t%d\n"
-               "a_aidl_bdis_tmout = \t%d\n"
-               "b_ase0_brst_tmout = \t%d\n"
-               "a_bus_drop = \t%d\n"
-               "a_bus_req = \t%d\n"
-               "a_clr_err = \t%d\n"
-               "a_suspend_req = \t%d\n"
-               "b_bus_req = \t%d\n"
-               "b_bus_suspend_tmout = \t%d\n"
-               "b_bus_suspend_vld = \t%d\n",
-               state_string(langwell->otg.state),
-               langwell->hsm.a_bus_resume,
-               langwell->hsm.a_bus_suspend,
-               langwell->hsm.a_conn,
-               langwell->hsm.a_sess_vld,
-               langwell->hsm.a_srp_det,
-               langwell->hsm.a_vbus_vld,
-               langwell->hsm.b_bus_resume,
-               langwell->hsm.b_bus_suspend,
-               langwell->hsm.b_conn,
-               langwell->hsm.b_se0_srp,
-               langwell->hsm.b_sess_end,
-               langwell->hsm.b_sess_vld,
-               langwell->hsm.id,
-               langwell->hsm.a_set_b_hnp_en,
-               langwell->hsm.b_srp_done,
-               langwell->hsm.b_hnp_enable,
-               langwell->hsm.a_wait_vrise_tmout,
-               langwell->hsm.a_wait_bcon_tmout,
-               langwell->hsm.a_aidl_bdis_tmout,
-               langwell->hsm.b_ase0_brst_tmout,
-               langwell->hsm.a_bus_drop,
-               langwell->hsm.a_bus_req,
-               langwell->hsm.a_clr_err,
-               langwell->hsm.a_suspend_req,
-               langwell->hsm.b_bus_req,
-               langwell->hsm.b_bus_suspend_tmout,
-               langwell->hsm.b_bus_suspend_vld
-               );
-       size -= t;
-       next += t;
-
-       return PAGE_SIZE - size;
-}
-static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL);
-
-static ssize_t
-get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct langwell_otg *langwell;
-       char *next;
-       unsigned size;
-       unsigned t;
-
-       langwell =  the_transceiver;
-       next = buf;
-       size = PAGE_SIZE;
-
-       t = scnprintf(next, size, "%d", langwell->hsm.a_bus_req);
-       size -= t;
-       next += t;
-
-       return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_a_bus_req(struct device *dev, struct device_attribute *attr,
-               const char *buf, size_t count)
-{
-       struct langwell_otg *langwell;
-       langwell = the_transceiver;
-       if (!langwell->otg.default_a)
-               return -1;
-       if (count > 2)
-               return -1;
-
-       if (buf[0] == '0') {
-               langwell->hsm.a_bus_req = 0;
-               otg_dbg("a_bus_req = 0\n");
-       } else if (buf[0] == '1') {
-               /* If a_bus_drop is TRUE, a_bus_req can't be set */
-               if (langwell->hsm.a_bus_drop)
-                       return -1;
-               langwell->hsm.a_bus_req = 1;
-               otg_dbg("a_bus_req = 1\n");
-       }
-       if (spin_trylock(&langwell->wq_lock)) {
-               queue_work(langwell->qwork, &langwell->work);
-               spin_unlock(&langwell->wq_lock);
-       }
-       return count;
-}
-static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUGO, get_a_bus_req, set_a_bus_req);
-
-static ssize_t
-get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct langwell_otg *langwell;
-       char *next;
-       unsigned size;
-       unsigned t;
-
-       langwell =  the_transceiver;
-       next = buf;
-       size = PAGE_SIZE;
-
-       t = scnprintf(next, size, "%d", langwell->hsm.a_bus_drop);
-       size -= t;
-       next += t;
-
-       return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_a_bus_drop(struct device *dev, struct device_attribute *attr,
-               const char *buf, size_t count)
-{
-       struct langwell_otg *langwell;
-       langwell = the_transceiver;
-       if (!langwell->otg.default_a)
-               return -1;
-       if (count > 2)
-               return -1;
-
-       if (buf[0] == '0') {
-               langwell->hsm.a_bus_drop = 0;
-               otg_dbg("a_bus_drop = 0\n");
-       } else if (buf[0] == '1') {
-               langwell->hsm.a_bus_drop = 1;
-               langwell->hsm.a_bus_req = 0;
-               otg_dbg("a_bus_drop = 1, then a_bus_req = 0\n");
-       }
-       if (spin_trylock(&langwell->wq_lock)) {
-               queue_work(langwell->qwork, &langwell->work);
-               spin_unlock(&langwell->wq_lock);
-       }
-       return count;
-}
-static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUGO,
-       get_a_bus_drop, set_a_bus_drop);
-
-static ssize_t
-get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct langwell_otg *langwell;
-       char *next;
-       unsigned size;
-       unsigned t;
-
-       langwell =  the_transceiver;
-       next = buf;
-       size = PAGE_SIZE;
-
-       t = scnprintf(next, size, "%d", langwell->hsm.b_bus_req);
-       size -= t;
-       next += t;
-
-       return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_b_bus_req(struct device *dev, struct device_attribute *attr,
-               const char *buf, size_t count)
-{
-       struct langwell_otg *langwell;
-       langwell = the_transceiver;
-
-       if (langwell->otg.default_a)
-               return -1;
-
-       if (count > 2)
-               return -1;
-
-       if (buf[0] == '0') {
-               langwell->hsm.b_bus_req = 0;
-               otg_dbg("b_bus_req = 0\n");
-       } else if (buf[0] == '1') {
-               langwell->hsm.b_bus_req = 1;
-               otg_dbg("b_bus_req = 1\n");
-       }
-       if (spin_trylock(&langwell->wq_lock)) {
-               queue_work(langwell->qwork, &langwell->work);
-               spin_unlock(&langwell->wq_lock);
-       }
-       return count;
-}
-static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUGO, get_b_bus_req, set_b_bus_req);
-
-static ssize_t
-set_a_clr_err(struct device *dev, struct device_attribute *attr,
-               const char *buf, size_t count)
-{
-       struct langwell_otg *langwell;
-       langwell = the_transceiver;
-
-       if (!langwell->otg.default_a)
-               return -1;
-       if (count > 2)
-               return -1;
-
-       if (buf[0] == '1') {
-               langwell->hsm.a_clr_err = 1;
-               otg_dbg("a_clr_err = 1\n");
-       }
-       if (spin_trylock(&langwell->wq_lock)) {
-               queue_work(langwell->qwork, &langwell->work);
-               spin_unlock(&langwell->wq_lock);
-       }
-       return count;
-}
-static DEVICE_ATTR(a_clr_err, S_IWUGO, NULL, set_a_clr_err);
-
-static struct attribute *inputs_attrs[] = {
-       &dev_attr_a_bus_req.attr,
-       &dev_attr_a_bus_drop.attr,
-       &dev_attr_b_bus_req.attr,
-       &dev_attr_a_clr_err.attr,
-       NULL,
-};
-
-static struct attribute_group debug_dev_attr_group = {
-       .name = "inputs",
-       .attrs = inputs_attrs,
-};
-
-int langwell_register_host(struct pci_driver *host_driver)
-{
-       int     ret = 0;
-
-       the_transceiver->host_ops = host_driver;
-       queue_work(the_transceiver->qwork, &the_transceiver->work);
-       otg_dbg("host controller driver is registered\n");
-
-       return ret;
-}
-EXPORT_SYMBOL(langwell_register_host);
-
-void langwell_unregister_host(struct pci_driver *host_driver)
-{
-       if (the_transceiver->host_ops)
-               the_transceiver->host_ops->remove(the_transceiver->pdev);
-       the_transceiver->host_ops = NULL;
-       the_transceiver->hsm.a_bus_drop = 1;
-       queue_work(the_transceiver->qwork, &the_transceiver->work);
-       otg_dbg("host controller driver is unregistered\n");
-}
-EXPORT_SYMBOL(langwell_unregister_host);
-
-int langwell_register_peripheral(struct pci_driver *client_driver)
-{
-       int     ret = 0;
-
-       if (client_driver)
-               ret = client_driver->probe(the_transceiver->pdev,
-                               client_driver->id_table);
-       if (!ret) {
-               the_transceiver->client_ops = client_driver;
-               queue_work(the_transceiver->qwork, &the_transceiver->work);
-               otg_dbg("client controller driver is registered\n");
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL(langwell_register_peripheral);
-
-void langwell_unregister_peripheral(struct pci_driver *client_driver)
-{
-       if (the_transceiver->client_ops)
-               the_transceiver->client_ops->remove(the_transceiver->pdev);
-       the_transceiver->client_ops = NULL;
-       the_transceiver->hsm.b_bus_req = 0;
-       queue_work(the_transceiver->qwork, &the_transceiver->work);
-       otg_dbg("client controller driver is unregistered\n");
-}
-EXPORT_SYMBOL(langwell_unregister_peripheral);
-
-static int langwell_otg_probe(struct pci_dev *pdev,
-               const struct pci_device_id *id)
-{
-       unsigned long           resource, len;
-       void __iomem            *base = NULL;
-       int                     retval;
-       u32                     val32;
-       struct langwell_otg     *langwell;
-       char                    qname[] = "langwell_otg_queue";
-
-       retval = 0;
-       otg_dbg("\notg controller is detected.\n");
-       if (pci_enable_device(pdev) < 0) {
-               retval = -ENODEV;
-               goto done;
-       }
-
-       langwell = kzalloc(sizeof *langwell, GFP_KERNEL);
-       if (langwell == NULL) {
-               retval = -ENOMEM;
-               goto done;
-       }
-       the_transceiver = langwell;
-
-       /* control register: BAR 0 */
-       resource = pci_resource_start(pdev, 0);
-       len = pci_resource_len(pdev, 0);
-       if (!request_mem_region(resource, len, driver_name)) {
-               retval = -EBUSY;
-               goto err;
-       }
-       langwell->region = 1;
-
-       base = ioremap_nocache(resource, len);
-       if (base == NULL) {
-               retval = -EFAULT;
-               goto err;
-       }
-       langwell->regs = base;
-
-       if (!pdev->irq) {
-               otg_dbg("No IRQ.\n");
-               retval = -ENODEV;
-               goto err;
-       }
-
-       langwell->qwork = create_workqueue(qname);
-       if (!langwell->qwork) {
-               otg_dbg("cannot create workqueue %s\n", qname);
-               retval = -ENOMEM;
-               goto err;
-       }
-       INIT_WORK(&langwell->work, langwell_otg_work);
-
-       /* OTG common part */
-       langwell->pdev = pdev;
-       langwell->otg.dev = &pdev->dev;
-       langwell->otg.label = driver_name;
-       langwell->otg.set_host = langwell_otg_set_host;
-       langwell->otg.set_peripheral = langwell_otg_set_peripheral;
-       langwell->otg.set_power = langwell_otg_set_power;
-       langwell->otg.start_srp = langwell_otg_start_srp;
-       langwell->otg.state = OTG_STATE_UNDEFINED;
-       if (otg_set_transceiver(&langwell->otg)) {
-               otg_dbg("can't set transceiver\n");
-               retval = -EBUSY;
-               goto err;
-       }
-
-       reset_otg();
-       init_hsm();
-
-       spin_lock_init(&langwell->lock);
-       spin_lock_init(&langwell->wq_lock);
-       INIT_LIST_HEAD(&active_timers);
-       langwell_otg_init_timers(&langwell->hsm);
-
-       if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
-                               driver_name, langwell) != 0) {
-               otg_dbg("request interrupt %d failed\n", pdev->irq);
-               retval = -EBUSY;
-               goto err;
-       }
-
-       /* enable OTGSC int */
-       val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE |
-               OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU;
-       writel(val32, langwell->regs + CI_OTGSC);
-
-       retval = device_create_file(&pdev->dev, &dev_attr_registers);
-       if (retval < 0) {
-               otg_dbg("Can't register sysfs attribute: %d\n", retval);
-               goto err;
-       }
-
-       retval = device_create_file(&pdev->dev, &dev_attr_hsm);
-       if (retval < 0) {
-               otg_dbg("Can't hsm sysfs attribute: %d\n", retval);
-               goto err;
-       }
-
-       retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group);
-       if (retval < 0) {
-               otg_dbg("Can't register sysfs attr group: %d\n", retval);
-               goto err;
-       }
-
-       if (langwell->otg.state == OTG_STATE_A_IDLE)
-               queue_work(langwell->qwork, &langwell->work);
-
-       return 0;
-
-err:
-       if (the_transceiver)
-               langwell_otg_remove(pdev);
-done:
-       return retval;
-}
-
-static void langwell_otg_remove(struct pci_dev *pdev)
-{
-       struct langwell_otg *langwell;
-
-       langwell = the_transceiver;
-
-       if (langwell->qwork) {
-               flush_workqueue(langwell->qwork);
-               destroy_workqueue(langwell->qwork);
-       }
-       langwell_otg_free_timers();
-
-       /* disable OTGSC interrupt as OTGSC doesn't change in reset */
-       writel(0, langwell->regs + CI_OTGSC);
-
-       if (pdev->irq)
-               free_irq(pdev->irq, langwell);
-       if (langwell->regs)
-               iounmap(langwell->regs);
-       if (langwell->region)
-               release_mem_region(pci_resource_start(pdev, 0),
-                               pci_resource_len(pdev, 0));
-
-       otg_set_transceiver(NULL);
-       pci_disable_device(pdev);
-       sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group);
-       device_remove_file(&pdev->dev, &dev_attr_hsm);
-       device_remove_file(&pdev->dev, &dev_attr_registers);
-       kfree(langwell);
-       langwell = NULL;
-}
-
-static void transceiver_suspend(struct pci_dev *pdev)
-{
-       pci_save_state(pdev);
-       pci_set_power_state(pdev, PCI_D3hot);
-       langwell_otg_phy_low_power(1);
-}
-
-static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message)
-{
-       int     ret = 0;
-       struct langwell_otg *langwell;
-
-       langwell = the_transceiver;
-
-       /* Disbale OTG interrupts */
-       langwell_otg_intr(0);
-
-       if (pdev->irq)
-               free_irq(pdev->irq, langwell);
-
-       /* Prevent more otg_work */
-       flush_workqueue(langwell->qwork);
-       spin_lock(&langwell->wq_lock);
-
-       /* start actions */
-       switch (langwell->otg.state) {
-       case OTG_STATE_A_IDLE:
-       case OTG_STATE_B_IDLE:
-       case OTG_STATE_A_WAIT_VFALL:
-       case OTG_STATE_A_VBUS_ERR:
-               transceiver_suspend(pdev);
-               break;
-       case OTG_STATE_A_WAIT_VRISE:
-               langwell_otg_del_timer(a_wait_vrise_tmr);
-               langwell->hsm.a_srp_det = 0;
-               langwell_otg_drv_vbus(0);
-               langwell->otg.state = OTG_STATE_A_IDLE;
-               transceiver_suspend(pdev);
-               break;
-       case OTG_STATE_A_WAIT_BCON:
-               langwell_otg_del_timer(a_wait_bcon_tmr);
-               if (langwell->host_ops)
-                       ret = langwell->host_ops->suspend(pdev, message);
-               langwell_otg_drv_vbus(0);
-               break;
-       case OTG_STATE_A_HOST:
-               if (langwell->host_ops)
-                       ret = langwell->host_ops->suspend(pdev, message);
-               langwell_otg_drv_vbus(0);
-               langwell_otg_phy_low_power(1);
-               break;
-       case OTG_STATE_A_SUSPEND:
-               langwell_otg_del_timer(a_aidl_bdis_tmr);
-               langwell_otg_HABA(0);
-               if (langwell->host_ops)
-                       langwell->host_ops->remove(pdev);
-               else
-                       otg_dbg("host driver has been removed.\n");
-               langwell_otg_drv_vbus(0);
-               transceiver_suspend(pdev);
-               langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
-               break;
-       case OTG_STATE_A_PERIPHERAL:
-               if (langwell->client_ops)
-                       ret = langwell->client_ops->suspend(pdev, message);
-               else
-                       otg_dbg("client driver has been removed.\n");
-               langwell_otg_drv_vbus(0);
-               transceiver_suspend(pdev);
-               langwell->otg.state = OTG_STATE_A_WAIT_VFALL;
-               break;
-       case OTG_STATE_B_HOST:
-               if (langwell->host_ops)
-                       langwell->host_ops->remove(pdev);
-               else
-                       otg_dbg("host driver has been removed.\n");
-               langwell->hsm.b_bus_req = 0;
-               transceiver_suspend(pdev);
-               langwell->otg.state = OTG_STATE_B_IDLE;
-               break;
-       case OTG_STATE_B_PERIPHERAL:
-               if (langwell->client_ops)
-                       ret = langwell->client_ops->suspend(pdev, message);
-               else
-                       otg_dbg("client driver has been removed.\n");
-               break;
-       case OTG_STATE_B_WAIT_ACON:
-               langwell_otg_del_timer(b_ase0_brst_tmr);
-               langwell_otg_HAAR(0);
-               if (langwell->host_ops)
-                       langwell->host_ops->remove(pdev);
-               else
-                       otg_dbg("host driver has been removed.\n");
-               langwell->hsm.b_bus_req = 0;
-               langwell->otg.state = OTG_STATE_B_IDLE;
-               transceiver_suspend(pdev);
-               break;
-       default:
-               otg_dbg("error state before suspend\n ");
-               break;
-       }
-       spin_unlock(&langwell->wq_lock);
-
-       return ret;
-}
-
-static void transceiver_resume(struct pci_dev *pdev)
-{
-       pci_restore_state(pdev);
-       pci_set_power_state(pdev, PCI_D0);
-       langwell_otg_phy_low_power(0);
-}
-
-static int langwell_otg_resume(struct pci_dev *pdev)
-{
-       int     ret = 0;
-       struct langwell_otg *langwell;
-
-       langwell = the_transceiver;
-
-       spin_lock(&langwell->wq_lock);
-
-       switch (langwell->otg.state) {
-       case OTG_STATE_A_IDLE:
-       case OTG_STATE_B_IDLE:
-       case OTG_STATE_A_WAIT_VFALL:
-       case OTG_STATE_A_VBUS_ERR:
-               transceiver_resume(pdev);
-               break;
-       case OTG_STATE_A_WAIT_BCON:
-               langwell_otg_add_timer(a_wait_bcon_tmr);
-               langwell_otg_drv_vbus(1);
-               if (langwell->host_ops)
-                       ret = langwell->host_ops->resume(pdev);
-               break;
-       case OTG_STATE_A_HOST:
-               langwell_otg_drv_vbus(1);
-               langwell_otg_phy_low_power(0);
-               if (langwell->host_ops)
-                       ret = langwell->host_ops->resume(pdev);
-               break;
-       case OTG_STATE_B_PERIPHERAL:
-               if (langwell->client_ops)
-                       ret = langwell->client_ops->resume(pdev);
-               else
-                       otg_dbg("client driver not loaded.\n");
-               break;
-       default:
-               otg_dbg("error state before suspend\n ");
-               break;
-       }
-
-       if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
-                               driver_name, the_transceiver) != 0) {
-               otg_dbg("request interrupt %d failed\n", pdev->irq);
-               ret = -EBUSY;
-       }
-
-       /* enable OTG interrupts */
-       langwell_otg_intr(1);
-
-       spin_unlock(&langwell->wq_lock);
-
-       queue_work(langwell->qwork, &langwell->work);
-
-
-       return ret;
-}
-
-static int __init langwell_otg_init(void)
-{
-       return pci_register_driver(&otg_pci_driver);
-}
-module_init(langwell_otg_init);
-
-static void __exit langwell_otg_cleanup(void)
-{
-       pci_unregister_driver(&otg_pci_driver);
-}
-module_exit(langwell_otg_cleanup);
index 9ed5ea568679c3715eae4a03700d1ff8bd05e409..af456b48985f06f3ebe09ae43363f47f7d0bfec7 100644 (file)
@@ -53,6 +53,7 @@ EXPORT_SYMBOL(usb_nop_xceiv_register);
 void usb_nop_xceiv_unregister(void)
 {
        platform_device_unregister(pd);
+       pd = NULL;
 }
 EXPORT_SYMBOL(usb_nop_xceiv_unregister);
 
index 247b61bfb7f45f4d179abd6ef36f9611eea046da..0e4f2e41ace5b064193a46d3409d98df9099c117 100644 (file)
@@ -169,9 +169,11 @@ static int usb_console_setup(struct console *co, char *options)
                        kfree(tty);
                }
        }
-       /* So we know not to kill the hardware on a hangup on this
-          port. We have also bumped the use count by one so it won't go
-          idle */
+       /* Now that any required fake tty operations are completed restore
+        * the tty port count */
+       --port->port.count;
+       /* The console is special in terms of closing the device so
+        * indicate this port is now acting as a system console. */
        port->console = 1;
        retval = 0;
 
@@ -204,7 +206,7 @@ static void usb_console_write(struct console *co,
 
        dbg("%s - port %d, %d byte(s)", __func__, port->number, count);
 
-       if (!port->port.count) {
+       if (!port->console) {
                dbg("%s - port not opened", __func__);
                return;
        }
@@ -300,8 +302,7 @@ void usb_serial_console_exit(void)
 {
        if (usbcons_info.port) {
                unregister_console(&usbcons);
-               if (usbcons_info.port->port.count)
-                       usbcons_info.port->port.count--;
+               usbcons_info.port->console = 0;
                usbcons_info.port = NULL;
        }
 }
index 2b9eeda62bfe7beb12a4b3abb8aec6b3954e9f9c..985cbcf48bda83317d235395fbbca689f5649ee1 100644 (file)
@@ -67,6 +67,8 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
        { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
        { USB_DEVICE(0x10C4, 0x0F91) }, /* Vstabi */
+       { USB_DEVICE(0x10C4, 0x1101) }, /* Arkham Technology DS101 Bus Monitor */
+       { USB_DEVICE(0x10C4, 0x1601) }, /* Arkham Technology DS101 Adapter */
        { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */
        { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
        { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
@@ -78,6 +80,7 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
        { USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */
        { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
+       { USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */
        { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
        { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
        { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
@@ -94,7 +97,9 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */
        { USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */
        { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
+       { USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */
        { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */
+       { USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */
        { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
        { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
index 9734085fd2fee19f99051320db97ae22d867dc1e..59adfe123110b5e3c631f2ffa111d5b3c56680a7 100644 (file)
@@ -1228,8 +1228,8 @@ static void cypress_read_int_callback(struct urb *urb)
                /* precursor to disconnect so just go away */
                return;
        case -EPIPE:
-               usb_clear_halt(port->serial->dev, 0x81);
-               break;
+               /* Can't call usb_clear_halt while in_interrupt */
+               /* FALLS THROUGH */
        default:
                /* something ugly is going on... */
                dev_err(&urb->dev->dev,
index 3dc3768ca71ca0afb4a2a8f19541b3b345787b72..8fec5d4455c94334eaa12ab8c80c3f47566fd84b 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
@@ -107,6 +108,7 @@ struct ftdi_sio_quirk {
 
 static int   ftdi_jtag_probe(struct usb_serial *serial);
 static int   ftdi_mtxorb_hack_setup(struct usb_serial *serial);
+static int   ftdi_NDI_device_setup(struct usb_serial *serial);
 static void  ftdi_USB_UIRT_setup(struct ftdi_private *priv);
 static void  ftdi_HE_TIRA1_setup(struct ftdi_private *priv);
 
@@ -118,6 +120,10 @@ static struct ftdi_sio_quirk ftdi_mtxorb_hack_quirk = {
        .probe  = ftdi_mtxorb_hack_setup,
 };
 
+static struct ftdi_sio_quirk ftdi_NDI_device_quirk = {
+       .probe  = ftdi_NDI_device_setup,
+};
+
 static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
        .port_probe = ftdi_USB_UIRT_setup,
 };
@@ -191,6 +197,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) },
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) },
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) },
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) },
@@ -579,6 +586,9 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CCSMACHX_2_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CCSLOAD_N_GO_3_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CCSICDU64_4_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CCSPRIME8_5_PID) },
        { USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) },
        { USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) },
        { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) },
@@ -644,6 +654,16 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) },
        { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
+       { USB_DEVICE(FTDI_VID, FTDI_NDI_SPECTRA_SCU_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
+       { USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_2_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
+       { USB_DEVICE(FTDI_VID, FTDI_NDI_FUTURE_3_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
+       { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
        { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) },
@@ -660,6 +680,8 @@ static struct usb_device_id id_table_combined [] = {
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(FTDI_VID, LMI_LM3S_EVAL_BOARD_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+       { USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
        { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
        { USB_DEVICE(PAPOUCH_VID, PAPOUCH_QUIDO4x4_PID) },
@@ -667,7 +689,6 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_DOMINTELL_DUSB_PID) },
        { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) },
        { USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) },
-       { USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID) },
        { USB_DEVICE(ATMEL_VID, STK541_PID) },
        { USB_DEVICE(DE_VID, STB_PID) },
        { USB_DEVICE(DE_VID, WHT_PID) },
@@ -677,6 +698,10 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },
+       { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) },
+       { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
+       { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { },                                    /* Optional parameter entry */
        { }                                     /* Terminating entry */
 };
@@ -1023,6 +1048,16 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
        case FT2232C: /* FT2232C chip */
        case FT232RL:
                if (baud <= 3000000) {
+                       __u16 product_id = le16_to_cpu(
+                               port->serial->dev->descriptor.idProduct);
+                       if (((FTDI_NDI_HUC_PID == product_id) ||
+                            (FTDI_NDI_SPECTRA_SCU_PID == product_id) ||
+                            (FTDI_NDI_FUTURE_2_PID == product_id) ||
+                            (FTDI_NDI_FUTURE_3_PID == product_id) ||
+                            (FTDI_NDI_AURORA_SCU_PID == product_id)) &&
+                           (baud == 19200)) {
+                               baud = 1200000;
+                       }
                        div_value = ftdi_232bm_baud_to_divisor(baud);
                } else {
                        dbg("%s - Baud rate too high!", __func__);
@@ -1553,6 +1588,39 @@ static void ftdi_HE_TIRA1_setup(struct ftdi_private *priv)
        priv->force_rtscts = 1;
 } /* ftdi_HE_TIRA1_setup */
 
+/*
+ * Module parameter to control latency timer for NDI FTDI-based USB devices.
+ * If this value is not set in modprobe.conf.local its value will be set to 1ms.
+ */
+static int ndi_latency_timer = 1;
+
+/* Setup for the NDI FTDI-based USB devices, which requires hardwired
+ * baudrate (19200 gets mapped to 1200000).
+ *
+ * Called from usbserial:serial_probe.
+ */
+static int ftdi_NDI_device_setup(struct usb_serial *serial)
+{
+       struct usb_device *udev = serial->dev;
+       int latency = ndi_latency_timer;
+       int rv = 0;
+       char buf[1];
+
+       if (latency == 0)
+               latency = 1;
+       if (latency > 99)
+               latency = 99;
+
+       dbg("%s setting NDI device latency to %d", __func__, latency);
+       dev_info(&udev->dev, "NDI device with a latency value of %d", latency);
+
+       rv = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                               FTDI_SIO_SET_LATENCY_TIMER_REQUEST,
+                               FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE,
+                               latency, 0, buf, 0, WDR_TIMEOUT);
+       return 0;
+}
+
 /*
  * First port on JTAG adaptors such as Olimex arm-usb-ocd or the FIC/OpenMoko
  * Neo1973 Debug Board is reserved for JTAG interface and can be accessed from
@@ -2121,7 +2189,7 @@ static void ftdi_process_read(struct work_struct *work)
                                /* Note that the error flag is duplicated for
                                   every character received since we don't know
                                   which character it applied to */
-                               if (!usb_serial_handle_sysrq_char(port,
+                               if (!usb_serial_handle_sysrq_char(tty, port,
                                                data[packet_offset + i]))
                                        tty_insert_flip_char(tty,
                                                data[packet_offset + i],
@@ -2622,3 +2690,5 @@ MODULE_PARM_DESC(vendor, "User specified vendor ID (default="
 module_param(product, ushort, 0);
 MODULE_PARM_DESC(product, "User specified product ID");
 
+module_param(ndi_latency_timer, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ndi_latency_timer, "NDI device latency timer override");
index f1d440a728a376770617ad7776a52eba590cc282..8c92b88166aec7a50be1f14aba009b802d518193 100644 (file)
  *
  * Armin Laeuger originally sent the PID for the UM 100 module.
  */
+#define FTDI_R2000KU_TRUE_RNG  0xFB80  /* R2000KU TRUE RNG */
 #define FTDI_ELV_UR100_PID     0xFB58  /* USB-RS232-Umsetzer (UR 100) */
 #define FTDI_ELV_UM100_PID     0xFB5A  /* USB-Modul UM 100 */
 #define FTDI_ELV_UO100_PID     0xFB5B  /* USB-Modul UO 100 */
 #define FTDI_CCSICDU20_0_PID    0xF9D0
 #define FTDI_CCSICDU40_1_PID    0xF9D1
 #define FTDI_CCSMACHX_2_PID     0xF9D2
+#define FTDI_CCSLOAD_N_GO_3_PID 0xF9D3
+#define FTDI_CCSICDU64_4_PID    0xF9D4
+#define FTDI_CCSPRIME8_5_PID    0xF9D5
 
 /* Inside Accesso contactless reader (http://www.insidefr.com) */
 #define INSIDE_ACCESSO         0xFAD0
 /* Pyramid Computer GmbH */
 #define FTDI_PYRAMID_PID       0xE6C8  /* Pyramid Appliance Display */
 
+/*
+ * NDI (www.ndigital.com) product ids
+ */
+#define FTDI_NDI_HUC_PID               0xDA70  /* NDI Host USB Converter */
+#define FTDI_NDI_SPECTRA_SCU_PID       0xDA71  /* NDI Spectra SCU */
+#define FTDI_NDI_FUTURE_2_PID          0xDA72  /* NDI future device #2 */
+#define FTDI_NDI_FUTURE_3_PID          0xDA73  /* NDI future device #3 */
+#define FTDI_NDI_AURORA_SCU_PID                0xDA74  /* NDI Aurora SCU */
+
 /*
  * Posiflex inc retail equipment (http://www.posiflex.com.tw)
  */
 #define TML_VID                        0x1B91  /* Vendor ID */
 #define TML_USB_SERIAL_PID     0x0064  /* USB - Serial Converter */
 
-/* NDI Polaris System */
-#define FTDI_NDI_HUC_PID        0xDA70
-
 /* Propox devices */
 #define FTDI_PROPOX_JTAGCABLEII_PID    0xD738
 
 #define MARVELL_VID            0x9e88
 #define MARVELL_SHEEVAPLUG_PID 0x9e8f
 
+#define FTDI_TURTELIZER_PID    0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */
+
+/*
+ * GN Otometrics (http://www.otometrics.com)
+ * Submitted by Ville Sundberg.
+ */
+#define GN_OTOMETRICS_VID      0x0c33  /* Vendor ID */
+#define AURICAL_USB_PID                0x0010  /* Aurical USB Audiometer */
+
+/*
+ * Bayer Ascensia Contour blood glucose meter USB-converter cable.
+ * http://winglucofacts.com/cables/
+ */
+#define BAYER_VID                      0x1A79
+#define BAYER_CONTOUR_CABLE_PID        0x6001
+
+/*
+ * Marvell OpenRD Base, Client
+ * http://www.open-rd.org
+ * OpenRD Base, Client use VID 0x0403
+ */
+#define MARVELL_OPENRD_PID     0x9e90
+
 /*
  *   BmRequestType:  1100 0000b
  *   bRequest:       FTDI_E2_READ
index 932d6241b787d2c399bae70f70bec85e4c979d71..ce57f6a32bdfb4cc7a5e30f78c1e8eca21a9364a 100644 (file)
@@ -424,10 +424,17 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port)
        if (!tty)
                goto done;
 
-       /* Push data to tty */
-       for (i = 0; i < urb->actual_length; i++, ch++) {
-               if (!usb_serial_handle_sysrq_char(port, *ch))
-                       tty_insert_flip_char(tty, *ch, TTY_NORMAL);
+       /* The per character mucking around with sysrq path it too slow for
+          stuff like 3G modems, so shortcircuit it in the 99.9999999% of cases
+          where the USB serial is not a console anyway */
+       if (!port->console || !port->sysrq)
+               tty_insert_flip_string(tty, ch, urb->actual_length);
+       else {
+               /* Push data to tty */
+               for (i = 0; i < urb->actual_length; i++, ch++) {
+                       if (!usb_serial_handle_sysrq_char(tty, port, *ch))
+                               tty_insert_flip_char(tty, *ch, TTY_NORMAL);
+               }
        }
        tty_flip_buffer_push(tty);
        tty_kref_put(tty);
@@ -527,11 +534,12 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
        }
 }
 
-int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
+int usb_serial_handle_sysrq_char(struct tty_struct *tty,
+                       struct usb_serial_port *port, unsigned int ch)
 {
        if (port->sysrq && port->console) {
                if (ch && time_before(jiffies, port->sysrq)) {
-                       handle_sysrq(ch, tty_port_tty_get(&port->port));
+                       handle_sysrq(ch, tty);
                        port->sysrq = 0;
                        return 1;
                }
index bfc5ce000ef92e8d664407dfd62dbf0ba4592832..ccd4dd340d2cff34ed7cedcd9c108a8be5e856f6 100644 (file)
@@ -521,7 +521,7 @@ static int mos7720_chars_in_buffer(struct tty_struct *tty)
        mos7720_port = usb_get_serial_port_data(port);
        if (mos7720_port == NULL) {
                dbg("%s:leaving ...........", __func__);
-               return -ENODEV;
+               return 0;
        }
 
        for (i = 0; i < NUM_URBS; ++i) {
index c40f95c1951cf0cf17e8fedc4e8e9f4782324c67..270009afdf77043f2e60034b8d29182dad053edf 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
 #define BANDB_DEVICE_ID_USOPTL4_4       0xAC44
 #define BANDB_DEVICE_ID_USOPTL4_2       0xAC42
 
-/* This driver also supports the ATEN UC2324 device since it is mos7840 based
- *  - if I knew the device id it would also support the ATEN UC2322 */
+/* This driver also supports
+ * ATEN UC2324 device using Moschip MCS7840
+ * ATEN UC2322 device using Moschip MCS7820
+ */
 #define USB_VENDOR_ID_ATENINTL         0x0557
 #define ATENINTL_DEVICE_ID_UC2324      0x2011
+#define ATENINTL_DEVICE_ID_UC2322      0x7820
 
 /* Interrupt Routine Defines    */
 
@@ -176,6 +180,7 @@ static struct usb_device_id moschip_port_id_table[] = {
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
        {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
+       {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
        {}                      /* terminating entry */
 };
 
@@ -185,6 +190,7 @@ static __devinitdata struct usb_device_id moschip_id_table_combined[] = {
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)},
        {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)},
        {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)},
+       {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)},
        {}                      /* terminating entry */
 };
 
index 575816e6ba371fb4ef5fbeeba3668e559b86bfe2..c784ddbe7b614cf13b4e57ab1fbd6ad2efdf3121 100644 (file)
@@ -66,8 +66,10 @@ static int  option_tiocmget(struct tty_struct *tty, struct file *file);
 static int  option_tiocmset(struct tty_struct *tty, struct file *file,
                                unsigned int set, unsigned int clear);
 static int  option_send_setup(struct usb_serial_port *port);
+#ifdef CONFIG_PM
 static int  option_suspend(struct usb_serial *serial, pm_message_t message);
 static int  option_resume(struct usb_serial *serial);
+#endif
 
 /* Vendor and product IDs */
 #define OPTION_VENDOR_ID                       0x0AF0
@@ -205,7 +207,9 @@ static int  option_resume(struct usb_serial *serial);
 #define NOVATELWIRELESS_PRODUCT_MC727          0x4100
 #define NOVATELWIRELESS_PRODUCT_MC950D         0x4400
 #define NOVATELWIRELESS_PRODUCT_U727           0x5010
+#define NOVATELWIRELESS_PRODUCT_MC727_NEW      0x5100
 #define NOVATELWIRELESS_PRODUCT_MC760          0x6000
+#define NOVATELWIRELESS_PRODUCT_OVMC760                0x6002
 
 /* FUTURE NOVATEL PRODUCTS */
 #define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED 0X6001
@@ -258,11 +262,6 @@ static int  option_resume(struct usb_serial *serial);
 #define AXESSTEL_VENDOR_ID                     0x1726
 #define AXESSTEL_PRODUCT_MV110H                        0x1000
 
-#define ONDA_VENDOR_ID                         0x19d2
-#define ONDA_PRODUCT_MSA501HS                  0x0001
-#define ONDA_PRODUCT_ET502HS                   0x0002
-#define ONDA_PRODUCT_MT503HS                   0x2000
-
 #define BANDRICH_VENDOR_ID                     0x1A8D
 #define BANDRICH_PRODUCT_C100_1                        0x1002
 #define BANDRICH_PRODUCT_C100_2                        0x1003
@@ -300,6 +299,7 @@ static int  option_resume(struct usb_serial *serial);
 #define ZTE_PRODUCT_MF628                      0x0015
 #define ZTE_PRODUCT_MF626                      0x0031
 #define ZTE_PRODUCT_CDMA_TECH                  0xfffe
+#define ZTE_PRODUCT_AC8710                     0xfff1
 
 #define BENQ_VENDOR_ID                         0x04a5
 #define BENQ_PRODUCT_H10                       0x4068
@@ -307,11 +307,25 @@ static int  option_resume(struct usb_serial *serial);
 #define DLINK_VENDOR_ID                                0x1186
 #define DLINK_PRODUCT_DWM_652                  0x3e04
 
+#define QISDA_VENDOR_ID                                0x1da5
+#define QISDA_PRODUCT_H21_4512                 0x4512
+#define QISDA_PRODUCT_H21_4523                 0x4523
+#define QISDA_PRODUCT_H20_4515                 0x4515
+#define QISDA_PRODUCT_H20_4519                 0x4519
+
 
 /* TOSHIBA PRODUCTS */
 #define TOSHIBA_VENDOR_ID                      0x0930
 #define TOSHIBA_PRODUCT_HSDPA_MINICARD         0x1302
 
+#define ALINK_VENDOR_ID                                0x1e0e
+#define ALINK_PRODUCT_3GU                      0x9200
+
+/* ALCATEL PRODUCTS */
+#define ALCATEL_VENDOR_ID                      0x1bbb
+#define ALCATEL_PRODUCT_X060S                  0x0000
+
+
 static struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -428,8 +442,10 @@ static struct usb_device_id option_ids[] = {
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727_NEW) }, /* Novatel MC727/U727/USB727 refresh */
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC760) }, /* Novatel MC760/U760/USB760 */
+       { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_OVMC760) }, /* Novatel Ovation MC760 */
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, /* Novatel HSPA Embedded product */
@@ -463,42 +479,6 @@ static struct usb_device_id option_ids[] = {
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
        { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
-       { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) },
-       { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0003) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0004) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0005) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0006) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0007) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0008) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0009) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x000a) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x000b) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x000c) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x000d) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x000e) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x000f) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0010) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0011) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0012) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0013) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0014) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0015) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0016) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0017) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0018) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0019) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0020) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0021) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0022) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0023) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0024) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0025) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0026) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0027) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0028) },
-       { USB_DEVICE(ONDA_VENDOR_ID, 0x0029) },
-       { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MT503HS) },
        { USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) },
        { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
        { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
@@ -523,14 +503,85 @@ static struct usb_device_id option_ids[] = {
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
        { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
-       { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622) },
-       { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) },
-       { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
-       { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0003, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0004, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0005, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0006, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0007, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0008, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0009, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000a, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000b, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000c, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000d, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000e, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000f, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0010, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0011, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0018, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0019, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0020, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0021, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0022, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0023, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0037, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0039, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0042, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0043, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0048, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0049, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0064, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0082, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
        { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
        { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
-       { USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */
+       { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) },
+       { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },
+       { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) },
+       { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) },
        { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
+       { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
+       { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
@@ -539,8 +590,10 @@ static struct usb_driver option_driver = {
        .name       = "option",
        .probe      = usb_serial_probe,
        .disconnect = usb_serial_disconnect,
+#ifdef CONFIG_PM
        .suspend    = usb_serial_suspend,
        .resume     = usb_serial_resume,
+#endif
        .id_table   = option_ids,
        .no_dynamic_id =        1,
 };
@@ -572,8 +625,10 @@ static struct usb_serial_driver option_1port_device = {
        .disconnect        = option_disconnect,
        .release           = option_release,
        .read_int_callback = option_instat_callback,
+#ifdef CONFIG_PM
        .suspend           = option_suspend,
        .resume            = option_resume,
+#endif
 };
 
 static int debug;
@@ -732,7 +787,6 @@ static int option_write(struct tty_struct *tty, struct usb_serial_port *port,
                memcpy(this_urb->transfer_buffer, buf, todo);
                this_urb->transfer_buffer_length = todo;
 
-               this_urb->dev = port->serial->dev;
                err = usb_submit_urb(this_urb, GFP_ATOMIC);
                if (err) {
                        dbg("usb_submit_urb %p (write bulk) failed "
@@ -816,7 +870,6 @@ static void option_instat_callback(struct urb *urb)
        int status = urb->status;
        struct usb_serial_port *port =  urb->context;
        struct option_port_private *portdata = usb_get_serial_port_data(port);
-       struct usb_serial *serial = port->serial;
 
        dbg("%s", __func__);
        dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata);
@@ -860,7 +913,6 @@ static void option_instat_callback(struct urb *urb)
 
        /* Resubmit urb so we continue receiving IRQ data */
        if (status != -ESHUTDOWN && status != -ENOENT) {
-               urb->dev = serial->dev;
                err = usb_submit_urb(urb, GFP_ATOMIC);
                if (err)
                        dbg("%s: resubmit intr urb failed. (%d)",
@@ -913,7 +965,6 @@ static int option_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp)
 {
        struct option_port_private *portdata;
-       struct usb_serial *serial = port->serial;
        int i, err;
        struct urb *urb;
 
@@ -921,23 +972,11 @@ static int option_open(struct tty_struct *tty,
 
        dbg("%s", __func__);
 
-       /* Reset low level data toggle and start reading from endpoints */
+       /* Start reading from the IN endpoint */
        for (i = 0; i < N_IN_URB; i++) {
                urb = portdata->in_urbs[i];
                if (!urb)
                        continue;
-               if (urb->dev != serial->dev) {
-                       dbg("%s: dev %p != %p", __func__,
-                               urb->dev, serial->dev);
-                       continue;
-               }
-
-               /*
-                * make sure endpoint data toggle is synchronized with the
-                * device
-                */
-               usb_clear_halt(urb->dev, urb->pipe);
-
                err = usb_submit_urb(urb, GFP_KERNEL);
                if (err) {
                        dbg("%s: submit urb %d failed (%d) %d",
@@ -946,16 +985,6 @@ static int option_open(struct tty_struct *tty,
                }
        }
 
-       /* Reset low level data toggle on out endpoints */
-       for (i = 0; i < N_OUT_URB; i++) {
-               urb = portdata->out_urbs[i];
-               if (!urb)
-                       continue;
-               urb->dev = serial->dev;
-               /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-                               usb_pipeout(urb->pipe), 0); */
-       }
-
        option_send_setup(port);
 
        return 0;
@@ -1195,6 +1224,7 @@ static void option_release(struct usb_serial *serial)
        }
 }
 
+#ifdef CONFIG_PM
 static int option_suspend(struct usb_serial *serial, pm_message_t message)
 {
        dbg("%s entered", __func__);
@@ -1218,7 +1248,6 @@ static int option_resume(struct usb_serial *serial)
                        dbg("%s: No interrupt URB for port %d\n", __func__, i);
                        continue;
                }
-               port->interrupt_in_urb->dev = serial->dev;
                err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
                dbg("Submitted interrupt URB for port %d (result %d)", i, err);
                if (err < 0) {
@@ -1254,6 +1283,7 @@ static int option_resume(struct usb_serial *serial)
        }
        return 0;
 }
+#endif
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
index ec6c132a25b56f0a63ffa3b0b3a702594d1097b3..3e86815b270534cfd3633820d5d142edd71df4b6 100644 (file)
@@ -94,6 +94,8 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
        { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) },
        { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) },
+       { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },
+       { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
        { }                                     /* Terminating entry */
 };
 
@@ -971,18 +973,46 @@ exit:
                        __func__, retval);
 }
 
+static void pl2303_push_data(struct tty_struct *tty,
+               struct usb_serial_port *port, struct urb *urb,
+               u8 line_status)
+{
+       unsigned char *data = urb->transfer_buffer;
+       /* get tty_flag from status */
+       char tty_flag = TTY_NORMAL;
+       /* break takes precedence over parity, */
+       /* which takes precedence over framing errors */
+       if (line_status & UART_BREAK_ERROR)
+               tty_flag = TTY_BREAK;
+       else if (line_status & UART_PARITY_ERROR)
+               tty_flag = TTY_PARITY;
+       else if (line_status & UART_FRAME_ERROR)
+               tty_flag = TTY_FRAME;
+       dbg("%s - tty_flag = %d", __func__, tty_flag);
+
+       tty_buffer_request_room(tty, urb->actual_length + 1);
+       /* overrun is special, not associated with a char */
+       if (line_status & UART_OVERRUN_ERROR)
+               tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+       if (port->console && port->sysrq) {
+               int i;
+               for (i = 0; i < urb->actual_length; ++i)
+                       if (!usb_serial_handle_sysrq_char(tty, port, data[i]))
+                               tty_insert_flip_char(tty, data[i], tty_flag);
+       } else
+               tty_insert_flip_string(tty, data, urb->actual_length);
+       tty_flip_buffer_push(tty);
+}
+
 static void pl2303_read_bulk_callback(struct urb *urb)
 {
        struct usb_serial_port *port =  urb->context;
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        struct tty_struct *tty;
-       unsigned char *data = urb->transfer_buffer;
        unsigned long flags;
-       int i;
        int result;
        int status = urb->status;
        u8 line_status;
-       char tty_flag;
 
        dbg("%s - port %d", __func__, port->number);
 
@@ -1010,10 +1040,7 @@ static void pl2303_read_bulk_callback(struct urb *urb)
        }
 
        usb_serial_debug_data(debug, &port->dev, __func__,
-                             urb->actual_length, data);
-
-       /* get tty_flag from status */
-       tty_flag = TTY_NORMAL;
+                             urb->actual_length, urb->transfer_buffer);
 
        spin_lock_irqsave(&priv->lock, flags);
        line_status = priv->line_status;
@@ -1021,26 +1048,9 @@ static void pl2303_read_bulk_callback(struct urb *urb)
        spin_unlock_irqrestore(&priv->lock, flags);
        wake_up_interruptible(&priv->delta_msr_wait);
 
-       /* break takes precedence over parity, */
-       /* which takes precedence over framing errors */
-       if (line_status & UART_BREAK_ERROR)
-               tty_flag = TTY_BREAK;
-       else if (line_status & UART_PARITY_ERROR)
-               tty_flag = TTY_PARITY;
-       else if (line_status & UART_FRAME_ERROR)
-               tty_flag = TTY_FRAME;
-       dbg("%s - tty_flag = %d", __func__, tty_flag);
-
        tty = tty_port_tty_get(&port->port);
        if (tty && urb->actual_length) {
-               tty_buffer_request_room(tty, urb->actual_length + 1);
-               /* overrun is special, not associated with a char */
-               if (line_status & UART_OVERRUN_ERROR)
-                       tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-               for (i = 0; i < urb->actual_length; ++i)
-                       if (!usb_serial_handle_sysrq_char(port, data[i]))
-                               tty_insert_flip_char(tty, data[i], tty_flag);
-               tty_flip_buffer_push(tty);
+               pl2303_push_data(tty, port, urb, line_status);
        }
        tty_kref_put(tty);
        /* Schedule the next read _if_ we are still open */
index 1d7a22e3a9fd1daa5df3c239185670763e7a5563..ee9505e1dd9273f17f5cede9f0e3418ec820b13f 100644 (file)
 /* Hewlett-Packard LD220-HP POS Pole Display */
 #define HP_VENDOR_ID           0x03f0
 #define HP_LD220_PRODUCT_ID    0x3524
+
+/* Cressi Edy (diving computer) PC interface */
+#define CRESSI_VENDOR_ID       0x04b8
+#define CRESSI_EDY_PRODUCT_ID  0x0521
+
+/* Sony, USB data cable for CMD-Jxx mobile phones */
+#define SONY_VENDOR_ID         0x054c
+#define SONY_QN3USB_PRODUCT_ID 0x0437
index 032f7aeb40a42b17b71b1f4c2ae7b3d1ff221640..f48d05e0acc135e89a5e4a7518f3d1364b07e35d 100644 (file)
@@ -181,35 +181,50 @@ static const struct sierra_iface_info direct_ip_interface_blacklist = {
 };
 
 static struct usb_device_id id_table [] = {
+       { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */
+       { USB_DEVICE(0x03F0, 0x1B1D) }, /* HP ev2200 a.k.a MC5720 */
+       { USB_DEVICE(0x03F0, 0x1E1D) }, /* HP hs2300 a.k.a MC8775 */
+
        { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
        { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
        { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
-       { USB_DEVICE(0x03f0, 0x1b1d) }, /* HP ev2200 a.k.a MC5720 */
        { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */
-       { USB_DEVICE(0x1199, 0x0024) }, /* Sierra Wireless MC5727 */
        { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */
+       { USB_DEVICE(0x1199, 0x0022) }, /* Sierra Wireless EM5725 */
+       { USB_DEVICE(0x1199, 0x0024) }, /* Sierra Wireless MC5727 */
+       { USB_DEVICE(0x1199, 0x0224) }, /* Sierra Wireless MC5727 */
        { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
        { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
+       { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
        { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */
-        /* Sierra Wireless C597 */
+       /* Sierra Wireless C597 */
        { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) },
-        /* Sierra Wireless Device */
+       /* Sierra Wireless T598 */
        { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) },
-       { USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless Device */
-       { USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless Device */
-       { USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless Device */
+       { USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless T11 */
+       { USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless AC402 */
+       { USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless MC5728 */
+       { USB_DEVICE(0x1199, 0x0029) }, /* Sierra Wireless Device */
 
        { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
-       { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
        { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
+       { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
+       { USB_DEVICE(0x1199, 0x6805) }, /* Sierra Wireless MC8765 */
+       { USB_DEVICE(0x1199, 0x6808) }, /* Sierra Wireless MC8755 */
+       { USB_DEVICE(0x1199, 0x6809) }, /* Sierra Wireless MC8765 */
        { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */
-       { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Lenovo) */
+       { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 */
        { USB_DEVICE(0x1199, 0x6815) }, /* Sierra Wireless MC8775 */
-       { USB_DEVICE(0x03f0, 0x1e1d) }, /* HP hs2300 a.k.a MC8775 */
+       { USB_DEVICE(0x1199, 0x6816) }, /* Sierra Wireless MC8775 */
        { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */
        { USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */
+       { USB_DEVICE(0x1199, 0x6822) }, /* Sierra Wireless AirCard 875E */
        { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780 */
        { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */
+       { USB_DEVICE(0x1199, 0x6834) }, /* Sierra Wireless MC8780 */
+       { USB_DEVICE(0x1199, 0x6835) }, /* Sierra Wireless MC8781 */
+       { USB_DEVICE(0x1199, 0x6838) }, /* Sierra Wireless MC8780 */
+       { USB_DEVICE(0x1199, 0x6839) }, /* Sierra Wireless MC8781 */
        { USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */
        { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */
        /* Sierra Wireless MC8790, MC8791, MC8792 Composite */
@@ -227,16 +242,13 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x1199, 0x685A) }, /* Sierra Wireless AirCard 885 E */
        /* Sierra Wireless C885 */
        { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)},
-       /* Sierra Wireless Device */
+       /* Sierra Wireless C888, Air Card 501, USB 303, USB 304 */
        { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)},
-       /* Sierra Wireless Device */
+       /* Sierra Wireless C22/C33 */
        { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6891, 0xFF, 0xFF, 0xFF)},
-       /* Sierra Wireless Device */
+       /* Sierra Wireless HSPA Non-Composite Device */
        { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
-
-       { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
-       { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */
-
+       { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */
        { USB_DEVICE(0x1199, 0x68A3),   /* Sierra Wireless Direct IP modems */
          .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
        },
@@ -814,7 +826,7 @@ static int sierra_startup(struct usb_serial *serial)
        return 0;
 }
 
-static void sierra_disconnect(struct usb_serial *serial)
+static void sierra_release(struct usb_serial *serial)
 {
        int i;
        struct usb_serial_port *port;
@@ -830,7 +842,6 @@ static void sierra_disconnect(struct usb_serial *serial)
                if (!portdata)
                        continue;
                kfree(portdata);
-               usb_set_serial_port_data(port, NULL);
        }
 }
 
@@ -853,7 +864,7 @@ static struct usb_serial_driver sierra_device = {
        .tiocmget          = sierra_tiocmget,
        .tiocmset          = sierra_tiocmset,
        .attach            = sierra_startup,
-       .disconnect        = sierra_disconnect,
+       .release           = sierra_release,
        .read_int_callback = sierra_instat_callback,
 };
 
index 991d8232e3765c39de562ec8e09181d0e8d4c547..3bc609fe2242a574643fe84353cf9de665fc25e3 100644 (file)
@@ -191,7 +191,6 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
        { USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },
        { USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },
        { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
-       { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) },
 };
 
 static struct usb_device_id ti_id_table_combined[14+2*TI_EXTRA_VID_PID_COUNT+1] = {
@@ -728,7 +727,7 @@ static int ti_write_room(struct tty_struct *tty)
        dbg("%s - port %d", __func__, port->number);
 
        if (tport == NULL)
-               return -ENODEV;
+               return 0;
 
        spin_lock_irqsave(&tport->tp_lock, flags);
        room = ti_buf_space_avail(tport->tp_write_buf);
@@ -749,7 +748,7 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
        dbg("%s - port %d", __func__, port->number);
 
        if (tport == NULL)
-               return -ENODEV;
+               return 0;
 
        spin_lock_irqsave(&tport->tp_lock, flags);
        chars = ti_buf_data_avail(tport->tp_write_buf);
@@ -1658,7 +1657,7 @@ static int ti_do_download(struct usb_device *dev, int pipe,
        u8 cs = 0;
        int done;
        struct ti_firmware_header *header;
-       int status;
+       int status = 0;
        int len;
 
        for (pos = sizeof(struct ti_firmware_header); pos < size; pos++)
index d595aa5586a733003532e6f0a7a95e051e3ce659..99188c92068bb4492416ff99b7655086721c9034 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
@@ -31,6 +32,7 @@
 #include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/uaccess.h>
+#include <linux/serial.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include "pl2303.h"
@@ -183,6 +185,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
        struct usb_serial_port *port;
        unsigned int portNumber;
        int retval = 0;
+       int first = 0;
 
        dbg("%s", __func__);
 
@@ -220,8 +223,9 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
        tty->driver_data = port;
        tty_port_tty_set(&port->port, tty);
 
-       if (port->port.count == 1) {
-
+       /* If the console is attached, the device is already open */
+       if (port->port.count == 1 && !port->console) {
+               first = 1;
                /* lock this module before we call it
                 * this may fail, which means we must bail out,
                 * safe because we are called with BKL held */
@@ -244,13 +248,21 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
                if (retval)
                        goto bailout_interface_put;
                mutex_unlock(&serial->disc_mutex);
+               set_bit(ASYNCB_INITIALIZED, &port->port.flags);
        }
        mutex_unlock(&port->mutex);
        /* Now do the correct tty layer semantics */
        retval = tty_port_block_til_ready(&port->port, tty, filp);
-       if (retval == 0)
+       if (retval == 0) {
+               if (!first)
+                       usb_serial_put(serial);
                return 0;
-
+       }
+       mutex_lock(&port->mutex);
+       if (first == 0)
+               goto bailout_mutex_unlock;
+       /* Undo the initial port actions */
+       mutex_lock(&serial->disc_mutex);
 bailout_interface_put:
        usb_autopm_put_interface(serial->interface);
 bailout_module_put:
@@ -333,8 +345,27 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
 {
        struct usb_serial_port *port = tty->driver_data;
 
+       if (!port)
+               return;
+
        dbg("%s - port %d", __func__, port->number);
 
+       /* FIXME:
+          This leaves a very narrow race. Really we should do the
+          serial_do_free() on tty->shutdown(), but tty->shutdown can
+          be called from IRQ context and serial_do_free can sleep.
+
+          The right fix is probably to make the tty free (which is rare)
+          and thus tty->shutdown() occur via a work queue and simplify all
+          the drivers that use it.
+       */
+       if (tty_hung_up_p(filp)) {
+               /* serial_hangup already called serial_down at this point.
+                  Another user may have already reopened the port but
+                  serial_do_free is refcounted */
+               serial_do_free(port);
+               return;
+       }
 
        if (tty_port_close_start(&port->port, tty, filp) == 0)
                return;
@@ -350,7 +381,8 @@ static void serial_hangup(struct tty_struct *tty)
        struct usb_serial_port *port = tty->driver_data;
        serial_do_down(port);
        tty_port_hangup(&port->port);
-       serial_do_free(port);
+       /* We must not free port yet - the USB serial layer depends on it's
+          continued existence */
 }
 
 static int serial_write(struct tty_struct *tty, const unsigned char *buf,
@@ -389,7 +421,6 @@ static int serial_chars_in_buffer(struct tty_struct *tty)
        struct usb_serial_port *port = tty->driver_data;
        dbg("%s = port %d", __func__, port->number);
 
-       WARN_ON(!port->port.count);
        /* if the device was unplugged then any remaining characters
           fell out of the connector ;) */
        if (port->serial->disconnected)
index d41cc0a970f79a147660da239bdc014612396354..773a5cd38c5aa7773f5b7f1837351a8945b3f084 100644 (file)
@@ -118,6 +118,9 @@ static int option_inquiry(struct us_data *us)
 
        result = memcmp(buffer+8, "Option", 6);
 
+       if (result != 0)
+               result = memcmp(buffer+8, "ZCOPTION", 8);
+
        /* Read the CSW */
        usb_stor_bulk_transfer_buf(us,
                        us->recv_bulk_pipe,
index fcb320217218109d60147b5bb5dc297f65b96da0..e20dc525d17763642f65a07835a4a2ca462f1a4a 100644 (file)
@@ -961,7 +961,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
                                 US_BULK_GET_MAX_LUN, 
                                 USB_DIR_IN | USB_TYPE_CLASS | 
                                 USB_RECIP_INTERFACE,
-                                0, us->ifnum, us->iobuf, 1, HZ);
+                                0, us->ifnum, us->iobuf, 1, 10*HZ);
 
        US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 
                  result, us->iobuf[0]);
index 1b9c5dd0fb27b00904c1cb9357f0402c9e12a323..7477d411959f6ab30f73b1b4d03a4b9d880dd8a3 100644 (file)
@@ -838,6 +838,13 @@ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001,
                US_SC_DEVICE, US_PR_DEVICE, NULL,
                US_FL_FIX_CAPACITY ),
 
+/* Reported by Rogerio Brito <rbrito@ime.usp.br> */
+UNUSUAL_DEV( 0x067b, 0x2317, 0x0001, 0x001,
+               "Prolific Technology, Inc.",
+               "Mass Storage Device",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_NOT_LOCKABLE ),
+
 /* Reported by Richard -=[]=- <micro_flyer@hotmail.com> */
 /* Change to bcdDeviceMin (0x0100 to 0x0001) reported by
  * Thomas Bartosik <tbartdev@gmx-topmail.de> */
index d6d65ef85f541b3cdb49ad45bfaa0430c4cbeba4..3b54b39401781a7b42c076b66cad74eab0ff5259 100644 (file)
@@ -616,6 +616,8 @@ config FB_STI
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
+       select STI_CONSOLE
+       select VT
        default y
        ---help---
          STI refers to the HP "Standard Text Interface" which is a set of
@@ -1117,12 +1119,13 @@ config FB_CARILLO_RANCH
 
 config FB_INTEL
        tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && FB && PCI && X86 && AGP_INTEL
+       depends on EXPERIMENTAL && FB && PCI && X86 && AGP_INTEL && EMBEDDED
        select FB_MODE_HELPERS
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
        select FB_BOOT_VESA_SUPPORT if FB_INTEL = y
+       depends on !DRM_I915
        help
          This driver supports the on-board graphics built in to the Intel
           830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets.
index fb8163d181abbb5383535b37e1b85a26367d5432..a21efcd10b78792bd75132d19e72cbd56b55e2bf 100644 (file)
@@ -226,9 +226,10 @@ static int clcdfb_set_par(struct fb_info *info)
        clcdfb_enable(fb, regs.cntl);
 
 #ifdef DEBUG
-       printk(KERN_INFO "CLCD: Registers set to\n"
-              KERN_INFO "  %08x %08x %08x %08x\n"
-              KERN_INFO "  %08x %08x %08x %08x\n",
+       printk(KERN_INFO
+              "CLCD: Registers set to\n"
+              "  %08x %08x %08x %08x\n"
+              "  %08x %08x %08x %08x\n",
                readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1),
                readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3),
                readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS),
index 018850c116c646edbeadf5cc6e4fc828e3901eff..8cd279be74e5de975d1e3871f806673e67de3783 100644 (file)
@@ -2405,6 +2405,9 @@ static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
        return 0;
 }
 
+/* fbhw->encode_fix() must be called with fb_info->mm_lock held
+ * if it is called after the register_framebuffer() - not a case here
+ */
 static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
 {
        struct atafb_par par;
@@ -2414,7 +2417,8 @@ static int atafb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
        if (err)
                return err;
        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-       return fbhw->encode_fix(fix, &par);
+       err = fbhw->encode_fix(fix, &par);
+       return err;
 }
 
 static int atafb_get_var(struct fb_var_screeninfo *var, struct fb_info *info)
@@ -2743,7 +2747,9 @@ static int atafb_set_par(struct fb_info *info)
 
        /* Decode wanted screen parameters */
        fbhw->decode_var(&info->var, par);
+       mutex_lock(&info->mm_lock);
        fbhw->encode_fix(&info->fix, par);
+       mutex_unlock(&info->mm_lock);
 
        /* Set new videomode */
        ata_set_par(par);
index 5afd64482f5584fd7c03f0d6267875da6eb3f16f..da05f0801bb754221188d15ddcd070e85b796830 100644 (file)
@@ -261,6 +261,9 @@ static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
 /**
  *     atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory
  *     @sinfo: the frame buffer to allocate memory for
+ *     
+ *     This function is called only from the atmel_lcdfb_probe()
+ *     so no locking by fb_info->mm_lock around smem_len setting is needed.
  */
 static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
 {
index 7691e73823d398fd76d8cadfdea557cc8a66d605..1f39a62f899be953384320f9bb25da13427c4374 100644 (file)
@@ -187,6 +187,8 @@ struct atyfb_par {
        int mtrr_reg;
 #endif
        u32 mem_cntl;
+       struct crtc saved_crtc;
+       union aty_pll saved_pll;
 };
 
     /*
@@ -217,6 +219,7 @@ struct atyfb_par {
 #define M64F_XL_DLL            0x00080000
 #define M64F_MFB_FORCE_4       0x00100000
 #define M64F_HW_TRIPLE         0x00200000
+#define M64F_XL_MEM            0x00400000
     /*
      *  Register access
      */
index 1207c208a30b32f243a6ab4ec952d811d69fe248..63d3739d43a85bf0e6264a51562f01283bb486ab 100644 (file)
@@ -66,6 +66,8 @@
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <linux/backlight.h>
+#include <linux/reboot.h>
+#include <linux/dmi.h>
 
 #include <asm/io.h>
 #include <linux/uaccess.h>
@@ -249,8 +251,6 @@ static int aty_init(struct fb_info *info);
 static int store_video_par(char *videopar, unsigned char m64_num);
 #endif
 
-static struct crtc saved_crtc;
-static union aty_pll saved_pll;
 static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc);
 
 static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc);
@@ -261,6 +261,8 @@ static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info);
 static int read_aty_sense(const struct atyfb_par *par);
 #endif
 
+static DEFINE_MUTEX(reboot_lock);
+static struct fb_info *reboot_info;
 
     /*
      *  Interface used by the world
@@ -361,8 +363,8 @@ static unsigned long phys_guiregbase[FB_MAX] __devinitdata = { 0, };
 #define ATI_CHIP_264GTPRO  (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
 #define ATI_CHIP_264LTPRO  (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)
 
-#define ATI_CHIP_264XL     (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4)
-#define ATI_CHIP_MOBILITY  (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_MOBIL_BUS)
+#define ATI_CHIP_264XL     (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM)
+#define ATI_CHIP_MOBILITY  (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_XL_MEM | M64F_MOBIL_BUS)
 
 static struct {
        u16 pci_id;
@@ -539,6 +541,7 @@ static char ram_edo[] __devinitdata = "EDO";
 static char ram_sdram[] __devinitdata = "SDRAM (1:1)";
 static char ram_sgram[] __devinitdata = "SGRAM (1:1)";
 static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)";
+static char ram_wram[] __devinitdata = "WRAM";
 static char ram_off[] __devinitdata = "OFF";
 #endif /* CONFIG_FB_ATY_CT */
 
@@ -552,6 +555,10 @@ static char *aty_gx_ram[8] __devinitdata = {
 
 #ifdef CONFIG_FB_ATY_CT
 static char *aty_ct_ram[8] __devinitdata = {
+       ram_off, ram_dram, ram_edo, ram_edo,
+       ram_sdram, ram_sgram, ram_wram, ram_resv
+};
+static char *aty_xl_ram[8] __devinitdata = {
        ram_off, ram_dram, ram_edo, ram_edo,
        ram_sdram, ram_sgram, ram_sdram32, ram_resv
 };
@@ -760,6 +767,17 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc)
 #endif /* CONFIG_FB_ATY_GENERIC_LCD */
 }
 
+static u32 calc_line_length(struct atyfb_par *par, u32 vxres, u32 bpp)
+{
+       u32 line_length = vxres * bpp / 8;
+
+       if (par->ram_type == SGRAM ||
+           (!M64_HAS(XL_MEM) && par->ram_type == WRAM))
+               line_length = (line_length + 63) & ~63;
+
+       return line_length;
+}
+
 static int aty_var_to_crtc(const struct fb_info *info,
        const struct fb_var_screeninfo *var, struct crtc *crtc)
 {
@@ -769,13 +787,14 @@ static int aty_var_to_crtc(const struct fb_info *info,
        u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol;
        u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync;
        u32 pix_width, dp_pix_width, dp_chain_mask;
+       u32 line_length;
 
        /* input */
-       xres = var->xres;
+       xres = (var->xres + 7) & ~7;
        yres = var->yres;
-       vxres = var->xres_virtual;
+       vxres = (var->xres_virtual + 7) & ~7;
        vyres = var->yres_virtual;
-       xoffset = var->xoffset;
+       xoffset = (var->xoffset + 7) & ~7;
        yoffset = var->yoffset;
        bpp = var->bits_per_pixel;
        if (bpp == 16)
@@ -827,7 +846,9 @@ static int aty_var_to_crtc(const struct fb_info *info,
        } else
                FAIL("invalid bpp");
 
-       if (vxres * vyres * bpp / 8 > info->fix.smem_len)
+       line_length = calc_line_length(par, vxres, bpp);
+
+       if (vyres * line_length > info->fix.smem_len)
                FAIL("not enough video RAM");
 
        h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
@@ -969,7 +990,9 @@ static int aty_var_to_crtc(const struct fb_info *info,
        crtc->xoffset = xoffset;
        crtc->yoffset = yoffset;
        crtc->bpp = bpp;
-       crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
+       crtc->off_pitch =
+               ((yoffset * line_length + xoffset * bpp / 8) / 8) |
+               ((line_length / bpp) << 22);
        crtc->vline_crnt_vline = 0;
 
        crtc->h_tot_disp = h_total | (h_disp<<16);
@@ -1394,7 +1417,9 @@ static int atyfb_set_par(struct fb_info *info)
        }
        aty_st_8(DAC_MASK, 0xff, par);
 
-       info->fix.line_length = var->xres_virtual * var->bits_per_pixel/8;
+       info->fix.line_length = calc_line_length(par, var->xres_virtual,
+                                                var->bits_per_pixel);
+
        info->fix.visual = var->bits_per_pixel <= 8 ?
                FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
 
@@ -1505,10 +1530,12 @@ static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info)
 {
        u32 xoffset = info->var.xoffset;
        u32 yoffset = info->var.yoffset;
-       u32 vxres = par->crtc.vxres;
+       u32 line_length = info->fix.line_length;
        u32 bpp = info->var.bits_per_pixel;
 
-       par->crtc.off_pitch = ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19);
+       par->crtc.off_pitch =
+               ((yoffset * line_length + xoffset * bpp / 8) / 8) |
+               ((line_length / bpp) << 22);
 }
 
 
@@ -2201,7 +2228,7 @@ static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
        const int *refresh_tbl;
        int i, size;
 
-       if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) {
+       if (M64_HAS(XL_MEM)) {
                refresh_tbl = ragexl_tbl;
                size = ARRAY_SIZE(ragexl_tbl);
        } else {
@@ -2335,7 +2362,10 @@ static int __devinit aty_init(struct fb_info *info)
                par->pll_ops = &aty_pll_ct;
                par->bus_type = PCI;
                par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07);
-               ramname = aty_ct_ram[par->ram_type];
+               if (M64_HAS(XL_MEM))
+                       ramname = aty_xl_ram[par->ram_type];
+               else
+                       ramname = aty_ct_ram[par->ram_type];
                /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
                if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM)
                        par->pll_limits.mclk = 63;
@@ -2390,9 +2420,9 @@ static int __devinit aty_init(struct fb_info *info)
 #endif /* CONFIG_FB_ATY_CT */
 
        /* save previous video mode */
-       aty_get_crtc(par, &saved_crtc);
+       aty_get_crtc(par, &par->saved_crtc);
        if(par->pll_ops->get_pll)
-               par->pll_ops->get_pll(info, &saved_pll);
+               par->pll_ops->get_pll(info, &par->saved_pll);
 
        par->mem_cntl = aty_ld_le32(MEM_CNTL, par);
        gtb_memsize = M64_HAS(GTB_DSP);
@@ -2667,8 +2697,8 @@ static int __devinit aty_init(struct fb_info *info)
 
 aty_init_exit:
        /* restore video mode */
-       aty_set_crtc(par, &saved_crtc);
-       par->pll_ops->set_pll(info, &saved_pll);
+       aty_set_crtc(par, &par->saved_crtc);
+       par->pll_ops->set_pll(info, &par->saved_pll);
 
 #ifdef CONFIG_MTRR
        if (par->mtrr_reg >= 0) {
@@ -3502,6 +3532,11 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
        par->mmap_map[1].prot_flag = _PAGE_E;
 #endif /* __sparc__ */
 
+       mutex_lock(&reboot_lock);
+       if (!reboot_info)
+               reboot_info = info;
+       mutex_unlock(&reboot_lock);
+
        return 0;
 
 err_release_io:
@@ -3614,8 +3649,8 @@ static void __devexit atyfb_remove(struct fb_info *info)
        struct atyfb_par *par = (struct atyfb_par *) info->par;
 
        /* restore video mode */
-       aty_set_crtc(par, &saved_crtc);
-       par->pll_ops->set_pll(info, &saved_pll);
+       aty_set_crtc(par, &par->saved_crtc);
+       par->pll_ops->set_pll(info, &par->saved_pll);
 
        unregister_framebuffer(info);
 
@@ -3661,6 +3696,11 @@ static void __devexit atyfb_pci_remove(struct pci_dev *pdev)
 {
        struct fb_info *info = pci_get_drvdata(pdev);
 
+       mutex_lock(&reboot_lock);
+       if (reboot_info == info)
+               reboot_info = NULL;
+       mutex_unlock(&reboot_lock);
+
        atyfb_remove(info);
 }
 
@@ -3808,6 +3848,56 @@ static int __init atyfb_setup(char *options)
 }
 #endif  /*  MODULE  */
 
+static int atyfb_reboot_notify(struct notifier_block *nb,
+                              unsigned long code, void *unused)
+{
+       struct atyfb_par *par;
+
+       if (code != SYS_RESTART)
+               return NOTIFY_DONE;
+
+       mutex_lock(&reboot_lock);
+
+       if (!reboot_info)
+               goto out;
+
+       if (!lock_fb_info(reboot_info))
+               goto out;
+
+       par = reboot_info->par;
+
+       /*
+        * HP OmniBook 500's BIOS doesn't like the state of the
+        * hardware after atyfb has been used. Restore the hardware
+        * to the original state to allow successful reboots.
+        */
+       aty_set_crtc(par, &par->saved_crtc);
+       par->pll_ops->set_pll(reboot_info, &par->saved_pll);
+
+       unlock_fb_info(reboot_info);
+ out:
+       mutex_unlock(&reboot_lock);
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block atyfb_reboot_notifier = {
+       .notifier_call = atyfb_reboot_notify,
+};
+
+static const struct dmi_system_id atyfb_reboot_ids[] = {
+       {
+               .ident = "HP OmniBook 500",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 500 FA"),
+               },
+       },
+
+       { }
+};
+
 static int __init atyfb_init(void)
 {
     int err1 = 1, err2 = 1;
@@ -3826,11 +3916,20 @@ static int __init atyfb_init(void)
     err2 = atyfb_atari_probe();
 #endif
 
-    return (err1 && err2) ? -ENODEV : 0;
+    if (err1 && err2)
+       return -ENODEV;
+
+    if (dmi_check_system(atyfb_reboot_ids))
+       register_reboot_notifier(&atyfb_reboot_notifier);
+
+    return 0;
 }
 
 static void __exit atyfb_exit(void)
 {
+       if (dmi_check_system(atyfb_reboot_ids))
+               unregister_reboot_notifier(&atyfb_reboot_notifier);
+
 #ifdef CONFIG_PCI
        pci_unregister_driver(&atyfb_driver);
 #endif
index 0cc9724e61a268cc8e21acfbd5cd4ff05100a6f6..51fcc0a2c94a9097aea33eff174b1b38969b263d 100644 (file)
@@ -63,14 +63,17 @@ static void reset_GTC_3D_engine(const struct atyfb_par *par)
 void aty_init_engine(struct atyfb_par *par, struct fb_info *info)
 {
        u32 pitch_value;
+       u32 vxres;
 
        /* determine modal information from global mode structure */
-       pitch_value = info->var.xres_virtual;
+       pitch_value = info->fix.line_length / (info->var.bits_per_pixel / 8);
+       vxres = info->var.xres_virtual;
 
        if (info->var.bits_per_pixel == 24) {
                /* In 24 bpp, the engine is in 8 bpp - this requires that all */
                /* horizontal coordinates and widths must be adjusted */
                pitch_value *= 3;
+               vxres *= 3;
        }
 
        /* On GTC (RagePro), we need to reset the 3D engine before */
@@ -133,7 +136,7 @@ void aty_init_engine(struct atyfb_par *par, struct fb_info *info)
        aty_st_le32(SC_LEFT, 0, par);
        aty_st_le32(SC_TOP, 0, par);
        aty_st_le32(SC_BOTTOM, par->crtc.vyres - 1, par);
-       aty_st_le32(SC_RIGHT, pitch_value - 1, par);
+       aty_st_le32(SC_RIGHT, vxres - 1, par);
 
        /* set background color to minimum value (usually BLACK) */
        aty_st_le32(DP_BKGD_CLR, 0, par);
index c3ebb6b41ce1afa0df0115af316141679de80174..7aed2565c1bd1b666ab7b46f63e02879e6097a54 100644 (file)
@@ -72,7 +72,7 @@ static int jornada_bl_update_status(struct backlight_device *bd)
                if (jornada_ssp_byte(SETBRIGHTNESS) != TXDUMMY) {
                        printk(KERN_INFO "bl : failed to set brightness\n");
                        ret = -ETIMEDOUT;
-                       goto out
+                       goto out;
                }
 
                /* at this point we expect that the mcu has accepted
index e641584e212e64c087cada21136b6840ff18d2e5..88716626744391a89cae97a5658fb3cc0ffbd545 100644 (file)
@@ -145,6 +145,8 @@ static int pwm_backlight_suspend(struct platform_device *pdev,
        struct backlight_device *bl = platform_get_drvdata(pdev);
        struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
 
+       if (pb->notify)
+               pb->notify(0);
        pwm_config(pb->pwm, 0, pb->period);
        pwm_disable(pb->pwm);
        return 0;
index 1dae7f8f3c6b47c7f4861ff824fff0a4d4dcf8f3..51422fc4f6060ff12b28ff05db0c55ea99613979 100644 (file)
@@ -356,7 +356,7 @@ static int __devinit tdo24m_probe(struct spi_device *spi)
        lcd->power = FB_BLANK_POWERDOWN;
        lcd->mode = MODE_VGA;   /* default to VGA */
 
-       lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, sizeof(GFP_KERNEL));
+       lcd->buf = kmalloc(TDO24M_SPI_BUFF_SIZE, GFP_KERNEL);
        if (lcd->buf == NULL) {
                kfree(lcd);
                return -ENOMEM;
index 7bad24ed04ef5eb2dc8a1e2bec9a56c902e45f7a..108b89e09a80dbdd8c8593f5977a6b8b1a1b7586 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Cobalt server LCD frame buffer driver.
  *
- *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2008  Yoichi Yuasa <yuasa@linux-mips.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
index 471a9a60376ae82a07a921e416b0ec35fb4dbdfe..3a44695b9c09b6c5c46b8fe9735b53df436177f8 100644 (file)
@@ -1082,7 +1082,6 @@ static void fbcon_init(struct vc_data *vc, int init)
        new_rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
        new_cols /= vc->vc_font.width;
        new_rows /= vc->vc_font.height;
-       vc_resize(vc, new_cols, new_rows);
 
        /*
         * We must always set the mode. The mode of the previous console
@@ -1111,10 +1110,11 @@ static void fbcon_init(struct vc_data *vc, int init)
         *  vc_{cols,rows}, but we must not set those if we are only
         *  resizing the console.
         */
-       if (!init) {
+       if (init) {
                vc->vc_cols = new_cols;
                vc->vc_rows = new_rows;
-       }
+       } else
+               vc_resize(vc, new_cols, new_rows);
 
        if (logo)
                fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);
index 75be5ce53dc541f74b15d014b2e652d6a627664c..e233444cda664783d055b372929cafd2f4ac2e89 100644 (file)
@@ -45,7 +45,7 @@ static inline void rotate_ud(const char *in, char *out, u32 width, u32 height)
        width = (width + 7) & ~7;
 
        for (i = 0; i < height; i++) {
-               for (j = 0; j < width; j++) {
+               for (j = 0; j < width - shift; j++) {
                        if (pattern_test_bit(j, i, width, in))
                                pattern_set_bit(width - (1 + j + shift),
                                                height - (1 + i),
index ef7870f5ea088e7e9eb8f59b6292175a6508915e..857b3668b3ba65a15843426685b4e07ce3ff327d 100644 (file)
@@ -957,9 +957,14 @@ static int __devinit sticore_pci_init(struct pci_dev *pd,
 #ifdef CONFIG_PCI
        unsigned long fb_base, rom_base;
        unsigned int fb_len, rom_len;
+       int err;
        struct sti_struct *sti;
        
-       pci_enable_device(pd);
+       err = pci_enable_device(pd);
+       if (err < 0) {
+               dev_err(&pd->dev, "Cannot enable PCI device\n");
+               return err;
+       }
 
        fb_base = pci_resource_start(pd, 0);
        fb_len = pci_resource_len(pd, 0);
@@ -1048,7 +1053,7 @@ static void __devinit sti_init_roms(void)
 
        /* Register drivers for native & PCI cards */
        register_parisc_driver(&pa_sti_driver);
-       pci_register_driver(&pci_sti_driver);
+       WARN_ON(pci_register_driver(&pci_sti_driver));
 
        /* if we didn't find the given default sti, take the first one */
        if (!default_sti)
index f8a09bf8d0cdecb0963116a4fb7a7d3793ed798d..a85c818be9453ecbdf11310b8a77f41435652000 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/compat.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/slab.h>
@@ -1310,8 +1309,6 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd,
 
 static int
 fb_mmap(struct file *file, struct vm_area_struct * vma)
-__acquires(&info->lock)
-__releases(&info->lock)
 {
        int fbidx = iminor(file->f_path.dentry->d_inode);
        struct fb_info *info = registered_fb[fbidx];
@@ -1325,16 +1322,14 @@ __releases(&info->lock)
        off = vma->vm_pgoff << PAGE_SHIFT;
        if (!fb)
                return -ENODEV;
+       mutex_lock(&info->mm_lock);
        if (fb->fb_mmap) {
                int res;
-               mutex_lock(&info->lock);
                res = fb->fb_mmap(info, vma);
-               mutex_unlock(&info->lock);
+               mutex_unlock(&info->mm_lock);
                return res;
        }
 
-       mutex_lock(&info->lock);
-
        /* frame buffer memory */
        start = info->fix.smem_start;
        len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
@@ -1342,13 +1337,13 @@ __releases(&info->lock)
                /* memory mapped io */
                off -= len;
                if (info->var.accel_flags) {
-                       mutex_unlock(&info->lock);
+                       mutex_unlock(&info->mm_lock);
                        return -EINVAL;
                }
                start = info->fix.mmio_start;
                len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
        }
-       mutex_unlock(&info->lock);
+       mutex_unlock(&info->mm_lock);
        start &= PAGE_MASK;
        if ((vma->vm_end - vma->vm_start + off) > len)
                return -EINVAL;
@@ -1518,6 +1513,7 @@ register_framebuffer(struct fb_info *fb_info)
                        break;
        fb_info->node = i;
        mutex_init(&fb_info->lock);
+       mutex_init(&fb_info->mm_lock);
 
        fb_info->dev = device_create(fb_class, fb_info->device,
                                     MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
index 5c1a2c01778fe6e195df9405d0409d7a1a2a09f9..9ae9cd32bd065b1142d63c9975ad51fd1a1972e5 100644 (file)
@@ -256,8 +256,8 @@ static void fix_edid(unsigned char *edid, int fix)
 
 static int edid_checksum(unsigned char *edid)
 {
-       unsigned char i, csum = 0, all_null = 0;
-       int err = 0, fix = check_edid(edid);
+       unsigned char csum = 0, all_null = 0;
+       int i, err = 0, fix = check_edid(edid);
 
        if (fix)
                fix_edid(edid, fix);
index f153c581cbd7bbe99f4558f98e5975b935463263..72d68b3dc478ec4292b6eef69025de3d25a43a52 100644 (file)
@@ -750,24 +750,26 @@ static void update_lcdc(struct fb_info *info)
 static int map_video_memory(struct fb_info *info)
 {
        phys_addr_t phys;
+       u32 smem_len = info->fix.line_length * info->var.yres_virtual;
 
        pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual);
        pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual);
        pr_debug("info->fix.line_length  = %d\n", info->fix.line_length);
+       pr_debug("MAP_VIDEO_MEMORY: smem_len = %u\n", smem_len);
 
-       info->fix.smem_len = info->fix.line_length * info->var.yres_virtual;
-       pr_debug("MAP_VIDEO_MEMORY: smem_len = %d\n", info->fix.smem_len);
-       info->screen_base = fsl_diu_alloc(info->fix.smem_len, &phys);
+       info->screen_base = fsl_diu_alloc(smem_len, &phys);
        if (info->screen_base == NULL) {
                printk(KERN_ERR "Unable to allocate fb memory\n");
                return -ENOMEM;
        }
+       mutex_lock(&info->mm_lock);
        info->fix.smem_start = (unsigned long) phys;
+       info->fix.smem_len = smem_len;
+       mutex_unlock(&info->mm_lock);
        info->screen_size = info->fix.smem_len;
 
        pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n",
-                               info->fix.smem_start,
-               info->fix.smem_len);
+                info->fix.smem_start, info->fix.smem_len);
        pr_debug("screen base %p\n", info->screen_base);
 
        return 0;
@@ -776,9 +778,11 @@ static int map_video_memory(struct fb_info *info)
 static void unmap_video_memory(struct fb_info *info)
 {
        fsl_diu_free(info->screen_base, info->fix.smem_len);
+       mutex_lock(&info->mm_lock);
        info->screen_base = NULL;
        info->fix.smem_start = 0;
        info->fix.smem_len = 0;
+       mutex_unlock(&info->mm_lock);
 }
 
 /*
@@ -1219,12 +1223,6 @@ static int __devinit install_fb(struct fb_info *info)
                return -EINVAL;
        }
 
-       if (fsl_diu_set_par(info)) {
-               printk(KERN_ERR "fb_set_par failed");
-               fb_dealloc_cmap(&info->cmap);
-               return -EINVAL;
-       }
-
        if (register_framebuffer(info) < 0) {
                printk(KERN_ERR "register_framebuffer failed");
                unmap_video_memory(info);
index 020db7fc9153ab1f3483909ccd02f76b9e455900..e7116a6d82d306b51e7b621c1e927fdd156c31ab 100644 (file)
@@ -44,9 +44,6 @@ static struct fb_fix_screeninfo hitfb_fix __initdata = {
        .accel          = FB_ACCEL_NONE,
 };
 
-static u32 pseudo_palette[16];
-static struct fb_info fb_info;
-
 static inline void hitfb_accel_wait(void)
 {
        while (fb_readw(HD64461_GRCFGR) & HD64461_GRCFGR_ACCSTATUS) ;
@@ -331,6 +328,8 @@ static struct fb_ops hitfb_ops = {
 static int __init hitfb_probe(struct platform_device *dev)
 {
        unsigned short lcdclor, ldr3, ldvndr;
+       struct fb_info *info;
+       int ret;
 
        if (fb_get_options("hitfb", NULL))
                return -ENODEV;
@@ -384,32 +383,53 @@ static int __init hitfb_probe(struct platform_device *dev)
                break;
        }
 
-       fb_info.fbops = &hitfb_ops;
-       fb_info.var = hitfb_var;
-       fb_info.fix = hitfb_fix;
-       fb_info.pseudo_palette = pseudo_palette;
-       fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
+       info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+       if (unlikely(!info))
+               return -ENOMEM;
+
+       info->fbops = &hitfb_ops;
+       info->var = hitfb_var;
+       info->fix = hitfb_fix;
+       info->pseudo_palette = info->par;
+       info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
                FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA;
 
-       fb_info.screen_base = (void *)hitfb_fix.smem_start;
+       info->screen_base = (void *)hitfb_fix.smem_start;
 
-       fb_alloc_cmap(&fb_info.cmap, 256, 0);
+       ret = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (unlikely(ret < 0))
+               goto err_fb;
 
-       if (register_framebuffer(&fb_info) < 0)
-               return -EINVAL;
+       ret = register_framebuffer(info);
+       if (unlikely(ret < 0))
+               goto err;
+
+       platform_set_drvdata(dev, info);
 
        printk(KERN_INFO "fb%d: %s frame buffer device\n",
-              fb_info.node, fb_info.fix.id);
+              info->node, info->fix.id);
+
        return 0;
+
+err:
+       fb_dealloc_cmap(&info->cmap);
+err_fb:
+       framebuffer_release(info);
+       return ret;
 }
 
 static int __exit hitfb_remove(struct platform_device *dev)
 {
-       return unregister_framebuffer(&fb_info);
+       struct fb_info *info = platform_get_drvdata(dev);
+
+       unregister_framebuffer(info);
+       fb_dealloc_cmap(&info->cmap);
+       framebuffer_release(info);
+
+       return 0;
 }
 
-#ifdef CONFIG_PM
-static int hitfb_suspend(struct platform_device *dev, pm_message_t state)
+static int hitfb_suspend(struct device *dev)
 {
        u16 v;
 
@@ -421,7 +441,7 @@ static int hitfb_suspend(struct platform_device *dev, pm_message_t state)
        return 0;
 }
 
-static int hitfb_resume(struct platform_device *dev)
+static int hitfb_resume(struct device *dev)
 {
        u16 v;
 
@@ -435,17 +455,19 @@ static int hitfb_resume(struct platform_device *dev)
 
        return 0;
 }
-#endif
+
+static struct dev_pm_ops hitfb_dev_pm_ops = {
+       .suspend        = hitfb_suspend,
+       .resume         = hitfb_resume,
+};
 
 static struct platform_driver hitfb_driver = {
        .probe          = hitfb_probe,
        .remove         = __exit_p(hitfb_remove),
-#ifdef CONFIG_PM
-       .suspend        = hitfb_suspend,
-       .resume         = hitfb_resume,
-#endif
        .driver         = {
                .name   = "hitfb",
+               .owner  = THIS_MODULE,
+               .pm     = &hitfb_dev_pm_ops,
        },
 };
 
index 2e940199fc892b40ceac2630019ef3cea9456c61..5743ea25e818814887fada1f82562e553dbfe2c2 100644 (file)
@@ -1090,8 +1090,10 @@ static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 
        strcpy(fix->id, "I810");
+       mutex_lock(&info->mm_lock);
        fix->smem_start = par->fb.physical;
        fix->smem_len = par->fb.size;
+       mutex_unlock(&info->mm_lock);
        fix->type = FB_TYPE_PACKED_PIXELS;
        fix->type_aux = 0;
        fix->xpanstep = 8;
@@ -2058,8 +2060,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
 
        fb_var_to_videomode(&mode, &info->var);
        fb_add_videomode(&mode, &info->modelist);
-       encode_fix(&info->fix, info); 
-                   
+
        i810fb_init_ringbuffer(info);
        err = register_framebuffer(info);
 
index 0ce3b0a8979805333158d8cd67f44a304ab9f43c..a74e5da17aa074b2454d70e1f30f0b7c2c5223e4 100644 (file)
@@ -454,9 +454,9 @@ static void DAC1064_restore_2(WPMINFO2) {
        dprintk(KERN_DEBUG "DAC1064regs ");
        for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
                dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], ACCESS_FBINFO(hw).DACreg[i]);
-               if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... ");
+               if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... ");
        }
-       dprintk("\n" KERN_DEBUG "DAC1064clk ");
+       dprintk(KERN_DEBUG "DAC1064clk ");
        for (i = 0; i < 6; i++)
                dprintk("C%02X=%02X ", i, ACCESS_FBINFO(hw).DACclk[i]);
        dprintk("\n");
index 13524821e242c7ef0b9f99d11ff31501da995543..4e825112a60173980018acd77f3398cfdb3d10b0 100644 (file)
@@ -651,9 +651,9 @@ static void Ti3026_restore(WPMINFO2) {
        dprintk(KERN_DEBUG "3026DACregs ");
        for (i = 0; i < 21; i++) {
                dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]);
-               if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... ");
+               if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... ");
        }
-       dprintk("\n" KERN_DEBUG "DACclk ");
+       dprintk(KERN_DEBUG "DACclk ");
        for (i = 0; i < 6; i++)
                dprintk("C%02X=%02X ", i, hw->DACclk[i]);
        dprintk("\n");
index 8e7a275df50c79a13c328785a2909d66aae7a0bb..0c1049b308bf3bb433867b0047b1b0afdda65e42 100644 (file)
@@ -724,8 +724,10 @@ static void matroxfb_update_fix(WPMINFO2)
        struct fb_fix_screeninfo *fix = &ACCESS_FBINFO(fbcon).fix;
        DBG(__func__)
 
+       mutex_lock(&ACCESS_FBINFO(fbcon).mm_lock);
        fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes);
        fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes);
+       mutex_unlock(&ACCESS_FBINFO(fbcon).mm_lock);
 }
 
 static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
@@ -1874,7 +1876,6 @@ static int initMatrox2(WPMINFO struct board* b){
        }
        matroxfb_init_fix(PMINFO2);
        ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase));
-       matroxfb_update_fix(PMINFO2);
        /* Normalize values (namely yres_virtual) */
        matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon));
        /* And put it into "current" var. Do NOT program hardware yet, or we'll not take over
@@ -2081,6 +2082,7 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
        spin_lock_init(&ACCESS_FBINFO(lock.accel));
        init_rwsem(&ACCESS_FBINFO(crtc2.lock));
        init_rwsem(&ACCESS_FBINFO(altout.lock));
+       mutex_init(&ACCESS_FBINFO(fbcon).mm_lock);
        ACCESS_FBINFO(irq_flags) = 0;
        init_waitqueue_head(&ACCESS_FBINFO(crtc1.vsync.wait));
        init_waitqueue_head(&ACCESS_FBINFO(crtc2.vsync.wait));
index 7ac4c5f6145d0e0746f3d8233f8f64ed08b05cc6..ebcb5c6b4962bb23cfab791073c9803244efa85f 100644 (file)
@@ -289,7 +289,12 @@ static int matroxfb_dh_release(struct fb_info* info, int user) {
 #undef m2info
 }
 
-static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) {
+/*
+ * This function is called before the register_framebuffer so
+ * no locking is needed.
+ */
+static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info)
+{
        struct fb_fix_screeninfo *fix = &m2info->fbcon.fix;
 
        strcpy(fix->id, "MATROX DH");
index b7af5256e887e0522e704a2165311220a5904666..054ef29be4795dd75900b9b48e66db9494fbb725 100644 (file)
@@ -669,7 +669,8 @@ static uint32_t bpp_to_pixfmt(int bpp)
 }
 
 static int mx3fb_blank(int blank, struct fb_info *fbi);
-static int mx3fb_map_video_memory(struct fb_info *fbi);
+static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len,
+                                 bool lock);
 static int mx3fb_unmap_video_memory(struct fb_info *fbi);
 
 /**
@@ -711,12 +712,7 @@ static void mx3fb_dma_done(void *arg)
        complete(&mx3_fbi->flip_cmpl);
 }
 
-/**
- * mx3fb_set_par() - set framebuffer parameters and change the operating mode.
- * @fbi:       framebuffer information pointer.
- * @return:    0 on success or negative error code on failure.
- */
-static int mx3fb_set_par(struct fb_info *fbi)
+static int __set_par(struct fb_info *fbi, bool lock)
 {
        u32 mem_len;
        struct ipu_di_signal_cfg sig_cfg;
@@ -727,10 +723,6 @@ static int mx3fb_set_par(struct fb_info *fbi)
        struct idmac_video_param *video = &ichan->params.video;
        struct scatterlist *sg = mx3_fbi->sg;
 
-       dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+');
-
-       mutex_lock(&mx3_fbi->mutex);
-
        /* Total cleanup */
        if (mx3_fbi->txd)
                sdc_disable_channel(mx3_fbi);
@@ -742,11 +734,8 @@ static int mx3fb_set_par(struct fb_info *fbi)
                if (fbi->fix.smem_start)
                        mx3fb_unmap_video_memory(fbi);
 
-               fbi->fix.smem_len = mem_len;
-               if (mx3fb_map_video_memory(fbi) < 0) {
-                       mutex_unlock(&mx3_fbi->mutex);
+               if (mx3fb_map_video_memory(fbi, mem_len, lock) < 0)
                        return -ENOMEM;
-               }
        }
 
        sg_init_table(&sg[0], 1);
@@ -792,7 +781,6 @@ static int mx3fb_set_par(struct fb_info *fbi)
                                   fbi->var.vsync_len,
                                   fbi->var.lower_margin +
                                   fbi->var.vsync_len, sig_cfg) != 0) {
-                       mutex_unlock(&mx3_fbi->mutex);
                        dev_err(fbi->device,
                                "mx3fb: Error initializing panel.\n");
                        return -EINVAL;
@@ -811,9 +799,30 @@ static int mx3fb_set_par(struct fb_info *fbi)
        if (mx3_fbi->blank == FB_BLANK_UNBLANK)
                sdc_enable_channel(mx3_fbi);
 
+       return 0;
+}
+
+/**
+ * mx3fb_set_par() - set framebuffer parameters and change the operating mode.
+ * @fbi:       framebuffer information pointer.
+ * @return:    0 on success or negative error code on failure.
+ */
+static int mx3fb_set_par(struct fb_info *fbi)
+{
+       struct mx3fb_info *mx3_fbi = fbi->par;
+       struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
+       struct idmac_channel *ichan = mx3_fbi->idmac_channel;
+       int ret;
+
+       dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+');
+
+       mutex_lock(&mx3_fbi->mutex);
+
+       ret = __set_par(fbi, true);
+
        mutex_unlock(&mx3_fbi->mutex);
 
-       return 0;
+       return ret;
 }
 
 /**
@@ -967,21 +976,11 @@ static int mx3fb_setcolreg(unsigned int regno, unsigned int red,
        return ret;
 }
 
-/**
- * mx3fb_blank() - blank the display.
- */
-static int mx3fb_blank(int blank, struct fb_info *fbi)
+static void __blank(int blank, struct fb_info *fbi)
 {
        struct mx3fb_info *mx3_fbi = fbi->par;
        struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;
 
-       dev_dbg(fbi->device, "%s, blank = %d, base %p, len %u\n", __func__,
-               blank, fbi->screen_base, fbi->fix.smem_len);
-
-       if (mx3_fbi->blank == blank)
-               return 0;
-
-       mutex_lock(&mx3_fbi->mutex);
        mx3_fbi->blank = blank;
 
        switch (blank) {
@@ -1000,6 +999,23 @@ static int mx3fb_blank(int blank, struct fb_info *fbi)
                sdc_set_brightness(mx3fb, mx3fb->backlight_level);
                break;
        }
+}
+
+/**
+ * mx3fb_blank() - blank the display.
+ */
+static int mx3fb_blank(int blank, struct fb_info *fbi)
+{
+       struct mx3fb_info *mx3_fbi = fbi->par;
+
+       dev_dbg(fbi->device, "%s, blank = %d, base %p, len %u\n", __func__,
+               blank, fbi->screen_base, fbi->fix.smem_len);
+
+       if (mx3_fbi->blank == blank)
+               return 0;
+
+       mutex_lock(&mx3_fbi->mutex);
+       __blank(blank, fbi);
        mutex_unlock(&mx3_fbi->mutex);
 
        return 0;
@@ -1198,6 +1214,8 @@ static int mx3fb_resume(struct platform_device *pdev)
 /**
  * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer.
  * @fbi:       framebuffer information pointer
+ * @mem_len:   length of mapped memory
+ * @lock:      do not lock during initialisation
  * @return:    Error code indicating success or failure
  *
  * This buffer is remapped into a non-cached, non-buffered, memory region to
@@ -1205,23 +1223,29 @@ static int mx3fb_resume(struct platform_device *pdev)
  * area is remapped, all virtual memory access to the video memory should occur
  * at the new region.
  */
-static int mx3fb_map_video_memory(struct fb_info *fbi)
+static int mx3fb_map_video_memory(struct fb_info *fbi, unsigned int mem_len,
+                                 bool lock)
 {
        int retval = 0;
        dma_addr_t addr;
 
        fbi->screen_base = dma_alloc_writecombine(fbi->device,
-                                                 fbi->fix.smem_len,
+                                                 mem_len,
                                                  &addr, GFP_DMA);
 
        if (!fbi->screen_base) {
                dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n",
-                       fbi->fix.smem_len);
+                       mem_len);
                retval = -EBUSY;
                goto err0;
        }
 
+       if (lock)
+               mutex_lock(&fbi->mm_lock);
        fbi->fix.smem_start = addr;
+       fbi->fix.smem_len = mem_len;
+       if (lock)
+               mutex_unlock(&fbi->mm_lock);
 
        dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n",
                (uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len);
@@ -1251,8 +1275,10 @@ static int mx3fb_unmap_video_memory(struct fb_info *fbi)
                              fbi->screen_base, fbi->fix.smem_start);
 
        fbi->screen_base = 0;
+       mutex_lock(&fbi->mm_lock);
        fbi->fix.smem_start = 0;
        fbi->fix.smem_len = 0;
+       mutex_unlock(&fbi->mm_lock);
        return 0;
 }
 
@@ -1360,11 +1386,11 @@ static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan)
        init_completion(&mx3fbi->flip_cmpl);
        disable_irq(ichan->eof_irq);
        dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq);
-       ret = mx3fb_set_par(fbi);
+       ret = __set_par(fbi, false);
        if (ret < 0)
                goto esetpar;
 
-       mx3fb_blank(FB_BLANK_UNBLANK, fbi);
+       __blank(FB_BLANK_UNBLANK, fbi);
 
        dev_info(dev, "registered, using mode %s\n", fb_mode);
 
index 060d72fe57cb1f639861ae24cf10a6ed0babdb40..8862233d57b65c0e9d779c680027339a004f7fd8 100644 (file)
@@ -393,8 +393,10 @@ static void set_fb_fix(struct fb_info *fbi)
 
        rg = &plane->fbdev->mem_desc.region[plane->idx];
        fbi->screen_base        = rg->vaddr;
+       mutex_lock(&fbi->mm_lock);
        fix->smem_start         = rg->paddr;
        fix->smem_len           = rg->size;
+       mutex_unlock(&fbi->mm_lock);
 
        fix->type = FB_TYPE_PACKED_PIXELS;
        bpp = var->bits_per_pixel;
@@ -886,8 +888,10 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
                                 * plane memory is dealloce'd, the other
                                 * screen parameters in var / fix are invalid.
                                 */
+                               mutex_lock(&fbi->mm_lock);
                                fbi->fix.smem_start = 0;
                                fbi->fix.smem_len = 0;
+                               mutex_unlock(&fbi->mm_lock);
                        }
                }
        }
@@ -1250,7 +1254,7 @@ static struct fb_ops omapfb_ops = {
 static ssize_t omapfb_show_caps_num(struct device *dev,
                                    struct device_attribute *attr, char *buf)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
        int plane;
        size_t size;
        struct omapfb_caps caps;
@@ -1270,7 +1274,7 @@ static ssize_t omapfb_show_caps_num(struct device *dev,
 static ssize_t omapfb_show_caps_text(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
        int i;
        struct omapfb_caps caps;
        int plane;
@@ -1317,7 +1321,7 @@ static DEVICE_ATTR(caps_text, 0444, omapfb_show_caps_text, NULL);
 static ssize_t omapfb_show_panel_name(struct device *dev,
                                      struct device_attribute *attr, char *buf)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
 
        return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->panel->name);
 }
@@ -1326,7 +1330,7 @@ static ssize_t omapfb_show_bklight_level(struct device *dev,
                                         struct device_attribute *attr,
                                         char *buf)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
        int r;
 
        if (fbdev->panel->get_bklight_level) {
@@ -1341,7 +1345,7 @@ static ssize_t omapfb_store_bklight_level(struct device *dev,
                                          struct device_attribute *attr,
                                          const char *buf, size_t size)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
        int r;
 
        if (fbdev->panel->set_bklight_level) {
@@ -1360,7 +1364,7 @@ static ssize_t omapfb_store_bklight_level(struct device *dev,
 static ssize_t omapfb_show_bklight_max(struct device *dev,
                                       struct device_attribute *attr, char *buf)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
        int r;
 
        if (fbdev->panel->get_bklight_level) {
@@ -1393,7 +1397,7 @@ static struct attribute_group panel_attr_grp = {
 static ssize_t omapfb_show_ctrl_name(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct omapfb_device *fbdev = (struct omapfb_device *)dev->driver_data;
+       struct omapfb_device *fbdev = dev_get_drvdata(dev);
 
        return snprintf(buf, PAGE_SIZE, "%s\n", fbdev->ctrl->name);
 }
index 03b3670130a0d16b81c6f2d6d7d73e0462d91522..bacfabd9ce1653825e14e85a6d702b067f54d9c6 100644 (file)
@@ -141,7 +141,9 @@ static int platinumfb_set_par (struct fb_info *info)
                offset = 0x10;
 
        info->screen_base = pinfo->frame_buffer + init->fb_offset + offset;
+       mutex_lock(&info->mm_lock);
        info->fix.smem_start = (pinfo->frame_buffer_phys) + init->fb_offset + offset;
+       mutex_unlock(&info->mm_lock);
        info->fix.visual = (pinfo->cmode == CMODE_8) ?
                FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
        info->fix.line_length = vmode_attrs[pinfo->vmode-1].hres * (1<<pinfo->cmode)
index 0889d50c3288e127e97fe604bcdb4fa2d52b6224..6506117c134ba136058689157f49d7e725f1818f 100644 (file)
@@ -815,8 +815,10 @@ static int overlayfb_map_video_memory(struct pxafb_layer *ofb)
        ofb->video_mem_phys = virt_to_phys(ofb->video_mem);
        ofb->video_mem_size = size;
 
+       mutex_lock(&ofb->fb.mm_lock);
        ofb->fb.fix.smem_start  = ofb->video_mem_phys;
        ofb->fb.fix.smem_len    = ofb->fb.fix.line_length * var->yres_virtual;
+       mutex_unlock(&ofb->fb.mm_lock);
        ofb->fb.screen_base     = ofb->video_mem;
        return 0;
 }
index 43680e545427f190b432252acb6bfe518219f089..5a72083dc67c76c4b7f9f9f2fbb4c5604cab5eca 100644 (file)
@@ -211,23 +211,21 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
 
 /**
  * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock.
+ * @id: window id.
  * @sfb: The hardware state.
  * @pixclock: The pixel clock wanted, in picoseconds.
  *
  * Given the specified pixel clock, work out the necessary divider to get
  * close to the output frequency.
  */
-static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
+static int s3c_fb_calc_pixclk(unsigned char id, struct s3c_fb *sfb, unsigned int pixclk)
 {
+       struct s3c_fb_pd_win *win = sfb->pdata->win[id];
        unsigned long clk = clk_get_rate(sfb->bus_clk);
-       unsigned long long tmp;
        unsigned int result;
 
-       tmp = (unsigned long long)clk;
-       tmp *= pixclk;
-
-       do_div(tmp, 1000000000UL);
-       result = (unsigned int)tmp / 1000;
+       pixclk *= win->win_mode.refresh;
+       result = clk / pixclk;
 
        dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n",
                pixclk, clk, result, clk / result);
@@ -267,6 +265,7 @@ static int s3c_fb_set_par(struct fb_info *info)
        struct s3c_fb *sfb = win->parent;
        void __iomem *regs = sfb->regs;
        int win_no = win->index;
+       u32 osdc_data = 0;
        u32 data;
        u32 pagewidth;
        int clkdiv;
@@ -302,7 +301,7 @@ static int s3c_fb_set_par(struct fb_info *info)
        /* use window 0 as the basis for the lcd output timings */
 
        if (win_no == 0) {
-               clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock);
+               clkdiv = s3c_fb_calc_pixclk(win_no, sfb, var->pixclock);
 
                data = sfb->pdata->vidcon0;
                data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
@@ -359,8 +358,6 @@ static int s3c_fb_set_par(struct fb_info *info)
 
        data = var->xres * var->yres;
 
-       u32 osdc_data = 0;
-
        osdc_data = VIDISD14C_ALPHA1_R(0xf) |
                VIDISD14C_ALPHA1_G(0xf) |
                VIDISD14C_ALPHA1_B(0xf);
@@ -967,7 +964,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
        struct s3c_fb *sfb = platform_get_drvdata(pdev);
        int win;
 
-       for (win = 0; win <= S3C_FB_MAX_WIN; win++)
+       for (win = 0; win < S3C_FB_MAX_WIN; win++)
                if (sfb->windows[win])
                        s3c_fb_release_win(sfb, sfb->windows[win]);
 
@@ -991,7 +988,7 @@ static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state)
        struct s3c_fb_win *win;
        int win_no;
 
-       for (win_no = S3C_FB_MAX_WIN; win_no >= 0; win_no--) {
+       for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
                win = sfb->windows[win_no];
                if (!win)
                        continue;
index 653bdfee30578fa9b6732f286b0c4fb435c5fd05..9f6d6e61f0cc73a91f6ce93c959b61b090f38464 100644 (file)
@@ -120,18 +120,6 @@ static int sh7760_setcolreg (u_int regno,
        return 0;
 }
 
-static void encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info,
-                      unsigned long stride)
-{
-       memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-       strcpy(fix->id, "sh7760-lcdc");
-
-       fix->smem_start = (unsigned long)info->screen_base;
-       fix->smem_len = info->screen_size;
-
-       fix->line_length = stride;
-}
-
 static int sh7760fb_get_color_info(struct device *dev,
                                   u16 lddfr, int *bpp, int *gray)
 {
@@ -334,7 +322,8 @@ static int sh7760fb_set_par(struct fb_info *info)
 
        iowrite32(ldsarl, par->base + LDSARL);  /* mem for lower half of DSTN */
 
-       encode_fix(&info->fix, info, stride);
+       info->fix.line_length = stride;
+
        sh7760fb_check_var(&info->var, info);
 
        sh7760fb_blank(FB_BLANK_UNBLANK, info); /* panel on! */
@@ -435,6 +424,8 @@ static int sh7760fb_alloc_mem(struct fb_info *info)
 
        info->screen_base = fbmem;
        info->screen_size = vram;
+       info->fix.smem_start = (unsigned long)info->screen_base;
+       info->fix.smem_len = info->screen_size;
 
        return 0;
 }
@@ -520,6 +511,8 @@ static int __devinit sh7760fb_probe(struct platform_device *pdev)
        info->var.transp.length = 0;
        info->var.transp.msb_right = 0;
 
+       strcpy(info->fix.id, "sh7760-lcdc");
+
        /* set the DON2 bit now, before cmap allocation, as it will randomize
         * palette memory.
         */
index f10d2fbeda060275750f3c61fc5dc5f48634f931..07f22b625632872c10476c33ab5dab5e97792adc 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
+#include <linux/vmalloc.h>
 #include <video/sh_mobile_lcdc.h>
 #include <asm/atomic.h>
 
@@ -30,9 +31,10 @@ struct sh_mobile_lcdc_chan {
        unsigned long enabled; /* ME and SE in LDCNT2R */
        struct sh_mobile_lcdc_chan_cfg cfg;
        u32 pseudo_palette[PALETTE_NR];
-       struct fb_info info;
+       struct fb_info *info;
        dma_addr_t dma_handle;
        struct fb_deferred_io defio;
+       struct scatterlist *sglist;
        unsigned long frame_end;
        wait_queue_head_t frame_end_wait;
 };
@@ -206,16 +208,38 @@ static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) {}
 static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {}
 #endif
 
+static int sh_mobile_lcdc_sginit(struct fb_info *info,
+                                 struct list_head *pagelist)
+{
+       struct sh_mobile_lcdc_chan *ch = info->par;
+       unsigned int nr_pages_max = info->fix.smem_len >> PAGE_SHIFT;
+       struct page *page;
+       int nr_pages = 0;
+
+       sg_init_table(ch->sglist, nr_pages_max);
+
+       list_for_each_entry(page, pagelist, lru)
+               sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0);
+
+       return nr_pages;
+}
+
 static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
                                       struct list_head *pagelist)
 {
        struct sh_mobile_lcdc_chan *ch = info->par;
+       unsigned int nr_pages;
 
        /* enable clocks before accessing hardware */
        sh_mobile_lcdc_clk_on(ch->lcdc);
 
+       nr_pages = sh_mobile_lcdc_sginit(info, pagelist);
+       dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
+
        /* trigger panel update */
        lcdc_write_chan(ch, LDSM2R, 1);
+
+       dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
 }
 
 static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
@@ -418,22 +442,22 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
                /* set bpp format in PKF[4:0] */
                tmp = lcdc_read_chan(ch, LDDFR);
                tmp &= ~(0x0001001f);
-               tmp |= (priv->ch[k].info.var.bits_per_pixel == 16) ? 3 : 0;
+               tmp |= (ch->info->var.bits_per_pixel == 16) ? 3 : 0;
                lcdc_write_chan(ch, LDDFR, tmp);
 
                /* point out our frame buffer */
-               lcdc_write_chan(ch, LDSA1R, ch->info.fix.smem_start);
+               lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start);
 
                /* set line size */
-               lcdc_write_chan(ch, LDMLSR, ch->info.fix.line_length);
+               lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length);
 
                /* setup deferred io if SYS bus */
                tmp = ch->cfg.sys_bus_cfg.deferred_io_msec;
                if (ch->ldmt1r_value & (1 << 12) && tmp) {
                        ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
                        ch->defio.delay = msecs_to_jiffies(tmp);
-                       ch->info.fbdefio = &ch->defio;
-                       fb_deferred_io_init(&ch->info);
+                       ch->info->fbdefio = &ch->defio;
+                       fb_deferred_io_init(ch->info);
 
                        /* one-shot mode */
                        lcdc_write_chan(ch, LDSM1R, 1);
@@ -457,6 +481,9 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
        /* tell the board code to enable the panel */
        for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
                ch = &priv->ch[k];
+               if (!ch->enabled)
+                       continue;
+
                board_cfg = &ch->cfg.board_cfg;
                if (board_cfg->display_on)
                        board_cfg->display_on(board_cfg->board_data);
@@ -474,17 +501,19 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
        /* clean up deferred io and ask board code to disable panel */
        for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
                ch = &priv->ch[k];
+               if (!ch->enabled)
+                       continue;
 
                /* deferred io mode:
                 * flush frame, and wait for frame end interrupt
                 * clean up deferred io and enable clock
                 */
-               if (ch->info.fbdefio) {
+               if (ch->info->fbdefio) {
                        ch->frame_end = 0;
-                       schedule_delayed_work(&ch->info.deferred_work, 0);
+                       schedule_delayed_work(&ch->info->deferred_work, 0);
                        wait_event(ch->frame_end_wait, ch->frame_end);
-                       fb_deferred_io_cleanup(&ch->info);
-                       ch->info.fbdefio = NULL;
+                       fb_deferred_io_cleanup(ch->info);
+                       ch->info->fbdefio = NULL;
                        sh_mobile_lcdc_clk_on(priv);
                }
 
@@ -793,9 +822,16 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
        priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1);
 
        for (i = 0; i < j; i++) {
-               info = &priv->ch[i].info;
                cfg = &priv->ch[i].cfg;
 
+               priv->ch[i].info = framebuffer_alloc(0, &pdev->dev);
+               if (!priv->ch[i].info) {
+                       dev_err(&pdev->dev, "unable to allocate fb_info\n");
+                       error = -ENOMEM;
+                       break;
+               }
+
+               info = priv->ch[i].info;
                info->fbops = &sh_mobile_lcdc_ops;
                info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres;
                info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres;
@@ -846,21 +882,31 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
        }
 
        for (i = 0; i < j; i++) {
-               error = register_framebuffer(&priv->ch[i].info);
+               struct sh_mobile_lcdc_chan *ch = priv->ch + i;
+
+               info = ch->info;
+
+               if (info->fbdefio) {
+                       priv->ch->sglist = vmalloc(sizeof(struct scatterlist) *
+                                       info->fix.smem_len >> PAGE_SHIFT);
+                       if (!priv->ch->sglist) {
+                               dev_err(&pdev->dev, "cannot allocate sglist\n");
+                               goto err1;
+                       }
+               }
+
+               error = register_framebuffer(info);
                if (error < 0)
                        goto err1;
-       }
 
-       for (i = 0; i < j; i++) {
-               info = &priv->ch[i].info;
                dev_info(info->dev,
                         "registered %s/%s as %dx%d %dbpp.\n",
                         pdev->name,
-                        (priv->ch[i].cfg.chan == LCDC_CHAN_MAINLCD) ?
+                        (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
                         "mainlcd" : "sublcd",
-                        (int) priv->ch[i].cfg.lcd_cfg.xres,
-                        (int) priv->ch[i].cfg.lcd_cfg.yres,
-                        priv->ch[i].cfg.bpp);
+                        (int) ch->cfg.lcd_cfg.xres,
+                        (int) ch->cfg.lcd_cfg.yres,
+                        ch->cfg.bpp);
 
                /* deferred io mode: disable clock to save power */
                if (info->fbdefio)
@@ -881,20 +927,24 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
-               if (priv->ch[i].info.dev)
-                       unregister_framebuffer(&priv->ch[i].info);
+               if (priv->ch[i].info->dev)
+                       unregister_framebuffer(priv->ch[i].info);
 
        sh_mobile_lcdc_stop(priv);
 
        for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
-               info = &priv->ch[i].info;
+               info = priv->ch[i].info;
 
-               if (!info->device)
+               if (!info || !info->device)
                        continue;
 
+               if (priv->ch[i].sglist)
+                       vfree(priv->ch[i].sglist);
+
                dma_free_coherent(&pdev->dev, info->fix.smem_len,
                                  info->screen_base, priv->ch[i].dma_handle);
                fb_dealloc_cmap(&info->cmap);
+               framebuffer_release(info);
        }
 
 #ifdef CONFIG_HAVE_CLK
index 7072d19080d584dbaf2f754dd31c177251932de4..4a067f0d0ceb49135dc3ef2c53f728600c6c8f18 100644 (file)
@@ -1847,8 +1847,10 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
 
        strcpy(fix->id, ivideo->myid);
 
+       mutex_lock(&info->mm_lock);
        fix->smem_start  = ivideo->video_base + ivideo->video_offset;
        fix->smem_len    = ivideo->sisfb_mem;
+       mutex_unlock(&info->mm_lock);
        fix->type        = FB_TYPE_PACKED_PIXELS;
        fix->type_aux    = 0;
        fix->visual      = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
@@ -6365,7 +6367,6 @@ error_3:  vfree(ivideo->bios_abase);
                sis_fb_info->fix = ivideo->sisfb_fix;
                sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
                sis_fb_info->fbops = &sisfb_ops;
-               sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
                sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
 
                fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
index eb5d73a0670244cee172b1d31aa028a1a86ff8f4..924d79462780c5eb34ee79f5dfa0fb61dec193f8 100644 (file)
@@ -145,7 +145,7 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info)
 #define SM501_MEMF_ACCEL               (8)
 
 static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
-                          unsigned int why, size_t size)
+                          unsigned int why, size_t size, u32 smem_len)
 {
        struct sm501fb_par *par;
        struct fb_info *fbi;
@@ -172,7 +172,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
                if (ptr > 0)
                        ptr &= ~(PAGE_SIZE - 1);
 
-               if (fbi && ptr < fbi->fix.smem_len)
+               if (fbi && ptr < smem_len)
                        return -ENOMEM;
 
                break;
@@ -197,7 +197,7 @@ static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem,
 
        case SM501_MEMF_ACCEL:
                fbi = inf->fb[HEAD_CRT];
-               ptr = fbi ? fbi->fix.smem_len : 0;
+               ptr = fbi ? smem_len : 0;
 
                fbi = inf->fb[HEAD_PANEL];
                if (fbi) {
@@ -413,6 +413,7 @@ static int sm501fb_set_par_common(struct fb_info *info,
        unsigned int mem_type;
        unsigned int clock_type;
        unsigned int head_addr;
+       unsigned int smem_len;
 
        dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n",
                __func__, var->xres, var->yres, var->bits_per_pixel,
@@ -453,18 +454,20 @@ static int sm501fb_set_par_common(struct fb_info *info,
 
        /* allocate fb memory within 501 */
        info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8;
-       info->fix.smem_len    = info->fix.line_length * var->yres_virtual;
+       smem_len = info->fix.line_length * var->yres_virtual;
 
        dev_dbg(fbi->dev, "%s: line length = %u\n", __func__,
                info->fix.line_length);
 
-       if (sm501_alloc_mem(fbi, &par->screen, mem_type,
-                           info->fix.smem_len)) {
+       if (sm501_alloc_mem(fbi, &par->screen, mem_type, smem_len, smem_len)) {
                dev_err(fbi->dev, "no memory available\n");
                return -ENOMEM;
        }
 
+       mutex_lock(&info->mm_lock);
        info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr;
+       info->fix.smem_len   = smem_len;
+       mutex_unlock(&info->mm_lock);
 
        info->screen_base = fbi->fbmem + par->screen.sm_addr;
        info->screen_size = info->fix.smem_len;
@@ -637,7 +640,8 @@ static int sm501fb_set_par_crt(struct fb_info *info)
        if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) {
                /* the head is displaying panel data... */
 
-               sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0);
+               sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0,
+                               info->fix.smem_len);
                goto out_update;
        }
 
@@ -1289,7 +1293,8 @@ static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
 
        par->cursor_regs = info->regs + reg_base;
 
-       ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024);
+       ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024,
+                             fbi->fix.smem_len);
        if (ret < 0)
                return ret;
 
@@ -1535,9 +1540,6 @@ static int sm501fb_init_fb(struct fb_info *fb,
        if (ret)
                dev_err(info->dev, "check_var() failed on initial setup?\n");
 
-       /* ensure we've activated our new configuration */
-       (fb->fbops->fb_set_par)(fb);
-
        return 0;
 }
 
@@ -1619,6 +1621,8 @@ static int __devinit sm501fb_start_one(struct sm501fb_info *info,
        if (!fbi)
                return 0;
 
+       mutex_init(&info->fb[head]->mm_lock);
+
        ret = sm501fb_init_fb(info->fb[head], head, drvname);
        if (ret) {
                dev_err(info->dev, "cannot initialise fb %s\n", drvname);
index eec9dcb7f59976f2a9fe337322fb82724a4ed5fe..6120f0c526fe0c7a42c8c27f9f053550ba1c89e8 100644 (file)
@@ -1115,10 +1115,9 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref)
                  if the device name contains the string "DX" and tell the
                  user how to reconfigure the card. */
                if (strstr(sti->outptr.dev_name, "DX")) {
-                  printk(KERN_WARNING "WARNING: stifb framebuffer driver does not "
-                       "support '%s' in double-buffer mode.\n"
-                       KERN_WARNING "WARNING: Please disable the double-buffer mode "
-                       "in IPL menu (the PARISC-BIOS).\n",
+                  printk(KERN_WARNING
+"WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n"
+"WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n",
                        sti->outptr.dev_name);
                   goto out_err0;
                }
index fcd53ceb88fa4c76f99ba8ba4891ef550edab377..c8960003f47dc4e0e8ed4de2e0b62c91633af8ae 100644 (file)
@@ -2407,14 +2407,14 @@ int viafb_setmode(int vmode_index, int hor_res, int ver_res, int video_bpp,
                        viafb_dvi_set_mode(viafb_get_mode_index
                                     (viaparinfo->tmds_setting_info->h_active,
                                      viaparinfo->tmds_setting_info->
-                                     v_active, 1),
+                                     v_active),
                                     video_bpp1, viaparinfo->
                                     tmds_setting_info->iga_path);
                } else {
                        viafb_dvi_set_mode(viafb_get_mode_index
                                     (viaparinfo->tmds_setting_info->h_active,
                                      viaparinfo->
-                                     tmds_setting_info->v_active, 0),
+                                     tmds_setting_info->v_active),
                                     video_bpp, viaparinfo->
                                     tmds_setting_info->iga_path);
                }
index 6c7290a6a44735d2f150282bda5e622f63f60c40..78c6b3387947e1a207525158b4924ca0cb0ffb71 100644 (file)
@@ -580,10 +580,7 @@ static void load_lcd_k400_patch_tbl(int set_hres, int set_vres,
        int reg_num = 0;
        struct io_reg *lcd_patch_reg = NULL;
 
-       if (viaparinfo->lvds_setting_info->iga_path == IGA2)
-               vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
-       else
-               vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
+       vmode_index = viafb_get_mode_index(set_hres, set_vres);
        switch (panel_id) {
                /* LCD 800x600 */
        case LCD_PANEL_ID1_800X600:
@@ -761,10 +758,7 @@ static void load_lcd_p880_patch_tbl(int set_hres, int set_vres,
        int reg_num = 0;
        struct io_reg *lcd_patch_reg = NULL;
 
-       if (viaparinfo->lvds_setting_info->iga_path == IGA2)
-               vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
-       else
-               vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
+       vmode_index = viafb_get_mode_index(set_hres, set_vres);
 
        switch (panel_id) {
        case LCD_PANEL_ID5_1400X1050:
@@ -832,10 +826,7 @@ static void load_lcd_patch_regs(int set_hres, int set_vres,
 {
        int vmode_index;
 
-       if (viaparinfo->lvds_setting_info->iga_path == IGA2)
-               vmode_index = viafb_get_mode_index(set_hres, set_vres, 1);
-       else
-               vmode_index = viafb_get_mode_index(set_hres, set_vres, 0);
+       vmode_index = viafb_get_mode_index(set_hres, set_vres);
 
        viafb_unlock_crt();
 
index a0fec298216ea26f86695e6253d774c3a0e23729..72833f3334b53ed583610906188c79e621811513 100644 (file)
@@ -32,7 +32,6 @@ static u32 pseudo_pal[17];
 /* video mode */
 static char *viafb_mode = "640x480";
 static char *viafb_mode1 = "640x480";
-static int viafb_resMode = VIA_RES_640X480;
 
 /* Added for specifying active devices.*/
 char *viafb_active_dev = "";
@@ -56,47 +55,47 @@ static void viafb_get_video_device(u32 *video_dev_info);
 
 /* Mode information */
 static const struct viafb_modeinfo viafb_modentry[] = {
-       {480, 640, VIA_RES_480X640, "480x640"},
-       {640, 480, VIA_RES_640X480, "640x480"},
-       {800, 480, VIA_RES_800X480, "800x480"},
-       {800, 600, VIA_RES_800X600, "800x600"},
-       {1024, 768, VIA_RES_1024X768, "1024x768"},
-       {1152, 864, VIA_RES_1152X864, "1152x864"},
-       {1280, 1024, VIA_RES_1280X1024, "1280x1024"},
-       {1600, 1200, VIA_RES_1600X1200, "1600x1200"},
-       {1440, 1050, VIA_RES_1440X1050, "1440x1050"},
-       {1280, 768, VIA_RES_1280X768, "1280x768"},
-       {1280, 800, VIA_RES_1280X800, "1280x800"},
-       {1280, 960, VIA_RES_1280X960, "1280x960"},
-       {1920, 1440, VIA_RES_1920X1440, "1920x1440"},
-       {848, 480, VIA_RES_848X480, "848x480"},
-       {1400, 1050, VIA_RES_1400X1050, "1400x1050"},
-       {720, 480, VIA_RES_720X480, "720x480"},
-       {720, 576, VIA_RES_720X576, "720x576"},
-       {1024, 512, VIA_RES_1024X512, "1024x512"},
-       {1024, 576, VIA_RES_1024X576, "1024x576"},
-       {1024, 600, VIA_RES_1024X600, "1024x600"},
-       {1280, 720, VIA_RES_1280X720, "1280x720"},
-       {1920, 1080, VIA_RES_1920X1080, "1920x1080"},
-       {1366, 768, VIA_RES_1368X768, "1368x768"},
-       {1680, 1050, VIA_RES_1680X1050, "1680x1050"},
-       {960, 600, VIA_RES_960X600, "960x600"},
-       {1000, 600, VIA_RES_1000X600, "1000x600"},
-       {1024, 576, VIA_RES_1024X576, "1024x576"},
-       {1024, 600, VIA_RES_1024X600, "1024x600"},
-       {1088, 612, VIA_RES_1088X612, "1088x612"},
-       {1152, 720, VIA_RES_1152X720, "1152x720"},
-       {1200, 720, VIA_RES_1200X720, "1200x720"},
-       {1280, 600, VIA_RES_1280X600, "1280x600"},
-       {1360, 768, VIA_RES_1360X768, "1360x768"},
-       {1440, 900, VIA_RES_1440X900, "1440x900"},
-       {1600, 900, VIA_RES_1600X900, "1600x900"},
-       {1600, 1024, VIA_RES_1600X1024, "1600x1024"},
-       {1792, 1344, VIA_RES_1792X1344, "1792x1344"},
-       {1856, 1392, VIA_RES_1856X1392, "1856x1392"},
-       {1920, 1200, VIA_RES_1920X1200, "1920x1200"},
-       {2048, 1536, VIA_RES_2048X1536, "2048x1536"},
-       {0, 0, VIA_RES_INVALID, "640x480"}
+       {480, 640, VIA_RES_480X640},
+       {640, 480, VIA_RES_640X480},
+       {800, 480, VIA_RES_800X480},
+       {800, 600, VIA_RES_800X600},
+       {1024, 768, VIA_RES_1024X768},
+       {1152, 864, VIA_RES_1152X864},
+       {1280, 1024, VIA_RES_1280X1024},
+       {1600, 1200, VIA_RES_1600X1200},
+       {1440, 1050, VIA_RES_1440X1050},
+       {1280, 768, VIA_RES_1280X768,},
+       {1280, 800, VIA_RES_1280X800},
+       {1280, 960, VIA_RES_1280X960},
+       {1920, 1440, VIA_RES_1920X1440},
+       {848, 480, VIA_RES_848X480},
+       {1400, 1050, VIA_RES_1400X1050},
+       {720, 480, VIA_RES_720X480},
+       {720, 576, VIA_RES_720X576},
+       {1024, 512, VIA_RES_1024X512},
+       {1024, 576, VIA_RES_1024X576},
+       {1024, 600, VIA_RES_1024X600},
+       {1280, 720, VIA_RES_1280X720},
+       {1920, 1080, VIA_RES_1920X1080},
+       {1366, 768, VIA_RES_1368X768},
+       {1680, 1050, VIA_RES_1680X1050},
+       {960, 600, VIA_RES_960X600},
+       {1000, 600, VIA_RES_1000X600},
+       {1024, 576, VIA_RES_1024X576},
+       {1024, 600, VIA_RES_1024X600},
+       {1088, 612, VIA_RES_1088X612},
+       {1152, 720, VIA_RES_1152X720},
+       {1200, 720, VIA_RES_1200X720},
+       {1280, 600, VIA_RES_1280X600},
+       {1360, 768, VIA_RES_1360X768},
+       {1440, 900, VIA_RES_1440X900},
+       {1600, 900, VIA_RES_1600X900},
+       {1600, 1024, VIA_RES_1600X1024},
+       {1792, 1344, VIA_RES_1792X1344},
+       {1856, 1392, VIA_RES_1856X1392},
+       {1920, 1200, VIA_RES_1920X1200},
+       {2048, 1536, VIA_RES_2048X1536},
+       {0, 0, VIA_RES_INVALID}
 };
 
 static struct fb_ops viafb_ops;
@@ -177,7 +176,7 @@ static int viafb_check_var(struct fb_var_screeninfo *var,
        if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
                return -EINVAL;
 
-       vmode_index = viafb_get_mode_index(var->xres, var->yres, 0);
+       vmode_index = viafb_get_mode_index(var->xres, var->yres);
        if (vmode_index == VIA_RES_INVALID) {
                DEBUG_MSG(KERN_INFO
                          "viafb: Mode %dx%dx%d not supported!!\n",
@@ -233,14 +232,14 @@ static int viafb_set_par(struct fb_info *info)
        viafb_update_device_setting(info->var.xres, info->var.yres,
                              info->var.bits_per_pixel, viafb_refresh, 0);
 
-       vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres, 0);
+       vmode_index = viafb_get_mode_index(info->var.xres, info->var.yres);
 
        if (viafb_SAMM_ON == 1) {
                DEBUG_MSG(KERN_INFO
                "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
                          viafb_second_xres, viafb_second_yres, viafb_bpp1);
                vmode_index1 = viafb_get_mode_index(viafb_second_xres,
-                       viafb_second_yres, 1);
+                       viafb_second_yres);
                DEBUG_MSG(KERN_INFO "->viafb_SAMM_ON: index=%d\n",
                        vmode_index1);
 
@@ -1262,7 +1261,7 @@ static int viafb_sync(struct fb_info *info)
        return 0;
 }
 
-int viafb_get_mode_index(int hres, int vres, int flag)
+int viafb_get_mode_index(int hres, int vres)
 {
        u32 i;
        DEBUG_MSG(KERN_INFO "viafb_get_mode_index!\n");
@@ -1272,13 +1271,7 @@ int viafb_get_mode_index(int hres, int vres, int flag)
                        viafb_modentry[i].yres == vres)
                        break;
 
-       viafb_resMode = viafb_modentry[i].mode_index;
-       if (flag)
-               viafb_mode1 = viafb_modentry[i].mode_res;
-       else
-               viafb_mode = viafb_modentry[i].mode_res;
-
-       return viafb_resMode;
+       return viafb_modentry[i].mode_index;
 }
 
 static void check_available_device_to_enable(int device_id)
@@ -2199,7 +2192,7 @@ static int __devinit via_pci_probe(void)
        strict_strtoul(tmpc, 0, &default_xres);
        strict_strtoul(tmpm, 0, &default_yres);
 
-       vmode_index = viafb_get_mode_index(default_xres, default_yres, 0);
+       vmode_index = viafb_get_mode_index(default_xres, default_yres);
        DEBUG_MSG(KERN_INFO "0->index=%d\n", vmode_index);
 
        if (viafb_SAMM_ON == 1) {
index a4158e8728783bc8b1e65a22310d633dfca0b11b..227b000feb3839f289a5bea173d54aff1c4c38c7 100644 (file)
@@ -81,7 +81,6 @@ struct viafb_modeinfo {
        u32 xres;
        u32 yres;
        int mode_index;
-       char *mode_res;
 };
 extern unsigned int viafb_second_virtual_yres;
 extern unsigned int viafb_second_virtual_xres;
@@ -102,7 +101,7 @@ extern int strict_strtoul(const char *cp, unsigned int base,
 void viafb_memory_pitch_patch(struct fb_info *info);
 void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
                          int mode_index);
-int viafb_get_mode_index(int hres, int vres, int flag);
+int viafb_get_mode_index(int hres, int vres);
 u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
        *plvds_setting_info, struct lvds_chip_information
        *plvds_chip_info, u8 index);
index d0674f1e3f10820e95a8e9db42160fe871908498..2376f688ec8b69addc7c4f0439bd62e127d8482b 100644 (file)
@@ -523,6 +523,7 @@ static int w100fb_set_par(struct fb_info *info)
                info->fix.ywrapstep = 0;
                info->fix.line_length = par->xres * BITS_PER_PIXEL / 8;
 
+               mutex_lock(&info->mm_lock);
                if ((par->xres*par->yres*BITS_PER_PIXEL/8) > (MEM_INT_SIZE+1)) {
                        par->extmem_active = 1;
                        info->fix.smem_len = par->mach->mem->size+1;
@@ -530,6 +531,7 @@ static int w100fb_set_par(struct fb_info *info)
                        par->extmem_active = 0;
                        info->fix.smem_len = MEM_INT_SIZE+1;
                }
+               mutex_unlock(&info->mm_lock);
 
                w100fb_activate_var(par);
        }
@@ -746,8 +748,6 @@ int __init w100fb_probe(struct platform_device *pdev)
                goto out;
        }
 
-       w100fb_set_par(info);
-
        if (register_framebuffer(info) < 0) {
                err = -EINVAL;
                goto out;
index 15502d5e3641890f1f6646cc661b5e26d4755753..54cd916101744ff7c5c1c21d68d4d4f6b028f066 100644 (file)
@@ -454,6 +454,10 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
 
        xenfb_init_shared_page(info, fb_info);
 
+       ret = xenfb_connect_backend(dev, info);
+       if (ret < 0)
+               goto error;
+
        ret = register_framebuffer(fb_info);
        if (ret) {
                fb_deferred_io_cleanup(fb_info);
@@ -464,10 +468,6 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
        }
        info->fb_info = fb_info;
 
-       ret = xenfb_connect_backend(dev, info);
-       if (ret < 0)
-               goto error;
-
        xenfb_make_preferred_console();
        return 0;
 
index 193c8f0e5cc5708a8e1077c0a60bc04c3eaafd2d..248e00ec4dc12fc32cc606eb02d4c67aa79b90d2 100644 (file)
@@ -52,8 +52,10 @@ struct virtio_pci_device
        char (*msix_names)[256];
        /* Number of available vectors */
        unsigned msix_vectors;
-       /* Vectors allocated */
+       /* Vectors allocated, excluding per-vq vectors if any */
        unsigned msix_used_vectors;
+       /* Whether we have vector per vq */
+       bool per_vq_vectors;
 };
 
 /* Constants for MSI-X */
@@ -258,7 +260,6 @@ static void vp_free_vectors(struct virtio_device *vdev)
 
        for (i = 0; i < vp_dev->msix_used_vectors; ++i)
                free_irq(vp_dev->msix_entries[i].vector, vp_dev);
-       vp_dev->msix_used_vectors = 0;
 
        if (vp_dev->msix_enabled) {
                /* Disable the vector used for configuration */
@@ -267,80 +268,77 @@ static void vp_free_vectors(struct virtio_device *vdev)
                /* Flush the write out to device */
                ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
 
-               vp_dev->msix_enabled = 0;
                pci_disable_msix(vp_dev->pci_dev);
+               vp_dev->msix_enabled = 0;
+               vp_dev->msix_vectors = 0;
        }
-}
 
-static int vp_enable_msix(struct pci_dev *dev, struct msix_entry *entries,
-                         int *options, int noptions)
-{
-       int i;
-       for (i = 0; i < noptions; ++i)
-               if (!pci_enable_msix(dev, entries, options[i]))
-                       return options[i];
-       return -EBUSY;
+       vp_dev->msix_used_vectors = 0;
+       kfree(vp_dev->msix_names);
+       vp_dev->msix_names = NULL;
+       kfree(vp_dev->msix_entries);
+       vp_dev->msix_entries = NULL;
 }
 
-static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs)
+static int vp_request_vectors(struct virtio_device *vdev, int nvectors,
+                             bool per_vq_vectors)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        const char *name = dev_name(&vp_dev->vdev.dev);
        unsigned i, v;
        int err = -ENOMEM;
-       /* We want at most one vector per queue and one for config changes.
-        * Fallback to separate vectors for config and a shared for queues.
-        * Finally fall back to regular interrupts. */
-       int options[] = { max_vqs + 1, 2 };
-       int nvectors = max(options[0], options[1]);
+
+       if (!nvectors) {
+               /* Can't allocate MSI-X vectors, use regular interrupt */
+               vp_dev->msix_vectors = 0;
+               err = request_irq(vp_dev->pci_dev->irq, vp_interrupt,
+                                 IRQF_SHARED, name, vp_dev);
+               if (err)
+                       return err;
+               vp_dev->intx_enabled = 1;
+               return 0;
+       }
 
        vp_dev->msix_entries = kmalloc(nvectors * sizeof *vp_dev->msix_entries,
                                       GFP_KERNEL);
        if (!vp_dev->msix_entries)
-               goto error_entries;
+               goto error;
        vp_dev->msix_names = kmalloc(nvectors * sizeof *vp_dev->msix_names,
                                     GFP_KERNEL);
        if (!vp_dev->msix_names)
-               goto error_names;
+               goto error;
 
        for (i = 0; i < nvectors; ++i)
                vp_dev->msix_entries[i].entry = i;
 
-       err = vp_enable_msix(vp_dev->pci_dev, vp_dev->msix_entries,
-                            options, ARRAY_SIZE(options));
-       if (err < 0) {
-               /* Can't allocate enough MSI-X vectors, use regular interrupt */
-               vp_dev->msix_vectors = 0;
-               err = request_irq(vp_dev->pci_dev->irq, vp_interrupt,
-                                 IRQF_SHARED, name, vp_dev);
-               if (err)
-                       goto error_irq;
-               vp_dev->intx_enabled = 1;
-       } else {
-               vp_dev->msix_vectors = err;
-               vp_dev->msix_enabled = 1;
-
-               /* Set the vector used for configuration */
-               v = vp_dev->msix_used_vectors;
-               snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names,
-                        "%s-config", name);
-               err = request_irq(vp_dev->msix_entries[v].vector,
-                                 vp_config_changed, 0, vp_dev->msix_names[v],
-                                 vp_dev);
-               if (err)
-                       goto error_irq;
-               ++vp_dev->msix_used_vectors;
-
-               iowrite16(v, vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
-               /* Verify we had enough resources to assign the vector */
-               v = ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
-               if (v == VIRTIO_MSI_NO_VECTOR) {
-                       err = -EBUSY;
-                       goto error_irq;
-               }
+       err = pci_enable_msix(vp_dev->pci_dev, vp_dev->msix_entries, nvectors);
+       if (err > 0)
+               err = -ENOSPC;
+       if (err)
+               goto error;
+       vp_dev->msix_vectors = nvectors;
+       vp_dev->msix_enabled = 1;
+
+       /* Set the vector used for configuration */
+       v = vp_dev->msix_used_vectors;
+       snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names,
+                "%s-config", name);
+       err = request_irq(vp_dev->msix_entries[v].vector,
+                         vp_config_changed, 0, vp_dev->msix_names[v],
+                         vp_dev);
+       if (err)
+               goto error;
+       ++vp_dev->msix_used_vectors;
+
+       iowrite16(v, vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
+       /* Verify we had enough resources to assign the vector */
+       v = ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
+       if (v == VIRTIO_MSI_NO_VECTOR) {
+               err = -EBUSY;
+               goto error;
        }
 
-       if (vp_dev->msix_vectors && vp_dev->msix_vectors != max_vqs + 1) {
+       if (!per_vq_vectors) {
                /* Shared vector for all VQs */
                v = vp_dev->msix_used_vectors;
                snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names,
@@ -349,28 +347,25 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs)
                                  vp_vring_interrupt, 0, vp_dev->msix_names[v],
                                  vp_dev);
                if (err)
-                       goto error_irq;
+                       goto error;
                ++vp_dev->msix_used_vectors;
        }
        return 0;
-error_irq:
+error:
        vp_free_vectors(vdev);
-       kfree(vp_dev->msix_names);
-error_names:
-       kfree(vp_dev->msix_entries);
-error_entries:
        return err;
 }
 
 static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index,
                                    void (*callback)(struct virtqueue *vq),
-                                   const char *name)
+                                   const char *name,
+                                   u16 vector)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        struct virtio_pci_vq_info *info;
        struct virtqueue *vq;
        unsigned long flags, size;
-       u16 num, vector;
+       u16 num;
        int err;
 
        /* Select the queue we're interested in */
@@ -389,7 +384,7 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index,
 
        info->queue_index = index;
        info->num = num;
-       info->vector = VIRTIO_MSI_NO_VECTOR;
+       info->vector = vector;
 
        size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN));
        info->queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO);
@@ -413,22 +408,7 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index,
        vq->priv = info;
        info->vq = vq;
 
-       /* allocate per-vq vector if available and necessary */
-       if (callback && vp_dev->msix_used_vectors < vp_dev->msix_vectors) {
-               vector = vp_dev->msix_used_vectors;
-               snprintf(vp_dev->msix_names[vector], sizeof *vp_dev->msix_names,
-                        "%s-%s", dev_name(&vp_dev->vdev.dev), name);
-               err = request_irq(vp_dev->msix_entries[vector].vector,
-                                 vring_interrupt, 0,
-                                 vp_dev->msix_names[vector], vq);
-               if (err)
-                       goto out_request_irq;
-               info->vector = vector;
-               ++vp_dev->msix_used_vectors;
-       } else
-               vector = VP_MSIX_VQ_VECTOR;
-
-        if (callback && vp_dev->msix_enabled) {
+        if (vector != VIRTIO_MSI_NO_VECTOR) {
                iowrite16(vector, vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR);
                vector = ioread16(vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR);
                if (vector == VIRTIO_MSI_NO_VECTOR) {
@@ -444,11 +424,6 @@ static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index,
        return vq;
 
 out_assign:
-       if (info->vector != VIRTIO_MSI_NO_VECTOR) {
-               free_irq(vp_dev->msix_entries[info->vector].vector, vq);
-               --vp_dev->msix_used_vectors;
-       }
-out_request_irq:
        vring_del_virtqueue(vq);
 out_activate_queue:
        iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
@@ -462,12 +437,13 @@ static void vp_del_vq(struct virtqueue *vq)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
        struct virtio_pci_vq_info *info = vq->priv;
-       unsigned long size;
+       unsigned long flags, size;
 
-       iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
+       spin_lock_irqsave(&vp_dev->lock, flags);
+       list_del(&info->node);
+       spin_unlock_irqrestore(&vp_dev->lock, flags);
 
-       if (info->vector != VIRTIO_MSI_NO_VECTOR)
-               free_irq(vp_dev->msix_entries[info->vector].vector, vq);
+       iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
 
        if (vp_dev->msix_enabled) {
                iowrite16(VIRTIO_MSI_NO_VECTOR,
@@ -489,36 +465,62 @@ static void vp_del_vq(struct virtqueue *vq)
 /* the config->del_vqs() implementation */
 static void vp_del_vqs(struct virtio_device *vdev)
 {
+       struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        struct virtqueue *vq, *n;
+       struct virtio_pci_vq_info *info;
 
-       list_for_each_entry_safe(vq, n, &vdev->vqs, list)
+       list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
+               info = vq->priv;
+               if (vp_dev->per_vq_vectors)
+                       free_irq(vp_dev->msix_entries[info->vector].vector, vq);
                vp_del_vq(vq);
+       }
+       vp_dev->per_vq_vectors = false;
 
        vp_free_vectors(vdev);
 }
 
-/* the config->find_vqs() implementation */
-static int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
-                      struct virtqueue *vqs[],
-                      vq_callback_t *callbacks[],
-                      const char *names[])
+static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+                             struct virtqueue *vqs[],
+                             vq_callback_t *callbacks[],
+                             const char *names[],
+                             int nvectors,
+                             bool per_vq_vectors)
 {
-       int vectors = 0;
-       int i, err;
-
-       /* How many vectors would we like? */
-       for (i = 0; i < nvqs; ++i)
-               if (callbacks[i])
-                       ++vectors;
+       struct virtio_pci_device *vp_dev = to_vp_device(vdev);
+       u16 vector;
+       int i, err, allocated_vectors;
 
-       err = vp_request_vectors(vdev, vectors);
+       err = vp_request_vectors(vdev, nvectors, per_vq_vectors);
        if (err)
                goto error_request;
 
+       vp_dev->per_vq_vectors = per_vq_vectors;
+       allocated_vectors = vp_dev->msix_used_vectors;
        for (i = 0; i < nvqs; ++i) {
-               vqs[i] = vp_find_vq(vdev, i, callbacks[i], names[i]);
-               if (IS_ERR(vqs[i]))
+               if (!callbacks[i] || !vp_dev->msix_enabled)
+                       vector = VIRTIO_MSI_NO_VECTOR;
+               else if (vp_dev->per_vq_vectors)
+                       vector = allocated_vectors++;
+               else
+                       vector = VP_MSIX_VQ_VECTOR;
+               vqs[i] = vp_find_vq(vdev, i, callbacks[i], names[i], vector);
+               if (IS_ERR(vqs[i])) {
+                       err = PTR_ERR(vqs[i]);
                        goto error_find;
+               }
+               /* allocate per-vq irq if available and necessary */
+               if (vp_dev->per_vq_vectors && vector != VIRTIO_MSI_NO_VECTOR) {
+                       snprintf(vp_dev->msix_names[vector], sizeof *vp_dev->msix_names,
+                                "%s-%s", dev_name(&vp_dev->vdev.dev), names[i]);
+                       err = request_irq(vp_dev->msix_entries[vector].vector,
+                                         vring_interrupt, 0,
+                                         vp_dev->msix_names[vector], vqs[i]);
+                       if (err) {
+                               vp_del_vq(vqs[i]);
+                               goto error_find;
+                       }
+               }
        }
        return 0;
 
@@ -526,7 +528,37 @@ error_find:
        vp_del_vqs(vdev);
 
 error_request:
-       return PTR_ERR(vqs[i]);
+       return err;
+}
+
+/* the config->find_vqs() implementation */
+static int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+                      struct virtqueue *vqs[],
+                      vq_callback_t *callbacks[],
+                      const char *names[])
+{
+       int vectors = 0;
+       int i, uninitialized_var(err);
+
+       /* How many vectors would we like? */
+       for (i = 0; i < nvqs; ++i)
+               if (callbacks[i])
+                       ++vectors;
+
+       /* We want at most one vector per queue and one for config changes. */
+       err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names,
+                                vectors + 1, true);
+       if (!err)
+               return 0;
+       /* Fallback to separate vectors for config and a shared for queues. */
+       err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names,
+                                2, false);
+       if (!err)
+               return 0;
+       /* Finally fall back to regular interrupts. */
+       err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names,
+                                0, false);
+       return err;
 }
 
 static struct virtio_config_ops virtio_pci_config_ops = {
@@ -669,7 +701,7 @@ static int __init virtio_pci_init(void)
 
        err = pci_register_driver(&virtio_pci_driver);
        if (err)
-               device_unregister(virtio_pci_root);
+               root_device_unregister(virtio_pci_root);
 
        return err;
 }
index f6542211db48ff6a137ca39b74af42822de25f9f..a9efb16253215593635eddcfbd475608232ebdaa 100644 (file)
@@ -13,7 +13,7 @@ config VLYNQ
 
 config VLYNQ_DEBUG
        bool "VLYNQ bus debug"
-       depends on VLYNQ && KERNEL_DEBUG
+       depends on VLYNQ && DEBUG_KERNEL
        help
          Turn on VLYNQ bus debugging.
 
index 7335433b067b300518efbe447b8294725055dce7..f05d2a368367cca553c9da79e0949416ecba5c99 100644 (file)
@@ -76,7 +76,7 @@ struct vlynq_regs {
        u32 int_device[8];
 };
 
-#ifdef VLYNQ_DEBUG
+#ifdef CONFIG_VLYNQ_DEBUG
 static void vlynq_dump_regs(struct vlynq_device *dev)
 {
        int i;
index a7e3b706b9d31f0cce657c448de4bedf8d91bd48..0d92969404c37098ade2311882ffd2a88ba8a9ba 100644 (file)
@@ -687,6 +687,7 @@ static int omap_hdq_remove(struct platform_device *pdev)
 
        if (hdq_data->hdq_usecount) {
                dev_dbg(&pdev->dev, "removed when use count is not zero\n");
+               mutex_unlock(&hdq_data->hdq_mutex);
                return -EBUSY;
        }
 
index 3fe9742c23caf3401a6844d1a5a057e7b5b35157..2f8643efe92c2eacba0657ac5b88479f5677d1c2 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/uaccess.h>
 
 #include <asm/addrspace.h>
-#include <asm/ar7/ar7.h>
+#include <asm/mach-ar7/ar7.h>
 
 #define DRVNAME "ar7_wdt"
 #define LONGNAME "TI AR7 Watchdog Timer"
index 5c7011cda6a6a65e1510022c06a8de3b4420a96b..751c003864ad6df86455248e8542e08578f05125 100644 (file)
@@ -161,7 +161,7 @@ static long bcm47xx_wdt_ioctl(struct file *file,
 {
        void __user *argp = (void __user *)arg;
        int __user *p = argp;
-       int new_value, retval = -EINVAL;;
+       int new_value, retval = -EINVAL;
 
        switch (cmd) {
        case WDIOC_GETSUPPORT:
index fecb307d28e99162308025f7ba1b85c975f076f5..aec7cefdef21b956678e1d7ab94a1bd42570590a 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/bitops.h>
 #include <linux/uaccess.h>
 #include <linux/clk.h>
+#include <linux/delay.h>
 
 #define DRV_NAME "WDOG COH 901 327"
 
@@ -92,6 +93,8 @@ static struct clk *clk;
 static void coh901327_enable(u16 timeout)
 {
        u16 val;
+       unsigned long freq;
+       unsigned long delay_ns;
 
        clk_enable(clk);
        /* Restart timer if it is disabled */
@@ -102,6 +105,14 @@ static void coh901327_enable(u16 timeout)
        /* Acknowledge any pending interrupt so it doesn't just fire off */
        writew(U300_WDOG_IER_WILL_BARK_IRQ_ACK_ENABLE,
               virtbase + U300_WDOG_IER);
+       /*
+        * The interrupt is cleared in the 32 kHz clock domain.
+        * Wait 3 32 kHz cycles for it to take effect
+        */
+       freq = clk_get_rate(clk);
+       delay_ns = (1000000000 + freq - 1) / freq; /* Freq to ns and round up */
+       delay_ns = 3 * delay_ns; /* Wait 3 cycles */
+       ndelay(delay_ns);
        /* Enable the watchdog interrupt */
        writew(U300_WDOG_IMR_WILL_BARK_IRQ_ENABLE, virtbase + U300_WDOG_IMR);
        /* Activate the watchdog timer */
index e9f950ff86eaee3e685bd35b4eb9c17221da4cde..cdd55e0d09f8410b949f730fb1cdd6ba07db8ddd 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/watchdog.h>
 #include <linux/timer.h>
 #include <linux/uaccess.h>
+#include <linux/io.h>
 #include <mach/hardware.h>
 
 #define WDT_VERSION    "0.3"
index 00b03eb43bf0920a7579245a6c1e6fa38f4150e9..e1c82769b08e26a1f103c91e64f9af9648b03890 100644 (file)
@@ -66,7 +66,7 @@ static inline void ks8695_wdt_stop(void)
 static inline void ks8695_wdt_start(void)
 {
        unsigned long tmcon;
-       unsigned long tval = wdt_time * CLOCK_TICK_RATE;
+       unsigned long tval = wdt_time * KS8695_CLOCK_RATE;
 
        spin_lock(&ks8695_lock);
        /* disable timer0 */
@@ -103,7 +103,7 @@ static inline void ks8695_wdt_reload(void)
 static int ks8695_wdt_settimeout(int new_time)
 {
        /*
-        * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
+        * All counting occurs at KS8695_CLOCK_RATE / 128 = 0.256 Hz
         *
         * Since WDV is a 16-bit counter, the maximum period is
         * 65536 / 0.256 = 256 seconds.
index ee1caae4d33b0683fe7e13501493eb933078b745..016245419fadb17eda3646152ab507ae1057440f 100644 (file)
@@ -38,7 +38,7 @@
 
 static unsigned long oscr_freq;
 static unsigned long sa1100wdt_users;
-static int pre_margin;
+static unsigned int pre_margin;
 static int boot_status;
 
 /*
@@ -84,6 +84,7 @@ static const struct watchdog_info ident = {
        .options        = WDIOF_CARDRESET | WDIOF_SETTIMEOUT
                                | WDIOF_KEEPALIVEPING,
        .identity       = "SA1100/PXA255 Watchdog",
+       .firmware_version       = 1,
 };
 
 static long sa1100dog_ioctl(struct file *file, unsigned int cmd,
@@ -118,7 +119,7 @@ static long sa1100dog_ioctl(struct file *file, unsigned int cmd,
                if (ret)
                        break;
 
-               if (time <= 0 || time > 255) {
+               if (time <= 0 || (oscr_freq * (long long)time >= 0xffffffff)) {
                        ret = -EINVAL;
                        break;
                }
index 916890abffdd3ca9f9010d90b53319db932fce4c..f201accc4e3d908a00ce91ad029177d0c5315f57 100644 (file)
@@ -89,6 +89,11 @@ static void w83627hf_select_wd_register(void)
                c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */
                outb_p(0x2b, WDT_EFER);
                outb_p(c, WDT_EFDR);    /* set GPIO3 to WDT0 */
+       } else if (c == 0x88) { /* W83627EHF */
+               outb_p(0x2d, WDT_EFER); /* select GPIO5 */
+               c = inb_p(WDT_EFDR) & ~0x01; /* PIN77 -> WDT0# */
+               outb_p(0x2d, WDT_EFER);
+               outb_p(c, WDT_EFDR); /* set GPIO5 to WDT0 */
        }
 
        outb_p(0x07, WDT_EFER); /* point to logical device number reg */
index 883b5f79673a65026f9f129bbe22b79b31bdd652..a6c12dec91a1434c57709b8570f3a3666ae04bc7 100644 (file)
@@ -149,8 +149,10 @@ static void wdt_ctrl(int timeout)
 {
        spin_lock(&io_lock);
 
-       if (w83697ug_select_wd_register() < 0)
+       if (w83697ug_select_wd_register() < 0) {
+               spin_unlock(&io_lock);
                return;
+       }
 
        outb_p(0xF4, WDT_EFER);    /* Select CRF4 */
        outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF4 */
index a4fe7a38d9b037e6c2b83eb5e5b735274998f818..3bde56bce63a3228c4f72089263cefe9d5357227 100644 (file)
@@ -218,16 +218,14 @@ static void wdrtas_timer_keepalive(void)
  */
 static int wdrtas_get_temperature(void)
 {
-       long result;
+       int result;
        int temperature = 0;
 
-       result = rtas_call(wdrtas_token_get_sensor_state, 2, 2,
-                          (void *)__pa(&temperature),
-                          WDRTAS_THERMAL_SENSOR, 0);
+       result = rtas_get_sensor(WDRTAS_THERMAL_SENSOR, 0, &temperature);
 
        if (result < 0)
                printk(KERN_WARNING "wdrtas: reading the thermal sensor "
-                      "faild: %li\n", result);
+                      "failed: %i\n", result);
        else
                temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */
 
index 891d2e90753ab6e9dd312b3120ce6904a96058c2..abad71b1632b10dab15c8fb51e2df7554fb4d62c 100644 (file)
@@ -927,9 +927,9 @@ static struct irq_chip xen_dynamic_chip __read_mostly = {
 void __init xen_init_IRQ(void)
 {
        int i;
-       size_t size = nr_cpu_ids * sizeof(struct cpu_evtchn_s);
 
-       cpu_evtchn_mask_p = alloc_bootmem(size);
+       cpu_evtchn_mask_p = kcalloc(nr_cpu_ids, sizeof(struct cpu_evtchn_s),
+                                   GFP_KERNEL);
        BUG_ON(cpu_evtchn_mask_p == NULL);
 
        init_evtchn_cpu_bindings();
index 332b5ff02fec11b8e8e43645c93ae09679ac9a61..f7003cfac63d3307b7797f4637985872a28f9a03 100644 (file)
@@ -76,7 +76,7 @@ static const match_table_t tokens = {
  * Return 0 upon success, -ERRNO upon failure.
  */
 
-static int v9fs_parse_options(struct v9fs_session_info *v9ses)
+static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
 {
        char *options;
        substring_t args[MAX_OPT_ARGS];
@@ -90,10 +90,10 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses)
        v9ses->debug = 0;
        v9ses->cache = 0;
 
-       if (!v9ses->options)
+       if (!opts)
                return 0;
 
-       options = kstrdup(v9ses->options, GFP_KERNEL);
+       options = kstrdup(opts, GFP_KERNEL);
        if (!options) {
                P9_DPRINTK(P9_DEBUG_ERROR,
                           "failed to allocate copy of option string\n");
@@ -206,24 +206,14 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
        v9ses->uid = ~0;
        v9ses->dfltuid = V9FS_DEFUID;
        v9ses->dfltgid = V9FS_DEFGID;
-       if (data) {
-               v9ses->options = kstrdup(data, GFP_KERNEL);
-               if (!v9ses->options) {
-                       P9_DPRINTK(P9_DEBUG_ERROR,
-                          "failed to allocate copy of option string\n");
-                       retval = -ENOMEM;
-                       goto error;
-               }
-       }
 
-       rc = v9fs_parse_options(v9ses);
+       rc = v9fs_parse_options(v9ses, data);
        if (rc < 0) {
                retval = rc;
                goto error;
        }
 
-       v9ses->clnt = p9_client_create(dev_name, v9ses->options);
-
+       v9ses->clnt = p9_client_create(dev_name, data);
        if (IS_ERR(v9ses->clnt)) {
                retval = PTR_ERR(v9ses->clnt);
                v9ses->clnt = NULL;
@@ -280,7 +270,6 @@ void v9fs_session_close(struct v9fs_session_info *v9ses)
 
        __putname(v9ses->uname);
        __putname(v9ses->aname);
-       kfree(v9ses->options);
 }
 
 /**
index a7d567192998e97cb292fdf313b25bea5f84fe81..38762bf102a9b04d124400ddfbb0b59daa007005 100644 (file)
@@ -85,7 +85,6 @@ struct v9fs_session_info {
        unsigned int afid;
        unsigned int cache;
 
-       char *options;          /* copy of mount options */
        char *uname;            /* user name to mount as */
        char *aname;            /* name of remote hierarchy being mounted */
        unsigned int maxdata;   /* max data for client interface */
index 6fcb1e7095cfe0a97255170656d76e3fe8ed9a30..92828281a30b9a0a449255003d6bf4468fab0512 100644 (file)
@@ -57,7 +57,7 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page)
        buffer = kmap(page);
        offset = page_offset(page);
 
-       retval = v9fs_file_readn(filp, buffer, NULL, offset, PAGE_CACHE_SIZE);
+       retval = v9fs_file_readn(filp, buffer, NULL, PAGE_CACHE_SIZE, offset);
        if (retval < 0)
                goto done;
 
index 81f8bbf12f9fe6867112e7e230a3862e46539455..06a223d50a8165d908e738ff293f572a896c1bca 100644 (file)
@@ -171,7 +171,6 @@ int v9fs_uflags2omode(int uflags, int extended)
 
 /**
  * v9fs_blank_wstat - helper function to setup a 9P stat structure
- * @v9ses: 9P session info (for determining extended mode)
  * @wstat: structure to initialize
  *
  */
@@ -207,65 +206,72 @@ v9fs_blank_wstat(struct p9_wstat *wstat)
 
 struct inode *v9fs_get_inode(struct super_block *sb, int mode)
 {
+       int err;
        struct inode *inode;
        struct v9fs_session_info *v9ses = sb->s_fs_info;
 
        P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
 
        inode = new_inode(sb);
-       if (inode) {
-               inode->i_mode = mode;
-               inode->i_uid = current_fsuid();
-               inode->i_gid = current_fsgid();
-               inode->i_blocks = 0;
-               inode->i_rdev = 0;
-               inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-               inode->i_mapping->a_ops = &v9fs_addr_operations;
-
-               switch (mode & S_IFMT) {
-               case S_IFIFO:
-               case S_IFBLK:
-               case S_IFCHR:
-               case S_IFSOCK:
-                       if (!v9fs_extended(v9ses)) {
-                               P9_DPRINTK(P9_DEBUG_ERROR,
-                                     "special files without extended mode\n");
-                               return ERR_PTR(-EINVAL);
-                       }
-                       init_special_inode(inode, inode->i_mode,
-                                          inode->i_rdev);
-                       break;
-               case S_IFREG:
-                       inode->i_op = &v9fs_file_inode_operations;
-                       inode->i_fop = &v9fs_file_operations;
-                       break;
-               case S_IFLNK:
-                       if (!v9fs_extended(v9ses)) {
-                               P9_DPRINTK(P9_DEBUG_ERROR,
-                                       "extended modes used w/o 9P2000.u\n");
-                               return ERR_PTR(-EINVAL);
-                       }
-                       inode->i_op = &v9fs_symlink_inode_operations;
-                       break;
-               case S_IFDIR:
-                       inc_nlink(inode);
-                       if (v9fs_extended(v9ses))
-                               inode->i_op = &v9fs_dir_inode_operations_ext;
-                       else
-                               inode->i_op = &v9fs_dir_inode_operations;
-                       inode->i_fop = &v9fs_dir_operations;
-                       break;
-               default:
-                       P9_DPRINTK(P9_DEBUG_ERROR,
-                               "BAD mode 0x%x S_IFMT 0x%x\n",
-                               mode, mode & S_IFMT);
-                       return ERR_PTR(-EINVAL);
-               }
-       } else {
+       if (!inode) {
                P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
                return ERR_PTR(-ENOMEM);
        }
+
+       inode->i_mode = mode;
+       inode->i_uid = current_fsuid();
+       inode->i_gid = current_fsgid();
+       inode->i_blocks = 0;
+       inode->i_rdev = 0;
+       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       inode->i_mapping->a_ops = &v9fs_addr_operations;
+
+       switch (mode & S_IFMT) {
+       case S_IFIFO:
+       case S_IFBLK:
+       case S_IFCHR:
+       case S_IFSOCK:
+               if (!v9fs_extended(v9ses)) {
+                       P9_DPRINTK(P9_DEBUG_ERROR,
+                                  "special files without extended mode\n");
+                       err = -EINVAL;
+                       goto error;
+               }
+               init_special_inode(inode, inode->i_mode, inode->i_rdev);
+               break;
+       case S_IFREG:
+               inode->i_op = &v9fs_file_inode_operations;
+               inode->i_fop = &v9fs_file_operations;
+               break;
+       case S_IFLNK:
+               if (!v9fs_extended(v9ses)) {
+                       P9_DPRINTK(P9_DEBUG_ERROR,
+                                  "extended modes used w/o 9P2000.u\n");
+                       err = -EINVAL;
+                       goto error;
+               }
+               inode->i_op = &v9fs_symlink_inode_operations;
+               break;
+       case S_IFDIR:
+               inc_nlink(inode);
+               if (v9fs_extended(v9ses))
+                       inode->i_op = &v9fs_dir_inode_operations_ext;
+               else
+                       inode->i_op = &v9fs_dir_inode_operations;
+               inode->i_fop = &v9fs_dir_operations;
+               break;
+       default:
+               P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
+                          mode, mode & S_IFMT);
+               err = -EINVAL;
+               goto error;
+       }
+
        return inode;
+
+error:
+       iput(inode);
+       return ERR_PTR(err);
 }
 
 /*
@@ -338,30 +344,25 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
 
        ret = NULL;
        st = p9_client_stat(fid);
-       if (IS_ERR(st)) {
-               err = PTR_ERR(st);
-               st = NULL;
-               goto error;
-       }
+       if (IS_ERR(st))
+               return ERR_CAST(st);
 
        umode = p9mode2unixmode(v9ses, st->mode);
        ret = v9fs_get_inode(sb, umode);
        if (IS_ERR(ret)) {
                err = PTR_ERR(ret);
-               ret = NULL;
                goto error;
        }
 
        v9fs_stat2inode(st, ret, sb);
        ret->i_ino = v9fs_qid2ino(&st->qid);
+       p9stat_free(st);
        kfree(st);
        return ret;
 
 error:
+       p9stat_free(st);
        kfree(st);
-       if (ret)
-               iput(ret);
-
        return ERR_PTR(err);
 }
 
@@ -403,9 +404,9 @@ v9fs_open_created(struct inode *inode, struct file *file)
  * @v9ses: session information
  * @dir: directory that dentry is being created in
  * @dentry:  dentry that is being created
+ * @extension: 9p2000.u extension string to support devices, etc.
  * @perm: create permissions
  * @mode: open mode
- * @extension: 9p2000.u extension string to support devices, etc.
  *
  */
 static struct p9_fid *
@@ -470,7 +471,10 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
                dentry->d_op = &v9fs_dentry_operations;
 
        d_instantiate(dentry, inode);
-       v9fs_fid_add(dentry, fid);
+       err = v9fs_fid_add(dentry, fid);
+       if (err < 0)
+               goto error;
+
        return ofid;
 
 error:
index 38d695d66a0b7899ff8c76ef21cfca4679722fa5..8961f1a8f6682bc04fbb7829f783bae29ec6a580 100644 (file)
@@ -81,7 +81,7 @@ static int v9fs_set_super(struct super_block *s, void *data)
 
 static void
 v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
-               int flags)
+               int flags, void *data)
 {
        sb->s_maxbytes = MAX_LFS_FILESIZE;
        sb->s_blocksize_bits = fls(v9ses->maxdata - 1);
@@ -91,6 +91,8 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
 
        sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC |
            MS_NOATIME;
+
+       save_mount_options(sb, data);
 }
 
 /**
@@ -113,14 +115,11 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
        struct v9fs_session_info *v9ses = NULL;
        struct p9_wstat *st = NULL;
        int mode = S_IRWXUGO | S_ISVTX;
-       uid_t uid = current_fsuid();
-       gid_t gid = current_fsgid();
        struct p9_fid *fid;
        int retval = 0;
 
        P9_DPRINTK(P9_DEBUG_VFS, " \n");
 
-       st = NULL;
        v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
        if (!v9ses)
                return -ENOMEM;
@@ -142,7 +141,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
                retval = PTR_ERR(sb);
                goto free_stat;
        }
-       v9fs_fill_super(sb, v9ses, flags);
+       v9fs_fill_super(sb, v9ses, flags, data);
 
        inode = v9fs_get_inode(sb, S_IFDIR | mode);
        if (IS_ERR(inode)) {
@@ -150,9 +149,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
                goto release_sb;
        }
 
-       inode->i_uid = uid;
-       inode->i_gid = gid;
-
        root = d_alloc_root(inode);
        if (!root) {
                iput(inode);
@@ -173,10 +169,8 @@ P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
        simple_set_mnt(mnt, sb);
        return 0;
 
-release_sb:
-       deactivate_locked_super(sb);
-
 free_stat:
+       p9stat_free(st);
        kfree(st);
 
 clunk_fid:
@@ -185,7 +179,12 @@ clunk_fid:
 close_session:
        v9fs_session_close(v9ses);
        kfree(v9ses);
+       return retval;
 
+release_sb:
+       p9stat_free(st);
+       kfree(st);
+       deactivate_locked_super(sb);
        return retval;
 }
 
@@ -207,24 +206,10 @@ static void v9fs_kill_super(struct super_block *s)
 
        v9fs_session_close(v9ses);
        kfree(v9ses);
+       s->s_fs_info = NULL;
        P9_DPRINTK(P9_DEBUG_VFS, "exiting kill_super\n");
 }
 
-/**
- * v9fs_show_options - Show mount options in /proc/mounts
- * @m: seq_file to write to
- * @mnt: mount descriptor
- *
- */
-
-static int v9fs_show_options(struct seq_file *m, struct vfsmount *mnt)
-{
-       struct v9fs_session_info *v9ses = mnt->mnt_sb->s_fs_info;
-
-       seq_printf(m, "%s", v9ses->options);
-       return 0;
-}
-
 static void
 v9fs_umount_begin(struct super_block *sb)
 {
@@ -237,7 +222,7 @@ v9fs_umount_begin(struct super_block *sb)
 static const struct super_operations v9fs_super_ops = {
        .statfs = simple_statfs,
        .clear_inode = v9fs_clear_inode,
-       .show_options = v9fs_show_options,
+       .show_options = generic_show_options,
        .umount_begin = v9fs_umount_begin,
 };
 
index a97263be6a91d4927bef9dd8c3e834c7c251a472..0e7da7bb5d9351756f691e4ced2e0df2c56a23f6 100644 (file)
@@ -186,32 +186,7 @@ source "fs/romfs/Kconfig"
 source "fs/sysv/Kconfig"
 source "fs/ufs/Kconfig"
 source "fs/exofs/Kconfig"
-
-config NILFS2_FS
-       tristate "NILFS2 file system support (EXPERIMENTAL)"
-       depends on BLOCK && EXPERIMENTAL
-       select CRC32
-       help
-         NILFS2 is a log-structured file system (LFS) supporting continuous
-         snapshotting.  In addition to versioning capability of the entire
-         file system, users can even restore files mistakenly overwritten or
-         destroyed just a few seconds ago.  Since this file system can keep
-         consistency like conventional LFS, it achieves quick recovery after
-         system crashes.
-
-         NILFS2 creates a number of checkpoints every few seconds or per
-         synchronous write basis (unless there is no change).  Users can
-         select significant versions among continuously created checkpoints,
-         and can change them into snapshots which will be preserved for long
-         periods until they are changed back to checkpoints.  Each
-         snapshot is mountable as a read-only file system concurrently with
-         its writable mount, and this feature is convenient for online backup.
-
-         Some features including atime, extended attributes, and POSIX ACLs,
-         are not supported yet.
-
-         To compile this file system support as a module, choose M here: the
-         module will be called nilfs2.  If unsure, say N.
+source "fs/nilfs2/Kconfig"
 
 endif # MISC_FILESYSTEMS
 
index aad92f0a1048428e9c02b010471511edcc15e015..6910a98bd73cefc29cc0e8435dfd0949625d34fd 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/parser.h>
 #include <linux/mount.h>
 #include <linux/seq_file.h>
+#include <linux/smp_lock.h>
 #include <linux/statfs.h>
 #include "adfs.h"
 #include "dir_f.h"
index 9bd757774c9ed0d154b7f8ec55f93db18f08c9bc..88067f36e5e7bea4c4d51cff5dd0a9e24e79b3ad 100644 (file)
@@ -564,7 +564,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
 static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
        struct afs_vnode *vnode, *dir;
-       struct afs_fid fid;
+       struct afs_fid uninitialized_var(fid);
        struct dentry *parent;
        struct key *key;
        void *dir_version;
index 0149dab365e722c95f466e7e5d17f94cab8b9e70..681c2a7b013fc3c06bfa2d0d75d05804eafb8ffb 100644 (file)
@@ -134,9 +134,16 @@ static int afs_readpage(struct file *file, struct page *page)
 
        inode = page->mapping->host;
 
-       ASSERT(file != NULL);
-       key = file->private_data;
-       ASSERT(key != NULL);
+       if (file) {
+               key = file->private_data;
+               ASSERT(key != NULL);
+       } else {
+               key = afs_request_key(AFS_FS_S(inode->i_sb)->volume->cell);
+               if (IS_ERR(key)) {
+                       ret = PTR_ERR(key);
+                       goto error_nokey;
+               }
+       }
 
        _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index);
 
@@ -207,12 +214,17 @@ static int afs_readpage(struct file *file, struct page *page)
                unlock_page(page);
        }
 
+       if (!file)
+               key_put(key);
        _leave(" = 0");
        return 0;
 
 error:
        SetPageError(page);
        unlock_page(page);
+       if (!file)
+               key_put(key);
+error_nokey:
        _leave(" = %d", ret);
        return ret;
 }
index 210acafe4a9b5d1ec4e5d919e474497c22073ba2..3ff8bdd18fb3b90de6829780d65b3d4bc3cbeb51 100644 (file)
@@ -432,7 +432,6 @@ vfs_rejected_lock:
        list_del_init(&fl->fl_u.afs.link);
        if (list_empty(&vnode->granted_locks))
                afs_defer_unlock(vnode, key);
-       spin_unlock(&vnode->lock);
        goto abort_attempt;
 }
 
index c52be53f694628e7a618b6a0405394b582050aca..5ffb570cd3a8e1d962b62d2b43324012741ff888 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/pagemap.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
-#include <linux/mnt_namespace.h>
 #include "internal.h"
 
 
index ad0514d0115f76356ab2aa6034fab3aa2ea79597..e1ea1c240b6a2caa7e6b5220bc02380db0e2dea5 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/parser.h>
index 76da12537956cf0635c5615303f8cbb0fb8337a7..d065b2c3273ea03615ae883558100b4962a2ddbb 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -485,6 +485,8 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req)
 {
        assert_spin_locked(&ctx->ctx_lock);
 
+       if (req->ki_eventfd != NULL)
+               eventfd_ctx_put(req->ki_eventfd);
        if (req->ki_dtor)
                req->ki_dtor(req);
        if (req->ki_iovec != &req->ki_inline_vec)
@@ -509,8 +511,6 @@ static void aio_fput_routine(struct work_struct *data)
                /* Complete the fput(s) */
                if (req->ki_filp != NULL)
                        __fput(req->ki_filp);
-               if (req->ki_eventfd != NULL)
-                       __fput(req->ki_eventfd);
 
                /* Link the iocb into the context's free list */
                spin_lock_irq(&ctx->ctx_lock);
@@ -528,8 +528,6 @@ static void aio_fput_routine(struct work_struct *data)
  */
 static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
 {
-       int schedule_putreq = 0;
-
        dprintk(KERN_DEBUG "aio_put(%p): f_count=%ld\n",
                req, atomic_long_read(&req->ki_filp->f_count));
 
@@ -549,24 +547,16 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
         * we would not be holding the last reference to the file*, so
         * this function will be executed w/out any aio kthread wakeup.
         */
-       if (unlikely(atomic_long_dec_and_test(&req->ki_filp->f_count)))
-               schedule_putreq++;
-       else
-               req->ki_filp = NULL;
-       if (req->ki_eventfd != NULL) {
-               if (unlikely(atomic_long_dec_and_test(&req->ki_eventfd->f_count)))
-                       schedule_putreq++;
-               else
-                       req->ki_eventfd = NULL;
-       }
-       if (unlikely(schedule_putreq)) {
+       if (unlikely(atomic_long_dec_and_test(&req->ki_filp->f_count))) {
                get_ioctx(ctx);
                spin_lock(&fput_lock);
                list_add(&req->ki_list, &fput_head);
                spin_unlock(&fput_lock);
                queue_work(aio_wq, &fput_work);
-       } else
+       } else {
+               req->ki_filp = NULL;
                really_put_req(ctx, req);
+       }
        return 1;
 }
 
@@ -1622,7 +1612,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                 * an eventfd() fd, and will be signaled for each completed
                 * event using the eventfd_signal() function.
                 */
-               req->ki_eventfd = eventfd_fget((int) iocb->aio_resfd);
+               req->ki_eventfd = eventfd_ctx_fdget((int) iocb->aio_resfd);
                if (IS_ERR(req->ki_eventfd)) {
                        ret = PTR_ERR(req->ki_eventfd);
                        req->ki_eventfd = NULL;
index f3da2eb51f56a2c02e579a76517a6547c1ca65e2..00bf8fcb245f13cfd7bab5fcd7bc0fdb92952087 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/sched.h>
 #include <linux/compat.h>
 #include <linux/syscalls.h>
-#include <linux/smp_lock.h>
 #include <linux/magic.h>
 #include <linux/dcache.h>
 #include <linux/uaccess.h>
index aa39ae83f0193da10f0b218954ae8ec9cf149cb3..3da18d4534881a199dccfa223d77c3019c813269 100644 (file)
@@ -77,7 +77,7 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
        }
 
        /* Update the expiry counter if fs is busy */
-       if (!may_umount_tree(mnt)) {
+       if (!may_umount_tree(path.mnt)) {
                struct autofs_info *ino = autofs4_dentry_ino(top);
                ino->last_used = jiffies;
                goto done;
index 54bd07d44e6875447ebcbfdc47b12bffb5484784..1e41aadb1068672a1969d6496dce9dd5e930b656 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/time.h>
 #include <linux/string.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/sched.h>
 #include "bfs.h"
index 6a021265f018e5e42717c9b7001b47fe69a744e9..88b9a3ff44e4bc71bcc15029283dd706f2eaa73a 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
-#include <linux/smp_lock.h>
 #include "bfs.h"
 
 #undef DEBUG
index 9fa212b014a50448534cb8e2deb1ba193c4ed257..b7c1603cd4bd4ded0f70d06dcb8e84546bfdd4ba 100644 (file)
@@ -1522,11 +1522,11 @@ static int fill_note_info(struct elfhdr *elf, int phdrs,
        info->thread = NULL;
 
        psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL);
-       fill_note(&info->psinfo, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
-
        if (psinfo == NULL)
                return 0;
 
+       fill_note(&info->psinfo, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
+
        /*
         * Figure out how many notes we're going to need for each thread.
         */
@@ -1929,7 +1929,10 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
        elf = kmalloc(sizeof(*elf), GFP_KERNEL);
        if (!elf)
                goto out;
-       
+       /*
+        * The number of segs are recored into ELF header as 16bit value.
+        * Please check DEFAULT_MAX_MAP_COUNT definition when you modify here.
+        */
        segs = current->mm->map_count;
 #ifdef ELF_CORE_EXTRA_PHDRS
        segs += ELF_CORE_EXTRA_PHDRS;
index 697f6b5f13139ac5ea95a3f7456687299f26775e..e92f229e3c6e9d994d61f5581625c35c2bde6bd7 100644 (file)
@@ -828,15 +828,22 @@ static int load_flat_shared_library(int id, struct lib_info *libs)
        if (IS_ERR(bprm.file))
                return res;
 
+       bprm.cred = prepare_exec_creds();
+       res = -ENOMEM;
+       if (!bprm.cred)
+               goto out;
+
        res = prepare_binprm(&bprm);
 
        if (res <= (unsigned long)-4096)
                res = load_flat_file(&bprm, libs, id, NULL);
-       if (bprm.file) {
-               allow_write_access(bprm.file);
-               fput(bprm.file);
-               bprm.file = NULL;
-       }
+
+       abort_creds(bprm.cred);
+
+out:
+       allow_write_access(bprm.file);
+       fput(bprm.file);
+
        return(res);
 }
 
index 31c46a241bac6838de2be1af7a9f452d58b9affb..49a34e7f7306d49af72b6d84fda277b82d01cc01 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * bio-integrity.c - bio data integrity extensions
  *
- * Copyright (C) 2007, 2008 Oracle Corporation
+ * Copyright (C) 2007, 2008, 2009 Oracle Corporation
  * Written by: Martin K. Petersen <martin.petersen@oracle.com>
  *
  * This program is free software; you can redistribute it and/or
 #include <linux/bio.h>
 #include <linux/workqueue.h>
 
-static struct kmem_cache *bio_integrity_slab __read_mostly;
-static mempool_t *bio_integrity_pool;
-static struct bio_set *integrity_bio_set;
+struct integrity_slab {
+       struct kmem_cache *slab;
+       unsigned short nr_vecs;
+       char name[8];
+};
+
+#define IS(x) { .nr_vecs = x, .name = "bip-"__stringify(x) }
+struct integrity_slab bip_slab[BIOVEC_NR_POOLS] __read_mostly = {
+       IS(1), IS(4), IS(16), IS(64), IS(128), IS(BIO_MAX_PAGES),
+};
+#undef IS
+
 static struct workqueue_struct *kintegrityd_wq;
 
+static inline unsigned int vecs_to_idx(unsigned int nr)
+{
+       switch (nr) {
+       case 1:
+               return 0;
+       case 2 ... 4:
+               return 1;
+       case 5 ... 16:
+               return 2;
+       case 17 ... 64:
+               return 3;
+       case 65 ... 128:
+               return 4;
+       case 129 ... BIO_MAX_PAGES:
+               return 5;
+       default:
+               BUG();
+       }
+}
+
+static inline int use_bip_pool(unsigned int idx)
+{
+       if (idx == BIOVEC_NR_POOLS)
+               return 1;
+
+       return 0;
+}
+
 /**
- * bio_integrity_alloc - Allocate integrity payload and attach it to bio
+ * bio_integrity_alloc_bioset - Allocate integrity payload and attach it to bio
  * @bio:       bio to attach integrity metadata to
  * @gfp_mask:  Memory allocation mask
  * @nr_vecs:   Number of integrity metadata scatter-gather elements
+ * @bs:                bio_set to allocate from
  *
  * Description: This function prepares a bio for attaching integrity
  * metadata.  nr_vecs specifies the maximum number of pages containing
  * integrity metadata that can be attached.
  */
-struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
-                                                 gfp_t gfp_mask,
-                                                 unsigned int nr_vecs)
+struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *bio,
+                                                        gfp_t gfp_mask,
+                                                        unsigned int nr_vecs,
+                                                        struct bio_set *bs)
 {
        struct bio_integrity_payload *bip;
-       struct bio_vec *iv;
-       unsigned long idx;
+       unsigned int idx = vecs_to_idx(nr_vecs);
 
        BUG_ON(bio == NULL);
+       bip = NULL;
 
-       bip = mempool_alloc(bio_integrity_pool, gfp_mask);
-       if (unlikely(bip == NULL)) {
-               printk(KERN_ERR "%s: could not alloc bip\n", __func__);
-               return NULL;
-       }
+       /* Lower order allocations come straight from slab */
+       if (!use_bip_pool(idx))
+               bip = kmem_cache_alloc(bip_slab[idx].slab, gfp_mask);
 
-       memset(bip, 0, sizeof(*bip));
+       /* Use mempool if lower order alloc failed or max vecs were requested */
+       if (bip == NULL) {
+               bip = mempool_alloc(bs->bio_integrity_pool, gfp_mask);
 
-       iv = bvec_alloc_bs(gfp_mask, nr_vecs, &idx, integrity_bio_set);
-       if (unlikely(iv == NULL)) {
-               printk(KERN_ERR "%s: could not alloc bip_vec\n", __func__);
-               mempool_free(bip, bio_integrity_pool);
-               return NULL;
+               if (unlikely(bip == NULL)) {
+                       printk(KERN_ERR "%s: could not alloc bip\n", __func__);
+                       return NULL;
+               }
        }
 
-       bip->bip_pool = idx;
-       bip->bip_vec = iv;
+       memset(bip, 0, sizeof(*bip));
+
+       bip->bip_slab = idx;
        bip->bip_bio = bio;
        bio->bi_integrity = bip;
 
        return bip;
 }
+EXPORT_SYMBOL(bio_integrity_alloc_bioset);
+
+/**
+ * bio_integrity_alloc - Allocate integrity payload and attach it to bio
+ * @bio:       bio to attach integrity metadata to
+ * @gfp_mask:  Memory allocation mask
+ * @nr_vecs:   Number of integrity metadata scatter-gather elements
+ *
+ * Description: This function prepares a bio for attaching integrity
+ * metadata.  nr_vecs specifies the maximum number of pages containing
+ * integrity metadata that can be attached.
+ */
+struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
+                                                 gfp_t gfp_mask,
+                                                 unsigned int nr_vecs)
+{
+       return bio_integrity_alloc_bioset(bio, gfp_mask, nr_vecs, fs_bio_set);
+}
 EXPORT_SYMBOL(bio_integrity_alloc);
 
 /**
  * bio_integrity_free - Free bio integrity payload
  * @bio:       bio containing bip to be freed
+ * @bs:                bio_set this bio was allocated from
  *
  * Description: Used to free the integrity portion of a bio. Usually
  * called from bio_free().
  */
-void bio_integrity_free(struct bio *bio)
+void bio_integrity_free(struct bio *bio, struct bio_set *bs)
 {
        struct bio_integrity_payload *bip = bio->bi_integrity;
 
@@ -92,8 +150,10 @@ void bio_integrity_free(struct bio *bio)
            && bip->bip_buf != NULL)
                kfree(bip->bip_buf);
 
-       bvec_free_bs(integrity_bio_set, bip->bip_vec, bip->bip_pool);
-       mempool_free(bip, bio_integrity_pool);
+       if (use_bip_pool(bip->bip_slab))
+               mempool_free(bip, bs->bio_integrity_pool);
+       else
+               kmem_cache_free(bip_slab[bip->bip_slab].slab, bip);
 
        bio->bi_integrity = NULL;
 }
@@ -114,7 +174,7 @@ int bio_integrity_add_page(struct bio *bio, struct page *page,
        struct bio_integrity_payload *bip = bio->bi_integrity;
        struct bio_vec *iv;
 
-       if (bip->bip_vcnt >= bvec_nr_vecs(bip->bip_pool)) {
+       if (bip->bip_vcnt >= bvec_nr_vecs(bip->bip_slab)) {
                printk(KERN_ERR "%s: bip_vec full\n", __func__);
                return 0;
        }
@@ -647,8 +707,8 @@ void bio_integrity_split(struct bio *bio, struct bio_pair *bp, int sectors)
        bp->iv1 = bip->bip_vec[0];
        bp->iv2 = bip->bip_vec[0];
 
-       bp->bip1.bip_vec = &bp->iv1;
-       bp->bip2.bip_vec = &bp->iv2;
+       bp->bip1.bip_vec[0] = bp->iv1;
+       bp->bip2.bip_vec[0] = bp->iv2;
 
        bp->iv1.bv_len = sectors * bi->tuple_size;
        bp->iv2.bv_offset += sectors * bi->tuple_size;
@@ -667,17 +727,19 @@ EXPORT_SYMBOL(bio_integrity_split);
  * @bio:       New bio
  * @bio_src:   Original bio
  * @gfp_mask:  Memory allocation mask
+ * @bs:                bio_set to allocate bip from
  *
  * Description:        Called to allocate a bip when cloning a bio
  */
-int bio_integrity_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp_mask)
+int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
+                       gfp_t gfp_mask, struct bio_set *bs)
 {
        struct bio_integrity_payload *bip_src = bio_src->bi_integrity;
        struct bio_integrity_payload *bip;
 
        BUG_ON(bip_src == NULL);
 
-       bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt);
+       bip = bio_integrity_alloc_bioset(bio, gfp_mask, bip_src->bip_vcnt, bs);
 
        if (bip == NULL)
                return -EIO;
@@ -693,25 +755,43 @@ int bio_integrity_clone(struct bio *bio, struct bio *bio_src, gfp_t gfp_mask)
 }
 EXPORT_SYMBOL(bio_integrity_clone);
 
-static int __init bio_integrity_init(void)
+int bioset_integrity_create(struct bio_set *bs, int pool_size)
 {
-       kintegrityd_wq = create_workqueue("kintegrityd");
+       unsigned int max_slab = vecs_to_idx(BIO_MAX_PAGES);
+
+       bs->bio_integrity_pool =
+               mempool_create_slab_pool(pool_size, bip_slab[max_slab].slab);
 
+       if (!bs->bio_integrity_pool)
+               return -1;
+
+       return 0;
+}
+EXPORT_SYMBOL(bioset_integrity_create);
+
+void bioset_integrity_free(struct bio_set *bs)
+{
+       if (bs->bio_integrity_pool)
+               mempool_destroy(bs->bio_integrity_pool);
+}
+EXPORT_SYMBOL(bioset_integrity_free);
+
+void __init bio_integrity_init(void)
+{
+       unsigned int i;
+
+       kintegrityd_wq = create_workqueue("kintegrityd");
        if (!kintegrityd_wq)
                panic("Failed to create kintegrityd\n");
 
-       bio_integrity_slab = KMEM_CACHE(bio_integrity_payload,
-                                       SLAB_HWCACHE_ALIGN|SLAB_PANIC);
+       for (i = 0 ; i < BIOVEC_NR_POOLS ; i++) {
+               unsigned int size;
 
-       bio_integrity_pool = mempool_create_slab_pool(BIO_POOL_SIZE,
-                                                     bio_integrity_slab);
-       if (!bio_integrity_pool)
-               panic("bio_integrity: can't allocate bip pool\n");
+               size = sizeof(struct bio_integrity_payload)
+                       + bip_slab[i].nr_vecs * sizeof(struct bio_vec);
 
-       integrity_bio_set = bioset_create(BIO_POOL_SIZE, 0);
-       if (!integrity_bio_set)
-               panic("bio_integrity: can't allocate bio_set\n");
-
-       return 0;
+               bip_slab[i].slab =
+                       kmem_cache_create(bip_slab[i].name, size, 0,
+                                         SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
+       }
 }
-subsys_initcall(bio_integrity_init);
index 24c9140435323e4caabbdf00156efd0060d1be55..76738005c8e8af43c3b084a48d4f752e36e2186d 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -238,7 +238,7 @@ void bio_free(struct bio *bio, struct bio_set *bs)
                bvec_free_bs(bs, bio->bi_io_vec, BIO_POOL_IDX(bio));
 
        if (bio_integrity(bio))
-               bio_integrity_free(bio);
+               bio_integrity_free(bio, bs);
 
        /*
         * If we have front padding, adjust the bio pointer before freeing
@@ -341,7 +341,7 @@ struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs)
 static void bio_kmalloc_destructor(struct bio *bio)
 {
        if (bio_integrity(bio))
-               bio_integrity_free(bio);
+               bio_integrity_free(bio, fs_bio_set);
        kfree(bio);
 }
 
@@ -472,7 +472,7 @@ struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask)
        if (bio_integrity(bio)) {
                int ret;
 
-               ret = bio_integrity_clone(b, bio, gfp_mask);
+               ret = bio_integrity_clone(b, bio, gfp_mask, fs_bio_set);
 
                if (ret < 0) {
                        bio_put(b);
@@ -705,14 +705,13 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count,
 }
 
 static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs,
-                         struct sg_iovec *iov, int iov_count, int uncopy,
-                         int do_free_page)
+                         struct sg_iovec *iov, int iov_count,
+                         int to_user, int from_user, int do_free_page)
 {
        int ret = 0, i;
        struct bio_vec *bvec;
        int iov_idx = 0;
        unsigned int iov_off = 0;
-       int read = bio_data_dir(bio) == READ;
 
        __bio_for_each_segment(bvec, bio, i, 0) {
                char *bv_addr = page_address(bvec->bv_page);
@@ -727,13 +726,14 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs,
                        iov_addr = iov[iov_idx].iov_base + iov_off;
 
                        if (!ret) {
-                               if (!read && !uncopy)
-                                       ret = copy_from_user(bv_addr, iov_addr,
-                                                            bytes);
-                               if (read && uncopy)
+                               if (to_user)
                                        ret = copy_to_user(iov_addr, bv_addr,
                                                           bytes);
 
+                               if (from_user)
+                                       ret = copy_from_user(bv_addr, iov_addr,
+                                                            bytes);
+
                                if (ret)
                                        ret = -EFAULT;
                        }
@@ -770,7 +770,8 @@ int bio_uncopy_user(struct bio *bio)
 
        if (!bio_flagged(bio, BIO_NULL_MAPPED))
                ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs,
-                                    bmd->nr_sgvecs, 1, bmd->is_our_pages);
+                                    bmd->nr_sgvecs, bio_data_dir(bio) == READ,
+                                    0, bmd->is_our_pages);
        bio_free_map_data(bmd);
        bio_put(bio);
        return ret;
@@ -875,8 +876,9 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
        /*
         * success
         */
-       if (!write_to_vm && (!map_data || !map_data->null_mapped)) {
-               ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 0);
+       if ((!write_to_vm && (!map_data || !map_data->null_mapped)) ||
+           (map_data && map_data->from_user)) {
+               ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 1, 0);
                if (ret)
                        goto cleanup;
        }
@@ -1539,6 +1541,7 @@ void bioset_free(struct bio_set *bs)
        if (bs->bio_pool)
                mempool_destroy(bs->bio_pool);
 
+       bioset_integrity_free(bs);
        biovec_free_pools(bs);
        bio_put_slab(bs);
 
@@ -1579,6 +1582,9 @@ struct bio_set *bioset_create(unsigned int pool_size, unsigned int front_pad)
        if (!bs->bio_pool)
                goto bad;
 
+       if (bioset_integrity_create(bs, pool_size))
+               goto bad;
+
        if (!biovec_create_pools(bs, pool_size))
                return bs;
 
@@ -1616,6 +1622,7 @@ static int __init init_bio(void)
        if (!bio_slabs)
                panic("bio: can't allocate bios\n");
 
+       bio_integrity_init();
        biovec_init_slabs();
 
        fs_bio_set = bioset_create(BIO_POOL_SIZE, 0);
index 3a6d4fb2a329ceb5795bb18eec19ca71f330832b..94dfda24c06e5ea08b7df4883b640db573d137e7 100644 (file)
@@ -564,6 +564,16 @@ struct block_device *bdget(dev_t dev)
 
 EXPORT_SYMBOL(bdget);
 
+/**
+ * bdgrab -- Grab a reference to an already referenced block device
+ * @bdev:      Block device to grab a reference to.
+ */
+struct block_device *bdgrab(struct block_device *bdev)
+{
+       atomic_inc(&bdev->bd_inode->i_count);
+       return bdev;
+}
+
 long nr_blockdev_pages(void)
 {
        struct block_device *bdev;
index 7f88628a1a72e3808c6f96d47bc0ba9e363ade4c..019e8af449abfeb1679c1a20c801d6b0082edf8b 100644 (file)
@@ -299,8 +299,8 @@ int btrfs_start_workers(struct btrfs_workers *workers, int num_workers)
                                           "btrfs-%s-%d", workers->name,
                                           workers->num_workers + i);
                if (IS_ERR(worker->task)) {
-                       kfree(worker);
                        ret = PTR_ERR(worker->task);
+                       kfree(worker);
                        goto fail;
                }
 
@@ -424,11 +424,11 @@ int btrfs_requeue_work(struct btrfs_work *work)
         * list
         */
        if (worker->idle) {
-               spin_lock_irqsave(&worker->workers->lock, flags);
+               spin_lock(&worker->workers->lock);
                worker->idle = 0;
                list_move_tail(&worker->worker_list,
                               &worker->workers->worker_list);
-               spin_unlock_irqrestore(&worker->workers->lock, flags);
+               spin_unlock(&worker->workers->lock);
        }
        if (!worker->working) {
                wake = 1;
index de1e2fd32080f0c5c4a835460abf514546c7a6bf..9d8ba4d54a37c3f96e9585de46b8e99d701410bc 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/time.h>
 #include <linux/init.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/backing-dev.h>
 #include <linux/mpage.h>
 #include <linux/swap.h>
index 60a45f3a4e916fe9af5a8c644b3a8eb9b5b73f81..3fdcc0512d3ab62f95d42708ca0d6a049340b877 100644 (file)
@@ -557,19 +557,7 @@ static int comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
 
        btrfs_disk_key_to_cpu(&k1, disk);
 
-       if (k1.objectid > k2->objectid)
-               return 1;
-       if (k1.objectid < k2->objectid)
-               return -1;
-       if (k1.type > k2->type)
-               return 1;
-       if (k1.type < k2->type)
-               return -1;
-       if (k1.offset > k2->offset)
-               return 1;
-       if (k1.offset < k2->offset)
-               return -1;
-       return 0;
+       return btrfs_comp_cpu_keys(&k1, k2);
 }
 
 /*
@@ -1052,9 +1040,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
            BTRFS_NODEPTRS_PER_BLOCK(root) / 4)
                return 0;
 
-       if (btrfs_header_nritems(mid) > 2)
-               return 0;
-
        if (btrfs_header_nritems(mid) < 2)
                err_on_enospc = 1;
 
@@ -1701,6 +1686,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
        struct extent_buffer *b;
        int slot;
        int ret;
+       int err;
        int level;
        int lowest_unlock = 1;
        u8 lowest_level = 0;
@@ -1737,8 +1723,6 @@ again:
                        p->locks[level] = 1;
 
                if (cow) {
-                       int wret;
-
                        /*
                         * if we don't really need to cow this block
                         * then we don't want to set the path blocking,
@@ -1749,12 +1733,12 @@ again:
 
                        btrfs_set_path_blocking(p);
 
-                       wret = btrfs_cow_block(trans, root, b,
-                                              p->nodes[level + 1],
-                                              p->slots[level + 1], &b);
-                       if (wret) {
+                       err = btrfs_cow_block(trans, root, b,
+                                             p->nodes[level + 1],
+                                             p->slots[level + 1], &b);
+                       if (err) {
                                free_extent_buffer(b);
-                               ret = wret;
+                               ret = err;
                                goto done;
                        }
                }
@@ -1793,41 +1777,45 @@ cow_done:
                ret = bin_search(b, key, level, &slot);
 
                if (level != 0) {
-                       if (ret && slot > 0)
+                       int dec = 0;
+                       if (ret && slot > 0) {
+                               dec = 1;
                                slot -= 1;
+                       }
                        p->slots[level] = slot;
-                       ret = setup_nodes_for_search(trans, root, p, b, level,
+                       err = setup_nodes_for_search(trans, root, p, b, level,
                                                     ins_len);
-                       if (ret == -EAGAIN)
+                       if (err == -EAGAIN)
                                goto again;
-                       else if (ret)
+                       if (err) {
+                               ret = err;
                                goto done;
+                       }
                        b = p->nodes[level];
                        slot = p->slots[level];
 
                        unlock_up(p, level, lowest_unlock);
 
-                       /* this is only true while dropping a snapshot */
                        if (level == lowest_level) {
-                               ret = 0;
+                               if (dec)
+                                       p->slots[level]++;
                                goto done;
                        }
 
-                       ret = read_block_for_search(trans, root, p,
+                       err = read_block_for_search(trans, root, p,
                                                    &b, level, slot, key);
-                       if (ret == -EAGAIN)
+                       if (err == -EAGAIN)
                                goto again;
-
-                       if (ret == -EIO)
+                       if (err) {
+                               ret = err;
                                goto done;
+                       }
 
                        if (!p->skip_locking) {
-                               int lret;
-
                                btrfs_clear_path_blocking(p, NULL);
-                               lret = btrfs_try_spin_lock(b);
+                               err = btrfs_try_spin_lock(b);
 
-                               if (!lret) {
+                               if (!err) {
                                        btrfs_set_path_blocking(p);
                                        btrfs_tree_lock(b);
                                        btrfs_clear_path_blocking(p, b);
@@ -1837,16 +1825,14 @@ cow_done:
                        p->slots[level] = slot;
                        if (ins_len > 0 &&
                            btrfs_leaf_free_space(root, b) < ins_len) {
-                               int sret;
-
                                btrfs_set_path_blocking(p);
-                               sret = split_leaf(trans, root, key,
-                                                     p, ins_len, ret == 0);
+                               err = split_leaf(trans, root, key,
+                                                p, ins_len, ret == 0);
                                btrfs_clear_path_blocking(p, NULL);
 
-                               BUG_ON(sret > 0);
-                               if (sret) {
-                                       ret = sret;
+                               BUG_ON(err > 0);
+                               if (err) {
+                                       ret = err;
                                        goto done;
                                }
                        }
@@ -3807,7 +3793,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
                }
 
                /* delete the leaf if it is mostly empty */
-               if (used < BTRFS_LEAF_DATA_SIZE(root) / 2) {
+               if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) {
                        /* push_leaf_left fixes the path.
                         * make sure the path still points to our leaf
                         * for possible call to del_ptr below
@@ -4042,10 +4028,9 @@ out:
  * calling this function.
  */
 int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path,
-                       struct btrfs_key *key, int lowest_level,
+                       struct btrfs_key *key, int level,
                        int cache_only, u64 min_trans)
 {
-       int level = lowest_level;
        int slot;
        struct extent_buffer *c;
 
@@ -4058,11 +4043,40 @@ int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path,
                c = path->nodes[level];
 next:
                if (slot >= btrfs_header_nritems(c)) {
-                       level++;
-                       if (level == BTRFS_MAX_LEVEL)
+                       int ret;
+                       int orig_lowest;
+                       struct btrfs_key cur_key;
+                       if (level + 1 >= BTRFS_MAX_LEVEL ||
+                           !path->nodes[level + 1])
                                return 1;
-                       continue;
+
+                       if (path->locks[level + 1]) {
+                               level++;
+                               continue;
+                       }
+
+                       slot = btrfs_header_nritems(c) - 1;
+                       if (level == 0)
+                               btrfs_item_key_to_cpu(c, &cur_key, slot);
+                       else
+                               btrfs_node_key_to_cpu(c, &cur_key, slot);
+
+                       orig_lowest = path->lowest_level;
+                       btrfs_release_path(root, path);
+                       path->lowest_level = level;
+                       ret = btrfs_search_slot(NULL, root, &cur_key, path,
+                                               0, 0);
+                       path->lowest_level = orig_lowest;
+                       if (ret < 0)
+                               return ret;
+
+                       c = path->nodes[level];
+                       slot = path->slots[level];
+                       if (ret == 0)
+                               slot++;
+                       goto next;
                }
+
                if (level == 0)
                        btrfs_item_key_to_cpu(c, key, slot);
                else {
@@ -4146,7 +4160,8 @@ again:
         * advance the path if there are now more items available.
         */
        if (nritems > 0 && path->slots[0] < nritems - 1) {
-               path->slots[0]++;
+               if (ret == 0)
+                       path->slots[0]++;
                ret = 0;
                goto done;
        }
@@ -4278,10 +4293,10 @@ int btrfs_previous_item(struct btrfs_root *root,
                        path->slots[0]--;
 
                btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
-               if (found_key.type == type)
-                       return 0;
                if (found_key.objectid < min_objectid)
                        break;
+               if (found_key.type == type)
+                       return 0;
                if (found_key.objectid == min_objectid &&
                    found_key.type < type)
                        break;
index 2779c2f5360ac6ea4678db5e14aa135c93507b4c..837435ce84caa104dcb00ba9830df29a47e95923 100644 (file)
@@ -481,7 +481,7 @@ struct btrfs_shared_data_ref {
 
 struct btrfs_extent_inline_ref {
        u8 type;
-       u64 offset;
+       __le64 offset;
 } __attribute__ ((__packed__));
 
 /* old style backrefs item */
@@ -689,6 +689,7 @@ struct btrfs_space_info {
        struct list_head block_groups;
        spinlock_t lock;
        struct rw_semaphore groups_sem;
+       atomic_t caching_threads;
 };
 
 /*
@@ -707,6 +708,9 @@ struct btrfs_free_cluster {
        /* first extent starting offset */
        u64 window_start;
 
+       /* if this cluster simply points at a bitmap in the block group */
+       bool points_to_bitmap;
+
        struct btrfs_block_group_cache *block_group;
        /*
         * when a cluster is allocated from a block group, we put the
@@ -716,24 +720,37 @@ struct btrfs_free_cluster {
        struct list_head block_group_list;
 };
 
+enum btrfs_caching_type {
+       BTRFS_CACHE_NO          = 0,
+       BTRFS_CACHE_STARTED     = 1,
+       BTRFS_CACHE_FINISHED    = 2,
+};
+
 struct btrfs_block_group_cache {
        struct btrfs_key key;
        struct btrfs_block_group_item item;
+       struct btrfs_fs_info *fs_info;
        spinlock_t lock;
-       struct mutex cache_mutex;
        u64 pinned;
        u64 reserved;
        u64 flags;
-       int cached;
+       u64 sectorsize;
+       int extents_thresh;
+       int free_extents;
+       int total_bitmaps;
        int ro;
        int dirty;
 
+       /* cache tracking stuff */
+       wait_queue_head_t caching_q;
+       int cached;
+
        struct btrfs_space_info *space_info;
 
        /* free space cache stuff */
        spinlock_t tree_lock;
-       struct rb_root free_space_bytes;
        struct rb_root free_space_offset;
+       u64 free_space;
 
        /* block group cache stuff */
        struct rb_node cache_node;
@@ -808,6 +825,7 @@ struct btrfs_fs_info {
        struct mutex drop_mutex;
        struct mutex volume_mutex;
        struct mutex tree_reloc_mutex;
+       struct rw_semaphore extent_commit_sem;
 
        /*
         * this protects the ordered operations list only while we are
@@ -1988,6 +2006,7 @@ void btrfs_delalloc_reserve_space(struct btrfs_root *root, struct inode *inode,
                                 u64 bytes);
 void btrfs_delalloc_free_space(struct btrfs_root *root, struct inode *inode,
                              u64 bytes);
+void btrfs_free_pinned_extents(struct btrfs_fs_info *info);
 /* ctree.c */
 int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key,
                     int level, int *slot);
@@ -2074,8 +2093,7 @@ static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans,
 int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
 int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
 int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf);
-int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
-                       *root);
+int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref);
 int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root,
                        struct extent_buffer *node,
index d28d29c95f7ca23a91e9ccf3c306840484ea29ed..e83be2e4602c256f959a2b9daf0c3da2b8e9bcab 100644 (file)
@@ -1639,6 +1639,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        mutex_init(&fs_info->cleaner_mutex);
        mutex_init(&fs_info->volume_mutex);
        mutex_init(&fs_info->tree_reloc_mutex);
+       init_rwsem(&fs_info->extent_commit_sem);
 
        btrfs_init_free_cluster(&fs_info->meta_alloc_cluster);
        btrfs_init_free_cluster(&fs_info->data_alloc_cluster);
@@ -1799,6 +1800,11 @@ struct btrfs_root *open_ctree(struct super_block *sb,
                                           btrfs_super_chunk_root(disk_super),
                                           blocksize, generation);
        BUG_ON(!chunk_root->node);
+       if (!test_bit(EXTENT_BUFFER_UPTODATE, &chunk_root->node->bflags)) {
+               printk(KERN_WARNING "btrfs: failed to read chunk root on %s\n",
+                      sb->s_id);
+               goto fail_chunk_root;
+       }
        btrfs_set_root_node(&chunk_root->root_item, chunk_root->node);
        chunk_root->commit_root = btrfs_root_node(chunk_root);
 
@@ -1826,6 +1832,11 @@ struct btrfs_root *open_ctree(struct super_block *sb,
                                          blocksize, generation);
        if (!tree_root->node)
                goto fail_chunk_root;
+       if (!test_bit(EXTENT_BUFFER_UPTODATE, &tree_root->node->bflags)) {
+               printk(KERN_WARNING "btrfs: failed to read tree root on %s\n",
+                      sb->s_id);
+               goto fail_tree_root;
+       }
        btrfs_set_root_node(&tree_root->root_item, tree_root->node);
        tree_root->commit_root = btrfs_root_node(tree_root);
 
@@ -2322,6 +2333,9 @@ int close_ctree(struct btrfs_root *root)
                        printk(KERN_ERR "btrfs: commit super ret %d\n", ret);
        }
 
+       fs_info->closing = 2;
+       smp_mb();
+
        if (fs_info->delalloc_bytes) {
                printk(KERN_INFO "btrfs: at unmount delalloc count %llu\n",
                       (unsigned long long)fs_info->delalloc_bytes);
@@ -2343,6 +2357,7 @@ int close_ctree(struct btrfs_root *root)
        free_extent_buffer(root->fs_info->csum_root->commit_root);
 
        btrfs_free_block_groups(root->fs_info);
+       btrfs_free_pinned_extents(root->fs_info);
 
        del_fs_roots(fs_info);
 
index edc7d208c5ce6032fc7de520f5f4a00739755fec..72a2b9c28e9fc7a6a7aacce09469cb6414215635 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/blkdev.h>
 #include <linux/sort.h>
 #include <linux/rcupdate.h>
+#include <linux/kthread.h>
 #include "compat.h"
 #include "hash.h"
 #include "ctree.h"
@@ -61,6 +62,13 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
                          struct btrfs_root *extent_root, u64 alloc_bytes,
                          u64 flags, int force);
 
+static noinline int
+block_group_cache_done(struct btrfs_block_group_cache *cache)
+{
+       smp_mb();
+       return cache->cached == BTRFS_CACHE_FINISHED;
+}
+
 static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits)
 {
        return (cache->flags & bits) == bits;
@@ -145,21 +153,71 @@ block_group_cache_tree_search(struct btrfs_fs_info *info, u64 bytenr,
        return ret;
 }
 
+/*
+ * We always set EXTENT_LOCKED for the super mirror extents so we don't
+ * overwrite them, so those bits need to be unset.  Also, if we are unmounting
+ * with pinned extents still sitting there because we had a block group caching,
+ * we need to clear those now, since we are done.
+ */
+void btrfs_free_pinned_extents(struct btrfs_fs_info *info)
+{
+       u64 start, end, last = 0;
+       int ret;
+
+       while (1) {
+               ret = find_first_extent_bit(&info->pinned_extents, last,
+                                           &start, &end,
+                                           EXTENT_LOCKED|EXTENT_DIRTY);
+               if (ret)
+                       break;
+
+               clear_extent_bits(&info->pinned_extents, start, end,
+                                 EXTENT_LOCKED|EXTENT_DIRTY, GFP_NOFS);
+               last = end+1;
+       }
+}
+
+static int remove_sb_from_cache(struct btrfs_root *root,
+                               struct btrfs_block_group_cache *cache)
+{
+       struct btrfs_fs_info *fs_info = root->fs_info;
+       u64 bytenr;
+       u64 *logical;
+       int stripe_len;
+       int i, nr, ret;
+
+       for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
+               bytenr = btrfs_sb_offset(i);
+               ret = btrfs_rmap_block(&root->fs_info->mapping_tree,
+                                      cache->key.objectid, bytenr,
+                                      0, &logical, &nr, &stripe_len);
+               BUG_ON(ret);
+               while (nr--) {
+                       try_lock_extent(&fs_info->pinned_extents,
+                                       logical[nr],
+                                       logical[nr] + stripe_len - 1, GFP_NOFS);
+               }
+               kfree(logical);
+       }
+
+       return 0;
+}
+
 /*
  * this is only called by cache_block_group, since we could have freed extents
  * we need to check the pinned_extents for any extents that can't be used yet
  * since their free space will be released as soon as the transaction commits.
  */
-static int add_new_free_space(struct btrfs_block_group_cache *block_group,
+static u64 add_new_free_space(struct btrfs_block_group_cache *block_group,
                              struct btrfs_fs_info *info, u64 start, u64 end)
 {
-       u64 extent_start, extent_end, size;
+       u64 extent_start, extent_end, size, total_added = 0;
        int ret;
 
        while (start < end) {
                ret = find_first_extent_bit(&info->pinned_extents, start,
                                            &extent_start, &extent_end,
-                                           EXTENT_DIRTY);
+                                           EXTENT_DIRTY|EXTENT_LOCKED);
                if (ret)
                        break;
 
@@ -167,6 +225,7 @@ static int add_new_free_space(struct btrfs_block_group_cache *block_group,
                        start = extent_end + 1;
                } else if (extent_start > start && extent_start < end) {
                        size = extent_start - start;
+                       total_added += size;
                        ret = btrfs_add_free_space(block_group, start,
                                                   size);
                        BUG_ON(ret);
@@ -178,84 +237,93 @@ static int add_new_free_space(struct btrfs_block_group_cache *block_group,
 
        if (start < end) {
                size = end - start;
+               total_added += size;
                ret = btrfs_add_free_space(block_group, start, size);
                BUG_ON(ret);
        }
 
-       return 0;
+       return total_added;
 }
 
-static int remove_sb_from_cache(struct btrfs_root *root,
-                               struct btrfs_block_group_cache *cache)
-{
-       u64 bytenr;
-       u64 *logical;
-       int stripe_len;
-       int i, nr, ret;
-
-       for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
-               bytenr = btrfs_sb_offset(i);
-               ret = btrfs_rmap_block(&root->fs_info->mapping_tree,
-                                      cache->key.objectid, bytenr, 0,
-                                      &logical, &nr, &stripe_len);
-               BUG_ON(ret);
-               while (nr--) {
-                       btrfs_remove_free_space(cache, logical[nr],
-                                               stripe_len);
-               }
-               kfree(logical);
-       }
-       return 0;
-}
-
-static int cache_block_group(struct btrfs_root *root,
-                            struct btrfs_block_group_cache *block_group)
+static int caching_kthread(void *data)
 {
+       struct btrfs_block_group_cache *block_group = data;
+       struct btrfs_fs_info *fs_info = block_group->fs_info;
+       u64 last = 0;
        struct btrfs_path *path;
        int ret = 0;
        struct btrfs_key key;
        struct extent_buffer *leaf;
        int slot;
-       u64 last;
+       u64 total_found = 0;
 
-       if (!block_group)
-               return 0;
-
-       root = root->fs_info->extent_root;
-
-       if (block_group->cached)
-               return 0;
+       BUG_ON(!fs_info);
 
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
 
-       path->reada = 2;
+       atomic_inc(&block_group->space_info->caching_threads);
+       last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET);
        /*
-        * we get into deadlocks with paths held by callers of this function.
-        * since the alloc_mutex is protecting things right now, just
-        * skip the locking here
+        * We don't want to deadlock with somebody trying to allocate a new
+        * extent for the extent root while also trying to search the extent
+        * root to add free space.  So we skip locking and search the commit
+        * root, since its read-only
         */
        path->skip_locking = 1;
-       last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET);
+       path->search_commit_root = 1;
+       path->reada = 2;
+
        key.objectid = last;
        key.offset = 0;
        btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
-       ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+again:
+       /* need to make sure the commit_root doesn't disappear */
+       down_read(&fs_info->extent_commit_sem);
+
+       ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0);
        if (ret < 0)
                goto err;
 
        while (1) {
+               smp_mb();
+               if (block_group->fs_info->closing > 1) {
+                       last = (u64)-1;
+                       break;
+               }
+
                leaf = path->nodes[0];
                slot = path->slots[0];
                if (slot >= btrfs_header_nritems(leaf)) {
-                       ret = btrfs_next_leaf(root, path);
+                       ret = btrfs_next_leaf(fs_info->extent_root, path);
                        if (ret < 0)
                                goto err;
-                       if (ret == 0)
-                               continue;
-                       else
+                       else if (ret)
                                break;
+
+                       if (need_resched() ||
+                           btrfs_transaction_in_commit(fs_info)) {
+                               leaf = path->nodes[0];
+
+                               /* this shouldn't happen, but if the
+                                * leaf is empty just move on.
+                                */
+                               if (btrfs_header_nritems(leaf) == 0)
+                                       break;
+                               /*
+                                * we need to copy the key out so that
+                                * we are sure the next search advances
+                                * us forward in the btree.
+                                */
+                               btrfs_item_key_to_cpu(leaf, &key, 0);
+                               btrfs_release_path(fs_info->extent_root, path);
+                               up_read(&fs_info->extent_commit_sem);
+                               schedule_timeout(1);
+                               goto again;
+                       }
+
+                       continue;
                }
                btrfs_item_key_to_cpu(leaf, &key, slot);
                if (key.objectid < block_group->key.objectid)
@@ -266,24 +334,59 @@ static int cache_block_group(struct btrfs_root *root,
                        break;
 
                if (btrfs_key_type(&key) == BTRFS_EXTENT_ITEM_KEY) {
-                       add_new_free_space(block_group, root->fs_info, last,
-                                          key.objectid);
-
+                       total_found += add_new_free_space(block_group,
+                                                         fs_info, last,
+                                                         key.objectid);
                        last = key.objectid + key.offset;
                }
+
+               if (total_found > (1024 * 1024 * 2)) {
+                       total_found = 0;
+                       wake_up(&block_group->caching_q);
+               }
 next:
                path->slots[0]++;
        }
+       ret = 0;
 
-       add_new_free_space(block_group, root->fs_info, last,
-                          block_group->key.objectid +
-                          block_group->key.offset);
+       total_found += add_new_free_space(block_group, fs_info, last,
+                                         block_group->key.objectid +
+                                         block_group->key.offset);
+
+       spin_lock(&block_group->lock);
+       block_group->cached = BTRFS_CACHE_FINISHED;
+       spin_unlock(&block_group->lock);
 
-       block_group->cached = 1;
-       remove_sb_from_cache(root, block_group);
-       ret = 0;
 err:
        btrfs_free_path(path);
+       up_read(&fs_info->extent_commit_sem);
+       atomic_dec(&block_group->space_info->caching_threads);
+       wake_up(&block_group->caching_q);
+
+       return 0;
+}
+
+static int cache_block_group(struct btrfs_block_group_cache *cache)
+{
+       struct task_struct *tsk;
+       int ret = 0;
+
+       spin_lock(&cache->lock);
+       if (cache->cached != BTRFS_CACHE_NO) {
+               spin_unlock(&cache->lock);
+               return ret;
+       }
+       cache->cached = BTRFS_CACHE_STARTED;
+       spin_unlock(&cache->lock);
+
+       tsk = kthread_run(caching_kthread, cache, "btrfs-cache-%llu\n",
+                         cache->key.objectid);
+       if (IS_ERR(tsk)) {
+               ret = PTR_ERR(tsk);
+               printk(KERN_ERR "error running thread %d\n", ret);
+               BUG();
+       }
+
        return ret;
 }
 
@@ -990,15 +1093,13 @@ static inline int extent_ref_type(u64 parent, u64 owner)
        return type;
 }
 
-static int find_next_key(struct btrfs_path *path, struct btrfs_key *key)
+static int find_next_key(struct btrfs_path *path, int level,
+                        struct btrfs_key *key)
 
 {
-       int level;
-       BUG_ON(!path->keep_locks);
-       for (level = 0; level < BTRFS_MAX_LEVEL; level++) {
+       for (; level < BTRFS_MAX_LEVEL; level++) {
                if (!path->nodes[level])
                        break;
-               btrfs_assert_tree_locked(path->nodes[level]);
                if (path->slots[level] + 1 >=
                    btrfs_header_nritems(path->nodes[level]))
                        continue;
@@ -1158,7 +1259,8 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
                 * For simplicity, we just do not add new inline back
                 * ref if there is any kind of item for this block
                 */
-               if (find_next_key(path, &key) == 0 && key.objectid == bytenr &&
+               if (find_next_key(path, 0, &key) == 0 &&
+                   key.objectid == bytenr &&
                    key.type < BTRFS_BLOCK_GROUP_ITEM_KEY) {
                        err = -EAGAIN;
                        goto out;
@@ -2388,13 +2490,29 @@ fail:
 
 }
 
+static struct btrfs_block_group_cache *
+next_block_group(struct btrfs_root *root,
+                struct btrfs_block_group_cache *cache)
+{
+       struct rb_node *node;
+       spin_lock(&root->fs_info->block_group_cache_lock);
+       node = rb_next(&cache->cache_node);
+       btrfs_put_block_group(cache);
+       if (node) {
+               cache = rb_entry(node, struct btrfs_block_group_cache,
+                                cache_node);
+               atomic_inc(&cache->count);
+       } else
+               cache = NULL;
+       spin_unlock(&root->fs_info->block_group_cache_lock);
+       return cache;
+}
+
 int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root)
 {
-       struct btrfs_block_group_cache *cache, *entry;
-       struct rb_node *n;
+       struct btrfs_block_group_cache *cache;
        int err = 0;
-       int werr = 0;
        struct btrfs_path *path;
        u64 last = 0;
 
@@ -2403,39 +2521,35 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
                return -ENOMEM;
 
        while (1) {
-               cache = NULL;
-               spin_lock(&root->fs_info->block_group_cache_lock);
-               for (n = rb_first(&root->fs_info->block_group_cache_tree);
-                    n; n = rb_next(n)) {
-                       entry = rb_entry(n, struct btrfs_block_group_cache,
-                                        cache_node);
-                       if (entry->dirty) {
-                               cache = entry;
-                               break;
-                       }
+               if (last == 0) {
+                       err = btrfs_run_delayed_refs(trans, root,
+                                                    (unsigned long)-1);
+                       BUG_ON(err);
                }
-               spin_unlock(&root->fs_info->block_group_cache_lock);
 
-               if (!cache)
-                       break;
+               cache = btrfs_lookup_first_block_group(root->fs_info, last);
+               while (cache) {
+                       if (cache->dirty)
+                               break;
+                       cache = next_block_group(root, cache);
+               }
+               if (!cache) {
+                       if (last == 0)
+                               break;
+                       last = 0;
+                       continue;
+               }
 
                cache->dirty = 0;
-               last += cache->key.offset;
+               last = cache->key.objectid + cache->key.offset;
 
-               err = write_one_cache_group(trans, root,
-                                           path, cache);
-               /*
-                * if we fail to write the cache group, we want
-                * to keep it marked dirty in hopes that a later
-                * write will work
-                */
-               if (err) {
-                       werr = err;
-                       continue;
-               }
+               err = write_one_cache_group(trans, root, path, cache);
+               BUG_ON(err);
+               btrfs_put_block_group(cache);
        }
+
        btrfs_free_path(path);
-       return werr;
+       return 0;
 }
 
 int btrfs_extent_readonly(struct btrfs_root *root, u64 bytenr)
@@ -2485,6 +2599,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
        found->force_alloc = 0;
        *space_info = found;
        list_add_rcu(&found->list, &info->space_info);
+       atomic_set(&found->caching_threads, 0);
        return 0;
 }
 
@@ -2697,7 +2812,7 @@ again:
 
                printk(KERN_ERR "no space left, need %llu, %llu delalloc bytes"
                       ", %llu bytes_used, %llu bytes_reserved, "
-                      "%llu bytes_pinned, %llu bytes_readonly, %llu may use"
+                      "%llu bytes_pinned, %llu bytes_readonly, %llu may use "
                       "%llu total\n", (unsigned long long)bytes,
                       (unsigned long long)data_sinfo->bytes_delalloc,
                       (unsigned long long)data_sinfo->bytes_used,
@@ -2948,13 +3063,9 @@ int btrfs_update_pinned_extents(struct btrfs_root *root,
        struct btrfs_block_group_cache *cache;
        struct btrfs_fs_info *fs_info = root->fs_info;
 
-       if (pin) {
+       if (pin)
                set_extent_dirty(&fs_info->pinned_extents,
                                bytenr, bytenr + num - 1, GFP_NOFS);
-       } else {
-               clear_extent_dirty(&fs_info->pinned_extents,
-                               bytenr, bytenr + num - 1, GFP_NOFS);
-       }
 
        while (num > 0) {
                cache = btrfs_lookup_block_group(fs_info, bytenr);
@@ -2970,14 +3081,34 @@ int btrfs_update_pinned_extents(struct btrfs_root *root,
                        spin_unlock(&cache->space_info->lock);
                        fs_info->total_pinned += len;
                } else {
+                       int unpin = 0;
+
+                       /*
+                        * in order to not race with the block group caching, we
+                        * only want to unpin the extent if we are cached.  If
+                        * we aren't cached, we want to start async caching this
+                        * block group so we can free the extent the next time
+                        * around.
+                        */
                        spin_lock(&cache->space_info->lock);
                        spin_lock(&cache->lock);
-                       cache->pinned -= len;
-                       cache->space_info->bytes_pinned -= len;
+                       unpin = (cache->cached == BTRFS_CACHE_FINISHED);
+                       if (likely(unpin)) {
+                               cache->pinned -= len;
+                               cache->space_info->bytes_pinned -= len;
+                               fs_info->total_pinned -= len;
+                       }
                        spin_unlock(&cache->lock);
                        spin_unlock(&cache->space_info->lock);
-                       fs_info->total_pinned -= len;
-                       if (cache->cached)
+
+                       if (likely(unpin))
+                               clear_extent_dirty(&fs_info->pinned_extents,
+                                                  bytenr, bytenr + len -1,
+                                                  GFP_NOFS);
+                       else
+                               cache_block_group(cache);
+
+                       if (unpin)
                                btrfs_add_free_space(cache, bytenr, len);
                }
                btrfs_put_block_group(cache);
@@ -3031,6 +3162,7 @@ int btrfs_copy_pinned(struct btrfs_root *root, struct extent_io_tree *copy)
                                            &start, &end, EXTENT_DIRTY);
                if (ret)
                        break;
+
                set_extent_dirty(copy, start, end, GFP_NOFS);
                last = end + 1;
        }
@@ -3059,6 +3191,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
 
                cond_resched();
        }
+
        return ret;
 }
 
@@ -3436,6 +3569,45 @@ static u64 stripe_align(struct btrfs_root *root, u64 val)
        return ret;
 }
 
+/*
+ * when we wait for progress in the block group caching, its because
+ * our allocation attempt failed at least once.  So, we must sleep
+ * and let some progress happen before we try again.
+ *
+ * This function will sleep at least once waiting for new free space to
+ * show up, and then it will check the block group free space numbers
+ * for our min num_bytes.  Another option is to have it go ahead
+ * and look in the rbtree for a free extent of a given size, but this
+ * is a good start.
+ */
+static noinline int
+wait_block_group_cache_progress(struct btrfs_block_group_cache *cache,
+                               u64 num_bytes)
+{
+       DEFINE_WAIT(wait);
+
+       prepare_to_wait(&cache->caching_q, &wait, TASK_UNINTERRUPTIBLE);
+
+       if (block_group_cache_done(cache)) {
+               finish_wait(&cache->caching_q, &wait);
+               return 0;
+       }
+       schedule();
+       finish_wait(&cache->caching_q, &wait);
+
+       wait_event(cache->caching_q, block_group_cache_done(cache) ||
+                  (cache->free_space >= num_bytes));
+       return 0;
+}
+
+enum btrfs_loop_type {
+       LOOP_CACHED_ONLY = 0,
+       LOOP_CACHING_NOWAIT = 1,
+       LOOP_CACHING_WAIT = 2,
+       LOOP_ALLOC_CHUNK = 3,
+       LOOP_NO_EMPTY_SIZE = 4,
+};
+
 /*
  * walks the btree of allocated extents and find a hole of a given size.
  * The key ins is changed to record the hole:
@@ -3461,6 +3633,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
        struct btrfs_space_info *space_info;
        int last_ptr_loop = 0;
        int loop = 0;
+       bool found_uncached_bg = false;
 
        WARN_ON(num_bytes < root->sectorsize);
        btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY);
@@ -3492,15 +3665,18 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
        search_start = max(search_start, first_logical_byte(root, 0));
        search_start = max(search_start, hint_byte);
 
-       if (!last_ptr) {
+       if (!last_ptr)
                empty_cluster = 0;
-               loop = 1;
-       }
 
        if (search_start == hint_byte) {
                block_group = btrfs_lookup_block_group(root->fs_info,
                                                       search_start);
-               if (block_group && block_group_bits(block_group, data)) {
+               /*
+                * we don't want to use the block group if it doesn't match our
+                * allocation bits, or if its not cached.
+                */
+               if (block_group && block_group_bits(block_group, data) &&
+                   block_group_cache_done(block_group)) {
                        down_read(&space_info->groups_sem);
                        if (list_empty(&block_group->list) ||
                            block_group->ro) {
@@ -3523,21 +3699,35 @@ search:
        down_read(&space_info->groups_sem);
        list_for_each_entry(block_group, &space_info->block_groups, list) {
                u64 offset;
+               int cached;
 
                atomic_inc(&block_group->count);
                search_start = block_group->key.objectid;
 
 have_block_group:
-               if (unlikely(!block_group->cached)) {
-                       mutex_lock(&block_group->cache_mutex);
-                       ret = cache_block_group(root, block_group);
-                       mutex_unlock(&block_group->cache_mutex);
-                       if (ret) {
-                               btrfs_put_block_group(block_group);
-                               break;
+               if (unlikely(block_group->cached == BTRFS_CACHE_NO)) {
+                       /*
+                        * we want to start caching kthreads, but not too many
+                        * right off the bat so we don't overwhelm the system,
+                        * so only start them if there are less than 2 and we're
+                        * in the initial allocation phase.
+                        */
+                       if (loop > LOOP_CACHING_NOWAIT ||
+                           atomic_read(&space_info->caching_threads) < 2) {
+                               ret = cache_block_group(block_group);
+                               BUG_ON(ret);
                        }
                }
 
+               cached = block_group_cache_done(block_group);
+               if (unlikely(!cached)) {
+                       found_uncached_bg = true;
+
+                       /* if we only want cached bgs, loop */
+                       if (loop == LOOP_CACHED_ONLY)
+                               goto loop;
+               }
+
                if (unlikely(block_group->ro))
                        goto loop;
 
@@ -3616,14 +3806,21 @@ refill_cluster:
                                        spin_unlock(&last_ptr->refill_lock);
                                        goto checks;
                                }
+                       } else if (!cached && loop > LOOP_CACHING_NOWAIT) {
+                               spin_unlock(&last_ptr->refill_lock);
+
+                               wait_block_group_cache_progress(block_group,
+                                      num_bytes + empty_cluster + empty_size);
+                               goto have_block_group;
                        }
+
                        /*
                         * at this point we either didn't find a cluster
                         * or we weren't able to allocate a block from our
                         * cluster.  Free the cluster we've been trying
                         * to use, and go to the next block group
                         */
-                       if (loop < 2) {
+                       if (loop < LOOP_NO_EMPTY_SIZE) {
                                btrfs_return_cluster_to_free_space(NULL,
                                                                   last_ptr);
                                spin_unlock(&last_ptr->refill_lock);
@@ -3634,11 +3831,17 @@ refill_cluster:
 
                offset = btrfs_find_space_for_alloc(block_group, search_start,
                                                    num_bytes, empty_size);
-               if (!offset)
+               if (!offset && (cached || (!cached &&
+                                          loop == LOOP_CACHING_NOWAIT))) {
                        goto loop;
+               } else if (!offset && (!cached &&
+                                      loop > LOOP_CACHING_NOWAIT)) {
+                       wait_block_group_cache_progress(block_group,
+                                       num_bytes + empty_size);
+                       goto have_block_group;
+               }
 checks:
                search_start = stripe_align(root, offset);
-
                /* move on to the next group */
                if (search_start + num_bytes >= search_end) {
                        btrfs_add_free_space(block_group, offset, num_bytes);
@@ -3684,13 +3887,26 @@ loop:
        }
        up_read(&space_info->groups_sem);
 
-       /* loop == 0, try to find a clustered alloc in every block group
-        * loop == 1, try again after forcing a chunk allocation
-        * loop == 2, set empty_size and empty_cluster to 0 and try again
+       /* LOOP_CACHED_ONLY, only search fully cached block groups
+        * LOOP_CACHING_NOWAIT, search partially cached block groups, but
+        *                      dont wait foR them to finish caching
+        * LOOP_CACHING_WAIT, search everything, and wait if our bg is caching
+        * LOOP_ALLOC_CHUNK, force a chunk allocation and try again
+        * LOOP_NO_EMPTY_SIZE, set empty_size and empty_cluster to 0 and try
+        *                      again
         */
-       if (!ins->objectid && loop < 3 &&
-           (empty_size || empty_cluster || allowed_chunk_alloc)) {
-               if (loop >= 2) {
+       if (!ins->objectid && loop < LOOP_NO_EMPTY_SIZE &&
+           (found_uncached_bg || empty_size || empty_cluster ||
+            allowed_chunk_alloc)) {
+               if (found_uncached_bg) {
+                       found_uncached_bg = false;
+                       if (loop < LOOP_CACHING_WAIT) {
+                               loop++;
+                               goto search;
+                       }
+               }
+
+               if (loop == LOOP_ALLOC_CHUNK) {
                        empty_size = 0;
                        empty_cluster = 0;
                }
@@ -3703,7 +3919,7 @@ loop:
                        space_info->force_alloc = 1;
                }
 
-               if (loop < 3) {
+               if (loop < LOOP_NO_EMPTY_SIZE) {
                        loop++;
                        goto search;
                }
@@ -3799,7 +4015,7 @@ again:
                               num_bytes, data, 1);
                goto again;
        }
-       if (ret) {
+       if (ret == -ENOSPC) {
                struct btrfs_space_info *sinfo;
 
                sinfo = __find_space_info(root->fs_info, data);
@@ -3807,7 +4023,6 @@ again:
                       "wanted %llu\n", (unsigned long long)data,
                       (unsigned long long)num_bytes);
                dump_space_info(sinfo, num_bytes);
-               BUG();
        }
 
        return ret;
@@ -3845,7 +4060,9 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
        ret = __btrfs_reserve_extent(trans, root, num_bytes, min_alloc_size,
                                     empty_size, hint_byte, search_end, ins,
                                     data);
-       update_reserved_extents(root, ins->objectid, ins->offset, 1);
+       if (!ret)
+               update_reserved_extents(root, ins->objectid, ins->offset, 1);
+
        return ret;
 }
 
@@ -4007,9 +4224,9 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
        struct btrfs_block_group_cache *block_group;
 
        block_group = btrfs_lookup_block_group(root->fs_info, ins->objectid);
-       mutex_lock(&block_group->cache_mutex);
-       cache_block_group(root, block_group);
-       mutex_unlock(&block_group->cache_mutex);
+       cache_block_group(block_group);
+       wait_event(block_group->caching_q,
+                  block_group_cache_done(block_group));
 
        ret = btrfs_remove_free_space(block_group, ins->objectid,
                                      ins->offset);
@@ -4040,7 +4257,8 @@ static int alloc_tree_block(struct btrfs_trans_handle *trans,
        ret = __btrfs_reserve_extent(trans, root, num_bytes, num_bytes,
                                     empty_size, hint_byte, search_end,
                                     ins, 0);
-       BUG_ON(ret);
+       if (ret)
+               return ret;
 
        if (root_objectid == BTRFS_TREE_RELOC_OBJECTID) {
                if (parent == 0)
@@ -4128,6 +4346,7 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
        return buf;
 }
 
+#if 0
 int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root, struct extent_buffer *leaf)
 {
@@ -4171,8 +4390,6 @@ int btrfs_drop_leaf_ref(struct btrfs_trans_handle *trans,
        return 0;
 }
 
-#if 0
-
 static noinline int cache_drop_leaf_ref(struct btrfs_trans_handle *trans,
                                        struct btrfs_root *root,
                                        struct btrfs_leaf_ref *ref)
@@ -4553,262 +4770,471 @@ out:
 }
 #endif
 
+struct walk_control {
+       u64 refs[BTRFS_MAX_LEVEL];
+       u64 flags[BTRFS_MAX_LEVEL];
+       struct btrfs_key update_progress;
+       int stage;
+       int level;
+       int shared_level;
+       int update_ref;
+       int keep_locks;
+};
+
+#define DROP_REFERENCE 1
+#define UPDATE_BACKREF 2
+
 /*
- * helper function for drop_subtree, this function is similar to
- * walk_down_tree. The main difference is that it checks reference
- * counts while tree blocks are locked.
+ * hepler to process tree block while walking down the tree.
+ *
+ * when wc->stage == DROP_REFERENCE, this function checks
+ * reference count of the block. if the block is shared and
+ * we need update back refs for the subtree rooted at the
+ * block, this function changes wc->stage to UPDATE_BACKREF
+ *
+ * when wc->stage == UPDATE_BACKREF, this function updates
+ * back refs for pointers in the block.
+ *
+ * NOTE: return value 1 means we should stop walking down.
  */
-static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
+static noinline int walk_down_proc(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root,
-                                  struct btrfs_path *path, int *level)
+                                  struct btrfs_path *path,
+                                  struct walk_control *wc)
 {
-       struct extent_buffer *next;
-       struct extent_buffer *cur;
-       struct extent_buffer *parent;
-       u64 bytenr;
-       u64 ptr_gen;
-       u64 refs;
-       u64 flags;
-       u32 blocksize;
+       int level = wc->level;
+       struct extent_buffer *eb = path->nodes[level];
+       struct btrfs_key key;
+       u64 flag = BTRFS_BLOCK_FLAG_FULL_BACKREF;
        int ret;
 
-       cur = path->nodes[*level];
-       ret = btrfs_lookup_extent_info(trans, root, cur->start, cur->len,
-                                      &refs, &flags);
-       BUG_ON(ret);
-       if (refs > 1)
-               goto out;
+       if (wc->stage == UPDATE_BACKREF &&
+           btrfs_header_owner(eb) != root->root_key.objectid)
+               return 1;
 
-       BUG_ON(!(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF));
+       /*
+        * when reference count of tree block is 1, it won't increase
+        * again. once full backref flag is set, we never clear it.
+        */
+       if ((wc->stage == DROP_REFERENCE && wc->refs[level] != 1) ||
+           (wc->stage == UPDATE_BACKREF && !(wc->flags[level] & flag))) {
+               BUG_ON(!path->locks[level]);
+               ret = btrfs_lookup_extent_info(trans, root,
+                                              eb->start, eb->len,
+                                              &wc->refs[level],
+                                              &wc->flags[level]);
+               BUG_ON(ret);
+               BUG_ON(wc->refs[level] == 0);
+       }
 
-       while (*level >= 0) {
-               cur = path->nodes[*level];
-               if (*level == 0) {
-                       ret = btrfs_drop_leaf_ref(trans, root, cur);
-                       BUG_ON(ret);
-                       clean_tree_block(trans, root, cur);
-                       break;
-               }
-               if (path->slots[*level] >= btrfs_header_nritems(cur)) {
-                       clean_tree_block(trans, root, cur);
-                       break;
+       if (wc->stage == DROP_REFERENCE &&
+           wc->update_ref && wc->refs[level] > 1) {
+               BUG_ON(eb == root->node);
+               BUG_ON(path->slots[level] > 0);
+               if (level == 0)
+                       btrfs_item_key_to_cpu(eb, &key, path->slots[level]);
+               else
+                       btrfs_node_key_to_cpu(eb, &key, path->slots[level]);
+               if (btrfs_header_owner(eb) == root->root_key.objectid &&
+                   btrfs_comp_cpu_keys(&key, &wc->update_progress) >= 0) {
+                       wc->stage = UPDATE_BACKREF;
+                       wc->shared_level = level;
                }
+       }
 
-               bytenr = btrfs_node_blockptr(cur, path->slots[*level]);
-               blocksize = btrfs_level_size(root, *level - 1);
-               ptr_gen = btrfs_node_ptr_generation(cur, path->slots[*level]);
+       if (wc->stage == DROP_REFERENCE) {
+               if (wc->refs[level] > 1)
+                       return 1;
 
-               next = read_tree_block(root, bytenr, blocksize, ptr_gen);
-               btrfs_tree_lock(next);
-               btrfs_set_lock_blocking(next);
+               if (path->locks[level] && !wc->keep_locks) {
+                       btrfs_tree_unlock(eb);
+                       path->locks[level] = 0;
+               }
+               return 0;
+       }
 
-               ret = btrfs_lookup_extent_info(trans, root, bytenr, blocksize,
-                                              &refs, &flags);
+       /* wc->stage == UPDATE_BACKREF */
+       if (!(wc->flags[level] & flag)) {
+               BUG_ON(!path->locks[level]);
+               ret = btrfs_inc_ref(trans, root, eb, 1);
                BUG_ON(ret);
-               if (refs > 1) {
-                       parent = path->nodes[*level];
-                       ret = btrfs_free_extent(trans, root, bytenr,
-                                               blocksize, parent->start,
-                                               btrfs_header_owner(parent),
-                                               *level - 1, 0);
+               ret = btrfs_dec_ref(trans, root, eb, 0);
+               BUG_ON(ret);
+               ret = btrfs_set_disk_extent_flags(trans, root, eb->start,
+                                                 eb->len, flag, 0);
+               BUG_ON(ret);
+               wc->flags[level] |= flag;
+       }
+
+       /*
+        * the block is shared by multiple trees, so it's not good to
+        * keep the tree lock
+        */
+       if (path->locks[level] && level > 0) {
+               btrfs_tree_unlock(eb);
+               path->locks[level] = 0;
+       }
+       return 0;
+}
+
+/*
+ * hepler to process tree block while walking up the tree.
+ *
+ * when wc->stage == DROP_REFERENCE, this function drops
+ * reference count on the block.
+ *
+ * when wc->stage == UPDATE_BACKREF, this function changes
+ * wc->stage back to DROP_REFERENCE if we changed wc->stage
+ * to UPDATE_BACKREF previously while processing the block.
+ *
+ * NOTE: return value 1 means we should stop walking up.
+ */
+static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
+                                struct btrfs_root *root,
+                                struct btrfs_path *path,
+                                struct walk_control *wc)
+{
+       int ret = 0;
+       int level = wc->level;
+       struct extent_buffer *eb = path->nodes[level];
+       u64 parent = 0;
+
+       if (wc->stage == UPDATE_BACKREF) {
+               BUG_ON(wc->shared_level < level);
+               if (level < wc->shared_level)
+                       goto out;
+
+               BUG_ON(wc->refs[level] <= 1);
+               ret = find_next_key(path, level + 1, &wc->update_progress);
+               if (ret > 0)
+                       wc->update_ref = 0;
+
+               wc->stage = DROP_REFERENCE;
+               wc->shared_level = -1;
+               path->slots[level] = 0;
+
+               /*
+                * check reference count again if the block isn't locked.
+                * we should start walking down the tree again if reference
+                * count is one.
+                */
+               if (!path->locks[level]) {
+                       BUG_ON(level == 0);
+                       btrfs_tree_lock(eb);
+                       btrfs_set_lock_blocking(eb);
+                       path->locks[level] = 1;
+
+                       ret = btrfs_lookup_extent_info(trans, root,
+                                                      eb->start, eb->len,
+                                                      &wc->refs[level],
+                                                      &wc->flags[level]);
                        BUG_ON(ret);
-                       path->slots[*level]++;
-                       btrfs_tree_unlock(next);
-                       free_extent_buffer(next);
-                       continue;
+                       BUG_ON(wc->refs[level] == 0);
+                       if (wc->refs[level] == 1) {
+                               btrfs_tree_unlock(eb);
+                               path->locks[level] = 0;
+                               return 1;
+                       }
+               } else {
+                       BUG_ON(level != 0);
                }
+       }
 
-               BUG_ON(!(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF));
+       /* wc->stage == DROP_REFERENCE */
+       BUG_ON(wc->refs[level] > 1 && !path->locks[level]);
 
-               *level = btrfs_header_level(next);
-               path->nodes[*level] = next;
-               path->slots[*level] = 0;
-               path->locks[*level] = 1;
-               cond_resched();
+       if (wc->refs[level] == 1) {
+               if (level == 0) {
+                       if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF)
+                               ret = btrfs_dec_ref(trans, root, eb, 1);
+                       else
+                               ret = btrfs_dec_ref(trans, root, eb, 0);
+                       BUG_ON(ret);
+               }
+               /* make block locked assertion in clean_tree_block happy */
+               if (!path->locks[level] &&
+                   btrfs_header_generation(eb) == trans->transid) {
+                       btrfs_tree_lock(eb);
+                       btrfs_set_lock_blocking(eb);
+                       path->locks[level] = 1;
+               }
+               clean_tree_block(trans, root, eb);
        }
-out:
-       if (path->nodes[*level] == root->node)
-               parent = path->nodes[*level];
-       else
-               parent = path->nodes[*level + 1];
-       bytenr = path->nodes[*level]->start;
-       blocksize = path->nodes[*level]->len;
 
-       ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent->start,
-                               btrfs_header_owner(parent), *level, 0);
+       if (eb == root->node) {
+               if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF)
+                       parent = eb->start;
+               else
+                       BUG_ON(root->root_key.objectid !=
+                              btrfs_header_owner(eb));
+       } else {
+               if (wc->flags[level + 1] & BTRFS_BLOCK_FLAG_FULL_BACKREF)
+                       parent = path->nodes[level + 1]->start;
+               else
+                       BUG_ON(root->root_key.objectid !=
+                              btrfs_header_owner(path->nodes[level + 1]));
+       }
+
+       ret = btrfs_free_extent(trans, root, eb->start, eb->len, parent,
+                               root->root_key.objectid, level, 0);
        BUG_ON(ret);
+out:
+       wc->refs[level] = 0;
+       wc->flags[level] = 0;
+       return ret;
+}
+
+static noinline int walk_down_tree(struct btrfs_trans_handle *trans,
+                                  struct btrfs_root *root,
+                                  struct btrfs_path *path,
+                                  struct walk_control *wc)
+{
+       struct extent_buffer *next;
+       struct extent_buffer *cur;
+       u64 bytenr;
+       u64 ptr_gen;
+       u32 blocksize;
+       int level = wc->level;
+       int ret;
+
+       while (level >= 0) {
+               cur = path->nodes[level];
+               BUG_ON(path->slots[level] >= btrfs_header_nritems(cur));
+
+               ret = walk_down_proc(trans, root, path, wc);
+               if (ret > 0)
+                       break;
+
+               if (level == 0)
+                       break;
+
+               bytenr = btrfs_node_blockptr(cur, path->slots[level]);
+               blocksize = btrfs_level_size(root, level - 1);
+               ptr_gen = btrfs_node_ptr_generation(cur, path->slots[level]);
+
+               next = read_tree_block(root, bytenr, blocksize, ptr_gen);
+               btrfs_tree_lock(next);
+               btrfs_set_lock_blocking(next);
 
-       if (path->locks[*level]) {
-               btrfs_tree_unlock(path->nodes[*level]);
-               path->locks[*level] = 0;
+               level--;
+               BUG_ON(level != btrfs_header_level(next));
+               path->nodes[level] = next;
+               path->slots[level] = 0;
+               path->locks[level] = 1;
+               wc->level = level;
        }
-       free_extent_buffer(path->nodes[*level]);
-       path->nodes[*level] = NULL;
-       *level += 1;
-       cond_resched();
        return 0;
 }
 
-/*
- * helper for dropping snapshots.  This walks back up the tree in the path
- * to find the first node higher up where we haven't yet gone through
- * all the slots
- */
 static noinline int walk_up_tree(struct btrfs_trans_handle *trans,
                                 struct btrfs_root *root,
                                 struct btrfs_path *path,
-                                int *level, int max_level)
+                                struct walk_control *wc, int max_level)
 {
-       struct btrfs_root_item *root_item = &root->root_item;
-       int i;
-       int slot;
+       int level = wc->level;
        int ret;
 
-       for (i = *level; i < max_level && path->nodes[i]; i++) {
-               slot = path->slots[i];
-               if (slot + 1 < btrfs_header_nritems(path->nodes[i])) {
-                       /*
-                        * there is more work to do in this level.
-                        * Update the drop_progress marker to reflect
-                        * the work we've done so far, and then bump
-                        * the slot number
-                        */
-                       path->slots[i]++;
-                       WARN_ON(*level == 0);
-                       if (max_level == BTRFS_MAX_LEVEL) {
-                               btrfs_node_key(path->nodes[i],
-                                              &root_item->drop_progress,
-                                              path->slots[i]);
-                               root_item->drop_level = i;
-                       }
-                       *level = i;
+       path->slots[level] = btrfs_header_nritems(path->nodes[level]);
+       while (level < max_level && path->nodes[level]) {
+               wc->level = level;
+               if (path->slots[level] + 1 <
+                   btrfs_header_nritems(path->nodes[level])) {
+                       path->slots[level]++;
                        return 0;
                } else {
-                       struct extent_buffer *parent;
-
-                       /*
-                        * this whole node is done, free our reference
-                        * on it and go up one level
-                        */
-                       if (path->nodes[*level] == root->node)
-                               parent = path->nodes[*level];
-                       else
-                               parent = path->nodes[*level + 1];
+                       ret = walk_up_proc(trans, root, path, wc);
+                       if (ret > 0)
+                               return 0;
 
-                       clean_tree_block(trans, root, path->nodes[i]);
-                       ret = btrfs_free_extent(trans, root,
-                                               path->nodes[i]->start,
-                                               path->nodes[i]->len,
-                                               parent->start,
-                                               btrfs_header_owner(parent),
-                                               *level, 0);
-                       BUG_ON(ret);
-                       if (path->locks[*level]) {
-                               btrfs_tree_unlock(path->nodes[i]);
-                               path->locks[i] = 0;
+                       if (path->locks[level]) {
+                               btrfs_tree_unlock(path->nodes[level]);
+                               path->locks[level] = 0;
                        }
-                       free_extent_buffer(path->nodes[i]);
-                       path->nodes[i] = NULL;
-                       *level = i + 1;
+                       free_extent_buffer(path->nodes[level]);
+                       path->nodes[level] = NULL;
+                       level++;
                }
        }
        return 1;
 }
 
 /*
- * drop the reference count on the tree rooted at 'snap'.  This traverses
- * the tree freeing any blocks that have a ref count of zero after being
- * decremented.
+ * drop a subvolume tree.
+ *
+ * this function traverses the tree freeing any blocks that only
+ * referenced by the tree.
+ *
+ * when a shared tree block is found. this function decreases its
+ * reference count by one. if update_ref is true, this function
+ * also make sure backrefs for the shared block and all lower level
+ * blocks are properly updated.
  */
-int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
-                       *root)
+int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref)
 {
-       int ret = 0;
-       int wret;
-       int level;
        struct btrfs_path *path;
-       int update_count;
+       struct btrfs_trans_handle *trans;
+       struct btrfs_root *tree_root = root->fs_info->tree_root;
        struct btrfs_root_item *root_item = &root->root_item;
+       struct walk_control *wc;
+       struct btrfs_key key;
+       int err = 0;
+       int ret;
+       int level;
 
        path = btrfs_alloc_path();
        BUG_ON(!path);
 
-       level = btrfs_header_level(root->node);
+       wc = kzalloc(sizeof(*wc), GFP_NOFS);
+       BUG_ON(!wc);
+
+       trans = btrfs_start_transaction(tree_root, 1);
+
        if (btrfs_disk_key_objectid(&root_item->drop_progress) == 0) {
+               level = btrfs_header_level(root->node);
                path->nodes[level] = btrfs_lock_root_node(root);
                btrfs_set_lock_blocking(path->nodes[level]);
                path->slots[level] = 0;
                path->locks[level] = 1;
+               memset(&wc->update_progress, 0,
+                      sizeof(wc->update_progress));
        } else {
-               struct btrfs_key key;
-               struct btrfs_disk_key found_key;
-               struct extent_buffer *node;
-
                btrfs_disk_key_to_cpu(&key, &root_item->drop_progress);
+               memcpy(&wc->update_progress, &key,
+                      sizeof(wc->update_progress));
+
                level = root_item->drop_level;
+               BUG_ON(level == 0);
                path->lowest_level = level;
-               wret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
-               if (wret < 0) {
-                       ret = wret;
+               ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+               path->lowest_level = 0;
+               if (ret < 0) {
+                       err = ret;
                        goto out;
                }
-               node = path->nodes[level];
-               btrfs_node_key(node, &found_key, path->slots[level]);
-               WARN_ON(memcmp(&found_key, &root_item->drop_progress,
-                              sizeof(found_key)));
+               btrfs_node_key_to_cpu(path->nodes[level], &key,
+                                     path->slots[level]);
+               WARN_ON(memcmp(&key, &wc->update_progress, sizeof(key)));
+
                /*
                 * unlock our path, this is safe because only this
                 * function is allowed to delete this snapshot
                 */
                btrfs_unlock_up_safe(path, 0);
+
+               level = btrfs_header_level(root->node);
+               while (1) {
+                       btrfs_tree_lock(path->nodes[level]);
+                       btrfs_set_lock_blocking(path->nodes[level]);
+
+                       ret = btrfs_lookup_extent_info(trans, root,
+                                               path->nodes[level]->start,
+                                               path->nodes[level]->len,
+                                               &wc->refs[level],
+                                               &wc->flags[level]);
+                       BUG_ON(ret);
+                       BUG_ON(wc->refs[level] == 0);
+
+                       if (level == root_item->drop_level)
+                               break;
+
+                       btrfs_tree_unlock(path->nodes[level]);
+                       WARN_ON(wc->refs[level] != 1);
+                       level--;
+               }
        }
+
+       wc->level = level;
+       wc->shared_level = -1;
+       wc->stage = DROP_REFERENCE;
+       wc->update_ref = update_ref;
+       wc->keep_locks = 0;
+
        while (1) {
-               unsigned long update;
-               wret = walk_down_tree(trans, root, path, &level);
-               if (wret > 0)
+               ret = walk_down_tree(trans, root, path, wc);
+               if (ret < 0) {
+                       err = ret;
                        break;
-               if (wret < 0)
-                       ret = wret;
+               }
 
-               wret = walk_up_tree(trans, root, path, &level,
-                                   BTRFS_MAX_LEVEL);
-               if (wret > 0)
+               ret = walk_up_tree(trans, root, path, wc, BTRFS_MAX_LEVEL);
+               if (ret < 0) {
+                       err = ret;
                        break;
-               if (wret < 0)
-                       ret = wret;
-               if (trans->transaction->in_commit ||
-                   trans->transaction->delayed_refs.flushing) {
-                       ret = -EAGAIN;
+               }
+
+               if (ret > 0) {
+                       BUG_ON(wc->stage != DROP_REFERENCE);
                        break;
                }
-               for (update_count = 0; update_count < 16; update_count++) {
+
+               if (wc->stage == DROP_REFERENCE) {
+                       level = wc->level;
+                       btrfs_node_key(path->nodes[level],
+                                      &root_item->drop_progress,
+                                      path->slots[level]);
+                       root_item->drop_level = level;
+               }
+
+               BUG_ON(wc->level == 0);
+               if (trans->transaction->in_commit ||
+                   trans->transaction->delayed_refs.flushing) {
+                       ret = btrfs_update_root(trans, tree_root,
+                                               &root->root_key,
+                                               root_item);
+                       BUG_ON(ret);
+
+                       btrfs_end_transaction(trans, tree_root);
+                       trans = btrfs_start_transaction(tree_root, 1);
+               } else {
+                       unsigned long update;
                        update = trans->delayed_ref_updates;
                        trans->delayed_ref_updates = 0;
                        if (update)
-                               btrfs_run_delayed_refs(trans, root, update);
-                       else
-                               break;
+                               btrfs_run_delayed_refs(trans, tree_root,
+                                                      update);
                }
        }
+       btrfs_release_path(root, path);
+       BUG_ON(err);
+
+       ret = btrfs_del_root(trans, tree_root, &root->root_key);
+       BUG_ON(ret);
+
+       free_extent_buffer(root->node);
+       free_extent_buffer(root->commit_root);
+       kfree(root);
 out:
+       btrfs_end_transaction(trans, tree_root);
+       kfree(wc);
        btrfs_free_path(path);
-       return ret;
+       return err;
 }
 
+/*
+ * drop subtree rooted at tree block 'node'.
+ *
+ * NOTE: this function will unlock and release tree block 'node'
+ */
 int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root,
                        struct extent_buffer *node,
                        struct extent_buffer *parent)
 {
        struct btrfs_path *path;
+       struct walk_control *wc;
        int level;
        int parent_level;
        int ret = 0;
        int wret;
 
+       BUG_ON(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID);
+
        path = btrfs_alloc_path();
        BUG_ON(!path);
 
+       wc = kzalloc(sizeof(*wc), GFP_NOFS);
+       BUG_ON(!wc);
+
        btrfs_assert_tree_locked(parent);
        parent_level = btrfs_header_level(parent);
        extent_buffer_get(parent);
@@ -4817,24 +5243,33 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
 
        btrfs_assert_tree_locked(node);
        level = btrfs_header_level(node);
-       extent_buffer_get(node);
        path->nodes[level] = node;
        path->slots[level] = 0;
+       path->locks[level] = 1;
+
+       wc->refs[parent_level] = 1;
+       wc->flags[parent_level] = BTRFS_BLOCK_FLAG_FULL_BACKREF;
+       wc->level = level;
+       wc->shared_level = -1;
+       wc->stage = DROP_REFERENCE;
+       wc->update_ref = 0;
+       wc->keep_locks = 1;
 
        while (1) {
-               wret = walk_down_tree(trans, root, path, &level);
-               if (wret < 0)
+               wret = walk_down_tree(trans, root, path, wc);
+               if (wret < 0) {
                        ret = wret;
-               if (wret != 0)
                        break;
+               }
 
-               wret = walk_up_tree(trans, root, path, &level, parent_level);
+               wret = walk_up_tree(trans, root, path, wc, parent_level);
                if (wret < 0)
                        ret = wret;
                if (wret != 0)
                        break;
        }
 
+       kfree(wc);
        btrfs_free_path(path);
        return ret;
 }
@@ -6739,11 +7174,16 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
                         &info->block_group_cache_tree);
                spin_unlock(&info->block_group_cache_lock);
 
-               btrfs_remove_free_space_cache(block_group);
                down_write(&block_group->space_info->groups_sem);
                list_del(&block_group->list);
                up_write(&block_group->space_info->groups_sem);
 
+               if (block_group->cached == BTRFS_CACHE_STARTED)
+                       wait_event(block_group->caching_q,
+                                  block_group_cache_done(block_group));
+
+               btrfs_remove_free_space_cache(block_group);
+
                WARN_ON(atomic_read(&block_group->count) != 1);
                kfree(block_group);
 
@@ -6809,9 +7249,19 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                atomic_set(&cache->count, 1);
                spin_lock_init(&cache->lock);
                spin_lock_init(&cache->tree_lock);
-               mutex_init(&cache->cache_mutex);
+               cache->fs_info = info;
+               init_waitqueue_head(&cache->caching_q);
                INIT_LIST_HEAD(&cache->list);
                INIT_LIST_HEAD(&cache->cluster_list);
+
+               /*
+                * we only want to have 32k of ram per block group for keeping
+                * track of free space, and if we pass 1/2 of that we want to
+                * start converting things over to using bitmaps
+                */
+               cache->extents_thresh = ((1024 * 32) / 2) /
+                       sizeof(struct btrfs_free_space);
+
                read_extent_buffer(leaf, &cache->item,
                                   btrfs_item_ptr_offset(leaf, path->slots[0]),
                                   sizeof(cache->item));
@@ -6820,6 +7270,26 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                key.objectid = found_key.objectid + found_key.offset;
                btrfs_release_path(root, path);
                cache->flags = btrfs_block_group_flags(&cache->item);
+               cache->sectorsize = root->sectorsize;
+
+               remove_sb_from_cache(root, cache);
+
+               /*
+                * check for two cases, either we are full, and therefore
+                * don't need to bother with the caching work since we won't
+                * find any space, or we are empty, and we can just add all
+                * the space in and be done with it.  This saves us _alot_ of
+                * time, particularly in the full case.
+                */
+               if (found_key.offset == btrfs_block_group_used(&cache->item)) {
+                       cache->cached = BTRFS_CACHE_FINISHED;
+               } else if (btrfs_block_group_used(&cache->item) == 0) {
+                       cache->cached = BTRFS_CACHE_FINISHED;
+                       add_new_free_space(cache, root->fs_info,
+                                          found_key.objectid,
+                                          found_key.objectid +
+                                          found_key.offset);
+               }
 
                ret = update_space_info(info, cache->flags, found_key.offset,
                                        btrfs_block_group_used(&cache->item),
@@ -6863,10 +7333,19 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
        cache->key.objectid = chunk_offset;
        cache->key.offset = size;
        cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
+       cache->sectorsize = root->sectorsize;
+
+       /*
+        * we only want to have 32k of ram per block group for keeping track
+        * of free space, and if we pass 1/2 of that we want to start
+        * converting things over to using bitmaps
+        */
+       cache->extents_thresh = ((1024 * 32) / 2) /
+               sizeof(struct btrfs_free_space);
        atomic_set(&cache->count, 1);
        spin_lock_init(&cache->lock);
        spin_lock_init(&cache->tree_lock);
-       mutex_init(&cache->cache_mutex);
+       init_waitqueue_head(&cache->caching_q);
        INIT_LIST_HEAD(&cache->list);
        INIT_LIST_HEAD(&cache->cluster_list);
 
@@ -6875,6 +7354,12 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
        cache->flags = type;
        btrfs_set_block_group_flags(&cache->item, type);
 
+       cache->cached = BTRFS_CACHE_FINISHED;
+       remove_sb_from_cache(root, cache);
+
+       add_new_free_space(cache, root->fs_info, chunk_offset,
+                          chunk_offset + size);
+
        ret = update_space_info(root->fs_info, cache->flags, size, bytes_used,
                                &cache->space_info);
        BUG_ON(ret);
@@ -6933,7 +7418,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
        rb_erase(&block_group->cache_node,
                 &root->fs_info->block_group_cache_tree);
        spin_unlock(&root->fs_info->block_group_cache_lock);
-       btrfs_remove_free_space_cache(block_group);
+
        down_write(&block_group->space_info->groups_sem);
        /*
         * we must use list_del_init so people can check to see if they
@@ -6942,11 +7427,18 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
        list_del_init(&block_group->list);
        up_write(&block_group->space_info->groups_sem);
 
+       if (block_group->cached == BTRFS_CACHE_STARTED)
+               wait_event(block_group->caching_q,
+                          block_group_cache_done(block_group));
+
+       btrfs_remove_free_space_cache(block_group);
+
        spin_lock(&block_group->space_info->lock);
        block_group->space_info->total_bytes -= block_group->key.offset;
        block_group->space_info->bytes_readonly -= block_group->key.offset;
        spin_unlock(&block_group->space_info->lock);
-       block_group->space_info->full = 0;
+
+       btrfs_clear_space_info_full(root->fs_info);
 
        btrfs_put_block_group(block_group);
        btrfs_put_block_group(block_group);
index 126477eaecf56f074a03581c17079d6b985caa81..4b833972273a75218eb775cf8caf64dc1be80ed7 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/time.h>
 #include <linux/init.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/backing-dev.h>
 #include <linux/mpage.h>
 #include <linux/swap.h>
@@ -151,7 +150,10 @@ static noinline int dirty_and_release_pages(struct btrfs_trans_handle *trans,
        }
        if (end_pos > isize) {
                i_size_write(inode, end_pos);
-               btrfs_update_inode(trans, root, inode);
+               /* we've only changed i_size in ram, and we haven't updated
+                * the disk i_size.  There is no need to log the inode
+                * at this time.
+                */
        }
        err = btrfs_end_transaction(trans, root);
 out_unlock:
index 4538e48581a5171b33af2d3d2c632dbff4e412e2..5edcee3a617f44e4608cefd709a6e8d7c38e14a5 100644 (file)
  * Boston, MA 021110-1307, USA.
  */
 
+#include <linux/pagemap.h>
 #include <linux/sched.h>
+#include <linux/math64.h>
 #include "ctree.h"
 #include "free-space-cache.h"
 #include "transaction.h"
 
-struct btrfs_free_space {
-       struct rb_node bytes_index;
-       struct rb_node offset_index;
-       u64 offset;
-       u64 bytes;
-};
+#define BITS_PER_BITMAP                (PAGE_CACHE_SIZE * 8)
+#define MAX_CACHE_BYTES_PER_GIG        (32 * 1024)
 
-static int tree_insert_offset(struct rb_root *root, u64 offset,
-                             struct rb_node *node)
+static inline unsigned long offset_to_bit(u64 bitmap_start, u64 sectorsize,
+                                         u64 offset)
 {
-       struct rb_node **p = &root->rb_node;
-       struct rb_node *parent = NULL;
-       struct btrfs_free_space *info;
+       BUG_ON(offset < bitmap_start);
+       offset -= bitmap_start;
+       return (unsigned long)(div64_u64(offset, sectorsize));
+}
 
-       while (*p) {
-               parent = *p;
-               info = rb_entry(parent, struct btrfs_free_space, offset_index);
+static inline unsigned long bytes_to_bits(u64 bytes, u64 sectorsize)
+{
+       return (unsigned long)(div64_u64(bytes, sectorsize));
+}
 
-               if (offset < info->offset)
-                       p = &(*p)->rb_left;
-               else if (offset > info->offset)
-                       p = &(*p)->rb_right;
-               else
-                       return -EEXIST;
-       }
+static inline u64 offset_to_bitmap(struct btrfs_block_group_cache *block_group,
+                                  u64 offset)
+{
+       u64 bitmap_start;
+       u64 bytes_per_bitmap;
 
-       rb_link_node(node, parent, p);
-       rb_insert_color(node, root);
+       bytes_per_bitmap = BITS_PER_BITMAP * block_group->sectorsize;
+       bitmap_start = offset - block_group->key.objectid;
+       bitmap_start = div64_u64(bitmap_start, bytes_per_bitmap);
+       bitmap_start *= bytes_per_bitmap;
+       bitmap_start += block_group->key.objectid;
 
-       return 0;
+       return bitmap_start;
 }
 
-static int tree_insert_bytes(struct rb_root *root, u64 bytes,
-                            struct rb_node *node)
+static int tree_insert_offset(struct rb_root *root, u64 offset,
+                             struct rb_node *node, int bitmap)
 {
        struct rb_node **p = &root->rb_node;
        struct rb_node *parent = NULL;
@@ -62,12 +63,34 @@ static int tree_insert_bytes(struct rb_root *root, u64 bytes,
 
        while (*p) {
                parent = *p;
-               info = rb_entry(parent, struct btrfs_free_space, bytes_index);
+               info = rb_entry(parent, struct btrfs_free_space, offset_index);
 
-               if (bytes < info->bytes)
+               if (offset < info->offset) {
                        p = &(*p)->rb_left;
-               else
+               } else if (offset > info->offset) {
                        p = &(*p)->rb_right;
+               } else {
+                       /*
+                        * we could have a bitmap entry and an extent entry
+                        * share the same offset.  If this is the case, we want
+                        * the extent entry to always be found first if we do a
+                        * linear search through the tree, since we want to have
+                        * the quickest allocation time, and allocating from an
+                        * extent is faster than allocating from a bitmap.  So
+                        * if we're inserting a bitmap and we find an entry at
+                        * this offset, we want to go right, or after this entry
+                        * logically.  If we are inserting an extent and we've
+                        * found a bitmap, we want to go left, or before
+                        * logically.
+                        */
+                       if (bitmap) {
+                               WARN_ON(info->bitmap);
+                               p = &(*p)->rb_right;
+                       } else {
+                               WARN_ON(!info->bitmap);
+                               p = &(*p)->rb_left;
+                       }
+               }
        }
 
        rb_link_node(node, parent, p);
@@ -79,110 +102,143 @@ static int tree_insert_bytes(struct rb_root *root, u64 bytes,
 /*
  * searches the tree for the given offset.
  *
- * fuzzy == 1: this is used for allocations where we are given a hint of where
- * to look for free space.  Because the hint may not be completely on an offset
- * mark, or the hint may no longer point to free space we need to fudge our
- * results a bit.  So we look for free space starting at or after offset with at
- * least bytes size.  We prefer to find as close to the given offset as we can.
- * Also if the offset is within a free space range, then we will return the free
- * space that contains the given offset, which means we can return a free space
- * chunk with an offset before the provided offset.
- *
- * fuzzy == 0: this is just a normal tree search.  Give us the free space that
- * starts at the given offset which is at least bytes size, and if its not there
- * return NULL.
+ * fuzzy - If this is set, then we are trying to make an allocation, and we just
+ * want a section that has at least bytes size and comes at or after the given
+ * offset.
  */
-static struct btrfs_free_space *tree_search_offset(struct rb_root *root,
-                                                  u64 offset, u64 bytes,
-                                                  int fuzzy)
+static struct btrfs_free_space *
+tree_search_offset(struct btrfs_block_group_cache *block_group,
+                  u64 offset, int bitmap_only, int fuzzy)
 {
-       struct rb_node *n = root->rb_node;
-       struct btrfs_free_space *entry, *ret = NULL;
+       struct rb_node *n = block_group->free_space_offset.rb_node;
+       struct btrfs_free_space *entry, *prev = NULL;
+
+       /* find entry that is closest to the 'offset' */
+       while (1) {
+               if (!n) {
+                       entry = NULL;
+                       break;
+               }
 
-       while (n) {
                entry = rb_entry(n, struct btrfs_free_space, offset_index);
+               prev = entry;
 
-               if (offset < entry->offset) {
-                       if (fuzzy &&
-                           (!ret || entry->offset < ret->offset) &&
-                           (bytes <= entry->bytes))
-                               ret = entry;
+               if (offset < entry->offset)
                        n = n->rb_left;
-               } else if (offset > entry->offset) {
-                       if (fuzzy &&
-                           (entry->offset + entry->bytes - 1) >= offset &&
-                           bytes <= entry->bytes) {
-                               ret = entry;
-                               break;
-                       }
+               else if (offset > entry->offset)
                        n = n->rb_right;
-               } else {
-                       if (bytes > entry->bytes) {
-                               n = n->rb_right;
-                               continue;
-                       }
-                       ret = entry;
+               else
                        break;
-               }
        }
 
-       return ret;
-}
+       if (bitmap_only) {
+               if (!entry)
+                       return NULL;
+               if (entry->bitmap)
+                       return entry;
 
-/*
- * return a chunk at least bytes size, as close to offset that we can get.
- */
-static struct btrfs_free_space *tree_search_bytes(struct rb_root *root,
-                                                 u64 offset, u64 bytes)
-{
-       struct rb_node *n = root->rb_node;
-       struct btrfs_free_space *entry, *ret = NULL;
-
-       while (n) {
-               entry = rb_entry(n, struct btrfs_free_space, bytes_index);
+               /*
+                * bitmap entry and extent entry may share same offset,
+                * in that case, bitmap entry comes after extent entry.
+                */
+               n = rb_next(n);
+               if (!n)
+                       return NULL;
+               entry = rb_entry(n, struct btrfs_free_space, offset_index);
+               if (entry->offset != offset)
+                       return NULL;
 
-               if (bytes < entry->bytes) {
+               WARN_ON(!entry->bitmap);
+               return entry;
+       } else if (entry) {
+               if (entry->bitmap) {
                        /*
-                        * We prefer to get a hole size as close to the size we
-                        * are asking for so we don't take small slivers out of
-                        * huge holes, but we also want to get as close to the
-                        * offset as possible so we don't have a whole lot of
-                        * fragmentation.
+                        * if previous extent entry covers the offset,
+                        * we should return it instead of the bitmap entry
                         */
-                       if (offset <= entry->offset) {
-                               if (!ret)
-                                       ret = entry;
-                               else if (entry->bytes < ret->bytes)
-                                       ret = entry;
-                               else if (entry->offset < ret->offset)
-                                       ret = entry;
+                       n = &entry->offset_index;
+                       while (1) {
+                               n = rb_prev(n);
+                               if (!n)
+                                       break;
+                               prev = rb_entry(n, struct btrfs_free_space,
+                                               offset_index);
+                               if (!prev->bitmap) {
+                                       if (prev->offset + prev->bytes > offset)
+                                               entry = prev;
+                                       break;
+                               }
                        }
-                       n = n->rb_left;
-               } else if (bytes > entry->bytes) {
-                       n = n->rb_right;
+               }
+               return entry;
+       }
+
+       if (!prev)
+               return NULL;
+
+       /* find last entry before the 'offset' */
+       entry = prev;
+       if (entry->offset > offset) {
+               n = rb_prev(&entry->offset_index);
+               if (n) {
+                       entry = rb_entry(n, struct btrfs_free_space,
+                                       offset_index);
+                       BUG_ON(entry->offset > offset);
                } else {
-                       /*
-                        * Ok we may have multiple chunks of the wanted size,
-                        * so we don't want to take the first one we find, we
-                        * want to take the one closest to our given offset, so
-                        * keep searching just in case theres a better match.
-                        */
-                       n = n->rb_right;
-                       if (offset > entry->offset)
-                               continue;
-                       else if (!ret || entry->offset < ret->offset)
-                               ret = entry;
+                       if (fuzzy)
+                               return entry;
+                       else
+                               return NULL;
                }
        }
 
-       return ret;
+       if (entry->bitmap) {
+               n = &entry->offset_index;
+               while (1) {
+                       n = rb_prev(n);
+                       if (!n)
+                               break;
+                       prev = rb_entry(n, struct btrfs_free_space,
+                                       offset_index);
+                       if (!prev->bitmap) {
+                               if (prev->offset + prev->bytes > offset)
+                                       return prev;
+                               break;
+                       }
+               }
+               if (entry->offset + BITS_PER_BITMAP *
+                   block_group->sectorsize > offset)
+                       return entry;
+       } else if (entry->offset + entry->bytes > offset)
+               return entry;
+
+       if (!fuzzy)
+               return NULL;
+
+       while (1) {
+               if (entry->bitmap) {
+                       if (entry->offset + BITS_PER_BITMAP *
+                           block_group->sectorsize > offset)
+                               break;
+               } else {
+                       if (entry->offset + entry->bytes > offset)
+                               break;
+               }
+
+               n = rb_next(&entry->offset_index);
+               if (!n)
+                       return NULL;
+               entry = rb_entry(n, struct btrfs_free_space, offset_index);
+       }
+       return entry;
 }
 
 static void unlink_free_space(struct btrfs_block_group_cache *block_group,
                              struct btrfs_free_space *info)
 {
        rb_erase(&info->offset_index, &block_group->free_space_offset);
-       rb_erase(&info->bytes_index, &block_group->free_space_bytes);
+       block_group->free_extents--;
+       block_group->free_space -= info->bytes;
 }
 
 static int link_free_space(struct btrfs_block_group_cache *block_group,
@@ -190,17 +246,353 @@ static int link_free_space(struct btrfs_block_group_cache *block_group,
 {
        int ret = 0;
 
-
-       BUG_ON(!info->bytes);
+       BUG_ON(!info->bitmap && !info->bytes);
        ret = tree_insert_offset(&block_group->free_space_offset, info->offset,
-                                &info->offset_index);
+                                &info->offset_index, (info->bitmap != NULL));
        if (ret)
                return ret;
 
-       ret = tree_insert_bytes(&block_group->free_space_bytes, info->bytes,
-                               &info->bytes_index);
-       if (ret)
-               return ret;
+       block_group->free_space += info->bytes;
+       block_group->free_extents++;
+       return ret;
+}
+
+static void recalculate_thresholds(struct btrfs_block_group_cache *block_group)
+{
+       u64 max_bytes, possible_bytes;
+
+       /*
+        * The goal is to keep the total amount of memory used per 1gb of space
+        * at or below 32k, so we need to adjust how much memory we allow to be
+        * used by extent based free space tracking
+        */
+       max_bytes = MAX_CACHE_BYTES_PER_GIG *
+               (div64_u64(block_group->key.offset, 1024 * 1024 * 1024));
+
+       possible_bytes = (block_group->total_bitmaps * PAGE_CACHE_SIZE) +
+               (sizeof(struct btrfs_free_space) *
+                block_group->extents_thresh);
+
+       if (possible_bytes > max_bytes) {
+               int extent_bytes = max_bytes -
+                       (block_group->total_bitmaps * PAGE_CACHE_SIZE);
+
+               if (extent_bytes <= 0) {
+                       block_group->extents_thresh = 0;
+                       return;
+               }
+
+               block_group->extents_thresh = extent_bytes /
+                       (sizeof(struct btrfs_free_space));
+       }
+}
+
+static void bitmap_clear_bits(struct btrfs_block_group_cache *block_group,
+                             struct btrfs_free_space *info, u64 offset,
+                             u64 bytes)
+{
+       unsigned long start, end;
+       unsigned long i;
+
+       start = offset_to_bit(info->offset, block_group->sectorsize, offset);
+       end = start + bytes_to_bits(bytes, block_group->sectorsize);
+       BUG_ON(end > BITS_PER_BITMAP);
+
+       for (i = start; i < end; i++)
+               clear_bit(i, info->bitmap);
+
+       info->bytes -= bytes;
+       block_group->free_space -= bytes;
+}
+
+static void bitmap_set_bits(struct btrfs_block_group_cache *block_group,
+                           struct btrfs_free_space *info, u64 offset,
+                           u64 bytes)
+{
+       unsigned long start, end;
+       unsigned long i;
+
+       start = offset_to_bit(info->offset, block_group->sectorsize, offset);
+       end = start + bytes_to_bits(bytes, block_group->sectorsize);
+       BUG_ON(end > BITS_PER_BITMAP);
+
+       for (i = start; i < end; i++)
+               set_bit(i, info->bitmap);
+
+       info->bytes += bytes;
+       block_group->free_space += bytes;
+}
+
+static int search_bitmap(struct btrfs_block_group_cache *block_group,
+                        struct btrfs_free_space *bitmap_info, u64 *offset,
+                        u64 *bytes)
+{
+       unsigned long found_bits = 0;
+       unsigned long bits, i;
+       unsigned long next_zero;
+
+       i = offset_to_bit(bitmap_info->offset, block_group->sectorsize,
+                         max_t(u64, *offset, bitmap_info->offset));
+       bits = bytes_to_bits(*bytes, block_group->sectorsize);
+
+       for (i = find_next_bit(bitmap_info->bitmap, BITS_PER_BITMAP, i);
+            i < BITS_PER_BITMAP;
+            i = find_next_bit(bitmap_info->bitmap, BITS_PER_BITMAP, i + 1)) {
+               next_zero = find_next_zero_bit(bitmap_info->bitmap,
+                                              BITS_PER_BITMAP, i);
+               if ((next_zero - i) >= bits) {
+                       found_bits = next_zero - i;
+                       break;
+               }
+               i = next_zero;
+       }
+
+       if (found_bits) {
+               *offset = (u64)(i * block_group->sectorsize) +
+                       bitmap_info->offset;
+               *bytes = (u64)(found_bits) * block_group->sectorsize;
+               return 0;
+       }
+
+       return -1;
+}
+
+static struct btrfs_free_space *find_free_space(struct btrfs_block_group_cache
+                                               *block_group, u64 *offset,
+                                               u64 *bytes, int debug)
+{
+       struct btrfs_free_space *entry;
+       struct rb_node *node;
+       int ret;
+
+       if (!block_group->free_space_offset.rb_node)
+               return NULL;
+
+       entry = tree_search_offset(block_group,
+                                  offset_to_bitmap(block_group, *offset),
+                                  0, 1);
+       if (!entry)
+               return NULL;
+
+       for (node = &entry->offset_index; node; node = rb_next(node)) {
+               entry = rb_entry(node, struct btrfs_free_space, offset_index);
+               if (entry->bytes < *bytes)
+                       continue;
+
+               if (entry->bitmap) {
+                       ret = search_bitmap(block_group, entry, offset, bytes);
+                       if (!ret)
+                               return entry;
+                       continue;
+               }
+
+               *offset = entry->offset;
+               *bytes = entry->bytes;
+               return entry;
+       }
+
+       return NULL;
+}
+
+static void add_new_bitmap(struct btrfs_block_group_cache *block_group,
+                          struct btrfs_free_space *info, u64 offset)
+{
+       u64 bytes_per_bg = BITS_PER_BITMAP * block_group->sectorsize;
+       int max_bitmaps = (int)div64_u64(block_group->key.offset +
+                                        bytes_per_bg - 1, bytes_per_bg);
+       BUG_ON(block_group->total_bitmaps >= max_bitmaps);
+
+       info->offset = offset_to_bitmap(block_group, offset);
+       link_free_space(block_group, info);
+       block_group->total_bitmaps++;
+
+       recalculate_thresholds(block_group);
+}
+
+static noinline int remove_from_bitmap(struct btrfs_block_group_cache *block_group,
+                             struct btrfs_free_space *bitmap_info,
+                             u64 *offset, u64 *bytes)
+{
+       u64 end;
+       u64 search_start, search_bytes;
+       int ret;
+
+again:
+       end = bitmap_info->offset +
+               (u64)(BITS_PER_BITMAP * block_group->sectorsize) - 1;
+
+       /*
+        * XXX - this can go away after a few releases.
+        *
+        * since the only user of btrfs_remove_free_space is the tree logging
+        * stuff, and the only way to test that is under crash conditions, we
+        * want to have this debug stuff here just in case somethings not
+        * working.  Search the bitmap for the space we are trying to use to
+        * make sure its actually there.  If its not there then we need to stop
+        * because something has gone wrong.
+        */
+       search_start = *offset;
+       search_bytes = *bytes;
+       ret = search_bitmap(block_group, bitmap_info, &search_start,
+                           &search_bytes);
+       BUG_ON(ret < 0 || search_start != *offset);
+
+       if (*offset > bitmap_info->offset && *offset + *bytes > end) {
+               bitmap_clear_bits(block_group, bitmap_info, *offset,
+                                 end - *offset + 1);
+               *bytes -= end - *offset + 1;
+               *offset = end + 1;
+       } else if (*offset >= bitmap_info->offset && *offset + *bytes <= end) {
+               bitmap_clear_bits(block_group, bitmap_info, *offset, *bytes);
+               *bytes = 0;
+       }
+
+       if (*bytes) {
+               struct rb_node *next = rb_next(&bitmap_info->offset_index);
+               if (!bitmap_info->bytes) {
+                       unlink_free_space(block_group, bitmap_info);
+                       kfree(bitmap_info->bitmap);
+                       kfree(bitmap_info);
+                       block_group->total_bitmaps--;
+                       recalculate_thresholds(block_group);
+               }
+
+               /*
+                * no entry after this bitmap, but we still have bytes to
+                * remove, so something has gone wrong.
+                */
+               if (!next)
+                       return -EINVAL;
+
+               bitmap_info = rb_entry(next, struct btrfs_free_space,
+                                      offset_index);
+
+               /*
+                * if the next entry isn't a bitmap we need to return to let the
+                * extent stuff do its work.
+                */
+               if (!bitmap_info->bitmap)
+                       return -EAGAIN;
+
+               /*
+                * Ok the next item is a bitmap, but it may not actually hold
+                * the information for the rest of this free space stuff, so
+                * look for it, and if we don't find it return so we can try
+                * everything over again.
+                */
+               search_start = *offset;
+               search_bytes = *bytes;
+               ret = search_bitmap(block_group, bitmap_info, &search_start,
+                                   &search_bytes);
+               if (ret < 0 || search_start != *offset)
+                       return -EAGAIN;
+
+               goto again;
+       } else if (!bitmap_info->bytes) {
+               unlink_free_space(block_group, bitmap_info);
+               kfree(bitmap_info->bitmap);
+               kfree(bitmap_info);
+               block_group->total_bitmaps--;
+               recalculate_thresholds(block_group);
+       }
+
+       return 0;
+}
+
+static int insert_into_bitmap(struct btrfs_block_group_cache *block_group,
+                             struct btrfs_free_space *info)
+{
+       struct btrfs_free_space *bitmap_info;
+       int added = 0;
+       u64 bytes, offset, end;
+       int ret;
+
+       /*
+        * If we are below the extents threshold then we can add this as an
+        * extent, and don't have to deal with the bitmap
+        */
+       if (block_group->free_extents < block_group->extents_thresh &&
+           info->bytes > block_group->sectorsize * 4)
+               return 0;
+
+       /*
+        * some block groups are so tiny they can't be enveloped by a bitmap, so
+        * don't even bother to create a bitmap for this
+        */
+       if (BITS_PER_BITMAP * block_group->sectorsize >
+           block_group->key.offset)
+               return 0;
+
+       bytes = info->bytes;
+       offset = info->offset;
+
+again:
+       bitmap_info = tree_search_offset(block_group,
+                                        offset_to_bitmap(block_group, offset),
+                                        1, 0);
+       if (!bitmap_info) {
+               BUG_ON(added);
+               goto new_bitmap;
+       }
+
+       end = bitmap_info->offset +
+               (u64)(BITS_PER_BITMAP * block_group->sectorsize);
+
+       if (offset >= bitmap_info->offset && offset + bytes > end) {
+               bitmap_set_bits(block_group, bitmap_info, offset,
+                               end - offset);
+               bytes -= end - offset;
+               offset = end;
+               added = 0;
+       } else if (offset >= bitmap_info->offset && offset + bytes <= end) {
+               bitmap_set_bits(block_group, bitmap_info, offset, bytes);
+               bytes = 0;
+       } else {
+               BUG();
+       }
+
+       if (!bytes) {
+               ret = 1;
+               goto out;
+       } else
+               goto again;
+
+new_bitmap:
+       if (info && info->bitmap) {
+               add_new_bitmap(block_group, info, offset);
+               added = 1;
+               info = NULL;
+               goto again;
+       } else {
+               spin_unlock(&block_group->tree_lock);
+
+               /* no pre-allocated info, allocate a new one */
+               if (!info) {
+                       info = kzalloc(sizeof(struct btrfs_free_space),
+                                      GFP_NOFS);
+                       if (!info) {
+                               spin_lock(&block_group->tree_lock);
+                               ret = -ENOMEM;
+                               goto out;
+                       }
+               }
+
+               /* allocate the bitmap */
+               info->bitmap = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS);
+               spin_lock(&block_group->tree_lock);
+               if (!info->bitmap) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               goto again;
+       }
+
+out:
+       if (info) {
+               if (info->bitmap)
+                       kfree(info->bitmap);
+               kfree(info);
+       }
 
        return ret;
 }
@@ -208,8 +600,8 @@ static int link_free_space(struct btrfs_block_group_cache *block_group,
 int btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
                         u64 offset, u64 bytes)
 {
-       struct btrfs_free_space *right_info;
-       struct btrfs_free_space *left_info;
+       struct btrfs_free_space *right_info = NULL;
+       struct btrfs_free_space *left_info = NULL;
        struct btrfs_free_space *info = NULL;
        int ret = 0;
 
@@ -227,18 +619,38 @@ int btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
         * are adding, if there is remove that struct and add a new one to
         * cover the entire range
         */
-       right_info = tree_search_offset(&block_group->free_space_offset,
-                                       offset+bytes, 0, 0);
-       left_info = tree_search_offset(&block_group->free_space_offset,
-                                      offset-1, 0, 1);
+       right_info = tree_search_offset(block_group, offset + bytes, 0, 0);
+       if (right_info && rb_prev(&right_info->offset_index))
+               left_info = rb_entry(rb_prev(&right_info->offset_index),
+                                    struct btrfs_free_space, offset_index);
+       else
+               left_info = tree_search_offset(block_group, offset - 1, 0, 0);
+
+       /*
+        * If there was no extent directly to the left or right of this new
+        * extent then we know we're going to have to allocate a new extent, so
+        * before we do that see if we need to drop this into a bitmap
+        */
+       if ((!left_info || left_info->bitmap) &&
+           (!right_info || right_info->bitmap)) {
+               ret = insert_into_bitmap(block_group, info);
+
+               if (ret < 0) {
+                       goto out;
+               } else if (ret) {
+                       ret = 0;
+                       goto out;
+               }
+       }
 
-       if (right_info) {
+       if (right_info && !right_info->bitmap) {
                unlink_free_space(block_group, right_info);
                info->bytes += right_info->bytes;
                kfree(right_info);
        }
 
-       if (left_info && left_info->offset + left_info->bytes == offset) {
+       if (left_info && !left_info->bitmap &&
+           left_info->offset + left_info->bytes == offset) {
                unlink_free_space(block_group, left_info);
                info->offset = left_info->offset;
                info->bytes += left_info->bytes;
@@ -248,11 +660,11 @@ int btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
        ret = link_free_space(block_group, info);
        if (ret)
                kfree(info);
-
+out:
        spin_unlock(&block_group->tree_lock);
 
        if (ret) {
-               printk(KERN_ERR "btrfs: unable to add free space :%d\n", ret);
+               printk(KERN_CRIT "btrfs: unable to add free space :%d\n", ret);
                BUG_ON(ret == -EEXIST);
        }
 
@@ -263,40 +675,74 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
                            u64 offset, u64 bytes)
 {
        struct btrfs_free_space *info;
+       struct btrfs_free_space *next_info = NULL;
        int ret = 0;
 
        spin_lock(&block_group->tree_lock);
 
-       info = tree_search_offset(&block_group->free_space_offset, offset, 0,
-                                 1);
-       if (info && info->offset == offset) {
-               if (info->bytes < bytes) {
-                       printk(KERN_ERR "Found free space at %llu, size %llu,"
-                              "trying to use %llu\n",
-                              (unsigned long long)info->offset,
-                              (unsigned long long)info->bytes,
-                              (unsigned long long)bytes);
+again:
+       info = tree_search_offset(block_group, offset, 0, 0);
+       if (!info) {
+               /*
+                * oops didn't find an extent that matched the space we wanted
+                * to remove, look for a bitmap instead
+                */
+               info = tree_search_offset(block_group,
+                                         offset_to_bitmap(block_group, offset),
+                                         1, 0);
+               if (!info) {
+                       WARN_ON(1);
+                       goto out_lock;
+               }
+       }
+
+       if (info->bytes < bytes && rb_next(&info->offset_index)) {
+               u64 end;
+               next_info = rb_entry(rb_next(&info->offset_index),
+                                            struct btrfs_free_space,
+                                            offset_index);
+
+               if (next_info->bitmap)
+                       end = next_info->offset + BITS_PER_BITMAP *
+                               block_group->sectorsize - 1;
+               else
+                       end = next_info->offset + next_info->bytes;
+
+               if (next_info->bytes < bytes ||
+                   next_info->offset > offset || offset > end) {
+                       printk(KERN_CRIT "Found free space at %llu, size %llu,"
+                             " trying to use %llu\n",
+                             (unsigned long long)info->offset,
+                             (unsigned long long)info->bytes,
+                             (unsigned long long)bytes);
                        WARN_ON(1);
                        ret = -EINVAL;
-                       spin_unlock(&block_group->tree_lock);
-                       goto out;
+                       goto out_lock;
                }
-               unlink_free_space(block_group, info);
 
-               if (info->bytes == bytes) {
-                       kfree(info);
-                       spin_unlock(&block_group->tree_lock);
-                       goto out;
+               info = next_info;
+       }
+
+       if (info->bytes == bytes) {
+               unlink_free_space(block_group, info);
+               if (info->bitmap) {
+                       kfree(info->bitmap);
+                       block_group->total_bitmaps--;
                }
+               kfree(info);
+               goto out_lock;
+       }
 
+       if (!info->bitmap && info->offset == offset) {
+               unlink_free_space(block_group, info);
                info->offset += bytes;
                info->bytes -= bytes;
+               link_free_space(block_group, info);
+               goto out_lock;
+       }
 
-               ret = link_free_space(block_group, info);
-               spin_unlock(&block_group->tree_lock);
-               BUG_ON(ret);
-       } else if (info && info->offset < offset &&
-                  info->offset + info->bytes >= offset + bytes) {
+       if (!info->bitmap && info->offset <= offset &&
+           info->offset + info->bytes >= offset + bytes) {
                u64 old_start = info->offset;
                /*
                 * we're freeing space in the middle of the info,
@@ -312,7 +758,9 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
                        info->offset = offset + bytes;
                        info->bytes = old_end - info->offset;
                        ret = link_free_space(block_group, info);
-                       BUG_ON(ret);
+                       WARN_ON(ret);
+                       if (ret)
+                               goto out_lock;
                } else {
                        /* the hole we're creating ends at the end
                         * of the info struct, just free the info
@@ -320,32 +768,22 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
                        kfree(info);
                }
                spin_unlock(&block_group->tree_lock);
-               /* step two, insert a new info struct to cover anything
-                * before the hole
+
+               /* step two, insert a new info struct to cover
+                * anything before the hole
                 */
                ret = btrfs_add_free_space(block_group, old_start,
                                           offset - old_start);
-               BUG_ON(ret);
-       } else {
-               spin_unlock(&block_group->tree_lock);
-               if (!info) {
-                       printk(KERN_ERR "couldn't find space %llu to free\n",
-                              (unsigned long long)offset);
-                       printk(KERN_ERR "cached is %d, offset %llu bytes %llu\n",
-                              block_group->cached,
-                              (unsigned long long)block_group->key.objectid,
-                              (unsigned long long)block_group->key.offset);
-                       btrfs_dump_free_space(block_group, bytes);
-               } else if (info) {
-                       printk(KERN_ERR "hmm, found offset=%llu bytes=%llu, "
-                              "but wanted offset=%llu bytes=%llu\n",
-                              (unsigned long long)info->offset,
-                              (unsigned long long)info->bytes,
-                              (unsigned long long)offset,
-                              (unsigned long long)bytes);
-               }
-               WARN_ON(1);
+               WARN_ON(ret);
+               goto out;
        }
+
+       ret = remove_from_bitmap(block_group, info, &offset, &bytes);
+       if (ret == -EAGAIN)
+               goto again;
+       BUG_ON(ret);
+out_lock:
+       spin_unlock(&block_group->tree_lock);
 out:
        return ret;
 }
@@ -361,10 +799,13 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group,
                info = rb_entry(n, struct btrfs_free_space, offset_index);
                if (info->bytes >= bytes)
                        count++;
-               printk(KERN_ERR "entry offset %llu, bytes %llu\n",
+               printk(KERN_CRIT "entry offset %llu, bytes %llu, bitmap %s\n",
                       (unsigned long long)info->offset,
-                      (unsigned long long)info->bytes);
+                      (unsigned long long)info->bytes,
+                      (info->bitmap) ? "yes" : "no");
        }
+       printk(KERN_INFO "block group has cluster?: %s\n",
+              list_empty(&block_group->cluster_list) ? "no" : "yes");
        printk(KERN_INFO "%d blocks of free space at or bigger than bytes is"
               "\n", count);
 }
@@ -397,26 +838,35 @@ __btrfs_return_cluster_to_free_space(
 {
        struct btrfs_free_space *entry;
        struct rb_node *node;
+       bool bitmap;
 
        spin_lock(&cluster->lock);
        if (cluster->block_group != block_group)
                goto out;
 
+       bitmap = cluster->points_to_bitmap;
+       cluster->block_group = NULL;
        cluster->window_start = 0;
+       list_del_init(&cluster->block_group_list);
+       cluster->points_to_bitmap = false;
+
+       if (bitmap)
+               goto out;
+
        node = rb_first(&cluster->root);
-       while(node) {
+       while (node) {
                entry = rb_entry(node, struct btrfs_free_space, offset_index);
                node = rb_next(&entry->offset_index);
                rb_erase(&entry->offset_index, &cluster->root);
-               link_free_space(block_group, entry);
+               BUG_ON(entry->bitmap);
+               tree_insert_offset(&block_group->free_space_offset,
+                                  entry->offset, &entry->offset_index, 0);
        }
-       list_del_init(&cluster->block_group_list);
-
-       btrfs_put_block_group(cluster->block_group);
-       cluster->block_group = NULL;
        cluster->root.rb_node = NULL;
+
 out:
        spin_unlock(&cluster->lock);
+       btrfs_put_block_group(block_group);
        return 0;
 }
 
@@ -425,20 +875,28 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group)
        struct btrfs_free_space *info;
        struct rb_node *node;
        struct btrfs_free_cluster *cluster;
-       struct btrfs_free_cluster *safe;
+       struct list_head *head;
 
        spin_lock(&block_group->tree_lock);
-
-       list_for_each_entry_safe(cluster, safe, &block_group->cluster_list,
-                                block_group_list) {
+       while ((head = block_group->cluster_list.next) !=
+              &block_group->cluster_list) {
+               cluster = list_entry(head, struct btrfs_free_cluster,
+                                    block_group_list);
 
                WARN_ON(cluster->block_group != block_group);
                __btrfs_return_cluster_to_free_space(block_group, cluster);
+               if (need_resched()) {
+                       spin_unlock(&block_group->tree_lock);
+                       cond_resched();
+                       spin_lock(&block_group->tree_lock);
+               }
        }
 
-       while ((node = rb_last(&block_group->free_space_bytes)) != NULL) {
-               info = rb_entry(node, struct btrfs_free_space, bytes_index);
+       while ((node = rb_last(&block_group->free_space_offset)) != NULL) {
+               info = rb_entry(node, struct btrfs_free_space, offset_index);
                unlink_free_space(block_group, info);
+               if (info->bitmap)
+                       kfree(info->bitmap);
                kfree(info);
                if (need_resched()) {
                        spin_unlock(&block_group->tree_lock);
@@ -446,6 +904,7 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group)
                        spin_lock(&block_group->tree_lock);
                }
        }
+
        spin_unlock(&block_group->tree_lock);
 }
 
@@ -453,25 +912,35 @@ u64 btrfs_find_space_for_alloc(struct btrfs_block_group_cache *block_group,
                               u64 offset, u64 bytes, u64 empty_size)
 {
        struct btrfs_free_space *entry = NULL;
+       u64 bytes_search = bytes + empty_size;
        u64 ret = 0;
 
        spin_lock(&block_group->tree_lock);
-       entry = tree_search_offset(&block_group->free_space_offset, offset,
-                                  bytes + empty_size, 1);
+       entry = find_free_space(block_group, &offset, &bytes_search, 0);
        if (!entry)
-               entry = tree_search_bytes(&block_group->free_space_bytes,
-                                         offset, bytes + empty_size);
-       if (entry) {
+               goto out;
+
+       ret = offset;
+       if (entry->bitmap) {
+               bitmap_clear_bits(block_group, entry, offset, bytes);
+               if (!entry->bytes) {
+                       unlink_free_space(block_group, entry);
+                       kfree(entry->bitmap);
+                       kfree(entry);
+                       block_group->total_bitmaps--;
+                       recalculate_thresholds(block_group);
+               }
+       } else {
                unlink_free_space(block_group, entry);
-               ret = entry->offset;
                entry->offset += bytes;
                entry->bytes -= bytes;
-
                if (!entry->bytes)
                        kfree(entry);
                else
                        link_free_space(block_group, entry);
        }
+
+out:
        spin_unlock(&block_group->tree_lock);
 
        return ret;
@@ -517,6 +986,54 @@ int btrfs_return_cluster_to_free_space(
        return ret;
 }
 
+static u64 btrfs_alloc_from_bitmap(struct btrfs_block_group_cache *block_group,
+                                  struct btrfs_free_cluster *cluster,
+                                  u64 bytes, u64 min_start)
+{
+       struct btrfs_free_space *entry;
+       int err;
+       u64 search_start = cluster->window_start;
+       u64 search_bytes = bytes;
+       u64 ret = 0;
+
+       spin_lock(&block_group->tree_lock);
+       spin_lock(&cluster->lock);
+
+       if (!cluster->points_to_bitmap)
+               goto out;
+
+       if (cluster->block_group != block_group)
+               goto out;
+
+       /*
+        * search_start is the beginning of the bitmap, but at some point it may
+        * be a good idea to point to the actual start of the free area in the
+        * bitmap, so do the offset_to_bitmap trick anyway, and set bitmap_only
+        * to 1 to make sure we get the bitmap entry
+        */
+       entry = tree_search_offset(block_group,
+                                  offset_to_bitmap(block_group, search_start),
+                                  1, 0);
+       if (!entry || !entry->bitmap)
+               goto out;
+
+       search_start = min_start;
+       search_bytes = bytes;
+
+       err = search_bitmap(block_group, entry, &search_start,
+                           &search_bytes);
+       if (err)
+               goto out;
+
+       ret = search_start;
+       bitmap_clear_bits(block_group, entry, ret, bytes);
+out:
+       spin_unlock(&cluster->lock);
+       spin_unlock(&block_group->tree_lock);
+
+       return ret;
+}
+
 /*
  * given a cluster, try to allocate 'bytes' from it, returns 0
  * if it couldn't find anything suitably large, or a logical disk offset
@@ -530,6 +1047,10 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
        struct rb_node *node;
        u64 ret = 0;
 
+       if (cluster->points_to_bitmap)
+               return btrfs_alloc_from_bitmap(block_group, cluster, bytes,
+                                              min_start);
+
        spin_lock(&cluster->lock);
        if (bytes > cluster->max_size)
                goto out;
@@ -567,9 +1088,73 @@ u64 btrfs_alloc_from_cluster(struct btrfs_block_group_cache *block_group,
        }
 out:
        spin_unlock(&cluster->lock);
+
        return ret;
 }
 
+static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group,
+                               struct btrfs_free_space *entry,
+                               struct btrfs_free_cluster *cluster,
+                               u64 offset, u64 bytes, u64 min_bytes)
+{
+       unsigned long next_zero;
+       unsigned long i;
+       unsigned long search_bits;
+       unsigned long total_bits;
+       unsigned long found_bits;
+       unsigned long start = 0;
+       unsigned long total_found = 0;
+       bool found = false;
+
+       i = offset_to_bit(entry->offset, block_group->sectorsize,
+                         max_t(u64, offset, entry->offset));
+       search_bits = bytes_to_bits(min_bytes, block_group->sectorsize);
+       total_bits = bytes_to_bits(bytes, block_group->sectorsize);
+
+again:
+       found_bits = 0;
+       for (i = find_next_bit(entry->bitmap, BITS_PER_BITMAP, i);
+            i < BITS_PER_BITMAP;
+            i = find_next_bit(entry->bitmap, BITS_PER_BITMAP, i + 1)) {
+               next_zero = find_next_zero_bit(entry->bitmap,
+                                              BITS_PER_BITMAP, i);
+               if (next_zero - i >= search_bits) {
+                       found_bits = next_zero - i;
+                       break;
+               }
+               i = next_zero;
+       }
+
+       if (!found_bits)
+               return -1;
+
+       if (!found) {
+               start = i;
+               found = true;
+       }
+
+       total_found += found_bits;
+
+       if (cluster->max_size < found_bits * block_group->sectorsize)
+               cluster->max_size = found_bits * block_group->sectorsize;
+
+       if (total_found < total_bits) {
+               i = find_next_bit(entry->bitmap, BITS_PER_BITMAP, next_zero);
+               if (i - start > total_bits * 2) {
+                       total_found = 0;
+                       cluster->max_size = 0;
+                       found = false;
+               }
+               goto again;
+       }
+
+       cluster->window_start = start * block_group->sectorsize +
+               entry->offset;
+       cluster->points_to_bitmap = true;
+
+       return 0;
+}
+
 /*
  * here we try to find a cluster of blocks in a block group.  The goal
  * is to find at least bytes free and up to empty_size + bytes free.
@@ -587,12 +1172,12 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
        struct btrfs_free_space *entry = NULL;
        struct rb_node *node;
        struct btrfs_free_space *next;
-       struct btrfs_free_space *last;
+       struct btrfs_free_space *last = NULL;
        u64 min_bytes;
        u64 window_start;
        u64 window_free;
        u64 max_extent = 0;
-       int total_retries = 0;
+       bool found_bitmap = false;
        int ret;
 
        /* for metadata, allow allocates with more holes */
@@ -620,30 +1205,79 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
                goto out;
        }
 again:
-       min_bytes = min(min_bytes, bytes + empty_size);
-       entry = tree_search_bytes(&block_group->free_space_bytes,
-                                 offset, min_bytes);
+       entry = tree_search_offset(block_group, offset, found_bitmap, 1);
        if (!entry) {
                ret = -ENOSPC;
                goto out;
        }
+
+       /*
+        * If found_bitmap is true, we exhausted our search for extent entries,
+        * and we just want to search all of the bitmaps that we can find, and
+        * ignore any extent entries we find.
+        */
+       while (entry->bitmap || found_bitmap ||
+              (!entry->bitmap && entry->bytes < min_bytes)) {
+               struct rb_node *node = rb_next(&entry->offset_index);
+
+               if (entry->bitmap && entry->bytes > bytes + empty_size) {
+                       ret = btrfs_bitmap_cluster(block_group, entry, cluster,
+                                                  offset, bytes + empty_size,
+                                                  min_bytes);
+                       if (!ret)
+                               goto got_it;
+               }
+
+               if (!node) {
+                       ret = -ENOSPC;
+                       goto out;
+               }
+               entry = rb_entry(node, struct btrfs_free_space, offset_index);
+       }
+
+       /*
+        * We already searched all the extent entries from the passed in offset
+        * to the end and didn't find enough space for the cluster, and we also
+        * didn't find any bitmaps that met our criteria, just go ahead and exit
+        */
+       if (found_bitmap) {
+               ret = -ENOSPC;
+               goto out;
+       }
+
+       cluster->points_to_bitmap = false;
        window_start = entry->offset;
        window_free = entry->bytes;
        last = entry;
        max_extent = entry->bytes;
 
-       while(1) {
+       while (1) {
                /* out window is just right, lets fill it */
                if (window_free >= bytes + empty_size)
                        break;
 
                node = rb_next(&last->offset_index);
                if (!node) {
+                       if (found_bitmap)
+                               goto again;
                        ret = -ENOSPC;
                        goto out;
                }
                next = rb_entry(node, struct btrfs_free_space, offset_index);
 
+               /*
+                * we found a bitmap, so if this search doesn't result in a
+                * cluster, we know to go and search again for the bitmaps and
+                * start looking for space there
+                */
+               if (next->bitmap) {
+                       if (!found_bitmap)
+                               offset = next->offset;
+                       found_bitmap = true;
+                       last = next;
+                       continue;
+               }
+
                /*
                 * we haven't filled the empty size and the window is
                 * very large.  reset and try again
@@ -655,19 +1289,6 @@ again:
                        window_free = entry->bytes;
                        last = entry;
                        max_extent = 0;
-                       total_retries++;
-                       if (total_retries % 64 == 0) {
-                               if (min_bytes >= (bytes + empty_size)) {
-                                       ret = -ENOSPC;
-                                       goto out;
-                               }
-                               /*
-                                * grow our allocation a bit, we're not having
-                                * much luck
-                                */
-                               min_bytes *= 2;
-                               goto again;
-                       }
                } else {
                        last = next;
                        window_free += next->bytes;
@@ -685,11 +1306,19 @@ again:
         * The cluster includes an rbtree, but only uses the offset index
         * of each free space cache entry.
         */
-       while(1) {
+       while (1) {
                node = rb_next(&entry->offset_index);
-               unlink_free_space(block_group, entry);
+               if (entry->bitmap && node) {
+                       entry = rb_entry(node, struct btrfs_free_space,
+                                        offset_index);
+                       continue;
+               } else if (entry->bitmap && !node) {
+                       break;
+               }
+
+               rb_erase(&entry->offset_index, &block_group->free_space_offset);
                ret = tree_insert_offset(&cluster->root, entry->offset,
-                                        &entry->offset_index);
+                                        &entry->offset_index, 0);
                BUG_ON(ret);
 
                if (!node || entry == last)
@@ -697,8 +1326,10 @@ again:
 
                entry = rb_entry(node, struct btrfs_free_space, offset_index);
        }
-       ret = 0;
+
        cluster->max_size = max_extent;
+got_it:
+       ret = 0;
        atomic_inc(&block_group->count);
        list_add_tail(&cluster->block_group_list, &block_group->cluster_list);
        cluster->block_group = block_group;
@@ -718,6 +1349,7 @@ void btrfs_init_free_cluster(struct btrfs_free_cluster *cluster)
        spin_lock_init(&cluster->refill_lock);
        cluster->root.rb_node = NULL;
        cluster->max_size = 0;
+       cluster->points_to_bitmap = false;
        INIT_LIST_HEAD(&cluster->block_group_list);
        cluster->block_group = NULL;
 }
index 266fb876405442841b31b7e8219fff82e339d821..890a8e79011b2cadc6adc545909289ed90707a27 100644 (file)
 #ifndef __BTRFS_FREE_SPACE_CACHE
 #define __BTRFS_FREE_SPACE_CACHE
 
+struct btrfs_free_space {
+       struct rb_node offset_index;
+       u64 offset;
+       u64 bytes;
+       unsigned long *bitmap;
+       struct list_head list;
+};
+
 int btrfs_add_free_space(struct btrfs_block_group_cache *block_group,
                         u64 bytenr, u64 size);
 int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group,
index dbe1aabf96cd918d43e31160e5953621f8835983..59cba180fe833f08f815f4ca968956eaa7f33e18 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/time.h>
 #include <linux/init.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/backing-dev.h>
 #include <linux/mpage.h>
 #include <linux/swap.h>
@@ -2604,8 +2603,8 @@ noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
        if (root->ref_cows)
                btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0);
        path = btrfs_alloc_path();
-       path->reada = -1;
        BUG_ON(!path);
+       path->reada = -1;
 
        /* FIXME, add redo link to tree so we don't leak on crash */
        key.objectid = inode->i_ino;
@@ -3100,8 +3099,12 @@ static void inode_tree_add(struct inode *inode)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_inode *entry;
-       struct rb_node **p = &root->inode_tree.rb_node;
-       struct rb_node *parent = NULL;
+       struct rb_node **p;
+       struct rb_node *parent;
+
+again:
+       p = &root->inode_tree.rb_node;
+       parent = NULL;
 
        spin_lock(&root->inode_lock);
        while (*p) {
@@ -3109,13 +3112,16 @@ static void inode_tree_add(struct inode *inode)
                entry = rb_entry(parent, struct btrfs_inode, rb_node);
 
                if (inode->i_ino < entry->vfs_inode.i_ino)
-                       p = &(*p)->rb_left;
+                       p = &parent->rb_left;
                else if (inode->i_ino > entry->vfs_inode.i_ino)
-                       p = &(*p)->rb_right;
+                       p = &parent->rb_right;
                else {
                        WARN_ON(!(entry->vfs_inode.i_state &
                                  (I_WILL_FREE | I_FREEING | I_CLEAR)));
-                       break;
+                       rb_erase(parent, &root->inode_tree);
+                       RB_CLEAR_NODE(parent);
+                       spin_unlock(&root->inode_lock);
+                       goto again;
                }
        }
        rb_link_node(&BTRFS_I(inode)->rb_node, parent, p);
@@ -3127,12 +3133,12 @@ static void inode_tree_del(struct inode *inode)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
 
+       spin_lock(&root->inode_lock);
        if (!RB_EMPTY_NODE(&BTRFS_I(inode)->rb_node)) {
-               spin_lock(&root->inode_lock);
                rb_erase(&BTRFS_I(inode)->rb_node, &root->inode_tree);
-               spin_unlock(&root->inode_lock);
                RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node);
        }
+       spin_unlock(&root->inode_lock);
 }
 
 static noinline void init_btrfs_i(struct inode *inode)
@@ -3580,12 +3586,6 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
                owner = 1;
        BTRFS_I(inode)->block_group =
                        btrfs_find_block_group(root, 0, alloc_hint, owner);
-       if ((mode & S_IFREG)) {
-               if (btrfs_test_opt(root, NODATASUM))
-                       BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
-               if (btrfs_test_opt(root, NODATACOW))
-                       BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW;
-       }
 
        key[0].objectid = objectid;
        btrfs_set_key_type(&key[0], BTRFS_INODE_ITEM_KEY);
@@ -3640,6 +3640,13 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
 
        btrfs_inherit_iflags(inode, dir);
 
+       if ((mode & S_IFREG)) {
+               if (btrfs_test_opt(root, NODATASUM))
+                       BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
+               if (btrfs_test_opt(root, NODATACOW))
+                       BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW;
+       }
+
        insert_inode_hash(inode);
        inode_tree_add(inode);
        return inode;
@@ -4785,8 +4792,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
         * and the replacement file is large.  Start IO on it now so
         * we don't add too much work to the end of the transaction
         */
-       if (new_inode && old_inode && S_ISREG(old_inode->i_mode) &&
-           new_inode->i_size &&
+       if (new_inode && S_ISREG(old_inode->i_mode) && new_inode->i_size &&
            old_inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT)
                filemap_flush(old_inode->i_mapping);
 
@@ -5082,6 +5088,7 @@ static long btrfs_fallocate(struct inode *inode, int mode,
        u64 mask = BTRFS_I(inode)->root->sectorsize - 1;
        struct extent_map *em;
        struct btrfs_trans_handle *trans;
+       struct btrfs_root *root;
        int ret;
 
        alloc_start = offset & ~mask;
@@ -5100,6 +5107,13 @@ static long btrfs_fallocate(struct inode *inode, int mode,
                        goto out;
        }
 
+       root = BTRFS_I(inode)->root;
+
+       ret = btrfs_check_data_free_space(root, inode,
+                                         alloc_end - alloc_start);
+       if (ret)
+               goto out;
+
        locked_end = alloc_end - 1;
        while (1) {
                struct btrfs_ordered_extent *ordered;
@@ -5107,7 +5121,7 @@ static long btrfs_fallocate(struct inode *inode, int mode,
                trans = btrfs_start_transaction(BTRFS_I(inode)->root, 1);
                if (!trans) {
                        ret = -EIO;
-                       goto out;
+                       goto out_free;
                }
 
                /* the extent lock is ordered inside the running
@@ -5168,6 +5182,8 @@ static long btrfs_fallocate(struct inode *inode, int mode,
                      GFP_NOFS);
 
        btrfs_end_transaction(trans, BTRFS_I(inode)->root);
+out_free:
+       btrfs_free_reserved_data_space(root, inode, alloc_end - alloc_start);
 out:
        mutex_unlock(&inode->i_mutex);
        return ret;
index eff18f5b53620f20a392f9c57a80c8897c61d317..bd88f25889f7c5daf94bf0aec8645041bfb2ce60 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/time.h>
 #include <linux/init.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/backing-dev.h>
 #include <linux/mount.h>
 #include <linux/mpage.h>
@@ -1028,7 +1027,8 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                                                struct btrfs_file_extent_item);
                        comp = btrfs_file_extent_compression(leaf, extent);
                        type = btrfs_file_extent_type(leaf, extent);
-                       if (type == BTRFS_FILE_EXTENT_REG) {
+                       if (type == BTRFS_FILE_EXTENT_REG ||
+                           type == BTRFS_FILE_EXTENT_PREALLOC) {
                                disko = btrfs_file_extent_disk_bytenr(leaf,
                                                                      extent);
                                diskl = btrfs_file_extent_disk_num_bytes(leaf,
@@ -1051,7 +1051,8 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
                        new_key.objectid = inode->i_ino;
                        new_key.offset = key.offset + destoff - off;
 
-                       if (type == BTRFS_FILE_EXTENT_REG) {
+                       if (type == BTRFS_FILE_EXTENT_REG ||
+                           type == BTRFS_FILE_EXTENT_PREALLOC) {
                                ret = btrfs_insert_empty_item(trans, root, path,
                                                              &new_key, size);
                                if (ret)
index 6d6523da0a30e769c56380c37c6e6aca019217bd..0d126be22b636c239d3e7585803e331d3d6c2f5b 100644 (file)
@@ -309,7 +309,7 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c)
        }
        printk(KERN_INFO "node %llu level %d total ptrs %d free spc %u\n",
               (unsigned long long)btrfs_header_bytenr(c),
-              btrfs_header_level(c), nr,
+             level, nr,
               (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr);
        for (i = 0; i < nr; i++) {
                btrfs_node_key_to_cpu(c, &key, i);
@@ -326,10 +326,10 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c)
                                        btrfs_level_size(root, level - 1),
                                        btrfs_node_ptr_generation(c, i));
                if (btrfs_is_leaf(next) &&
-                   btrfs_header_level(c) != 1)
+                  level != 1)
                        BUG();
                if (btrfs_header_level(next) !=
-                       btrfs_header_level(c) - 1)
+                      level - 1)
                        BUG();
                btrfs_print_tree(root, next);
                free_extent_buffer(next);
index b23dc209ae103192bf4eea8ab6ca70f27adda11e..c04f7f212602c4bcb71e58db938fcd0d8a9128ad 100644 (file)
@@ -670,6 +670,8 @@ again:
                        err = ret;
                        goto out;
                }
+               if (ret > 0 && path2->slots[level] > 0)
+                       path2->slots[level]--;
 
                eb = path2->nodes[level];
                WARN_ON(btrfs_node_blockptr(eb, path2->slots[level]) !=
@@ -1609,6 +1611,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
                BUG_ON(level == 0);
                path->lowest_level = level;
                ret = btrfs_search_slot(NULL, reloc_root, &key, path, 0, 0);
+               path->lowest_level = 0;
                if (ret < 0) {
                        btrfs_free_path(path);
                        return ret;
@@ -1788,7 +1791,7 @@ static void merge_func(struct btrfs_work *work)
                btrfs_end_transaction(trans, root);
        }
 
-       btrfs_drop_dead_root(reloc_root);
+       btrfs_drop_snapshot(reloc_root, 0);
 
        if (atomic_dec_and_test(async->num_pending))
                complete(async->done);
@@ -2075,9 +2078,6 @@ static int do_relocation(struct btrfs_trans_handle *trans,
 
                        ret = btrfs_drop_subtree(trans, root, eb, upper->eb);
                        BUG_ON(ret);
-
-                       btrfs_tree_unlock(eb);
-                       free_extent_buffer(eb);
                }
                if (!lowest) {
                        btrfs_tree_unlock(upper->eb);
@@ -2553,8 +2553,13 @@ int relocate_inode_pages(struct inode *inode, u64 start, u64 len)
        last_index = (start + len - 1) >> PAGE_CACHE_SHIFT;
 
        /* make sure the dirty trick played by the caller work */
-       ret = invalidate_inode_pages2_range(inode->i_mapping,
-                                           first_index, last_index);
+       while (1) {
+               ret = invalidate_inode_pages2_range(inode->i_mapping,
+                                                   first_index, last_index);
+               if (ret != -EBUSY)
+                       break;
+               schedule_timeout(HZ/10);
+       }
        if (ret)
                goto out_unlock;
 
index 9f179d4832d5c90e6270c732628b4e1998a28013..6d6d06cb6dfce1e0bf950ca6d0175e9993f53010 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/init.h>
 #include <linux/seq_file.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/backing-dev.h>
 #include <linux/mount.h>
 #include <linux/mpage.h>
index 4e83457ea253e798ccfc8cb1d493ad7e48daa2bd..cdbb5022da52df1e2b33593650401021077ba280 100644 (file)
@@ -40,6 +40,12 @@ static noinline void put_transaction(struct btrfs_transaction *transaction)
        }
 }
 
+static noinline void switch_commit_root(struct btrfs_root *root)
+{
+       free_extent_buffer(root->commit_root);
+       root->commit_root = btrfs_root_node(root);
+}
+
 /*
  * either allocate a new transaction or hop into the existing one
  */
@@ -444,9 +450,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
 
        btrfs_write_dirty_block_groups(trans, root);
 
-       ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
-       BUG_ON(ret);
-
        while (1) {
                old_root_bytenr = btrfs_root_bytenr(&root->root_item);
                if (old_root_bytenr == root->node->start)
@@ -457,13 +460,14 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,
                                        &root->root_key,
                                        &root->root_item);
                BUG_ON(ret);
-               btrfs_write_dirty_block_groups(trans, root);
 
-               ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
+               ret = btrfs_write_dirty_block_groups(trans, root);
                BUG_ON(ret);
        }
-       free_extent_buffer(root->commit_root);
-       root->commit_root = btrfs_root_node(root);
+
+       if (root != root->fs_info->extent_root)
+               switch_commit_root(root);
+
        return 0;
 }
 
@@ -495,10 +499,12 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,
                root = list_entry(next, struct btrfs_root, dirty_list);
 
                update_cowonly_root(trans, root);
-
-               ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
-               BUG_ON(ret);
        }
+
+       down_write(&fs_info->extent_commit_sem);
+       switch_commit_root(fs_info->extent_root);
+       up_write(&fs_info->extent_commit_sem);
+
        return 0;
 }
 
@@ -544,8 +550,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans,
                        btrfs_update_reloc_root(trans, root);
 
                        if (root->commit_root != root->node) {
-                               free_extent_buffer(root->commit_root);
-                               root->commit_root = btrfs_root_node(root);
+                               switch_commit_root(root);
                                btrfs_set_root_node(&root->root_item,
                                                    root->node);
                        }
@@ -593,6 +598,7 @@ int btrfs_defrag_root(struct btrfs_root *root, int cacheonly)
        return 0;
 }
 
+#if 0
 /*
  * when dropping snapshots, we generate a ton of delayed refs, and it makes
  * sense not to join the transaction while it is trying to flush the current
@@ -681,6 +687,7 @@ int btrfs_drop_dead_root(struct btrfs_root *root)
        btrfs_btree_balance_dirty(tree_root, nr);
        return ret;
 }
+#endif
 
 /*
  * new snapshots need to be created at a very specific time in the
@@ -850,6 +857,16 @@ static void update_super_roots(struct btrfs_root *root)
        super->root_level = root_item->level;
 }
 
+int btrfs_transaction_in_commit(struct btrfs_fs_info *info)
+{
+       int ret = 0;
+       spin_lock(&info->new_trans_lock);
+       if (info->running_transaction)
+               ret = info->running_transaction->in_commit;
+       spin_unlock(&info->new_trans_lock);
+       return ret;
+}
+
 int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
                             struct btrfs_root *root)
 {
@@ -941,9 +958,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 
                mutex_unlock(&root->fs_info->trans_mutex);
 
-               if (flush_on_commit || snap_pending) {
-                       if (flush_on_commit)
-                               btrfs_start_delalloc_inodes(root);
+               if (flush_on_commit) {
+                       btrfs_start_delalloc_inodes(root);
+                       ret = btrfs_wait_ordered_extents(root, 0);
+                       BUG_ON(ret);
+               } else if (snap_pending) {
                        ret = btrfs_wait_ordered_extents(root, 1);
                        BUG_ON(ret);
                }
@@ -1007,15 +1026,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 
        btrfs_set_root_node(&root->fs_info->tree_root->root_item,
                            root->fs_info->tree_root->node);
-       free_extent_buffer(root->fs_info->tree_root->commit_root);
-       root->fs_info->tree_root->commit_root =
-                               btrfs_root_node(root->fs_info->tree_root);
+       switch_commit_root(root->fs_info->tree_root);
 
        btrfs_set_root_node(&root->fs_info->chunk_root->root_item,
                            root->fs_info->chunk_root->node);
-       free_extent_buffer(root->fs_info->chunk_root->commit_root);
-       root->fs_info->chunk_root->commit_root =
-                               btrfs_root_node(root->fs_info->chunk_root);
+       switch_commit_root(root->fs_info->chunk_root);
 
        update_super_roots(root);
 
@@ -1055,6 +1070,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
        cur_trans->commit_done = 1;
 
        root->fs_info->last_trans_committed = cur_trans->transid;
+
        wake_up(&cur_trans->commit_wait);
 
        put_transaction(cur_trans);
@@ -1081,7 +1097,7 @@ int btrfs_clean_old_snapshots(struct btrfs_root *root)
        while (!list_empty(&list)) {
                root = list_entry(list.next, struct btrfs_root, root_list);
                list_del_init(&root->root_list);
-               btrfs_drop_dead_root(root);
+               btrfs_drop_snapshot(root, 0);
        }
        return 0;
 }
index 961c3ee5a2e10697a120c2dbd7c0dd6d639f27ab..663c67404918dd30fb1c5cf0943b07b2455018bd 100644 (file)
@@ -107,4 +107,5 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root);
 int btrfs_write_and_wait_marked_extents(struct btrfs_root *root,
                                        struct extent_io_tree *dirty_pages);
+int btrfs_transaction_in_commit(struct btrfs_fs_info *info);
 #endif
index c13922206d1be59196a8c59c95f9a98bae12be74..d91b0de7c502d13ef51eaeaf667b61cc0230d8a8 100644 (file)
@@ -797,7 +797,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
                return -ENOENT;
 
        inode = read_one_inode(root, key->objectid);
-       BUG_ON(!dir);
+       BUG_ON(!inode);
 
        ref_ptr = btrfs_item_ptr_offset(eb, slot);
        ref_end = ref_ptr + btrfs_item_size_nr(eb, slot);
index 3ab80e9cd76767a674e3005185ee99f3afa53433..5dbefd11b4af524f969c21b857067281eab0dc71 100644 (file)
@@ -721,7 +721,8 @@ error:
  */
 static noinline int find_free_dev_extent(struct btrfs_trans_handle *trans,
                                         struct btrfs_device *device,
-                                        u64 num_bytes, u64 *start)
+                                        u64 num_bytes, u64 *start,
+                                        u64 *max_avail)
 {
        struct btrfs_key key;
        struct btrfs_root *root = device->dev_root;
@@ -758,9 +759,13 @@ static noinline int find_free_dev_extent(struct btrfs_trans_handle *trans,
        ret = btrfs_search_slot(trans, root, &key, path, 0, 0);
        if (ret < 0)
                goto error;
-       ret = btrfs_previous_item(root, path, 0, key.type);
-       if (ret < 0)
-               goto error;
+       if (ret > 0) {
+               ret = btrfs_previous_item(root, path, key.objectid, key.type);
+               if (ret < 0)
+                       goto error;
+               if (ret > 0)
+                       start_found = 1;
+       }
        l = path->nodes[0];
        btrfs_item_key_to_cpu(l, &key, path->slots[0]);
        while (1) {
@@ -803,6 +808,10 @@ no_more_items:
                        if (last_byte < search_start)
                                last_byte = search_start;
                        hole_size = key.offset - last_byte;
+
+                       if (hole_size > *max_avail)
+                               *max_avail = hole_size;
+
                        if (key.offset > last_byte &&
                            hole_size >= num_bytes) {
                                *start = last_byte;
@@ -1621,6 +1630,7 @@ static int __btrfs_grow_device(struct btrfs_trans_handle *trans,
        device->fs_devices->total_rw_bytes += diff;
 
        device->total_bytes = new_size;
+       device->disk_total_bytes = new_size;
        btrfs_clear_space_info_full(device->dev_root->fs_info);
 
        return btrfs_update_device(trans, device);
@@ -2007,7 +2017,7 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
                        goto done;
                if (ret) {
                        ret = 0;
-                       goto done;
+                       break;
                }
 
                l = path->nodes[0];
@@ -2015,7 +2025,7 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
                btrfs_item_key_to_cpu(l, &key, path->slots[0]);
 
                if (key.objectid != device->devid)
-                       goto done;
+                       break;
 
                dev_extent = btrfs_item_ptr(l, slot, struct btrfs_dev_extent);
                length = btrfs_dev_extent_length(l, dev_extent);
@@ -2171,6 +2181,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
                             max_chunk_size);
 
 again:
+       max_avail = 0;
        if (!map || map->num_stripes != num_stripes) {
                kfree(map);
                map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS);
@@ -2219,7 +2230,8 @@ again:
 
                if (device->in_fs_metadata && avail >= min_free) {
                        ret = find_free_dev_extent(trans, device,
-                                                  min_free, &dev_offset);
+                                                  min_free, &dev_offset,
+                                                  &max_avail);
                        if (ret == 0) {
                                list_move_tail(&device->dev_alloc_list,
                                               &private_devs);
@@ -2795,26 +2807,6 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
                }
        }
 
-       for (i = 0; i > nr; i++) {
-               struct btrfs_multi_bio *multi;
-               struct btrfs_bio_stripe *stripe;
-               int ret;
-
-               length = 1;
-               ret = btrfs_map_block(map_tree, WRITE, buf[i],
-                                     &length, &multi, 0);
-               BUG_ON(ret);
-
-               stripe = multi->stripes;
-               for (j = 0; j < multi->num_stripes; j++) {
-                       if (stripe->physical >= physical &&
-                           physical < stripe->physical + length)
-                               break;
-               }
-               BUG_ON(j >= multi->num_stripes);
-               kfree(multi);
-       }
-
        *logical = buf;
        *naddrs = nr;
        *stripe_len = map->stripe_len;
index ecfbce836d32b31333a034f33ca07d83d9e479cc..3e2b90eaa23945415d56cbd0edfec6848e5dd2d6 100644 (file)
@@ -208,7 +208,7 @@ int btrfs_zlib_compress_pages(struct address_space *mapping,
        *total_in = 0;
 
        workspace = find_zlib_workspace();
-       if (!workspace)
+       if (IS_ERR(workspace))
                return -1;
 
        if (Z_OK != zlib_deflateInit(&workspace->def_strm, 3)) {
@@ -366,7 +366,7 @@ int btrfs_zlib_decompress_biovec(struct page **pages_in,
        char *kaddr;
 
        workspace = find_zlib_workspace();
-       if (!workspace)
+       if (IS_ERR(workspace))
                return -ENOMEM;
 
        data_in = kmap(pages_in[page_in_index]);
@@ -547,7 +547,7 @@ int btrfs_zlib_decompress(unsigned char *data_in,
                return -ENOMEM;
 
        workspace = find_zlib_workspace();
-       if (!workspace)
+       if (IS_ERR(workspace))
                return -ENOMEM;
 
        workspace->inf_strm.next_in = data_in;
index a3ef091a45bd4664e5ba5e683f9329bda3d1d3df..28f320fac4d4261ec8626d0cfe221be83778c20e 100644 (file)
@@ -1165,8 +1165,11 @@ void mark_buffer_dirty(struct buffer_head *bh)
 
        if (!test_set_buffer_dirty(bh)) {
                struct page *page = bh->b_page;
-               if (!TestSetPageDirty(page))
-                       __set_page_dirty(page, page_mapping(page), 0);
+               if (!TestSetPageDirty(page)) {
+                       struct address_space *mapping = page_mapping(page);
+                       if (mapping)
+                               __set_page_dirty(page, mapping, 0);
+               }
        }
 }
 
index b7c9d5187a756e019bc88c2bcbf0ed3f9d5844f7..2f18c1e4e3013ccb059713cda2de1eacb2459a35 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/major.h>
 #include <linux/errno.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/seq_file.h>
 
 #include <linux/kobject.h>
@@ -238,8 +237,10 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
 }
 
 /**
- * register_chrdev() - Register a major number for character devices.
+ * __register_chrdev() - create and register a cdev occupying a range of minors
  * @major: major device number or 0 for dynamic allocation
+ * @baseminor: first of the requested range of minor numbers
+ * @count: the number of minor numbers required
  * @name: name of this range of devices
  * @fops: file operations associated with this devices
  *
@@ -255,19 +256,17 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
  * /dev. It only helps to keep track of the different owners of devices. If
  * your module name has only one type of devices it's ok to use e.g. the name
  * of the module here.
- *
- * This function registers a range of 256 minor numbers. The first minor number
- * is 0.
  */
-int register_chrdev(unsigned int major, const char *name,
-                   const struct file_operations *fops)
+int __register_chrdev(unsigned int major, unsigned int baseminor,
+                     unsigned int count, const char *name,
+                     const struct file_operations *fops)
 {
        struct char_device_struct *cd;
        struct cdev *cdev;
        char *s;
        int err = -ENOMEM;
 
-       cd = __register_chrdev_region(major, 0, 256, name);
+       cd = __register_chrdev_region(major, baseminor, count, name);
        if (IS_ERR(cd))
                return PTR_ERR(cd);
        
@@ -281,7 +280,7 @@ int register_chrdev(unsigned int major, const char *name,
        for (s = strchr(kobject_name(&cdev->kobj),'/'); s; s = strchr(s, '/'))
                *s = '!';
                
-       err = cdev_add(cdev, MKDEV(cd->major, 0), 256);
+       err = cdev_add(cdev, MKDEV(cd->major, baseminor), count);
        if (err)
                goto out;
 
@@ -291,7 +290,7 @@ int register_chrdev(unsigned int major, const char *name,
 out:
        kobject_put(&cdev->kobj);
 out2:
-       kfree(__unregister_chrdev_region(cd->major, 0, 256));
+       kfree(__unregister_chrdev_region(cd->major, baseminor, count));
        return err;
 }
 
@@ -317,10 +316,23 @@ void unregister_chrdev_region(dev_t from, unsigned count)
        }
 }
 
-void unregister_chrdev(unsigned int major, const char *name)
+/**
+ * __unregister_chrdev - unregister and destroy a cdev
+ * @major: major device number
+ * @baseminor: first of the range of minor numbers
+ * @count: the number of minor numbers this cdev is occupying
+ * @name: name of this range of devices
+ *
+ * Unregister and destroy the cdev occupying the region described by
+ * @major, @baseminor and @count.  This function undoes what
+ * __register_chrdev() did.
+ */
+void __unregister_chrdev(unsigned int major, unsigned int baseminor,
+                        unsigned int count, const char *name)
 {
        struct char_device_struct *cd;
-       cd = __unregister_chrdev_region(major, 0, 256);
+
+       cd = __unregister_chrdev_region(major, baseminor, count);
        if (cd && cd->cdev)
                cdev_del(cd->cdev);
        kfree(cd);
@@ -569,6 +581,6 @@ EXPORT_SYMBOL(cdev_alloc);
 EXPORT_SYMBOL(cdev_del);
 EXPORT_SYMBOL(cdev_add);
 EXPORT_SYMBOL(cdev_index);
-EXPORT_SYMBOL(register_chrdev);
-EXPORT_SYMBOL(unregister_chrdev);
+EXPORT_SYMBOL(__register_chrdev);
+EXPORT_SYMBOL(__unregister_chrdev);
 EXPORT_SYMBOL(directly_mappable_cdev_bdi);
index b48689839428805efd6175eacd0a7396068cdafe..e85b1e4389e093e13c6ed23768c875ba49271dc1 100644 (file)
@@ -1,3 +1,10 @@
+Version 1.60
+-------------
+Fix memory leak in reconnect.  Fix oops in DFS mount error path.
+Set s_maxbytes to smaller (the max that vfs can handle) so that
+sendfile will now work over cifs mounts again.  Add noforcegid
+and noforceuid mount parameters.
+
 Version 1.59
 ------------
 Client uses server inode numbers (which are persistent) rather than
@@ -5,7 +12,11 @@ client generated ones by default (mount option "serverino" turned
 on by default if server supports it).  Add forceuid and forcegid
 mount options (so that when negotiating unix extensions specifying
 which uid mounted does not immediately force the server's reported
-uids to be overridden).
+uids to be overridden).  Add support for scope mount parm. Improve
+hard link detection to use same inode for both.  Do not set
+read-only dos attribute on directories (for chmod) since Windows
+explorer special cases this attribute bit for directories for
+a different purpose.
 
 Version 1.58
 ------------
index ad92921dbde415b7a00d0c063d6ca9adfb0d582d..79c1a93400bea9e8b7c39603c1375a574e925b20 100644 (file)
@@ -262,11 +262,11 @@ A partial list of the supported mount options follows:
                mount.  
   domain       Set the SMB/CIFS workgroup name prepended to the
                username during CIFS session establishment
-  forceuid     Set the default uid for inodes based on the uid
-               passed in. For mounts to servers
+  forceuid     Set the default uid for inodes to the uid
+               passed in on mount. For mounts to servers
                which do support the CIFS Unix extensions, such as a
                properly configured Samba server, the server provides
-               the uid, gid and mode so this parameter should  not be
+               the uid, gid and mode so this parameter should not be
                specified unless the server and clients uid and gid
                numbering differ.  If the server and client are in the
                same domain (e.g. running winbind or nss_ldap) and
@@ -278,11 +278,7 @@ A partial list of the supported mount options follows:
                of existing files will be the uid (gid) of the person
                who executed the mount (root, except when mount.cifs
                is configured setuid for user mounts) unless the "uid=" 
-               (gid) mount option is specified.  For the uid (gid) of newly
-               created files and directories, ie files created since 
-               the last mount of the server share, the expected uid 
-               (gid) is cached as long as the inode remains in 
-               memory on the client.   Also note that permission
+               (gid) mount option is specified. Also note that permission
                checks (authorization checks) on accesses to a file occur
                at the server, but there are cases in which an administrator
                may want to restrict at the client as well.  For those
@@ -290,12 +286,15 @@ A partial list of the supported mount options follows:
                (such as Windows), permissions can also be checked at the
                client, and a crude form of client side permission checking 
                can be enabled by specifying file_mode and dir_mode on 
-               the client.  Note that the mount.cifs helper must be
-               at version 1.10 or higher to support specifying the uid
-               (or gid) in non-numeric form.
-  forcegid     (similar to above but for the groupid instead of uid)
+               the client.  (default)
+  forcegid     (similar to above but for the groupid instead of uid) (default)
+  noforceuid   Fill in file owner information (uid) by requesting it from
+               the server if possible. With this option, the value given in
+               the uid= option (on mount) will only be used if the server
+               can not support returning uids on inodes.
+  noforcegid   (similar to above but for the group owner, gid, instead of uid)
   uid          Set the default uid for inodes, and indicate to the
-               cifs kernel driver which local user mounted . If the server
+               cifs kernel driver which local user mounted. If the server
                supports the unix extensions the default uid is
                not used to fill in the owner fields of inodes (files)
                unless the "forceuid" parameter is specified.
index 1b09f167006160ad911211a83bd1a8a53f51db82..20692fbfdb244ffb3d5b7acc5e5d84da00d3f7ba 100644 (file)
@@ -49,6 +49,7 @@
 #define ASN1_OJI       6       /* Object Identifier  */
 #define ASN1_OJD       7       /* Object Description */
 #define ASN1_EXT       8       /* External */
+#define ASN1_ENUM      10      /* Enumerated */
 #define ASN1_SEQ       16      /* Sequence */
 #define ASN1_SET       17      /* Set */
 #define ASN1_NUMSTR    18      /* Numerical String */
 #define SPNEGO_OID_LEN 7
 #define NTLMSSP_OID_LEN  10
 #define KRB5_OID_LEN  7
+#define KRB5U2U_OID_LEN  8
 #define MSKRB5_OID_LEN  7
 static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 };
 static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 };
 static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 };
+static unsigned long KRB5U2U_OID[8] = { 1, 2, 840, 113554, 1, 2, 2, 3 };
 static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 };
 
 /*
@@ -122,6 +125,28 @@ asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
        return 1;
 }
 
+#if 0 /* will be needed later by spnego decoding/encoding of ntlmssp */
+static unsigned char
+asn1_enum_decode(struct asn1_ctx *ctx, __le32 *val)
+{
+       unsigned char ch;
+
+       if (ctx->pointer >= ctx->end) {
+               ctx->error = ASN1_ERR_DEC_EMPTY;
+               return 0;
+       }
+
+       ch = *(ctx->pointer)++; /* ch has 0xa, ptr points to lenght octet */
+       if ((ch) == ASN1_ENUM)  /* if ch value is ENUM, 0xa */
+               *val = *(++(ctx->pointer)); /* value has enum value */
+       else
+               return 0;
+
+       ctx->pointer++;
+       return 1;
+}
+#endif
+
 static unsigned char
 asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
 {
@@ -476,10 +501,9 @@ decode_negTokenInit(unsigned char *security_blob, int length,
        unsigned int cls, con, tag, oidlen, rc;
        bool use_ntlmssp = false;
        bool use_kerberos = false;
+       bool use_kerberosu2u = false;
        bool use_mskerberos = false;
 
-       *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/
-
        /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */
 
        asn1_open(&ctx, security_blob, length);
@@ -515,6 +539,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
                return 0;
        }
 
+       /* SPNEGO */
        if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
                cFYI(1, ("Error decoding negTokenInit"));
                return 0;
@@ -526,6 +551,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
                return 0;
        }
 
+       /* negTokenInit */
        if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
                cFYI(1, ("Error decoding negTokenInit"));
                return 0;
@@ -537,6 +563,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
                return 0;
        }
 
+       /* sequence */
        if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
                cFYI(1, ("Error decoding 2nd part of negTokenInit"));
                return 0;
@@ -548,6 +575,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
                return 0;
        }
 
+       /* sequence of */
        if (asn1_header_decode
            (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
                cFYI(1, ("Error decoding 2nd part of negTokenInit"));
@@ -560,6 +588,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
                return 0;
        }
 
+       /* list of security mechanisms */
        while (!asn1_eoc_decode(&ctx, sequence_end)) {
                rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
                if (!rc) {
@@ -576,11 +605,15 @@ decode_negTokenInit(unsigned char *security_blob, int length,
 
                                if (compare_oid(oid, oidlen, MSKRB5_OID,
                                                MSKRB5_OID_LEN) &&
-                                               !use_kerberos)
+                                               !use_mskerberos)
                                        use_mskerberos = true;
+                               else if (compare_oid(oid, oidlen, KRB5U2U_OID,
+                                                    KRB5U2U_OID_LEN) &&
+                                                    !use_kerberosu2u)
+                                       use_kerberosu2u = true;
                                else if (compare_oid(oid, oidlen, KRB5_OID,
                                                     KRB5_OID_LEN) &&
-                                                    !use_mskerberos)
+                                                    !use_kerberos)
                                        use_kerberos = true;
                                else if (compare_oid(oid, oidlen, NTLMSSP_OID,
                                                     NTLMSSP_OID_LEN))
@@ -593,7 +626,12 @@ decode_negTokenInit(unsigned char *security_blob, int length,
                }
        }
 
+       /* mechlistMIC */
        if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
+               /* Check if we have reached the end of the blob, but with
+                  no mechListMic (e.g. NTLMSSP instead of KRB5) */
+               if (ctx.error == ASN1_ERR_DEC_EMPTY)
+                       goto decode_negtoken_exit;
                cFYI(1, ("Error decoding last part negTokenInit exit3"));
                return 0;
        } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
@@ -602,6 +640,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
                         cls, con, tag, end, *end));
                return 0;
        }
+
+       /* sequence */
        if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
                cFYI(1, ("Error decoding last part negTokenInit exit5"));
                return 0;
@@ -611,6 +651,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
                        cls, con, tag, end, *end));
        }
 
+       /* sequence of */
        if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
                cFYI(1, ("Error decoding last part negTokenInit exit 7"));
                return 0;
@@ -619,6 +660,8 @@ decode_negTokenInit(unsigned char *security_blob, int length,
                         cls, con, tag, end, *end));
                return 0;
        }
+
+       /* general string */
        if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
                cFYI(1, ("Error decoding last part negTokenInit exit9"));
                return 0;
@@ -630,13 +673,13 @@ decode_negTokenInit(unsigned char *security_blob, int length,
        }
        cFYI(1, ("Need to call asn1_octets_decode() function for %s",
                 ctx.pointer)); /* is this UTF-8 or ASCII? */
-
+decode_negtoken_exit:
        if (use_kerberos)
                *secType = Kerberos;
        else if (use_mskerberos)
                *secType = MSKerberos;
        else if (use_ntlmssp)
-               *secType = NTLMSSP;
+               *secType = RawNTLMSSP;
 
        return 1;
 }
index 7f19fefd3d45a2790d426e68e59f80f687b4911c..42cec2a7c0cf41aa250aa01a18df4cc67a9264f9 100644 (file)
@@ -261,6 +261,8 @@ static ssize_t cifs_stats_proc_write(struct file *file,
                                        atomic_set(&tcon->num_reads, 0);
                                        atomic_set(&tcon->num_oplock_brks, 0);
                                        atomic_set(&tcon->num_opens, 0);
+                                       atomic_set(&tcon->num_posixopens, 0);
+                                       atomic_set(&tcon->num_posixmkdirs, 0);
                                        atomic_set(&tcon->num_closes, 0);
                                        atomic_set(&tcon->num_deletes, 0);
                                        atomic_set(&tcon->num_mkdirs, 0);
@@ -347,11 +349,15 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
                                        atomic_read(&tcon->num_locks),
                                        atomic_read(&tcon->num_hardlinks),
                                        atomic_read(&tcon->num_symlinks));
-                               seq_printf(m, "\nOpens: %d Closes: %d"
+                               seq_printf(m, "\nOpens: %d Closes: %d "
                                              "Deletes: %d",
                                        atomic_read(&tcon->num_opens),
                                        atomic_read(&tcon->num_closes),
                                        atomic_read(&tcon->num_deletes));
+                               seq_printf(m, "\nPosix Opens: %d "
+                                             "Posix Mkdirs: %d",
+                                       atomic_read(&tcon->num_posixopens),
+                                       atomic_read(&tcon->num_posixmkdirs));
                                seq_printf(m, "\nMkdirs: %d Rmdirs: %d",
                                        atomic_read(&tcon->num_mkdirs),
                                        atomic_read(&tcon->num_rmdirs));
index 3bb11be8b6a8210271368fc8b6c44942c77a02a7..606912d8f2a885d9272a843e34542adc1cc9c3d0 100644 (file)
@@ -55,7 +55,7 @@ void cifs_dfs_release_automount_timer(void)
  * i.e. strips from UNC trailing path that is not part of share
  * name and fixup missing '\' in the begining of DFS node refferal
  * if neccessary.
- * Returns pointer to share name on success or NULL on error.
+ * Returns pointer to share name on success or ERR_PTR on error.
  * Caller is responsible for freeing returned string.
  */
 static char *cifs_get_share_name(const char *node_name)
@@ -68,7 +68,7 @@ static char *cifs_get_share_name(const char *node_name)
        UNC = kmalloc(len+2 /*for term null and additional \ if it's missed */,
                         GFP_KERNEL);
        if (!UNC)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        /* get share name and server name */
        if (node_name[1] != '\\') {
@@ -87,7 +87,7 @@ static char *cifs_get_share_name(const char *node_name)
                cERROR(1, ("%s: no server name end in node name: %s",
                        __func__, node_name));
                kfree(UNC);
-               return NULL;
+               return ERR_PTR(-EINVAL);
        }
 
        /* find sharename end */
@@ -133,6 +133,12 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
                return ERR_PTR(-EINVAL);
 
        *devname = cifs_get_share_name(ref->node_name);
+       if (IS_ERR(*devname)) {
+               rc = PTR_ERR(*devname);
+               *devname = NULL;
+               goto compose_mount_options_err;
+       }
+
        rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
        if (rc != 0) {
                cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d",
index 4a4581cb2b5e3442e1cc0da0f0a7cd2f6de930bd..051caecf7d677ebb621ba825e7b23962aef957bb 100644 (file)
@@ -86,6 +86,9 @@ struct key_type cifs_spnego_key_type = {
 /* strlen of ";user=" */
 #define USER_KEY_LEN           6
 
+/* strlen of ";pid=0x" */
+#define PID_KEY_LEN            7
+
 /* get a key struct with a SPNEGO security blob, suitable for session setup */
 struct key *
 cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
@@ -103,7 +106,8 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
                   IP_KEY_LEN + INET6_ADDRSTRLEN +
                   MAX_MECH_STR_LEN +
                   UID_KEY_LEN + (sizeof(uid_t) * 2) +
-                  USER_KEY_LEN + strlen(sesInfo->userName) + 1;
+                  USER_KEY_LEN + strlen(sesInfo->userName) +
+                  PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;
 
        spnego_key = ERR_PTR(-ENOMEM);
        description = kzalloc(desc_len, GFP_KERNEL);
@@ -141,6 +145,9 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
        dp = description + strlen(description);
        sprintf(dp, ";user=%s", sesInfo->userName);
 
+       dp = description + strlen(description);
+       sprintf(dp, ";pid=0x%x", current->pid);
+
        cFYI(1, ("key description = %s", description));
        spnego_key = request_key(&cifs_spnego_key_type, description, "");
 
index 60e3c4253de0b9774cb79767966847779c6d92b5..714a542cbafce7f3efbe242339bec3d99a0c929f 100644 (file)
@@ -44,7 +44,7 @@ cifs_ucs2_bytes(const __le16 *from, int maxbytes,
        int maxwords = maxbytes / 2;
        char tmp[NLS_MAX_CHARSET_SIZE];
 
-       for (i = 0; from[i] && i < maxwords; i++) {
+       for (i = 0; i < maxwords && from[i]; i++) {
                charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp,
                                             NLS_MAX_CHARSET_SIZE);
                if (charlen > 0)
index 1403b5d86a739d67725e0dc94db1bec593e5ddab..6941c22398a6ac4097528add80d3ebcbcad2bbc2 100644 (file)
@@ -327,7 +327,7 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
 
 static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
                       struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
-                      struct inode *inode)
+                      struct cifs_fattr *fattr)
 {
        int i;
        int num_aces = 0;
@@ -340,7 +340,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
        if (!pdacl) {
                /* no DACL in the security descriptor, set
                   all the permissions for user/group/other */
-               inode->i_mode |= S_IRWXUGO;
+               fattr->cf_mode |= S_IRWXUGO;
                return;
        }
 
@@ -357,7 +357,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
        /* reset rwx permissions for user/group/other.
           Also, if num_aces is 0 i.e. DACL has no ACEs,
           user/group/other have no permissions */
-       inode->i_mode &= ~(S_IRWXUGO);
+       fattr->cf_mode &= ~(S_IRWXUGO);
 
        acl_base = (char *)pdacl;
        acl_size = sizeof(struct cifs_acl);
@@ -379,17 +379,17 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
                        if (compare_sids(&(ppace[i]->sid), pownersid))
                                access_flags_to_mode(ppace[i]->access_req,
                                                     ppace[i]->type,
-                                                    &(inode->i_mode),
+                                                    &fattr->cf_mode,
                                                     &user_mask);
                        if (compare_sids(&(ppace[i]->sid), pgrpsid))
                                access_flags_to_mode(ppace[i]->access_req,
                                                     ppace[i]->type,
-                                                    &(inode->i_mode),
+                                                    &fattr->cf_mode,
                                                     &group_mask);
                        if (compare_sids(&(ppace[i]->sid), &sid_everyone))
                                access_flags_to_mode(ppace[i]->access_req,
                                                     ppace[i]->type,
-                                                    &(inode->i_mode),
+                                                    &fattr->cf_mode,
                                                     &other_mask);
 
 /*                     memcpy((void *)(&(cifscred->aces[i])),
@@ -464,7 +464,7 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
 
 /* Convert CIFS ACL to POSIX form */
 static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
-                         struct inode *inode)
+                         struct cifs_fattr *fattr)
 {
        int rc;
        struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
@@ -472,7 +472,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
        char *end_of_acl = ((char *)pntsd) + acl_len;
        __u32 dacloffset;
 
-       if ((inode == NULL) || (pntsd == NULL))
+       if (pntsd == NULL)
                return -EIO;
 
        owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
@@ -497,7 +497,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
 
        if (dacloffset)
                parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
-                          group_sid_ptr, inode);
+                          group_sid_ptr, fattr);
        else
                cFYI(1, ("no ACL")); /* BB grant all or default perms? */
 
@@ -508,7 +508,6 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
        memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
                        sizeof(struct cifs_sid)); */
 
-
        return 0;
 }
 
@@ -671,8 +670,9 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
 }
 
 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
-void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode,
-                    const char *path, const __u16 *pfid)
+void
+cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
+                 struct inode *inode, const char *path, const __u16 *pfid)
 {
        struct cifs_ntsd *pntsd = NULL;
        u32 acllen = 0;
@@ -687,7 +687,7 @@ void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode,
 
        /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
        if (pntsd)
-               rc = parse_sec_desc(pntsd, acllen, inode);
+               rc = parse_sec_desc(pntsd, acllen, fattr);
        if (rc)
                cFYI(1, ("parse sec desc failed rc = %d", rc));
 
index 0d92114195ab6adb4e74acaba8d3380f94123356..84b75253b05a01cf13748b33d642e58a515e7c41 100644 (file)
@@ -308,7 +308,6 @@ cifs_alloc_inode(struct super_block *sb)
        if (!cifs_inode)
                return NULL;
        cifs_inode->cifsAttrs = 0x20;   /* default */
-       atomic_set(&cifs_inode->inUse, 0);
        cifs_inode->time = 0;
        cifs_inode->write_behind_rc = 0;
        /* Until the file is open and we have gotten oplock
@@ -333,6 +332,27 @@ cifs_destroy_inode(struct inode *inode)
        kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
 }
 
+static void
+cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
+{
+       seq_printf(s, ",addr=");
+
+       switch (server->addr.sockAddr.sin_family) {
+       case AF_INET:
+               seq_printf(s, "%pI4", &server->addr.sockAddr.sin_addr.s_addr);
+               break;
+       case AF_INET6:
+               seq_printf(s, "%pI6",
+                          &server->addr.sockAddr6.sin6_addr.s6_addr);
+               if (server->addr.sockAddr6.sin6_scope_id)
+                       seq_printf(s, "%%%u",
+                                  server->addr.sockAddr6.sin6_scope_id);
+               break;
+       default:
+               seq_printf(s, "(unknown)");
+       }
+}
+
 /*
  * cifs_show_options() is for displaying mount options in /proc/mounts.
  * Not all settable options are displayed but most of the important
@@ -343,83 +363,68 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
 {
        struct cifs_sb_info *cifs_sb;
        struct cifsTconInfo *tcon;
-       struct TCP_Server_Info *server;
 
        cifs_sb = CIFS_SB(m->mnt_sb);
+       tcon = cifs_sb->tcon;
 
-       if (cifs_sb) {
-               tcon = cifs_sb->tcon;
-               if (tcon) {
-                       seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
-                       if (tcon->ses) {
-                               if (tcon->ses->userName)
-                                       seq_printf(s, ",username=%s",
-                                          tcon->ses->userName);
-                               if (tcon->ses->domainName)
-                                       seq_printf(s, ",domain=%s",
-                                          tcon->ses->domainName);
-                               server = tcon->ses->server;
-                               if (server) {
-                                       seq_printf(s, ",addr=");
-                                       switch (server->addr.sockAddr6.
-                                               sin6_family) {
-                                       case AF_INET6:
-                                               seq_printf(s, "%pI6",
-                                                          &server->addr.sockAddr6.sin6_addr);
-                                               break;
-                                       case AF_INET:
-                                               seq_printf(s, "%pI4",
-                                                          &server->addr.sockAddr.sin_addr.s_addr);
-                                               break;
-                                       }
-                               }
-                       }
-                       if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
-                          !(tcon->unix_ext))
-                               seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
-                       if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
-                          !(tcon->unix_ext))
-                               seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
-                       if (!tcon->unix_ext) {
-                               seq_printf(s, ",file_mode=0%o,dir_mode=0%o",
+       seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName);
+       if (tcon->ses->userName)
+               seq_printf(s, ",username=%s", tcon->ses->userName);
+       if (tcon->ses->domainName)
+               seq_printf(s, ",domain=%s", tcon->ses->domainName);
+
+       seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
+               seq_printf(s, ",forceuid");
+       else
+               seq_printf(s, ",noforceuid");
+
+       seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
+               seq_printf(s, ",forcegid");
+       else
+               seq_printf(s, ",noforcegid");
+
+       cifs_show_address(s, tcon->ses->server);
+
+       if (!tcon->unix_ext)
+               seq_printf(s, ",file_mode=0%o,dir_mode=0%o",
                                           cifs_sb->mnt_file_mode,
                                           cifs_sb->mnt_dir_mode);
-                       }
-                       if (tcon->seal)
-                               seq_printf(s, ",seal");
-                       if (tcon->nocase)
-                               seq_printf(s, ",nocase");
-                       if (tcon->retry)
-                               seq_printf(s, ",hard");
-               }
-               if (cifs_sb->prepath)
-                       seq_printf(s, ",prepath=%s", cifs_sb->prepath);
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
-                       seq_printf(s, ",posixpaths");
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
-                       seq_printf(s, ",setuids");
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
-                       seq_printf(s, ",serverino");
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
-                       seq_printf(s, ",directio");
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
-                       seq_printf(s, ",nouser_xattr");
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
-                       seq_printf(s, ",mapchars");
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
-                       seq_printf(s, ",sfu");
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
-                       seq_printf(s, ",nobrl");
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
-                       seq_printf(s, ",cifsacl");
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
-                       seq_printf(s, ",dynperm");
-               if (m->mnt_sb->s_flags & MS_POSIXACL)
-                       seq_printf(s, ",acl");
-
-               seq_printf(s, ",rsize=%d", cifs_sb->rsize);
-               seq_printf(s, ",wsize=%d", cifs_sb->wsize);
-       }
+       if (tcon->seal)
+               seq_printf(s, ",seal");
+       if (tcon->nocase)
+               seq_printf(s, ",nocase");
+       if (tcon->retry)
+               seq_printf(s, ",hard");
+       if (cifs_sb->prepath)
+               seq_printf(s, ",prepath=%s", cifs_sb->prepath);
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
+               seq_printf(s, ",posixpaths");
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
+               seq_printf(s, ",setuids");
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
+               seq_printf(s, ",serverino");
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+               seq_printf(s, ",directio");
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
+               seq_printf(s, ",nouser_xattr");
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
+               seq_printf(s, ",mapchars");
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
+               seq_printf(s, ",sfu");
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+               seq_printf(s, ",nobrl");
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
+               seq_printf(s, ",cifsacl");
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
+               seq_printf(s, ",dynperm");
+       if (m->mnt_sb->s_flags & MS_POSIXACL)
+               seq_printf(s, ",acl");
+
+       seq_printf(s, ",rsize=%d", cifs_sb->rsize);
+       seq_printf(s, ",wsize=%d", cifs_sb->wsize);
+
        return 0;
 }
 
@@ -535,9 +540,14 @@ static void cifs_umount_begin(struct super_block *sb)
        if (tcon == NULL)
                return;
 
-       lock_kernel();
        read_lock(&cifs_tcp_ses_lock);
-       if (tcon->tc_count == 1)
+       if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) {
+               /* we have other mounts to same share or we have
+                  already tried to force umount this and woken up
+                  all waiting network requests, nothing to do */
+               read_unlock(&cifs_tcp_ses_lock);
+               return;
+       } else if (tcon->tc_count == 1)
                tcon->tidStatus = CifsExiting;
        read_unlock(&cifs_tcp_ses_lock);
 
@@ -552,9 +562,7 @@ static void cifs_umount_begin(struct super_block *sb)
                wake_up_all(&tcon->ses->server->response_q);
                msleep(1);
        }
-/* BB FIXME - finish add checks for tidStatus BB */
 
-       unlock_kernel();
        return;
 }
 
index 9570a0e8023f4258941d1f4cdc0e8141188a622d..6c170948300d9be5cc6d8cc47eac8d73053bf390 100644 (file)
 
 #define ROOT_I 2
 
+/*
+ * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down
+ * so that it will fit.
+ */
+static inline ino_t
+cifs_uniqueid_to_ino_t(u64 fileid)
+{
+       ino_t ino = (ino_t) fileid;
+       if (sizeof(ino_t) < sizeof(u64))
+               ino ^= fileid >> (sizeof(u64)-sizeof(ino_t)) * 8;
+       return ino;
+}
+
 extern struct file_system_type cifs_fs_type;
 extern const struct address_space_operations cifs_addr_ops;
 extern const struct address_space_operations cifs_addr_ops_smallbuf;
@@ -100,5 +113,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
 extern const struct export_operations cifs_export_ops;
 #endif /* EXPERIMENTAL */
 
-#define CIFS_VERSION   "1.59"
+#define CIFS_VERSION   "1.60"
 #endif                         /* _CIFSFS_H */
index a61ab772c6f633dde7ac0e5628214b0bc8c4268f..6084d6379c03fb95ddf268e33ba903a55aa3b7c7 100644 (file)
@@ -83,7 +83,7 @@ enum securityEnum {
        NTLM,                   /* Legacy NTLM012 auth with NTLM hash */
        NTLMv2,                 /* Legacy NTLM auth with NTLMv2 hash */
        RawNTLMSSP,             /* NTLMSSP without SPNEGO, NTLMv2 hash */
-       NTLMSSP,                /* NTLMSSP via SPNEGO, NTLMv2 hash */
+/*     NTLMSSP, */ /* can use rawNTLMSSP instead of NTLMSSP via SPNEGO */
        Kerberos,               /* Kerberos via SPNEGO */
        MSKerberos,             /* MS Kerberos via SPNEGO */
 };
@@ -260,6 +260,8 @@ struct cifsTconInfo {
        atomic_t num_closes;
        atomic_t num_deletes;
        atomic_t num_mkdirs;
+       atomic_t num_posixopens;
+       atomic_t num_posixmkdirs;
        atomic_t num_rmdirs;
        atomic_t num_renames;
        atomic_t num_t2renames;
@@ -364,13 +366,13 @@ struct cifsInodeInfo {
        struct list_head openFileList;
        int write_behind_rc;
        __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
-       atomic_t inUse;  /* num concurrent users (local openers cifs) of file*/
        unsigned long time;     /* jiffies of last update/check of inode */
        bool clientCanCacheRead:1;      /* read oplock */
        bool clientCanCacheAll:1;       /* read and writebehind oplock */
        bool oplockPending:1;
        bool delete_pending:1;          /* DELETE_ON_CLOSE is set */
        u64  server_eof;                /* current file size on server */
+       u64  uniqueid;                  /* server inode number */
        struct inode vfs_inode;
 };
 
@@ -472,6 +474,32 @@ struct dfs_info3_param {
        char *node_name;
 };
 
+/*
+ * common struct for holding inode info when searching for or updating an
+ * inode with new info
+ */
+
+#define CIFS_FATTR_DFS_REFERRAL                0x1
+#define CIFS_FATTR_DELETE_PENDING      0x2
+#define CIFS_FATTR_NEED_REVAL          0x4
+
+struct cifs_fattr {
+       u32             cf_flags;
+       u32             cf_cifsattrs;
+       u64             cf_uniqueid;
+       u64             cf_eof;
+       u64             cf_bytes;
+       uid_t           cf_uid;
+       gid_t           cf_gid;
+       umode_t         cf_mode;
+       dev_t           cf_rdev;
+       unsigned int    cf_nlink;
+       unsigned int    cf_dtype;
+       struct timespec cf_atime;
+       struct timespec cf_mtime;
+       struct timespec cf_ctime;
+};
+
 static inline void free_dfs_info_param(struct dfs_info3_param *param)
 {
        if (param) {
index a785f69dbc9feecd616eba56dfaa47e8ab74b392..2d07f890a842f1fac459c39d2d53044a9c19df91 100644 (file)
@@ -2328,19 +2328,7 @@ struct file_attrib_tag {
 typedef struct {
        __le32 NextEntryOffset;
        __u32 ResumeKey; /* as with FileIndex - no need to convert */
-       __le64 EndOfFile;
-       __le64 NumOfBytes;
-       __le64 LastStatusChange; /*SNIA specs DCE time for the 3 time fields */
-       __le64 LastAccessTime;
-       __le64 LastModificationTime;
-       __le64 Uid;
-       __le64 Gid;
-       __le32 Type;
-       __le64 DevMajor;
-       __le64 DevMinor;
-       __le64 UniqueId;
-       __le64 Permissions;
-       __le64 Nlinks;
+       FILE_UNIX_BASIC_INFO basic;
        char FileName[1];
 } __attribute__((packed)) FILE_UNIX_INFO; /* level 0x202 */
 
index f9452329bcce5b02929c5090a79220170d329813..da8fbf565991906320359743d0860ee0d026b812 100644 (file)
@@ -74,7 +74,7 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr);
 extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
 extern int decode_negTokenInit(unsigned char *security_blob, int length,
                        enum securityEnum *secType);
-extern int cifs_inet_pton(const int, const char *source, void *dst);
+extern int cifs_convert_address(char *src, void *dst);
 extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr);
 extern void header_assemble(struct smb_hdr *, char /* command */ ,
                            const struct cifsTconInfo *, int /* length of
@@ -98,9 +98,13 @@ extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
 extern int cifs_posix_open(char *full_path, struct inode **pinode,
                           struct super_block *sb, int mode, int oflags,
                           int *poplock, __u16 *pnetfid, int xid);
-extern void posix_fill_in_inode(struct inode *tmp_inode,
-                               FILE_UNIX_BASIC_INFO *pData, int isNewInode);
-extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum);
+extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
+                                    FILE_UNIX_BASIC_INFO *info,
+                                    struct cifs_sb_info *cifs_sb);
+extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr);
+extern struct inode *cifs_iget(struct super_block *sb,
+                              struct cifs_fattr *fattr);
+
 extern int cifs_get_inode_info(struct inode **pinode,
                        const unsigned char *search_path,
                        FILE_ALL_INFO *pfile_info,
@@ -108,8 +112,9 @@ extern int cifs_get_inode_info(struct inode **pinode,
 extern int cifs_get_inode_info_unix(struct inode **pinode,
                        const unsigned char *search_path,
                        struct super_block *sb, int xid);
-extern void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode,
-                           const char *path, const __u16 *pfid);
+extern void cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
+                             struct cifs_fattr *fattr, struct inode *inode,
+                             const char *path, const __u16 *pfid);
 extern int mode_to_acl(struct inode *inode, const char *path, __u64);
 
 extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
@@ -215,7 +220,11 @@ struct cifs_unix_set_info_args {
        dev_t   device;
 };
 
-extern int CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *pTcon,
+extern int CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
+                                 const struct cifs_unix_set_info_args *args,
+                                 u16 fid, u32 pid_of_opener);
+
+extern int CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *pTcon,
                        char *fileName,
                        const struct cifs_unix_set_info_args *args,
                        const struct nls_table *nls_codepage,
index b84c61d5bca419d2ea221484636508f1ddaceaa1..1866bc2927d4f376182e98e71182fcff345f0a71 100644 (file)
@@ -594,7 +594,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
        else if (secFlags & CIFSSEC_MAY_KRB5)
                server->secType = Kerberos;
        else if (secFlags & CIFSSEC_MAY_NTLMSSP)
-               server->secType = NTLMSSP;
+               server->secType = RawNTLMSSP;
        else if (secFlags & CIFSSEC_MAY_LANMAN)
                server->secType = LANMAN;
 /* #ifdef CONFIG_CIFS_EXPERIMENTAL
@@ -729,7 +729,7 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
         * the tcon is no longer on the list, so no need to take lock before
         * checking this.
         */
-       if (tcon->need_reconnect)
+       if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
                return 0;
 
        rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
@@ -1113,7 +1113,10 @@ PsxCreat:
 psx_create_err:
        cifs_buf_release(pSMB);
 
-       cifs_stats_inc(&tcon->num_mkdirs);
+       if (posix_flags & SMB_O_DIRECTORY)
+               cifs_stats_inc(&tcon->num_posixmkdirs);
+       else
+               cifs_stats_inc(&tcon->num_posixopens);
 
        if (rc == -EAGAIN)
                goto PsxCreat;
@@ -5074,10 +5077,114 @@ SetAttrLgcyRetry:
 }
 #endif /* temporarily unneeded SetAttr legacy function */
 
+static void
+cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
+                       const struct cifs_unix_set_info_args *args)
+{
+       u64 mode = args->mode;
+
+       /*
+        * Samba server ignores set of file size to zero due to bugs in some
+        * older clients, but we should be precise - we use SetFileSize to
+        * set file size and do not want to truncate file size to zero
+        * accidently as happened on one Samba server beta by putting
+        * zero instead of -1 here
+        */
+       data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
+       data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
+       data_offset->LastStatusChange = cpu_to_le64(args->ctime);
+       data_offset->LastAccessTime = cpu_to_le64(args->atime);
+       data_offset->LastModificationTime = cpu_to_le64(args->mtime);
+       data_offset->Uid = cpu_to_le64(args->uid);
+       data_offset->Gid = cpu_to_le64(args->gid);
+       /* better to leave device as zero when it is  */
+       data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
+       data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
+       data_offset->Permissions = cpu_to_le64(mode);
+
+       if (S_ISREG(mode))
+               data_offset->Type = cpu_to_le32(UNIX_FILE);
+       else if (S_ISDIR(mode))
+               data_offset->Type = cpu_to_le32(UNIX_DIR);
+       else if (S_ISLNK(mode))
+               data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
+       else if (S_ISCHR(mode))
+               data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
+       else if (S_ISBLK(mode))
+               data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
+       else if (S_ISFIFO(mode))
+               data_offset->Type = cpu_to_le32(UNIX_FIFO);
+       else if (S_ISSOCK(mode))
+               data_offset->Type = cpu_to_le32(UNIX_SOCKET);
+}
+
 int
-CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
-                  const struct cifs_unix_set_info_args *args,
-                  const struct nls_table *nls_codepage, int remap)
+CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon,
+                      const struct cifs_unix_set_info_args *args,
+                      u16 fid, u32 pid_of_opener)
+{
+       struct smb_com_transaction2_sfi_req *pSMB  = NULL;
+       FILE_UNIX_BASIC_INFO *data_offset;
+       int rc = 0;
+       u16 params, param_offset, offset, byte_count, count;
+
+       cFYI(1, ("Set Unix Info (via SetFileInfo)"));
+       rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
+
+       if (rc)
+               return rc;
+
+       pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+       pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
+
+       params = 6;
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+       pSMB->Flags = 0;
+       pSMB->Timeout = 0;
+       pSMB->Reserved2 = 0;
+       param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
+       offset = param_offset + params;
+
+       data_offset = (FILE_UNIX_BASIC_INFO *)
+                               ((char *)(&pSMB->hdr.Protocol) + offset);
+       count = sizeof(FILE_UNIX_BASIC_INFO);
+
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+       /* BB find max SMB PDU from sess */
+       pSMB->MaxDataCount = cpu_to_le16(1000);
+       pSMB->SetupCount = 1;
+       pSMB->Reserved3 = 0;
+       pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
+       byte_count = 3 /* pad */  + params + count;
+       pSMB->DataCount = cpu_to_le16(count);
+       pSMB->ParameterCount = cpu_to_le16(params);
+       pSMB->TotalDataCount = pSMB->DataCount;
+       pSMB->TotalParameterCount = pSMB->ParameterCount;
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
+       pSMB->Fid = fid;
+       pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
+       pSMB->Reserved4 = 0;
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+
+       cifs_fill_unix_set_info(data_offset, args);
+
+       rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0);
+       if (rc)
+               cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc));
+
+       /* Note: On -EAGAIN error only caller can retry on handle based calls
+               since file handle passed in no longer valid */
+
+       return rc;
+}
+
+int
+CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
+                      const struct cifs_unix_set_info_args *args,
+                      const struct nls_table *nls_codepage, int remap)
 {
        TRANSACTION2_SPI_REQ *pSMB = NULL;
        TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -5086,7 +5193,6 @@ CIFSSMBUnixSetInfo(const int xid, struct cifsTconInfo *tcon, char *fileName,
        int bytes_returned = 0;
        FILE_UNIX_BASIC_INFO *data_offset;
        __u16 params, param_offset, offset, count, byte_count;
-       __u64 mode = args->mode;
 
        cFYI(1, ("In SetUID/GID/Mode"));
 setPermsRetry:
@@ -5137,38 +5243,8 @@ setPermsRetry:
        pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
        pSMB->Reserved4 = 0;
        pSMB->hdr.smb_buf_length += byte_count;
-       /* Samba server ignores set of file size to zero due to bugs in some
-       older clients, but we should be precise - we use SetFileSize to
-       set file size and do not want to truncate file size to zero
-       accidently as happened on one Samba server beta by putting
-       zero instead of -1 here */
-       data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
-       data_offset->NumOfBytes = cpu_to_le64(NO_CHANGE_64);
-       data_offset->LastStatusChange = cpu_to_le64(args->ctime);
-       data_offset->LastAccessTime = cpu_to_le64(args->atime);
-       data_offset->LastModificationTime = cpu_to_le64(args->mtime);
-       data_offset->Uid = cpu_to_le64(args->uid);
-       data_offset->Gid = cpu_to_le64(args->gid);
-       /* better to leave device as zero when it is  */
-       data_offset->DevMajor = cpu_to_le64(MAJOR(args->device));
-       data_offset->DevMinor = cpu_to_le64(MINOR(args->device));
-       data_offset->Permissions = cpu_to_le64(mode);
-
-       if (S_ISREG(mode))
-               data_offset->Type = cpu_to_le32(UNIX_FILE);
-       else if (S_ISDIR(mode))
-               data_offset->Type = cpu_to_le32(UNIX_DIR);
-       else if (S_ISLNK(mode))
-               data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
-       else if (S_ISCHR(mode))
-               data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
-       else if (S_ISBLK(mode))
-               data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
-       else if (S_ISFIFO(mode))
-               data_offset->Type = cpu_to_le32(UNIX_FIFO);
-       else if (S_ISSOCK(mode))
-               data_offset->Type = cpu_to_le32(UNIX_SOCKET);
 
+       cifs_fill_unix_set_info(data_offset, args);
 
        pSMB->ByteCount = cpu_to_le16(byte_count);
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
index 97f4311b9a8ea2f40325ac2fda8a2929153402eb..1f3345d7fa79a5e5dffc6f7be54f9734873ed3da 100644 (file)
@@ -70,7 +70,6 @@ struct smb_vol {
        mode_t file_mode;
        mode_t dir_mode;
        unsigned secFlg;
-       bool rw:1;
        bool retry:1;
        bool intr:1;
        bool setuids:1;
@@ -804,6 +803,10 @@ cifs_parse_mount_options(char *options, const char *devname,
        char *data;
        unsigned int  temp_len, i, j;
        char separator[2];
+       short int override_uid = -1;
+       short int override_gid = -1;
+       bool uid_specified = false;
+       bool gid_specified = false;
 
        separator[0] = ',';
        separator[1] = 0;
@@ -832,7 +835,6 @@ cifs_parse_mount_options(char *options, const char *devname,
        vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR;
 
        /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
-       vol->rw = true;
        /* default is always to request posix paths. */
        vol->posix_paths = 1;
        /* default to using server inode numbers where available */
@@ -1095,18 +1097,20 @@ cifs_parse_mount_options(char *options, const char *devname,
                                                    "too long.\n");
                                return 1;
                        }
-               } else if (strnicmp(data, "uid", 3) == 0) {
-                       if (value && *value)
-                               vol->linux_uid =
-                                       simple_strtoul(value, &value, 0);
-               } else if (strnicmp(data, "forceuid", 8) == 0) {
-                               vol->override_uid = 1;
-               } else if (strnicmp(data, "gid", 3) == 0) {
-                       if (value && *value)
-                               vol->linux_gid =
-                                       simple_strtoul(value, &value, 0);
-               } else if (strnicmp(data, "forcegid", 8) == 0) {
-                               vol->override_gid = 1;
+               } else if (!strnicmp(data, "uid", 3) && value && *value) {
+                       vol->linux_uid = simple_strtoul(value, &value, 0);
+                       uid_specified = true;
+               } else if (!strnicmp(data, "forceuid", 8)) {
+                       override_uid = 1;
+               } else if (!strnicmp(data, "noforceuid", 10)) {
+                       override_uid = 0;
+               } else if (!strnicmp(data, "gid", 3) && value && *value) {
+                       vol->linux_gid = simple_strtoul(value, &value, 0);
+                       gid_specified = true;
+               } else if (!strnicmp(data, "forcegid", 8)) {
+                       override_gid = 1;
+               } else if (!strnicmp(data, "noforcegid", 10)) {
+                       override_gid = 0;
                } else if (strnicmp(data, "file_mode", 4) == 0) {
                        if (value && *value) {
                                vol->file_mode =
@@ -1199,7 +1203,9 @@ cifs_parse_mount_options(char *options, const char *devname,
                } else if (strnicmp(data, "guest", 5) == 0) {
                        /* ignore */
                } else if (strnicmp(data, "rw", 2) == 0) {
-                       vol->rw = true;
+                       /* ignore */
+               } else if (strnicmp(data, "ro", 2) == 0) {
+                       /* ignore */
                } else if (strnicmp(data, "noblocksend", 11) == 0) {
                        vol->noblocksnd = 1;
                } else if (strnicmp(data, "noautotune", 10) == 0) {
@@ -1218,8 +1224,6 @@ cifs_parse_mount_options(char *options, const char *devname,
                            parse these options again and set anything and it
                            is ok to just ignore them */
                        continue;
-               } else if (strnicmp(data, "ro", 2) == 0) {
-                       vol->rw = false;
                } else if (strnicmp(data, "hard", 4) == 0) {
                        vol->retry = 1;
                } else if (strnicmp(data, "soft", 4) == 0) {
@@ -1357,6 +1361,18 @@ cifs_parse_mount_options(char *options, const char *devname,
        if (vol->UNCip == NULL)
                vol->UNCip = &vol->UNC[2];
 
+       if (uid_specified)
+               vol->override_uid = override_uid;
+       else if (override_uid == 1)
+               printk(KERN_NOTICE "CIFS: ignoring forceuid mount option "
+                                  "specified with no uid= option.\n");
+
+       if (gid_specified)
+               vol->override_gid = override_gid;
+       else if (override_gid == 1)
+               printk(KERN_NOTICE "CIFS: ignoring forcegid mount option "
+                                  "specified with no gid= option.\n");
+
        return 0;
 }
 
@@ -1386,8 +1402,10 @@ cifs_find_tcp_session(struct sockaddr_storage *addr)
                     server->addr.sockAddr.sin_addr.s_addr))
                        continue;
                else if (addr->ss_family == AF_INET6 &&
-                        !ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr,
-                                         &addr6->sin6_addr))
+                        (!ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr,
+                                          &addr6->sin6_addr) ||
+                         server->addr.sockAddr6.sin6_scope_id !=
+                                          addr6->sin6_scope_id))
                        continue;
 
                ++server->srv_count;
@@ -1433,28 +1451,15 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
 
        memset(&addr, 0, sizeof(struct sockaddr_storage));
 
-       if (volume_info->UNCip && volume_info->UNC) {
-               rc = cifs_inet_pton(AF_INET, volume_info->UNCip,
-                                   &sin_server->sin_addr.s_addr);
-
-               if (rc <= 0) {
-                       /* not ipv4 address, try ipv6 */
-                       rc = cifs_inet_pton(AF_INET6, volume_info->UNCip,
-                                           &sin_server6->sin6_addr.in6_u);
-                       if (rc > 0)
-                               addr.ss_family = AF_INET6;
-               } else {
-                       addr.ss_family = AF_INET;
-               }
+       cFYI(1, ("UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip));
 
-               if (rc <= 0) {
+       if (volume_info->UNCip && volume_info->UNC) {
+               rc = cifs_convert_address(volume_info->UNCip, &addr);
+               if (!rc) {
                        /* we failed translating address */
                        rc = -EINVAL;
                        goto out_err;
                }
-
-               cFYI(1, ("UNC: %s ip: %s", volume_info->UNC,
-                        volume_info->UNCip));
        } else if (volume_info->UNCip) {
                /* BB using ip addr as tcp_ses name to connect to the
                   DFS root below */
@@ -1513,14 +1518,14 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
                cFYI(1, ("attempting ipv6 connect"));
                /* BB should we allow ipv6 on port 139? */
                /* other OS never observed in Wild doing 139 with v6 */
+               sin_server6->sin6_port = htons(volume_info->port);
                memcpy(&tcp_ses->addr.sockAddr6, sin_server6,
                        sizeof(struct sockaddr_in6));
-               sin_server6->sin6_port = htons(volume_info->port);
                rc = ipv6_connect(tcp_ses);
        } else {
+               sin_server->sin_port = htons(volume_info->port);
                memcpy(&tcp_ses->addr.sockAddr, sin_server,
                        sizeof(struct sockaddr_in));
-               sin_server->sin_port = htons(volume_info->port);
                rc = ipv4_connect(tcp_ses);
        }
        if (rc < 0) {
@@ -2465,10 +2470,10 @@ try_mount_again:
                tcon->local_lease = volume_info->local_lease;
        }
        if (pSesInfo) {
-               if (pSesInfo->capabilities & CAP_LARGE_FILES) {
-                       sb->s_maxbytes = (u64) 1 << 63;
-               else
-                       sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
+               if (pSesInfo->capabilities & CAP_LARGE_FILES)
+                       sb->s_maxbytes = MAX_LFS_FILESIZE;
+               else
+                       sb->s_maxbytes = MAX_NON_LFS;
        }
 
        /* BB FIXME fix time_gran to be larger for LANMAN sessions */
@@ -2557,11 +2562,20 @@ remote_path_check:
 
                        if (mount_data != mount_data_global)
                                kfree(mount_data);
+
                        mount_data = cifs_compose_mount_options(
                                        cifs_sb->mountdata, full_path + 1,
                                        referrals, &fake_devname);
-                       kfree(fake_devname);
+
                        free_dfs_info_array(referrals, num_referrals);
+                       kfree(fake_devname);
+                       kfree(full_path);
+
+                       if (IS_ERR(mount_data)) {
+                               rc = PTR_ERR(mount_data);
+                               mount_data = NULL;
+                               goto mount_fail_check;
+                       }
 
                        if (tcon)
                                cifs_put_tcon(tcon);
@@ -2569,8 +2583,6 @@ remote_path_check:
                                cifs_put_smb_ses(pSesInfo);
 
                        cleanup_volume_info(&volume_info);
-                       FreeXid(xid);
-                       kfree(full_path);
                        referral_walks_count++;
                        goto try_mount_again;
                }
@@ -2739,6 +2751,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
                strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
 
                /* mostly informational -- no need to fail on error here */
+               kfree(tcon->nativeFileSystem);
                tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
                                                      bytes_left, is_unicode,
                                                      nls_codepage);
index 3758965d73d56c8b281a3ea055b2eb27eed3892d..4326ffd90fa91b92086ab993bcfe7631396c7cf4 100644 (file)
@@ -188,6 +188,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
        FILE_UNIX_BASIC_INFO *presp_data;
        __u32 posix_flags = 0;
        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+       struct cifs_fattr fattr;
 
        cFYI(1, ("posix open %s", full_path));
 
@@ -236,22 +237,21 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
        if (presp_data->Type == cpu_to_le32(-1))
                goto posix_open_ret; /* open ok, caller does qpathinfo */
 
-       /* get new inode and set it up */
        if (!pinode)
                goto posix_open_ret; /* caller does not need info */
 
+       cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
+
+       /* get new inode and set it up */
        if (*pinode == NULL) {
-               __u64 unique_id = le64_to_cpu(presp_data->UniqueId);
-               *pinode = cifs_new_inode(sb, &unique_id);
+               *pinode = cifs_iget(sb, &fattr);
+               if (!*pinode) {
+                       rc = -ENOMEM;
+                       goto posix_open_ret;
+               }
+       } else {
+               cifs_fattr_to_inode(*pinode, &fattr);
        }
-       /* else an inode was passed in. Update its info, don't create one */
-
-       /* We do not need to close the file if new_inode fails since
-          the caller will retry qpathinfo as long as inode is null */
-       if (*pinode == NULL)
-               goto posix_open_ret;
-
-       posix_fill_in_inode(*pinode, presp_data, 1);
 
        cifs_fill_fileinfo(*pinode, *pnetfid, cifs_sb->tcon, write_only);
 
@@ -307,8 +307,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
 
        full_path = build_path_from_dentry(direntry);
        if (full_path == NULL) {
+               rc = -ENOMEM;
                FreeXid(xid);
-               return -ENOMEM;
+               return rc;
        }
 
        if (oplockEnabled)
@@ -424,9 +425,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                        args.uid = NO_CHANGE_64;
                        args.gid = NO_CHANGE_64;
                }
-               CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
-                       cifs_sb->local_nls,
-                       cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+               CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
+                                       cifs_sb->local_nls,
+                                       cifs_sb->mnt_cifs_flags &
+                                               CIFS_MOUNT_MAP_SPECIAL_CHR);
        } else {
                /* BB implement mode setting via Windows security
                   descriptors e.g. */
@@ -514,10 +516,10 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
                        args.uid = NO_CHANGE_64;
                        args.gid = NO_CHANGE_64;
                }
-               rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path,
-                       &args, cifs_sb->local_nls,
-                       cifs_sb->mnt_cifs_flags &
-                               CIFS_MOUNT_MAP_SPECIAL_CHR);
+               rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
+                                           cifs_sb->local_nls,
+                                           cifs_sb->mnt_cifs_flags &
+                                               CIFS_MOUNT_MAP_SPECIAL_CHR);
 
                if (!rc) {
                        rc = cifs_get_inode_info_unix(&newinode, full_path,
@@ -540,8 +542,9 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
                        buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
                        if (buf == NULL) {
                                kfree(full_path);
+                               rc = -ENOMEM;
                                FreeXid(xid);
-                               return -ENOMEM;
+                               return rc;
                        }
 
                        rc = CIFSSMBOpen(xid, pTcon, full_path,
@@ -641,6 +644,15 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
                        }
        }
 
+       /*
+        * O_EXCL: optimize away the lookup, but don't hash the dentry. Let
+        * the VFS handle the create.
+        */
+       if (nd->flags & LOOKUP_EXCL) {
+               d_instantiate(direntry, NULL);
+               return 0;
+       }
+
        /* can not grab the rename sem here since it would
        deadlock in the cases (beginning of sys_rename itself)
        in which we already have the sb rename sem */
index df4a306f697efc9c5772d52ae88045095b28e077..87948147d7ece68d64e7218c8331624410ac2196 100644 (file)
  *             0 - name is not IP
  */
 static int
-is_ip(const char *name)
+is_ip(char *name)
 {
-       int rc;
-       struct sockaddr_in sin_server;
-       struct sockaddr_in6 sin_server6;
-
-       rc = cifs_inet_pton(AF_INET, name,
-                       &sin_server.sin_addr.s_addr);
-
-       if (rc <= 0) {
-               /* not ipv4 address, try ipv6 */
-               rc = cifs_inet_pton(AF_INET6, name,
-                               &sin_server6.sin6_addr.in6_u);
-               if (rc > 0)
-                       return 1;
-       } else {
-               return 1;
-       }
-       /* we failed translating address */
-       return 0;
+       struct sockaddr_storage ss;
+
+       return cifs_convert_address(name, &ss);
 }
 
 static int
@@ -72,7 +57,7 @@ dns_resolver_instantiate(struct key *key, const void *data,
        ip[datalen] = '\0';
 
        /* make sure this looks like an address */
-       if (!is_ip((const char *) ip)) {
+       if (!is_ip(ip)) {
                kfree(ip);
                return -EINVAL;
        }
index 06866841b97f1b9993ea3dd577f3f4478d06880e..c34b7f8a217b383b1f8505822f00052276779833 100644 (file)
@@ -300,14 +300,16 @@ int cifs_open(struct inode *inode, struct file *file)
        pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
        pCifsFile = cifs_fill_filedata(file);
        if (pCifsFile) {
+               rc = 0;
                FreeXid(xid);
-               return 0;
+               return rc;
        }
 
        full_path = build_path_from_dentry(file->f_path.dentry);
        if (full_path == NULL) {
+               rc = -ENOMEM;
                FreeXid(xid);
-               return -ENOMEM;
+               return rc;
        }
 
        cFYI(1, ("inode = 0x%p file flags are 0x%x for %s",
@@ -446,9 +448,9 @@ int cifs_open(struct inode *inode, struct file *file)
                                .mtime  = NO_CHANGE_64,
                                .device = 0,
                        };
-                       CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
-                                           cifs_sb->local_nls,
-                                           cifs_sb->mnt_cifs_flags &
+                       CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
+                                              cifs_sb->local_nls,
+                                              cifs_sb->mnt_cifs_flags &
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
                }
        }
@@ -491,11 +493,12 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
                return -EBADF;
 
        xid = GetXid();
-       mutex_unlock(&pCifsFile->fh_mutex);
+       mutex_lock(&pCifsFile->fh_mutex);
        if (!pCifsFile->invalidHandle) {
-               mutex_lock(&pCifsFile->fh_mutex);
+               mutex_unlock(&pCifsFile->fh_mutex);
+               rc = 0;
                FreeXid(xid);
-               return 0;
+               return rc;
        }
 
        if (file->f_path.dentry == NULL) {
@@ -524,7 +527,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
        if (full_path == NULL) {
                rc = -ENOMEM;
 reopen_error_exit:
-               mutex_lock(&pCifsFile->fh_mutex);
+               mutex_unlock(&pCifsFile->fh_mutex);
                FreeXid(xid);
                return rc;
        }
@@ -566,14 +569,14 @@ reopen_error_exit:
                         cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
                                CIFS_MOUNT_MAP_SPECIAL_CHR);
        if (rc) {
-               mutex_lock(&pCifsFile->fh_mutex);
+               mutex_unlock(&pCifsFile->fh_mutex);
                cFYI(1, ("cifs_open returned 0x%x", rc));
                cFYI(1, ("oplock: %d", oplock));
        } else {
 reopen_success:
                pCifsFile->netfid = netfid;
                pCifsFile->invalidHandle = false;
-               mutex_lock(&pCifsFile->fh_mutex);
+               mutex_unlock(&pCifsFile->fh_mutex);
                pCifsInode = CIFS_I(inode);
                if (pCifsInode) {
                        if (can_flush) {
@@ -845,8 +848,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
        tcon = cifs_sb->tcon;
 
        if (file->private_data == NULL) {
+               rc = -EBADF;
                FreeXid(xid);
-               return -EBADF;
+               return rc;
        }
        netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
 
@@ -1805,8 +1809,9 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
        pTcon = cifs_sb->tcon;
 
        if (file->private_data == NULL) {
+               rc = -EBADF;
                FreeXid(xid);
-               return -EBADF;
+               return rc;
        }
        open_file = (struct cifsFileInfo *)file->private_data;
 
@@ -1885,8 +1890,9 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
        pTcon = cifs_sb->tcon;
 
        if (file->private_data == NULL) {
+               rc = -EBADF;
                FreeXid(xid);
-               return -EBADF;
+               return rc;
        }
        open_file = (struct cifsFileInfo *)file->private_data;
 
@@ -2019,8 +2025,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
 
        xid = GetXid();
        if (file->private_data == NULL) {
+               rc = -EBADF;
                FreeXid(xid);
-               return -EBADF;
+               return rc;
        }
        open_file = (struct cifsFileInfo *)file->private_data;
        cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
@@ -2185,8 +2192,9 @@ static int cifs_readpage(struct file *file, struct page *page)
        xid = GetXid();
 
        if (file->private_data == NULL) {
+               rc = -EBADF;
                FreeXid(xid);
-               return -EBADF;
+               return rc;
        }
 
        cFYI(1, ("readpage %p at offset %d 0x%x\n",
index fad882b075ba50358b113e58808b9845f6baca4c..82d83839655eed195fa91dd10120e048309bd287 100644 (file)
@@ -77,239 +77,202 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
        }
 }
 
-static void cifs_unix_info_to_inode(struct inode *inode,
-               FILE_UNIX_BASIC_INFO *info, int force_uid_gid)
+/* populate an inode with info from a cifs_fattr struct */
+void
+cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
 {
+       struct cifsInodeInfo *cifs_i = CIFS_I(inode);
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-       struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
-       __u64 num_of_bytes = le64_to_cpu(info->NumOfBytes);
-       __u64 end_of_file = le64_to_cpu(info->EndOfFile);
+       unsigned long oldtime = cifs_i->time;
+
+       inode->i_atime = fattr->cf_atime;
+       inode->i_mtime = fattr->cf_mtime;
+       inode->i_ctime = fattr->cf_ctime;
+       inode->i_rdev = fattr->cf_rdev;
+       inode->i_nlink = fattr->cf_nlink;
+       inode->i_uid = fattr->cf_uid;
+       inode->i_gid = fattr->cf_gid;
+
+       /* if dynperm is set, don't clobber existing mode */
+       if (inode->i_state & I_NEW ||
+           !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
+               inode->i_mode = fattr->cf_mode;
+
+       cifs_i->cifsAttrs = fattr->cf_cifsattrs;
+       cifs_i->uniqueid = fattr->cf_uniqueid;
+
+       if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
+               cifs_i->time = 0;
+       else
+               cifs_i->time = jiffies;
+
+       cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode,
+                oldtime, cifs_i->time));
 
-       inode->i_atime = cifs_NTtimeToUnix(info->LastAccessTime);
-       inode->i_mtime =
-               cifs_NTtimeToUnix(info->LastModificationTime);
-       inode->i_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
-       inode->i_mode = le64_to_cpu(info->Permissions);
+       cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
+
+       /*
+        * Can't safely change the file size here if the client is writing to
+        * it due to potential races.
+        */
+       spin_lock(&inode->i_lock);
+       if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
+               i_size_write(inode, fattr->cf_eof);
+
+               /*
+                * i_blocks is not related to (i_size / i_blksize),
+                * but instead 512 byte (2**9) size is required for
+                * calculating num blocks.
+                */
+               inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
+       }
+       spin_unlock(&inode->i_lock);
+
+       cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL);
+}
+
+/* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
+void
+cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
+                        struct cifs_sb_info *cifs_sb)
+{
+       memset(fattr, 0, sizeof(*fattr));
+       fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
+       fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
+       fattr->cf_eof = le64_to_cpu(info->EndOfFile);
+
+       fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
+       fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
+       fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
+       fattr->cf_mode = le64_to_cpu(info->Permissions);
 
        /*
         * Since we set the inode type below we need to mask off
         * to avoid strange results if bits set above.
         */
-       inode->i_mode &= ~S_IFMT;
+       fattr->cf_mode &= ~S_IFMT;
        switch (le32_to_cpu(info->Type)) {
        case UNIX_FILE:
-               inode->i_mode |= S_IFREG;
+               fattr->cf_mode |= S_IFREG;
+               fattr->cf_dtype = DT_REG;
                break;
        case UNIX_SYMLINK:
-               inode->i_mode |= S_IFLNK;
+               fattr->cf_mode |= S_IFLNK;
+               fattr->cf_dtype = DT_LNK;
                break;
        case UNIX_DIR:
-               inode->i_mode |= S_IFDIR;
+               fattr->cf_mode |= S_IFDIR;
+               fattr->cf_dtype = DT_DIR;
                break;
        case UNIX_CHARDEV:
-               inode->i_mode |= S_IFCHR;
-               inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor),
-                                     le64_to_cpu(info->DevMinor) & MINORMASK);
+               fattr->cf_mode |= S_IFCHR;
+               fattr->cf_dtype = DT_CHR;
+               fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
+                                      le64_to_cpu(info->DevMinor) & MINORMASK);
                break;
        case UNIX_BLOCKDEV:
-               inode->i_mode |= S_IFBLK;
-               inode->i_rdev = MKDEV(le64_to_cpu(info->DevMajor),
-                                     le64_to_cpu(info->DevMinor) & MINORMASK);
+               fattr->cf_mode |= S_IFBLK;
+               fattr->cf_dtype = DT_BLK;
+               fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
+                                      le64_to_cpu(info->DevMinor) & MINORMASK);
                break;
        case UNIX_FIFO:
-               inode->i_mode |= S_IFIFO;
+               fattr->cf_mode |= S_IFIFO;
+               fattr->cf_dtype = DT_FIFO;
                break;
        case UNIX_SOCKET:
-               inode->i_mode |= S_IFSOCK;
+               fattr->cf_mode |= S_IFSOCK;
+               fattr->cf_dtype = DT_SOCK;
                break;
        default:
                /* safest to call it a file if we do not know */
-               inode->i_mode |= S_IFREG;
+               fattr->cf_mode |= S_IFREG;
+               fattr->cf_dtype = DT_REG;
                cFYI(1, ("unknown type %d", le32_to_cpu(info->Type)));
                break;
        }
 
-       if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) &&
-           !force_uid_gid)
-               inode->i_uid = cifs_sb->mnt_uid;
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
+               fattr->cf_uid = cifs_sb->mnt_uid;
        else
-               inode->i_uid = le64_to_cpu(info->Uid);
+               fattr->cf_uid = le64_to_cpu(info->Uid);
 
-       if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) &&
-           !force_uid_gid)
-               inode->i_gid = cifs_sb->mnt_gid;
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
+               fattr->cf_gid = cifs_sb->mnt_gid;
        else
-               inode->i_gid = le64_to_cpu(info->Gid);
-
-       inode->i_nlink = le64_to_cpu(info->Nlinks);
-
-       cifsInfo->server_eof = end_of_file;
-       spin_lock(&inode->i_lock);
-       if (is_size_safe_to_change(cifsInfo, end_of_file)) {
-               /*
-                * We can not safely change the file size here if the client
-                * is writing to it due to potential races.
-                */
-               i_size_write(inode, end_of_file);
+               fattr->cf_gid = le64_to_cpu(info->Gid);
 
-               /*
-                * i_blocks is not related to (i_size / i_blksize),
-                * but instead 512 byte (2**9) size is required for
-                * calculating num blocks.
-                */
-               inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
-       }
-       spin_unlock(&inode->i_lock);
+       fattr->cf_nlink = le64_to_cpu(info->Nlinks);
 }
 
-
 /*
- *     Needed to setup inode data for the directory which is the
- *     junction to the new submount (ie to setup the fake directory
- *      which represents a DFS referral)
- */
-static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat,
-                              struct super_block *sb)
-{
-       struct inode *pinode = NULL;
-
-       memset(pfnd_dat, 0, sizeof(FILE_UNIX_BASIC_INFO));
-
-/*     __le64 pfnd_dat->EndOfFile = cpu_to_le64(0);
-       __le64 pfnd_dat->NumOfBytes = cpu_to_le64(0);
-       __u64 UniqueId = 0;  */
-       pfnd_dat->LastStatusChange =
-               cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
-       pfnd_dat->LastAccessTime =
-               cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
-       pfnd_dat->LastModificationTime =
-               cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
-       pfnd_dat->Type = cpu_to_le32(UNIX_DIR);
-       pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU);
-       pfnd_dat->Nlinks = cpu_to_le64(2);
-       if (sb->s_root)
-               pinode = sb->s_root->d_inode;
-       if (pinode == NULL)
-               return;
-
-       /* fill in default values for the remaining based on root
-          inode since we can not query the server for this inode info */
-       pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev));
-       pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev));
-       pfnd_dat->Uid = cpu_to_le64(pinode->i_uid);
-       pfnd_dat->Gid = cpu_to_le64(pinode->i_gid);
-}
-
-/**
- * cifs_new inode - create new inode, initialize, and hash it
- * @sb - pointer to superblock
- * @inum - if valid pointer and serverino is enabled, replace i_ino with val
- *
- * Create a new inode, initialize it for CIFS and hash it. Returns the new
- * inode or NULL if one couldn't be allocated.
+ * Fill a cifs_fattr struct with fake inode info.
  *
- * If the share isn't mounted with "serverino" or inum is a NULL pointer then
- * we'll just use the inode number assigned by new_inode(). Note that this can
- * mean i_ino collisions since the i_ino assigned by new_inode is not
- * guaranteed to be unique.
+ * Needed to setup cifs_fattr data for the directory which is the
+ * junction to the new submount (ie to setup the fake directory
+ * which represents a DFS referral).
  */
-struct inode *
-cifs_new_inode(struct super_block *sb, __u64 *inum)
+static void
+cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
 {
-       struct inode *inode;
-
-       inode = new_inode(sb);
-       if (inode == NULL)
-               return NULL;
-
-       /*
-        * BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we
-        *     stop passing inum as ptr. Are there sanity checks we can use to
-        *     ensure that the server is really filling in that field? Also,
-        *     if serverino is disabled, perhaps we should be using iunique()?
-        */
-       if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
-               inode->i_ino = (unsigned long) *inum;
-
-       /*
-        * must set this here instead of cifs_alloc_inode since VFS will
-        * clobber i_flags
-        */
-       if (sb->s_flags & MS_NOATIME)
-               inode->i_flags |= S_NOATIME | S_NOCMTIME;
-
-       insert_inode_hash(inode);
+       struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 
-       return inode;
+       cFYI(1, ("creating fake fattr for DFS referral"));
+
+       memset(fattr, 0, sizeof(*fattr));
+       fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
+       fattr->cf_uid = cifs_sb->mnt_uid;
+       fattr->cf_gid = cifs_sb->mnt_gid;
+       fattr->cf_atime = CURRENT_TIME;
+       fattr->cf_ctime = CURRENT_TIME;
+       fattr->cf_mtime = CURRENT_TIME;
+       fattr->cf_nlink = 2;
+       fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
 }
 
 int cifs_get_inode_info_unix(struct inode **pinode,
-       const unsigned char *full_path, struct super_block *sb, int xid)
+                            const unsigned char *full_path,
+                            struct super_block *sb, int xid)
 {
-       int rc = 0;
+       int rc;
        FILE_UNIX_BASIC_INFO find_data;
-       struct cifsTconInfo *pTcon;
-       struct inode *inode;
+       struct cifs_fattr fattr;
+       struct cifsTconInfo *tcon;
        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-       bool is_dfs_referral = false;
-       struct cifsInodeInfo *cifsInfo;
-       __u64 num_of_bytes;
-       __u64 end_of_file;
 
-       pTcon = cifs_sb->tcon;
+       tcon = cifs_sb->tcon;
        cFYI(1, ("Getting info on %s", full_path));
 
        /* could have done a find first instead but this returns more info */
-       rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data,
+       rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
                                  cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
-       if (rc == -EREMOTE && !is_dfs_referral) {
-               is_dfs_referral = true;
-               cFYI(DBG2, ("DFS ref"));
-               /* for DFS, server does not give us real inode data */
-               fill_fake_finddataunix(&find_data, sb);
-               rc = 0;
-       } else if (rc)
-               goto cgiiu_exit;
 
-       num_of_bytes = le64_to_cpu(find_data.NumOfBytes);
-       end_of_file = le64_to_cpu(find_data.EndOfFile);
+       if (!rc) {
+               cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
+       } else if (rc == -EREMOTE) {
+               cifs_create_dfs_fattr(&fattr, sb);
+               rc = 0;
+       } else {
+               return rc;
+       }
 
-       /* get new inode */
        if (*pinode == NULL) {
-               __u64 unique_id = le64_to_cpu(find_data.UniqueId);
-               *pinode = cifs_new_inode(sb, &unique_id);
-               if (*pinode == NULL) {
+               /* get new inode */
+               *pinode = cifs_iget(sb, &fattr);
+               if (!*pinode)
                        rc = -ENOMEM;
-                       goto cgiiu_exit;
-               }
+       } else {
+               /* we already have inode, update it */
+               cifs_fattr_to_inode(*pinode, &fattr);
        }
 
-       inode = *pinode;
-       cifsInfo = CIFS_I(inode);
-
-       cFYI(1, ("Old time %ld", cifsInfo->time));
-       cifsInfo->time = jiffies;
-       cFYI(1, ("New time %ld", cifsInfo->time));
-       /* this is ok to set on every inode revalidate */
-       atomic_set(&cifsInfo->inUse, 1);
-
-       cifs_unix_info_to_inode(inode, &find_data, 0);
-
-       if (num_of_bytes < end_of_file)
-               cFYI(1, ("allocation size less than end of file"));
-       cFYI(1, ("Size %ld and blocks %llu",
-               (unsigned long) inode->i_size,
-               (unsigned long long)inode->i_blocks));
-
-       cifs_set_ops(inode, is_dfs_referral);
-cgiiu_exit:
        return rc;
 }
 
-static int decode_sfu_inode(struct inode *inode, __u64 size,
-                           const unsigned char *path,
-                           struct cifs_sb_info *cifs_sb, int xid)
+static int
+cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
+             struct cifs_sb_info *cifs_sb, int xid)
 {
        int rc;
        int oplock = 0;
@@ -321,10 +284,15 @@ static int decode_sfu_inode(struct inode *inode, __u64 size,
 
        pbuf = buf;
 
-       if (size == 0) {
-               inode->i_mode |= S_IFIFO;
+       fattr->cf_mode &= ~S_IFMT;
+
+       if (fattr->cf_eof == 0) {
+               fattr->cf_mode |= S_IFIFO;
+               fattr->cf_dtype = DT_FIFO;
                return 0;
-       } else if (size < 8) {
+       } else if (fattr->cf_eof < 8) {
+               fattr->cf_mode |= S_IFREG;
+               fattr->cf_dtype = DT_REG;
                return -EINVAL;  /* EOPNOTSUPP? */
        }
 
@@ -336,42 +304,46 @@ static int decode_sfu_inode(struct inode *inode, __u64 size,
        if (rc == 0) {
                int buf_type = CIFS_NO_BUFFER;
                        /* Read header */
-               rc = CIFSSMBRead(xid, pTcon,
-                                netfid,
+               rc = CIFSSMBRead(xid, pTcon, netfid,
                                 24 /* length */, 0 /* offset */,
                                 &bytes_read, &pbuf, &buf_type);
                if ((rc == 0) && (bytes_read >= 8)) {
                        if (memcmp("IntxBLK", pbuf, 8) == 0) {
                                cFYI(1, ("Block device"));
-                               inode->i_mode |= S_IFBLK;
+                               fattr->cf_mode |= S_IFBLK;
+                               fattr->cf_dtype = DT_BLK;
                                if (bytes_read == 24) {
                                        /* we have enough to decode dev num */
                                        __u64 mjr; /* major */
                                        __u64 mnr; /* minor */
                                        mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
                                        mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
-                                       inode->i_rdev = MKDEV(mjr, mnr);
+                                       fattr->cf_rdev = MKDEV(mjr, mnr);
                                }
                        } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
                                cFYI(1, ("Char device"));
-                               inode->i_mode |= S_IFCHR;
+                               fattr->cf_mode |= S_IFCHR;
+                               fattr->cf_dtype = DT_CHR;
                                if (bytes_read == 24) {
                                        /* we have enough to decode dev num */
                                        __u64 mjr; /* major */
                                        __u64 mnr; /* minor */
                                        mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
                                        mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
-                                       inode->i_rdev = MKDEV(mjr, mnr);
+                                       fattr->cf_rdev = MKDEV(mjr, mnr);
                                }
                        } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
                                cFYI(1, ("Symlink"));
-                               inode->i_mode |= S_IFLNK;
+                               fattr->cf_mode |= S_IFLNK;
+                               fattr->cf_dtype = DT_LNK;
                        } else {
-                               inode->i_mode |= S_IFREG; /* file? */
+                               fattr->cf_mode |= S_IFREG; /* file? */
+                               fattr->cf_dtype = DT_REG;
                                rc = -EOPNOTSUPP;
                        }
                } else {
-                       inode->i_mode |= S_IFREG; /* then it is a file */
+                       fattr->cf_mode |= S_IFREG; /* then it is a file */
+                       fattr->cf_dtype = DT_REG;
                        rc = -EOPNOTSUPP; /* or some unknown SFU type */
                }
                CIFSSMBClose(xid, pTcon, netfid);
@@ -381,9 +353,13 @@ static int decode_sfu_inode(struct inode *inode, __u64 size,
 
 #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID)  /* SETFILEBITS valid bits */
 
-static int get_sfu_mode(struct inode *inode,
-                       const unsigned char *path,
-                       struct cifs_sb_info *cifs_sb, int xid)
+/*
+ * Fetch mode bits as provided by SFU.
+ *
+ * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
+ */
+static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
+                        struct cifs_sb_info *cifs_sb, int xid)
 {
 #ifdef CONFIG_CIFS_XATTR
        ssize_t rc;
@@ -391,68 +367,80 @@ static int get_sfu_mode(struct inode *inode,
        __u32 mode;
 
        rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
-                       ea_value, 4 /* size of buf */, cifs_sb->local_nls,
-               cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+                           ea_value, 4 /* size of buf */, cifs_sb->local_nls,
+                           cifs_sb->mnt_cifs_flags &
+                               CIFS_MOUNT_MAP_SPECIAL_CHR);
        if (rc < 0)
                return (int)rc;
        else if (rc > 3) {
                mode = le32_to_cpu(*((__le32 *)ea_value));
-               inode->i_mode &= ~SFBITS_MASK;
-               cFYI(1, ("special bits 0%o org mode 0%o", mode, inode->i_mode));
-               inode->i_mode = (mode &  SFBITS_MASK) | inode->i_mode;
+               fattr->cf_mode &= ~SFBITS_MASK;
+               cFYI(1, ("special bits 0%o org mode 0%o", mode,
+                        fattr->cf_mode));
+               fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
                cFYI(1, ("special mode bits 0%o", mode));
-               return 0;
-       } else {
-               return 0;
        }
+
+       return 0;
 #else
        return -EOPNOTSUPP;
 #endif
 }
 
-/*
- *     Needed to setup inode data for the directory which is the
- *     junction to the new submount (ie to setup the fake directory
- *      which represents a DFS referral)
- */
-static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat,
-                              struct super_block *sb)
+/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
+static void
+cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
+                      struct cifs_sb_info *cifs_sb, bool adjust_tz)
 {
-       memset(pfnd_dat, 0, sizeof(FILE_ALL_INFO));
-
-/*     __le64 pfnd_dat->AllocationSize = cpu_to_le64(0);
-       __le64 pfnd_dat->EndOfFile = cpu_to_le64(0);
-       __u8 pfnd_dat->DeletePending = 0;
-       __u8 pfnd_data->Directory = 0;
-       __le32 pfnd_dat->EASize = 0;
-       __u64 pfnd_dat->IndexNumber = 0;
-       __u64 pfnd_dat->IndexNumber1 = 0;  */
-       pfnd_dat->CreationTime =
-               cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
-       pfnd_dat->LastAccessTime =
-               cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
-       pfnd_dat->LastWriteTime =
-               cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
-       pfnd_dat->ChangeTime =
-               cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
-       pfnd_dat->Attributes = cpu_to_le32(ATTR_DIRECTORY);
-       pfnd_dat->NumberOfLinks = cpu_to_le32(2);
+       memset(fattr, 0, sizeof(*fattr));
+       fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
+       if (info->DeletePending)
+               fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
+
+       if (info->LastAccessTime)
+               fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
+       else
+               fattr->cf_atime = CURRENT_TIME;
+
+       fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
+       fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
+
+       if (adjust_tz) {
+               fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
+               fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
+       }
+
+       fattr->cf_eof = le64_to_cpu(info->EndOfFile);
+       fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
+
+       if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
+               fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
+               fattr->cf_dtype = DT_DIR;
+       } else {
+               fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
+               fattr->cf_dtype = DT_REG;
+
+               /* clear write bits if ATTR_READONLY is set */
+               if (fattr->cf_cifsattrs & ATTR_READONLY)
+                       fattr->cf_mode &= ~(S_IWUGO);
+       }
+
+       fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
+
+       fattr->cf_uid = cifs_sb->mnt_uid;
+       fattr->cf_gid = cifs_sb->mnt_gid;
 }
 
 int cifs_get_inode_info(struct inode **pinode,
        const unsigned char *full_path, FILE_ALL_INFO *pfindData,
        struct super_block *sb, int xid, const __u16 *pfid)
 {
-       int rc = 0;
-       __u32 attr;
-       struct cifsInodeInfo *cifsInfo;
+       int rc = 0, tmprc;
        struct cifsTconInfo *pTcon;
-       struct inode *inode;
        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
        char *buf = NULL;
        bool adjustTZ = false;
-       bool is_dfs_referral = false;
-       umode_t default_mode;
+       struct cifs_fattr fattr;
 
        pTcon = cifs_sb->tcon;
        cFYI(1, ("Getting info on %s", full_path));
@@ -487,163 +475,85 @@ int cifs_get_inode_info(struct inode **pinode,
                        adjustTZ = true;
                }
        }
-       /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
-       if (rc == -EREMOTE) {
-               is_dfs_referral = true;
-               fill_fake_finddata(pfindData, sb);
+
+       if (!rc) {
+               cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData,
+                                      cifs_sb, adjustTZ);
+       } else if (rc == -EREMOTE) {
+               cifs_create_dfs_fattr(&fattr, sb);
                rc = 0;
-       } else if (rc)
+       } else {
                goto cgii_exit;
+       }
 
-       attr = le32_to_cpu(pfindData->Attributes);
-
-       /* get new inode */
+       /*
+        * If an inode wasn't passed in, then get the inode number
+        *
+        * Is an i_ino of zero legal? Can we use that to check if the server
+        * supports returning inode numbers?  Are there other sanity checks we
+        * can use to ensure that the server is really filling in that field?
+        *
+        * We can not use the IndexNumber field by default from Windows or
+        * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
+        * CIFS spec claims that this value is unique within the scope of a
+        * share, and the windows docs hint that it's actually unique
+        * per-machine.
+        *
+        * There may be higher info levels that work but are there Windows
+        * server or network appliances for which IndexNumber field is not
+        * guaranteed unique?
+        */
        if (*pinode == NULL) {
-               __u64 inode_num;
-               __u64 *pinum = &inode_num;
-
-               /* Is an i_ino of zero legal? Can we use that to check
-                  if the server supports returning inode numbers?  Are
-                  there other sanity checks we can use to ensure that
-                  the server is really filling in that field? */
-
-               /* We can not use the IndexNumber field by default from
-                  Windows or Samba (in ALL_INFO buf) but we can request
-                  it explicitly.  It may not be unique presumably if
-                  the server has multiple devices mounted under one share */
-
-               /* There may be higher info levels that work but are
-                  there Windows server or network appliances for which
-                  IndexNumber field is not guaranteed unique? */
-
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
                        int rc1 = 0;
 
                        rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
-                                       full_path, pinum,
+                                       full_path, &fattr.cf_uniqueid,
                                        cifs_sb->local_nls,
                                        cifs_sb->mnt_cifs_flags &
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
                        if (rc1) {
                                cFYI(1, ("GetSrvInodeNum rc %d", rc1));
-                               pinum = NULL;
-                               /* BB EOPNOSUPP disable SERVER_INUM? */
+                               fattr.cf_uniqueid = iunique(sb, ROOT_I);
+                               /* disable serverino if call not supported */
+                               if (rc1 == -EINVAL)
+                                       cifs_sb->mnt_cifs_flags &=
+                                                       ~CIFS_MOUNT_SERVER_INUM;
                        }
                } else {
-                       pinum = NULL;
-               }
-
-               *pinode = cifs_new_inode(sb, pinum);
-               if (*pinode == NULL) {
-                       rc = -ENOMEM;
-                       goto cgii_exit;
+                       fattr.cf_uniqueid = iunique(sb, ROOT_I);
                }
-       }
-       inode = *pinode;
-       cifsInfo = CIFS_I(inode);
-       cifsInfo->cifsAttrs = attr;
-       cifsInfo->delete_pending = pfindData->DeletePending ? true : false;
-       cFYI(1, ("Old time %ld", cifsInfo->time));
-       cifsInfo->time = jiffies;
-       cFYI(1, ("New time %ld", cifsInfo->time));
-
-       /* blksize needs to be multiple of two. So safer to default to
-       blksize and blkbits set in superblock so 2**blkbits and blksize
-       will match rather than setting to:
-       (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
-
-       /* Linux can not store file creation time so ignore it */
-       if (pfindData->LastAccessTime)
-               inode->i_atime = cifs_NTtimeToUnix(pfindData->LastAccessTime);
-       else /* do not need to use current_fs_time - time not stored */
-               inode->i_atime = CURRENT_TIME;
-       inode->i_mtime = cifs_NTtimeToUnix(pfindData->LastWriteTime);
-       inode->i_ctime = cifs_NTtimeToUnix(pfindData->ChangeTime);
-       cFYI(DBG2, ("Attributes came in as 0x%x", attr));
-       if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
-               inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
-               inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
-       }
-
-       /* get default inode mode */
-       if (attr & ATTR_DIRECTORY)
-               default_mode = cifs_sb->mnt_dir_mode;
-       else
-               default_mode = cifs_sb->mnt_file_mode;
-
-       /* set permission bits */
-       if (atomic_read(&cifsInfo->inUse) == 0 ||
-           (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
-               inode->i_mode = default_mode;
-       else {
-               /* just reenable write bits if !ATTR_READONLY */
-               if ((inode->i_mode & S_IWUGO) == 0 &&
-                   (attr & ATTR_READONLY) == 0)
-                       inode->i_mode |= (S_IWUGO & default_mode);
-
-               inode->i_mode &= ~S_IFMT;
-       }
-       /* clear write bits if ATTR_READONLY is set */
-       if (attr & ATTR_READONLY)
-               inode->i_mode &= ~S_IWUGO;
-
-       /* set inode type */
-       if ((attr & ATTR_SYSTEM) &&
-           (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) {
-               /* no need to fix endianness on 0 */
-               if (pfindData->EndOfFile == 0)
-                       inode->i_mode |= S_IFIFO;
-               else if (decode_sfu_inode(inode,
-                               le64_to_cpu(pfindData->EndOfFile),
-                               full_path, cifs_sb, xid))
-                       cFYI(1, ("unknown SFU file type\n"));
        } else {
-               if (attr & ATTR_DIRECTORY)
-                       inode->i_mode |= S_IFDIR;
-               else
-                       inode->i_mode |= S_IFREG;
+               fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid;
        }
 
-       cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile);
-       spin_lock(&inode->i_lock);
-       if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) {
-               /* can not safely shrink the file size here if the
-                  client is writing to it due to potential races */
-               i_size_write(inode, cifsInfo->server_eof);
-
-               /* 512 bytes (2**9) is the fake blocksize that must be
-                  used for this calculation */
-               inode->i_blocks = (512 - 1 + le64_to_cpu(
-                                  pfindData->AllocationSize)) >> 9;
+       /* query for SFU type info if supported and needed */
+       if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
+           cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
+               tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
+               if (tmprc)
+                       cFYI(1, ("cifs_sfu_type failed: %d", tmprc));
        }
-       spin_unlock(&inode->i_lock);
 
-       inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
-
-       /* BB fill in uid and gid here? with help from winbind?
-          or retrieve from NTFS stream extended attribute */
 #ifdef CONFIG_CIFS_EXPERIMENTAL
        /* fill in 0777 bits from ACL */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
                cFYI(1, ("Getting mode bits from ACL"));
-               acl_to_uid_mode(cifs_sb, inode, full_path, pfid);
+               cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid);
        }
 #endif
-       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
-               /* fill in remaining high mode bits e.g. SUID, VTX */
-               get_sfu_mode(inode, full_path, cifs_sb, xid);
-       } else if (atomic_read(&cifsInfo->inUse) == 0) {
-               inode->i_uid = cifs_sb->mnt_uid;
-               inode->i_gid = cifs_sb->mnt_gid;
-               /* set so we do not keep refreshing these fields with
-                  bad data after user has changed them in memory */
-               atomic_set(&cifsInfo->inUse, 1);
-       }
-
-       cifs_set_ops(inode, is_dfs_referral);
-
 
+       /* fill in remaining high mode bits e.g. SUID, VTX */
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
+               cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
 
+       if (!*pinode) {
+               *pinode = cifs_iget(sb, &fattr);
+               if (!*pinode)
+                       rc = -ENOMEM;
+       } else {
+               cifs_fattr_to_inode(*pinode, &fattr);
+       }
 
 cgii_exit:
        kfree(buf);
@@ -695,33 +605,78 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
        return full_path;
 }
 
+static int
+cifs_find_inode(struct inode *inode, void *opaque)
+{
+       struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
+
+       if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
+               return 0;
+
+       return 1;
+}
+
+static int
+cifs_init_inode(struct inode *inode, void *opaque)
+{
+       struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
+
+       CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
+       return 0;
+}
+
+/* Given fattrs, get a corresponding inode */
+struct inode *
+cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
+{
+       unsigned long hash;
+       struct inode *inode;
+
+       cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid));
+
+       /* hash down to 32-bits on 32-bit arch */
+       hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
+
+       inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
+
+       /* we have fattrs in hand, update the inode */
+       if (inode) {
+               cifs_fattr_to_inode(inode, fattr);
+               if (sb->s_flags & MS_NOATIME)
+                       inode->i_flags |= S_NOATIME | S_NOCMTIME;
+               if (inode->i_state & I_NEW) {
+                       inode->i_ino = hash;
+                       unlock_new_inode(inode);
+               }
+       }
+
+       return inode;
+}
+
 /* gets root inode */
 struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
 {
        int xid;
        struct cifs_sb_info *cifs_sb;
-       struct inode *inode;
+       struct inode *inode = NULL;
        long rc;
        char *full_path;
 
-       inode = iget_locked(sb, ino);
-       if (!inode)
-               return ERR_PTR(-ENOMEM);
-       if (!(inode->i_state & I_NEW))
-               return inode;
-
-       cifs_sb = CIFS_SB(inode->i_sb);
+       cifs_sb = CIFS_SB(sb);
        full_path = cifs_build_path_to_root(cifs_sb);
        if (full_path == NULL)
                return ERR_PTR(-ENOMEM);
 
        xid = GetXid();
        if (cifs_sb->tcon->unix_ext)
-               rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
-                                               xid);
+               rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
        else
-               rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb,
+               rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
                                                xid, NULL);
+
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
+
        if (rc && cifs_sb->tcon->ipc) {
                cFYI(1, ("ipc connection - fake read inode"));
                inode->i_mode |= S_IFDIR;
@@ -737,7 +692,6 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
                return ERR_PTR(rc);
        }
 
-       unlock_new_inode(inode);
 
        kfree(full_path);
        /* can not call macro FreeXid here since in a void func
@@ -988,8 +942,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
         * sb->s_vfs_rename_mutex here */
        full_path = build_path_from_dentry(dentry);
        if (full_path == NULL) {
+               rc = -ENOMEM;
                FreeXid(xid);
-               return -ENOMEM;
+               return rc;
        }
 
        if ((tcon->ses->capabilities & CAP_UNIX) &&
@@ -1062,44 +1017,6 @@ out_reval:
        return rc;
 }
 
-void posix_fill_in_inode(struct inode *tmp_inode,
-       FILE_UNIX_BASIC_INFO *pData, int isNewInode)
-{
-       struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
-       loff_t local_size;
-       struct timespec local_mtime;
-
-       cifsInfo->time = jiffies;
-       atomic_inc(&cifsInfo->inUse);
-
-       /* save mtime and size */
-       local_mtime = tmp_inode->i_mtime;
-       local_size  = tmp_inode->i_size;
-
-       cifs_unix_info_to_inode(tmp_inode, pData, 1);
-       cifs_set_ops(tmp_inode, false);
-
-       if (!S_ISREG(tmp_inode->i_mode))
-               return;
-
-       /*
-        * No sense invalidating pages for new inode
-        * since we we have not started caching
-        * readahead file data yet.
-        */
-       if (isNewInode)
-               return;
-
-       if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
-               (local_size == tmp_inode->i_size)) {
-               cFYI(1, ("inode exists but unchanged"));
-       } else {
-               /* file may have changed on server */
-               cFYI(1, ("invalidate inode, readdir detected change"));
-               invalidate_remote_inode(tmp_inode);
-       }
-}
-
 int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
 {
        int rc = 0, tmprc;
@@ -1108,6 +1025,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
        struct cifsTconInfo *pTcon;
        char *full_path = NULL;
        struct inode *newinode = NULL;
+       struct cifs_fattr fattr;
 
        cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));
 
@@ -1118,8 +1036,9 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
 
        full_path = build_path_from_dentry(direntry);
        if (full_path == NULL) {
+               rc = -ENOMEM;
                FreeXid(xid);
-               return -ENOMEM;
+               return rc;
        }
 
        if ((pTcon->ses->capabilities & CAP_UNIX) &&
@@ -1146,7 +1065,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
                        cFYI(1, ("posix mkdir returned 0x%x", rc));
                        d_drop(direntry);
                } else {
-                       __u64 unique_id;
                        if (pInfo->Type == cpu_to_le32(-1)) {
                                /* no return info, go query for it */
                                kfree(pInfo);
@@ -1160,20 +1078,15 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
                        else
                                direntry->d_op = &cifs_dentry_ops;
 
-                       unique_id = le64_to_cpu(pInfo->UniqueId);
-                       newinode = cifs_new_inode(inode->i_sb, &unique_id);
-                       if (newinode == NULL) {
+                       cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb);
+                       newinode = cifs_iget(inode->i_sb, &fattr);
+                       if (!newinode) {
                                kfree(pInfo);
                                goto mkdir_get_info;
                        }
 
-                       newinode->i_nlink = 2;
                        d_instantiate(direntry, newinode);
 
-                       /* we already checked in POSIXCreate whether
-                          frame was long enough */
-                       posix_fill_in_inode(direntry->d_inode,
-                                       pInfo, 1 /* NewInode */);
 #ifdef CONFIG_CIFS_DEBUG2
                        cFYI(1, ("instantiated dentry %p %s to inode %p",
                                direntry, direntry->d_name.name, newinode));
@@ -1236,10 +1149,10 @@ mkdir_get_info:
                                args.uid = NO_CHANGE_64;
                                args.gid = NO_CHANGE_64;
                        }
-                       CIFSSMBUnixSetInfo(xid, pTcon, full_path, &args,
-                                           cifs_sb->local_nls,
-                                           cifs_sb->mnt_cifs_flags &
-                                           CIFS_MOUNT_MAP_SPECIAL_CHR);
+                       CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
+                                              cifs_sb->local_nls,
+                                              cifs_sb->mnt_cifs_flags &
+                                               CIFS_MOUNT_MAP_SPECIAL_CHR);
                } else {
                        if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
                            (mode & S_IWUGO) == 0) {
@@ -1303,8 +1216,9 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
 
        full_path = build_path_from_dentry(direntry);
        if (full_path == NULL) {
+               rc = -ENOMEM;
                FreeXid(xid);
-               return -ENOMEM;
+               return rc;
        }
 
        rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
@@ -1508,8 +1422,9 @@ int cifs_revalidate(struct dentry *direntry)
           since that would deadlock */
        full_path = build_path_from_dentry(direntry);
        if (full_path == NULL) {
+               rc = -ENOMEM;
                FreeXid(xid);
-               return -ENOMEM;
+               return rc;
        }
        cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
                 "jiffies %ld", full_path, direntry->d_inode,
@@ -1618,6 +1533,7 @@ int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
        if (!err) {
                generic_fillattr(dentry->d_inode, stat);
                stat->blksize = CIFS_MAX_MSGSIZE;
+               stat->ino = CIFS_I(dentry->d_inode)->uniqueid;
        }
        return err;
 }
@@ -1782,6 +1698,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct cifsTconInfo *pTcon = cifs_sb->tcon;
        struct cifs_unix_set_info_args *args = NULL;
+       struct cifsFileInfo *open_file;
 
        cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x",
                 direntry->d_name.name, attrs->ia_valid));
@@ -1868,10 +1785,18 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
                args->ctime = NO_CHANGE_64;
 
        args->device = 0;
-       rc = CIFSSMBUnixSetInfo(xid, pTcon, full_path, args,
-                               cifs_sb->local_nls,
-                               cifs_sb->mnt_cifs_flags &
-                               CIFS_MOUNT_MAP_SPECIAL_CHR);
+       open_file = find_writable_file(cifsInode);
+       if (open_file) {
+               u16 nfid = open_file->netfid;
+               u32 npid = open_file->pid;
+               rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
+               atomic_dec(&open_file->wrtPending);
+       } else {
+               rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
+                                   cifs_sb->local_nls,
+                                   cifs_sb->mnt_cifs_flags &
+                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
+       }
 
        if (!rc)
                rc = inode_setattr(inode, attrs);
@@ -1911,8 +1836,9 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
 
        full_path = build_path_from_dentry(direntry);
        if (full_path == NULL) {
+               rc = -ENOMEM;
                FreeXid(xid);
-               return -ENOMEM;
+               return rc;
        }
 
        /*
index cd83c53fcbb546f72253dd0306430319db073f6e..fc1e0487eaee3c5a2b0c4fba34e4c532e930e06b 100644 (file)
@@ -172,8 +172,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
        full_path = build_path_from_dentry(direntry);
 
        if (full_path == NULL) {
+               rc = -ENOMEM;
                FreeXid(xid);
-               return -ENOMEM;
+               return rc;
        }
 
        cFYI(1, ("Full path: %s", full_path));
index 32d6baa0a54fa907963d976c56d75c09d301e055..bd6d6895730d885442f5715e7d4c4e3e693ce333 100644 (file)
@@ -133,10 +133,12 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
        {0, 0}
 };
 
-/* Convert string containing dotted ip address to binary form */
-/* returns 0 if invalid address */
-
-int
+/*
+ * Convert a string containing text IPv4 or IPv6 address to binary form.
+ *
+ * Returns 0 on failure.
+ */
+static int
 cifs_inet_pton(const int address_family, const char *cp, void *dst)
 {
        int ret = 0;
@@ -153,6 +155,52 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst)
        return ret;
 }
 
+/*
+ * Try to convert a string to an IPv4 address and then attempt to convert
+ * it to an IPv6 address if that fails. Set the family field if either
+ * succeeds. If it's an IPv6 address and it has a '%' sign in it, try to
+ * treat the part following it as a numeric sin6_scope_id.
+ *
+ * Returns 0 on failure.
+ */
+int
+cifs_convert_address(char *src, void *dst)
+{
+       int rc;
+       char *pct, *endp;
+       struct sockaddr_in *s4 = (struct sockaddr_in *) dst;
+       struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst;
+
+       /* IPv4 address */
+       if (cifs_inet_pton(AF_INET, src, &s4->sin_addr.s_addr)) {
+               s4->sin_family = AF_INET;
+               return 1;
+       }
+
+       /* temporarily terminate string */
+       pct = strchr(src, '%');
+       if (pct)
+               *pct = '\0';
+
+       rc = cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr);
+
+       /* repair temp termination (if any) and make pct point to scopeid */
+       if (pct)
+               *pct++ = '%';
+
+       if (!rc)
+               return rc;
+
+       s6->sin6_family = AF_INET6;
+       if (pct) {
+               s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0);
+               if (!*pct || *endp)
+                       return 0;
+       }
+
+       return rc;
+}
+
 /*****************************************************************************
 convert a NT status code to a dos class/code
  *****************************************************************************/
index 86d0055dc529906df58a3dfddbc4b5601af08d0f..f823a4a208a71b049499cfb4e3a5bf3191370a58 100644 (file)
@@ -63,374 +63,123 @@ static inline void dump_cifs_file_struct(struct file *file, char *label)
 }
 #endif /* DEBUG2 */
 
-/* Returns 1 if new inode created, 2 if both dentry and inode were */
-/* Might check in the future if inode number changed so we can rehash inode */
-static int
-construct_dentry(struct qstr *qstring, struct file *file,
-                struct inode **ptmp_inode, struct dentry **pnew_dentry,
-                __u64 *inum)
+/*
+ * Find the dentry that matches "name". If there isn't one, create one. If it's
+ * a negative dentry or the uniqueid changed, then drop it and recreate it.
+ */
+static struct dentry *
+cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
+                   struct cifs_fattr *fattr)
 {
-       struct dentry *tmp_dentry = NULL;
-       struct super_block *sb = file->f_path.dentry->d_sb;
-       int rc = 0;
+       struct dentry *dentry, *alias;
+       struct inode *inode;
+       struct super_block *sb = parent->d_inode->i_sb;
+
+       cFYI(1, ("For %s", name->name));
+
+       dentry = d_lookup(parent, name);
+       if (dentry) {
+               /* FIXME: check for inode number changes? */
+               if (dentry->d_inode != NULL)
+                       return dentry;
+               d_drop(dentry);
+               dput(dentry);
+       }
 
-       cFYI(1, ("For %s", qstring->name));
-
-       qstring->hash = full_name_hash(qstring->name, qstring->len);
-       tmp_dentry = d_lookup(file->f_path.dentry, qstring);
-       if (tmp_dentry) {
-               /* BB: overwrite old name? i.e. tmp_dentry->d_name and
-                * tmp_dentry->d_name.len??
-                */
-               cFYI(0, ("existing dentry with inode 0x%p",
-                        tmp_dentry->d_inode));
-               *ptmp_inode = tmp_dentry->d_inode;
-               if (*ptmp_inode == NULL) {
-                       *ptmp_inode = cifs_new_inode(sb, inum);
-                       if (*ptmp_inode == NULL)
-                               return rc;
-                       rc = 1;
-               }
-       } else {
-               tmp_dentry = d_alloc(file->f_path.dentry, qstring);
-               if (tmp_dentry == NULL) {
-                       cERROR(1, ("Failed allocating dentry"));
-                       *ptmp_inode = NULL;
-                       return rc;
-               }
+       dentry = d_alloc(parent, name);
+       if (dentry == NULL)
+               return NULL;
 
-               if (CIFS_SB(sb)->tcon->nocase)
-                       tmp_dentry->d_op = &cifs_ci_dentry_ops;
-               else
-                       tmp_dentry->d_op = &cifs_dentry_ops;
+       inode = cifs_iget(sb, fattr);
+       if (!inode) {
+               dput(dentry);
+               return NULL;
+       }
 
-               *ptmp_inode = cifs_new_inode(sb, inum);
-               if (*ptmp_inode == NULL)
-                       return rc;
-               rc = 2;
+       if (CIFS_SB(sb)->tcon->nocase)
+               dentry->d_op = &cifs_ci_dentry_ops;
+       else
+               dentry->d_op = &cifs_dentry_ops;
+
+       alias = d_materialise_unique(dentry, inode);
+       if (alias != NULL) {
+               dput(dentry);
+               if (IS_ERR(alias))
+                       return NULL;
+               dentry = alias;
        }
 
-       tmp_dentry->d_time = jiffies;
-       *pnew_dentry = tmp_dentry;
-       return rc;
+       return dentry;
 }
 
-static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
-                         char *buf, unsigned int *pobject_type, int isNewInode)
+static void
+cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
 {
-       loff_t local_size;
-       struct timespec local_mtime;
-
-       struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
-       struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
-       __u32 attr;
-       __u64 allocation_size;
-       __u64 end_of_file;
-       umode_t default_mode;
-
-       /* save mtime and size */
-       local_mtime = tmp_inode->i_mtime;
-       local_size  = tmp_inode->i_size;
-
-       if (new_buf_type) {
-               FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf;
-
-               attr = le32_to_cpu(pfindData->ExtFileAttributes);
-               allocation_size = le64_to_cpu(pfindData->AllocationSize);
-               end_of_file = le64_to_cpu(pfindData->EndOfFile);
-               tmp_inode->i_atime =
-                       cifs_NTtimeToUnix(pfindData->LastAccessTime);
-               tmp_inode->i_mtime =
-                       cifs_NTtimeToUnix(pfindData->LastWriteTime);
-               tmp_inode->i_ctime =
-                       cifs_NTtimeToUnix(pfindData->ChangeTime);
-       } else { /* legacy, OS2 and DOS style */
-               int offset = cifs_sb->tcon->ses->server->timeAdj;
-               FIND_FILE_STANDARD_INFO *pfindData =
-                       (FIND_FILE_STANDARD_INFO *)buf;
-
-               tmp_inode->i_mtime = cnvrtDosUnixTm(pfindData->LastWriteDate,
-                                                   pfindData->LastWriteTime,
-                                                   offset);
-               tmp_inode->i_atime = cnvrtDosUnixTm(pfindData->LastAccessDate,
-                                                   pfindData->LastAccessTime,
-                                                   offset);
-               tmp_inode->i_ctime = cnvrtDosUnixTm(pfindData->LastWriteDate,
-                                                   pfindData->LastWriteTime,
-                                                   offset);
-               attr = le16_to_cpu(pfindData->Attributes);
-               allocation_size = le32_to_cpu(pfindData->AllocationSize);
-               end_of_file = le32_to_cpu(pfindData->DataSize);
-       }
+       fattr->cf_uid = cifs_sb->mnt_uid;
+       fattr->cf_gid = cifs_sb->mnt_gid;
 
-       /* Linux can not store file creation time unfortunately so ignore it */
-
-       cifsInfo->cifsAttrs = attr;
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
-               /* get more accurate mode via ACL - so force inode refresh */
-               cifsInfo->time = 0;
-       } else
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
-               cifsInfo->time = jiffies;
-
-       /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
-       /* 2767 perms - indicate mandatory locking */
-               /* BB fill in uid and gid here? with help from winbind?
-                  or retrieve from NTFS stream extended attribute */
-       if (atomic_read(&cifsInfo->inUse) == 0) {
-               tmp_inode->i_uid = cifs_sb->mnt_uid;
-               tmp_inode->i_gid = cifs_sb->mnt_gid;
-       }
-
-       if (attr & ATTR_DIRECTORY)
-               default_mode = cifs_sb->mnt_dir_mode;
-       else
-               default_mode = cifs_sb->mnt_file_mode;
-
-       /* set initial permissions */
-       if ((atomic_read(&cifsInfo->inUse) == 0) ||
-           (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
-               tmp_inode->i_mode = default_mode;
-       else {
-               /* just reenable write bits if !ATTR_READONLY */
-               if ((tmp_inode->i_mode & S_IWUGO) == 0 &&
-                   (attr & ATTR_READONLY) == 0)
-                       tmp_inode->i_mode |= (S_IWUGO & default_mode);
-
-               tmp_inode->i_mode &= ~S_IFMT;
+       if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
+               fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
+               fattr->cf_dtype = DT_DIR;
+       } else {
+               fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
+               fattr->cf_dtype = DT_REG;
        }
 
-       /* clear write bits if ATTR_READONLY is set */
-       if (attr & ATTR_READONLY)
-               tmp_inode->i_mode &= ~S_IWUGO;
+       if (fattr->cf_cifsattrs & ATTR_READONLY)
+               fattr->cf_mode &= ~S_IWUGO;
 
-       /* set inode type */
-       if ((attr & ATTR_SYSTEM) &&
-           (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) {
-               if (end_of_file == 0)  {
-                       tmp_inode->i_mode |= S_IFIFO;
-                       *pobject_type = DT_FIFO;
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL &&
+           fattr->cf_cifsattrs & ATTR_SYSTEM) {
+               if (fattr->cf_eof == 0)  {
+                       fattr->cf_mode &= ~S_IFMT;
+                       fattr->cf_mode |= S_IFIFO;
+                       fattr->cf_dtype = DT_FIFO;
                } else {
                        /*
-                        * trying to get the type can be slow, so just call
-                        * this a regular file for now, and mark for reval
+                        * trying to get the type and mode via SFU can be slow,
+                        * so just call those regular files for now, and mark
+                        * for reval
                         */
-                       tmp_inode->i_mode |= S_IFREG;
-                       *pobject_type = DT_REG;
-                       cifsInfo->time = 0;
-               }
-       } else {
-               if (attr & ATTR_DIRECTORY) {
-                       tmp_inode->i_mode |= S_IFDIR;
-                       *pobject_type = DT_DIR;
-               } else {
-                       tmp_inode->i_mode |= S_IFREG;
-                       *pobject_type = DT_REG;
+                       fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
                }
        }
+}
 
-       /* can not fill in nlink here as in qpathinfo version and Unx search */
-       if (atomic_read(&cifsInfo->inUse) == 0)
-               atomic_set(&cifsInfo->inUse, 1);
-
-       cifsInfo->server_eof = end_of_file;
-       spin_lock(&tmp_inode->i_lock);
-       if (is_size_safe_to_change(cifsInfo, end_of_file)) {
-               /* can not safely change the file size here if the
-               client is writing to it due to potential races */
-               i_size_write(tmp_inode, end_of_file);
-
-       /* 512 bytes (2**9) is the fake blocksize that must be used */
-       /* for this calculation, even though the reported blocksize is larger */
-               tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;
-       }
-       spin_unlock(&tmp_inode->i_lock);
-
-       if (allocation_size < end_of_file)
-               cFYI(1, ("May be sparse file, allocation less than file size"));
-       cFYI(1, ("File Size %ld and blocks %llu",
-               (unsigned long)tmp_inode->i_size,
-               (unsigned long long)tmp_inode->i_blocks));
-       if (S_ISREG(tmp_inode->i_mode)) {
-               cFYI(1, ("File inode"));
-               tmp_inode->i_op = &cifs_file_inode_ops;
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
-                       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
-                               tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
-                       else
-                               tmp_inode->i_fop = &cifs_file_direct_ops;
-               } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
-                       tmp_inode->i_fop = &cifs_file_nobrl_ops;
-               else
-                       tmp_inode->i_fop = &cifs_file_ops;
-
-               if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
-                  (cifs_sb->tcon->ses->server->maxBuf <
-                       PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
-                       tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
-               else
-                       tmp_inode->i_data.a_ops = &cifs_addr_ops;
-
-               if (isNewInode)
-                       return; /* No sense invalidating pages for new inode
-                                  since have not started caching readahead file
-                                  data yet */
-
-               if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
-                       (local_size == tmp_inode->i_size)) {
-                       cFYI(1, ("inode exists but unchanged"));
-               } else {
-                       /* file may have changed on server */
-                       cFYI(1, ("invalidate inode, readdir detected change"));
-                       invalidate_remote_inode(tmp_inode);
-               }
-       } else if (S_ISDIR(tmp_inode->i_mode)) {
-               cFYI(1, ("Directory inode"));
-               tmp_inode->i_op = &cifs_dir_inode_ops;
-               tmp_inode->i_fop = &cifs_dir_ops;
-       } else if (S_ISLNK(tmp_inode->i_mode)) {
-               cFYI(1, ("Symbolic Link inode"));
-               tmp_inode->i_op = &cifs_symlink_inode_ops;
-       } else {
-               cFYI(1, ("Init special inode"));
-               init_special_inode(tmp_inode, tmp_inode->i_mode,
-                                  tmp_inode->i_rdev);
-       }
+void
+cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
+                      struct cifs_sb_info *cifs_sb)
+{
+       memset(fattr, 0, sizeof(*fattr));
+       fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes);
+       fattr->cf_eof = le64_to_cpu(info->EndOfFile);
+       fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
+       fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
+       fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
+       fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
+
+       cifs_fill_common_info(fattr, cifs_sb);
 }
 
-static void unix_fill_in_inode(struct inode *tmp_inode,
-       FILE_UNIX_INFO *pfindData, unsigned int *pobject_type, int isNewInode)
+void
+cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
+                      struct cifs_sb_info *cifs_sb)
 {
-       loff_t local_size;
-       struct timespec local_mtime;
-
-       struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
-       struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
-
-       __u32 type = le32_to_cpu(pfindData->Type);
-       __u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes);
-       __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
-       cifsInfo->time = jiffies;
-       atomic_inc(&cifsInfo->inUse);
-
-       /* save mtime and size */
-       local_mtime = tmp_inode->i_mtime;
-       local_size  = tmp_inode->i_size;
-
-       tmp_inode->i_atime =
-           cifs_NTtimeToUnix(pfindData->LastAccessTime);
-       tmp_inode->i_mtime =
-           cifs_NTtimeToUnix(pfindData->LastModificationTime);
-       tmp_inode->i_ctime =
-           cifs_NTtimeToUnix(pfindData->LastStatusChange);
-
-       tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
-       /* since we set the inode type below we need to mask off type
-          to avoid strange results if bits above were corrupt */
-       tmp_inode->i_mode &= ~S_IFMT;
-       if (type == UNIX_FILE) {
-               *pobject_type = DT_REG;
-               tmp_inode->i_mode |= S_IFREG;
-       } else if (type == UNIX_SYMLINK) {
-               *pobject_type = DT_LNK;
-               tmp_inode->i_mode |= S_IFLNK;
-       } else if (type == UNIX_DIR) {
-               *pobject_type = DT_DIR;
-               tmp_inode->i_mode |= S_IFDIR;
-       } else if (type == UNIX_CHARDEV) {
-               *pobject_type = DT_CHR;
-               tmp_inode->i_mode |= S_IFCHR;
-               tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
-                               le64_to_cpu(pfindData->DevMinor) & MINORMASK);
-       } else if (type == UNIX_BLOCKDEV) {
-               *pobject_type = DT_BLK;
-               tmp_inode->i_mode |= S_IFBLK;
-               tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
-                               le64_to_cpu(pfindData->DevMinor) & MINORMASK);
-       } else if (type == UNIX_FIFO) {
-               *pobject_type = DT_FIFO;
-               tmp_inode->i_mode |= S_IFIFO;
-       } else if (type == UNIX_SOCKET) {
-               *pobject_type = DT_SOCK;
-               tmp_inode->i_mode |= S_IFSOCK;
-       } else {
-               /* safest to just call it a file */
-               *pobject_type = DT_REG;
-               tmp_inode->i_mode |= S_IFREG;
-               cFYI(1, ("unknown inode type %d", type));
-       }
+       int offset = cifs_sb->tcon->ses->server->timeAdj;
 
-       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
-               tmp_inode->i_uid = cifs_sb->mnt_uid;
-       else
-               tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
-       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
-               tmp_inode->i_gid = cifs_sb->mnt_gid;
-       else
-               tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
-       tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
-
-       cifsInfo->server_eof = end_of_file;
-       spin_lock(&tmp_inode->i_lock);
-       if (is_size_safe_to_change(cifsInfo, end_of_file)) {
-               /* can not safely change the file size here if the
-               client is writing to it due to potential races */
-               i_size_write(tmp_inode, end_of_file);
-
-       /* 512 bytes (2**9) is the fake blocksize that must be used */
-       /* for this calculation, not the real blocksize */
-               tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
-       }
-       spin_unlock(&tmp_inode->i_lock);
+       memset(fattr, 0, sizeof(*fattr));
+       fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
+                                           info->LastAccessTime, offset);
+       fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate,
+                                           info->LastWriteTime, offset);
+       fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate,
+                                           info->LastWriteTime, offset);
 
-       if (S_ISREG(tmp_inode->i_mode)) {
-               cFYI(1, ("File inode"));
-               tmp_inode->i_op = &cifs_file_inode_ops;
+       fattr->cf_cifsattrs = le16_to_cpu(info->Attributes);
+       fattr->cf_bytes = le32_to_cpu(info->AllocationSize);
+       fattr->cf_eof = le32_to_cpu(info->DataSize);
 
-               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
-                       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
-                               tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
-                       else
-                               tmp_inode->i_fop = &cifs_file_direct_ops;
-               } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
-                       tmp_inode->i_fop = &cifs_file_nobrl_ops;
-               else
-                       tmp_inode->i_fop = &cifs_file_ops;
-
-               if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
-                  (cifs_sb->tcon->ses->server->maxBuf <
-                       PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
-                       tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
-               else
-                       tmp_inode->i_data.a_ops = &cifs_addr_ops;
-
-               if (isNewInode)
-                       return; /* No sense invalidating pages for new inode
-                                  since we have not started caching readahead
-                                  file data for it yet */
-
-               if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
-                       (local_size == tmp_inode->i_size)) {
-                       cFYI(1, ("inode exists but unchanged"));
-               } else {
-                       /* file may have changed on server */
-                       cFYI(1, ("invalidate inode, readdir detected change"));
-                       invalidate_remote_inode(tmp_inode);
-               }
-       } else if (S_ISDIR(tmp_inode->i_mode)) {
-               cFYI(1, ("Directory inode"));
-               tmp_inode->i_op = &cifs_dir_inode_ops;
-               tmp_inode->i_fop = &cifs_dir_ops;
-       } else if (S_ISLNK(tmp_inode->i_mode)) {
-               cFYI(1, ("Symbolic Link inode"));
-               tmp_inode->i_op = &cifs_symlink_inode_ops;
-/* tmp_inode->i_fop = *//* do not need to set to anything */
-       } else {
-               cFYI(1, ("Special inode"));
-               init_special_inode(tmp_inode, tmp_inode->i_mode,
-                                  tmp_inode->i_rdev);
-       }
+       cifs_fill_common_info(fattr, cifs_sb);
 }
 
 /* BB eventually need to add the following helper function to
@@ -872,7 +621,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
                        len = strnlen(filename, PATH_MAX);
                }
 
-               *pinum = le64_to_cpu(pFindData->UniqueId);
+               *pinum = le64_to_cpu(pFindData->basic.UniqueId);
        } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
                FILE_DIRECTORY_INFO *pFindData =
                        (FILE_DIRECTORY_INFO *)current_entry;
@@ -932,11 +681,12 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
        int rc = 0;
        struct qstr qstring;
        struct cifsFileInfo *pCifsF;
-       unsigned int obj_type;
-       __u64  inum;
+       u64    inum;
+       ino_t  ino;
+       struct super_block *sb;
        struct cifs_sb_info *cifs_sb;
-       struct inode *tmp_inode;
        struct dentry *tmp_dentry;
+       struct cifs_fattr fattr;
 
        /* get filename and len into qstring */
        /* get dentry */
@@ -954,60 +704,53 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
        if (rc != 0)
                return 0;
 
-       cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+       sb = file->f_path.dentry->d_sb;
+       cifs_sb = CIFS_SB(sb);
 
        qstring.name = scratch_buf;
        rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
                        pCifsF->srch_inf.info_level,
                        pCifsF->srch_inf.unicode, cifs_sb,
-                       max_len,
-                       &inum /* returned */);
+                       max_len, &inum /* returned */);
 
        if (rc)
                return rc;
 
-       /* only these two infolevels return valid inode numbers */
-       if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX ||
-           pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO)
-               rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry,
-                                       &inum);
-       else
-               rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry,
-                                       NULL);
-
-       if ((tmp_inode == NULL) || (tmp_dentry == NULL))
-               return -ENOMEM;
-
-       /* we pass in rc below, indicating whether it is a new inode,
-          so we can figure out whether to invalidate the inode cached
-          data if the file has changed */
        if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
-               unix_fill_in_inode(tmp_inode,
-                                  (FILE_UNIX_INFO *)pfindEntry,
-                                  &obj_type, rc);
+               cifs_unix_basic_to_fattr(&fattr,
+                                &((FILE_UNIX_INFO *) pfindEntry)->basic,
+                                cifs_sb);
        else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
-               fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */,
-                               pfindEntry, &obj_type, rc);
+               cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *)
+                                       pfindEntry, cifs_sb);
        else
-               fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc);
+               cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *)
+                                       pfindEntry, cifs_sb);
 
-       if (rc) /* new inode - needs to be tied to dentry */ {
-               d_instantiate(tmp_dentry, tmp_inode);
-               if (rc == 2)
-                       d_rehash(tmp_dentry);
-       }
+       /* FIXME: make _to_fattr functions fill this out */
+       if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO)
+               fattr.cf_uniqueid = inum;
+       else
+               fattr.cf_uniqueid = iunique(sb, ROOT_I);
 
+       ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
+       tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr);
 
        rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
-                    tmp_inode->i_ino, obj_type);
+                    ino, fattr.cf_dtype);
+
+       /*
+        * we can not return filldir errors to the caller since they are
+        * "normal" when the stat blocksize is too small - we return remapped
+        * error instead
+        *
+        * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above
+        * case already. Why should we be clobbering other errors from it?
+        */
        if (rc) {
                cFYI(1, ("filldir rc = %d", rc));
-               /* we can not return filldir errors to the caller
-               since they are "normal" when the stat blocksize
-               is too small - we return remapped error instead */
                rc = -EOVERFLOW;
        }
-
        dput(tmp_dentry);
        return rc;
 }
index 897a052270f90731628da48138ed93ada05cdf5f..7085a6275c4c9f0635383033dde2ee572bb046b0 100644 (file)
@@ -802,7 +802,7 @@ ssetup_ntlmssp_authenticate:
 #endif /* CONFIG_CIFS_UPCALL */
        } else {
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-               if ((experimEnabled > 1) && (type == RawNTLMSSP)) {
+               if (type == RawNTLMSSP) {
                        if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
                                cERROR(1, ("NTLMSSP requires Unicode support"));
                                rc = -ENOSYS;
index e9527eedc6396f9afd8dd25720a78730142a14b5..a75afa3dd9e18c9c606fe3f0c9ece44d343c47a0 100644 (file)
@@ -64,8 +64,9 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
 
        full_path = build_path_from_dentry(direntry);
        if (full_path == NULL) {
+               rc = -ENOMEM;
                FreeXid(xid);
-               return -ENOMEM;
+               return rc;
        }
        if (ea_name == NULL) {
                cFYI(1, ("Null xattr names not supported"));
@@ -118,8 +119,9 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
 
        full_path = build_path_from_dentry(direntry);
        if (full_path == NULL) {
+               rc = -ENOMEM;
                FreeXid(xid);
-               return -ENOMEM;
+               return rc;
        }
        /* return dos attributes as pseudo xattr */
        /* return alt name if available as pseudo attr */
@@ -225,8 +227,9 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
 
        full_path = build_path_from_dentry(direntry);
        if (full_path == NULL) {
+               rc = -ENOMEM;
                FreeXid(xid);
-               return -ENOMEM;
+               return rc;
        }
        /* return dos attributes as pseudo xattr */
        /* return alt name if available as pseudo attr */
@@ -351,8 +354,9 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
 
        full_path = build_path_from_dentry(direntry);
        if (full_path == NULL) {
+               rc = -ENOMEM;
                FreeXid(xid);
-               return -ENOMEM;
+               return rc;
        }
        /* return dos attributes as pseudo xattr */
        /* return alt name if available as pseudo attr */
index cdd51a3a7c537cd361d18ab21dabd1eafa4d4445..6d6f98fe64a086ae02c864d1e93ab3b597ef216e 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/smb_mount.h>
 #include <linux/ncp_mount.h>
 #include <linux/nfs4_mount.h>
-#include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 #include <linux/ctype.h>
 #include <linux/module.h>
@@ -1486,20 +1485,15 @@ int compat_do_execve(char * filename,
        if (!bprm)
                goto out_files;
 
-       retval = mutex_lock_interruptible(&current->cred_guard_mutex);
-       if (retval < 0)
+       retval = prepare_bprm_creds(bprm);
+       if (retval)
                goto out_free;
-       current->in_execve = 1;
-
-       retval = -ENOMEM;
-       bprm->cred = prepare_exec_creds();
-       if (!bprm->cred)
-               goto out_unlock;
 
        retval = check_unsafe_exec(bprm);
        if (retval < 0)
-               goto out_unlock;
+               goto out_free;
        clear_in_exec = retval;
+       current->in_execve = 1;
 
        file = open_exec(filename);
        retval = PTR_ERR(file);
@@ -1548,7 +1542,6 @@ int compat_do_execve(char * filename,
        /* execve succeeded */
        current->fs->in_exec = 0;
        current->in_execve = 0;
-       mutex_unlock(&current->cred_guard_mutex);
        acct_update_integrals(current);
        free_bprm(bprm);
        if (displaced)
@@ -1568,10 +1561,7 @@ out_file:
 out_unmark:
        if (clear_in_exec)
                current->fs->in_exec = 0;
-
-out_unlock:
        current->in_execve = 0;
-       mutex_unlock(&current->cred_guard_mutex);
 
 out_free:
        free_bprm(bprm);
index 626c7483b4de4e4f076bd4ab07af690007f9a0ae..f91fd51b32e321efc97a61b0d79274ecd81533ca 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/compiler.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
+#include <linux/smp_lock.h>
 #include <linux/ioctl.h>
 #include <linux/if.h>
 #include <linux/if_bridge.h>
@@ -1904,6 +1905,7 @@ COMPATIBLE_IOCTL(FIONCLEX)
 COMPATIBLE_IOCTL(FIOASYNC)
 COMPATIBLE_IOCTL(FIONBIO)
 COMPATIBLE_IOCTL(FIONREAD)  /* This is also TIOCINQ */
+COMPATIBLE_IOCTL(FS_IOC_FIEMAP)
 /* 0x00 */
 COMPATIBLE_IOCTL(FIBMAP)
 COMPATIBLE_IOCTL(FIGETBSZ)
index 205ec95b347e3001b6cb4358b8c6539802d95bed..eb507c453c5ff7ca221f933619a085461bec3300 100644 (file)
@@ -435,7 +435,7 @@ static int search_rsb(struct dlm_ls *ls, char *name, int len, int b,
 static int find_rsb(struct dlm_ls *ls, char *name, int namelen,
                    unsigned int flags, struct dlm_rsb **r_ret)
 {
-       struct dlm_rsb *r, *tmp;
+       struct dlm_rsb *r = NULL, *tmp;
        uint32_t hash, bucket;
        int error = -EINVAL;
 
index cdb580a9c7a28352e903fa660c848826966b9dc1..618a60f03886bf75118cefbe1fa113c1733e6baf 100644 (file)
@@ -902,7 +902,7 @@ static void tcp_connect_to_sock(struct connection *con)
        int result = -EHOSTUNREACH;
        struct sockaddr_storage saddr, src_addr;
        int addr_len;
-       struct socket *sock;
+       struct socket *sock = NULL;
 
        if (con->nodeid == 0) {
                log_print("attempt to connect sock 0 foiled");
@@ -962,6 +962,8 @@ out_err:
        if (con->sock) {
                sock_release(con->sock);
                con->sock = NULL;
+       } else if (sock) {
+               sock_release(sock);
        }
        /*
         * Some errors are fatal and this list might need adjusting. For other
index 894a32d438d5094bb9f1882825f5f01f12f096d7..16f682e26c07e49493e8a667a6b36cf0cf9f6bb6 100644 (file)
@@ -353,7 +353,7 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
 {
        struct dlm_plock_info info;
        struct plock_op *op;
-       int found = 0;
+       int found = 0, do_callback = 0;
 
        if (count != sizeof(info))
                return -EINVAL;
@@ -366,21 +366,24 @@ static ssize_t dev_write(struct file *file, const char __user *u, size_t count,
 
        spin_lock(&ops_lock);
        list_for_each_entry(op, &recv_list, list) {
-               if (op->info.fsid == info.fsid && op->info.number == info.number &&
+               if (op->info.fsid == info.fsid &&
+                   op->info.number == info.number &&
                    op->info.owner == info.owner) {
+                       struct plock_xop *xop = (struct plock_xop *)op;
                        list_del_init(&op->list);
-                       found = 1;
-                       op->done = 1;
                        memcpy(&op->info, &info, sizeof(info));
+                       if (xop->callback)
+                               do_callback = 1;
+                       else
+                               op->done = 1;
+                       found = 1;
                        break;
                }
        }
        spin_unlock(&ops_lock);
 
        if (found) {
-               struct plock_xop *xop;
-               xop = (struct plock_xop *)op;
-               if (xop->callback)
+               if (do_callback)
                        dlm_plock_callback(op);
                else
                        wake_up(&recv_wq);
index af737bb56cb71942ebed99c9bad8eb6a34bdaeb8..259525c9abb8c0296f19fa3dc340b9ac29e70acd 100644 (file)
@@ -1303,6 +1303,13 @@ parse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
        }
        (*new_auth_tok)->session_key.encrypted_key_size =
                (body_size - (ECRYPTFS_SALT_SIZE + 5));
+       if ((*new_auth_tok)->session_key.encrypted_key_size
+           > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
+               printk(KERN_WARNING "Tag 3 packet contains key larger "
+                      "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES\n");
+               rc = -EINVAL;
+               goto out_free;
+       }
        if (unlikely(data[(*packet_size)++] != 0x04)) {
                printk(KERN_WARNING "Unknown version number [%d]\n",
                       data[(*packet_size) - 1]);
@@ -1449,6 +1456,12 @@ parse_tag_11_packet(unsigned char *data, unsigned char *contents,
                rc = -EINVAL;
                goto out;
        }
+       if (unlikely((*tag_11_contents_size) > max_contents_bytes)) {
+               printk(KERN_ERR "Literal data section in tag 11 packet exceeds "
+                      "expected size\n");
+               rc = -EINVAL;
+               goto out;
+       }
        if (data[(*packet_size)++] != 0x62) {
                printk(KERN_WARNING "Unrecognizable packet\n");
                rc = -EINVAL;
index 3f0e1974abdcfbfb8cd8afff3a19346667768672..31d12de83a2a9584245e8c983e6c5f0e1a74ea29 100644 (file)
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/anon_inodes.h>
-#include <linux/eventfd.h>
 #include <linux/syscalls.h>
 #include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/eventfd.h>
 
 struct eventfd_ctx {
+       struct kref kref;
        wait_queue_head_t wqh;
        /*
         * Every time that a write(2) is performed on an eventfd, the
         * value of the __u64 being written is added to "count" and a
         * wakeup is performed on "wqh". A read(2) will return the "count"
         * value to userspace, and will reset "count" to zero. The kernel
-        * size eventfd_signal() also, adds to the "count" counter and
+        * side eventfd_signal() also, adds to the "count" counter and
         * issue a wakeup.
         */
        __u64 count;
        unsigned int flags;
 };
 
-/*
- * Adds "n" to the eventfd counter "count". Returns "n" in case of
- * success, or a value lower then "n" in case of coutner overflow.
- * This function is supposed to be called by the kernel in paths
- * that do not allow sleeping. In this function we allow the counter
- * to reach the ULLONG_MAX value, and we signal this as overflow
- * condition by returining a POLLERR to poll(2).
+/**
+ * eventfd_signal - Adds @n to the eventfd counter.
+ * @ctx: [in] Pointer to the eventfd context.
+ * @n: [in] Value of the counter to be added to the eventfd internal counter.
+ *          The value cannot be negative.
+ *
+ * This function is supposed to be called by the kernel in paths that do not
+ * allow sleeping. In this function we allow the counter to reach the ULLONG_MAX
+ * value, and we signal this as overflow condition by returining a POLLERR
+ * to poll(2).
+ *
+ * Returns @n in case of success, a non-negative number lower than @n in case
+ * of overflow, or the following error codes:
+ *
+ * -EINVAL    : The value of @n is negative.
  */
-int eventfd_signal(struct file *file, int n)
+int eventfd_signal(struct eventfd_ctx *ctx, int n)
 {
-       struct eventfd_ctx *ctx = file->private_data;
        unsigned long flags;
 
        if (n < 0)
@@ -59,9 +68,45 @@ int eventfd_signal(struct file *file, int n)
 }
 EXPORT_SYMBOL_GPL(eventfd_signal);
 
+static void eventfd_free(struct kref *kref)
+{
+       struct eventfd_ctx *ctx = container_of(kref, struct eventfd_ctx, kref);
+
+       kfree(ctx);
+}
+
+/**
+ * eventfd_ctx_get - Acquires a reference to the internal eventfd context.
+ * @ctx: [in] Pointer to the eventfd context.
+ *
+ * Returns: In case of success, returns a pointer to the eventfd context.
+ */
+struct eventfd_ctx *eventfd_ctx_get(struct eventfd_ctx *ctx)
+{
+       kref_get(&ctx->kref);
+       return ctx;
+}
+EXPORT_SYMBOL_GPL(eventfd_ctx_get);
+
+/**
+ * eventfd_ctx_put - Releases a reference to the internal eventfd context.
+ * @ctx: [in] Pointer to eventfd context.
+ *
+ * The eventfd context reference must have been previously acquired either
+ * with eventfd_ctx_get() or eventfd_ctx_fdget()).
+ */
+void eventfd_ctx_put(struct eventfd_ctx *ctx)
+{
+       kref_put(&ctx->kref, eventfd_free);
+}
+EXPORT_SYMBOL_GPL(eventfd_ctx_put);
+
 static int eventfd_release(struct inode *inode, struct file *file)
 {
-       kfree(file->private_data);
+       struct eventfd_ctx *ctx = file->private_data;
+
+       wake_up_poll(&ctx->wqh, POLLHUP);
+       eventfd_ctx_put(ctx);
        return 0;
 }
 
@@ -185,6 +230,16 @@ static const struct file_operations eventfd_fops = {
        .write          = eventfd_write,
 };
 
+/**
+ * eventfd_fget - Acquire a reference of an eventfd file descriptor.
+ * @fd: [in] Eventfd file descriptor.
+ *
+ * Returns a pointer to the eventfd file structure in case of success, or the
+ * following error pointer:
+ *
+ * -EBADF    : Invalid @fd file descriptor.
+ * -EINVAL   : The @fd file descriptor is not an eventfd file.
+ */
 struct file *eventfd_fget(int fd)
 {
        struct file *file;
@@ -201,6 +256,48 @@ struct file *eventfd_fget(int fd)
 }
 EXPORT_SYMBOL_GPL(eventfd_fget);
 
+/**
+ * eventfd_ctx_fdget - Acquires a reference to the internal eventfd context.
+ * @fd: [in] Eventfd file descriptor.
+ *
+ * Returns a pointer to the internal eventfd context, otherwise the error
+ * pointers returned by the following functions:
+ *
+ * eventfd_fget
+ */
+struct eventfd_ctx *eventfd_ctx_fdget(int fd)
+{
+       struct file *file;
+       struct eventfd_ctx *ctx;
+
+       file = eventfd_fget(fd);
+       if (IS_ERR(file))
+               return (struct eventfd_ctx *) file;
+       ctx = eventfd_ctx_get(file->private_data);
+       fput(file);
+
+       return ctx;
+}
+EXPORT_SYMBOL_GPL(eventfd_ctx_fdget);
+
+/**
+ * eventfd_ctx_fileget - Acquires a reference to the internal eventfd context.
+ * @file: [in] Eventfd file pointer.
+ *
+ * Returns a pointer to the internal eventfd context, otherwise the error
+ * pointer:
+ *
+ * -EINVAL   : The @fd file descriptor is not an eventfd file.
+ */
+struct eventfd_ctx *eventfd_ctx_fileget(struct file *file)
+{
+       if (file->f_op != &eventfd_fops)
+               return ERR_PTR(-EINVAL);
+
+       return eventfd_ctx_get(file->private_data);
+}
+EXPORT_SYMBOL_GPL(eventfd_ctx_fileget);
+
 SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags)
 {
        int fd;
@@ -217,6 +314,7 @@ SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags)
        if (!ctx)
                return -ENOMEM;
 
+       kref_init(&ctx->kref);
        init_waitqueue_head(&ctx->wqh);
        ctx->count = count;
        ctx->flags = flags;
index e639957d7a57a310c12718e8fe3e4f0d9dfe2fe2..172ceb6edde4df6ff8520cd9951b3bc2ca86b2c2 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -678,8 +678,8 @@ exit:
 }
 EXPORT_SYMBOL(open_exec);
 
-int kernel_read(struct file *file, unsigned long offset,
-       char *addr, unsigned long count)
+int kernel_read(struct file *file, loff_t offset,
+               char *addr, unsigned long count)
 {
        mm_segment_t old_fs;
        loff_t pos = offset;
@@ -1015,6 +1015,35 @@ out:
 
 EXPORT_SYMBOL(flush_old_exec);
 
+/*
+ * Prepare credentials and lock ->cred_guard_mutex.
+ * install_exec_creds() commits the new creds and drops the lock.
+ * Or, if exec fails before, free_bprm() should release ->cred and
+ * and unlock.
+ */
+int prepare_bprm_creds(struct linux_binprm *bprm)
+{
+       if (mutex_lock_interruptible(&current->cred_guard_mutex))
+               return -ERESTARTNOINTR;
+
+       bprm->cred = prepare_exec_creds();
+       if (likely(bprm->cred))
+               return 0;
+
+       mutex_unlock(&current->cred_guard_mutex);
+       return -ENOMEM;
+}
+
+void free_bprm(struct linux_binprm *bprm)
+{
+       free_arg_pages(bprm);
+       if (bprm->cred) {
+               mutex_unlock(&current->cred_guard_mutex);
+               abort_creds(bprm->cred);
+       }
+       kfree(bprm);
+}
+
 /*
  * install the new credentials for this executable
  */
@@ -1024,12 +1053,13 @@ void install_exec_creds(struct linux_binprm *bprm)
 
        commit_creds(bprm->cred);
        bprm->cred = NULL;
-
-       /* cred_guard_mutex must be held at least to this point to prevent
+       /*
+        * cred_guard_mutex must be held at least to this point to prevent
         * ptrace_attach() from altering our determination of the task's
-        * credentials; any time after this it may be unlocked */
-
+        * credentials; any time after this it may be unlocked.
+        */
        security_bprm_committed_creds(bprm);
+       mutex_unlock(&current->cred_guard_mutex);
 }
 EXPORT_SYMBOL(install_exec_creds);
 
@@ -1246,14 +1276,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
 
 EXPORT_SYMBOL(search_binary_handler);
 
-void free_bprm(struct linux_binprm *bprm)
-{
-       free_arg_pages(bprm);
-       if (bprm->cred)
-               abort_creds(bprm->cred);
-       kfree(bprm);
-}
-
 /*
  * sys_execve() executes a new program.
  */
@@ -1277,20 +1299,15 @@ int do_execve(char * filename,
        if (!bprm)
                goto out_files;
 
-       retval = mutex_lock_interruptible(&current->cred_guard_mutex);
-       if (retval < 0)
+       retval = prepare_bprm_creds(bprm);
+       if (retval)
                goto out_free;
-       current->in_execve = 1;
-
-       retval = -ENOMEM;
-       bprm->cred = prepare_exec_creds();
-       if (!bprm->cred)
-               goto out_unlock;
 
        retval = check_unsafe_exec(bprm);
        if (retval < 0)
-               goto out_unlock;
+               goto out_free;
        clear_in_exec = retval;
+       current->in_execve = 1;
 
        file = open_exec(filename);
        retval = PTR_ERR(file);
@@ -1340,7 +1357,6 @@ int do_execve(char * filename,
        /* execve succeeded */
        current->fs->in_exec = 0;
        current->in_execve = 0;
-       mutex_unlock(&current->cred_guard_mutex);
        acct_update_integrals(current);
        free_bprm(bprm);
        if (displaced)
@@ -1360,10 +1376,7 @@ out_file:
 out_unmark:
        if (clear_in_exec)
                current->fs->in_exec = 0;
-
-out_unlock:
        current->in_execve = 0;
-       mutex_unlock(&current->cred_guard_mutex);
 
 out_free:
        free_bprm(bprm);
index 24667eedc02329554735f72420cbc04d99faa871..c6718e4817feab5e56a2903b409493a458d3de84 100644 (file)
@@ -2,9 +2,7 @@
  * common.h - Common definitions for both Kernel and user-mode utilities
  *
  * Copyright (C) 2005, 2006
- * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com)
- * Copyright (C) 2005, 2006
- * International Business Machines
+ * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
  * Boaz Harrosh <bharrosh@panasas.com>
  *
index 65b0c8c776a1db8144c74ce0d7074512da882b51..4cfab1cc75c03a0bb7654e5c8150c2009fe4aa11 100644 (file)
@@ -1,8 +1,6 @@
 /*
  * Copyright (C) 2005, 2006
- * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com)
- * Copyright (C) 2005, 2006
- * International Business Machines
+ * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
  * Boaz Harrosh <bharrosh@panasas.com>
  *
index 0fd4c7859679390e11eac05838ec5d35e6718c74..5ec72e020b22bb8fcbb1f08d1df4af037ab179bd 100644 (file)
@@ -1,8 +1,6 @@
 /*
  * Copyright (C) 2005, 2006
- * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com)
- * Copyright (C) 2005, 2006
- * International Business Machines
+ * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
  * Boaz Harrosh <bharrosh@panasas.com>
  *
@@ -156,6 +154,9 @@ ino_t exofs_parent_ino(struct dentry *child);
 int exofs_set_link(struct inode *, struct exofs_dir_entry *, struct page *,
                    struct inode *);
 
+/* super.c               */
+int exofs_sync_fs(struct super_block *sb, int wait);
+
 /*********************
  * operation vectors *
  *********************/
index 6ed7fe4847522db1f7766528478d6b508ad64af7..839b9dc1e70f3f6663a428e2d48938f6aadfcb0c 100644 (file)
@@ -1,8 +1,6 @@
 /*
  * Copyright (C) 2005, 2006
- * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com)
- * Copyright (C) 2005, 2006
- * International Business Machines
+ * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
  * Boaz Harrosh <bharrosh@panasas.com>
  *
@@ -47,16 +45,23 @@ static int exofs_file_fsync(struct file *filp, struct dentry *dentry,
 {
        int ret;
        struct address_space *mapping = filp->f_mapping;
+       struct inode *inode = dentry->d_inode;
+       struct super_block *sb;
 
        ret = filemap_write_and_wait(mapping);
        if (ret)
                return ret;
 
-       /*Note: file_fsync below also calles sync_blockdev, which is a no-op
-        *      for exofs, but other then that it does sync_inode and
-        *      sync_superblock which is what we need here.
-        */
-       return file_fsync(filp, dentry, datasync);
+       /* sync the inode attributes */
+       ret = write_inode_now(inode, 1);
+
+       /* This is a good place to write the sb */
+       /* TODO: Sechedule an sb-sync on create */
+       sb = inode->i_sb;
+       if (sb->s_dirt)
+               exofs_sync_fs(sb, 1);
+
+       return ret;
 }
 
 static int exofs_flush(struct file *file, fl_owner_t id)
index 77d0a295eb1cd3e95443da014fc9801cf64f5aff..6c10f7476699c4da76b18453a844aefcaa6c9f09 100644 (file)
@@ -1,8 +1,6 @@
 /*
  * Copyright (C) 2005, 2006
- * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com)
- * Copyright (C) 2005, 2006
- * International Business Machines
+ * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
  * Boaz Harrosh <bharrosh@panasas.com>
  *
@@ -295,6 +293,9 @@ static int read_exec(struct page_collect *pcol, bool is_sync)
 err:
        if (!is_sync)
                _unlock_pcol_pages(pcol, ret, READ);
+       else /* Pages unlocked by caller in sync mode only free bio */
+               pcol_free(pcol);
+
        kfree(pcol_copy);
        if (or)
                osd_end_request(or);
index 77fdd765e76d13300432de102a7b19986da6fc09..b7dd0c23686376822ffd40c185bc9b1683796d31 100644 (file)
@@ -1,8 +1,6 @@
 /*
  * Copyright (C) 2005, 2006
- * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com)
- * Copyright (C) 2005, 2006
- * International Business Machines
+ * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
  * Boaz Harrosh <bharrosh@panasas.com>
  *
index b3d2ccb87aaa8981374e824066bfd2aa608fa86a..4372542df284ed8336a86f6ce205f9465980e707 100644 (file)
@@ -1,8 +1,6 @@
 /*
  * Copyright (C) 2005, 2006
- * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com)
- * Copyright (C) 2005, 2006
- * International Business Machines
+ * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
  * Boaz Harrosh <bharrosh@panasas.com>
  *
index 8216c5b77b5325db78970efc711ab3729a1ea46e..5ab10c3bbebec0dd1ba2ab81c340b6be415dcafd 100644 (file)
@@ -1,8 +1,6 @@
 /*
  * Copyright (C) 2005, 2006
- * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com)
- * Copyright (C) 2005, 2006
- * International Business Machines
+ * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
  * Boaz Harrosh <bharrosh@panasas.com>
  *
@@ -33,6 +31,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <linux/smp_lock.h>
 #include <linux/string.h>
 #include <linux/parser.h>
 #include <linux/vfs.h>
@@ -200,7 +199,7 @@ static const struct export_operations exofs_export_ops;
 /*
  * Write the superblock to the OSD
  */
-static int exofs_sync_fs(struct super_block *sb, int wait)
+int exofs_sync_fs(struct super_block *sb, int wait)
 {
        struct exofs_sb_info *sbi;
        struct exofs_fscb *fscb;
index 36e2d7bc7f7bd2a93eb8363b7b9b31801732e60f..4dd687c3e74740f57b9ea4180859ed34f57da8cc 100644 (file)
@@ -1,8 +1,6 @@
 /*
  * Copyright (C) 2005, 2006
- * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com)
- * Copyright (C) 2005, 2006
- * International Business Machines
+ * Avishay Traeger (avishay@gmail.com)
  * Copyright (C) 2008, 2009
  * Boaz Harrosh <bharrosh@panasas.com>
  *
index 7cb4badef927433ec90618b67c69cc08bec936f1..e7431309bdca9b7c873a34718263f14097b81ff5 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/sched.h>
 #include <linux/compat.h>
 #include <linux/mount.h>
-#include <linux/smp_lock.h>
 #include <asm/current.h>
 #include <asm/uaccess.h>
 
index 6524ecaebb7a6fe6910587026c5f8039b1a1f88c..78d9b925fc94dc7e35d1abe920dcdeeaff92bead 100644 (file)
@@ -66,8 +66,16 @@ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, str
        inode = NULL;
        if (ino) {
                inode = ext2_iget(dir->i_sb, ino);
-               if (IS_ERR(inode))
-                       return ERR_CAST(inode);
+               if (unlikely(IS_ERR(inode))) {
+                       if (PTR_ERR(inode) == -ESTALE) {
+                               ext2_error(dir->i_sb, __func__,
+                                               "deleted inode referenced: %lu",
+                                               ino);
+                               return ERR_PTR(-EIO);
+                       } else {
+                               return ERR_CAST(inode);
+                       }
+               }
        }
        return d_splice_alias(inode, dentry);
 }
@@ -354,6 +362,10 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
        if (dir_de) {
                if (old_dir != new_dir)
                        ext2_set_link(old_inode, dir_de, dir_page, new_dir, 0);
+               else {
+                       kunmap(dir_page);
+                       page_cache_release(dir_page);
+               }
                inode_dec_link_count(old_dir);
        }
        return 0;
index fb3c1a21b13594d1edf76fd09e6fdc35b0a5f216..522b15498f459da163b2318348108569f1f34a92 100644 (file)
@@ -29,23 +29,25 @@ config EXT3_FS
          module will be called ext3.
 
 config EXT3_DEFAULTS_TO_ORDERED
-       bool "Default to 'data=ordered' in ext3 (legacy option)"
+       bool "Default to 'data=ordered' in ext3"
        depends on EXT3_FS
        help
-         If a filesystem does not explicitly specify a data ordering
-         mode, and the journal capability allowed it, ext3 used to
-         historically default to 'data=ordered'.
-
-         That was a rather unfortunate choice, because it leads to all
-         kinds of latency problems, and the 'data=writeback' mode is more
-         appropriate these days.
-
-         You should probably always answer 'n' here, and if you really
-         want to use 'data=ordered' mode, set it in the filesystem itself
-         with 'tune2fs -o journal_data_ordered'.
-
-         But if you really want to enable the legacy default, you can do
-         so by answering 'y' to this question.
+         The journal mode options for ext3 have different tradeoffs
+         between when data is guaranteed to be on disk and
+         performance.  The use of "data=writeback" can cause
+         unwritten data to appear in files after an system crash or
+         power failure, which can be a security issue.  However,
+         "data=ordered" mode can also result in major performance
+         problems, including seconds-long delays before an fsync()
+         call returns.  For details, see:
+
+         http://ext4.wiki.kernel.org/index.php/Ext3_data_mode_tradeoffs
+
+         If you have been historically happy with ext3's performance,
+         data=ordered mode will be a safe choice and you should
+         answer 'y' here.  If you understand the reliability and data
+         privacy issues of data=writeback and are willing to make
+         that trade off, answer 'n'.
 
 config EXT3_FS_XATTR
        bool "Ext3 extended attributes"
index 3d724a95882f618672a45ee8f945d9164f80b89f..373fa90c796a0821c23cd441c0a238a1a52cfb69 100644 (file)
@@ -130,8 +130,7 @@ static int ext3_readdir(struct file * filp,
                struct buffer_head *bh = NULL;
 
                map_bh.b_state = 0;
-               err = ext3_get_blocks_handle(NULL, inode, blk, 1,
-                                               &map_bh, 0, 0);
+               err = ext3_get_blocks_handle(NULL, inode, blk, 1, &map_bh, 0);
                if (err > 0) {
                        pgoff_t index = map_bh.b_blocknr >>
                                        (PAGE_CACHE_SHIFT - inode->i_blkbits);
index 5f51fed5c750870b8c575fdf7dd8e877fe986bfb..b49908a167ae09d366f76ddcef57432f338b5735 100644 (file)
@@ -788,7 +788,7 @@ err_out:
 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 create)
 {
        int err = -EIO;
        int offsets[4];
@@ -911,13 +911,6 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
        if (!err)
                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
-        * ext3_get_block() -bzzz
-       */
-       if (!err && extend_disksize && inode->i_size > ei->i_disksize)
-               ei->i_disksize = inode->i_size;
        mutex_unlock(&ei->truncate_mutex);
        if (err)
                goto cleanup;
@@ -972,7 +965,7 @@ static int ext3_get_block(struct inode *inode, sector_t iblock,
        }
 
        ret = ext3_get_blocks_handle(handle, inode, iblock,
-                                       max_blocks, bh_result, create, 0);
+                                       max_blocks, bh_result, create);
        if (ret > 0) {
                bh_result->b_size = (ret << inode->i_blkbits);
                ret = 0;
@@ -1005,7 +998,7 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode *inode,
        dummy.b_blocknr = -1000;
        buffer_trace_init(&dummy.b_history);
        err = ext3_get_blocks_handle(handle, inode, block, 1,
-                                       &dummy, create, 1);
+                                       &dummy, create);
        /*
         * ext3_get_blocks_handle() returns number of blocks
         * mapped. 0 in case of a HOLE.
@@ -1193,15 +1186,16 @@ write_begin_failed:
                 * i_size_read because we hold i_mutex.
                 *
                 * Add inode to orphan list in case we crash before truncate
-                * finishes.
+                * finishes. Do this only if ext3_can_truncate() agrees so
+                * that orphan processing code is happy.
                 */
-               if (pos + len > inode->i_size)
+               if (pos + len > inode->i_size && ext3_can_truncate(inode))
                        ext3_orphan_add(handle, inode);
                ext3_journal_stop(handle);
                unlock_page(page);
                page_cache_release(page);
                if (pos + len > inode->i_size)
-                       vmtruncate(inode, inode->i_size);
+                       ext3_truncate(inode);
        }
        if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
                goto retry;
@@ -1287,7 +1281,7 @@ static int ext3_ordered_write_end(struct file *file,
         * There may be allocated blocks outside of i_size because
         * we failed to copy some data. Prepare for truncate.
         */
-       if (pos + len > inode->i_size)
+       if (pos + len > inode->i_size && ext3_can_truncate(inode))
                ext3_orphan_add(handle, inode);
        ret2 = ext3_journal_stop(handle);
        if (!ret)
@@ -1296,7 +1290,7 @@ static int ext3_ordered_write_end(struct file *file,
        page_cache_release(page);
 
        if (pos + len > inode->i_size)
-               vmtruncate(inode, inode->i_size);
+               ext3_truncate(inode);
        return ret ? ret : copied;
 }
 
@@ -1315,14 +1309,14 @@ static int ext3_writeback_write_end(struct file *file,
         * There may be allocated blocks outside of i_size because
         * we failed to copy some data. Prepare for truncate.
         */
-       if (pos + len > inode->i_size)
+       if (pos + len > inode->i_size && ext3_can_truncate(inode))
                ext3_orphan_add(handle, inode);
        ret = ext3_journal_stop(handle);
        unlock_page(page);
        page_cache_release(page);
 
        if (pos + len > inode->i_size)
-               vmtruncate(inode, inode->i_size);
+               ext3_truncate(inode);
        return ret ? ret : copied;
 }
 
@@ -1358,7 +1352,7 @@ static int ext3_journalled_write_end(struct file *file,
         * There may be allocated blocks outside of i_size because
         * we failed to copy some data. Prepare for truncate.
         */
-       if (pos + len > inode->i_size)
+       if (pos + len > inode->i_size && ext3_can_truncate(inode))
                ext3_orphan_add(handle, inode);
        EXT3_I(inode)->i_state |= EXT3_STATE_JDATA;
        if (inode->i_size > EXT3_I(inode)->i_disksize) {
@@ -1375,7 +1369,7 @@ static int ext3_journalled_write_end(struct file *file,
        page_cache_release(page);
 
        if (pos + len > inode->i_size)
-               vmtruncate(inode, inode->i_size);
+               ext3_truncate(inode);
        return ret ? ret : copied;
 }
 
index 524b349c6299ca248b366cf299071939e5843aba..a8d80a7f11050d7a518e79ac003701d12865b3a7 100644 (file)
@@ -543,6 +543,19 @@ static inline void ext3_show_quota_options(struct seq_file *seq, struct super_bl
 #endif
 }
 
+static char *data_mode_string(unsigned long mode)
+{
+       switch (mode) {
+       case EXT3_MOUNT_JOURNAL_DATA:
+               return "journal";
+       case EXT3_MOUNT_ORDERED_DATA:
+               return "ordered";
+       case EXT3_MOUNT_WRITEBACK_DATA:
+               return "writeback";
+       }
+       return "unknown";
+}
+
 /*
  * Show an option if
  *  - it's set to a non-default value OR
@@ -616,13 +629,8 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
        if (test_opt(sb, NOBH))
                seq_puts(seq, ",nobh");
 
-       if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA)
-               seq_puts(seq, ",data=journal");
-       else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA)
-               seq_puts(seq, ",data=ordered");
-       else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
-               seq_puts(seq, ",data=writeback");
-
+       seq_printf(seq, ",data=%s", data_mode_string(sbi->s_mount_opt &
+                                                    EXT3_MOUNT_DATA_FLAGS));
        if (test_opt(sb, DATA_ERR_ABORT))
                seq_puts(seq, ",data_err=abort");
 
@@ -1024,12 +1032,18 @@ static int parse_options (char *options, struct super_block *sb,
                datacheck:
                        if (is_remount) {
                                if ((sbi->s_mount_opt & EXT3_MOUNT_DATA_FLAGS)
-                                               != data_opt) {
-                                       printk(KERN_ERR
-                                               "EXT3-fs: cannot change data "
-                                               "mode on remount\n");
-                                       return 0;
-                               }
+                                               == data_opt)
+                                       break;
+                               printk(KERN_ERR
+                                       "EXT3-fs (device %s): Cannot change "
+                                       "data mode on remount. The filesystem "
+                                       "is mounted in data=%s mode and you "
+                                       "try to remount it in data=%s mode.\n",
+                                       sb->s_id,
+                                       data_mode_string(sbi->s_mount_opt &
+                                                       EXT3_MOUNT_DATA_FLAGS),
+                                       data_mode_string(data_opt));
+                               return 0;
                        } else {
                                sbi->s_mount_opt &= ~EXT3_MOUNT_DATA_FLAGS;
                                sbi->s_mount_opt |= data_opt;
index 0ddf7e55abe181e3ac1bd31fea3357bf4c1bf8a6..9714db393efe8a1b6fa2ff0b2e7cf36fb7ecc199 100644 (file)
@@ -93,20 +93,20 @@ typedef unsigned int ext4_group_t;
 struct ext4_allocation_request {
        /* target inode for block we're allocating */
        struct inode *inode;
+       /* how many blocks we want to allocate */
+       unsigned int len;
        /* logical block in target inode */
        ext4_lblk_t logical;
-       /* phys. target (a hint) */
-       ext4_fsblk_t goal;
        /* the closest logical allocated block to the left */
        ext4_lblk_t lleft;
-       /* phys. block for ^^^ */
-       ext4_fsblk_t pleft;
        /* the closest logical allocated block to the right */
        ext4_lblk_t lright;
-       /* phys. block for ^^^ */
+       /* phys. target (a hint) */
+       ext4_fsblk_t goal;
+       /* phys. block for the closest logical allocated block to the left */
+       ext4_fsblk_t pleft;
+       /* phys. block for the closest logical allocated block to the right */
        ext4_fsblk_t pright;
-       /* how many blocks we want to allocate */
-       unsigned int len;
        /* flags. see above EXT4_MB_HINT_* */
        unsigned int flags;
 };
index ad13a84644e1ff94000dda0ab8bbe09f05a417e7..eb27fd0f2ee86dd4c8badd2ed146f2a306e1f35f 100644 (file)
@@ -43,6 +43,8 @@ int __ext4_journal_forget(const char *where, handle_t *handle,
                        ext4_journal_abort_handle(where, __func__, bh,
                                                  handle, err);
        }
+       else
+               brelse(bh);
        return err;
 }
 
@@ -57,6 +59,8 @@ int __ext4_journal_revoke(const char *where, handle_t *handle,
                        ext4_journal_abort_handle(where, __func__, bh,
                                                  handle, err);
        }
+       else
+               brelse(bh);
        return err;
 }
 
index be2f426f680538065b86aac16bb1f2f822a49a48..139fb8cb87e40dabf2538ff28d163849ed8d2bfa 100644 (file)
@@ -131,9 +131,11 @@ int __ext4_journal_get_undo_access(const char *where, handle_t *handle,
 int __ext4_journal_get_write_access(const char *where, handle_t *handle,
                                struct buffer_head *bh);
 
+/* When called with an invalid handle, this will still do a put on the BH */
 int __ext4_journal_forget(const char *where, handle_t *handle,
                                struct buffer_head *bh);
 
+/* When called with an invalid handle, this will still do a put on the BH */
 int __ext4_journal_revoke(const char *where, handle_t *handle,
                                ext4_fsblk_t blocknr, struct buffer_head *bh);
 
@@ -281,10 +283,10 @@ static inline int ext4_should_order_data(struct inode *inode)
 
 static inline int ext4_should_writeback_data(struct inode *inode)
 {
-       if (EXT4_JOURNAL(inode) == NULL)
-               return 0;
        if (!S_ISREG(inode->i_mode))
                return 0;
+       if (EXT4_JOURNAL(inode) == NULL)
+               return 1;
        if (EXT4_I(inode)->i_flags & EXT4_JOURNAL_DATA_FL)
                return 0;
        if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
index 50322a09bd01af54d66cf2d344765b8b92075332..73ebfb44ad750f0405976f7ff6c792936edb0765 100644 (file)
@@ -1977,6 +1977,7 @@ int ext4_ext_calc_credits_for_single_extent(struct inode *inode, int nrblocks,
                         */
                        /* 1 bitmap, 1 block group descriptor */
                        ret = 2 + EXT4_META_TRANS_BLOCKS(inode->i_sb);
+                       return ret;
                }
        }
 
index 2f645732e3b76ef84e76f58761c16116825c2763..29e6dc7299b8b6186cf46a39deac0a88594b6028 100644 (file)
@@ -833,7 +833,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode,
        if (!goal)
                goal = sbi->s_inode_goal;
 
-       if (goal && goal < le32_to_cpu(sbi->s_es->s_inodes_count)) {
+       if (goal && goal <= le32_to_cpu(sbi->s_es->s_inodes_count)) {
                group = (goal - 1) / EXT4_INODES_PER_GROUP(sb);
                ino = (goal - 1) % EXT4_INODES_PER_GROUP(sb);
                ret2 = 0;
index 60a26f3a6f8bd3e2ac5db8cfc220538630b7de6a..f9c642b22efabb56f5ec3ae109bf2eaf75beee8a 100644 (file)
@@ -78,16 +78,14 @@ static int ext4_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.
  *
- * If the handle isn't valid we're not journaling so there's nothing to do.
+ * If the handle isn't valid we're not journaling, but we still need to
+ * call into ext4_journal_revoke() to put the buffer head.
  */
 int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
                struct buffer_head *bh, ext4_fsblk_t blocknr)
 {
        int err;
 
-       if (!ext4_handle_valid(handle))
-               return 0;
-
        might_sleep();
 
        BUFFER_TRACE(bh, "enter");
@@ -1513,14 +1511,14 @@ retry:
                 * Add inode to orphan list in case we crash before
                 * truncate finishes
                 */
-               if (pos + len > inode->i_size)
+               if (pos + len > inode->i_size && ext4_can_truncate(inode))
                        ext4_orphan_add(handle, inode);
 
                ext4_journal_stop(handle);
                if (pos + len > inode->i_size) {
-                       vmtruncate(inode, inode->i_size);
+                       ext4_truncate(inode);
                        /*
-                        * If vmtruncate failed early the inode might
+                        * If truncate failed early the inode might
                         * still be on the orphan list; we need to
                         * make sure the inode is removed from the
                         * orphan list in that case.
@@ -1614,7 +1612,7 @@ static int ext4_ordered_write_end(struct file *file,
                ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
                                                        page, fsdata);
                copied = ret2;
-               if (pos + len > inode->i_size)
+               if (pos + len > inode->i_size && ext4_can_truncate(inode))
                        /* if we have allocated more blocks and copied
                         * less. We will have blocks allocated outside
                         * inode->i_size. So truncate them
@@ -1628,9 +1626,9 @@ static int ext4_ordered_write_end(struct file *file,
                ret = ret2;
 
        if (pos + len > inode->i_size) {
-               vmtruncate(inode, inode->i_size);
+               ext4_truncate(inode);
                /*
-                * If vmtruncate failed early the inode might still be
+                * If truncate failed early the inode might still be
                 * on the orphan list; we need to make sure the inode
                 * is removed from the orphan list in that case.
                 */
@@ -1655,7 +1653,7 @@ static int ext4_writeback_write_end(struct file *file,
        ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
                                                        page, fsdata);
        copied = ret2;
-       if (pos + len > inode->i_size)
+       if (pos + len > inode->i_size && ext4_can_truncate(inode))
                /* if we have allocated more blocks and copied
                 * less. We will have blocks allocated outside
                 * inode->i_size. So truncate them
@@ -1670,9 +1668,9 @@ static int ext4_writeback_write_end(struct file *file,
                ret = ret2;
 
        if (pos + len > inode->i_size) {
-               vmtruncate(inode, inode->i_size);
+               ext4_truncate(inode);
                /*
-                * If vmtruncate failed early the inode might still be
+                * If truncate failed early the inode might still be
                 * on the orphan list; we need to make sure the inode
                 * is removed from the orphan list in that case.
                 */
@@ -1722,7 +1720,7 @@ static int ext4_journalled_write_end(struct file *file,
 
        unlock_page(page);
        page_cache_release(page);
-       if (pos + len > inode->i_size)
+       if (pos + len > inode->i_size && ext4_can_truncate(inode))
                /* if we have allocated more blocks and copied
                 * less. We will have blocks allocated outside
                 * inode->i_size. So truncate them
@@ -1733,9 +1731,9 @@ static int ext4_journalled_write_end(struct file *file,
        if (!ret)
                ret = ret2;
        if (pos + len > inode->i_size) {
-               vmtruncate(inode, inode->i_size);
+               ext4_truncate(inode);
                /*
-                * If vmtruncate failed early the inode might still be
+                * If truncate failed early the inode might still be
                 * on the orphan list; we need to make sure the inode
                 * is removed from the orphan list in that case.
                 */
@@ -2305,15 +2303,9 @@ flush_it:
        return;
 }
 
-static int ext4_bh_unmapped_or_delay(handle_t *handle, struct buffer_head *bh)
+static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh)
 {
-       /*
-        * unmapped buffer is possible for holes.
-        * delay buffer is possible with delayed allocation.
-        * We also need to consider unwritten buffer as unmapped.
-        */
-       return (!buffer_mapped(bh) || buffer_delay(bh) ||
-                               buffer_unwritten(bh)) && buffer_dirty(bh);
+       return (buffer_delay(bh) || buffer_unwritten(bh)) && buffer_dirty(bh);
 }
 
 /*
@@ -2398,9 +2390,9 @@ static int __mpage_da_writepage(struct page *page,
                         * We need to try to allocate
                         * unmapped blocks in the same page.
                         * Otherwise we won't make progress
-                        * with the page in ext4_da_writepage
+                        * with the page in ext4_writepage
                         */
-                       if (ext4_bh_unmapped_or_delay(NULL, bh)) {
+                       if (ext4_bh_delay_or_unwritten(NULL, bh)) {
                                mpage_add_bh_to_extent(mpd, logical,
                                                       bh->b_size,
                                                       bh->b_state);
@@ -2517,7 +2509,6 @@ static int noalloc_get_block_write(struct inode *inode, sector_t iblock,
         * so call get_block_wrap with create = 0
         */
        ret = ext4_get_blocks(NULL, inode, iblock, max_blocks, bh_result, 0);
-       BUG_ON(create && ret == 0);
        if (ret > 0) {
                bh_result->b_size = (ret << inode->i_blkbits);
                ret = 0;
@@ -2525,15 +2516,102 @@ static int noalloc_get_block_write(struct inode *inode, sector_t iblock,
        return ret;
 }
 
+static int bget_one(handle_t *handle, struct buffer_head *bh)
+{
+       get_bh(bh);
+       return 0;
+}
+
+static int bput_one(handle_t *handle, struct buffer_head *bh)
+{
+       put_bh(bh);
+       return 0;
+}
+
+static int __ext4_journalled_writepage(struct page *page,
+                                      struct writeback_control *wbc,
+                                      unsigned int len)
+{
+       struct address_space *mapping = page->mapping;
+       struct inode *inode = mapping->host;
+       struct buffer_head *page_bufs;
+       handle_t *handle = NULL;
+       int ret = 0;
+       int err;
+
+       page_bufs = page_buffers(page);
+       BUG_ON(!page_bufs);
+       walk_page_buffers(handle, page_bufs, 0, len, NULL, bget_one);
+       /* As soon as we unlock the page, it can go away, but we have
+        * references to buffers so we are safe */
+       unlock_page(page);
+
+       handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode));
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               goto out;
+       }
+
+       ret = walk_page_buffers(handle, page_bufs, 0, len, NULL,
+                               do_journal_get_write_access);
+
+       err = walk_page_buffers(handle, page_bufs, 0, len, NULL,
+                               write_end_fn);
+       if (ret == 0)
+               ret = err;
+       err = ext4_journal_stop(handle);
+       if (!ret)
+               ret = err;
+
+       walk_page_buffers(handle, page_bufs, 0, len, NULL, bput_one);
+       EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
+out:
+       return ret;
+}
+
 /*
+ * Note that we don't need to start a transaction unless we're journaling data
+ * because we should have holes filled from ext4_page_mkwrite(). We even don't
+ * need to file the inode to the transaction's list in ordered mode because if
+ * we are writing back data added by write(), the inode is already there and if
+ * we are writing back data modified via mmap(), noone guarantees in which
+ * transaction the data will hit the disk. In case we are journaling data, we
+ * cannot start transaction directly because transaction start ranks above page
+ * lock so we have to do some magic.
+ *
  * This function can get called via...
  *   - ext4_da_writepages after taking page lock (have journal handle)
  *   - journal_submit_inode_data_buffers (no journal handle)
  *   - shrink_page_list via pdflush (no journal handle)
  *   - grab_page_cache when doing write_begin (have journal handle)
+ *
+ * We don't do any block allocation in this function. If we have page with
+ * multiple blocks we need to write those buffer_heads that are mapped. This
+ * is important for mmaped based write. So if we do with blocksize 1K
+ * truncate(f, 1024);
+ * a = mmap(f, 0, 4096);
+ * a[0] = 'a';
+ * truncate(f, 4096);
+ * we have in the page first buffer_head mapped via page_mkwrite call back
+ * but other bufer_heads would be unmapped but dirty(dirty done via the
+ * do_wp_page). So writepage should write the first block. If we modify
+ * the mmap area beyond 1024 we will again get a page_fault and the
+ * page_mkwrite callback will do the block allocation and mark the
+ * buffer_heads mapped.
+ *
+ * We redirty the page if we have any buffer_heads that is either delay or
+ * unwritten in the page.
+ *
+ * We can get recursively called as show below.
+ *
+ *     ext4_writepage() -> kmalloc() -> __alloc_pages() -> page_launder() ->
+ *             ext4_writepage()
+ *
+ * But since we don't do any block allocation we should not deadlock.
+ * Page also have the dirty flag cleared so we don't get recurive page_lock.
  */
-static int ext4_da_writepage(struct page *page,
-                               struct writeback_control *wbc)
+static int ext4_writepage(struct page *page,
+                         struct writeback_control *wbc)
 {
        int ret = 0;
        loff_t size;
@@ -2541,7 +2619,7 @@ static int ext4_da_writepage(struct page *page,
        struct buffer_head *page_bufs;
        struct inode *inode = page->mapping->host;
 
-       trace_ext4_da_writepage(inode, page);
+       trace_ext4_writepage(inode, page);
        size = i_size_read(inode);
        if (page->index == size >> PAGE_CACHE_SHIFT)
                len = size & ~PAGE_CACHE_MASK;
@@ -2551,7 +2629,7 @@ static int ext4_da_writepage(struct page *page,
        if (page_has_buffers(page)) {
                page_bufs = page_buffers(page);
                if (walk_page_buffers(NULL, page_bufs, 0, len, NULL,
-                                       ext4_bh_unmapped_or_delay)) {
+                                       ext4_bh_delay_or_unwritten)) {
                        /*
                         * We don't want to do  block allocation
                         * So redirty the page and return
@@ -2578,13 +2656,13 @@ static int ext4_da_writepage(struct page *page,
                 * all are mapped and non delay. We don't want to
                 * do block allocation here.
                 */
-               ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE,
+               ret = block_prepare_write(page, 0, len,
                                          noalloc_get_block_write);
                if (!ret) {
                        page_bufs = page_buffers(page);
                        /* check whether all are mapped and non delay */
                        if (walk_page_buffers(NULL, page_bufs, 0, len, NULL,
-                                               ext4_bh_unmapped_or_delay)) {
+                                               ext4_bh_delay_or_unwritten)) {
                                redirty_page_for_writepage(wbc, page);
                                unlock_page(page);
                                return 0;
@@ -2600,7 +2678,16 @@ static int ext4_da_writepage(struct page *page,
                        return 0;
                }
                /* now mark the buffer_heads as dirty and uptodate */
-               block_commit_write(page, 0, PAGE_CACHE_SIZE);
+               block_commit_write(page, 0, len);
+       }
+
+       if (PageChecked(page) && ext4_should_journal_data(inode)) {
+               /*
+                * It's mmapped pagecache.  Add buffers and journal it.  There
+                * doesn't seem much point in redirtying the page here.
+                */
+               ClearPageChecked(page);
+               return __ext4_journalled_writepage(page, wbc, len);
        }
 
        if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
@@ -2907,7 +2994,7 @@ retry:
                 * i_size_read because we hold i_mutex.
                 */
                if (pos + len > inode->i_size)
-                       vmtruncate(inode, inode->i_size);
+                       ext4_truncate(inode);
        }
 
        if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
@@ -3130,222 +3217,6 @@ static sector_t ext4_bmap(struct address_space *mapping, sector_t block)
        return generic_block_bmap(mapping, block, ext4_get_block);
 }
 
-static int bget_one(handle_t *handle, struct buffer_head *bh)
-{
-       get_bh(bh);
-       return 0;
-}
-
-static int bput_one(handle_t *handle, struct buffer_head *bh)
-{
-       put_bh(bh);
-       return 0;
-}
-
-/*
- * Note that we don't need to start a transaction unless we're journaling data
- * because we should have holes filled from ext4_page_mkwrite(). We even don't
- * need to file the inode to the transaction's list in ordered mode because if
- * we are writing back data added by write(), the inode is already there and if
- * we are writing back data modified via mmap(), noone guarantees in which
- * transaction the data will hit the disk. In case we are journaling data, we
- * cannot start transaction directly because transaction start ranks above page
- * lock so we have to do some magic.
- *
- * In all journaling modes block_write_full_page() will start the I/O.
- *
- * Problem:
- *
- *     ext4_writepage() -> kmalloc() -> __alloc_pages() -> page_launder() ->
- *             ext4_writepage()
- *
- * Similar for:
- *
- *     ext4_file_write() -> generic_file_write() -> __alloc_pages() -> ...
- *
- * Same applies to ext4_get_block().  We will deadlock on various things like
- * lock_journal and i_data_sem
- *
- * Setting PF_MEMALLOC here doesn't work - too many internal memory
- * allocations fail.
- *
- * 16May01: If we're reentered then journal_current_handle() will be
- *         non-zero. We simply *return*.
- *
- * 1 July 2001: @@@ FIXME:
- *   In journalled data mode, a data buffer may be metadata against the
- *   current transaction.  But the same file is part of a shared mapping
- *   and someone does a writepage() on it.
- *
- *   We will move the buffer onto the async_data list, but *after* it has
- *   been dirtied. So there's a small window where we have dirty data on
- *   BJ_Metadata.
- *
- *   Note that this only applies to the last partial page in the file.  The
- *   bit which block_write_full_page() uses prepare/commit for.  (That's
- *   broken code anyway: it's wrong for msync()).
- *
- *   It's a rare case: affects the final partial page, for journalled data
- *   where the file is subject to bith write() and writepage() in the same
- *   transction.  To fix it we'll need a custom block_write_full_page().
- *   We'll probably need that anyway for journalling writepage() output.
- *
- * We don't honour synchronous mounts for writepage().  That would be
- * disastrous.  Any write() or metadata operation will sync the fs for
- * us.
- *
- */
-static int __ext4_normal_writepage(struct page *page,
-                                  struct writeback_control *wbc)
-{
-       struct inode *inode = page->mapping->host;
-
-       if (test_opt(inode->i_sb, NOBH))
-               return nobh_writepage(page, noalloc_get_block_write, wbc);
-       else
-               return block_write_full_page(page, noalloc_get_block_write,
-                                            wbc);
-}
-
-static int ext4_normal_writepage(struct page *page,
-                                struct writeback_control *wbc)
-{
-       struct inode *inode = page->mapping->host;
-       loff_t size = i_size_read(inode);
-       loff_t len;
-
-       trace_ext4_normal_writepage(inode, page);
-       J_ASSERT(PageLocked(page));
-       if (page->index == size >> PAGE_CACHE_SHIFT)
-               len = size & ~PAGE_CACHE_MASK;
-       else
-               len = PAGE_CACHE_SIZE;
-
-       if (page_has_buffers(page)) {
-               /* if page has buffers it should all be mapped
-                * and allocated. If there are not buffers attached
-                * to the page we know the page is dirty but it lost
-                * buffers. That means that at some moment in time
-                * after write_begin() / write_end() has been called
-                * all buffers have been clean and thus they must have been
-                * written at least once. So they are all mapped and we can
-                * happily proceed with mapping them and writing the page.
-                */
-               BUG_ON(walk_page_buffers(NULL, page_buffers(page), 0, len, NULL,
-                                       ext4_bh_unmapped_or_delay));
-       }
-
-       if (!ext4_journal_current_handle())
-               return __ext4_normal_writepage(page, wbc);
-
-       redirty_page_for_writepage(wbc, page);
-       unlock_page(page);
-       return 0;
-}
-
-static int __ext4_journalled_writepage(struct page *page,
-                                      struct writeback_control *wbc)
-{
-       struct address_space *mapping = page->mapping;
-       struct inode *inode = mapping->host;
-       struct buffer_head *page_bufs;
-       handle_t *handle = NULL;
-       int ret = 0;
-       int err;
-
-       ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE,
-                                 noalloc_get_block_write);
-       if (ret != 0)
-               goto out_unlock;
-
-       page_bufs = page_buffers(page);
-       walk_page_buffers(handle, page_bufs, 0, PAGE_CACHE_SIZE, NULL,
-                                                               bget_one);
-       /* As soon as we unlock the page, it can go away, but we have
-        * references to buffers so we are safe */
-       unlock_page(page);
-
-       handle = ext4_journal_start(inode, ext4_writepage_trans_blocks(inode));
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               goto out;
-       }
-
-       ret = walk_page_buffers(handle, page_bufs, 0,
-                       PAGE_CACHE_SIZE, NULL, do_journal_get_write_access);
-
-       err = walk_page_buffers(handle, page_bufs, 0,
-                               PAGE_CACHE_SIZE, NULL, write_end_fn);
-       if (ret == 0)
-               ret = err;
-       err = ext4_journal_stop(handle);
-       if (!ret)
-               ret = err;
-
-       walk_page_buffers(handle, page_bufs, 0,
-                               PAGE_CACHE_SIZE, NULL, bput_one);
-       EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
-       goto out;
-
-out_unlock:
-       unlock_page(page);
-out:
-       return ret;
-}
-
-static int ext4_journalled_writepage(struct page *page,
-                                    struct writeback_control *wbc)
-{
-       struct inode *inode = page->mapping->host;
-       loff_t size = i_size_read(inode);
-       loff_t len;
-
-       trace_ext4_journalled_writepage(inode, page);
-       J_ASSERT(PageLocked(page));
-       if (page->index == size >> PAGE_CACHE_SHIFT)
-               len = size & ~PAGE_CACHE_MASK;
-       else
-               len = PAGE_CACHE_SIZE;
-
-       if (page_has_buffers(page)) {
-               /* if page has buffers it should all be mapped
-                * and allocated. If there are not buffers attached
-                * to the page we know the page is dirty but it lost
-                * buffers. That means that at some moment in time
-                * after write_begin() / write_end() has been called
-                * all buffers have been clean and thus they must have been
-                * written at least once. So they are all mapped and we can
-                * happily proceed with mapping them and writing the page.
-                */
-               BUG_ON(walk_page_buffers(NULL, page_buffers(page), 0, len, NULL,
-                                       ext4_bh_unmapped_or_delay));
-       }
-
-       if (ext4_journal_current_handle())
-               goto no_write;
-
-       if (PageChecked(page)) {
-               /*
-                * It's mmapped pagecache.  Add buffers and journal it.  There
-                * doesn't seem much point in redirtying the page here.
-                */
-               ClearPageChecked(page);
-               return __ext4_journalled_writepage(page, wbc);
-       } else {
-               /*
-                * It may be a page full of checkpoint-mode buffers.  We don't
-                * really know unless we go poke around in the buffer_heads.
-                * But block_write_full_page will do the right thing.
-                */
-               return block_write_full_page(page, noalloc_get_block_write,
-                                            wbc);
-       }
-no_write:
-       redirty_page_for_writepage(wbc, page);
-       unlock_page(page);
-       return 0;
-}
-
 static int ext4_readpage(struct file *file, struct page *page)
 {
        return mpage_readpage(page, ext4_get_block);
@@ -3492,7 +3363,7 @@ static int ext4_journalled_set_page_dirty(struct page *page)
 static const struct address_space_operations ext4_ordered_aops = {
        .readpage               = ext4_readpage,
        .readpages              = ext4_readpages,
-       .writepage              = ext4_normal_writepage,
+       .writepage              = ext4_writepage,
        .sync_page              = block_sync_page,
        .write_begin            = ext4_write_begin,
        .write_end              = ext4_ordered_write_end,
@@ -3507,7 +3378,7 @@ static const struct address_space_operations ext4_ordered_aops = {
 static const struct address_space_operations ext4_writeback_aops = {
        .readpage               = ext4_readpage,
        .readpages              = ext4_readpages,
-       .writepage              = ext4_normal_writepage,
+       .writepage              = ext4_writepage,
        .sync_page              = block_sync_page,
        .write_begin            = ext4_write_begin,
        .write_end              = ext4_writeback_write_end,
@@ -3522,7 +3393,7 @@ static const struct address_space_operations ext4_writeback_aops = {
 static const struct address_space_operations ext4_journalled_aops = {
        .readpage               = ext4_readpage,
        .readpages              = ext4_readpages,
-       .writepage              = ext4_journalled_writepage,
+       .writepage              = ext4_writepage,
        .sync_page              = block_sync_page,
        .write_begin            = ext4_write_begin,
        .write_end              = ext4_journalled_write_end,
@@ -3536,7 +3407,7 @@ static const struct address_space_operations ext4_journalled_aops = {
 static const struct address_space_operations ext4_da_aops = {
        .readpage               = ext4_readpage,
        .readpages              = ext4_readpages,
-       .writepage              = ext4_da_writepage,
+       .writepage              = ext4_writepage,
        .writepages             = ext4_da_writepages,
        .sync_page              = block_sync_page,
        .write_begin            = ext4_da_write_begin,
@@ -3583,7 +3454,8 @@ int ext4_block_truncate_page(handle_t *handle,
        struct page *page;
        int err = 0;
 
-       page = grab_cache_page(mapping, from >> PAGE_CACHE_SHIFT);
+       page = find_or_create_page(mapping, from >> PAGE_CACHE_SHIFT,
+                                  mapping_gfp_mask(mapping) & ~__GFP_FS);
        if (!page)
                return -EINVAL;
 
index bb415408fdb60cc18243b70c4eec8ea9d82a67ed..7050a9cd04a4361bb66851781b9e494893f257ee 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/capability.h>
 #include <linux/time.h>
 #include <linux/compat.h>
-#include <linux/smp_lock.h>
 #include <linux/mount.h>
 #include <linux/file.h>
 #include <asm/uaccess.h>
@@ -192,7 +191,7 @@ setversion_out:
        case EXT4_IOC_GROUP_EXTEND: {
                ext4_fsblk_t n_blocks_count;
                struct super_block *sb = inode->i_sb;
-               int err, err2;
+               int err, err2=0;
 
                if (!capable(CAP_SYS_RESOURCE))
                        return -EPERM;
@@ -205,9 +204,11 @@ setversion_out:
                        return err;
 
                err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count);
-               jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
-               err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
-               jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
+               if (EXT4_SB(sb)->s_journal) {
+                       jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
+                       err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
+                       jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
+               }
                if (err == 0)
                        err = err2;
                mnt_drop_write(filp->f_path.mnt);
@@ -252,7 +253,7 @@ setversion_out:
        case EXT4_IOC_GROUP_ADD: {
                struct ext4_new_group_data input;
                struct super_block *sb = inode->i_sb;
-               int err, err2;
+               int err, err2=0;
 
                if (!capable(CAP_SYS_RESOURCE))
                        return -EPERM;
@@ -266,9 +267,11 @@ setversion_out:
                        return err;
 
                err = ext4_group_add(sb, &input);
-               jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
-               err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
-               jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
+               if (EXT4_SB(sb)->s_journal) {
+                       jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
+                       err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
+                       jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
+               }
                if (err == 0)
                        err = err2;
                mnt_drop_write(filp->f_path.mnt);
index 519a0a686d946343ca646702aa5c4603c9a75308..cd258463e2a9e017f949367b403d87332e5a3d24 100644 (file)
@@ -657,7 +657,8 @@ static void ext4_mb_mark_free_simple(struct super_block *sb,
        }
 }
 
-static void ext4_mb_generate_buddy(struct super_block *sb,
+static noinline_for_stack
+void ext4_mb_generate_buddy(struct super_block *sb,
                                void *buddy, void *bitmap, ext4_group_t group)
 {
        struct ext4_group_info *grp = ext4_get_group_info(sb, group);
@@ -1480,7 +1481,8 @@ static void ext4_mb_measure_extent(struct ext4_allocation_context *ac,
        ext4_mb_check_limits(ac, e4b, 0);
 }
 
-static int ext4_mb_try_best_found(struct ext4_allocation_context *ac,
+static noinline_for_stack
+int ext4_mb_try_best_found(struct ext4_allocation_context *ac,
                                        struct ext4_buddy *e4b)
 {
        struct ext4_free_extent ex = ac->ac_b_ex;
@@ -1507,7 +1509,8 @@ static int ext4_mb_try_best_found(struct ext4_allocation_context *ac,
        return 0;
 }
 
-static int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
+static noinline_for_stack
+int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
                                struct ext4_buddy *e4b)
 {
        ext4_group_t group = ac->ac_g_ex.fe_group;
@@ -1566,7 +1569,8 @@ static int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
  * The routine scans buddy structures (not bitmap!) from given order
  * to max order and tries to find big enough chunk to satisfy the req
  */
-static void ext4_mb_simple_scan_group(struct ext4_allocation_context *ac,
+static noinline_for_stack
+void ext4_mb_simple_scan_group(struct ext4_allocation_context *ac,
                                        struct ext4_buddy *e4b)
 {
        struct super_block *sb = ac->ac_sb;
@@ -1609,7 +1613,8 @@ static void ext4_mb_simple_scan_group(struct ext4_allocation_context *ac,
  * In order to optimize scanning, caller must pass number of
  * free blocks in the group, so the routine can know upper limit.
  */
-static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
+static noinline_for_stack
+void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
                                        struct ext4_buddy *e4b)
 {
        struct super_block *sb = ac->ac_sb;
@@ -1668,7 +1673,8 @@ static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
  * we try to find stripe-aligned chunks for stripe-size requests
  * XXX should do so at least for multiples of stripe size as well
  */
-static void ext4_mb_scan_aligned(struct ext4_allocation_context *ac,
+static noinline_for_stack
+void ext4_mb_scan_aligned(struct ext4_allocation_context *ac,
                                 struct ext4_buddy *e4b)
 {
        struct super_block *sb = ac->ac_sb;
@@ -1831,7 +1837,8 @@ void ext4_mb_put_buddy_cache_lock(struct super_block *sb,
 
 }
 
-static int ext4_mb_init_group(struct super_block *sb, ext4_group_t group)
+static noinline_for_stack
+int ext4_mb_init_group(struct super_block *sb, ext4_group_t group)
 {
 
        int ret;
@@ -2902,7 +2909,11 @@ int __init init_ext4_mballoc(void)
 
 void exit_ext4_mballoc(void)
 {
-       /* XXX: synchronize_rcu(); */
+       /* 
+        * Wait for completion of call_rcu()'s on ext4_pspace_cachep
+        * before destroying the slab cache.
+        */
+       rcu_barrier();
        kmem_cache_destroy(ext4_pspace_cachep);
        kmem_cache_destroy(ext4_ac_cachep);
        kmem_cache_destroy(ext4_free_ext_cachep);
@@ -3457,7 +3468,8 @@ static void ext4_mb_generate_from_freelist(struct super_block *sb, void *bitmap,
  * used in in-core bitmap. buddy must be generated from this bitmap
  * Need to be called with ext4 group lock held
  */
-static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
+static noinline_for_stack
+void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap,
                                        ext4_group_t group)
 {
        struct ext4_group_info *grp = ext4_get_group_info(sb, group);
@@ -4215,14 +4227,9 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
        ext4_get_group_no_and_offset(sb, goal, &group, &block);
 
        /* set up allocation goals */
+       memset(ac, 0, sizeof(struct ext4_allocation_context));
        ac->ac_b_ex.fe_logical = ar->logical;
-       ac->ac_b_ex.fe_group = 0;
-       ac->ac_b_ex.fe_start = 0;
-       ac->ac_b_ex.fe_len = 0;
        ac->ac_status = AC_STATUS_CONTINUE;
-       ac->ac_groups_scanned = 0;
-       ac->ac_ex_scanned = 0;
-       ac->ac_found = 0;
        ac->ac_sb = sb;
        ac->ac_inode = ar->inode;
        ac->ac_o_ex.fe_logical = ar->logical;
@@ -4233,15 +4240,7 @@ ext4_mb_initialize_context(struct ext4_allocation_context *ac,
        ac->ac_g_ex.fe_group = group;
        ac->ac_g_ex.fe_start = block;
        ac->ac_g_ex.fe_len = len;
-       ac->ac_f_ex.fe_len = 0;
        ac->ac_flags = ar->flags;
-       ac->ac_2order = 0;
-       ac->ac_criteria = 0;
-       ac->ac_pa = NULL;
-       ac->ac_bitmap_page = NULL;
-       ac->ac_buddy_page = NULL;
-       ac->alloc_semp = NULL;
-       ac->ac_lg = NULL;
 
        /* we have to define context: we'll we work with a file or
         * locality group. this is a policy, actually */
@@ -4509,10 +4508,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
        }
 
        ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS);
-       if (ac) {
-               ac->ac_sb = sb;
-               ac->ac_inode = ar->inode;
-       } else {
+       if (!ac) {
                ar->len = 0;
                *errp = -ENOMEM;
                goto out1;
index 38ff75a0fe22d3b8764e9be001dd57857c5abe66..530b4ca0151037ae212fe9d2d8ffb827fc970f98 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/time.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/compat.h>
 #include <asm/uaccess.h>
index b28ea646ff607cfdbe0f1ebda29158b5feadef88..f042b965c95c8a9c6c0dbb21020877372b1a9c21 100644 (file)
@@ -134,7 +134,7 @@ static int fat_file_release(struct inode *inode, struct file *filp)
        if ((filp->f_mode & FMODE_WRITE) &&
             MSDOS_SB(inode->i_sb)->options.flush) {
                fat_flush_inodes(inode->i_sb, inode, NULL);
-               congestion_wait(WRITE, HZ/10);
+               congestion_wait(BLK_RW_ASYNC, HZ/10);
        }
        return 0;
 }
index 82f88733b681accfa68bdeb86bed85734b9fcc6e..bbc94ae4fd77150203435058b79e46a03bfb40bc 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/module.h>
 #include <linux/time.h>
 #include <linux/buffer_head.h>
-#include <linux/smp_lock.h>
 #include "fat.h"
 
 /* Characters that are undesirable in an MS-DOS file name */
index 73471b7ecc8c2bd90591f43391afaaeacf6c39af..cb6e83557112d74e03cf00f37d6b3bddfa66cd83 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/jiffies.h>
 #include <linux/ctype.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/namei.h>
 #include "fat.h"
index a040b764f8e38b6a5067642713d4f9c6e9dc92ba..ae413086db978093123b2a59947d78e23a02a693 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/signal.h>
 #include <linux/rcupdate.h>
 #include <linux/pid_namespace.h>
-#include <linux/smp_lock.h>
 
 #include <asm/poll.h>
 #include <asm/siginfo.h>
index cdbd1654e4cde4b6dd6b62e7bb6f2bd4a128a42c..1e8af939b3e4ad58d41726db3851269193a2e0c9 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/buffer_head.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/stat.h>
 #include <linux/vfs.h>
 #include <linux/mount.h>
index 8fed2ed12f38b3ab468a042964ae800479f18d18..6484eb75acd6f318c04238a51763b7cf2c9599ea 100644 (file)
@@ -286,8 +286,8 @@ __releases(&fc->lock)
                }
                if (fc->num_background == FUSE_CONGESTION_THRESHOLD &&
                    fc->connected && fc->bdi_initialized) {
-                       clear_bdi_congested(&fc->bdi, READ);
-                       clear_bdi_congested(&fc->bdi, WRITE);
+                       clear_bdi_congested(&fc->bdi, BLK_RW_SYNC);
+                       clear_bdi_congested(&fc->bdi, BLK_RW_ASYNC);
                }
                fc->num_background--;
                fc->active_background--;
@@ -414,8 +414,8 @@ static void fuse_request_send_nowait_locked(struct fuse_conn *fc,
                fc->blocked = 1;
        if (fc->num_background == FUSE_CONGESTION_THRESHOLD &&
            fc->bdi_initialized) {
-               set_bdi_congested(&fc->bdi, READ);
-               set_bdi_congested(&fc->bdi, WRITE);
+               set_bdi_congested(&fc->bdi, BLK_RW_SYNC);
+               set_bdi_congested(&fc->bdi, BLK_RW_ASYNC);
        }
        list_add_tail(&req->list, &fc->bg_queue);
        flush_bg_queue(fc);
@@ -849,6 +849,81 @@ err:
        return err;
 }
 
+static int fuse_notify_inval_inode(struct fuse_conn *fc, unsigned int size,
+                                  struct fuse_copy_state *cs)
+{
+       struct fuse_notify_inval_inode_out outarg;
+       int err = -EINVAL;
+
+       if (size != sizeof(outarg))
+               goto err;
+
+       err = fuse_copy_one(cs, &outarg, sizeof(outarg));
+       if (err)
+               goto err;
+       fuse_copy_finish(cs);
+
+       down_read(&fc->killsb);
+       err = -ENOENT;
+       if (!fc->sb)
+               goto err_unlock;
+
+       err = fuse_reverse_inval_inode(fc->sb, outarg.ino,
+                                      outarg.off, outarg.len);
+
+err_unlock:
+       up_read(&fc->killsb);
+       return err;
+
+err:
+       fuse_copy_finish(cs);
+       return err;
+}
+
+static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size,
+                                  struct fuse_copy_state *cs)
+{
+       struct fuse_notify_inval_entry_out outarg;
+       int err = -EINVAL;
+       char buf[FUSE_NAME_MAX+1];
+       struct qstr name;
+
+       if (size < sizeof(outarg))
+               goto err;
+
+       err = fuse_copy_one(cs, &outarg, sizeof(outarg));
+       if (err)
+               goto err;
+
+       err = -ENAMETOOLONG;
+       if (outarg.namelen > FUSE_NAME_MAX)
+               goto err;
+
+       name.name = buf;
+       name.len = outarg.namelen;
+       err = fuse_copy_one(cs, buf, outarg.namelen + 1);
+       if (err)
+               goto err;
+       fuse_copy_finish(cs);
+       buf[outarg.namelen] = 0;
+       name.hash = full_name_hash(name.name, name.len);
+
+       down_read(&fc->killsb);
+       err = -ENOENT;
+       if (!fc->sb)
+               goto err_unlock;
+
+       err = fuse_reverse_inval_entry(fc->sb, outarg.parent, &name);
+
+err_unlock:
+       up_read(&fc->killsb);
+       return err;
+
+err:
+       fuse_copy_finish(cs);
+       return err;
+}
+
 static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
                       unsigned int size, struct fuse_copy_state *cs)
 {
@@ -856,6 +931,12 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
        case FUSE_NOTIFY_POLL:
                return fuse_notify_poll(fc, size, cs);
 
+       case FUSE_NOTIFY_INVAL_INODE:
+               return fuse_notify_inval_inode(fc, size, cs);
+
+       case FUSE_NOTIFY_INVAL_ENTRY:
+               return fuse_notify_inval_entry(fc, size, cs);
+
        default:
                fuse_copy_finish(cs);
                return -EINVAL;
@@ -910,7 +991,7 @@ static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov,
                               unsigned long nr_segs, loff_t pos)
 {
        int err;
-       unsigned nbytes = iov_length(iov, nr_segs);
+       size_t nbytes = iov_length(iov, nr_segs);
        struct fuse_req *req;
        struct fuse_out_header oh;
        struct fuse_copy_state cs;
index b3089a083d30c36a2afa17c03ca1345cc6d38206..e703654e7f40d901975d3a0953ce353a755248d7 100644 (file)
@@ -375,7 +375,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
        struct fuse_conn *fc = get_fuse_conn(dir);
        struct fuse_req *req;
        struct fuse_req *forget_req;
-       struct fuse_open_in inarg;
+       struct fuse_create_in inarg;
        struct fuse_open_out outopen;
        struct fuse_entry_out outentry;
        struct fuse_file *ff;
@@ -399,15 +399,20 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
        if (!ff)
                goto out_put_request;
 
+       if (!fc->dont_mask)
+               mode &= ~current_umask();
+
        flags &= ~O_NOCTTY;
        memset(&inarg, 0, sizeof(inarg));
        memset(&outentry, 0, sizeof(outentry));
        inarg.flags = flags;
        inarg.mode = mode;
+       inarg.umask = current_umask();
        req->in.h.opcode = FUSE_CREATE;
        req->in.h.nodeid = get_node_id(dir);
        req->in.numargs = 2;
-       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) :
+                                               sizeof(inarg);
        req->in.args[0].value = &inarg;
        req->in.args[1].size = entry->d_name.len + 1;
        req->in.args[1].value = entry->d_name.name;
@@ -546,12 +551,17 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
        if (IS_ERR(req))
                return PTR_ERR(req);
 
+       if (!fc->dont_mask)
+               mode &= ~current_umask();
+
        memset(&inarg, 0, sizeof(inarg));
        inarg.mode = mode;
        inarg.rdev = new_encode_dev(rdev);
+       inarg.umask = current_umask();
        req->in.h.opcode = FUSE_MKNOD;
        req->in.numargs = 2;
-       req->in.args[0].size = sizeof(inarg);
+       req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE :
+                                               sizeof(inarg);
        req->in.args[0].value = &inarg;
        req->in.args[1].size = entry->d_name.len + 1;
        req->in.args[1].value = entry->d_name.name;
@@ -578,8 +588,12 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
        if (IS_ERR(req))
                return PTR_ERR(req);
 
+       if (!fc->dont_mask)
+               mode &= ~current_umask();
+
        memset(&inarg, 0, sizeof(inarg));
        inarg.mode = mode;
+       inarg.umask = current_umask();
        req->in.h.opcode = FUSE_MKDIR;
        req->in.numargs = 2;
        req->in.args[0].size = sizeof(inarg);
@@ -845,6 +859,43 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat,
        return err;
 }
 
+int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
+                            struct qstr *name)
+{
+       int err = -ENOTDIR;
+       struct inode *parent;
+       struct dentry *dir;
+       struct dentry *entry;
+
+       parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid);
+       if (!parent)
+               return -ENOENT;
+
+       mutex_lock(&parent->i_mutex);
+       if (!S_ISDIR(parent->i_mode))
+               goto unlock;
+
+       err = -ENOENT;
+       dir = d_find_alias(parent);
+       if (!dir)
+               goto unlock;
+
+       entry = d_lookup(dir, name);
+       dput(dir);
+       if (!entry)
+               goto unlock;
+
+       fuse_invalidate_attr(parent);
+       fuse_invalidate_entry(entry);
+       dput(entry);
+       err = 0;
+
+ unlock:
+       mutex_unlock(&parent->i_mutex);
+       iput(parent);
+       return err;
+}
+
 /*
  * Calling into a user-controlled filesystem gives the filesystem
  * daemon ptrace-like capabilities over the requester process.  This
index fce6ce694fdee3c4d6764c1dff661de755de675d..cbc464043b6f02f1383be3153e24b73b2e8f4875 100644 (file)
@@ -1922,7 +1922,7 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait)
 
        req = fuse_get_req(fc);
        if (IS_ERR(req))
-               return PTR_ERR(req);
+               return POLLERR;
 
        req->in.h.opcode = FUSE_POLL;
        req->in.h.nodeid = ff->nodeid;
index aaf2f9ff970ec4b824b6bf792264db9dd579f58c..52b641fc0faf1f8d1a938c10cf6460f203f28205 100644 (file)
@@ -446,6 +446,9 @@ struct fuse_conn {
        /** Do multi-page cached writes */
        unsigned big_writes:1;
 
+       /** Don't apply umask to creation modes */
+       unsigned dont_mask:1;
+
        /** The number of requests waiting for completion */
        atomic_t num_waiting;
 
@@ -481,6 +484,12 @@ struct fuse_conn {
 
        /** Called on final put */
        void (*release)(struct fuse_conn *);
+
+       /** Super block for this connection. */
+       struct super_block *sb;
+
+       /** Read/write semaphore to hold when accessing sb. */
+       struct rw_semaphore killsb;
 };
 
 static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
@@ -508,6 +517,11 @@ extern const struct file_operations fuse_dev_operations;
 
 extern const struct dentry_operations fuse_dentry_operations;
 
+/**
+ * Inode to nodeid comparison.
+ */
+int fuse_inode_eq(struct inode *inode, void *_nodeidp);
+
 /**
  * Get a filled in inode
  */
@@ -708,6 +722,19 @@ void fuse_release_nowrite(struct inode *inode);
 
 u64 fuse_get_attr_version(struct fuse_conn *fc);
 
+/**
+ * File-system tells the kernel to invalidate cache for the given node id.
+ */
+int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid,
+                            loff_t offset, loff_t len);
+
+/**
+ * File-system tells the kernel to invalidate parent attributes and
+ * the dentry matching parent/name.
+ */
+int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid,
+                            struct qstr *name);
+
 int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
                 bool isdir);
 ssize_t fuse_direct_io(struct file *file, const char __user *buf,
index d8673ccf90b75033c0d4f0a37ed5a775accf0025..f91ccc4a189de18b52450f8d847b4983ac5e4311 100644 (file)
@@ -206,7 +206,7 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
                BUG();
 }
 
-static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
+int fuse_inode_eq(struct inode *inode, void *_nodeidp)
 {
        u64 nodeid = *(u64 *) _nodeidp;
        if (get_node_id(inode) == nodeid)
@@ -257,6 +257,31 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
        return inode;
 }
 
+int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid,
+                            loff_t offset, loff_t len)
+{
+       struct inode *inode;
+       pgoff_t pg_start;
+       pgoff_t pg_end;
+
+       inode = ilookup5(sb, nodeid, fuse_inode_eq, &nodeid);
+       if (!inode)
+               return -ENOENT;
+
+       fuse_invalidate_attr(inode);
+       if (offset >= 0) {
+               pg_start = offset >> PAGE_CACHE_SHIFT;
+               if (len <= 0)
+                       pg_end = -1;
+               else
+                       pg_end = (offset + len - 1) >> PAGE_CACHE_SHIFT;
+               invalidate_inode_pages2_range(inode->i_mapping,
+                                             pg_start, pg_end);
+       }
+       iput(inode);
+       return 0;
+}
+
 static void fuse_umount_begin(struct super_block *sb)
 {
        fuse_abort_conn(get_fuse_conn_super(sb));
@@ -480,6 +505,7 @@ void fuse_conn_init(struct fuse_conn *fc)
        memset(fc, 0, sizeof(*fc));
        spin_lock_init(&fc->lock);
        mutex_init(&fc->inst_mutex);
+       init_rwsem(&fc->killsb);
        atomic_set(&fc->count, 1);
        init_waitqueue_head(&fc->waitq);
        init_waitqueue_head(&fc->blocked_waitq);
@@ -725,6 +751,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
                        }
                        if (arg->flags & FUSE_BIG_WRITES)
                                fc->big_writes = 1;
+                       if (arg->flags & FUSE_DONT_MASK)
+                               fc->dont_mask = 1;
                } else {
                        ra_pages = fc->max_read / PAGE_CACHE_SIZE;
                        fc->no_lock = 1;
@@ -748,7 +776,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
        arg->minor = FUSE_KERNEL_MINOR_VERSION;
        arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
        arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
-               FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES;
+               FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK;
        req->in.h.opcode = FUSE_INIT;
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(*arg);
@@ -860,10 +888,16 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        fuse_conn_init(fc);
 
        fc->dev = sb->s_dev;
+       fc->sb = sb;
        err = fuse_bdi_init(fc, sb);
        if (err)
                goto err_put_conn;
 
+       /* Handle umasking inside the fuse code */
+       if (sb->s_flags & MS_POSIXACL)
+               fc->dont_mask = 1;
+       sb->s_flags |= MS_POSIXACL;
+
        fc->release = fuse_free_conn;
        fc->flags = d.flags;
        fc->user_id = d.user_id;
@@ -941,12 +975,25 @@ static int fuse_get_sb(struct file_system_type *fs_type,
        return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super, mnt);
 }
 
+static void fuse_kill_sb_anon(struct super_block *sb)
+{
+       struct fuse_conn *fc = get_fuse_conn_super(sb);
+
+       if (fc) {
+               down_write(&fc->killsb);
+               fc->sb = NULL;
+               up_write(&fc->killsb);
+       }
+
+       kill_anon_super(sb);
+}
+
 static struct file_system_type fuse_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "fuse",
        .fs_flags       = FS_HAS_SUBTYPE,
        .get_sb         = fuse_get_sb,
-       .kill_sb        = kill_anon_super,
+       .kill_sb        = fuse_kill_sb_anon,
 };
 
 #ifdef CONFIG_BLOCK
@@ -958,11 +1005,24 @@ static int fuse_get_sb_blk(struct file_system_type *fs_type,
                           mnt);
 }
 
+static void fuse_kill_sb_blk(struct super_block *sb)
+{
+       struct fuse_conn *fc = get_fuse_conn_super(sb);
+
+       if (fc) {
+               down_write(&fc->killsb);
+               fc->sb = NULL;
+               up_write(&fc->killsb);
+       }
+
+       kill_block_super(sb);
+}
+
 static struct file_system_type fuseblk_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "fuseblk",
        .get_sb         = fuse_get_sb_blk,
-       .kill_sb        = kill_block_super,
+       .kill_sb        = fuse_kill_sb_blk,
        .fs_flags       = FS_REQUIRES_DEV | FS_HAS_SUBTYPE,
 };
 
index 03ebb439ace077847bd31b3d722cd92ee7a07fc1..7ebae9a4ecc01b50533cf0316dc936626a3350b9 100644 (file)
@@ -624,6 +624,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
 {
        struct gfs2_inode *ip = GFS2_I(mapping->host);
        struct gfs2_sbd *sdp = GFS2_SB(mapping->host);
+       struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
        unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
        int alloc_required;
        int error = 0;
@@ -637,6 +638,14 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
        error = gfs2_glock_nq(&ip->i_gh);
        if (unlikely(error))
                goto out_uninit;
+       if (&ip->i_inode == sdp->sd_rindex) {
+               error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE,
+                                          GL_NOCACHE, &m_ip->i_gh);
+               if (unlikely(error)) {
+                       gfs2_glock_dq(&ip->i_gh);
+                       goto out_uninit;
+               }
+       }
 
        error = gfs2_write_alloc_required(ip, pos, len, &alloc_required);
        if (error)
@@ -667,6 +676,8 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
                rblocks += data_blocks ? data_blocks : 1;
        if (ind_blocks || data_blocks)
                rblocks += RES_STATFS + RES_QUOTA;
+       if (&ip->i_inode == sdp->sd_rindex)
+               rblocks += 2 * RES_STATFS;
 
        error = gfs2_trans_begin(sdp, rblocks,
                                 PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize);
@@ -712,6 +723,10 @@ out_alloc_put:
                gfs2_alloc_put(ip);
        }
 out_unlock:
+       if (&ip->i_inode == sdp->sd_rindex) {
+               gfs2_glock_dq(&m_ip->i_gh);
+               gfs2_holder_uninit(&m_ip->i_gh);
+       }
        gfs2_glock_dq(&ip->i_gh);
 out_uninit:
        gfs2_holder_uninit(&ip->i_gh);
@@ -725,14 +740,21 @@ out_uninit:
 static void adjust_fs_space(struct inode *inode)
 {
        struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
+       struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
+       struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
        struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
        struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
+       struct buffer_head *m_bh, *l_bh;
        u64 fs_total, new_free;
 
        /* Total up the file system space, according to the latest rindex. */
        fs_total = gfs2_ri_total(sdp);
+       if (gfs2_meta_inode_buffer(m_ip, &m_bh) != 0)
+               return;
 
        spin_lock(&sdp->sd_statfs_spin);
+       gfs2_statfs_change_in(m_sc, m_bh->b_data +
+                             sizeof(struct gfs2_dinode));
        if (fs_total > (m_sc->sc_total + l_sc->sc_total))
                new_free = fs_total - (m_sc->sc_total + l_sc->sc_total);
        else
@@ -741,6 +763,13 @@ static void adjust_fs_space(struct inode *inode)
        fs_warn(sdp, "File system extended by %llu blocks.\n",
                (unsigned long long)new_free);
        gfs2_statfs_change(sdp, new_free, new_free, 0);
+
+       if (gfs2_meta_inode_buffer(l_ip, &l_bh) != 0)
+               goto out;
+       update_statfs(sdp, m_bh, l_bh);
+       brelse(l_bh);
+out:
+       brelse(m_bh);
 }
 
 /**
@@ -763,6 +792,7 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
 {
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_sbd *sdp = GFS2_SB(inode);
+       struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
        u64 to = pos + copied;
        void *kaddr;
        unsigned char *buf = dibh->b_data + sizeof(struct gfs2_dinode);
@@ -794,6 +824,10 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,
 
        brelse(dibh);
        gfs2_trans_end(sdp);
+       if (inode == sdp->sd_rindex) {
+               gfs2_glock_dq(&m_ip->i_gh);
+               gfs2_holder_uninit(&m_ip->i_gh);
+       }
        gfs2_glock_dq(&ip->i_gh);
        gfs2_holder_uninit(&ip->i_gh);
        return copied;
@@ -823,6 +857,7 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
        struct inode *inode = page->mapping->host;
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_sbd *sdp = GFS2_SB(inode);
+       struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
        struct buffer_head *dibh;
        struct gfs2_alloc *al = ip->i_alloc;
        unsigned int from = pos & (PAGE_CACHE_SIZE - 1);
@@ -865,6 +900,10 @@ failed:
                gfs2_quota_unlock(ip);
                gfs2_alloc_put(ip);
        }
+       if (inode == sdp->sd_rindex) {
+               gfs2_glock_dq(&m_ip->i_gh);
+               gfs2_holder_uninit(&m_ip->i_gh);
+       }
        gfs2_glock_dq(&ip->i_gh);
        gfs2_holder_uninit(&ip->i_gh);
        return ret;
index 297421c0427a86ef58fa79cc2ce9518d10171381..8b674b1f3a554d4300e7965328f750c13b34bbe1 100644 (file)
@@ -63,6 +63,7 @@ static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int
 static DECLARE_RWSEM(gfs2_umount_flush_sem);
 static struct dentry *gfs2_root;
 static struct workqueue_struct *glock_workqueue;
+struct workqueue_struct *gfs2_delete_workqueue;
 static LIST_HEAD(lru_list);
 static atomic_t lru_count = ATOMIC_INIT(0);
 static DEFINE_SPINLOCK(lru_lock);
@@ -167,12 +168,32 @@ static void glock_free(struct gfs2_glock *gl)
  *
  */
 
-static void gfs2_glock_hold(struct gfs2_glock *gl)
+void gfs2_glock_hold(struct gfs2_glock *gl)
 {
        GLOCK_BUG_ON(gl, atomic_read(&gl->gl_ref) == 0);
        atomic_inc(&gl->gl_ref);
 }
 
+/**
+ * demote_ok - Check to see if it's ok to unlock a glock
+ * @gl: the glock
+ *
+ * Returns: 1 if it's ok
+ */
+
+static int demote_ok(const struct gfs2_glock *gl)
+{
+       const struct gfs2_glock_operations *glops = gl->gl_ops;
+
+       if (gl->gl_state == LM_ST_UNLOCKED)
+               return 0;
+       if (!list_empty(&gl->gl_holders))
+               return 0;
+       if (glops->go_demote_ok)
+               return glops->go_demote_ok(gl);
+       return 1;
+}
+
 /**
  * gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list
  * @gl: the glock
@@ -181,14 +202,34 @@ static void gfs2_glock_hold(struct gfs2_glock *gl)
 
 static void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl)
 {
+       int may_reclaim;
+       may_reclaim = (demote_ok(gl) &&
+                      (atomic_read(&gl->gl_ref) == 1 ||
+                       (gl->gl_name.ln_type == LM_TYPE_INODE &&
+                        atomic_read(&gl->gl_ref) <= 2)));
        spin_lock(&lru_lock);
-       if (list_empty(&gl->gl_lru) && gl->gl_state != LM_ST_UNLOCKED) {
+       if (list_empty(&gl->gl_lru) && may_reclaim) {
                list_add_tail(&gl->gl_lru, &lru_list);
                atomic_inc(&lru_count);
        }
        spin_unlock(&lru_lock);
 }
 
+/**
+ * gfs2_glock_put_nolock() - Decrement reference count on glock
+ * @gl: The glock to put
+ *
+ * This function should only be used if the caller has its own reference
+ * to the glock, in addition to the one it is dropping.
+ */
+
+void gfs2_glock_put_nolock(struct gfs2_glock *gl)
+{
+       if (atomic_dec_and_test(&gl->gl_ref))
+               GLOCK_BUG_ON(gl, 1);
+       gfs2_glock_schedule_for_reclaim(gl);
+}
+
 /**
  * gfs2_glock_put() - Decrement reference count on glock
  * @gl: The glock to put
@@ -214,9 +255,9 @@ int gfs2_glock_put(struct gfs2_glock *gl)
                rv = 1;
                goto out;
        }
-       /* 1 for being hashed, 1 for having state != LM_ST_UNLOCKED */
-       if (atomic_read(&gl->gl_ref) == 2)
-               gfs2_glock_schedule_for_reclaim(gl);
+       spin_lock(&gl->gl_spin);
+       gfs2_glock_schedule_for_reclaim(gl);
+       spin_unlock(&gl->gl_spin);
        write_unlock(gl_lock_addr(gl->gl_hash));
 out:
        return rv;
@@ -398,7 +439,7 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state)
                if (held2)
                        gfs2_glock_hold(gl);
                else
-                       gfs2_glock_put(gl);
+                       gfs2_glock_put_nolock(gl);
        }
 
        gl->gl_state = new_state;
@@ -633,12 +674,35 @@ out:
 out_sched:
        gfs2_glock_hold(gl);
        if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
-               gfs2_glock_put(gl);
+               gfs2_glock_put_nolock(gl);
 out_unlock:
        clear_bit(GLF_LOCK, &gl->gl_flags);
        goto out;
 }
 
+static void delete_work_func(struct work_struct *work)
+{
+       struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_delete);
+       struct gfs2_sbd *sdp = gl->gl_sbd;
+       struct gfs2_inode *ip = NULL;
+       struct inode *inode;
+       u64 no_addr = 0;
+
+       spin_lock(&gl->gl_spin);
+       ip = (struct gfs2_inode *)gl->gl_object;
+       if (ip)
+               no_addr = ip->i_no_addr;
+       spin_unlock(&gl->gl_spin);
+       if (ip) {
+               inode = gfs2_ilookup(sdp->sd_vfs, no_addr);
+               if (inode) {
+                       d_prune_aliases(inode);
+                       iput(inode);
+               }
+       }
+       gfs2_glock_put(gl);
+}
+
 static void glock_work_func(struct work_struct *work)
 {
        unsigned long delay = 0;
@@ -717,6 +781,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
        gl->gl_sbd = sdp;
        gl->gl_aspace = NULL;
        INIT_DELAYED_WORK(&gl->gl_work, glock_work_func);
+       INIT_WORK(&gl->gl_delete, delete_work_func);
 
        /* If this glock protects actual on-disk data or metadata blocks,
           create a VFS inode to manage the pages/buffers holding them. */
@@ -858,6 +923,8 @@ static void handle_callback(struct gfs2_glock *gl, unsigned int state,
                        gl->gl_demote_state != state) {
                gl->gl_demote_state = LM_ST_UNLOCKED;
        }
+       if (gl->gl_ops->go_callback)
+               gl->gl_ops->go_callback(gl);
        trace_gfs2_demote_rq(gl);
 }
 
@@ -1274,33 +1341,12 @@ void gfs2_glock_complete(struct gfs2_glock *gl, int ret)
                gfs2_glock_put(gl);
 }
 
-/**
- * demote_ok - Check to see if it's ok to unlock a glock
- * @gl: the glock
- *
- * Returns: 1 if it's ok
- */
-
-static int demote_ok(const struct gfs2_glock *gl)
-{
-       const struct gfs2_glock_operations *glops = gl->gl_ops;
-
-       if (gl->gl_state == LM_ST_UNLOCKED)
-               return 0;
-       if (!list_empty(&gl->gl_holders))
-               return 0;
-       if (glops->go_demote_ok)
-               return glops->go_demote_ok(gl);
-       return 1;
-}
-
 
 static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask)
 {
        struct gfs2_glock *gl;
        int may_demote;
        int nr_skipped = 0;
-       int got_ref = 0;
        LIST_HEAD(skipped);
 
        if (nr == 0)
@@ -1315,37 +1361,29 @@ static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask)
                list_del_init(&gl->gl_lru);
                atomic_dec(&lru_count);
 
+               /* Check if glock is about to be freed */
+               if (atomic_read(&gl->gl_ref) == 0)
+                       continue;
+
                /* Test for being demotable */
                if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
                        gfs2_glock_hold(gl);
-                       got_ref = 1;
                        spin_unlock(&lru_lock);
                        spin_lock(&gl->gl_spin);
                        may_demote = demote_ok(gl);
-                       spin_unlock(&gl->gl_spin);
-                       clear_bit(GLF_LOCK, &gl->gl_flags);
                        if (may_demote) {
                                handle_callback(gl, LM_ST_UNLOCKED, 0);
                                nr--;
-                               if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
-                                       gfs2_glock_put(gl);
-                               got_ref = 0;
                        }
+                       if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
+                               gfs2_glock_put_nolock(gl);
+                       spin_unlock(&gl->gl_spin);
+                       clear_bit(GLF_LOCK, &gl->gl_flags);
                        spin_lock(&lru_lock);
-                       if (may_demote)
-                               continue;
-               }
-               if (list_empty(&gl->gl_lru) &&
-                   (atomic_read(&gl->gl_ref) <= (2 + got_ref))) {
-                       nr_skipped++;
-                       list_add(&gl->gl_lru, &skipped);
-               }
-               if (got_ref) {
-                       spin_unlock(&lru_lock);
-                       gfs2_glock_put(gl);
-                       spin_lock(&lru_lock);
-                       got_ref = 0;
+                       continue;
                }
+               nr_skipped++;
+               list_add(&gl->gl_lru, &skipped);
        }
        list_splice(&skipped, &lru_list);
        atomic_add(nr_skipped, &lru_count);
@@ -1727,6 +1765,11 @@ int __init gfs2_glock_init(void)
        glock_workqueue = create_workqueue("glock_workqueue");
        if (IS_ERR(glock_workqueue))
                return PTR_ERR(glock_workqueue);
+       gfs2_delete_workqueue = create_workqueue("delete_workqueue");
+       if (IS_ERR(gfs2_delete_workqueue)) {
+               destroy_workqueue(glock_workqueue);
+               return PTR_ERR(gfs2_delete_workqueue);
+       }
 
        register_shrinker(&glock_shrinker);
 
@@ -1737,6 +1780,7 @@ void gfs2_glock_exit(void)
 {
        unregister_shrinker(&glock_shrinker);
        destroy_workqueue(glock_workqueue);
+       destroy_workqueue(gfs2_delete_workqueue);
 }
 
 static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi)
index a602a28f6f08b5bc259624ff7ee1fb6193da6eb7..c609894ec0d03a0831456379367d381393daca22 100644 (file)
@@ -143,6 +143,7 @@ struct lm_lockops {
 
 #define GLR_TRYFAILED          13
 
+extern struct workqueue_struct *gfs2_delete_workqueue;
 static inline struct gfs2_holder *gfs2_glock_is_locked_by_me(struct gfs2_glock *gl)
 {
        struct gfs2_holder *gh;
@@ -191,6 +192,8 @@ static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl)
 int gfs2_glock_get(struct gfs2_sbd *sdp,
                   u64 number, const struct gfs2_glock_operations *glops,
                   int create, struct gfs2_glock **glp);
+void gfs2_glock_hold(struct gfs2_glock *gl);
+void gfs2_glock_put_nolock(struct gfs2_glock *gl);
 int gfs2_glock_put(struct gfs2_glock *gl);
 void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags,
                      struct gfs2_holder *gh);
index d5e4ab155ca0a939c6219edb1137d442a9bf803d..6985eef06c392c79e4bd90340f60979776ecea1a 100644 (file)
@@ -323,6 +323,7 @@ static void trans_go_sync(struct gfs2_glock *gl)
 
        if (gl->gl_state != LM_ST_UNLOCKED &&
            test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
+               flush_workqueue(gfs2_delete_workqueue);
                gfs2_meta_syncfs(sdp);
                gfs2_log_shutdown(sdp);
        }
@@ -372,6 +373,25 @@ static int trans_go_demote_ok(const struct gfs2_glock *gl)
        return 0;
 }
 
+/**
+ * iopen_go_callback - schedule the dcache entry for the inode to be deleted
+ * @gl: the glock
+ *
+ * gl_spin lock is held while calling this
+ */
+static void iopen_go_callback(struct gfs2_glock *gl)
+{
+       struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object;
+
+       if (gl->gl_demote_state == LM_ST_UNLOCKED &&
+           gl->gl_state == LM_ST_SHARED &&
+           ip && test_bit(GIF_USER, &ip->i_flags)) {
+               gfs2_glock_hold(gl);
+               if (queue_work(gfs2_delete_workqueue, &gl->gl_delete) == 0)
+                       gfs2_glock_put_nolock(gl);
+       }
+}
+
 const struct gfs2_glock_operations gfs2_meta_glops = {
        .go_type = LM_TYPE_META,
 };
@@ -406,6 +426,7 @@ const struct gfs2_glock_operations gfs2_trans_glops = {
 
 const struct gfs2_glock_operations gfs2_iopen_glops = {
        .go_type = LM_TYPE_IOPEN,
+       .go_callback = iopen_go_callback,
 };
 
 const struct gfs2_glock_operations gfs2_flock_glops = {
index 225347fbff3c25ee72fdaa1e3d5106356bafde16..61801ada36f0daa1393799643f3e1957e7ba6c90 100644 (file)
@@ -159,6 +159,7 @@ struct gfs2_glock_operations {
        int (*go_lock) (struct gfs2_holder *gh);
        void (*go_unlock) (struct gfs2_holder *gh);
        int (*go_dump)(struct seq_file *seq, const struct gfs2_glock *gl);
+       void (*go_callback) (struct gfs2_glock *gl);
        const int go_type;
        const unsigned long go_min_hold_time;
 };
@@ -228,6 +229,7 @@ struct gfs2_glock {
        struct list_head gl_ail_list;
        atomic_t gl_ail_count;
        struct delayed_work gl_work;
+       struct work_struct gl_delete;
 };
 
 #define GFS2_MIN_LVB_SIZE 32   /* Min size of LVB that gfs2 supports */
index daa4ae341a292fe03175c378d441e767706fb9c8..fba795798d3a1b63f1ea10aab5342d5f044b7f21 100644 (file)
@@ -285,27 +285,19 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd)
        }
 
        tmp = rgd->rd_data - rgd->rd_free - rgd->rd_dinodes;
-       if (count[1] + count[2] != tmp) {
+       if (count[1] != tmp) {
                if (gfs2_consist_rgrpd(rgd))
                        fs_err(sdp, "used data mismatch:  %u != %u\n",
                               count[1], tmp);
                return;
        }
 
-       if (count[3] != rgd->rd_dinodes) {
+       if (count[2] + count[3] != rgd->rd_dinodes) {
                if (gfs2_consist_rgrpd(rgd))
                        fs_err(sdp, "used metadata mismatch:  %u != %u\n",
-                              count[3], rgd->rd_dinodes);
+                              count[2] + count[3], rgd->rd_dinodes);
                return;
        }
-
-       if (count[2] > count[3]) {
-               if (gfs2_consist_rgrpd(rgd))
-                       fs_err(sdp, "unlinked inodes > inodes:  %u\n",
-                              count[2]);
-               return;
-       }
-
 }
 
 static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block)
@@ -961,7 +953,8 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al)
  * Returns: The inode, if one has been found
  */
 
-static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
+static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked,
+                                    u64 skip)
 {
        struct inode *inode;
        u32 goal = 0, block;
@@ -985,6 +978,8 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
                goal++;
                if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked)
                        continue;
+               if (no_addr == skip)
+                       continue;
                *last_unlinked = no_addr;
                inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN,
                                          no_addr, -1, 1);
@@ -1104,7 +1099,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
                        if (try_rgrp_fit(rgd, al))
                                goto out;
                        if (rgd->rd_flags & GFS2_RDF_CHECK)
-                               inode = try_rgrp_unlink(rgd, last_unlinked);
+                               inode = try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr);
                        if (!rg_locked)
                                gfs2_glock_dq_uninit(&al->al_rgd_gh);
                        if (inode)
@@ -1138,7 +1133,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
                        if (try_rgrp_fit(rgd, al))
                                goto out;
                        if (rgd->rd_flags & GFS2_RDF_CHECK)
-                               inode = try_rgrp_unlink(rgd, last_unlinked);
+                               inode = try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr);
                        if (!rg_locked)
                                gfs2_glock_dq_uninit(&al->al_rgd_gh);
                        if (inode)
index 0a68013364708dbcafe39398952defaa9f560450..f522bb017973350932638ff55fd18d93af65014a 100644 (file)
@@ -353,7 +353,7 @@ fail:
        return error;
 }
 
-static void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf)
+void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc, const void *buf)
 {
        const struct gfs2_statfs_change *str = buf;
 
@@ -441,6 +441,29 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,
        brelse(l_bh);
 }
 
+void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh,
+                  struct buffer_head *l_bh)
+{
+       struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
+       struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);
+       struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;
+       struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local;
+
+       gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1);
+
+       spin_lock(&sdp->sd_statfs_spin);
+       m_sc->sc_total += l_sc->sc_total;
+       m_sc->sc_free += l_sc->sc_free;
+       m_sc->sc_dinodes += l_sc->sc_dinodes;
+       memset(l_sc, 0, sizeof(struct gfs2_statfs_change));
+       memset(l_bh->b_data + sizeof(struct gfs2_dinode),
+              0, sizeof(struct gfs2_statfs_change));
+       spin_unlock(&sdp->sd_statfs_spin);
+
+       gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1);
+       gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode));
+}
+
 int gfs2_statfs_sync(struct gfs2_sbd *sdp)
 {
        struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);
@@ -477,19 +500,7 @@ int gfs2_statfs_sync(struct gfs2_sbd *sdp)
        if (error)
                goto out_bh2;
 
-       gfs2_trans_add_bh(l_ip->i_gl, l_bh, 1);
-
-       spin_lock(&sdp->sd_statfs_spin);
-       m_sc->sc_total += l_sc->sc_total;
-       m_sc->sc_free += l_sc->sc_free;
-       m_sc->sc_dinodes += l_sc->sc_dinodes;
-       memset(l_sc, 0, sizeof(struct gfs2_statfs_change));
-       memset(l_bh->b_data + sizeof(struct gfs2_dinode),
-              0, sizeof(struct gfs2_statfs_change));
-       spin_unlock(&sdp->sd_statfs_spin);
-
-       gfs2_trans_add_bh(m_ip->i_gl, m_bh, 1);
-       gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode));
+       update_statfs(sdp, m_bh, l_bh);
 
        gfs2_trans_end(sdp);
 
@@ -680,6 +691,7 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
        struct gfs2_holder t_gh;
        int error;
 
+       flush_workqueue(gfs2_delete_workqueue);
        gfs2_quota_sync(sdp);
        gfs2_statfs_sync(sdp);
 
index b56413e3e40d8f86d14b5abd5aaed1c29013b4be..22e0417ed996c676f2941459912e0130e4e2aca9 100644 (file)
@@ -40,6 +40,10 @@ extern int gfs2_make_fs_rw(struct gfs2_sbd *sdp);
 extern int gfs2_statfs_init(struct gfs2_sbd *sdp);
 extern void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,
                               s64 dinodes);
+extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc,
+                                 const void *buf);
+extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh,
+                         struct buffer_head *l_bh);
 extern int gfs2_statfs_sync(struct gfs2_sbd *sdp);
 
 extern int gfs2_freeze_fs(struct gfs2_sbd *sdp);
index 23419dc3027b69659aab64eeb0a6aced7504810e..a7cbfbd340c7d53fa282f41d543a9737dbebfe8b 100644 (file)
@@ -386,16 +386,16 @@ static ssize_t jid_show(struct gfs2_sbd *sdp, char *buf)
 #define GDLM_ATTR(_name,_mode,_show,_store) \
 static struct gfs2_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store)
 
-GDLM_ATTR(proto_name,     0444, proto_name_show,       NULL);
-GDLM_ATTR(block,          0644, block_show,            block_store);
-GDLM_ATTR(withdraw,       0644, withdraw_show,         withdraw_store);
-GDLM_ATTR(id,             0444, lkid_show,             NULL);
-GDLM_ATTR(jid,           0444, jid_show,               NULL);
-GDLM_ATTR(first,          0444, lkfirst_show,          NULL);
-GDLM_ATTR(first_done,     0444, first_done_show,       NULL);
-GDLM_ATTR(recover,        0200, NULL,                  recover_store);
-GDLM_ATTR(recover_done,   0444, recover_done_show,     NULL);
-GDLM_ATTR(recover_status, 0444, recover_status_show,   NULL);
+GDLM_ATTR(proto_name,          0444, proto_name_show,          NULL);
+GDLM_ATTR(block,               0644, block_show,               block_store);
+GDLM_ATTR(withdraw,            0644, withdraw_show,            withdraw_store);
+GDLM_ATTR(id,                  0444, lkid_show,                NULL);
+GDLM_ATTR(jid,                 0444, jid_show,                 NULL);
+GDLM_ATTR(first,               0444, lkfirst_show,             NULL);
+GDLM_ATTR(first_done,          0444, first_done_show,          NULL);
+GDLM_ATTR(recover,             0600, NULL,                     recover_store);
+GDLM_ATTR(recover_done,                0444, recover_done_show,        NULL);
+GDLM_ATTR(recover_status,      0444, recover_status_show,      NULL);
 
 static struct attribute *lock_module_attrs[] = {
        &gdlm_attr_proto_name.attr,
index 98d6ef1c1dc067eba8a780fca4c5dac84dd1d379..148d55c14171dee39435c83d56c906c09dcd0cf8 100644 (file)
@@ -1,12 +1,11 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM gfs2
+
 #if !defined(_TRACE_GFS2_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_GFS2_H
 
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM gfs2
-#define TRACE_INCLUDE_FILE trace_gfs2
-
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
 #include <linux/dlmconstants.h>
@@ -403,5 +402,6 @@ TRACE_EVENT(gfs2_block_alloc,
 /* This part must be outside protection */
 #undef TRACE_INCLUDE_PATH
 #define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_gfs2
 #include <trace/define_trace.h>
 
index 6f833dc8e91022411939a290988af8a36e8d2018..f7fcbe49da723c40b56c816c8f04bea6e8d24616 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/nls.h>
 #include <linux/parser.h>
 #include <linux/seq_file.h>
+#include <linux/smp_lock.h>
 #include <linux/vfs.h>
 
 #include "hfs_fs.h"
index 9fc3af0c0dab6cd5b58af0f8a0cb0d0019ed9011..c0759fe0855b623863eac1345c8b8e4bf35608a9 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/pagemap.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/vfs.h>
 #include <linux/nls.h>
 
index fe02ad4740e76a2b4246657575d2a0f682b254f1..032604e5ef2ca36b1f9171d4fc2a775e9bcd7074 100644 (file)
@@ -972,6 +972,7 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
        sb->s_blocksize_bits = 10;
        sb->s_magic = HOSTFS_SUPER_MAGIC;
        sb->s_op = &hostfs_sbops;
+       sb->s_maxbytes = MAX_LFS_FILESIZE;
 
        /* NULL is printed as <NULL> by sprintf: avoid that. */
        if (req_root == NULL)
index 6916c41d70176f97dd22326dd7d47d4a39abfdeb..8865c94f55f602f19cb3b68182fc70bd41fcb4e4 100644 (file)
@@ -6,6 +6,7 @@
  *  directory VFS functions
  */
 
+#include <linux/smp_lock.h>
 #include "hpfs_fn.h"
 
 static int hpfs_dir_release(struct inode *inode, struct file *filp)
index 64ab52259204b24f20aa356d60ab73b1df982346..3efabff00367672a5a7bb722984590c14346338a 100644 (file)
@@ -6,6 +6,7 @@
  *  file VFS functions
  */
 
+#include <linux/smp_lock.h>
 #include "hpfs_fn.h"
 
 #define BLOCKS(size) (((size) + 511) >> 9)
index c2ea31bae313092dff76107889b79596cf7b417a..701ca54c0867fe482b9c33fdb6615a015114fa95 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 
 #include "hpfs.h"
 
index 39a1bfbea3122ed430fdffcd38f5aab02d62b68f..fe703ae46bc773f95a8502f12ccae915531d4271 100644 (file)
@@ -6,6 +6,7 @@
  *  inode VFS functions
  */
 
+#include <linux/smp_lock.h>
 #include "hpfs_fn.h"
 
 void hpfs_init_inode(struct inode *i)
index b649232dde97baf4eac591548b7944c5aedcc666..82b9c4ba9ed08b07eda6832d6a5953581f515967 100644 (file)
@@ -6,6 +6,7 @@
  *  adding & removing files & directories
  */
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include "hpfs_fn.h"
 
 static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
index 941c8425c10b34493e9ad6fefef7fe54f451c84a..cb88dac8ccaae6f43dfc25edbcaa202fa0cb26cb 100644 (file)
@@ -935,26 +935,28 @@ static int can_do_hugetlb_shm(void)
        return capable(CAP_IPC_LOCK) || in_group_p(sysctl_hugetlb_shm_group);
 }
 
-struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag)
+struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag,
+                                               struct user_struct **user)
 {
        int error = -ENOMEM;
-       int unlock_shm = 0;
        struct file *file;
        struct inode *inode;
        struct dentry *dentry, *root;
        struct qstr quick_string;
-       struct user_struct *user = current_user();
 
+       *user = NULL;
        if (!hugetlbfs_vfsmount)
                return ERR_PTR(-ENOENT);
 
        if (!can_do_hugetlb_shm()) {
-               if (user_shm_lock(size, user)) {
-                       unlock_shm = 1;
+               *user = current_user();
+               if (user_shm_lock(size, *user)) {
                        WARN_ONCE(1,
                          "Using mlock ulimits for SHM_HUGETLB deprecated\n");
-               } else
+               } else {
+                       *user = NULL;
                        return ERR_PTR(-EPERM);
+               }
        }
 
        root = hugetlbfs_vfsmount->mnt_root;
@@ -996,8 +998,10 @@ out_inode:
 out_dentry:
        dput(dentry);
 out_shm_unlock:
-       if (unlock_shm)
-               user_shm_unlock(size, user);
+       if (*user) {
+               user_shm_unlock(size, *user);
+               *user = NULL;
+       }
        return ERR_PTR(error);
 }
 
index 901bad1e5f1210cce8f2bc2a474345f5b1a4072a..ae7b67e48661b0f078679a67d6f0c1d40847bf06 100644 (file)
@@ -120,12 +120,11 @@ static void wake_up_inode(struct inode *inode)
  * These are initializations that need to be done on every inode
  * allocation as the fields are not initialised by slab allocation.
  */
-struct inode *inode_init_always(struct super_block *sb, struct inode *inode)
+int inode_init_always(struct super_block *sb, struct inode *inode)
 {
        static const struct address_space_operations empty_aops;
        static struct inode_operations empty_iops;
        static const struct file_operations empty_fops;
-
        struct address_space *const mapping = &inode->i_data;
 
        inode->i_sb = sb;
@@ -152,7 +151,7 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode)
        inode->dirtied_when = 0;
 
        if (security_inode_alloc(inode))
-               goto out_free_inode;
+               goto out;
 
        /* allocate and initialize an i_integrity */
        if (ima_inode_alloc(inode))
@@ -198,16 +197,12 @@ struct inode *inode_init_always(struct super_block *sb, struct inode *inode)
        inode->i_fsnotify_mask = 0;
 #endif
 
-       return inode;
+       return 0;
 
 out_free_security:
        security_inode_free(inode);
-out_free_inode:
-       if (inode->i_sb->s_op->destroy_inode)
-               inode->i_sb->s_op->destroy_inode(inode);
-       else
-               kmem_cache_free(inode_cachep, (inode));
-       return NULL;
+out:
+       return -ENOMEM;
 }
 EXPORT_SYMBOL(inode_init_always);
 
@@ -220,12 +215,21 @@ static struct inode *alloc_inode(struct super_block *sb)
        else
                inode = kmem_cache_alloc(inode_cachep, GFP_KERNEL);
 
-       if (inode)
-               return inode_init_always(sb, inode);
-       return NULL;
+       if (!inode)
+               return NULL;
+
+       if (unlikely(inode_init_always(sb, inode))) {
+               if (inode->i_sb->s_op->destroy_inode)
+                       inode->i_sb->s_op->destroy_inode(inode);
+               else
+                       kmem_cache_free(inode_cachep, inode);
+               return NULL;
+       }
+
+       return inode;
 }
 
-void destroy_inode(struct inode *inode)
+void __destroy_inode(struct inode *inode)
 {
        BUG_ON(inode_has_buffers(inode));
        ima_inode_free(inode);
@@ -237,13 +241,17 @@ void destroy_inode(struct inode *inode)
        if (inode->i_default_acl && inode->i_default_acl != ACL_NOT_CACHED)
                posix_acl_release(inode->i_default_acl);
 #endif
+}
+EXPORT_SYMBOL(__destroy_inode);
+
+void destroy_inode(struct inode *inode)
+{
+       __destroy_inode(inode);
        if (inode->i_sb->s_op->destroy_inode)
                inode->i_sb->s_op->destroy_inode(inode);
        else
                kmem_cache_free(inode_cachep, (inode));
 }
-EXPORT_SYMBOL(destroy_inode);
-
 
 /*
  * These are initializations that only need to be done
index 58a7963e168ae4b8b4486fa54cd4b5fb5d66a9ee..85f96bc651c727ba04915138c50b45e9b63a3acd 100644 (file)
@@ -142,6 +142,7 @@ static const struct dentry_operations isofs_dentry_ops[] = {
 
 struct iso9660_options{
        unsigned int rock:1;
+       unsigned int joliet:1;
        unsigned int cruft:1;
        unsigned int hide:1;
        unsigned int showassoc:1;
@@ -151,7 +152,6 @@ struct iso9660_options{
        unsigned int gid_set:1;
        unsigned int utf8:1;
        unsigned char map;
-       char joliet;
        unsigned char check;
        unsigned int blocksize;
        mode_t fmode;
@@ -632,7 +632,7 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
                        else if (isonum_711(vdp->type) == ISO_VD_SUPPLEMENTARY) {
                                sec = (struct iso_supplementary_descriptor *)vdp;
                                if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) {
-                                       if (opt.joliet == 'y') {
+                                       if (opt.joliet) {
                                                if (sec->escape[2] == 0x40)
                                                        joliet_level = 1;
                                                else if (sec->escape[2] == 0x43)
index 737f7246a4b5ddc750b4a5198928f4b5afacc193..f96f85092d1cf2bffb671d147470666118b4bc7d 100644 (file)
@@ -287,6 +287,7 @@ int journal_write_metadata_buffer(transaction_t *transaction,
        struct page *new_page;
        unsigned int new_offset;
        struct buffer_head *bh_in = jh2bh(jh_in);
+       journal_t *journal = transaction->t_journal;
 
        /*
         * The buffer really shouldn't be locked: only the current committing
@@ -300,6 +301,11 @@ int journal_write_metadata_buffer(transaction_t *transaction,
        J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in));
 
        new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL);
+       /* keep subsequent assertions sane */
+       new_bh->b_state = 0;
+       init_buffer(new_bh, NULL, NULL);
+       atomic_set(&new_bh->b_count, 1);
+       new_jh = journal_add_journal_head(new_bh);      /* This sleeps */
 
        /*
         * If a new transaction has already done a buffer copy-out, then
@@ -361,14 +367,6 @@ repeat:
                kunmap_atomic(mapped_data, KM_USER0);
        }
 
-       /* keep subsequent assertions sane */
-       new_bh->b_state = 0;
-       init_buffer(new_bh, NULL, NULL);
-       atomic_set(&new_bh->b_count, 1);
-       jbd_unlock_bh_state(bh_in);
-
-       new_jh = journal_add_journal_head(new_bh);      /* This sleeps */
-
        set_bh_page(new_bh, new_page, new_offset);
        new_jh->b_transaction = NULL;
        new_bh->b_size = jh2bh(jh_in)->b_size;
@@ -385,7 +383,11 @@ repeat:
         * copying is moved to the transaction's shadow queue.
         */
        JBUFFER_TRACE(jh_in, "file as BJ_Shadow");
-       journal_file_buffer(jh_in, transaction, BJ_Shadow);
+       spin_lock(&journal->j_list_lock);
+       __journal_file_buffer(jh_in, transaction, BJ_Shadow);
+       spin_unlock(&journal->j_list_lock);
+       jbd_unlock_bh_state(bh_in);
+
        JBUFFER_TRACE(new_jh, "file as BJ_IO");
        journal_file_buffer(new_jh, transaction, BJ_IO);
 
@@ -848,6 +850,12 @@ static int journal_reset(journal_t *journal)
 
        first = be32_to_cpu(sb->s_first);
        last = be32_to_cpu(sb->s_maxlen);
+       if (first + JFS_MIN_JOURNAL_BLOCKS > last + 1) {
+               printk(KERN_ERR "JBD: Journal too short (blocks %lu-%lu).\n",
+                      first, last);
+               journal_fail_superblock(journal);
+               return -EINVAL;
+       }
 
        journal->j_first = first;
        journal->j_last = last;
index 73242ba7c7b1315d9cea08de1f85f1189293dd22..c03ac11f74be1313b8f7d09a24eba88f1d27ceed 100644 (file)
@@ -489,34 +489,15 @@ void journal_unlock_updates (journal_t *journal)
        wake_up(&journal->j_wait_transaction_locked);
 }
 
-/*
- * Report any unexpected dirty buffers which turn up.  Normally those
- * indicate an error, but they can occur if the user is running (say)
- * tune2fs to modify the live filesystem, so we need the option of
- * continuing as gracefully as possible.  #
- *
- * The caller should already hold the journal lock and
- * j_list_lock spinlock: most callers will need those anyway
- * in order to probe the buffer's journaling state safely.
- */
-static void jbd_unexpected_dirty_buffer(struct journal_head *jh)
+static void warn_dirty_buffer(struct buffer_head *bh)
 {
-       int jlist;
-
-       /* If this buffer is one which might reasonably be dirty
-        * --- ie. data, or not part of this journal --- then
-        * we're OK to leave it alone, but otherwise we need to
-        * move the dirty bit to the journal's own internal
-        * JBDDirty bit. */
-       jlist = jh->b_jlist;
+       char b[BDEVNAME_SIZE];
 
-       if (jlist == BJ_Metadata || jlist == BJ_Reserved ||
-           jlist == BJ_Shadow || jlist == BJ_Forget) {
-               struct buffer_head *bh = jh2bh(jh);
-
-               if (test_clear_buffer_dirty(bh))
-                       set_buffer_jbddirty(bh);
-       }
+       printk(KERN_WARNING
+              "JBD: Spotted dirty metadata buffer (dev = %s, blocknr = %llu). "
+              "There's a risk of filesystem corruption in case of system "
+              "crash.\n",
+              bdevname(bh->b_bdev, b), (unsigned long long)bh->b_blocknr);
 }
 
 /*
@@ -583,14 +564,16 @@ repeat:
                        if (jh->b_next_transaction)
                                J_ASSERT_JH(jh, jh->b_next_transaction ==
                                                        transaction);
+                       warn_dirty_buffer(bh);
                }
                /*
                 * In any case we need to clean the dirty flag and we must
                 * do it under the buffer lock to be sure we don't race
                 * with running write-out.
                 */
-               JBUFFER_TRACE(jh, "Unexpected dirty buffer");
-               jbd_unexpected_dirty_buffer(jh);
+               JBUFFER_TRACE(jh, "Journalling dirty buffer");
+               clear_buffer_dirty(bh);
+               set_buffer_jbddirty(bh);
        }
 
        unlock_buffer(bh);
@@ -826,6 +809,15 @@ int journal_get_create_access(handle_t *handle, struct buffer_head *bh)
        J_ASSERT_JH(jh, buffer_locked(jh2bh(jh)));
 
        if (jh->b_transaction == NULL) {
+               /*
+                * Previous journal_forget() could have left the buffer
+                * with jbddirty bit set because it was being committed. When
+                * the commit finished, we've filed the buffer for
+                * checkpointing and marked it dirty. Now we are reallocating
+                * the buffer so the transaction freeing it must have
+                * committed and so it's safe to clear the dirty bit.
+                */
+               clear_buffer_dirty(jh2bh(jh));
                jh->b_transaction = transaction;
 
                /* first access by this transaction */
@@ -1782,8 +1774,13 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
 
        if (jh->b_cp_transaction) {
                JBUFFER_TRACE(jh, "on running+cp transaction");
+               /*
+                * We don't want to write the buffer anymore, clear the
+                * bit so that we don't confuse checks in
+                * __journal_file_buffer
+                */
+               clear_buffer_dirty(bh);
                __journal_file_buffer(jh, transaction, BJ_Forget);
-               clear_buffer_jbddirty(bh);
                may_free = 0;
        } else {
                JBUFFER_TRACE(jh, "on running transaction");
@@ -2041,12 +2038,17 @@ void __journal_file_buffer(struct journal_head *jh,
        if (jh->b_transaction && jh->b_jlist == jlist)
                return;
 
-       /* The following list of buffer states needs to be consistent
-        * with __jbd_unexpected_dirty_buffer()'s handling of dirty
-        * state. */
-
        if (jlist == BJ_Metadata || jlist == BJ_Reserved ||
            jlist == BJ_Shadow || jlist == BJ_Forget) {
+               /*
+                * For metadata buffers, we track dirty bit in buffer_jbddirty
+                * instead of buffer_dirty. We should not see a dirty bit set
+                * here because we clear it in do_get_write_access but e.g.
+                * tune2fs can modify the sb and set the dirty bit at any time
+                * so we try to gracefully handle that.
+                */
+               if (buffer_dirty(bh))
+                       warn_dirty_buffer(bh);
                if (test_clear_buffer_dirty(bh) ||
                    test_clear_buffer_jbddirty(bh))
                        was_dirty = 1;
index 18bfd5dab64220d7d11fc90b6efb7c79e807c16a..e378cb383979a3e8e54234b14aa354e890c54e26 100644 (file)
@@ -297,6 +297,7 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction,
        unsigned int new_offset;
        struct buffer_head *bh_in = jh2bh(jh_in);
        struct jbd2_buffer_trigger_type *triggers;
+       journal_t *journal = transaction->t_journal;
 
        /*
         * The buffer really shouldn't be locked: only the current committing
@@ -310,6 +311,11 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction,
        J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in));
 
        new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL);
+       /* keep subsequent assertions sane */
+       new_bh->b_state = 0;
+       init_buffer(new_bh, NULL, NULL);
+       atomic_set(&new_bh->b_count, 1);
+       new_jh = jbd2_journal_add_journal_head(new_bh); /* This sleeps */
 
        /*
         * If a new transaction has already done a buffer copy-out, then
@@ -388,14 +394,6 @@ repeat:
                kunmap_atomic(mapped_data, KM_USER0);
        }
 
-       /* keep subsequent assertions sane */
-       new_bh->b_state = 0;
-       init_buffer(new_bh, NULL, NULL);
-       atomic_set(&new_bh->b_count, 1);
-       jbd_unlock_bh_state(bh_in);
-
-       new_jh = jbd2_journal_add_journal_head(new_bh); /* This sleeps */
-
        set_bh_page(new_bh, new_page, new_offset);
        new_jh->b_transaction = NULL;
        new_bh->b_size = jh2bh(jh_in)->b_size;
@@ -412,7 +410,11 @@ repeat:
         * copying is moved to the transaction's shadow queue.
         */
        JBUFFER_TRACE(jh_in, "file as BJ_Shadow");
-       jbd2_journal_file_buffer(jh_in, transaction, BJ_Shadow);
+       spin_lock(&journal->j_list_lock);
+       __jbd2_journal_file_buffer(jh_in, transaction, BJ_Shadow);
+       spin_unlock(&journal->j_list_lock);
+       jbd_unlock_bh_state(bh_in);
+
        JBUFFER_TRACE(new_jh, "file as BJ_IO");
        jbd2_journal_file_buffer(new_jh, transaction, BJ_IO);
 
@@ -2410,6 +2412,7 @@ const char *jbd2_dev_to_name(dev_t device)
        int     i = hash_32(device, CACHE_SIZE_BITS);
        char    *ret;
        struct block_device *bd;
+       static struct devname_cache *new_dev;
 
        rcu_read_lock();
        if (devcache[i] && devcache[i]->device == device) {
@@ -2419,20 +2422,20 @@ const char *jbd2_dev_to_name(dev_t device)
        }
        rcu_read_unlock();
 
+       new_dev = kmalloc(sizeof(struct devname_cache), GFP_KERNEL);
+       if (!new_dev)
+               return "NODEV-ALLOCFAILURE"; /* Something non-NULL */
        spin_lock(&devname_cache_lock);
        if (devcache[i]) {
                if (devcache[i]->device == device) {
+                       kfree(new_dev);
                        ret = devcache[i]->devname;
                        spin_unlock(&devname_cache_lock);
                        return ret;
                }
                call_rcu(&devcache[i]->rcu, free_devcache);
        }
-       devcache[i] = kmalloc(sizeof(struct devname_cache), GFP_KERNEL);
-       if (!devcache[i]) {
-               spin_unlock(&devname_cache_lock);
-               return "NODEV-ALLOCFAILURE"; /* Something non-NULL */
-       }
+       devcache[i] = new_dev;
        devcache[i]->device = device;
        bd = bdget(device);
        if (bd) {
index 494501edba6bcf0ce39c129848d5862177e1d38b..6213ac728f303286e15a2b6703fc90d69e2bd6ba 100644 (file)
@@ -499,34 +499,15 @@ void jbd2_journal_unlock_updates (journal_t *journal)
        wake_up(&journal->j_wait_transaction_locked);
 }
 
-/*
- * Report any unexpected dirty buffers which turn up.  Normally those
- * indicate an error, but they can occur if the user is running (say)
- * tune2fs to modify the live filesystem, so we need the option of
- * continuing as gracefully as possible.  #
- *
- * The caller should already hold the journal lock and
- * j_list_lock spinlock: most callers will need those anyway
- * in order to probe the buffer's journaling state safely.
- */
-static void jbd_unexpected_dirty_buffer(struct journal_head *jh)
+static void warn_dirty_buffer(struct buffer_head *bh)
 {
-       int jlist;
-
-       /* If this buffer is one which might reasonably be dirty
-        * --- ie. data, or not part of this journal --- then
-        * we're OK to leave it alone, but otherwise we need to
-        * move the dirty bit to the journal's own internal
-        * JBDDirty bit. */
-       jlist = jh->b_jlist;
+       char b[BDEVNAME_SIZE];
 
-       if (jlist == BJ_Metadata || jlist == BJ_Reserved ||
-           jlist == BJ_Shadow || jlist == BJ_Forget) {
-               struct buffer_head *bh = jh2bh(jh);
-
-               if (test_clear_buffer_dirty(bh))
-                       set_buffer_jbddirty(bh);
-       }
+       printk(KERN_WARNING
+              "JBD: Spotted dirty metadata buffer (dev = %s, blocknr = %llu). "
+              "There's a risk of filesystem corruption in case of system "
+              "crash.\n",
+              bdevname(bh->b_bdev, b), (unsigned long long)bh->b_blocknr);
 }
 
 /*
@@ -593,14 +574,16 @@ repeat:
                        if (jh->b_next_transaction)
                                J_ASSERT_JH(jh, jh->b_next_transaction ==
                                                        transaction);
+                       warn_dirty_buffer(bh);
                }
                /*
                 * In any case we need to clean the dirty flag and we must
                 * do it under the buffer lock to be sure we don't race
                 * with running write-out.
                 */
-               JBUFFER_TRACE(jh, "Unexpected dirty buffer");
-               jbd_unexpected_dirty_buffer(jh);
+               JBUFFER_TRACE(jh, "Journalling dirty buffer");
+               clear_buffer_dirty(bh);
+               set_buffer_jbddirty(bh);
        }
 
        unlock_buffer(bh);
@@ -843,6 +826,15 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
        J_ASSERT_JH(jh, buffer_locked(jh2bh(jh)));
 
        if (jh->b_transaction == NULL) {
+               /*
+                * Previous jbd2_journal_forget() could have left the buffer
+                * with jbddirty bit set because it was being committed. When
+                * the commit finished, we've filed the buffer for
+                * checkpointing and marked it dirty. Now we are reallocating
+                * the buffer so the transaction freeing it must have
+                * committed and so it's safe to clear the dirty bit.
+                */
+               clear_buffer_dirty(jh2bh(jh));
                jh->b_transaction = transaction;
 
                /* first access by this transaction */
@@ -1644,8 +1636,13 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
 
        if (jh->b_cp_transaction) {
                JBUFFER_TRACE(jh, "on running+cp transaction");
+               /*
+                * We don't want to write the buffer anymore, clear the
+                * bit so that we don't confuse checks in
+                * __journal_file_buffer
+                */
+               clear_buffer_dirty(bh);
                __jbd2_journal_file_buffer(jh, transaction, BJ_Forget);
-               clear_buffer_jbddirty(bh);
                may_free = 0;
        } else {
                JBUFFER_TRACE(jh, "on running transaction");
@@ -1896,12 +1893,17 @@ void __jbd2_journal_file_buffer(struct journal_head *jh,
        if (jh->b_transaction && jh->b_jlist == jlist)
                return;
 
-       /* The following list of buffer states needs to be consistent
-        * with __jbd_unexpected_dirty_buffer()'s handling of dirty
-        * state. */
-
        if (jlist == BJ_Metadata || jlist == BJ_Reserved ||
            jlist == BJ_Shadow || jlist == BJ_Forget) {
+               /*
+                * For metadata buffers, we track dirty bit in buffer_jbddirty
+                * instead of buffer_dirty. We should not see a dirty bit set
+                * here because we clear it in do_get_write_access but e.g.
+                * tune2fs can modify the sb and set the dirty bit at any time
+                * so we try to gracefully handle that.
+                */
+               if (buffer_dirty(bh))
+                       warn_dirty_buffer(bh);
                if (test_clear_buffer_dirty(bh) ||
                    test_clear_buffer_jbddirty(bh))
                        was_dirty = 1;
index a0244740b75a4d9aa04eff4beb8cacb147a63ab2..b47679be118a5fe00a04585d54b07f9797e7f700 100644 (file)
@@ -270,19 +270,21 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
        D2({
                int i=0;
                struct jffs2_raw_node_ref *this;
-               printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n" KERN_DEBUG);
+               printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n");
 
                this = ic->nodes;
 
+               printk(KERN_DEBUG);
                while(this) {
-                       printk( "0x%08x(%d)->", ref_offset(this), ref_flags(this));
+                       printk(KERN_CONT "0x%08x(%d)->",
+                              ref_offset(this), ref_flags(this));
                        if (++i == 5) {
-                               printk("\n" KERN_DEBUG);
+                               printk(KERN_DEBUG);
                                i=0;
                        }
                        this = this->next_in_ino;
                }
-               printk("\n");
+               printk(KERN_CONT "\n");
        });
 
        switch (ic->class) {
index 5edc2bf2058134505369a0f7844363f7e3a2ecfd..23c947539864a0c0613ade018cb9e6400149de3a 100644 (file)
@@ -99,7 +99,7 @@ static int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg)
        kunmap(pg);
 
        D2(printk(KERN_DEBUG "readpage finished\n"));
-       return 0;
+       return ret;
 }
 
 int jffs2_do_readpage_unlock(struct inode *inode, struct page *pg)
index 7515e73e2bfbd0729069b0ec0f16df2da74f71a6..696686cc206e1d807df1b6706a4a1a54f3f6b2bf 100644 (file)
@@ -130,9 +130,9 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
        if (jffs2_sum_active()) {
                s = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
                if (!s) {
-                       kfree(flashbuf);
                        JFFS2_WARNING("Can't allocate memory for summary\n");
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto out;
                }
        }
 
index 07a22caf26878223efffacdb01c69e23d4ce7a47..0035c021395ac840cd71bd38c82f28b4ad154f19 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/fs.h>
index d9a721e6db70139073ca055cbea471769f6a83dd..5ef7bac265e5238495e7da7d8470fac62f922b66 100644 (file)
@@ -1268,10 +1268,20 @@ int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) {
        if (!c->wbuf)
                return -ENOMEM;
 
+#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
+       c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
+       if (!c->wbuf_verify) {
+               kfree(c->wbuf);
+               return -ENOMEM;
+       }
+#endif
        return 0;
 }
 
 void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c) {
+#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
+       kfree(c->wbuf_verify);
+#endif
        kfree(c->wbuf);
 }
 
index 91fa3ad6e8c2dc01144bcf1ab56c250a9c9e54bb..a29c7c3e3fb81a58148c93e0dd56e858bac04939 100644 (file)
@@ -67,10 +67,8 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type)
                acl = posix_acl_from_xattr(value, size);
        }
        kfree(value);
-       if (!IS_ERR(acl)) {
+       if (!IS_ERR(acl))
                set_cached_acl(inode, type, acl);
-               posix_acl_release(acl);
-       }
        return acl;
 }
 
index ddfa89948c3f1e6cbf553f213883cb2ca2a4ed5e..dcec3d3ea64f944cd51d36f35b4150279c5659f2 100644 (file)
@@ -217,7 +217,7 @@ int get_sb_pseudo(struct file_system_type *fs_type, char *name,
                return PTR_ERR(s);
 
        s->s_flags = MS_NOUSER;
-       s->s_maxbytes = ~0ULL;
+       s->s_maxbytes = MAX_LFS_FILESIZE;
        s->s_blocksize = PAGE_SIZE;
        s->s_blocksize_bits = PAGE_SHIFT;
        s->s_magic = magic;
index f2fdcbce143efa9bb43ed363301674e0db179294..4336adba952a770343150468053a866fe49016c7 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/smp_lock.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
index 1725037374c595e3919f2cbb566f33593fd388f1..bd173a6ca3b1b0723b29d796ca77d6883f4fd25f 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/types.h>
 #include <linux/time.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/in.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/clnt.h>
index 3688e55901fc48e733c24329d05e140252004648..e1d28ddd21699060a8b1e0907a8806bea9e62f95 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/types.h>
 #include <linux/time.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/in.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/clnt.h>
index 5b961eb71cbf9781988b50559ff10842f49e483a..1f13751693a5007e8ba1be6b0b06c948665b260c 100644 (file)
@@ -1542,28 +1542,31 @@ int may_open(struct path *path, int acc_mode, int flag)
         * An append-only file must be opened in append mode for writing.
         */
        if (IS_APPEND(inode)) {
+               error = -EPERM;
                if  ((flag & FMODE_WRITE) && !(flag & O_APPEND))
-                       return -EPERM;
+                       goto err_out;
                if (flag & O_TRUNC)
-                       return -EPERM;
+                       goto err_out;
        }
 
        /* O_NOATIME can only be set by the owner or superuser */
        if (flag & O_NOATIME)
-               if (!is_owner_or_cap(inode))
-                       return -EPERM;
+               if (!is_owner_or_cap(inode)) {
+                       error = -EPERM;
+                       goto err_out;
+               }
 
        /*
         * Ensure there are no outstanding leases on the file.
         */
        error = break_lease(inode, flag);
        if (error)
-               return error;
+               goto err_out;
 
        if (flag & O_TRUNC) {
                error = get_write_access(inode);
                if (error)
-                       return error;
+                       goto err_out;
 
                /*
                 * Refuse to truncate files with mandatory locks held on them.
@@ -1581,12 +1584,17 @@ int may_open(struct path *path, int acc_mode, int flag)
                }
                put_write_access(inode);
                if (error)
-                       return error;
+                       goto err_out;
        } else
                if (flag & FMODE_WRITE)
                        vfs_dq_init(inode);
 
        return 0;
+err_out:
+       ima_counts_put(path, acc_mode ?
+                      acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) :
+                      ACC_MODE(flag) & (MAY_READ | MAY_WRITE));
+       return error;
 }
 
 /*
@@ -1761,6 +1769,10 @@ do_last:
                        goto exit;
                }
                filp = nameidata_to_filp(&nd, open_flag);
+               if (IS_ERR(filp))
+                       ima_counts_put(&nd.path,
+                                      acc_mode & (MAY_READ | MAY_WRITE |
+                                                  MAY_EXEC));
                mnt_drop_write(nd.path.mnt);
                if (nd.root.mnt)
                        path_put(&nd.root);
@@ -1817,6 +1829,9 @@ ok:
                goto exit;
        }
        filp = nameidata_to_filp(&nd, open_flag);
+       if (IS_ERR(filp))
+               ima_counts_put(&nd.path,
+                              acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC));
        /*
         * It is now safe to drop the mnt write
         * because the filp has had a write taken
index 3dc283fd4716beacfe037839d2fc5fd5974c925d..7230787d18b02979122218429b4bf8af59b24cf7 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/seq_file.h>
 #include <linux/mnt_namespace.h>
 #include <linux/namei.h>
+#include <linux/nsproxy.h>
 #include <linux/security.h>
 #include <linux/mount.h>
 #include <linux/ramfs.h>
@@ -315,7 +316,8 @@ EXPORT_SYMBOL_GPL(mnt_clone_write);
  */
 int mnt_want_write_file(struct file *file)
 {
-       if (!(file->f_mode & FMODE_WRITE))
+       struct inode *inode = file->f_dentry->d_inode;
+       if (!(file->f_mode & FMODE_WRITE) || special_file(inode->i_mode))
                return mnt_want_write(file->f_path.mnt);
        else
                return mnt_clone_write(file->f_path.mnt);
index c2d061675d80724ecf1f3ae45b467f7286cf28db..8d25ccb2d51d514a27a5098cfd13ad872cb46dc8 100644 (file)
@@ -1242,20 +1242,6 @@ error:
        return error;
 }
 
-/*
- * Initialize a session.
- * Note: save the mount rsize and wsize for create_server negotiation.
- */
-static void nfs4_init_session(struct nfs_client *clp,
-                             unsigned int wsize, unsigned int rsize)
-{
-#if defined(CONFIG_NFS_V4_1)
-       if (nfs4_has_session(clp)) {
-               clp->cl_session->fc_attrs.max_rqst_sz = wsize;
-               clp->cl_session->fc_attrs.max_resp_sz = rsize;
-       }
-#endif /* CONFIG_NFS_V4_1 */
-}
 
 /*
  * Session has been established, and the client marked ready.
@@ -1350,7 +1336,9 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
        BUG_ON(!server->nfs_client->rpc_ops);
        BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
 
-       nfs4_init_session(server->nfs_client, server->wsize, server->rsize);
+       error = nfs4_init_session(server);
+       if (error < 0)
+               goto error;
 
        /* Probe the root fh to retrieve its FSID */
        error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path);
index af05b918cb5bcce6655aee1d16adaf9000fe9d25..6dd48a4405b46d409af629d4195b27b17e83dab1 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 
 #include <linux/nfs4.h>
index 89f98e9a024b73accbfce55d575834e9357be491..32062c33c859496198395db435117c7c33105d3d 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/nfs_fs.h>
 #include <linux/nfs_mount.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include <linux/pagevec.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
@@ -1026,12 +1025,12 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
                                res = NULL;
                                goto out;
                        /* This turned out not to be a regular file */
-                       case -EISDIR:
                        case -ENOTDIR:
                                goto no_open;
                        case -ELOOP:
                                if (!(nd->intent.open.flags & O_NOFOLLOW))
                                        goto no_open;
+                       /* case -EISDIR: */
                        /* case -EINVAL: */
                        default:
                                goto out;
index 489fc01a3204e9d7b21b99bee47dcdded6fb38d0..e4e089a8f294343875f730b655a18f156b4839e3 100644 (file)
@@ -255,7 +255,7 @@ static void nfs_direct_read_release(void *calldata)
 
        if (put_dreq(dreq))
                nfs_direct_complete(dreq);
-       nfs_readdata_release(calldata);
+       nfs_readdata_free(data);
 }
 
 static const struct rpc_call_ops nfs_read_direct_ops = {
@@ -314,14 +314,14 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
                                        data->npages, 1, 0, data->pagevec, NULL);
                up_read(&current->mm->mmap_sem);
                if (result < 0) {
-                       nfs_readdata_release(data);
+                       nfs_readdata_free(data);
                        break;
                }
                if ((unsigned)result < data->npages) {
                        bytes = result * PAGE_SIZE;
                        if (bytes <= pgbase) {
                                nfs_direct_release_pages(data->pagevec, result);
-                               nfs_readdata_release(data);
+                               nfs_readdata_free(data);
                                break;
                        }
                        bytes -= pgbase;
@@ -334,7 +334,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
                data->inode = inode;
                data->cred = msg.rpc_cred;
                data->args.fh = NFS_FH(inode);
-               data->args.context = get_nfs_open_context(ctx);
+               data->args.context = ctx;
                data->args.offset = pos;
                data->args.pgbase = pgbase;
                data->args.pages = data->pagevec;
@@ -441,7 +441,7 @@ static void nfs_direct_free_writedata(struct nfs_direct_req *dreq)
                struct nfs_write_data *data = list_entry(dreq->rewrite_list.next, struct nfs_write_data, pages);
                list_del(&data->pages);
                nfs_direct_release_pages(data->pagevec, data->npages);
-               nfs_writedata_release(data);
+               nfs_writedata_free(data);
        }
 }
 
@@ -534,7 +534,7 @@ static void nfs_direct_commit_release(void *calldata)
 
        dprintk("NFS: %5u commit returned %d\n", data->task.tk_pid, status);
        nfs_direct_write_complete(dreq, data->inode);
-       nfs_commitdata_release(calldata);
+       nfs_commit_free(data);
 }
 
 static const struct rpc_call_ops nfs_commit_direct_ops = {
@@ -570,7 +570,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
        data->args.fh = NFS_FH(data->inode);
        data->args.offset = 0;
        data->args.count = 0;
-       data->args.context = get_nfs_open_context(dreq->ctx);
+       data->args.context = dreq->ctx;
        data->res.count = 0;
        data->res.fattr = &data->fattr;
        data->res.verf = &data->verf;
@@ -734,14 +734,14 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
                                        data->npages, 0, 0, data->pagevec, NULL);
                up_read(&current->mm->mmap_sem);
                if (result < 0) {
-                       nfs_writedata_release(data);
+                       nfs_writedata_free(data);
                        break;
                }
                if ((unsigned)result < data->npages) {
                        bytes = result * PAGE_SIZE;
                        if (bytes <= pgbase) {
                                nfs_direct_release_pages(data->pagevec, result);
-                               nfs_writedata_release(data);
+                               nfs_writedata_free(data);
                                break;
                        }
                        bytes -= pgbase;
@@ -756,7 +756,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq,
                data->inode = inode;
                data->cred = msg.rpc_cred;
                data->args.fh = NFS_FH(inode);
-               data->args.context = get_nfs_open_context(ctx);
+               data->args.context = ctx;
                data->args.offset = pos;
                data->args.pgbase = pgbase;
                data->args.pages = data->pagevec;
index 0055b813ec2c7004e9647ad781c3706066aeac3e..05062329b678a148c464990b0f9d4f6a68ab617f 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include <linux/aio.h>
 
 #include <asm/uaccess.h>
index 46177cb8706402cff250c18a7b10640deee0b38f..b35d2a616066ada8029be5e62b8a23dca6988113 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/nfs_idmap.h>
 #include <linux/vfs.h>
 #include <linux/namei.h>
-#include <linux/mnt_namespace.h>
 #include <linux/security.h>
 
 #include <asm/system.h>
index 64f87194d3907620709c5413f23c95324b23afd9..bd7938eda6a8258a6e3ced41f495b78ab57afb3d 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/nfs_mount.h>
 #include <linux/nfs4_mount.h>
 #include <linux/lockd/bind.h>
-#include <linux/smp_lock.h>
 #include <linux/seq_file.h>
 #include <linux/mount.h>
 #include <linux/nfs_idmap.h>
index 61bc3a32e1e25780c4b9aa896814e22945fc2842..6ea07a3c75d4942f6197e54791b7504502d3f54c 100644 (file)
@@ -220,6 +220,7 @@ extern void nfs4_destroy_session(struct nfs4_session *session);
 extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
 extern int nfs4_proc_create_session(struct nfs_client *, int reset);
 extern int nfs4_proc_destroy_session(struct nfs4_session *);
+extern int nfs4_init_session(struct nfs_server *server);
 #else /* CONFIG_NFS_v4_1 */
 static inline int nfs4_setup_sequence(struct nfs_client *clp,
                struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
@@ -227,6 +228,11 @@ static inline int nfs4_setup_sequence(struct nfs_client *clp,
 {
        return 0;
 }
+
+static inline int nfs4_init_session(struct nfs_server *server)
+{
+       return 0;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 extern struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[];
index 92ce4351781459e648958e58c0cf59d106b3bc5c..6917311f201c32d679772337e440ba21e807a04b 100644 (file)
@@ -45,7 +45,6 @@
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
-#include <linux/smp_lock.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/module.h>
@@ -2041,15 +2040,9 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
                .rpc_argp = &args,
                .rpc_resp = &res,
        };
-       int status;
 
        nfs_fattr_init(info->fattr);
-       status = nfs4_recover_expired_lease(server);
-       if (!status)
-               status = nfs4_check_client_ready(server->nfs_client);
-       if (!status)
-               status = nfs4_call_sync(server, &msg, &args, &res, 0);
-       return status;
+       return nfs4_call_sync(server, &msg, &args, &res, 0);
 }
 
 static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -4100,15 +4093,23 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
        if (request->fl_start < 0 || request->fl_end < 0)
                return -EINVAL;
 
-       if (IS_GETLK(cmd))
-               return nfs4_proc_getlk(state, F_GETLK, request);
+       if (IS_GETLK(cmd)) {
+               if (state != NULL)
+                       return nfs4_proc_getlk(state, F_GETLK, request);
+               return 0;
+       }
 
        if (!(IS_SETLK(cmd) || IS_SETLKW(cmd)))
                return -EINVAL;
 
-       if (request->fl_type == F_UNLCK)
-               return nfs4_proc_unlck(state, cmd, request);
+       if (request->fl_type == F_UNLCK) {
+               if (state != NULL)
+                       return nfs4_proc_unlck(state, cmd, request);
+               return 0;
+       }
 
+       if (state == NULL)
+               return -ENOLCK;
        do {
                status = nfs4_proc_setlk(state, cmd, request);
                if ((status != -EAGAIN) || IS_SETLK(cmd))
@@ -4794,6 +4795,22 @@ int nfs4_proc_destroy_session(struct nfs4_session *session)
        return status;
 }
 
+int nfs4_init_session(struct nfs_server *server)
+{
+       struct nfs_client *clp = server->nfs_client;
+       int ret;
+
+       if (!nfs4_has_session(clp))
+               return 0;
+
+       clp->cl_session->fc_attrs.max_rqst_sz = server->wsize;
+       clp->cl_session->fc_attrs.max_resp_sz = server->rsize;
+       ret = nfs4_recover_expired_lease(server);
+       if (!ret)
+               ret = nfs4_check_client_ready(clp);
+       return ret;
+}
+
 /*
  * Renew the cl_session lease.
  */
index b73c5a728655adef0a90751b18133c75895aac0c..1434080aefeb22e77896c4f2a18f26e77df535bc 100644 (file)
@@ -553,6 +553,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
        INIT_LIST_HEAD(&lsp->ls_sequence.list);
        lsp->ls_seqid.sequence = &lsp->ls_sequence;
        atomic_set(&lsp->ls_count, 1);
+       lsp->ls_state = state;
        lsp->ls_owner = fl_owner;
        spin_lock(&clp->cl_lock);
        nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64);
@@ -587,7 +588,6 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_
                if (lsp != NULL)
                        break;
                if (new != NULL) {
-                       new->ls_state = state;
                        list_add(&new->ls_locks, &state->lock_states);
                        set_bit(LK_STATE_IN_USE, &state->flags);
                        lsp = new;
@@ -1250,8 +1250,8 @@ static void nfs4_state_manager(struct nfs_client *clp)
                                continue;
                }
                /* Initialize or reset the session */
-               if (nfs4_has_session(clp) &&
-                  test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) {
+               if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)
+                  && nfs4_has_session(clp)) {
                        if (clp->cl_cons_state == NFS_CS_SESSION_INITING)
                                status = nfs4_initialize_session(clp);
                        else
index 96c4ebfa46f4f8892b125fcf59bdb300cc2f01ad..12c9e66d3f1d9739147573ecd00cbc703f9f70a8 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/sunrpc/clnt.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
-#include <linux/smp_lock.h>
 
 #include <asm/system.h>
 
@@ -61,17 +60,15 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
        return p;
 }
 
-static void nfs_readdata_free(struct nfs_read_data *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)
+static void nfs_readdata_release(struct nfs_read_data *rdata)
 {
-       struct nfs_read_data *rdata = data;
-
        put_nfs_open_context(rdata->args.context);
        nfs_readdata_free(rdata);
 }
index ce728829f79a5dce2b238ccbe763631adec71343..a34fae21fe109c8dc9fd8a90e8b8123b937d5ee3 100644 (file)
@@ -87,17 +87,15 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
        return p;
 }
 
-static void nfs_writedata_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_wdata_mempool);
 }
 
-void nfs_writedata_release(void *data)
+static void nfs_writedata_release(struct nfs_write_data *wdata)
 {
-       struct nfs_write_data *wdata = data;
-
        put_nfs_open_context(wdata->args.context);
        nfs_writedata_free(wdata);
 }
@@ -202,8 +200,10 @@ static int nfs_set_page_writeback(struct page *page)
                struct nfs_server *nfss = NFS_SERVER(inode);
 
                if (atomic_long_inc_return(&nfss->writeback) >
-                               NFS_CONGESTION_ON_THRESH)
-                       set_bdi_congested(&nfss->backing_dev_info, WRITE);
+                               NFS_CONGESTION_ON_THRESH) {
+                       set_bdi_congested(&nfss->backing_dev_info,
+                                               BLK_RW_ASYNC);
+               }
        }
        return ret;
 }
@@ -215,7 +215,7 @@ static void nfs_end_page_writeback(struct page *page)
 
        end_page_writeback(page);
        if (atomic_long_dec_return(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH)
-               clear_bdi_congested(&nfss->backing_dev_info, WRITE);
+               clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC);
 }
 
 /*
index 1250fb978ac1451b8d00f87bfe5183eb12d9f26f..6d0847562d876374a6e5ba838651af37c00aad2d 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/init.h>
 #include <linux/inet.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/ctype.h>
 
 #include <linux/nfs.h>
index d4c9884cd54b2bf680cc2360eaa1a9f20dec8b55..492c79b7800b5b7fcb4f8a8813b2d369a5039d7a 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/unistd.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/freezer.h>
 #include <linux/fs_struct.h>
 #include <linux/kthread.h>
index 4145083dcf8817ed883652939cac1faa4dfd7cac..23341c1063bcd05fb2841dc6b49d0a91eef36293 100644 (file)
@@ -678,7 +678,6 @@ __be32
 nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
                        int access, struct file **filp)
 {
-       const struct cred *cred = current_cred();
        struct dentry   *dentry;
        struct inode    *inode;
        int             flags = O_RDONLY|O_LARGEFILE;
@@ -733,7 +732,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
                vfs_dq_init(inode);
        }
        *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt),
-                           flags, cred);
+                           flags, current_cred());
        if (IS_ERR(*filp))
                host_err = PTR_ERR(*filp);
        else
diff --git a/fs/nilfs2/Kconfig b/fs/nilfs2/Kconfig
new file mode 100644 (file)
index 0000000..72da095
--- /dev/null
@@ -0,0 +1,25 @@
+config NILFS2_FS
+       tristate "NILFS2 file system support (EXPERIMENTAL)"
+       depends on BLOCK && EXPERIMENTAL
+       select CRC32
+       help
+         NILFS2 is a log-structured file system (LFS) supporting continuous
+         snapshotting.  In addition to versioning capability of the entire
+         file system, users can even restore files mistakenly overwritten or
+         destroyed just a few seconds ago.  Since this file system can keep
+         consistency like conventional LFS, it achieves quick recovery after
+         system crashes.
+
+         NILFS2 creates a number of checkpoints every few seconds or per
+         synchronous write basis (unless there is no change).  Users can
+         select significant versions among continuously created checkpoints,
+         and can change them into snapshots which will be preserved for long
+         periods until they are changed back to checkpoints.  Each
+         snapshot is mountable as a read-only file system concurrently with
+         its writable mount, and this feature is convenient for online backup.
+
+         Some features including atime, extended attributes, and POSIX ACLs,
+         are not supported yet.
+
+         To compile this file system support as a module, choose M here: the
+         module will be called nilfs2.  If unsure, say N.
index 36df60b6d8a4b79e9fde8f0f58e3a76ee8d0a1f4..99d58a028b94c3c9698661bac527e14ed2812a72 100644 (file)
@@ -568,6 +568,7 @@ void nilfs_bmap_abort_update_v(struct nilfs_bmap *bmap,
 }
 
 static struct lock_class_key nilfs_bmap_dat_lock_key;
+static struct lock_class_key nilfs_bmap_mdt_lock_key;
 
 /**
  * nilfs_bmap_read - read a bmap from an inode
@@ -603,7 +604,11 @@ int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode)
                bmap->b_ptr_type = NILFS_BMAP_PTR_VS;
                bmap->b_last_allocated_key = 0;
                bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
+               lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key);
                break;
+       case NILFS_IFILE_INO:
+               lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key);
+               /* Fall through */
        default:
                bmap->b_ptr_type = NILFS_BMAP_PTR_VM;
                bmap->b_last_allocated_key = 0;
index 7e0b61be212e8a18476518db9507d2d018f7fed6..c668bca579c1baca6c25fc345462d881b227edb4 100644 (file)
@@ -209,6 +209,7 @@ int nilfs_btnode_prepare_change_key(struct address_space *btnc,
                 * We cannot call radix_tree_preload for the kernels older
                 * than 2.6.23, because it is not exported for modules.
                 */
+retry:
                err = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
                if (err)
                        goto failed_unlock;
@@ -219,7 +220,6 @@ int nilfs_btnode_prepare_change_key(struct address_space *btnc,
                                       (unsigned long long)oldkey,
                                       (unsigned long long)newkey);
 
-retry:
                spin_lock_irq(&btnc->tree_lock);
                err = radix_tree_insert(&btnc->page_tree, newkey, obh->b_page);
                spin_unlock_irq(&btnc->tree_lock);
index 7d49813f66d6c157d95c9ec8f6568379fa71565c..aec942cf79e34cc35764d270e645fd3f24a29229 100644 (file)
@@ -307,7 +307,7 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile,
                ret = nilfs_cpfile_get_checkpoint_block(cpfile, cno, 0, &cp_bh);
                if (ret < 0) {
                        if (ret != -ENOENT)
-                               goto out_header;
+                               break;
                        /* skip hole */
                        ret = 0;
                        continue;
@@ -340,7 +340,7 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile,
                                        continue;
                                printk(KERN_ERR "%s: cannot delete block\n",
                                       __func__);
-                               goto out_header;
+                               break;
                        }
                }
 
@@ -358,7 +358,6 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile,
                kunmap_atomic(kaddr, KM_USER0);
        }
 
- out_header:
        brelse(header_bh);
 
  out_sem:
index 0b2710e2d56547ac7aa36b6367e5ed6f36685c49..8927ca27e6f79cbd82db5028d5dfd002baa99bb0 100644 (file)
@@ -134,15 +134,6 @@ void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req,
        entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr,
                                             req->pr_entry_bh, kaddr);
        entry->de_start = cpu_to_le64(nilfs_mdt_cno(dat));
-       if (entry->de_blocknr != cpu_to_le64(0) ||
-           entry->de_end != cpu_to_le64(NILFS_CNO_MAX)) {
-               printk(KERN_CRIT
-                      "%s: vbn = %llu, start = %llu, end = %llu, pbn = %llu\n",
-                      __func__, (unsigned long long)req->pr_entry_nr,
-                      (unsigned long long)le64_to_cpu(entry->de_start),
-                      (unsigned long long)le64_to_cpu(entry->de_end),
-                      (unsigned long long)le64_to_cpu(entry->de_blocknr));
-       }
        entry->de_blocknr = cpu_to_le64(blocknr);
        kunmap_atomic(kaddr, KM_USER0);
 
index 54100acc1102706ed6c39116b89f7fbaa6c72f02..1a4fa04cf071bd8a82ae9f21d079612e963b419b 100644 (file)
@@ -43,7 +43,6 @@
  */
 
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 #include "nilfs.h"
 #include "page.h"
 
index 3d3ddb3f51775301533daf55ff21e331a360ff63..2dfd47714ae5b7329448b107cebd1614989e6e89 100644 (file)
@@ -412,8 +412,10 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc)
                return 0; /* Do not request flush for shadow page cache */
        if (!sb) {
                writer = nilfs_get_writer(NILFS_MDT(inode)->mi_nilfs);
-               if (!writer)
+               if (!writer) {
+                       nilfs_put_writer(NILFS_MDT(inode)->mi_nilfs);
                        return -EROFS;
+               }
                sb = writer->s_super;
        }
 
index aa977549919ecd2d92d40ff3d3d4f17f207f4814..51ff3d0a4ee256445f8ddbe9e85d7ff2ae2a7798 100644 (file)
@@ -1829,26 +1829,13 @@ static int nilfs_segctor_write(struct nilfs_sc_info *sci,
                err = nilfs_segbuf_write(segbuf, &wi);
 
                res = nilfs_segbuf_wait(segbuf, &wi);
-               err = unlikely(err) ? : res;
-               if (unlikely(err))
+               err = err ? : res;
+               if (err)
                        return err;
        }
        return 0;
 }
 
-static int nilfs_page_has_uncleared_buffer(struct page *page)
-{
-       struct buffer_head *head, *bh;
-
-       head = bh = page_buffers(page);
-       do {
-               if (buffer_dirty(bh) && !list_empty(&bh->b_assoc_buffers))
-                       return 1;
-               bh = bh->b_this_page;
-       } while (bh != head);
-       return 0;
-}
-
 static void __nilfs_end_page_io(struct page *page, int err)
 {
        if (!err) {
@@ -1872,13 +1859,26 @@ static void nilfs_end_page_io(struct page *page, int err)
        if (!page)
                return;
 
-       if (buffer_nilfs_node(page_buffers(page)) &&
-           nilfs_page_has_uncleared_buffer(page))
-               /* For b-tree node pages, this function may be called twice
-                  or more because they might be split in a segment.
-                  This check assures that cleanup has been done for all
-                  buffers in a split btnode page. */
+       if (buffer_nilfs_node(page_buffers(page)) && !PageWriteback(page)) {
+               /*
+                * For b-tree node pages, this function may be called twice
+                * or more because they might be split in a segment.
+                */
+               if (PageDirty(page)) {
+                       /*
+                        * For pages holding split b-tree node buffers, dirty
+                        * flag on the buffers may be cleared discretely.
+                        * In that case, the page is once redirtied for
+                        * remaining buffers, and it must be cancelled if
+                        * all the buffers get cleaned later.
+                        */
+                       lock_page(page);
+                       if (nilfs_page_buffers_clean(page))
+                               __nilfs_clear_page_dirty(page);
+                       unlock_page(page);
+               }
                return;
+       }
 
        __nilfs_end_page_io(page, err);
 }
@@ -1940,7 +1940,7 @@ static void nilfs_segctor_abort_write(struct nilfs_sc_info *sci,
                        }
                        if (bh->b_page != fs_page) {
                                nilfs_end_page_io(fs_page, err);
-                               if (unlikely(fs_page == failed_page))
+                               if (fs_page && fs_page == failed_page)
                                        goto done;
                                fs_page = bh->b_page;
                        }
index 8e2ec43b18f4f458b6f683fc94a9f656a36a9c3a..151964f0de4c1e475f0c89222928d82e5ac45684 100644 (file)
@@ -416,8 +416,10 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno)
        if (unlikely(err))
                goto failed;
 
+       down_read(&nilfs->ns_segctor_sem);
        err = nilfs_cpfile_get_checkpoint(nilfs->ns_cpfile, cno, 0, &raw_cp,
                                          &bh_cp);
+       up_read(&nilfs->ns_segctor_sem);
        if (unlikely(err)) {
                if (err == -ENOENT || err == -EINVAL) {
                        printk(KERN_ERR
index e8adbffc626f0547e3484aeef7cf96bfaa9d4e4d..1b9caafb866270a78c0d7e61cf4fb741f2a71a84 100644 (file)
@@ -253,7 +253,7 @@ nilfs_detach_writer(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
 
 static inline void nilfs_put_sbinfo(struct nilfs_sb_info *sbi)
 {
-       if (!atomic_dec_and_test(&sbi->s_count))
+       if (atomic_dec_and_test(&sbi->s_count))
                kfree(sbi);
 }
 
index 31dac7e3b0f10c9e5eff17eb815bdbdfb36b2dbf..dffbb0911d022cea33b599aecb336f481a2a8741 100644 (file)
@@ -1,15 +1,5 @@
 config FSNOTIFY
-       bool "Filesystem notification backend"
-       default y
-       ---help---
-          fsnotify is a backend for filesystem notification.  fsnotify does
-          not provide any userspace interface but does provide the basis
-          needed for other notification schemes such as dnotify, inotify,
-          and fanotify.
-
-          Say Y here to enable fsnotify suport.
-
-          If unsure, say Y.
+       def_bool n
 
 source "fs/notify/dnotify/Kconfig"
 source "fs/notify/inotify/Kconfig"
index 904ff8d5405a04e5fd2a3cb38e8089f66aa5d622..f9c1ca139d8f6d3f134b1068dfef46e6058b5115 100644 (file)
@@ -1,6 +1,6 @@
 config DNOTIFY
        bool "Dnotify support"
-       depends on FSNOTIFY
+       select FSNOTIFY
        default y
        help
          Dnotify is a directory-based per-fd file change notification system
index ec2f7bd76818411b7a64b2784e86abec2eb9611b..037e878e03fcac70005fd6da12f776c76d89b38f 100644 (file)
@@ -159,7 +159,9 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const
                        if (!group->ops->should_send_event(group, to_tell, mask))
                                continue;
                        if (!event) {
-                               event = fsnotify_create_event(to_tell, mask, data, data_is, file_name, cookie);
+                               event = fsnotify_create_event(to_tell, mask, data,
+                                                             data_is, file_name, cookie,
+                                                             GFP_KERNEL);
                                /* shit, we OOM'd and now we can't tell, maybe
                                 * someday someone else will want to do something
                                 * here */
index 5356884289a155d8375ef8315c41cea50e64781e..3e56dbffe7294421e58c17184d98b817c867ac0e 100644 (file)
@@ -15,7 +15,7 @@ config INOTIFY
 
 config INOTIFY_USER
        bool "Inotify support for userspace"
-       depends on FSNOTIFY
+       select FSNOTIFY
        default y
        ---help---
          Say Y here to enable inotify support for userspace, including the
index 47cd258fd24d8dc2588b68759608205b87387891..c9ee67b442e17b7713c8d1ca481b0ec22271b0f8 100644 (file)
@@ -62,13 +62,14 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev
        event_priv->wd = wd;
 
        ret = fsnotify_add_notify_event(group, event, fsn_event_priv);
-       /* EEXIST is not an error */
-       if (ret == -EEXIST)
-               ret = 0;
-
-       /* did event_priv get attached? */
-       if (list_empty(&fsn_event_priv->event_list))
+       if (ret) {
                inotify_free_event_priv(fsn_event_priv);
+               /* EEXIST says we tail matched, EOVERFLOW isn't something
+                * to report up the stack. */
+               if ((ret == -EEXIST) ||
+                   (ret == -EOVERFLOW))
+                       ret = 0;
+       }
 
        /*
         * If we hold the entry until after the event is on the queue
@@ -104,16 +105,45 @@ static bool inotify_should_send_event(struct fsnotify_group *group, struct inode
        return send;
 }
 
+/*
+ * This is NEVER supposed to be called.  Inotify marks should either have been
+ * removed from the idr when the watch was removed or in the
+ * fsnotify_destroy_mark_by_group() call when the inotify instance was being
+ * torn down.  This is only called if the idr is about to be freed but there
+ * are still marks in it.
+ */
 static int idr_callback(int id, void *p, void *data)
 {
-       BUG();
+       struct fsnotify_mark_entry *entry;
+       struct inotify_inode_mark_entry *ientry;
+       static bool warned = false;
+
+       if (warned)
+               return 0;
+
+       warned = false;
+       entry = p;
+       ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry);
+
+       WARN(1, "inotify closing but id=%d for entry=%p in group=%p still in "
+               "idr.  Probably leaking memory\n", id, p, data);
+
+       /*
+        * I'm taking the liberty of assuming that the mark in question is a
+        * valid address and I'm dereferencing it.  This might help to figure
+        * out why we got here and the panic is no worse than the original
+        * BUG() that was here.
+        */
+       if (entry)
+               printk(KERN_WARNING "entry->group=%p inode=%p wd=%d\n",
+                       entry->group, entry->inode, ientry->wd);
        return 0;
 }
 
 static void inotify_free_group_priv(struct fsnotify_group *group)
 {
        /* ideally the idr is empty and we won't hit the BUG in teh callback */
-       idr_for_each(&group->inotify_data.idr, idr_callback, NULL);
+       idr_for_each(&group->inotify_data.idr, idr_callback, group);
        idr_remove_all(&group->inotify_data.idr);
        idr_destroy(&group->inotify_data.idr);
 }
index ff231ad23895ea179a5507ace2e4ca5c54db1470..dcd2040d330c4397d8cfdaa78a9c27dd990fe9ad 100644 (file)
@@ -47,9 +47,6 @@
 
 static struct vfsmount *inotify_mnt __read_mostly;
 
-/* this just sits here and wastes global memory.  used to just pad userspace messages with zeros */
-static struct inotify_event nul_inotify_event;
-
 /* these are configurable via /proc/sys/fs/inotify/ */
 static int inotify_max_user_instances __read_mostly;
 static int inotify_max_queued_events __read_mostly;
@@ -57,7 +54,6 @@ int inotify_max_user_watches __read_mostly;
 
 static struct kmem_cache *inotify_inode_mark_cachep __read_mostly;
 struct kmem_cache *event_priv_cachep __read_mostly;
-static struct fsnotify_event *inotify_ignored_event;
 
 /*
  * When inotify registers a new group it increments this and uses that
@@ -158,7 +154,8 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group,
 
        event = fsnotify_peek_notify_event(group);
 
-       event_size += roundup(event->name_len, event_size);
+       if (event->name_len)
+               event_size += roundup(event->name_len + 1, event_size);
 
        if (event_size > count)
                return ERR_PTR(-EINVAL);
@@ -184,7 +181,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
        struct fsnotify_event_private_data *fsn_priv;
        struct inotify_event_private_data *priv;
        size_t event_size = sizeof(struct inotify_event);
-       size_t name_len;
+       size_t name_len = 0;
 
        /* we get the inotify watch descriptor from the event private data */
        spin_lock(&event->lock);
@@ -200,8 +197,12 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
                inotify_free_event_priv(fsn_priv);
        }
 
-       /* round up event->name_len so it is a multiple of event_size */
-       name_len = roundup(event->name_len, event_size);
+       /*
+        * round up event->name_len so it is a multiple of event_size
+        * plus an extra byte for the terminating '\0'.
+        */
+       if (event->name_len)
+               name_len = roundup(event->name_len + 1, event_size);
        inotify_event.len = name_len;
 
        inotify_event.mask = inotify_mask_to_arg(event->mask);
@@ -225,8 +226,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
                        return -EFAULT;
                buf += event->name_len;
 
-               /* fill userspace with 0's from nul_inotify_event */
-               if (copy_to_user(buf, &nul_inotify_event, len_to_zero))
+               /* fill userspace with 0's */
+               if (clear_user(buf, len_to_zero))
                        return -EFAULT;
                buf += len_to_zero;
                event_size += name_len;
@@ -296,12 +297,15 @@ static int inotify_fasync(int fd, struct file *file, int on)
 static int inotify_release(struct inode *ignored, struct file *file)
 {
        struct fsnotify_group *group = file->private_data;
+       struct user_struct *user = group->inotify_data.user;
 
        fsnotify_clear_marks_by_group(group);
 
        /* free this group, matching get was inotify_init->fsnotify_obtain_group */
        fsnotify_put_group(group);
 
+       atomic_dec(&user->inotify_devs);
+
        return 0;
 }
 
@@ -324,8 +328,9 @@ static long inotify_ioctl(struct file *file, unsigned int cmd,
                list_for_each_entry(holder, &group->notification_list, event_list) {
                        event = holder->event;
                        send_len += sizeof(struct inotify_event);
-                       send_len += roundup(event->name_len,
-                                            sizeof(struct inotify_event));
+                       if (event->name_len)
+                               send_len += roundup(event->name_len + 1,
+                                               sizeof(struct inotify_event));
                }
                mutex_unlock(&group->notification_mutex);
                ret = put_user(send_len, (int __user *) p);
@@ -363,20 +368,71 @@ static int inotify_find_inode(const char __user *dirname, struct path *path, uns
 }
 
 /*
- * Send IN_IGNORED for this wd, remove this wd from the idr, and drop the
- * internal reference help on the mark because it is in the idr.
+ * Remove the mark from the idr (if present) and drop the reference
+ * on the mark because it was in the idr.
+ */
+static void inotify_remove_from_idr(struct fsnotify_group *group,
+                                   struct inotify_inode_mark_entry *ientry)
+{
+       struct idr *idr;
+       struct fsnotify_mark_entry *entry;
+       struct inotify_inode_mark_entry *found_ientry;
+       int wd;
+
+       spin_lock(&group->inotify_data.idr_lock);
+       idr = &group->inotify_data.idr;
+       wd = ientry->wd;
+
+       if (wd == -1)
+               goto out;
+
+       entry = idr_find(&group->inotify_data.idr, wd);
+       if (unlikely(!entry))
+               goto out;
+
+       found_ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry);
+       if (unlikely(found_ientry != ientry)) {
+               /* We found an entry in the idr with the right wd, but it's
+                * not the entry we were told to remove.  eparis seriously
+                * fucked up somewhere. */
+               WARN_ON(1);
+               ientry->wd = -1;
+               goto out;
+       }
+
+       /* One ref for being in the idr, one ref held by the caller */
+       BUG_ON(atomic_read(&entry->refcnt) < 2);
+
+       idr_remove(idr, wd);
+       ientry->wd = -1;
+
+       /* removed from the idr, drop that ref */
+       fsnotify_put_mark(entry);
+out:
+       spin_unlock(&group->inotify_data.idr_lock);
+}
+
+/*
+ * Send IN_IGNORED for this wd, remove this wd from the idr.
  */
 void inotify_ignored_and_remove_idr(struct fsnotify_mark_entry *entry,
                                    struct fsnotify_group *group)
 {
        struct inotify_inode_mark_entry *ientry;
+       struct fsnotify_event *ignored_event;
        struct inotify_event_private_data *event_priv;
        struct fsnotify_event_private_data *fsn_event_priv;
-       struct idr *idr;
+       int ret;
+
+       ignored_event = fsnotify_create_event(NULL, FS_IN_IGNORED, NULL,
+                                             FSNOTIFY_EVENT_NONE, NULL, 0,
+                                             GFP_NOFS);
+       if (!ignored_event)
+               return;
 
        ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry);
 
-       event_priv = kmem_cache_alloc(event_priv_cachep, GFP_KERNEL);
+       event_priv = kmem_cache_alloc(event_priv_cachep, GFP_NOFS);
        if (unlikely(!event_priv))
                goto skip_send_ignore;
 
@@ -385,22 +441,19 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark_entry *entry,
        fsn_event_priv->group = group;
        event_priv->wd = ientry->wd;
 
-       fsnotify_add_notify_event(group, inotify_ignored_event, fsn_event_priv);
-
-       /* did the private data get added? */
-       if (list_empty(&fsn_event_priv->event_list))
+       ret = fsnotify_add_notify_event(group, ignored_event, fsn_event_priv);
+       if (ret)
                inotify_free_event_priv(fsn_event_priv);
 
 skip_send_ignore:
 
+       /* matches the reference taken when the event was created */
+       fsnotify_put_event(ignored_event);
+
        /* remove this entry from the idr */
-       spin_lock(&group->inotify_data.idr_lock);
-       idr = &group->inotify_data.idr;
-       idr_remove(idr, ientry->wd);
-       spin_unlock(&group->inotify_data.idr_lock);
+       inotify_remove_from_idr(group, ientry);
 
-       /* removed from idr, drop that reference */
-       fsnotify_put_mark(entry);
+       atomic_dec(&group->inotify_data.user->inotify_watches);
 }
 
 /* ding dong the mark is dead */
@@ -411,67 +464,29 @@ static void inotify_free_mark(struct fsnotify_mark_entry *entry)
        kmem_cache_free(inotify_inode_mark_cachep, ientry);
 }
 
-static int inotify_update_watch(struct fsnotify_group *group, struct inode *inode, u32 arg)
+static int inotify_update_existing_watch(struct fsnotify_group *group,
+                                        struct inode *inode,
+                                        u32 arg)
 {
-       struct fsnotify_mark_entry *entry = NULL;
+       struct fsnotify_mark_entry *entry;
        struct inotify_inode_mark_entry *ientry;
-       int ret = 0;
-       int add = (arg & IN_MASK_ADD);
-       __u32 mask;
        __u32 old_mask, new_mask;
+       __u32 mask;
+       int add = (arg & IN_MASK_ADD);
+       int ret;
 
        /* don't allow invalid bits: we don't want flags set */
        mask = inotify_arg_to_mask(arg);
        if (unlikely(!mask))
                return -EINVAL;
 
-       ientry = kmem_cache_alloc(inotify_inode_mark_cachep, GFP_KERNEL);
-       if (unlikely(!ientry))
-               return -ENOMEM;
-       /* we set the mask at the end after attaching it */
-       fsnotify_init_mark(&ientry->fsn_entry, inotify_free_mark);
-       ientry->wd = 0;
-
-find_entry:
        spin_lock(&inode->i_lock);
        entry = fsnotify_find_mark_entry(group, inode);
        spin_unlock(&inode->i_lock);
-       if (entry) {
-               kmem_cache_free(inotify_inode_mark_cachep, ientry);
-               ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry);
-       } else {
-               if (atomic_read(&group->inotify_data.user->inotify_watches) >= inotify_max_user_watches) {
-                       ret = -ENOSPC;
-                       goto out_err;
-               }
+       if (!entry)
+               return -ENOENT;
 
-               ret = fsnotify_add_mark(&ientry->fsn_entry, group, inode);
-               if (ret == -EEXIST)
-                       goto find_entry;
-               else if (ret)
-                       goto out_err;
-
-               entry = &ientry->fsn_entry;
-retry:
-               ret = -ENOMEM;
-               if (unlikely(!idr_pre_get(&group->inotify_data.idr, GFP_KERNEL)))
-                       goto out_err;
-
-               spin_lock(&group->inotify_data.idr_lock);
-               /* if entry is added to the idr we keep the reference obtained
-                * through fsnotify_mark_add.  remember to drop this reference
-                * when entry is removed from idr */
-               ret = idr_get_new_above(&group->inotify_data.idr, entry,
-                                       ++group->inotify_data.last_wd,
-                                       &ientry->wd);
-               spin_unlock(&group->inotify_data.idr_lock);
-               if (ret) {
-                       if (ret == -EAGAIN)
-                               goto retry;
-                       goto out_err;
-               }
-               atomic_inc(&group->inotify_data.user->inotify_watches);
-       }
+       ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry);
 
        spin_lock(&entry->lock);
 
@@ -503,14 +518,108 @@ retry:
                        fsnotify_recalc_group_mask(group);
        }
 
-       return ientry->wd;
+       /* return the wd */
+       ret = ientry->wd;
 
-out_err:
-       /* see this isn't supposed to happen, just kill the watch */
-       if (entry) {
-               fsnotify_destroy_mark_by_entry(entry);
-               fsnotify_put_mark(entry);
+       /* match the get from fsnotify_find_mark_entry() */
+       fsnotify_put_mark(entry);
+
+       return ret;
+}
+
+static int inotify_new_watch(struct fsnotify_group *group,
+                            struct inode *inode,
+                            u32 arg)
+{
+       struct inotify_inode_mark_entry *tmp_ientry;
+       __u32 mask;
+       int ret;
+
+       /* don't allow invalid bits: we don't want flags set */
+       mask = inotify_arg_to_mask(arg);
+       if (unlikely(!mask))
+               return -EINVAL;
+
+       tmp_ientry = kmem_cache_alloc(inotify_inode_mark_cachep, GFP_KERNEL);
+       if (unlikely(!tmp_ientry))
+               return -ENOMEM;
+
+       fsnotify_init_mark(&tmp_ientry->fsn_entry, inotify_free_mark);
+       tmp_ientry->fsn_entry.mask = mask;
+       tmp_ientry->wd = -1;
+
+       ret = -ENOSPC;
+       if (atomic_read(&group->inotify_data.user->inotify_watches) >= inotify_max_user_watches)
+               goto out_err;
+retry:
+       ret = -ENOMEM;
+       if (unlikely(!idr_pre_get(&group->inotify_data.idr, GFP_KERNEL)))
+               goto out_err;
+
+       spin_lock(&group->inotify_data.idr_lock);
+       ret = idr_get_new_above(&group->inotify_data.idr, &tmp_ientry->fsn_entry,
+                               group->inotify_data.last_wd,
+                               &tmp_ientry->wd);
+       spin_unlock(&group->inotify_data.idr_lock);
+       if (ret) {
+               /* idr was out of memory allocate and try again */
+               if (ret == -EAGAIN)
+                       goto retry;
+               goto out_err;
        }
+
+       /* we put the mark on the idr, take a reference */
+       fsnotify_get_mark(&tmp_ientry->fsn_entry);
+
+       /* we are on the idr, now get on the inode */
+       ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode);
+       if (ret) {
+               /* we failed to get on the inode, get off the idr */
+               inotify_remove_from_idr(group, tmp_ientry);
+               goto out_err;
+       }
+
+       /* update the idr hint, who cares about races, it's just a hint */
+       group->inotify_data.last_wd = tmp_ientry->wd;
+
+       /* increment the number of watches the user has */
+       atomic_inc(&group->inotify_data.user->inotify_watches);
+
+       /* return the watch descriptor for this new entry */
+       ret = tmp_ientry->wd;
+
+       /* match the ref from fsnotify_init_markentry() */
+       fsnotify_put_mark(&tmp_ientry->fsn_entry);
+
+       /* if this mark added a new event update the group mask */
+       if (mask & ~group->mask)
+               fsnotify_recalc_group_mask(group);
+
+out_err:
+       if (ret < 0)
+               kmem_cache_free(inotify_inode_mark_cachep, tmp_ientry);
+
+       return ret;
+}
+
+static int inotify_update_watch(struct fsnotify_group *group, struct inode *inode, u32 arg)
+{
+       int ret = 0;
+
+retry:
+       /* try to update and existing watch with the new arg */
+       ret = inotify_update_existing_watch(group, inode, arg);
+       /* no mark present, try to add a new one */
+       if (ret == -ENOENT)
+               ret = inotify_new_watch(group, inode, arg);
+       /*
+        * inotify_new_watch could race with another thread which did an
+        * inotify_new_watch between the update_existing and the add watch
+        * here, go back and try to update an existing mark again.
+        */
+       if (ret == -EEXIST)
+               goto retry;
+
        return ret;
 }
 
@@ -529,7 +638,7 @@ static struct fsnotify_group *inotify_new_group(struct user_struct *user, unsign
 
        spin_lock_init(&group->inotify_data.idr_lock);
        idr_init(&group->inotify_data.idr);
-       group->inotify_data.last_wd = 0;
+       group->inotify_data.last_wd = 1;
        group->inotify_data.user = user;
        group->inotify_data.fa = NULL;
 
@@ -718,9 +827,6 @@ static int __init inotify_user_setup(void)
 
        inotify_inode_mark_cachep = KMEM_CACHE(inotify_inode_mark_entry, SLAB_PANIC);
        event_priv_cachep = KMEM_CACHE(inotify_event_private_data, SLAB_PANIC);
-       inotify_ignored_event = fsnotify_create_event(NULL, FS_IN_IGNORED, NULL, FSNOTIFY_EVENT_NONE, NULL, 0);
-       if (!inotify_ignored_event)
-               panic("unable to allocate the inotify ignored event\n");
 
        inotify_max_queued_events = 16384;
        inotify_max_user_instances = 128;
index 959b73e756fd8f22219b80e8224fec7cadb3bace..3816d5750dd55eb6f8b2c710b6a017a4694b450c 100644 (file)
@@ -136,18 +136,28 @@ static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new
 {
        if ((old->mask == new->mask) &&
            (old->to_tell == new->to_tell) &&
-           (old->data_type == new->data_type)) {
+           (old->data_type == new->data_type) &&
+           (old->name_len == new->name_len)) {
                switch (old->data_type) {
                case (FSNOTIFY_EVENT_INODE):
-                       if (old->inode == new->inode)
+                       /* remember, after old was put on the wait_q we aren't
+                        * allowed to look at the inode any more, only thing
+                        * left to check was if the file_name is the same */
+                       if (old->name_len &&
+                           !strcmp(old->file_name, new->file_name))
                                return true;
                        break;
                case (FSNOTIFY_EVENT_PATH):
                        if ((old->path.mnt == new->path.mnt) &&
                            (old->path.dentry == new->path.dentry))
                                return true;
+                       break;
                case (FSNOTIFY_EVENT_NONE):
-                       return true;
+                       if (old->mask & FS_Q_OVERFLOW)
+                               return true;
+                       else if (old->mask & FS_IN_IGNORED)
+                               return false;
+                       return false;
                };
        }
        return false;
@@ -165,9 +175,7 @@ int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_even
        struct list_head *list = &group->notification_list;
        struct fsnotify_event_holder *last_holder;
        struct fsnotify_event *last_event;
-
-       /* easy to tell if priv was attached to the event */
-       INIT_LIST_HEAD(&priv->event_list);
+       int ret = 0;
 
        /*
         * There is one fsnotify_event_holder embedded inside each fsnotify_event.
@@ -188,6 +196,7 @@ alloc_holder:
 
        if (group->q_len >= group->max_events) {
                event = &q_overflow_event;
+               ret = -EOVERFLOW;
                /* sorry, no private data on the overflow event */
                priv = NULL;
        }
@@ -229,7 +238,7 @@ alloc_holder:
        mutex_unlock(&group->notification_mutex);
 
        wake_up(&group->notification_waitq);
-       return 0;
+       return ret;
 }
 
 /*
@@ -339,18 +348,19 @@ static void initialize_event(struct fsnotify_event *event)
  * @name the filename, if available
  */
 struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, void *data,
-                                            int data_type, const char *name, u32 cookie)
+                                            int data_type, const char *name, u32 cookie,
+                                            gfp_t gfp)
 {
        struct fsnotify_event *event;
 
-       event = kmem_cache_alloc(fsnotify_event_cachep, GFP_KERNEL);
+       event = kmem_cache_alloc(fsnotify_event_cachep, gfp);
        if (!event)
                return NULL;
 
        initialize_event(event);
 
        if (name) {
-               event->file_name = kstrdup(name, GFP_KERNEL);
+               event->file_name = kstrdup(name, gfp);
                if (!event->file_name) {
                        kmem_cache_free(fsnotify_event_cachep, event);
                        return NULL;
index 9edcde4974aa22a37841d8b22aac86c7e435cea6..ab513ddaeff2f6944c5f0d54356e7484fa63cfeb 100644 (file)
@@ -1914,7 +1914,8 @@ static void ocfs2_adjust_adjacent_records(struct ocfs2_extent_rec *left_rec,
         * immediately to their right.
         */
        left_clusters = le32_to_cpu(right_child_el->l_recs[0].e_cpos);
-       if (ocfs2_is_empty_extent(&right_child_el->l_recs[0])) {
+       if (!ocfs2_rec_clusters(right_child_el, &right_child_el->l_recs[0])) {
+               BUG_ON(right_child_el->l_tree_depth);
                BUG_ON(le16_to_cpu(right_child_el->l_next_free_rec) <= 1);
                left_clusters = le32_to_cpu(right_child_el->l_recs[1].e_cpos);
        }
@@ -2476,15 +2477,37 @@ out_ret_path:
        return ret;
 }
 
-static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
-                                     struct ocfs2_path *path)
+static int ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
+                                    int subtree_index, struct ocfs2_path *path)
 {
-       int i, idx;
+       int i, idx, ret;
        struct ocfs2_extent_rec *rec;
        struct ocfs2_extent_list *el;
        struct ocfs2_extent_block *eb;
        u32 range;
 
+       /*
+        * In normal tree rotation process, we will never touch the
+        * tree branch above subtree_index and ocfs2_extend_rotate_transaction
+        * doesn't reserve the credits for them either.
+        *
+        * But we do have a special case here which will update the rightmost
+        * records for all the bh in the path.
+        * So we have to allocate extra credits and access them.
+        */
+       ret = ocfs2_extend_trans(handle,
+                                handle->h_buffer_credits + subtree_index);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       ret = ocfs2_journal_access_path(inode, handle, path);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
        /* Path should always be rightmost. */
        eb = (struct ocfs2_extent_block *)path_leaf_bh(path)->b_data;
        BUG_ON(eb->h_next_leaf_blk != 0ULL);
@@ -2505,6 +2528,8 @@ static void ocfs2_update_edge_lengths(struct inode *inode, handle_t *handle,
 
                ocfs2_journal_dirty(handle, path->p_node[i].bh);
        }
+out:
+       return ret;
 }
 
 static void ocfs2_unlink_path(struct inode *inode, handle_t *handle,
@@ -2717,7 +2742,12 @@ static int ocfs2_rotate_subtree_left(struct inode *inode, handle_t *handle,
        if (del_right_subtree) {
                ocfs2_unlink_subtree(inode, handle, left_path, right_path,
                                     subtree_index, dealloc);
-               ocfs2_update_edge_lengths(inode, handle, left_path);
+               ret = ocfs2_update_edge_lengths(inode, handle, subtree_index,
+                                               left_path);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
 
                eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
                ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
@@ -3034,7 +3064,12 @@ static int ocfs2_remove_rightmost_path(struct inode *inode, handle_t *handle,
 
                ocfs2_unlink_subtree(inode, handle, left_path, path,
                                     subtree_index, dealloc);
-               ocfs2_update_edge_lengths(inode, handle, left_path);
+               ret = ocfs2_update_edge_lengths(inode, handle, subtree_index,
+                                               left_path);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
 
                eb = (struct ocfs2_extent_block *)path_leaf_bh(left_path)->b_data;
                ocfs2_et_set_last_eb_blk(et, le64_to_cpu(eb->h_blkno));
@@ -6816,7 +6851,7 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb,
        }
        status = 0;
 bail:
-
+       brelse(last_eb_bh);
        mlog_exit(status);
        return status;
 }
index b2c52b3a1484f1c57c4b098bf9706fe21c186ac0..8a1e61545f4169de491eb00ee6c661ebf0054a30 100644 (file)
@@ -193,6 +193,7 @@ static int ocfs2_get_block(struct inode *inode, sector_t iblock,
                             (unsigned long long)OCFS2_I(inode)->ip_blkno);
                        mlog(ML_ERROR, "Size %llu, clusters %u\n", (unsigned long long)i_size_read(inode), OCFS2_I(inode)->ip_clusters);
                        dump_stack();
+                       goto bail;
                }
 
                past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode));
@@ -894,18 +895,17 @@ struct ocfs2_write_cluster_desc {
         */
        unsigned        c_new;
        unsigned        c_unwritten;
+       unsigned        c_needs_zero;
 };
 
-static inline int ocfs2_should_zero_cluster(struct ocfs2_write_cluster_desc *d)
-{
-       return d->c_new || d->c_unwritten;
-}
-
 struct ocfs2_write_ctxt {
        /* Logical cluster position / len of write */
        u32                             w_cpos;
        u32                             w_clen;
 
+       /* First cluster allocated in a nonsparse extend */
+       u32                             w_first_new_cpos;
+
        struct ocfs2_write_cluster_desc w_desc[OCFS2_MAX_CLUSTERS_PER_PAGE];
 
        /*
@@ -983,6 +983,7 @@ static int ocfs2_alloc_write_ctxt(struct ocfs2_write_ctxt **wcp,
                return -ENOMEM;
 
        wc->w_cpos = pos >> osb->s_clustersize_bits;
+       wc->w_first_new_cpos = UINT_MAX;
        cend = (pos + len - 1) >> osb->s_clustersize_bits;
        wc->w_clen = cend - wc->w_cpos + 1;
        get_bh(di_bh);
@@ -1217,20 +1218,18 @@ out:
  */
 static int ocfs2_write_cluster(struct address_space *mapping,
                               u32 phys, unsigned int unwritten,
+                              unsigned int should_zero,
                               struct ocfs2_alloc_context *data_ac,
                               struct ocfs2_alloc_context *meta_ac,
                               struct ocfs2_write_ctxt *wc, u32 cpos,
                               loff_t user_pos, unsigned user_len)
 {
-       int ret, i, new, should_zero = 0;
+       int ret, i, new;
        u64 v_blkno, p_blkno;
        struct inode *inode = mapping->host;
        struct ocfs2_extent_tree et;
 
        new = phys == 0 ? 1 : 0;
-       if (new || unwritten)
-               should_zero = 1;
-
        if (new) {
                u32 tmp_pos;
 
@@ -1301,7 +1300,7 @@ static int ocfs2_write_cluster(struct address_space *mapping,
                if (tmpret) {
                        mlog_errno(tmpret);
                        if (ret == 0)
-                               tmpret = ret;
+                               ret = tmpret;
                }
        }
 
@@ -1341,7 +1340,9 @@ static int ocfs2_write_cluster_by_desc(struct address_space *mapping,
                        local_len = osb->s_clustersize - cluster_off;
 
                ret = ocfs2_write_cluster(mapping, desc->c_phys,
-                                         desc->c_unwritten, data_ac, meta_ac,
+                                         desc->c_unwritten,
+                                         desc->c_needs_zero,
+                                         data_ac, meta_ac,
                                          wc, desc->c_cpos, pos, local_len);
                if (ret) {
                        mlog_errno(ret);
@@ -1391,14 +1392,14 @@ static void ocfs2_set_target_boundaries(struct ocfs2_super *osb,
                 * newly allocated cluster.
                 */
                desc = &wc->w_desc[0];
-               if (ocfs2_should_zero_cluster(desc))
+               if (desc->c_needs_zero)
                        ocfs2_figure_cluster_boundaries(osb,
                                                        desc->c_cpos,
                                                        &wc->w_target_from,
                                                        NULL);
 
                desc = &wc->w_desc[wc->w_clen - 1];
-               if (ocfs2_should_zero_cluster(desc))
+               if (desc->c_needs_zero)
                        ocfs2_figure_cluster_boundaries(osb,
                                                        desc->c_cpos,
                                                        NULL,
@@ -1466,13 +1467,28 @@ static int ocfs2_populate_write_desc(struct inode *inode,
                        phys++;
                }
 
+               /*
+                * If w_first_new_cpos is < UINT_MAX, we have a non-sparse
+                * file that got extended.  w_first_new_cpos tells us
+                * where the newly allocated clusters are so we can
+                * zero them.
+                */
+               if (desc->c_cpos >= wc->w_first_new_cpos) {
+                       BUG_ON(phys == 0);
+                       desc->c_needs_zero = 1;
+               }
+
                desc->c_phys = phys;
                if (phys == 0) {
                        desc->c_new = 1;
+                       desc->c_needs_zero = 1;
                        *clusters_to_alloc = *clusters_to_alloc + 1;
                }
-               if (ext_flags & OCFS2_EXT_UNWRITTEN)
+
+               if (ext_flags & OCFS2_EXT_UNWRITTEN) {
                        desc->c_unwritten = 1;
+                       desc->c_needs_zero = 1;
+               }
 
                num_clusters--;
        }
@@ -1632,10 +1648,13 @@ static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos,
        if (newsize <= i_size_read(inode))
                return 0;
 
-       ret = ocfs2_extend_no_holes(inode, newsize, newsize - len);
+       ret = ocfs2_extend_no_holes(inode, newsize, pos);
        if (ret)
                mlog_errno(ret);
 
+       wc->w_first_new_cpos =
+               ocfs2_clusters_for_bytes(inode->i_sb, i_size_read(inode));
+
        return ret;
 }
 
@@ -1644,7 +1663,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
                             struct page **pagep, void **fsdata,
                             struct buffer_head *di_bh, struct page *mmap_page)
 {
-       int ret, credits = OCFS2_INODE_UPDATE_CREDITS;
+       int ret, cluster_of_pages, credits = OCFS2_INODE_UPDATE_CREDITS;
        unsigned int clusters_to_alloc, extents_to_split;
        struct ocfs2_write_ctxt *wc;
        struct inode *inode = mapping->host;
@@ -1722,8 +1741,19 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
 
        }
 
-       ocfs2_set_target_boundaries(osb, wc, pos, len,
-                                   clusters_to_alloc + extents_to_split);
+       /*
+        * We have to zero sparse allocated clusters, unwritten extent clusters,
+        * and non-sparse clusters we just extended.  For non-sparse writes,
+        * we know zeros will only be needed in the first and/or last cluster.
+        */
+       if (clusters_to_alloc || extents_to_split ||
+           (wc->w_clen && (wc->w_desc[0].c_needs_zero ||
+                           wc->w_desc[wc->w_clen - 1].c_needs_zero)))
+               cluster_of_pages = 1;
+       else
+               cluster_of_pages = 0;
+
+       ocfs2_set_target_boundaries(osb, wc, pos, len, cluster_of_pages);
 
        handle = ocfs2_start_trans(osb, credits);
        if (IS_ERR(handle)) {
@@ -1756,8 +1786,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
         * extent.
         */
        ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos,
-                                        clusters_to_alloc + extents_to_split,
-                                        mmap_page);
+                                        cluster_of_pages, mmap_page);
        if (ret) {
                mlog_errno(ret);
                goto out_quota;
index b574431a031d5cd9721de53c46a80825f752bb9d..b4957c7d9fe2262a203a3efb3573eda9ed3d2638 100644 (file)
@@ -85,6 +85,17 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry,
                goto bail;
        }
 
+       /*
+        * If the last lookup failed to create dentry lock, let us
+        * redo it.
+        */
+       if (!dentry->d_fsdata) {
+               mlog(0, "Inode %llu doesn't have dentry lock, "
+                    "returning false\n",
+                    (unsigned long long)OCFS2_I(inode)->ip_blkno);
+               goto bail;
+       }
+
        ret = 1;
 
 bail:
@@ -310,22 +321,19 @@ out_attach:
        return ret;
 }
 
-static DEFINE_SPINLOCK(dentry_list_lock);
+DEFINE_SPINLOCK(dentry_list_lock);
 
 /* We limit the number of dentry locks to drop in one go. We have
  * this limit so that we don't starve other users of ocfs2_wq. */
 #define DL_INODE_DROP_COUNT 64
 
 /* Drop inode references from dentry locks */
-void ocfs2_drop_dl_inodes(struct work_struct *work)
+static void __ocfs2_drop_dl_inodes(struct ocfs2_super *osb, int drop_count)
 {
-       struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
-                                              dentry_lock_work);
        struct ocfs2_dentry_lock *dl;
-       int drop_count = DL_INODE_DROP_COUNT;
 
        spin_lock(&dentry_list_lock);
-       while (osb->dentry_lock_list && drop_count--) {
+       while (osb->dentry_lock_list && (drop_count < 0 || drop_count--)) {
                dl = osb->dentry_lock_list;
                osb->dentry_lock_list = dl->dl_next;
                spin_unlock(&dentry_list_lock);
@@ -333,11 +341,32 @@ void ocfs2_drop_dl_inodes(struct work_struct *work)
                kfree(dl);
                spin_lock(&dentry_list_lock);
        }
-       if (osb->dentry_lock_list)
+       spin_unlock(&dentry_list_lock);
+}
+
+void ocfs2_drop_dl_inodes(struct work_struct *work)
+{
+       struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
+                                              dentry_lock_work);
+
+       __ocfs2_drop_dl_inodes(osb, DL_INODE_DROP_COUNT);
+       /*
+        * Don't queue dropping if umount is in progress. We flush the
+        * list in ocfs2_dismount_volume
+        */
+       spin_lock(&dentry_list_lock);
+       if (osb->dentry_lock_list &&
+           !ocfs2_test_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED))
                queue_work(ocfs2_wq, &osb->dentry_lock_work);
        spin_unlock(&dentry_list_lock);
 }
 
+/* Flush the whole work queue */
+void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb)
+{
+       __ocfs2_drop_dl_inodes(osb, -1);
+}
+
 /*
  * ocfs2_dentry_iput() and friends.
  *
@@ -368,7 +397,8 @@ static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
        /* We leave dropping of inode reference to ocfs2_wq as that can
         * possibly lead to inode deletion which gets tricky */
        spin_lock(&dentry_list_lock);
-       if (!osb->dentry_lock_list)
+       if (!osb->dentry_lock_list &&
+           !ocfs2_test_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED))
                queue_work(ocfs2_wq, &osb->dentry_lock_work);
        dl->dl_next = osb->dentry_lock_list;
        osb->dentry_lock_list = dl;
index faa12e75f98d117a9cf2f7f0bf519a05b83c5401..f5dd1789acf1b4527373217ce7c6b0374695eb17 100644 (file)
@@ -49,10 +49,13 @@ struct ocfs2_dentry_lock {
 int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode,
                             u64 parent_blkno);
 
+extern spinlock_t dentry_list_lock;
+
 void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
                           struct ocfs2_dentry_lock *dl);
 
 void ocfs2_drop_dl_inodes(struct work_struct *work);
+void ocfs2_drop_all_dl_inodes(struct ocfs2_super *osb);
 
 struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno,
                                      int skip_unhashed);
index d07ddbe4b2836d3e3e6d0f002808d8c36ef6c591..81eff8e583222747cc824ce02d6edde94378e711 100644 (file)
@@ -103,7 +103,6 @@ static void __dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock)
                     lock->ast_pending, lock->ml.type);
                BUG();
        }
-       BUG_ON(!list_empty(&lock->ast_list));
        if (lock->ast_pending)
                mlog(0, "lock has an ast getting flushed right now\n");
 
index bcb9260c37359a832c601f0c00e718094063af25..43e6e328056902a0fdd8cb98c7961b76a912c3dd 100644 (file)
@@ -1118,7 +1118,7 @@ static int dlm_send_mig_lockres_msg(struct dlm_ctxt *dlm,
 
        mlog(0, "%s:%.*s: sending mig lockres (%s) to %u\n",
             dlm->name, res->lockname.len, res->lockname.name,
-            orig_flags & DLM_MRES_MIGRATION ? "migrate" : "recovery",
+            orig_flags & DLM_MRES_MIGRATION ? "migration" : "recovery",
             send_to);
 
        /* send it */
index fcf879ed69308e9518d0504428d3afbe13ee9f8f..756f5b0998e0d4e389ffcda4b558f861094eeb91 100644 (file)
@@ -122,7 +122,7 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm,
         * that still has AST's pending... */
        in_use = !list_empty(&lock->ast_list);
        spin_unlock(&dlm->ast_lock);
-       if (in_use) {
+       if (in_use && !(flags & LKM_CANCEL)) {
               mlog(ML_ERROR, "lockres %.*s: Someone is calling dlmunlock "
                    "while waiting for an ast!", res->lockname.len,
                    res->lockname.name);
@@ -131,7 +131,7 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm,
 
        spin_lock(&res->spinlock);
        if (res->state & DLM_LOCK_RES_IN_PROGRESS) {
-               if (master_node) {
+               if (master_node && !(flags & LKM_CANCEL)) {
                        mlog(ML_ERROR, "lockres in progress!\n");
                        spin_unlock(&res->spinlock);
                        return DLM_FORWARD;
index 62442e413a001cfbe57607c43e06d408418cf13e..aa501d3f93f1bcec3af38a24361ab61cda2cc052 100644 (file)
@@ -1851,6 +1851,7 @@ relock:
                if (ret)
                        goto out_dio;
 
+               count = ocount;
                ret = generic_write_checks(file, ppos, &count,
                                           S_ISBLK(inode->i_mode));
                if (ret)
@@ -1918,8 +1919,10 @@ out_sems:
 
        mutex_unlock(&inode->i_mutex);
 
+       if (written)
+               ret = written;
        mlog_exit(ret);
-       return written ? written : ret;
+       return ret;
 }
 
 static int ocfs2_splice_to_file(struct pipe_inode_info *pipe,
index 9fcd36dcc9a05920e5cc3f2d4d001d5bc8a82120..467b413bec21e7b407f45a2adba2002e72504e72 100644 (file)
@@ -7,7 +7,6 @@
 
 #include <linux/fs.h>
 #include <linux/mount.h>
-#include <linux/smp_lock.h>
 
 #define MLOG_MASK_PREFIX ML_INODE
 #include <cluster/masklog.h>
index f033760ecbeaae0dde0944d190828aedb7b9c5d0..c48b93ac6b65c55bc2b90daf8b3efa1397b9b6e4 100644 (file)
@@ -1954,10 +1954,16 @@ void ocfs2_orphan_scan_init(struct ocfs2_super *osb)
        os->os_osb = osb;
        os->os_count = 0;
        os->os_seqno = 0;
-       os->os_scantime = CURRENT_TIME;
        mutex_init(&os->os_lock);
        INIT_DELAYED_WORK(&os->os_orphan_scan_work, ocfs2_orphan_scan_work);
+}
 
+void ocfs2_orphan_scan_start(struct ocfs2_super *osb)
+{
+       struct ocfs2_orphan_scan *os;
+
+       os = &osb->osb_orphan_scan;
+       os->os_scantime = CURRENT_TIME;
        if (ocfs2_is_hard_readonly(osb) || ocfs2_mount_local(osb))
                atomic_set(&os->os_state, ORPHAN_SCAN_INACTIVE);
        else {
index 5432c7f79cc6a959d3c39cd2cbcb41663ef599b5..2c3222aec6228a83b9acac2122e42beea94042fb 100644 (file)
@@ -145,6 +145,7 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb,
 
 /* Exported only for the journal struct init code in super.c. Do not call. */
 void ocfs2_orphan_scan_init(struct ocfs2_super *osb);
+void ocfs2_orphan_scan_start(struct ocfs2_super *osb);
 void ocfs2_orphan_scan_stop(struct ocfs2_super *osb);
 void ocfs2_orphan_scan_exit(struct ocfs2_super *osb);
 
@@ -329,20 +330,27 @@ int                  ocfs2_journal_dirty(handle_t *handle,
 /* extended attribute block update */
 #define OCFS2_XATTR_BLOCK_UPDATE_CREDITS 1
 
+/* Update of a single quota block */
+#define OCFS2_QUOTA_BLOCK_UPDATE_CREDITS 1
+
 /* global quotafile inode update, data block */
-#define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 1)
+#define OCFS2_QINFO_WRITE_CREDITS (OCFS2_INODE_UPDATE_CREDITS + \
+                                  OCFS2_QUOTA_BLOCK_UPDATE_CREDITS)
 
+#define OCFS2_LOCAL_QINFO_WRITE_CREDITS OCFS2_QUOTA_BLOCK_UPDATE_CREDITS
 /*
  * The two writes below can accidentally see global info dirty due
  * to set_info() quotactl so make them prepared for the writes.
  */
 /* quota data block, global info */
 /* Write to local quota file */
-#define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + 1)
+#define OCFS2_QWRITE_CREDITS (OCFS2_QINFO_WRITE_CREDITS + \
+                             OCFS2_QUOTA_BLOCK_UPDATE_CREDITS)
 
 /* global quota data block, local quota data block, global quota inode,
  * global quota info */
-#define OCFS2_QSYNC_CREDITS (OCFS2_INODE_UPDATE_CREDITS + 3)
+#define OCFS2_QSYNC_CREDITS (OCFS2_QINFO_WRITE_CREDITS + \
+                            2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS)
 
 static inline int ocfs2_quota_trans_credits(struct super_block *sb)
 {
@@ -355,11 +363,6 @@ static inline int ocfs2_quota_trans_credits(struct super_block *sb)
        return credits;
 }
 
-/* Number of credits needed for removing quota structure from file */
-int ocfs2_calc_qdel_credits(struct super_block *sb, int type);
-/* Number of credits needed for initialization of new quota structure */
-int ocfs2_calc_qinit_credits(struct super_block *sb, int type);
-
 /* group extend. inode update and last group update. */
 #define OCFS2_GROUP_EXTEND_CREDITS     (OCFS2_INODE_UPDATE_CREDITS + 1)
 
index c9345ebb849343873adf6b2b67ae226f8181f65e..39e1d5a39505221a458846ab37950c922d6da76b 100644 (file)
@@ -224,10 +224,12 @@ enum ocfs2_mount_options
        OCFS2_MOUNT_GRPQUOTA = 1 << 10, /* We support group quotas */
 };
 
-#define OCFS2_OSB_SOFT_RO      0x0001
-#define OCFS2_OSB_HARD_RO      0x0002
-#define OCFS2_OSB_ERROR_FS     0x0004
-#define OCFS2_DEFAULT_ATIME_QUANTUM    60
+#define OCFS2_OSB_SOFT_RO                      0x0001
+#define OCFS2_OSB_HARD_RO                      0x0002
+#define OCFS2_OSB_ERROR_FS                     0x0004
+#define OCFS2_OSB_DROP_DENTRY_LOCK_IMMED       0x0008
+
+#define OCFS2_DEFAULT_ATIME_QUANTUM            60
 
 struct ocfs2_journal;
 struct ocfs2_slot_info;
@@ -490,6 +492,18 @@ static inline void ocfs2_set_osb_flag(struct ocfs2_super *osb,
        spin_unlock(&osb->osb_lock);
 }
 
+
+static inline unsigned long  ocfs2_test_osb_flag(struct ocfs2_super *osb,
+                                                unsigned long flag)
+{
+       unsigned long ret;
+
+       spin_lock(&osb->osb_lock);
+       ret = osb->osb_flags & flag;
+       spin_unlock(&osb->osb_lock);
+       return ret;
+}
+
 static inline void ocfs2_set_ro_flag(struct ocfs2_super *osb,
                                     int hard)
 {
index fcdba091af3dd8be6706950e83a772049bf775b1..c212cf5a2bdf3ad9e8e6c02672f4b76189202f5a 100644 (file)
@@ -108,6 +108,7 @@ static char *ocfs2_lock_type_strings[] = {
        [OCFS2_LOCK_TYPE_OPEN] = "Open",
        [OCFS2_LOCK_TYPE_FLOCK] = "Flock",
        [OCFS2_LOCK_TYPE_QINFO] = "Quota",
+       [OCFS2_LOCK_TYPE_NFS_SYNC] = "NFSSync",
        [OCFS2_LOCK_TYPE_ORPHAN_SCAN] = "OrphanScan",
 };
 
index 7365e2e08706ef6ea07b5f034310f5fec6fd9e4a..3fb96fcd4c81cd185db0e7b5132f831c322dedca 100644 (file)
@@ -50,7 +50,6 @@ struct ocfs2_mem_dqinfo {
        unsigned int dqi_chunks;        /* Number of chunks in local quota file */
        unsigned int dqi_blocks;        /* Number of blocks allocated for local quota file */
        unsigned int dqi_syncms;        /* How often should we sync with other nodes */
-       unsigned int dqi_syncjiff;      /* Precomputed dqi_syncms in jiffies */
        struct list_head dqi_chunk;     /* List of chunks */
        struct inode *dqi_gqinode;      /* Global quota file inode */
        struct ocfs2_lock_res dqi_gqlock;       /* Lock protecting quota information structure */
index edfa60cd155c18e9ac67a1fe6ae1476900fed8b7..44f2a5e1d04233bae9fc5b72bf894cbdd67461f2 100644 (file)
@@ -23,6 +23,7 @@
 #include "sysfile.h"
 #include "dlmglue.h"
 #include "uptodate.h"
+#include "super.h"
 #include "quota.h"
 
 static struct workqueue_struct *ocfs2_quota_wq = NULL;
@@ -69,6 +70,7 @@ static void ocfs2_global_mem2diskdqb(void *dp, struct dquot *dquot)
        d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
        d->dqb_btime = cpu_to_le64(m->dqb_btime);
        d->dqb_itime = cpu_to_le64(m->dqb_itime);
+       d->dqb_pad1 = d->dqb_pad2 = 0;
 }
 
 static int ocfs2_global_is_id(void *dp, struct dquot *dquot)
@@ -113,6 +115,15 @@ int ocfs2_read_quota_block(struct inode *inode, u64 v_block,
        int rc = 0;
        struct buffer_head *tmp = *bh;
 
+       if (i_size_read(inode) >> inode->i_sb->s_blocksize_bits <= v_block) {
+               ocfs2_error(inode->i_sb,
+                           "Quota file %llu is probably corrupted! Requested "
+                           "to read block %Lu but file has size only %Lu\n",
+                           (unsigned long long)OCFS2_I(inode)->ip_blkno,
+                           (unsigned long long)v_block,
+                           (unsigned long long)i_size_read(inode));
+               return -EIO;
+       }
        rc = ocfs2_read_virt_blocks(inode, v_block, 1, &tmp, 0,
                                    ocfs2_validate_quota_block);
        if (rc)
@@ -211,14 +222,13 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type,
 
        mutex_lock_nested(&gqinode->i_mutex, I_MUTEX_QUOTA);
        if (gqinode->i_size < off + len) {
-               down_write(&OCFS2_I(gqinode)->ip_alloc_sem);
-               err = ocfs2_extend_no_holes(gqinode, off + len, off);
-               up_write(&OCFS2_I(gqinode)->ip_alloc_sem);
-               if (err < 0)
-                       goto out;
+               loff_t rounded_end =
+                               ocfs2_align_bytes_to_blocks(sb, off + len);
+
+               /* Space is already allocated in ocfs2_global_read_dquot() */
                err = ocfs2_simple_size_update(gqinode,
                                               oinfo->dqi_gqi_bh,
-                                              off + len);
+                                              rounded_end);
                if (err < 0)
                        goto out;
                new = 1;
@@ -234,7 +244,7 @@ ssize_t ocfs2_quota_write(struct super_block *sb, int type,
        }
        if (err) {
                mlog_errno(err);
-               return err;
+               goto out;
        }
        lock_buffer(bh);
        if (new)
@@ -342,7 +352,6 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
        info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
        info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
        oinfo->dqi_syncms = le32_to_cpu(dinfo.dqi_syncms);
-       oinfo->dqi_syncjiff = msecs_to_jiffies(oinfo->dqi_syncms);
        oinfo->dqi_gi.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
        oinfo->dqi_gi.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
        oinfo->dqi_gi.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
@@ -352,7 +361,7 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
        oinfo->dqi_gi.dqi_qtree_depth = qtree_depth(&oinfo->dqi_gi);
        INIT_DELAYED_WORK(&oinfo->dqi_sync_work, qsync_work_fn);
        queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
-                          oinfo->dqi_syncjiff);
+                          msecs_to_jiffies(oinfo->dqi_syncms));
 
 out_err:
        mlog_exit(status);
@@ -402,13 +411,36 @@ int ocfs2_global_write_info(struct super_block *sb, int type)
        return err;
 }
 
+static int ocfs2_global_qinit_alloc(struct super_block *sb, int type)
+{
+       struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
+
+       /*
+        * We may need to allocate tree blocks and a leaf block but not the
+        * root block
+        */
+       return oinfo->dqi_gi.dqi_qtree_depth;
+}
+
+static int ocfs2_calc_global_qinit_credits(struct super_block *sb, int type)
+{
+       /* We modify all the allocated blocks, tree root, and info block */
+       return (ocfs2_global_qinit_alloc(sb, type) + 2) *
+                       OCFS2_QUOTA_BLOCK_UPDATE_CREDITS;
+}
+
 /* Read in information from global quota file and acquire a reference to it.
  * dquot_acquire() has already started the transaction and locked quota file */
 int ocfs2_global_read_dquot(struct dquot *dquot)
 {
        int err, err2, ex = 0;
-       struct ocfs2_mem_dqinfo *info =
-                       sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
+       struct super_block *sb = dquot->dq_sb;
+       int type = dquot->dq_type;
+       struct ocfs2_mem_dqinfo *info = sb_dqinfo(sb, type)->dqi_priv;
+       struct ocfs2_super *osb = OCFS2_SB(sb);
+       struct inode *gqinode = info->dqi_gqinode;
+       int need_alloc = ocfs2_global_qinit_alloc(sb, type);
+       handle_t *handle = NULL;
 
        err = ocfs2_qinfo_lock(info, 0);
        if (err < 0)
@@ -419,14 +451,33 @@ int ocfs2_global_read_dquot(struct dquot *dquot)
        OCFS2_DQUOT(dquot)->dq_use_count++;
        OCFS2_DQUOT(dquot)->dq_origspace = dquot->dq_dqb.dqb_curspace;
        OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
+       ocfs2_qinfo_unlock(info, 0);
+
        if (!dquot->dq_off) {   /* No real quota entry? */
-               /* Upgrade to exclusive lock for allocation */
-               ocfs2_qinfo_unlock(info, 0);
-               err = ocfs2_qinfo_lock(info, 1);
-               if (err < 0)
-                       goto out_qlock;
                ex = 1;
+               /*
+                * Add blocks to quota file before we start a transaction since
+                * locking allocators ranks above a transaction start
+                */
+               WARN_ON(journal_current_handle());
+               down_write(&OCFS2_I(gqinode)->ip_alloc_sem);
+               err = ocfs2_extend_no_holes(gqinode,
+                       gqinode->i_size + (need_alloc << sb->s_blocksize_bits),
+                       gqinode->i_size);
+               up_write(&OCFS2_I(gqinode)->ip_alloc_sem);
+               if (err < 0)
+                       goto out;
        }
+
+       handle = ocfs2_start_trans(osb,
+                                  ocfs2_calc_global_qinit_credits(sb, type));
+       if (IS_ERR(handle)) {
+               err = PTR_ERR(handle);
+               goto out;
+       }
+       err = ocfs2_qinfo_lock(info, ex);
+       if (err < 0)
+               goto out_trans;
        err = qtree_write_dquot(&info->dqi_gi, dquot);
        if (ex && info_dirty(sb_dqinfo(dquot->dq_sb, dquot->dq_type))) {
                err2 = __ocfs2_global_write_info(dquot->dq_sb, dquot->dq_type);
@@ -438,6 +489,9 @@ out_qlock:
                ocfs2_qinfo_unlock(info, 1);
        else
                ocfs2_qinfo_unlock(info, 0);
+out_trans:
+       if (handle)
+               ocfs2_commit_trans(osb, handle);
 out:
        if (err < 0)
                mlog_errno(err);
@@ -607,7 +661,7 @@ static void qsync_work_fn(struct work_struct *work)
 
        dquot_scan_active(sb, ocfs2_sync_dquot_helper, oinfo->dqi_type);
        queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
-                          oinfo->dqi_syncjiff);
+                          msecs_to_jiffies(oinfo->dqi_syncms));
 }
 
 /*
@@ -635,20 +689,18 @@ out:
        return status;
 }
 
-int ocfs2_calc_qdel_credits(struct super_block *sb, int type)
+static int ocfs2_calc_qdel_credits(struct super_block *sb, int type)
 {
-       struct ocfs2_mem_dqinfo *oinfo;
-       int features[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
-                                   OCFS2_FEATURE_RO_COMPAT_GRPQUOTA };
-
-       if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, features[type]))
-               return 0;
-
-       oinfo = sb_dqinfo(sb, type)->dqi_priv;
-       /* We modify tree, leaf block, global info, local chunk header,
-        * global and local inode */
-       return oinfo->dqi_gi.dqi_qtree_depth + 2 + 1 +
-              2 * OCFS2_INODE_UPDATE_CREDITS;
+       struct ocfs2_mem_dqinfo *oinfo = sb_dqinfo(sb, type)->dqi_priv;
+       /*
+        * We modify tree, leaf block, global info, local chunk header,
+        * global and local inode; OCFS2_QINFO_WRITE_CREDITS already
+        * accounts for inode update
+        */
+       return (oinfo->dqi_gi.dqi_qtree_depth + 2) *
+              OCFS2_QUOTA_BLOCK_UPDATE_CREDITS +
+              OCFS2_QINFO_WRITE_CREDITS +
+              OCFS2_INODE_UPDATE_CREDITS;
 }
 
 static int ocfs2_release_dquot(struct dquot *dquot)
@@ -680,33 +732,10 @@ out:
        return status;
 }
 
-int ocfs2_calc_qinit_credits(struct super_block *sb, int type)
-{
-       struct ocfs2_mem_dqinfo *oinfo;
-       int features[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
-                                   OCFS2_FEATURE_RO_COMPAT_GRPQUOTA };
-       struct ocfs2_dinode *lfe, *gfe;
-
-       if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, features[type]))
-               return 0;
-
-       oinfo = sb_dqinfo(sb, type)->dqi_priv;
-       gfe = (struct ocfs2_dinode *)oinfo->dqi_gqi_bh->b_data;
-       lfe = (struct ocfs2_dinode *)oinfo->dqi_lqi_bh->b_data;
-       /* We can extend local file + global file. In local file we
-        * can modify info, chunk header block and dquot block. In
-        * global file we can modify info, tree and leaf block */
-       return ocfs2_calc_extend_credits(sb, &lfe->id2.i_list, 0) +
-              ocfs2_calc_extend_credits(sb, &gfe->id2.i_list, 0) +
-              3 + oinfo->dqi_gi.dqi_qtree_depth + 2;
-}
-
 static int ocfs2_acquire_dquot(struct dquot *dquot)
 {
-       handle_t *handle;
        struct ocfs2_mem_dqinfo *oinfo =
                        sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
-       struct ocfs2_super *osb = OCFS2_SB(dquot->dq_sb);
        int status = 0;
 
        mlog_entry("id=%u, type=%d", dquot->dq_id, dquot->dq_type);
@@ -715,16 +744,7 @@ static int ocfs2_acquire_dquot(struct dquot *dquot)
        status = ocfs2_lock_global_qf(oinfo, 1);
        if (status < 0)
                goto out;
-       handle = ocfs2_start_trans(osb,
-               ocfs2_calc_qinit_credits(dquot->dq_sb, dquot->dq_type));
-       if (IS_ERR(handle)) {
-               status = PTR_ERR(handle);
-               mlog_errno(status);
-               goto out_ilock;
-       }
        status = dquot_acquire(dquot);
-       ocfs2_commit_trans(osb, handle);
-out_ilock:
        ocfs2_unlock_global_qf(oinfo, 1);
 out:
        mlog_exit(status);
index 5a460fa8255384f615d2dd7ca8836d3091fc58b5..bdb09cb6e1fef216821b7e7a8d94503ce7d097fd 100644 (file)
@@ -20,6 +20,7 @@
 #include "sysfile.h"
 #include "dlmglue.h"
 #include "quota.h"
+#include "uptodate.h"
 
 /* Number of local quota structures per block */
 static inline unsigned int ol_quota_entries_per_block(struct super_block *sb)
@@ -100,7 +101,8 @@ static int ocfs2_modify_bh(struct inode *inode, struct buffer_head *bh,
        handle_t *handle;
        int status;
 
-       handle = ocfs2_start_trans(OCFS2_SB(sb), 1);
+       handle = ocfs2_start_trans(OCFS2_SB(sb),
+                                  OCFS2_QUOTA_BLOCK_UPDATE_CREDITS);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                mlog_errno(status);
@@ -610,7 +612,8 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb,
                        goto out_bh;
                /* Mark quota file as clean if we are recovering quota file of
                 * some other node. */
-               handle = ocfs2_start_trans(osb, 1);
+               handle = ocfs2_start_trans(osb,
+                                          OCFS2_LOCAL_QINFO_WRITE_CREDITS);
                if (IS_ERR(handle)) {
                        status = PTR_ERR(handle);
                        mlog_errno(status);
@@ -940,7 +943,7 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
        struct ocfs2_local_disk_chunk *dchunk;
        int status;
        handle_t *handle;
-       struct buffer_head *bh = NULL;
+       struct buffer_head *bh = NULL, *dbh = NULL;
        u64 p_blkno;
 
        /* We are protected by dqio_sem so no locking needed */
@@ -964,32 +967,35 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
                mlog_errno(status);
                goto out;
        }
+       /* Local quota info and two new blocks we initialize */
+       handle = ocfs2_start_trans(OCFS2_SB(sb),
+                       OCFS2_LOCAL_QINFO_WRITE_CREDITS +
+                       2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS);
+       if (IS_ERR(handle)) {
+               status = PTR_ERR(handle);
+               mlog_errno(status);
+               goto out;
+       }
 
+       /* Initialize chunk header */
        down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
        status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks,
                                             &p_blkno, NULL, NULL);
        up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
        if (status < 0) {
                mlog_errno(status);
-               goto out;
+               goto out_trans;
        }
        bh = sb_getblk(sb, p_blkno);
        if (!bh) {
                status = -ENOMEM;
                mlog_errno(status);
-               goto out;
+               goto out_trans;
        }
        dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data;
-
-       handle = ocfs2_start_trans(OCFS2_SB(sb), 2);
-       if (IS_ERR(handle)) {
-               status = PTR_ERR(handle);
-               mlog_errno(status);
-               goto out;
-       }
-
+       ocfs2_set_new_buffer_uptodate(lqinode, bh);
        status = ocfs2_journal_access_dq(handle, lqinode, bh,
-                                        OCFS2_JOURNAL_ACCESS_WRITE);
+                                        OCFS2_JOURNAL_ACCESS_CREATE);
        if (status < 0) {
                mlog_errno(status);
                goto out_trans;
@@ -999,7 +1005,6 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
        memset(dchunk->dqc_bitmap, 0,
               sb->s_blocksize - sizeof(struct ocfs2_local_disk_chunk) -
               OCFS2_QBLK_RESERVED_SPACE);
-       set_buffer_uptodate(bh);
        unlock_buffer(bh);
        status = ocfs2_journal_dirty(handle, bh);
        if (status < 0) {
@@ -1007,6 +1012,38 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk(
                goto out_trans;
        }
 
+       /* Initialize new block with structures */
+       down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
+       status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks + 1,
+                                            &p_blkno, NULL, NULL);
+       up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+       dbh = sb_getblk(sb, p_blkno);
+       if (!dbh) {
+               status = -ENOMEM;
+               mlog_errno(status);
+               goto out_trans;
+       }
+       ocfs2_set_new_buffer_uptodate(lqinode, dbh);
+       status = ocfs2_journal_access_dq(handle, lqinode, dbh,
+                                        OCFS2_JOURNAL_ACCESS_CREATE);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+       lock_buffer(dbh);
+       memset(dbh->b_data, 0, sb->s_blocksize - OCFS2_QBLK_RESERVED_SPACE);
+       unlock_buffer(dbh);
+       status = ocfs2_journal_dirty(handle, dbh);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+
+       /* Update local quotafile info */
        oinfo->dqi_blocks += 2;
        oinfo->dqi_chunks++;
        status = ocfs2_local_write_info(sb, type);
@@ -1031,6 +1068,7 @@ out_trans:
        ocfs2_commit_trans(OCFS2_SB(sb), handle);
 out:
        brelse(bh);
+       brelse(dbh);
        kmem_cache_free(ocfs2_qf_chunk_cachep, chunk);
        return ERR_PTR(status);
 }
@@ -1048,6 +1086,8 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
        struct ocfs2_local_disk_chunk *dchunk;
        int epb = ol_quota_entries_per_block(sb);
        unsigned int chunk_blocks;
+       struct buffer_head *bh;
+       u64 p_blkno;
        int status;
        handle_t *handle;
 
@@ -1075,12 +1115,49 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
                mlog_errno(status);
                goto out;
        }
-       handle = ocfs2_start_trans(OCFS2_SB(sb), 2);
+
+       /* Get buffer from the just added block */
+       down_read(&OCFS2_I(lqinode)->ip_alloc_sem);
+       status = ocfs2_extent_map_get_blocks(lqinode, oinfo->dqi_blocks,
+                                            &p_blkno, NULL, NULL);
+       up_read(&OCFS2_I(lqinode)->ip_alloc_sem);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out;
+       }
+       bh = sb_getblk(sb, p_blkno);
+       if (!bh) {
+               status = -ENOMEM;
+               mlog_errno(status);
+               goto out;
+       }
+       ocfs2_set_new_buffer_uptodate(lqinode, bh);
+
+       /* Local quota info, chunk header and the new block we initialize */
+       handle = ocfs2_start_trans(OCFS2_SB(sb),
+                       OCFS2_LOCAL_QINFO_WRITE_CREDITS +
+                       2 * OCFS2_QUOTA_BLOCK_UPDATE_CREDITS);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                mlog_errno(status);
                goto out;
        }
+       /* Zero created block */
+       status = ocfs2_journal_access_dq(handle, lqinode, bh,
+                                OCFS2_JOURNAL_ACCESS_CREATE);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+       lock_buffer(bh);
+       memset(bh->b_data, 0, sb->s_blocksize);
+       unlock_buffer(bh);
+       status = ocfs2_journal_dirty(handle, bh);
+       if (status < 0) {
+               mlog_errno(status);
+               goto out_trans;
+       }
+       /* Update chunk header */
        status = ocfs2_journal_access_dq(handle, lqinode, chunk->qc_headerbh,
                                 OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
@@ -1097,6 +1174,7 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file(
                mlog_errno(status);
                goto out_trans;
        }
+       /* Update file header */
        oinfo->dqi_blocks++;
        status = ocfs2_local_write_info(sb, type);
        if (status < 0) {
index 3f661376a2ded76e08769f1766de3c1523d448d9..e49c41050264dfa9d36afc48e742b626ee9d2755 100644 (file)
@@ -17,6 +17,7 @@
  * General Public License for more details.
  */
 
+#include <linux/kernel.h>
 #include <linux/crc32.h>
 #include <linux/module.h>
 
@@ -153,7 +154,7 @@ static int status_map[] = {
 
 static int dlm_status_to_errno(enum dlm_status status)
 {
-       BUG_ON(status > (sizeof(status_map) / sizeof(status_map[0])));
+       BUG_ON(status < 0 || status >= ARRAY_SIZE(status_map));
 
        return status_map[status];
 }
index 7efb349fb9bdafe0678bd63786db244bba410b4a..a3f8871d21fd516fb29aefbc040e30e6be016069 100644 (file)
@@ -777,6 +777,7 @@ static int ocfs2_sb_probe(struct super_block *sb,
                }
                di = (struct ocfs2_dinode *) (*bh)->b_data;
                memset(stats, 0, sizeof(struct ocfs2_blockcheck_stats));
+               spin_lock_init(&stats->b_lock);
                status = ocfs2_verify_volume(di, *bh, blksize, stats);
                if (status >= 0)
                        goto bail;
@@ -1182,7 +1183,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
        wake_up(&osb->osb_mount_event);
 
        /* Start this when the mount is almost sure of being successful */
-       ocfs2_orphan_scan_init(osb);
+       ocfs2_orphan_scan_start(osb);
 
        mlog_exit(status);
        return status;
@@ -1213,14 +1214,31 @@ static int ocfs2_get_sb(struct file_system_type *fs_type,
                           mnt);
 }
 
+static void ocfs2_kill_sb(struct super_block *sb)
+{
+       struct ocfs2_super *osb = OCFS2_SB(sb);
+
+       /* Failed mount? */
+       if (!osb || atomic_read(&osb->vol_state) == VOLUME_DISABLED)
+               goto out;
+
+       /* Prevent further queueing of inode drop events */
+       spin_lock(&dentry_list_lock);
+       ocfs2_set_osb_flag(osb, OCFS2_OSB_DROP_DENTRY_LOCK_IMMED);
+       spin_unlock(&dentry_list_lock);
+       /* Wait for work to finish and/or remove it */
+       cancel_work_sync(&osb->dentry_lock_work);
+out:
+       kill_block_super(sb);
+}
+
 static struct file_system_type ocfs2_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "ocfs2",
        .get_sb         = ocfs2_get_sb, /* is this called when we mount
                                        * the fs? */
-       .kill_sb        = kill_block_super, /* set to the generic one
-                                            * right now, but do we
-                                            * need to change that? */
+       .kill_sb        = ocfs2_kill_sb,
+
        .fs_flags       = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE,
        .next           = NULL
 };
@@ -1819,6 +1837,12 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
 
        debugfs_remove(osb->osb_ctxt);
 
+       /*
+        * Flush inode dropping work queue so that deletes are
+        * performed while the filesystem is still working
+        */
+       ocfs2_drop_all_dl_inodes(osb);
+
        /* Orphan scan should be stopped as early as possible */
        ocfs2_orphan_scan_stop(osb);
 
@@ -1981,6 +2005,8 @@ static int ocfs2_initialize_super(struct super_block *sb,
        snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u",
                 MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
 
+       ocfs2_orphan_scan_init(osb);
+
        status = ocfs2_recovery_init(osb);
        if (status) {
                mlog(ML_ERROR, "Unable to initialize recovery state\n");
index ba320e250747fd01dedcd06a85df0d2e867dbe44..d1a27cda984f10811fb66fe7a7a53e76f6036d34 100644 (file)
@@ -1052,7 +1052,8 @@ static int ocfs2_xattr_block_get(struct inode *inode,
        struct ocfs2_xattr_block *xb;
        struct ocfs2_xattr_value_root *xv;
        size_t size;
-       int ret = -ENODATA, name_offset, name_len, block_off, i;
+       int ret = -ENODATA, name_offset, name_len, i;
+       int uninitialized_var(block_off);
 
        xs->bucket = ocfs2_xattr_bucket_new(inode);
        if (!xs->bucket) {
index 1a9c7878f8649b1df14531f66aa247fd2587e2c8..ea4e6cb29e1394f709f834df066a7659e12b1d2e 100644 (file)
@@ -436,7 +436,7 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno,
        rcu_assign_pointer(ptbl->part[partno], p);
 
        /* suppress uevent if the disk supresses it */
-       if (!dev_get_uevent_suppress(pdev))
+       if (!dev_get_uevent_suppress(ddev))
                kobject_uevent(&pdev->kobj, KOBJ_ADD);
 
        return p;
index f7dd21ad85a61937666eddf0ccbff66e11e6c3fd..52c4151148383c2e9cd89f891e322241e110d3c1 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -68,8 +68,8 @@ void pipe_double_lock(struct pipe_inode_info *pipe1,
                pipe_lock_nested(pipe1, I_MUTEX_PARENT);
                pipe_lock_nested(pipe2, I_MUTEX_CHILD);
        } else {
-               pipe_lock_nested(pipe2, I_MUTEX_CHILD);
-               pipe_lock_nested(pipe1, I_MUTEX_PARENT);
+               pipe_lock_nested(pipe2, I_MUTEX_PARENT);
+               pipe_lock_nested(pipe1, I_MUTEX_CHILD);
        }
 }
 
index 3ce5ae9e3d2dabd36dce105ecb4545a4723c1202..6f742f6658a9897503568c3ea7b78407829e760f 100644 (file)
@@ -234,23 +234,20 @@ static int check_mem_permission(struct task_struct *task)
 
 struct mm_struct *mm_for_maps(struct task_struct *task)
 {
-       struct mm_struct *mm = get_task_mm(task);
-       if (!mm)
+       struct mm_struct *mm;
+
+       if (mutex_lock_killable(&task->cred_guard_mutex))
                return NULL;
-       down_read(&mm->mmap_sem);
-       task_lock(task);
-       if (task->mm != mm)
-               goto out;
-       if (task->mm != current->mm &&
-           __ptrace_may_access(task, PTRACE_MODE_READ) < 0)
-               goto out;
-       task_unlock(task);
+
+       mm = get_task_mm(task);
+       if (mm && mm != current->mm &&
+                       !ptrace_may_access(task, PTRACE_MODE_READ)) {
+               mmput(mm);
+               mm = NULL;
+       }
+       mutex_unlock(&task->cred_guard_mutex);
+
        return mm;
-out:
-       task_unlock(task);
-       up_read(&mm->mmap_sem);
-       mmput(mm);
-       return NULL;
 }
 
 static int proc_pid_cmdline(struct task_struct *task, char * buffer)
@@ -1006,12 +1003,7 @@ static ssize_t oom_adjust_read(struct file *file, char __user *buf,
 
        if (!task)
                return -ESRCH;
-       task_lock(task);
-       if (task->mm)
-               oom_adjust = task->mm->oom_adj;
-       else
-               oom_adjust = OOM_DISABLE;
-       task_unlock(task);
+       oom_adjust = task->oomkilladj;
        put_task_struct(task);
 
        len = snprintf(buffer, sizeof(buffer), "%i\n", oom_adjust);
@@ -1040,19 +1032,11 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
        task = get_proc_task(file->f_path.dentry->d_inode);
        if (!task)
                return -ESRCH;
-       task_lock(task);
-       if (!task->mm) {
-               task_unlock(task);
-               put_task_struct(task);
-               return -EINVAL;
-       }
-       if (oom_adjust < task->mm->oom_adj && !capable(CAP_SYS_RESOURCE)) {
-               task_unlock(task);
+       if (oom_adjust < task->oomkilladj && !capable(CAP_SYS_RESOURCE)) {
                put_task_struct(task);
                return -EACCES;
        }
-       task->mm->oom_adj = oom_adjust;
-       task_unlock(task);
+       task->oomkilladj = oom_adjust;
        put_task_struct(task);
        if (end - buffer == 0)
                return -EIO;
index 6f61b7cc32e0e09c39aea2dd31cf64e2bc049060..9bd8be1d235c2b420e348d25e801bdce88efd977 100644 (file)
@@ -119,6 +119,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
        mm = mm_for_maps(priv->task);
        if (!mm)
                return NULL;
+       down_read(&mm->mmap_sem);
 
        tail_vma = get_gate_vma(priv->task);
        priv->tail_vma = tail_vma;
index 64a72e2e76509545bf6c0d4d4e0788779baaab26..8f5c05d3dbd3e2aaa4abcd3fcc92af79e324daca 100644 (file)
@@ -189,6 +189,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
                priv->task = NULL;
                return NULL;
        }
+       down_read(&mm->mmap_sem);
 
        /* start from the Nth VMA */
        for (p = rb_first(&mm->mm_rb); p; p = rb_next(p))
index 607c579e5eca0cc0427c53a844d68ff159186e47..38f7bd559f35eff8c690cebaf50958f352bd02d1 100644 (file)
@@ -2042,7 +2042,6 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
                 * changes */
                invalidate_bdev(sb->s_bdev);
        }
-       mutex_lock(&inode->i_mutex);
        mutex_lock(&dqopt->dqonoff_mutex);
        if (sb_has_quota_loaded(sb, type)) {
                error = -EBUSY;
@@ -2054,9 +2053,11 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
                 * possible) Also nobody should write to the file - we use
                 * special IO operations which ignore the immutable bit. */
                down_write(&dqopt->dqptr_sem);
+               mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
                oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE |
                                             S_NOQUOTA);
                inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE;
+               mutex_unlock(&inode->i_mutex);
                up_write(&dqopt->dqptr_sem);
                sb->dq_op->drop(inode);
        }
@@ -2080,7 +2081,6 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
                goto out_file_init;
        }
        mutex_unlock(&dqopt->dqio_mutex);
-       mutex_unlock(&inode->i_mutex);
        spin_lock(&dq_state_lock);
        dqopt->flags |= dquot_state_flag(flags, type);
        spin_unlock(&dq_state_lock);
@@ -2094,16 +2094,17 @@ out_file_init:
        dqopt->files[type] = NULL;
        iput(inode);
 out_lock:
-       mutex_unlock(&dqopt->dqonoff_mutex);
        if (oldflags != -1) {
                down_write(&dqopt->dqptr_sem);
+               mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
                /* Set the flags back (in the case of accidental quotaon()
                 * on a wrong file we don't want to mess up the flags) */
                inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE);
                inode->i_flags |= oldflags;
+               mutex_unlock(&inode->i_mutex);
                up_write(&dqopt->dqptr_sem);
        }
-       mutex_unlock(&inode->i_mutex);
+       mutex_unlock(&dqopt->dqonoff_mutex);
 out_fmt:
        put_quota_format(fmt);
 
index ebb2c417912c0c7306d73c007b771702e7faee2e..11f0c06316ded778283af0bdbe53d06101225df0 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/ramfs.h>
 #include <linux/pagevec.h>
 #include <linux/mman.h>
+#include <linux/sched.h>
 
 #include <asm/uaccess.h>
 #include "internal.h"
index 77f5bb746bf073969140539752ee87dc8f4f0861..90622200b39c0622e0f159d423c929a036d76257 100644 (file)
@@ -997,7 +997,7 @@ static int reiserfs_async_progress_wait(struct super_block *s)
        DEFINE_WAIT(wait);
        struct reiserfs_journal *j = SB_JOURNAL(s);
        if (atomic_read(&j->j_async_throttle))
-               congestion_wait(WRITE, HZ / 10);
+               congestion_wait(BLK_RW_ASYNC, HZ / 10);
        return 0;
 }
 
index d3aeb061612bf3818ec60972f6e78d569239d065..7adea74d6a8ac829d3c1efb877b9feec5027ccaa 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/exportfs.h>
 #include <linux/quotaops.h>
 #include <linux/vfs.h>
-#include <linux/mnt_namespace.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/crc32.h>
index f3d47d8568482f3dd2b20077e296b40bc8a428f1..6925b835a43b6f2f94e8a4217180b2e8d1735ab7 100644 (file)
@@ -46,7 +46,6 @@
 #include <linux/reiserfs_acl.h>
 #include <asm/uaccess.h>
 #include <net/checksum.h>
-#include <linux/smp_lock.h>
 #include <linux/stat.h>
 #include <linux/quotaops.h>
 
index d870237e42c74f018b2824304345aa44a90b8607..8084834e123efed4e100fe030e2e26ced3ede1c9 100644 (file)
@@ -110,6 +110,7 @@ void poll_initwait(struct poll_wqueues *pwq)
 {
        init_poll_funcptr(&pwq->pt, __pollwait);
        pwq->polling_task = current;
+       pwq->triggered = 0;
        pwq->error = 0;
        pwq->table = NULL;
        pwq->inline_index = 0;
index 3b52770f46ffdcfbd4c6187a6dfd928f6135203c..cb5fc57e370be3babf4de90514fa89c2656f99f3 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/fs.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/mutex.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
index dd200025af8521d65e7bf28efceaece55994c59d..3422ba61d86dcad558fd47d59756b411bfae7a81 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -112,8 +112,13 @@ restart:
        mutex_unlock(&mutex);
 }
 
+/*
+ * sync everything.  Start out by waking pdflush, because that writes back
+ * all queues in parallel.
+ */
 SYSCALL_DEFINE0(sync)
 {
+       wakeup_pdflush(0);
        sync_filesystems(0);
        sync_filesystems(1);
        if (unlikely(laptop_mode))
index 9345806c8853e369ba34695542081bb2e3f347db..2524714bece1b87e68d68c6928cfd720f0a9b259 100644 (file)
@@ -171,6 +171,7 @@ static ssize_t write(struct file *file, const char __user *userbuf,
        if (count > 0)
                *off = offs + count;
 
+       kfree(temp);
        return count;
 }
 
index d88d0fac9fa5f185afd13b1f36b11f58baec672d..14f2d71ea3ce8b7077b0da8774bc554b912cd0fb 100644 (file)
@@ -939,8 +939,10 @@ again:
        /* Remove from old parent's list and insert into new parent's list. */
        sysfs_unlink_sibling(sd);
        sysfs_get(new_parent_sd);
+       drop_nlink(old_parent->d_inode);
        sysfs_put(sd->s_parent);
        sd->s_parent = new_parent_sd;
+       inc_nlink(new_parent->d_inode);
        sysfs_link_sibling(sd);
 
  out_unlock:
index bc5857199ec2a021c1f9f9838b11329461704b4f..762a7d6cec73de8433c58c6a6c691115e3c23e1c 100644 (file)
@@ -297,6 +297,7 @@ static enum hrtimer_restart wbuf_timer_callback_nolock(struct hrtimer *timer)
 {
        struct ubifs_wbuf *wbuf = container_of(timer, struct ubifs_wbuf, timer);
 
+       dbg_io("jhead %d", wbuf->jhead);
        wbuf->need_sync = 1;
        wbuf->c->need_wbuf_sync = 1;
        ubifs_wake_up_bgt(wbuf->c);
@@ -311,8 +312,12 @@ static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
 {
        ubifs_assert(!hrtimer_active(&wbuf->timer));
 
-       if (!ktime_to_ns(wbuf->softlimit))
+       if (wbuf->no_timer)
                return;
+       dbg_io("set timer for jhead %d, %llu-%llu millisecs", wbuf->jhead,
+              div_u64(ktime_to_ns(wbuf->softlimit), USEC_PER_SEC),
+              div_u64(ktime_to_ns(wbuf->softlimit) + wbuf->delta,
+                      USEC_PER_SEC));
        hrtimer_start_range_ns(&wbuf->timer, wbuf->softlimit, wbuf->delta,
                               HRTIMER_MODE_REL);
 }
@@ -323,11 +328,8 @@ static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
  */
 static void cancel_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
 {
-       /*
-        * If the syncer is waiting for the lock (from the background thread's
-        * context) and another task is changing write-buffer then the syncing
-        * should be canceled.
-        */
+       if (wbuf->no_timer)
+               return;
        wbuf->need_sync = 0;
        hrtimer_cancel(&wbuf->timer);
 }
@@ -349,8 +351,8 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
                /* Write-buffer is empty or not seeked */
                return 0;
 
-       dbg_io("LEB %d:%d, %d bytes",
-              wbuf->lnum, wbuf->offs, wbuf->used);
+       dbg_io("LEB %d:%d, %d bytes, jhead %d",
+              wbuf->lnum, wbuf->offs, wbuf->used, wbuf->jhead);
        ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
        ubifs_assert(!(wbuf->avail & 7));
        ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
@@ -390,7 +392,7 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
  * @offs: logical eraseblock offset to seek to
  * @dtype: data type
  *
- * This function targets the write buffer to logical eraseblock @lnum:@offs.
+ * This function targets the write-buffer to logical eraseblock @lnum:@offs.
  * The write-buffer is synchronized if it is not empty. Returns zero in case of
  * success and a negative error code in case of failure.
  */
@@ -399,7 +401,7 @@ int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
 {
        const struct ubifs_info *c = wbuf->c;
 
-       dbg_io("LEB %d:%d", lnum, offs);
+       dbg_io("LEB %d:%d, jhead %d", lnum, offs, wbuf->jhead);
        ubifs_assert(lnum >= 0 && lnum < c->leb_cnt);
        ubifs_assert(offs >= 0 && offs <= c->leb_size);
        ubifs_assert(offs % c->min_io_size == 0 && !(offs & 7));
@@ -506,9 +508,9 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
        struct ubifs_info *c = wbuf->c;
        int err, written, n, aligned_len = ALIGN(len, 8), offs;
 
-       dbg_io("%d bytes (%s) to wbuf at LEB %d:%d", len,
-              dbg_ntype(((struct ubifs_ch *)buf)->node_type), wbuf->lnum,
-              wbuf->offs + wbuf->used);
+       dbg_io("%d bytes (%s) to jhead %d wbuf at LEB %d:%d", len,
+              dbg_ntype(((struct ubifs_ch *)buf)->node_type), wbuf->jhead,
+              wbuf->lnum, wbuf->offs + wbuf->used);
        ubifs_assert(len > 0 && wbuf->lnum >= 0 && wbuf->lnum < c->leb_cnt);
        ubifs_assert(wbuf->offs >= 0 && wbuf->offs % c->min_io_size == 0);
        ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
@@ -533,8 +535,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
                memcpy(wbuf->buf + wbuf->used, buf, len);
 
                if (aligned_len == wbuf->avail) {
-                       dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum,
-                               wbuf->offs);
+                       dbg_io("flush jhead %d wbuf to LEB %d:%d",
+                              wbuf->jhead, wbuf->lnum, wbuf->offs);
                        err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf,
                                            wbuf->offs, c->min_io_size,
                                            wbuf->dtype);
@@ -562,7 +564,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
         * minimal I/O unit. We have to fill and flush write-buffer and switch
         * to the next min. I/O unit.
         */
-       dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum, wbuf->offs);
+       dbg_io("flush jhead %d wbuf to LEB %d:%d",
+              wbuf->jhead, wbuf->lnum, wbuf->offs);
        memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
        err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
                            c->min_io_size, wbuf->dtype);
@@ -695,7 +698,8 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
        int err, rlen, overlap;
        struct ubifs_ch *ch = buf;
 
-       dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
+       dbg_io("LEB %d:%d, %s, length %d, jhead %d", lnum, offs,
+              dbg_ntype(type), len, wbuf->jhead);
        ubifs_assert(wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
        ubifs_assert(!(offs & 7) && offs < c->leb_size);
        ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
@@ -819,13 +823,12 @@ out:
  * @c: UBIFS file-system description object
  * @wbuf: write-buffer to initialize
  *
- * This function initializes write buffer. Returns zero in case of success
+ * This function initializes write-buffer. Returns zero in case of success
  * %-ENOMEM in case of failure.
  */
 int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
 {
        size_t size;
-       ktime_t hardlimit;
 
        wbuf->buf = kmalloc(c->min_io_size, GFP_KERNEL);
        if (!wbuf->buf)
@@ -851,22 +854,16 @@ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
 
        hrtimer_init(&wbuf->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        wbuf->timer.function = wbuf_timer_callback_nolock;
-       /*
-        * Make write-buffer soft limit to be 20% of the hard limit. The
-        * write-buffer timer is allowed to expire any time between the soft
-        * and hard limits.
-        */
-       hardlimit = ktime_set(DEFAULT_WBUF_TIMEOUT_SECS, 0);
-       wbuf->delta = (DEFAULT_WBUF_TIMEOUT_SECS * NSEC_PER_SEC) * 2 / 10;
-       wbuf->softlimit = ktime_sub_ns(hardlimit, wbuf->delta);
-       hrtimer_set_expires_range_ns(&wbuf->timer,  wbuf->softlimit,
-                                    wbuf->delta);
+       wbuf->softlimit = ktime_set(WBUF_TIMEOUT_SOFTLIMIT, 0);
+       wbuf->delta = WBUF_TIMEOUT_HARDLIMIT - WBUF_TIMEOUT_SOFTLIMIT;
+       wbuf->delta *= 1000000000ULL;
+       ubifs_assert(wbuf->delta <= ULONG_MAX);
        return 0;
 }
 
 /**
  * ubifs_wbuf_add_ino_nolock - add an inode number into the wbuf inode array.
- * @wbuf: the write-buffer whereto add
+ * @wbuf: the write-buffer where to add
  * @inum: the inode number
  *
  * This function adds an inode number to the inode array of the write-buffer.
index 6db7a6be6c9732a8a14cecc8ea60683522493442..8aacd64957a223c0a01e2d9c54dd73c9d7fbd409 100644 (file)
@@ -25,7 +25,6 @@
 /* This file implements EXT2-compatible extended attribute ioctl() calls */
 
 #include <linux/compat.h>
-#include <linux/smp_lock.h>
 #include <linux/mount.h>
 #include "ubifs.h"
 
index 805605250f128af9b6a978fa8c29c5c31660539a..e5f6cf8a115535e469a646e4806d9dcdbf19a490 100644 (file)
@@ -52,6 +52,25 @@ static int is_empty(void *buf, int len)
        return 1;
 }
 
+/**
+ * first_non_ff - find offset of the first non-0xff byte.
+ * @buf: buffer to search in
+ * @len: length of buffer
+ *
+ * This function returns offset of the first non-0xff byte in @buf or %-1 if
+ * the buffer contains only 0xff bytes.
+ */
+static int first_non_ff(void *buf, int len)
+{
+       uint8_t *p = buf;
+       int i;
+
+       for (i = 0; i < len; i++)
+               if (*p++ != 0xff)
+                       return i;
+       return -1;
+}
+
 /**
  * get_master_node - get the last valid master node allowing for corruption.
  * @c: UBIFS file-system description object
@@ -357,11 +376,7 @@ static int is_last_write(const struct ubifs_info *c, void *buf, int offs)
        empty_offs = ALIGN(offs + 1, c->min_io_size);
        check_len = c->leb_size - empty_offs;
        p = buf + empty_offs - offs;
-
-       for (; check_len > 0; check_len--)
-               if (*p++ != 0xff)
-                       return 0;
-       return 1;
+       return is_empty(p, check_len);
 }
 
 /**
@@ -543,8 +558,8 @@ static int drop_incomplete_group(struct ubifs_scan_leb *sleb, int *offs)
  *
  * This function does a scan of a LEB, but caters for errors that might have
  * been caused by the unclean unmount from which we are attempting to recover.
- *
- * This function returns %0 on success and a negative error code on failure.
+ * Returns %0 in case of success, %-EUCLEAN if an unrecoverable corruption is
+ * found, and a negative error code in case of failure.
  */
 struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
                                         int offs, void *sbuf, int grouped)
@@ -643,7 +658,8 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
                        goto corrupted;
                default:
                        dbg_err("unknown");
-                       goto corrupted;
+                       err = -EINVAL;
+                       goto error;
                }
        }
 
@@ -652,8 +668,13 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
                        clean_buf(c, &buf, lnum, &offs, &len);
                        need_clean = 1;
                } else {
-                       ubifs_err("corrupt empty space at LEB %d:%d",
-                                 lnum, offs);
+                       int corruption = first_non_ff(buf, len);
+
+                       ubifs_err("corrupt empty space LEB %d:%d, corruption "
+                                 "starts at %d", lnum, offs, corruption);
+                       /* Make sure we dump interesting non-0xFF data */
+                       offs = corruption;
+                       buf += corruption;
                        goto corrupted;
                }
        }
@@ -813,7 +834,7 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
 static int recover_head(const struct ubifs_info *c, int lnum, int offs,
                        void *sbuf)
 {
-       int len, err, need_clean = 0;
+       int len, err;
 
        if (c->min_io_size > 1)
                len = c->min_io_size;
@@ -827,19 +848,7 @@ static int recover_head(const struct ubifs_info *c, int lnum, int offs,
 
        /* Read at the head location and check it is empty flash */
        err = ubi_read(c->ubi, lnum, sbuf, offs, len);
-       if (err)
-               need_clean = 1;
-       else {
-               uint8_t *p = sbuf;
-
-               while (len--)
-                       if (*p++ != 0xff) {
-                               need_clean = 1;
-                               break;
-                       }
-       }
-
-       if (need_clean) {
+       if (err || !is_empty(sbuf, len)) {
                dbg_rcvry("cleaning head at %d:%d", lnum, offs);
                if (offs == 0)
                        return ubifs_leb_unmap(c, lnum);
index 11cc80125a49524cef118b97173ed7ff5fb94fd9..2970500f32dfbb76ca9b8d6ff39fd8ee08fada4a 100644 (file)
@@ -837,9 +837,10 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
 
        dbg_mnt("replay log LEB %d:%d", lnum, offs);
        sleb = ubifs_scan(c, lnum, offs, sbuf);
-       if (IS_ERR(sleb)) {
-               if (c->need_recovery)
-                       sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf);
+       if (IS_ERR(sleb) ) {
+               if (PTR_ERR(sleb) != -EUCLEAN || !c->need_recovery)
+                       return PTR_ERR(sleb);
+               sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf);
                if (IS_ERR(sleb))
                        return PTR_ERR(sleb);
        }
@@ -957,7 +958,7 @@ out:
        return err;
 
 out_dump:
-       ubifs_err("log error detected while replying the log at LEB %d:%d",
+       ubifs_err("log error detected while replaying the log at LEB %d:%d",
                  lnum, offs + snod->offs);
        dbg_dump_node(c, snod->node);
        ubifs_scan_destroy(sleb);
index 0ed82479b44b4daca156a80107fee1b040ec10a7..892ebfee4fe538fe033596c5d42d13860d5fe82a 100644 (file)
@@ -238,12 +238,12 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
 {
        int len;
 
-       ubifs_err("corrupted data at LEB %d:%d", lnum, offs);
+       ubifs_err("corruption at LEB %d:%d", lnum, offs);
        if (dbg_failure_mode)
                return;
        len = c->leb_size - offs;
-       if (len > 4096)
-               len = 4096;
+       if (len > 8192)
+               len = 8192;
        dbg_err("first %d bytes from LEB %d:%d", len, lnum, offs);
        print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
 }
@@ -256,7 +256,9 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
  * @sbuf: scan buffer (must be c->leb_size)
  *
  * This function scans LEB number @lnum and returns complete information about
- * its contents. Returns an error code in case of failure.
+ * its contents. Returns the scaned information in case of success and,
+ * %-EUCLEAN if the LEB neads recovery, and other negative error codes in case
+ * of failure.
  */
 struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
                                  int offs, void *sbuf)
@@ -279,7 +281,6 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
                cond_resched();
 
                ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 0);
-
                if (ret > 0) {
                        /* Padding bytes or a valid padding node */
                        offs += ret;
@@ -304,7 +305,8 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
                        goto corrupted;
                default:
                        dbg_err("unknown");
-                       goto corrupted;
+                       err = -EINVAL;
+                       goto error;
                }
 
                err = ubifs_add_snod(c, sleb, buf, offs);
@@ -317,8 +319,10 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
                len -= node_len;
        }
 
-       if (offs % c->min_io_size)
-               goto corrupted;
+       if (offs % c->min_io_size) {
+               ubifs_err("empty space starts at non-aligned offset %d", offs);
+               goto corrupted;;
+       }
 
        ubifs_end_scan(c, sleb, lnum, offs);
 
index 79fad43f3c57ecc71b9d6adaf8dfd5e650e6fa08..26d2e0d8046598ed579a400293dbebd38eefc7e3 100644 (file)
@@ -797,7 +797,7 @@ static int alloc_wbufs(struct ubifs_info *c)
         * does not need to be synchronized by timer.
         */
        c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM;
-       c->jheads[GCHD].wbuf.softlimit = ktime_set(0, 0);
+       c->jheads[GCHD].wbuf.no_timer = 1;
 
        return 0;
 }
@@ -986,7 +986,7 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options,
                switch (token) {
                /*
                 * %Opt_fast_unmount and %Opt_norm_unmount options are ignored.
-                * We accepte them in order to be backware-compatible. But this
+                * We accept them in order to be backward-compatible. But this
                 * should be removed at some point.
                 */
                case Opt_fast_unmount:
@@ -1287,6 +1287,9 @@ static int mount_ubifs(struct ubifs_info *c)
        if (err)
                goto out_journal;
 
+       /* Calculate 'min_idx_lebs' after journal replay */
+       c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
+
        err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only);
        if (err)
                goto out_orphans;
@@ -1754,10 +1757,8 @@ static void ubifs_put_super(struct super_block *sb)
 
                /* Synchronize write-buffers */
                if (c->jheads)
-                       for (i = 0; i < c->jhead_cnt; i++) {
+                       for (i = 0; i < c->jhead_cnt; i++)
                                ubifs_wbuf_sync(&c->jheads[i].wbuf);
-                               hrtimer_cancel(&c->jheads[i].wbuf.timer);
-                       }
 
                /*
                 * On fatal errors c->ro_media is set to 1, in which case we do
@@ -1975,7 +1976,8 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
        err  = bdi_init(&c->bdi);
        if (err)
                goto out_close;
-       err = bdi_register(&c->bdi, NULL, "ubifs");
+       err = bdi_register(&c->bdi, NULL, "ubifs_%d_%d",
+                          c->vi.ubi_num, c->vi.vol_id);
        if (err)
                goto out_bdi;
 
index 1bf01d8200667503cb0f0e310fafbc4304701721..a29349094422731766fa82a95201e0f14ad3c7fb 100644 (file)
@@ -95,8 +95,9 @@
  */
 #define BGT_NAME_PATTERN "ubifs_bgt%d_%d"
 
-/* Default write-buffer synchronization timeout in seconds */
-#define DEFAULT_WBUF_TIMEOUT_SECS 5
+/* Write-buffer synchronization timeout interval in seconds */
+#define WBUF_TIMEOUT_SOFTLIMIT 3
+#define WBUF_TIMEOUT_HARDLIMIT 5
 
 /* Maximum possible inode number (only 32-bit inodes are supported now) */
 #define MAX_INUM 0xFFFFFFFF
@@ -654,7 +655,8 @@ typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c,
  * @delta: hard and soft timeouts delta (the timer expire inteval is @softlimit
  *         and @softlimit + @delta)
  * @timer: write-buffer timer
- * @need_sync: it is set if its timer expired and needs sync
+ * @no_timer: non-zero if this write-buffer does not have a timer
+ * @need_sync: non-zero if the timer expired and the wbuf needs sync'ing
  * @next_ino: points to the next position of the following inode number
  * @inodes: stores the inode numbers of the nodes which are in wbuf
  *
@@ -683,7 +685,8 @@ struct ubifs_wbuf {
        ktime_t softlimit;
        unsigned long long delta;
        struct hrtimer timer;
-       int need_sync;
+       unsigned int no_timer:1;
+       unsigned int need_sync:1;
        int next_ino;
        ino_t *inodes;
 };
index 6832135159b680e8563a9ebadd03ebf19eb8f80c..9d1b8c2e6c45bcc3d5428ef2095f718b970a139f 100644 (file)
@@ -1087,11 +1087,23 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
        struct udf_inode_info *vati;
        uint32_t pos;
        struct virtualAllocationTable20 *vat20;
+       sector_t blocks = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits;
 
        /* VAT file entry is in the last recorded block */
        ino.partitionReferenceNum = type1_index;
        ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root;
        sbi->s_vat_inode = udf_iget(sb, &ino);
+       if (!sbi->s_vat_inode &&
+           sbi->s_last_block != blocks - 1) {
+               printk(KERN_NOTICE "UDF-fs: Failed to read VAT inode from the"
+                      " last recorded block (%lu), retrying with the last "
+                      "block of the device (%lu).\n",
+                      (unsigned long)sbi->s_last_block,
+                      (unsigned long)blocks - 1);
+               ino.partitionReferenceNum = type1_index;
+               ino.logicalBlockNum = blocks - 1 - map->s_partition_root;
+               sbi->s_vat_inode = udf_iget(sb, &ino);
+       }
        if (!sbi->s_vat_inode)
                return 1;
 
index 1cd3b55ee3d227d5916c18d95c2dd84a45e5285d..2d3f90afe5f14ee6ef3543d0bd6e01be014952ba 100644 (file)
@@ -53,7 +53,7 @@ kmem_alloc(size_t size, unsigned int __nocast flags)
                        printk(KERN_ERR "XFS: possible memory allocation "
                                        "deadlock in %s (mode:0x%x)\n",
                                        __func__, lflags);
-               congestion_wait(WRITE, HZ/50);
+               congestion_wait(BLK_RW_ASYNC, HZ/50);
        } while (1);
 }
 
@@ -130,7 +130,7 @@ kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags)
                        printk(KERN_ERR "XFS: possible memory allocation "
                                        "deadlock in %s (mode:0x%x)\n",
                                        __func__, lflags);
-               congestion_wait(WRITE, HZ/50);
+               congestion_wait(BLK_RW_ASYNC, HZ/50);
        } while (1);
 }
 
index 7ec89fc05b2b66d9ed5ca462d2d7f05d44c83dbc..aecf2519db76345a206fb812c61f0598d85440fb 100644 (file)
@@ -1268,6 +1268,14 @@ xfs_vm_writepage(
        if (!page_has_buffers(page))
                create_empty_buffers(page, 1 << inode->i_blkbits, 0);
 
+
+       /*
+        *  VM calculation for nr_to_write seems off.  Bump it way
+        *  up, this gets simple streaming writes zippy again.
+        *  To be reviewed again after Jens' writeback changes.
+        */
+       wbc->nr_to_write *= 4;
+
        /*
         * Convert delayed allocate, unwritten or unmapped space
         * to real space and flush out to disk.
index 1418b916fc2755306cca61e60c734154d543c82f..965df1227d644df44b4d2b79810f1ab42747f957 100644 (file)
@@ -412,7 +412,7 @@ _xfs_buf_lookup_pages(
 
                        XFS_STATS_INC(xb_page_retries);
                        xfsbufd_wakeup(0, gfp_mask);
-                       congestion_wait(WRITE, HZ/50);
+                       congestion_wait(BLK_RW_ASYNC, HZ/50);
                        goto retry;
                }
 
@@ -770,7 +770,7 @@ xfs_buf_associate_memory(
        bp->b_pages = NULL;
        bp->b_addr = mem;
 
-       rval = _xfs_buf_get_pages(bp, page_count, 0);
+       rval = _xfs_buf_get_pages(bp, page_count, XBF_DONT_BLOCK);
        if (rval)
                return rval;
 
index f4e25544157422812b4a1e576d3539e86b75b9bd..0542fd50764945935bd6975bc8094a8df2348601 100644 (file)
@@ -41,7 +41,6 @@
 #include "xfs_ioctl.h"
 
 #include <linux/dcache.h>
-#include <linux/smp_lock.h>
 
 static struct vm_operations_struct xfs_file_vm_ops;
 
index 0882d166239a071985b8309362c257e3878dde19..eafcc7c1870687817c663816995894f0cfa4c127 100644 (file)
@@ -619,7 +619,7 @@ xfs_file_compat_ioctl(
        case XFS_IOC_GETVERSION_32:
                cmd = _NATIVE_IOC(cmd, long);
                return xfs_file_ioctl(filp, cmd, p);
-       case XFS_IOC_SWAPEXT: {
+       case XFS_IOC_SWAPEXT_32: {
                struct xfs_swapext        sxp;
                struct compat_xfs_swapext __user *sxu = arg;
 
index 58973bb460388b2ef3dd8f85f2017ff347810c31..8070b34cc287db18f8eb40653d4a8f59f8bd3aa7 100644 (file)
@@ -680,8 +680,8 @@ xfs_vn_fiemap(
        else
                bm.bmv_length = BTOBB(length);
 
-       /* our formatter will tell xfs_getbmap when to stop. */
-       bm.bmv_count = MAXEXTNUM;
+       /* We add one because in getbmap world count includes the header */
+       bm.bmv_count = fieinfo->fi_extents_max + 1;
        bm.bmv_iflags = BMV_IF_PREALLOC;
        if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR)
                bm.bmv_iflags |= BMV_IF_ATTRFORK;
index b619d6b8ca4323afc02abab54d967f352d899e6a..98ef624d9baf65a2bb3503d0fb6c599fdbdfd02f 100644 (file)
@@ -708,6 +708,16 @@ xfs_reclaim_inode(
        return 0;
 }
 
+void
+__xfs_inode_set_reclaim_tag(
+       struct xfs_perag        *pag,
+       struct xfs_inode        *ip)
+{
+       radix_tree_tag_set(&pag->pag_ici_root,
+                          XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino),
+                          XFS_ICI_RECLAIM_TAG);
+}
+
 /*
  * We set the inode flag atomically with the radix tree tag.
  * Once we get tag lookups on the radix tree, this inode flag
@@ -722,8 +732,7 @@ xfs_inode_set_reclaim_tag(
 
        read_lock(&pag->pag_ici_lock);
        spin_lock(&ip->i_flags_lock);
-       radix_tree_tag_set(&pag->pag_ici_root,
-                       XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG);
+       __xfs_inode_set_reclaim_tag(pag, ip);
        __xfs_iflags_set(ip, XFS_IRECLAIMABLE);
        spin_unlock(&ip->i_flags_lock);
        read_unlock(&pag->pag_ici_lock);
index 2a10301c99c79b8bf73e3d89a73f965ef580b23a..59120602588a370168282a3177a66c7a477bbb42 100644 (file)
@@ -48,6 +48,7 @@ int xfs_reclaim_inode(struct xfs_inode *ip, int locked, int sync_mode);
 int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
 
 void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
+void __xfs_inode_set_reclaim_tag(struct xfs_perag *pag, struct xfs_inode *ip);
 void xfs_inode_clear_reclaim_tag(struct xfs_inode *ip);
 void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, struct xfs_perag *pag,
                                struct xfs_inode *ip);
index db15feb906fffa0e38b0e44f23ef3967faea33fd..4ece1906bd41c0d801f8b66a41efb48bd3bcad6d 100644 (file)
@@ -2010,7 +2010,9 @@ xfs_attr_rmtval_get(xfs_da_args_t *args)
                        dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
                        blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
                        error = xfs_read_buf(mp, mp->m_ddev_targp, dblkno,
-                                            blkcnt, XFS_BUF_LOCK, &bp);
+                                            blkcnt,
+                                            XFS_BUF_LOCK | XBF_DONT_BLOCK,
+                                            &bp);
                        if (error)
                                return(error);
 
@@ -2141,8 +2143,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args)
                dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
                blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
 
-               bp = xfs_buf_get_flags(mp->m_ddev_targp, dblkno,
-                                                       blkcnt, XFS_BUF_LOCK);
+               bp = xfs_buf_get_flags(mp->m_ddev_targp, dblkno, blkcnt,
+                                      XFS_BUF_LOCK | XBF_DONT_BLOCK);
                ASSERT(bp);
                ASSERT(!XFS_BUF_GETERROR(bp));
 
index 7928b9983c1d53e6d0ca3c2719ce361bb95175f8..8ee5b5a76a2aff78995fb5a86926a0c9b1546bbd 100644 (file)
@@ -6009,7 +6009,7 @@ xfs_getbmap(
         */
        error = ENOMEM;
        subnex = 16;
-       map = kmem_alloc(subnex * sizeof(*map), KM_MAYFAIL);
+       map = kmem_alloc(subnex * sizeof(*map), KM_MAYFAIL | KM_NOFS);
        if (!map)
                goto out_unlock_ilock;
 
index e9df995748291047922ef29257e9423357d386db..26717388acf5a250c0ec8b039e041dbe753c0b77 100644 (file)
@@ -120,8 +120,8 @@ xfs_btree_check_sblock(
                        XFS_RANDOM_BTREE_CHECK_SBLOCK))) {
                if (bp)
                        xfs_buftrace("SBTREE ERROR", bp);
-               XFS_ERROR_REPORT("xfs_btree_check_sblock", XFS_ERRLEVEL_LOW,
-                                cur->bc_mp);
+               XFS_CORRUPTION_ERROR("xfs_btree_check_sblock",
+                       XFS_ERRLEVEL_LOW, cur->bc_mp, block);
                return XFS_ERROR(EFSCORRUPTED);
        }
        return 0;
index 9ff6e57a50758f10ddc076dc7875dad2172963a3..2847bbc1c534db4b9e2b3bd49645773678d15e07 100644 (file)
@@ -2201,7 +2201,7 @@ kmem_zone_t *xfs_dabuf_zone;              /* dabuf zone */
 xfs_da_state_t *
 xfs_da_state_alloc(void)
 {
-       return kmem_zone_zalloc(xfs_da_state_zone, KM_SLEEP);
+       return kmem_zone_zalloc(xfs_da_state_zone, KM_NOFS);
 }
 
 /*
@@ -2261,9 +2261,9 @@ xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra)
        int             off;
 
        if (nbuf == 1)
-               dabuf = kmem_zone_alloc(xfs_dabuf_zone, KM_SLEEP);
+               dabuf = kmem_zone_alloc(xfs_dabuf_zone, KM_NOFS);
        else
-               dabuf = kmem_alloc(XFS_DA_BUF_SIZE(nbuf), KM_SLEEP);
+               dabuf = kmem_alloc(XFS_DA_BUF_SIZE(nbuf), KM_NOFS);
        dabuf->dirty = 0;
 #ifdef XFS_DABUF_DEBUG
        dabuf->ra = ra;
index c657bec6d9513849f2ad86dca172e88417742f14..bb1d58eb398238e5e485a8f0bad9ce51ba141e63 100644 (file)
@@ -256,7 +256,7 @@ xfs_dir_cilookup_result(
                                        !(args->op_flags & XFS_DA_OP_CILOOKUP))
                return EEXIST;
 
-       args->value = kmem_alloc(len, KM_MAYFAIL);
+       args->value = kmem_alloc(len, KM_NOFS | KM_MAYFAIL);
        if (!args->value)
                return ENOMEM;
 
index cbd451bb4848b38e398e583ba9537540bbfce1d0..2d0b3e1da9e69094f798967e3ff432d679249f00 100644 (file)
@@ -167,17 +167,25 @@ xfs_growfs_data_private(
        new = nb - mp->m_sb.sb_dblocks;
        oagcount = mp->m_sb.sb_agcount;
        if (nagcount > oagcount) {
+               void *new_perag, *old_perag;
+
                xfs_filestream_flush(mp);
+
+               new_perag = kmem_zalloc(sizeof(xfs_perag_t) * nagcount,
+                                       KM_MAYFAIL);
+               if (!new_perag)
+                       return XFS_ERROR(ENOMEM);
+
                down_write(&mp->m_peraglock);
-               mp->m_perag = kmem_realloc(mp->m_perag,
-                       sizeof(xfs_perag_t) * nagcount,
-                       sizeof(xfs_perag_t) * oagcount,
-                       KM_SLEEP);
-               memset(&mp->m_perag[oagcount], 0,
-                       (nagcount - oagcount) * sizeof(xfs_perag_t));
+               memcpy(new_perag, mp->m_perag, sizeof(xfs_perag_t) * oagcount);
+               old_perag = mp->m_perag;
+               mp->m_perag = new_perag;
+
                mp->m_flags |= XFS_MOUNT_32BITINODES;
                nagimax = xfs_initialize_perag(mp, nagcount);
                up_write(&mp->m_peraglock);
+
+               kmem_free(old_perag);
        }
        tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
        tp->t_flags |= XFS_TRANS_RESERVE;
index 5fcec6f020a7ddff25df7e54e58750ca651733b1..ecbf8b4d2e2e4d0f8ae4506b64a4b787dc84e5db 100644 (file)
@@ -64,6 +64,10 @@ xfs_inode_alloc(
        ip = kmem_zone_alloc(xfs_inode_zone, KM_SLEEP);
        if (!ip)
                return NULL;
+       if (inode_init_always(mp->m_super, VFS_I(ip))) {
+               kmem_zone_free(xfs_inode_zone, ip);
+               return NULL;
+       }
 
        ASSERT(atomic_read(&ip->i_iocount) == 0);
        ASSERT(atomic_read(&ip->i_pincount) == 0);
@@ -105,17 +109,6 @@ xfs_inode_alloc(
 #ifdef XFS_DIR2_TRACE
        ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS);
 #endif
-       /*
-       * Now initialise the VFS inode. We do this after the xfs_inode
-       * initialisation as internal failures will result in ->destroy_inode
-       * being called and that will pass down through the reclaim path and
-       * free the XFS inode. This path requires the XFS inode to already be
-       * initialised. Hence if this call fails, the xfs_inode has already
-       * been freed and we should not reference it at all in the error
-       * handling.
-       */
-       if (!inode_init_always(mp->m_super, VFS_I(ip)))
-               return NULL;
 
        /* prevent anyone from using this yet */
        VFS_I(ip)->i_state = I_NEW|I_LOCK;
@@ -123,6 +116,71 @@ xfs_inode_alloc(
        return ip;
 }
 
+STATIC void
+xfs_inode_free(
+       struct xfs_inode        *ip)
+{
+       switch (ip->i_d.di_mode & S_IFMT) {
+       case S_IFREG:
+       case S_IFDIR:
+       case S_IFLNK:
+               xfs_idestroy_fork(ip, XFS_DATA_FORK);
+               break;
+       }
+
+       if (ip->i_afp)
+               xfs_idestroy_fork(ip, XFS_ATTR_FORK);
+
+#ifdef XFS_INODE_TRACE
+       ktrace_free(ip->i_trace);
+#endif
+#ifdef XFS_BMAP_TRACE
+       ktrace_free(ip->i_xtrace);
+#endif
+#ifdef XFS_BTREE_TRACE
+       ktrace_free(ip->i_btrace);
+#endif
+#ifdef XFS_RW_TRACE
+       ktrace_free(ip->i_rwtrace);
+#endif
+#ifdef XFS_ILOCK_TRACE
+       ktrace_free(ip->i_lock_trace);
+#endif
+#ifdef XFS_DIR2_TRACE
+       ktrace_free(ip->i_dir_trace);
+#endif
+
+       if (ip->i_itemp) {
+               /*
+                * Only if we are shutting down the fs will we see an
+                * inode still in the AIL. If it is there, we should remove
+                * it to prevent a use-after-free from occurring.
+                */
+               xfs_log_item_t  *lip = &ip->i_itemp->ili_item;
+               struct xfs_ail  *ailp = lip->li_ailp;
+
+               ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) ||
+                                      XFS_FORCED_SHUTDOWN(ip->i_mount));
+               if (lip->li_flags & XFS_LI_IN_AIL) {
+                       spin_lock(&ailp->xa_lock);
+                       if (lip->li_flags & XFS_LI_IN_AIL)
+                               xfs_trans_ail_delete(ailp, lip);
+                       else
+                               spin_unlock(&ailp->xa_lock);
+               }
+               xfs_inode_item_destroy(ip);
+               ip->i_itemp = NULL;
+       }
+
+       /* asserts to verify all state is correct here */
+       ASSERT(atomic_read(&ip->i_iocount) == 0);
+       ASSERT(atomic_read(&ip->i_pincount) == 0);
+       ASSERT(!spin_is_locked(&ip->i_flags_lock));
+       ASSERT(completion_done(&ip->i_flush));
+
+       kmem_zone_free(xfs_inode_zone, ip);
+}
+
 /*
  * Check the validity of the inode we just found it the cache
  */
@@ -133,80 +191,82 @@ xfs_iget_cache_hit(
        int                     flags,
        int                     lock_flags) __releases(pag->pag_ici_lock)
 {
+       struct inode            *inode = VFS_I(ip);
        struct xfs_mount        *mp = ip->i_mount;
-       int                     error = EAGAIN;
+       int                     error;
+
+       spin_lock(&ip->i_flags_lock);
 
        /*
-        * If INEW is set this inode is being set up
-        * If IRECLAIM is set this inode is being torn down
-        * Pause and try again.
+        * If we are racing with another cache hit that is currently
+        * instantiating this inode or currently recycling it out of
+        * reclaimabe state, wait for the initialisation to complete
+        * before continuing.
+        *
+        * XXX(hch): eventually we should do something equivalent to
+        *           wait_on_inode to wait for these flags to be cleared
+        *           instead of polling for it.
         */
-       if (xfs_iflags_test(ip, (XFS_INEW|XFS_IRECLAIM))) {
+       if (ip->i_flags & (XFS_INEW|XFS_IRECLAIM)) {
                XFS_STATS_INC(xs_ig_frecycle);
+               error = EAGAIN;
                goto out_error;
        }
 
-       /* If IRECLAIMABLE is set, we've torn down the vfs inode part */
-       if (xfs_iflags_test(ip, XFS_IRECLAIMABLE)) {
-
-               /*
-                * If lookup is racing with unlink, then we should return an
-                * error immediately so we don't remove it from the reclaim
-                * list and potentially leak the inode.
-                */
-               if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) {
-                       error = ENOENT;
-                       goto out_error;
-               }
+       /*
+        * If lookup is racing with unlink return an error immediately.
+        */
+       if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) {
+               error = ENOENT;
+               goto out_error;
+       }
 
+       /*
+        * If IRECLAIMABLE is set, we've torn down the VFS inode already.
+        * Need to carefully get it back into useable state.
+        */
+       if (ip->i_flags & XFS_IRECLAIMABLE) {
                xfs_itrace_exit_tag(ip, "xfs_iget.alloc");
 
                /*
-                * We need to re-initialise the VFS inode as it has been
-                * 'freed' by the VFS. Do this here so we can deal with
-                * errors cleanly, then tag it so it can be set up correctly
-                * later.
+                * We need to set XFS_INEW atomically with clearing the
+                * reclaimable tag so that we do have an indicator of the
+                * inode still being initialized.
                 */
-               if (!inode_init_always(mp->m_super, VFS_I(ip))) {
-                       error = ENOMEM;
-                       goto out_error;
-               }
+               ip->i_flags |= XFS_INEW;
+               ip->i_flags &= ~XFS_IRECLAIMABLE;
+               __xfs_inode_clear_reclaim_tag(mp, pag, ip);
 
-               /*
-                * We must set the XFS_INEW flag before clearing the
-                * XFS_IRECLAIMABLE flag so that if a racing lookup does
-                * not find the XFS_IRECLAIMABLE above but has the igrab()
-                * below succeed we can safely check XFS_INEW to detect
-                * that this inode is still being initialised.
-                */
-               xfs_iflags_set(ip, XFS_INEW);
-               xfs_iflags_clear(ip, XFS_IRECLAIMABLE);
+               spin_unlock(&ip->i_flags_lock);
+               read_unlock(&pag->pag_ici_lock);
 
-               /* clear the radix tree reclaim flag as well. */
-               __xfs_inode_clear_reclaim_tag(mp, pag, ip);
-       } else if (!igrab(VFS_I(ip))) {
+               error = -inode_init_always(mp->m_super, inode);
+               if (error) {
+                       /*
+                        * Re-initializing the inode failed, and we are in deep
+                        * trouble.  Try to re-add it to the reclaim list.
+                        */
+                       read_lock(&pag->pag_ici_lock);
+                       spin_lock(&ip->i_flags_lock);
+
+                       ip->i_flags &= ~XFS_INEW;
+                       ip->i_flags |= XFS_IRECLAIMABLE;
+                       __xfs_inode_set_reclaim_tag(pag, ip);
+                       goto out_error;
+               }
+               inode->i_state = I_LOCK|I_NEW;
+       } else {
                /* If the VFS inode is being torn down, pause and try again. */
-               XFS_STATS_INC(xs_ig_frecycle);
-               goto out_error;
-       } else if (xfs_iflags_test(ip, XFS_INEW)) {
-               /*
-                * We are racing with another cache hit that is
-                * currently recycling this inode out of the XFS_IRECLAIMABLE
-                * state. Wait for the initialisation to complete before
-                * continuing.
-                */
-               wait_on_inode(VFS_I(ip));
-       }
+               if (!igrab(inode)) {
+                       error = EAGAIN;
+                       goto out_error;
+               }
 
-       if (ip->i_d.di_mode == 0 && !(flags & XFS_IGET_CREATE)) {
-               error = ENOENT;
-               iput(VFS_I(ip));
-               goto out_error;
+               /* We've got a live one. */
+               spin_unlock(&ip->i_flags_lock);
+               read_unlock(&pag->pag_ici_lock);
        }
 
-       /* We've got a live one. */
-       read_unlock(&pag->pag_ici_lock);
-
        if (lock_flags != 0)
                xfs_ilock(ip, lock_flags);
 
@@ -216,6 +276,7 @@ xfs_iget_cache_hit(
        return 0;
 
 out_error:
+       spin_unlock(&ip->i_flags_lock);
        read_unlock(&pag->pag_ici_lock);
        return error;
 }
@@ -299,7 +360,8 @@ out_preload_end:
        if (lock_flags)
                xfs_iunlock(ip, lock_flags);
 out_destroy:
-       xfs_destroy_inode(ip);
+       __destroy_inode(VFS_I(ip));
+       xfs_inode_free(ip);
        return error;
 }
 
@@ -504,62 +566,7 @@ xfs_ireclaim(
        xfs_qm_dqdetach(ip);
        xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
 
-       switch (ip->i_d.di_mode & S_IFMT) {
-       case S_IFREG:
-       case S_IFDIR:
-       case S_IFLNK:
-               xfs_idestroy_fork(ip, XFS_DATA_FORK);
-               break;
-       }
-
-       if (ip->i_afp)
-               xfs_idestroy_fork(ip, XFS_ATTR_FORK);
-
-#ifdef XFS_INODE_TRACE
-       ktrace_free(ip->i_trace);
-#endif
-#ifdef XFS_BMAP_TRACE
-       ktrace_free(ip->i_xtrace);
-#endif
-#ifdef XFS_BTREE_TRACE
-       ktrace_free(ip->i_btrace);
-#endif
-#ifdef XFS_RW_TRACE
-       ktrace_free(ip->i_rwtrace);
-#endif
-#ifdef XFS_ILOCK_TRACE
-       ktrace_free(ip->i_lock_trace);
-#endif
-#ifdef XFS_DIR2_TRACE
-       ktrace_free(ip->i_dir_trace);
-#endif
-       if (ip->i_itemp) {
-               /*
-                * Only if we are shutting down the fs will we see an
-                * inode still in the AIL. If it is there, we should remove
-                * it to prevent a use-after-free from occurring.
-                */
-               xfs_log_item_t  *lip = &ip->i_itemp->ili_item;
-               struct xfs_ail  *ailp = lip->li_ailp;
-
-               ASSERT(((lip->li_flags & XFS_LI_IN_AIL) == 0) ||
-                                      XFS_FORCED_SHUTDOWN(ip->i_mount));
-               if (lip->li_flags & XFS_LI_IN_AIL) {
-                       spin_lock(&ailp->xa_lock);
-                       if (lip->li_flags & XFS_LI_IN_AIL)
-                               xfs_trans_ail_delete(ailp, lip);
-                       else
-                               spin_unlock(&ailp->xa_lock);
-               }
-               xfs_inode_item_destroy(ip);
-               ip->i_itemp = NULL;
-       }
-       /* asserts to verify all state is correct here */
-       ASSERT(atomic_read(&ip->i_iocount) == 0);
-       ASSERT(atomic_read(&ip->i_pincount) == 0);
-       ASSERT(!spin_is_locked(&ip->i_flags_lock));
-       ASSERT(completion_done(&ip->i_flush));
-       kmem_zone_free(xfs_inode_zone, ip);
+       xfs_inode_free(ip);
 }
 
 /*
index 1f22d65fed0a48d230a117f848598ba220017ad1..da428b3fe0f5777980ba58aef8c5e566334f318d 100644 (file)
@@ -343,6 +343,16 @@ xfs_iformat(
                return XFS_ERROR(EFSCORRUPTED);
        }
 
+       if (unlikely((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) &&
+                    !ip->i_mount->m_rtdev_targp)) {
+               xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+                       "corrupt dinode %Lu, has realtime flag set.",
+                       ip->i_ino);
+               XFS_CORRUPTION_ERROR("xfs_iformat(realtime)",
+                                    XFS_ERRLEVEL_LOW, ip->i_mount, dip);
+               return XFS_ERROR(EFSCORRUPTED);
+       }
+
        switch (ip->i_d.di_mode & S_IFMT) {
        case S_IFIFO:
        case S_IFCHR:
index 1804f866a71d285b760db6bd5df1574676ecb898..65f24a3cc9922a174b8989c276691e01b1e56621 100644 (file)
@@ -309,23 +309,6 @@ static inline struct inode *VFS_I(struct xfs_inode *ip)
        return &ip->i_vnode;
 }
 
-/*
- * Get rid of a partially initialized inode.
- *
- * We have to go through destroy_inode to make sure allocations
- * from init_inode_always like the security data are undone.
- *
- * We mark the inode bad so that it takes the short cut in
- * the reclaim path instead of going through the flush path
- * which doesn't make sense for an inode that has never seen the
- * light of day.
- */
-static inline void xfs_destroy_inode(struct xfs_inode *ip)
-{
-       make_bad_inode(VFS_I(ip));
-       return destroy_inode(VFS_I(ip));
-}
-
 /*
  * i_flags helper functions
  */
index 3750f04ede0bf283a4592cb05a5ce4e04884b45b..9dbdff3ea484bf008d1b634a53a2f42aedb3effc 100644 (file)
@@ -3180,7 +3180,7 @@ try_again:
 STATIC void
 xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog)
 {
-       ASSERT(spin_is_locked(&log->l_icloglock));
+       assert_spin_locked(&log->l_icloglock);
 
        if (iclog->ic_state == XLOG_STATE_ACTIVE) {
                xlog_state_switch_iclogs(log, iclog, 0);
index c4eca5ed5dabf81d6c0133294a1f6dbad73d2a4a..492d75bae2bf22f25ff52fac48953e9e95141a01 100644 (file)
@@ -538,7 +538,9 @@ xfs_readlink_bmap(
                d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
                byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
 
-               bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0);
+               bp = xfs_buf_read_flags(mp->m_ddev_targp, d, BTOBB(byte_cnt),
+                                       XBF_LOCK | XBF_MAPPED |
+                                       XBF_DONT_BLOCK);
                error = XFS_BUF_GETERROR(bp);
                if (error) {
                        xfs_ioerror_alert("xfs_readlink",
index 3e798593b17b0db94494bfeb6fc8b6c012300045..ab0b85cf21f38df08b0eb3a3b752b42e2453d8fa 100644 (file)
@@ -242,6 +242,10 @@ acpi_os_derive_pci_id(acpi_handle rhandle,
 acpi_status acpi_os_validate_interface(char *interface);
 acpi_status acpi_osi_invalidate(char* interface);
 
+acpi_status
+acpi_os_validate_address(u8 space_id, acpi_physical_address address,
+                        acpi_size length, char *name);
+
 u64 acpi_os_get_timer(void);
 
 acpi_status acpi_os_signal(u32 function, void *info);
index baf1e0a9a7ee9f4ccc309cb72e1554e7bdf46ff8..740ac3ad8fd06fc61b8e2dacc10054ec27469439 100644 (file)
@@ -174,7 +174,7 @@ struct acpi_processor_throttling {
        cpumask_var_t shared_cpu_map;
        int (*acpi_processor_get_throttling) (struct acpi_processor * pr);
        int (*acpi_processor_set_throttling) (struct acpi_processor * pr,
-                                             int state);
+                                             int state, bool force);
 
        u32 address;
        u8 duty_offset;
@@ -321,7 +321,8 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
 /* in processor_throttling.c */
 int acpi_processor_tstate_has_changed(struct acpi_processor *pr);
 int acpi_processor_get_throttling_info(struct acpi_processor *pr);
-extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
+extern int acpi_processor_set_throttling(struct acpi_processor *pr,
+                                        int state, bool force);
 extern const struct file_operations acpi_processor_throttling_fops;
 extern void acpi_processor_throttling_init(void);
 /* in processor_idle.c */
index 9d40e879f99ea968e18e07f142519c5839392003..77ff547730af53f8da5850f05ee70866b720f4b9 100644 (file)
@@ -27,9 +27,9 @@
 #define pud_page_vaddr(pud)            pgd_page_vaddr(pud)
 
 #undef pud_free_tlb
-#define pud_free_tlb(tlb, x)            do { } while (0)
+#define pud_free_tlb(tlb, x, addr)     do { } while (0)
 #define pud_free(mm, x)                        do { } while (0)
-#define __pud_free_tlb(tlb, x)         do { } while (0)
+#define __pud_free_tlb(tlb, x, addr)   do { } while (0)
 
 #undef  pud_addr_end
 #define pud_addr_end(addr, end)                (end)
index d7d50d7ee51ec0716baa0c3725ad5f5ae85602a2..aa00800adaccdfbb751e6d85786474d1775006ce 100644 (file)
@@ -97,4 +97,8 @@ extern void setup_per_cpu_areas(void);
 #define PER_CPU_ATTRIBUTES
 #endif
 
+#ifndef PER_CPU_DEF_ATTRIBUTES
+#define PER_CPU_DEF_ATTRIBUTES
+#endif
+
 #endif /* _ASM_GENERIC_PERCPU_H_ */
index a7cdc48e8b78703156456f8eb2472251e66c8d78..725612b793ce1d55462de9ab2158a795ab3b4faa 100644 (file)
@@ -59,7 +59,7 @@ static inline pmd_t * pmd_offset(pud_t * pud, unsigned long address)
 static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
 {
 }
-#define __pmd_free_tlb(tlb, x)                 do { } while (0)
+#define __pmd_free_tlb(tlb, x, a)              do { } while (0)
 
 #undef  pmd_addr_end
 #define pmd_addr_end(addr, end)                        (end)
index 87cf449a6df380e6be3a11fd24648ef3aefe588b..810431d8351b16c14c3d1954ddc2890866c41658 100644 (file)
@@ -52,7 +52,7 @@ static inline pud_t * pud_offset(pgd_t * pgd, unsigned long address)
  */
 #define pud_alloc_one(mm, address)             NULL
 #define pud_free(mm, x)                                do { } while (0)
-#define __pud_free_tlb(tlb, x)                 do { } while (0)
+#define __pud_free_tlb(tlb, x, a)              do { } while (0)
 
 #undef  pud_addr_end
 #define pud_addr_end(addr, end)                        (end)
index f490e43a90b90a09e1cfe78a9f1215b66d3df74e..e43f9766259f301b2087e83d70a1e563e568edbd 100644 (file)
@@ -123,24 +123,24 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
                __tlb_remove_tlb_entry(tlb, ptep, address);     \
        } while (0)
 
-#define pte_free_tlb(tlb, ptep)                                        \
+#define pte_free_tlb(tlb, ptep, address)                       \
        do {                                                    \
                tlb->need_flush = 1;                            \
-               __pte_free_tlb(tlb, ptep);                      \
+               __pte_free_tlb(tlb, ptep, address);             \
        } while (0)
 
 #ifndef __ARCH_HAS_4LEVEL_HACK
-#define pud_free_tlb(tlb, pudp)                                        \
+#define pud_free_tlb(tlb, pudp, address)                       \
        do {                                                    \
                tlb->need_flush = 1;                            \
-               __pud_free_tlb(tlb, pudp);                      \
+               __pud_free_tlb(tlb, pudp, address);             \
        } while (0)
 #endif
 
-#define pmd_free_tlb(tlb, pmdp)                                        \
+#define pmd_free_tlb(tlb, pmdp, address)                       \
        do {                                                    \
                tlb->need_flush = 1;                            \
-               __pmd_free_tlb(tlb, pmdp);                      \
+               __pmd_free_tlb(tlb, pmdp, address);             \
        } while (0)
 
 #define tlb_migrate_finish(mm) do {} while (0)
index 92b73b6140ff4328741ef415468b8008428215cc..6ad76bf5fb40dd03b03682fa561b943ad209650d 100644 (file)
@@ -30,9 +30,7 @@
  *     EXCEPTION_TABLE(...)
  *     NOTES
  *
- *     __bss_start = .;
- *     BSS_SECTION(0, 0)
- *     __bss_stop = .;
+ *     BSS_SECTION(0, 0, 0)
  *     _end = .;
  *
  *     /DISCARD/ : {
        . = ALIGN(align);                                               \
        *(.data.cacheline_aligned)
 
-#define INIT_TASK(align)                                               \
+#define INIT_TASK_DATA(align)                                          \
        . = ALIGN(align);                                               \
        *(.data.init_task)
 
 /*
  * Init task
  */
-#define INIT_TASK_DATA(align)                                          \
+#define INIT_TASK_DATA_SECTION(align)                                  \
        . = ALIGN(align);                                               \
        .data.init_task : {                                             \
-               INIT_TASK                                               \
+               INIT_TASK_DATA(align)                                   \
        }
 
 #ifdef CONFIG_CONSTRUCTORS
-#define KERNEL_CTORS() VMLINUX_SYMBOL(__ctors_start) = .; \
+#define KERNEL_CTORS() . = ALIGN(8);                      \
+                       VMLINUX_SYMBOL(__ctors_start) = .; \
                        *(.ctors)                          \
                        VMLINUX_SYMBOL(__ctors_end) = .;
 #else
  * bss (Block Started by Symbol) - uninitialized data
  * zeroed during startup
  */
-#define SBSS                                                           \
+#define SBSS(sbss_align)                                               \
+       . = ALIGN(sbss_align);                                          \
        .sbss : AT(ADDR(.sbss) - LOAD_OFFSET) {                         \
                *(.sbss)                                                \
                *(.scommon)                                             \
 #define BSS(bss_align)                                                 \
        . = ALIGN(bss_align);                                           \
        .bss : AT(ADDR(.bss) - LOAD_OFFSET) {                           \
-               VMLINUX_SYMBOL(__bss_start) = .;                        \
                *(.bss.page_aligned)                                    \
                *(.dynbss)                                              \
                *(.bss)                                                 \
                *(COMMON)                                               \
-               VMLINUX_SYMBOL(__bss_stop) = .;                         \
        }
 
 /*
  * matches the requirment of PAGE_ALIGNED_DATA.
  *
  * use 0 as page_align if page_aligned data is not used */
-#define RW_DATA_SECTION(cacheline, nosave, pagealigned, inittask)      \
+#define RW_DATA_SECTION(cacheline, pagealigned, inittask)              \
        . = ALIGN(PAGE_SIZE);                                           \
        .data : AT(ADDR(.data) - LOAD_OFFSET) {                         \
-               INIT_TASK(inittask)                                     \
+               INIT_TASK_DATA(inittask)                                \
                CACHELINE_ALIGNED_DATA(cacheline)                       \
                READ_MOSTLY_DATA(cacheline)                             \
                DATA_DATA                                               \
                CONSTRUCTORS                                            \
-               NOSAVE_DATA(nosave)                                     \
+               NOSAVE_DATA                                             \
                PAGE_ALIGNED_DATA(pagealigned)                          \
        }
 
                INIT_RAM_FS                                             \
        }
 
-#define BSS_SECTION(sbss_align, bss_align)                             \
-       SBSS                                                            \
+#define BSS_SECTION(sbss_align, bss_align, stop_align)                 \
+       . = ALIGN(sbss_align);                                          \
+       VMLINUX_SYMBOL(__bss_start) = .;                                \
+       SBSS(sbss_align)                                                \
        BSS(bss_align)                                                  \
-       . = ALIGN(4);
-
+       . = ALIGN(stop_align);                                          \
+       VMLINUX_SYMBOL(__bss_stop) = .;
index 010545436efa22593f4a124c9a68849f78a85872..5a2bd1cc9656b56e8462c0f8569fb6b1479609f4 100644 (file)
@@ -137,6 +137,7 @@ struct crypto_instance *crypto_alloc_instance(const char *name,
 void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen);
 int crypto_enqueue_request(struct crypto_queue *queue,
                           struct crypto_async_request *request);
+void *__crypto_dequeue_request(struct crypto_queue *queue, unsigned int offset);
 struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue);
 int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm);
 
index 2ba42cd7d6aa4c4fa708ba2733b6a20a59c3c526..3a748a6bf772b25e83e8657024cddea8f40d8026 100644 (file)
@@ -79,8 +79,8 @@ static inline int skcipher_enqueue_givcrypt(
 static inline struct skcipher_givcrypt_request *skcipher_dequeue_givcrypt(
        struct crypto_queue *queue)
 {
-       return container_of(ablkcipher_dequeue_request(queue),
-                           struct skcipher_givcrypt_request, creq);
+       return __crypto_dequeue_request(
+               queue, offsetof(struct skcipher_givcrypt_request, creq.base));
 }
 
 static inline void *skcipher_givcrypt_reqctx(
index c263e4d71754095d56ec29489f20804cab5ad3d0..7d6c9a2dfcbbb8608e400e310640511031c27f76 100644 (file)
@@ -35,11 +35,11 @@ struct est_timings {
 } __attribute__((packed));
 
 /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */
-#define EDID_TIMING_ASPECT_SHIFT 0
+#define EDID_TIMING_ASPECT_SHIFT 6
 #define EDID_TIMING_ASPECT_MASK  (0x3 << EDID_TIMING_ASPECT_SHIFT)
 
 /* need to add 60 */
-#define EDID_TIMING_VFREQ_SHIFT  2
+#define EDID_TIMING_VFREQ_SHIFT  0
 #define EDID_TIMING_VFREQ_MASK   (0x3f << EDID_TIMING_VFREQ_SHIFT)
 
 struct std_timing {
@@ -47,11 +47,11 @@ struct std_timing {
        u8 vfreq_aspect;
 } __attribute__((packed));
 
-#define DRM_EDID_PT_HSYNC_POSITIVE (1 << 6)
-#define DRM_EDID_PT_VSYNC_POSITIVE (1 << 5)
+#define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1)
+#define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2)
 #define DRM_EDID_PT_SEPARATE_SYNC  (3 << 3)
-#define DRM_EDID_PT_STEREO         (1 << 2)
-#define DRM_EDID_PT_INTERLACED     (1 << 1)
+#define DRM_EDID_PT_STEREO         (1 << 5)
+#define DRM_EDID_PT_INTERLACED     (1 << 7)
 
 /* If detailed data is pixel timing */
 struct detailed_pixel_timing {
@@ -93,7 +93,7 @@ struct detailed_data_monitor_range {
 } __attribute__((packed));
 
 struct detailed_data_wpindex {
-       u8 white_xy_lo; /* Upper 2 bits each */
+       u8 white_yx_lo; /* Lower 2 bits each */
        u8 white_x_hi;
        u8 white_y_hi;
        u8 gamma; /* need to divide by 100 then add 1 */
@@ -135,21 +135,21 @@ struct detailed_timing {
        } data;
 } __attribute__((packed));
 
-#define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 7)
-#define DRM_EDID_INPUT_SYNC_ON_GREEN   (1 << 5)
-#define DRM_EDID_INPUT_COMPOSITE_SYNC  (1 << 4)
+#define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 0)
+#define DRM_EDID_INPUT_SYNC_ON_GREEN   (1 << 1)
+#define DRM_EDID_INPUT_COMPOSITE_SYNC  (1 << 2)
 #define DRM_EDID_INPUT_SEPARATE_SYNCS  (1 << 3)
-#define DRM_EDID_INPUT_BLANK_TO_BLACK  (1 << 2)
-#define DRM_EDID_INPUT_VIDEO_LEVEL     (3 << 1)
-#define DRM_EDID_INPUT_DIGITAL         (1 << 0) /* bits above must be zero if set */
+#define DRM_EDID_INPUT_BLANK_TO_BLACK  (1 << 4)
+#define DRM_EDID_INPUT_VIDEO_LEVEL     (3 << 5)
+#define DRM_EDID_INPUT_DIGITAL         (1 << 7) /* bits below must be zero if set */
 
-#define DRM_EDID_FEATURE_DEFAULT_GTF      (1 << 7)
-#define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 6)
-#define DRM_EDID_FEATURE_STANDARD_COLOR   (1 << 5)
+#define DRM_EDID_FEATURE_DEFAULT_GTF      (1 << 0)
+#define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 1)
+#define DRM_EDID_FEATURE_STANDARD_COLOR   (1 << 2)
 #define DRM_EDID_FEATURE_DISPLAY_TYPE     (3 << 3) /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */
-#define DRM_EDID_FEATURE_PM_ACTIVE_OFF    (1 << 2)
-#define DRM_EDID_FEATURE_PM_SUSPEND       (1 << 1)
-#define DRM_EDID_FEATURE_PM_STANDBY       (1 << 0)
+#define DRM_EDID_FEATURE_PM_ACTIVE_OFF    (1 << 5)
+#define DRM_EDID_FEATURE_PM_SUSPEND       (1 << 6)
+#define DRM_EDID_FEATURE_PM_STANDBY       (1 << 7)
 
 struct edid {
        u8 header[8];
index 45c18672b0936dc50c04b0cb33f105376401db2b..853508499d20d12b5d197178e68bbc809633e55b 100644 (file)
@@ -43,6 +43,7 @@
        {0x1002, 0x4A4F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x4A50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x4A54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x4B48, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x4B49, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x4B4A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x4B4B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x940F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x94A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x94A1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x94A3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x94B1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x94B3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x94B4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x94B5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x94B9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9441, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9442, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x9443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9444, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x944A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x948F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9490, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9491, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x9495, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9498, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x949C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x949E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV730|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9552, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9553, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9555, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x9557, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV710|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9580, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9581, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9583, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV630|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9599, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV635|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x959B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV635|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95C0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x95C2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x95C4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95C5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95C6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95C7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95C9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x95C2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
-       {0x1002, 0x95C4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95CD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x95CE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV620|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x9614, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9615, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9616, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9713, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9714, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0, 0, 0}
 
 #define r128_PCI_IDS \
index 41862e9a4c2097bd2cae6e6a90d33b50fe8f751f..2ba61e18fc8bc9abd78d56e7d9bdfbe6688d274e 100644 (file)
@@ -506,6 +506,9 @@ typedef struct {
 #define DRM_RADEON_GEM_WAIT_IDLE       0x24
 #define DRM_RADEON_CS                  0x26
 #define DRM_RADEON_INFO                        0x27
+#define DRM_RADEON_GEM_SET_TILING      0x28
+#define DRM_RADEON_GEM_GET_TILING      0x29
+#define DRM_RADEON_GEM_BUSY            0x2a
 
 #define DRM_IOCTL_RADEON_CP_INIT    DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
 #define DRM_IOCTL_RADEON_CP_START   DRM_IO(  DRM_COMMAND_BASE + DRM_RADEON_CP_START)
@@ -544,7 +547,9 @@ typedef struct {
 #define DRM_IOCTL_RADEON_GEM_WAIT_IDLE DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_IDLE, struct drm_radeon_gem_wait_idle)
 #define DRM_IOCTL_RADEON_CS            DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs)
 #define DRM_IOCTL_RADEON_INFO          DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INFO, struct drm_radeon_info)
-
+#define DRM_IOCTL_RADEON_SET_TILING    DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_TILING, struct drm_radeon_gem_set_tiling)
+#define DRM_IOCTL_RADEON_GET_TILING    DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_GET_TILING, struct drm_radeon_gem_get_tiling)
+#define DRM_IOCTL_RADEON_GEM_BUSY      DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_BUSY, struct drm_radeon_gem_busy)
 
 typedef struct drm_radeon_init {
        enum {
@@ -704,6 +709,7 @@ typedef struct drm_radeon_indirect {
 #define RADEON_PARAM_FB_LOCATION           14   /* FB location */
 #define RADEON_PARAM_NUM_GB_PIPES          15   /* num GB pipes */
 #define RADEON_PARAM_DEVICE_ID             16
+#define RADEON_PARAM_NUM_Z_PIPES           17   /* num Z pipes */
 
 typedef struct drm_radeon_getparam {
        int param;
@@ -796,6 +802,24 @@ struct drm_radeon_gem_create {
        uint32_t        flags;
 };
 
+#define RADEON_TILING_MACRO 0x1
+#define RADEON_TILING_MICRO 0x2
+#define RADEON_TILING_SWAP  0x4
+#define RADEON_TILING_SURFACE  0x8 /* this object requires a surface
+                                   * when mapped - i.e. front buffer */
+
+struct drm_radeon_gem_set_tiling {
+       uint32_t        handle;
+       uint32_t        tiling_flags;
+       uint32_t        pitch;
+};
+
+struct drm_radeon_gem_get_tiling {
+       uint32_t        handle;
+       uint32_t        tiling_flags;
+       uint32_t        pitch;
+};
+
 struct drm_radeon_gem_mmap {
        uint32_t        handle;
        uint32_t        pad;
@@ -817,7 +841,7 @@ struct drm_radeon_gem_wait_idle {
 
 struct drm_radeon_gem_busy {
        uint32_t        handle;
-       uint32_t        busy;
+       uint32_t        domain;
 };
 
 struct drm_radeon_gem_pread {
@@ -874,6 +898,7 @@ struct drm_radeon_cs {
 
 #define RADEON_INFO_DEVICE_ID          0x00
 #define RADEON_INFO_NUM_GB_PIPES       0x01
+#define RADEON_INFO_NUM_Z_PIPES        0x02
 
 struct drm_radeon_info {
        uint32_t                request;
index 62ed733c52a23898a893c51bf05eb80e17995bf4..a68829db381aea2543bace257b14b4eefee3c1a8 100644 (file)
@@ -121,6 +121,7 @@ struct ttm_backend {
 #define TTM_PAGE_FLAG_SWAPPED         (1 << 4)
 #define TTM_PAGE_FLAG_PERSISTANT_SWAP (1 << 5)
 #define TTM_PAGE_FLAG_ZERO_ALLOC      (1 << 6)
+#define TTM_PAGE_FLAG_DMA32           (1 << 7)
 
 enum ttm_caching_state {
        tt_uncached,
@@ -353,6 +354,14 @@ struct ttm_bo_driver {
        int (*sync_obj_flush) (void *sync_obj, void *sync_arg);
        void (*sync_obj_unref) (void **sync_obj);
        void *(*sync_obj_ref) (void *sync_obj);
+
+       /* hook to notify driver about a driver move so it
+        * can do tiling things */
+       void (*move_notify)(struct ttm_buffer_object *bo,
+                           struct ttm_mem_reg *new_mem);
+       /* notify the driver we are taking a fault on this BO
+        * and have reserved it */
+       void (*fault_reserve_notify)(struct ttm_buffer_object *bo);
 };
 
 #define TTM_NUM_MEM_TYPES 8
@@ -429,6 +438,8 @@ struct ttm_bo_device {
         */
 
        struct delayed_work wq;
+
+       bool need_dma32;
 };
 
 /**
@@ -648,7 +659,14 @@ extern int ttm_bo_device_release(struct ttm_bo_device *bdev);
 extern int ttm_bo_device_init(struct ttm_bo_device *bdev,
                              struct ttm_mem_global *mem_glob,
                              struct ttm_bo_driver *driver,
-                             uint64_t file_page_offset);
+                             uint64_t file_page_offset, bool need_dma32);
+
+/**
+ * ttm_bo_unmap_virtual
+ *
+ * @bo: tear down the virtual mappings for this BO
+ */
+extern void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo);
 
 /**
  * ttm_bo_reserve:
index 889a4c7958ae7cd02769db1899d1a0b25689587d..d1d433834e4f85235e141f3213efbd6270e85ef3 100644 (file)
@@ -33,7 +33,7 @@
 
 #include <linux/kernel.h>
 
-#define TTM_PFX "[TTM]"
+#define TTM_PFX "[TTM] "
 
 enum ttm_global_types {
        TTM_GLOBAL_TTM_MEM = 0,
index b16a957030f87e16341efe5b41b476a04e742fc2..47f7d932a01d5d7694835b184429112f681f139b 100644 (file)
@@ -121,9 +121,9 @@ struct kiocb {
 
        /*
         * If the aio_resfd field of the userspace iocb is not zero,
-        * this is the underlying file* to deliver event to.
+        * this is the underlying eventfd context to deliver events to.
         */
-       struct file             *ki_eventfd;
+       struct eventfd_ctx      *ki_eventfd;
 };
 
 #define is_sync_kiocb(iocb)    ((iocb)->ki_key == KIOCB_SYNC_KEY)
index 0ec2c594868e657ad20cfaffc21227bf7ee2e18b..1d52425a61189e15c739a1009449e97022bd2eb8 100644 (file)
@@ -229,9 +229,14 @@ static inline int bdi_rw_congested(struct backing_dev_info *bdi)
                                  (1 << BDI_async_congested));
 }
 
-void clear_bdi_congested(struct backing_dev_info *bdi, int rw);
-void set_bdi_congested(struct backing_dev_info *bdi, int rw);
-long congestion_wait(int rw, long timeout);
+enum {
+       BLK_RW_ASYNC    = 0,
+       BLK_RW_SYNC     = 1,
+};
+
+void clear_bdi_congested(struct backing_dev_info *bdi, int sync);
+void set_bdi_congested(struct backing_dev_info *bdi, int sync);
+long congestion_wait(int sync, long timeout);
 
 
 static inline bool bdi_cap_writeback_dirty(struct backing_dev_info *bdi)
index 61ee18c1bdb44bd714b39b840d7b73b4ad02698a..2046b5b8af48ae094d0182b143450b5459b67b30 100644 (file)
@@ -117,6 +117,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm,
                           int executable_stack);
 extern int bprm_mm_init(struct linux_binprm *bprm);
 extern int copy_strings_kernel(int argc,char ** argv,struct linux_binprm *bprm);
+extern int prepare_bprm_creds(struct linux_binprm *bprm);
 extern void install_exec_creds(struct linux_binprm *bprm);
 extern void do_coredump(long signr, int exit_code, struct pt_regs *regs);
 extern int set_binfmt(struct linux_binfmt *new);
index 2a04eb54c0dd05b8eda048c8463b9a8eddabde46..2892b710771c5b112b74670c56051ccffb05e7da 100644 (file)
@@ -319,7 +319,6 @@ static inline int bio_has_allocated_vec(struct bio *bio)
  */
 struct bio_integrity_payload {
        struct bio              *bip_bio;       /* parent bio */
-       struct bio_vec          *bip_vec;       /* integrity data vector */
 
        sector_t                bip_sector;     /* virtual start sector */
 
@@ -328,11 +327,12 @@ struct bio_integrity_payload {
 
        unsigned int            bip_size;
 
-       unsigned short          bip_pool;       /* pool the ivec came from */
+       unsigned short          bip_slab;       /* slab the bip came from */
        unsigned short          bip_vcnt;       /* # of integrity bio_vecs */
        unsigned short          bip_idx;        /* current bip_vec index */
 
        struct work_struct      bip_work;       /* I/O completion */
+       struct bio_vec          bip_vec[0];     /* embedded bvec array */
 };
 #endif /* CONFIG_BLK_DEV_INTEGRITY */
 
@@ -430,6 +430,9 @@ struct bio_set {
        unsigned int front_pad;
 
        mempool_t *bio_pool;
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+       mempool_t *bio_integrity_pool;
+#endif
        mempool_t *bvec_pool;
 };
 
@@ -634,8 +637,9 @@ static inline struct bio *bio_list_get(struct bio_list *bl)
 
 #define bio_integrity(bio) (bio->bi_integrity != NULL)
 
+extern struct bio_integrity_payload *bio_integrity_alloc_bioset(struct bio *, gfp_t, unsigned int, struct bio_set *);
 extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int);
-extern void bio_integrity_free(struct bio *);
+extern void bio_integrity_free(struct bio *, struct bio_set *);
 extern int bio_integrity_add_page(struct bio *, struct page *, unsigned int, unsigned int);
 extern int bio_integrity_enabled(struct bio *bio);
 extern int bio_integrity_set_tag(struct bio *, void *, unsigned int);
@@ -645,21 +649,27 @@ extern void bio_integrity_endio(struct bio *, int);
 extern void bio_integrity_advance(struct bio *, unsigned int);
 extern void bio_integrity_trim(struct bio *, unsigned int, unsigned int);
 extern void bio_integrity_split(struct bio *, struct bio_pair *, int);
-extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t);
+extern int bio_integrity_clone(struct bio *, struct bio *, gfp_t, struct bio_set *);
+extern int bioset_integrity_create(struct bio_set *, int);
+extern void bioset_integrity_free(struct bio_set *);
+extern void bio_integrity_init(void);
 
 #else /* CONFIG_BLK_DEV_INTEGRITY */
 
 #define bio_integrity(a)               (0)
+#define bioset_integrity_create(a, b)  (0)
 #define bio_integrity_prep(a)          (0)
 #define bio_integrity_enabled(a)       (0)
-#define bio_integrity_clone(a, b, c)   (0)
-#define bio_integrity_free(a)          do { } while (0)
+#define bio_integrity_clone(a, b, c, d)        (0)
+#define bioset_integrity_free(a)       do { } while (0)
+#define bio_integrity_free(a, b)       do { } while (0)
 #define bio_integrity_endio(a, b)      do { } while (0)
 #define bio_integrity_advance(a, b)    do { } while (0)
 #define bio_integrity_trim(a, b, c)    do { } while (0)
 #define bio_integrity_split(a, b, c)   do { } while (0)
 #define bio_integrity_set_tag(a, b, c) do { } while (0)
 #define bio_integrity_get_tag(a, b, c) do { } while (0)
+#define bio_integrity_init(a)          do { } while (0)
 
 #endif /* CONFIG_BLK_DEV_INTEGRITY */
 
index 2878811c61346f09520ffdc086742c77943e91ea..756d78b8c1c5e52195fc4b0db951c883c1a07122 100644 (file)
@@ -94,13 +94,13 @@ extern void __bitmap_shift_right(unsigned long *dst,
                         const unsigned long *src, int shift, int bits);
 extern void __bitmap_shift_left(unsigned long *dst,
                         const unsigned long *src, int shift, int bits);
-extern void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
+extern int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
                        const unsigned long *bitmap2, int bits);
 extern void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
                        const unsigned long *bitmap2, int bits);
 extern void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
                        const unsigned long *bitmap2, int bits);
-extern void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
+extern int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
                        const unsigned long *bitmap2, int bits);
 extern int __bitmap_intersects(const unsigned long *bitmap1,
                        const unsigned long *bitmap2, int bits);
@@ -171,13 +171,12 @@ static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
        }
 }
 
-static inline void bitmap_and(unsigned long *dst, const unsigned long *src1,
+static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
                        const unsigned long *src2, int nbits)
 {
        if (small_const_nbits(nbits))
-               *dst = *src1 & *src2;
-       else
-               __bitmap_and(dst, src1, src2, nbits);
+               return (*dst = *src1 & *src2) != 0;
+       return __bitmap_and(dst, src1, src2, nbits);
 }
 
 static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
@@ -198,13 +197,12 @@ static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
                __bitmap_xor(dst, src1, src2, nbits);
 }
 
-static inline void bitmap_andnot(unsigned long *dst, const unsigned long *src1,
+static inline int bitmap_andnot(unsigned long *dst, const unsigned long *src1,
                        const unsigned long *src2, int nbits)
 {
        if (small_const_nbits(nbits))
-               *dst = *src1 & ~(*src2);
-       else
-               __bitmap_andnot(dst, src1, src2, nbits);
+               return (*dst = *src1 & ~(*src2)) != 0;
+       return __bitmap_andnot(dst, src1, src2, nbits);
 }
 
 static inline void bitmap_complement(unsigned long *dst, const unsigned long *src,
index 8963d9149b5fcf77e47d9b0c32379bd8f28e2476..69103e053c9266e65e28eab0a15ae2c273de1094 100644 (file)
@@ -70,11 +70,6 @@ enum rq_cmd_type_bits {
        REQ_TYPE_ATA_PC,
 };
 
-enum {
-       BLK_RW_ASYNC    = 0,
-       BLK_RW_SYNC     = 1,
-};
-
 /*
  * For request of type REQ_TYPE_LINUX_BLOCK, rq->cmd[0] is the opcode being
  * sent down (similar to how REQ_TYPE_BLOCK_PC means that ->cmd[] holds a
@@ -301,12 +296,6 @@ struct blk_queue_tag {
 #define BLK_SCSI_MAX_CMDS      (256)
 #define BLK_SCSI_CMD_PER_LONG  (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8))
 
-struct blk_cmd_filter {
-       unsigned long read_ok[BLK_SCSI_CMD_PER_LONG];
-       unsigned long write_ok[BLK_SCSI_CMD_PER_LONG];
-       struct kobject kobj;
-};
-
 struct queue_limits {
        unsigned long           bounce_pfn;
        unsigned long           seg_boundary_mask;
@@ -445,7 +434,6 @@ struct request_queue
 #if defined(CONFIG_BLK_DEV_BSG)
        struct bsg_class_device bsg_dev;
 #endif
-       struct blk_cmd_filter cmd_filter;
 };
 
 #define QUEUE_FLAG_CLUSTER     0       /* cluster several segments into 1 */
@@ -730,6 +718,7 @@ struct rq_map_data {
        int nr_entries;
        unsigned long offset;
        int null_mapped;
+       int from_user;
 };
 
 struct req_iterator {
@@ -786,18 +775,18 @@ extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t,
  * congested queues, and wake up anyone who was waiting for requests to be
  * put back.
  */
-static inline void blk_clear_queue_congested(struct request_queue *q, int rw)
+static inline void blk_clear_queue_congested(struct request_queue *q, int sync)
 {
-       clear_bdi_congested(&q->backing_dev_info, rw);
+       clear_bdi_congested(&q->backing_dev_info, sync);
 }
 
 /*
  * A queue has just entered congestion.  Flag that in the queue's VM-visible
  * state flags and increment the global gounter of congested queues.
  */
-static inline void blk_set_queue_congested(struct request_queue *q, int rw)
+static inline void blk_set_queue_congested(struct request_queue *q, int sync)
 {
-       set_bdi_congested(&q->backing_dev_info, rw);
+       set_bdi_congested(&q->backing_dev_info, sync);
 }
 
 extern void blk_start_queue(struct request_queue *q);
@@ -924,6 +913,7 @@ extern void blk_queue_logical_block_size(struct request_queue *, unsigned short)
 extern void blk_queue_physical_block_size(struct request_queue *, unsigned short);
 extern void blk_queue_alignment_offset(struct request_queue *q,
                                       unsigned int alignment);
+extern void blk_limits_io_min(struct queue_limits *limits, unsigned int min);
 extern void blk_queue_io_min(struct request_queue *q, unsigned int min);
 extern void blk_queue_io_opt(struct request_queue *q, unsigned int opt);
 extern void blk_set_default_limits(struct queue_limits *lim);
@@ -998,13 +988,7 @@ static inline int sb_issue_discard(struct super_block *sb,
        return blkdev_issue_discard(sb->s_bdev, block, nr_blocks, GFP_KERNEL);
 }
 
-/*
-* command filter functions
-*/
-extern int blk_verify_command(struct blk_cmd_filter *filter,
-                             unsigned char *cmd, fmode_t has_write_perm);
-extern void blk_unregister_filter(struct gendisk *disk);
-extern void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter);
+extern int blk_verify_command(unsigned char *cmd, fmode_t has_write_perm);
 
 #define MAX_PHYS_SEGMENTS 128
 #define MAX_HW_SEGMENTS 128
index 63bc9a4d292651b7713b32206c76c0cc5cee1495..8cc10411bab206f757bee1c87f45465e03686946 100644 (file)
@@ -140,29 +140,6 @@ void cb710_dump_regs(struct cb710_chip *chip, unsigned dump);
 #include <linux/highmem.h>
 #include <linux/scatterlist.h>
 
-/**
- * cb710_sg_miter_stop_writing - stop mapping iteration after writing
- * @miter: sg mapping iter to be stopped
- *
- * Description:
- *   Stops mapping iterator @miter.  @miter should have been started
- *   started using sg_miter_start().  A stopped iteration can be
- *   resumed by calling sg_miter_next() on it.  This is useful when
- *   resources (kmap) need to be released during iteration.
- *
- *   This is a convenience wrapper that will be optimized out for arches
- *   that don't need flush_kernel_dcache_page().
- *
- * Context:
- *   IRQ disabled if the SG_MITER_ATOMIC is set.  Don't care otherwise.
- */
-static inline void cb710_sg_miter_stop_writing(struct sg_mapping_iter *miter)
-{
-       if (miter->page)
-               flush_kernel_dcache_page(miter->page);
-       sg_miter_stop(miter);
-}
-
 /*
  * 32-bit PIO mapping sg iterator
  *
@@ -171,12 +148,12 @@ static inline void cb710_sg_miter_stop_writing(struct sg_mapping_iter *miter)
  * without DMA support).
  *
  * Best-case reading (transfer from device):
- *   sg_miter_start();
+ *   sg_miter_start(, SG_MITER_TO_SG);
  *   cb710_sg_dwiter_write_from_io();
- *   cb710_sg_miter_stop_writing();
+ *   sg_miter_stop();
  *
  * Best-case writing (transfer to device):
- *   sg_miter_start();
+ *   sg_miter_start(, SG_MITER_FROM_SG);
  *   cb710_sg_dwiter_read_to_io();
  *   sg_miter_stop();
  */
index 665fa70e4094166c76b85176f0fbb3f5f6fae7c5..90bba9e622864b88156638d231476a7889e4b125 100644 (file)
@@ -179,14 +179,11 @@ struct cgroup {
         */
        struct list_head release_list;
 
-       /* pids_mutex protects the fields below */
+       /* pids_mutex protects pids_list and cached pid arrays. */
        struct rw_semaphore pids_mutex;
-       /* Array of process ids in the cgroup */
-       pid_t *tasks_pids;
-       /* How many files are using the current tasks_pids array */
-       int pids_use_count;
-       /* Length of the current tasks_pids array */
-       int pids_length;
+
+       /* Linked list of struct cgroup_pids */
+       struct list_head pids_list;
 
        /* For RCU-protected deletion */
        struct rcu_head rcu_head;
@@ -365,6 +362,23 @@ int cgroup_task_count(const struct cgroup *cgrp);
 /* Return true if cgrp is a descendant of the task's cgroup */
 int cgroup_is_descendant(const struct cgroup *cgrp, struct task_struct *task);
 
+/*
+ * When the subsys has to access css and may add permanent refcnt to css,
+ * it should take care of racy conditions with rmdir(). Following set of
+ * functions, is for stop/restart rmdir if necessary.
+ * Because these will call css_get/put, "css" should be alive css.
+ *
+ *  cgroup_exclude_rmdir();
+ *  ...do some jobs which may access arbitrary empty cgroup
+ *  cgroup_release_and_wakeup_rmdir();
+ *
+ *  When someone removes a cgroup while cgroup_exclude_rmdir() holds it,
+ *  it sleeps and cgroup_release_and_wakeup_rmdir() will wake him up.
+ */
+
+void cgroup_exclude_rmdir(struct cgroup_subsys_state *css);
+void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css);
+
 /*
  * Control Group subsystem type.
  * See Documentation/cgroups/cgroups.txt for details
index 20a100fe2b4f3040554f3994706d8f7b238460af..3a1dbba4d3ae2da500e710387d130cd8ad5dd4c2 100644 (file)
@@ -143,12 +143,3 @@ extern void clockevents_notify(unsigned long reason, void *arg);
 #endif
 
 #endif
-
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
-extern ktime_t clockevents_get_next_event(int cpu);
-#else
-static inline ktime_t clockevents_get_next_event(int cpu)
-{
-       return (ktime_t) { .tv64 = KTIME_MAX };
-}
-#endif
index c56457c8334eea7ece9236c963fec845791909ba..1219be4fb42e8f2a86e9e1268dfe7958fde8263c 100644 (file)
@@ -293,7 +293,12 @@ static inline int clocksource_enable(struct clocksource *cs)
        if (cs->enable)
                ret = cs->enable(cs);
 
-       /* save mult_orig on enable */
+       /*
+        * The frequency may have changed while the clocksource
+        * was disabled. If so the code in ->enable() must update
+        * the mult value to reflect the new frequency. Make sure
+        * mult_orig follows this change.
+        */
        cs->mult_orig = cs->mult;
 
        return ret;
@@ -309,6 +314,13 @@ static inline int clocksource_enable(struct clocksource *cs)
  */
 static inline void clocksource_disable(struct clocksource *cs)
 {
+       /*
+        * Save mult_orig in mult so clocksource_enable() can
+        * restore the value regardless if ->enable() updates
+        * the value of mult or not.
+        */
+       cs->mult = cs->mult_orig;
+
        if (cs->disable)
                cs->disable(cs);
 }
index d71f7c0f931b34b63bfacde2b06d19ffc5001616..38fe59dc89aefaa97871270371f28ff74bf8ca3f 100644 (file)
@@ -89,7 +89,6 @@ struct vc_data {
        unsigned int    vc_need_wrap    : 1;
        unsigned int    vc_can_do_color : 1;
        unsigned int    vc_report_mouse : 2;
-       unsigned int    vc_kmalloced    : 1;
        unsigned char   vc_utf          : 1;    /* Unicode UTF-8 encoding */
        unsigned char   vc_utf_count;
                 int    vc_utf_char;
index c5ac87ca7bc647d32caef606c9c26ab0bb606090..796df12091b7687a450d26e57c4acf6ecc15b34d 100644 (file)
  * int cpu_isset(cpu, mask)            true iff bit 'cpu' set in mask
  * int cpu_test_and_set(cpu, mask)     test and set bit 'cpu' in mask
  *
- * void cpus_and(dst, src1, src2)      dst = src1 & src2  [intersection]
+ * int cpus_and(dst, src1, src2)       dst = src1 & src2  [intersection]
  * void cpus_or(dst, src1, src2)       dst = src1 | src2  [union]
  * void cpus_xor(dst, src1, src2)      dst = src1 ^ src2
- * void cpus_andnot(dst, src1, src2)   dst = src1 & ~src2
+ * int cpus_andnot(dst, src1, src2)    dst = src1 & ~src2
  * void cpus_complement(dst, src)      dst = ~src
  *
  * int cpus_equal(mask1, mask2)                Does mask1 == mask2?
@@ -179,10 +179,10 @@ static inline int __cpu_test_and_set(int cpu, cpumask_t *addr)
 }
 
 #define cpus_and(dst, src1, src2) __cpus_and(&(dst), &(src1), &(src2), NR_CPUS)
-static inline void __cpus_and(cpumask_t *dstp, const cpumask_t *src1p,
+static inline int __cpus_and(cpumask_t *dstp, const cpumask_t *src1p,
                                        const cpumask_t *src2p, int nbits)
 {
-       bitmap_and(dstp->bits, src1p->bits, src2p->bits, nbits);
+       return bitmap_and(dstp->bits, src1p->bits, src2p->bits, nbits);
 }
 
 #define cpus_or(dst, src1, src2) __cpus_or(&(dst), &(src1), &(src2), NR_CPUS)
@@ -201,10 +201,10 @@ static inline void __cpus_xor(cpumask_t *dstp, const cpumask_t *src1p,
 
 #define cpus_andnot(dst, src1, src2) \
                                __cpus_andnot(&(dst), &(src1), &(src2), NR_CPUS)
-static inline void __cpus_andnot(cpumask_t *dstp, const cpumask_t *src1p,
+static inline int __cpus_andnot(cpumask_t *dstp, const cpumask_t *src1p,
                                        const cpumask_t *src2p, int nbits)
 {
-       bitmap_andnot(dstp->bits, src1p->bits, src2p->bits, nbits);
+       return bitmap_andnot(dstp->bits, src1p->bits, src2p->bits, nbits);
 }
 
 #define cpus_complement(dst, src) __cpus_complement(&(dst), &(src), NR_CPUS)
@@ -738,11 +738,11 @@ static inline void cpumask_clear(struct cpumask *dstp)
  * @src1p: the first input
  * @src2p: the second input
  */
-static inline void cpumask_and(struct cpumask *dstp,
+static inline int cpumask_and(struct cpumask *dstp,
                               const struct cpumask *src1p,
                               const struct cpumask *src2p)
 {
-       bitmap_and(cpumask_bits(dstp), cpumask_bits(src1p),
+       return bitmap_and(cpumask_bits(dstp), cpumask_bits(src1p),
                                       cpumask_bits(src2p), nr_cpumask_bits);
 }
 
@@ -779,11 +779,11 @@ static inline void cpumask_xor(struct cpumask *dstp,
  * @src1p: the first input
  * @src2p: the second input
  */
-static inline void cpumask_andnot(struct cpumask *dstp,
+static inline int cpumask_andnot(struct cpumask *dstp,
                                  const struct cpumask *src1p,
                                  const struct cpumask *src2p)
 {
-       bitmap_andnot(cpumask_bits(dstp), cpumask_bits(src1p),
+       return bitmap_andnot(cpumask_bits(dstp), cpumask_bits(src1p),
                                          cpumask_bits(src2p), nr_cpumask_bits);
 }
 
index 2dac064d8359046c178f0d98bd9ea915ca369eaa..0026f267da20d6e9f1a0dc5343b978c1e5f0b6f1 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef CONFIG_CRASH_DUMP
 #include <linux/kexec.h>
-#include <linux/smp_lock.h>
 #include <linux/device.h>
 #include <linux/proc_fs.h>
 
index 6dfb856327bbe714300ae004cba6787d59d961d0..0c7111a55a1aaf101dd5aefbef1f77036ed599d6 100644 (file)
@@ -1,31 +1,37 @@
 #ifndef DECOMPRESS_GENERIC_H
 #define DECOMPRESS_GENERIC_H
 
-/* Minimal chunksize to be read.
- *Bzip2 prefers at least 4096
- *Lzma prefers 0x10000 */
-#define COMPR_IOBUF_SIZE       4096
-
 typedef int (*decompress_fn) (unsigned char *inbuf, int len,
                              int(*fill)(void*, unsigned int),
-                             int(*writebb)(void*, unsigned int),
-                             unsigned char *output,
+                             int(*flush)(void*, unsigned int),
+                             unsigned char *outbuf,
                              int *posp,
                              void(*error)(char *x));
 
 /* inbuf   - input buffer
  *len     - len of pre-read data in inbuf
- *fill    - function to fill inbuf if empty
- *writebb - function to write out outbug
+ *fill    - function to fill inbuf when empty
+ *flush   - function to write out outbuf
+ *outbuf  - output buffer
  *posp    - if non-null, input position (number of bytes read) will be
  *       returned here
  *
- *If len != 0, the inbuf is initialized (with as much data), and fill
- *should not be called
- *If len = 0, the inbuf is allocated, but empty. Its size is IOBUF_SIZE
- *fill should be called (repeatedly...) to read data, at most IOBUF_SIZE
+ *If len != 0, inbuf should contain all the necessary input data, and fill
+ *should be NULL
+ *If len = 0, inbuf can be NULL, in which case the decompressor will allocate
+ *the input buffer.  If inbuf != NULL it must be at least XXX_IOBUF_SIZE bytes.
+ *fill will be called (repeatedly...) to read data, at most XXX_IOBUF_SIZE
+ *bytes should be read per call.  Replace XXX with the appropriate decompressor
+ *name, i.e. LZMA_IOBUF_SIZE.
+ *
+ *If flush = NULL, outbuf must be large enough to buffer all the expected
+ *output.  If flush != NULL, the output buffer will be allocated by the
+ *decompressor (outbuf = NULL), and the flush function will be called to
+ *flush the output buffer at the appropriate time (decompressor and stream
+ *dependent).
  */
 
+
 /* Utility routine to detect the decompression method */
 decompress_fn decompress_method(const unsigned char *inbuf, int len,
                                const char **name);
index 0d6310657f32a41cc6f5af7150f13db9c35a51e7..df7607e6dce80ec188d061524103fbdf822cd2a7 100644 (file)
@@ -84,13 +84,16 @@ typedef int (*dm_merge_fn) (struct dm_target *ti, struct bvec_merge_data *bvm,
 
 typedef int (*iterate_devices_callout_fn) (struct dm_target *ti,
                                           struct dm_dev *dev,
-                                          sector_t physical_start,
+                                          sector_t start, sector_t len,
                                           void *data);
 
 typedef int (*dm_iterate_devices_fn) (struct dm_target *ti,
                                      iterate_devices_callout_fn fn,
                                      void *data);
 
+typedef void (*dm_io_hints_fn) (struct dm_target *ti,
+                               struct queue_limits *limits);
+
 /*
  * Returns:
  *    0: The target can handle the next I/O immediately.
@@ -104,7 +107,7 @@ void dm_error(const char *message);
  * Combine device limits.
  */
 int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
-                        sector_t start, void *data);
+                        sector_t start, sector_t len, void *data);
 
 struct dm_dev {
        struct block_device *bdev;
@@ -151,6 +154,7 @@ struct target_type {
        dm_merge_fn merge;
        dm_busy_fn busy;
        dm_iterate_devices_fn iterate_devices;
+       dm_io_hints_fn io_hints;
 
        /* For internal device-mapper use. */
        struct list_head list;
index ed4e39f2c4230da03f93651f5d323f805cdb6c94..aebb81036db2d368a7b55664f5a2b9d102c5109d 100644 (file)
@@ -25,8 +25,6 @@
 #include <asm/atomic.h>
 #include <asm/device.h>
 
-#define BUS_ID_SIZE            20
-
 struct device;
 struct device_private;
 struct device_driver;
index 642e3017b51f9415db90bd968c00484ed4a3def3..8a1f972c0fe97a0ceaf4fa8b6c99f1d42ac84d33 100644 (file)
        (DM_ULOG_REQUEST_MASK & (request_type))
 
 struct dm_ulog_request {
-       char uuid[DM_UUID_LEN]; /* Ties a request to a specific mirror log */
+       /*
+        * The local unique identifier (luid) and the universally unique
+        * identifier (uuid) are used to tie a request to a specific
+        * mirror log.  A single machine log could probably make due with
+        * just the 'luid', but a cluster-aware log must use the 'uuid' and
+        * the 'luid'.  The uuid is what is required for node to node
+        * communication concerning a particular log, but the 'luid' helps
+        * differentiate between logs that are being swapped and have the
+        * same 'uuid'.  (Think "live" and "inactive" device-mapper tables.)
+        */
+       uint64_t luid;
+       char uuid[DM_UUID_LEN];
        char padding[7];        /* Padding because DM_UUID_LEN = 129 */
 
        int32_t error;          /* Used to report back processing errors */
index 7605c5e9589f4cc9d08c4aca7ccebd3f707fb710..00d6a68d04215e7e289a3451ca4a8f714e2b6975 100644 (file)
@@ -122,9 +122,10 @@ static inline void elf_core_copy_kernel_regs(elf_gregset_t *elfregs, struct pt_r
 
 static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* elfregs)
 {
-#ifdef ELF_CORE_COPY_TASK_REGS
-       
+#if defined (ELF_CORE_COPY_TASK_REGS)
        return ELF_CORE_COPY_TASK_REGS(t, elfregs);
+#elif defined (task_pt_regs)
+       elf_core_copy_regs(elfregs, task_pt_regs(t));
 #endif
        return 0;
 }
index f45a8ae5f8281bc51348b942a36899b8355f13d9..3b85ba6479f48e31f3173de8c2ff86959a190bb3 100644 (file)
@@ -8,10 +8,8 @@
 #ifndef _LINUX_EVENTFD_H
 #define _LINUX_EVENTFD_H
 
-#ifdef CONFIG_EVENTFD
-
-/* For O_CLOEXEC and O_NONBLOCK */
 #include <linux/fcntl.h>
+#include <linux/file.h>
 
 /*
  * CAREFUL: Check include/asm-generic/fcntl.h when defining
 #define EFD_SHARED_FCNTL_FLAGS (O_CLOEXEC | O_NONBLOCK)
 #define EFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS | EFD_SEMAPHORE)
 
+#ifdef CONFIG_EVENTFD
+
+struct eventfd_ctx *eventfd_ctx_get(struct eventfd_ctx *ctx);
+void eventfd_ctx_put(struct eventfd_ctx *ctx);
 struct file *eventfd_fget(int fd);
-int eventfd_signal(struct file *file, int n);
+struct eventfd_ctx *eventfd_ctx_fdget(int fd);
+struct eventfd_ctx *eventfd_ctx_fileget(struct file *file);
+int eventfd_signal(struct eventfd_ctx *ctx, int n);
 
 #else /* CONFIG_EVENTFD */
 
-#define eventfd_fget(fd) ERR_PTR(-ENOSYS)
-static inline int eventfd_signal(struct file *file, int n)
-{ return 0; }
+/*
+ * Ugly ugly ugly error layer to support modules that uses eventfd but
+ * pretend to work in !CONFIG_EVENTFD configurations. Namely, AIO.
+ */
+static inline struct eventfd_ctx *eventfd_ctx_fdget(int fd)
+{
+       return ERR_PTR(-ENOSYS);
+}
+
+static inline int eventfd_signal(struct eventfd_ctx *ctx, int n)
+{
+       return -ENOSYS;
+}
+
+static inline void eventfd_ctx_put(struct eventfd_ctx *ctx)
+{
+
+}
 
-#endif /* CONFIG_EVENTFD */
+#endif
 
 #endif /* _LINUX_EVENTFD_H */
 
index 634a5e5aba3e219844fbffadce72b0361c794203..7499b36677985240f73743c9993c0ceadd16bc5b 100644 (file)
@@ -874,7 +874,7 @@ 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_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 create);
 
 extern struct inode *ext3_iget(struct super_block *, unsigned long);
 extern int  ext3_write_inode (struct inode *, int);
index dd68358996b716da2b1be8e1ab9069b282ab9902..f847df9e99b6f4fcd44991e757c1d5b7ca50681a 100644 (file)
@@ -819,6 +819,7 @@ struct fb_info {
        int node;
        int flags;
        struct mutex lock;              /* Lock for open/release/ioctl funcs */
+       struct mutex mm_lock;           /* Lock for fb_mmap and smem_* fields */
        struct fb_var_screeninfo var;   /* Current var */
        struct fb_fix_screeninfo fix;   /* Current fix */
        struct fb_monspecs monspecs;    /* Current Monitor specs */
index 9823946adbc513af5f2784b9f7c7a97f622d1a36..192d1e43c43c394ce14a967ee32ecbd3de261606 100644 (file)
@@ -127,6 +127,7 @@ struct fw_card {
        struct delayed_work work;
        int bm_retries;
        int bm_generation;
+       __be32 bm_transaction_data[2];
 
        bool broadcast_channel_allocated;
        u32 broadcast_channel;
diff --git a/include/linux/flex_array.h b/include/linux/flex_array.h
new file mode 100644 (file)
index 0000000..45ff184
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef _FLEX_ARRAY_H
+#define _FLEX_ARRAY_H
+
+#include <linux/types.h>
+#include <asm/page.h>
+
+#define FLEX_ARRAY_PART_SIZE PAGE_SIZE
+#define FLEX_ARRAY_BASE_SIZE PAGE_SIZE
+
+struct flex_array_part;
+
+/*
+ * This is meant to replace cases where an array-like
+ * structure has gotten too big to fit into kmalloc()
+ * and the developer is getting tempted to use
+ * vmalloc().
+ */
+
+struct flex_array {
+       union {
+               struct {
+                       int element_size;
+                       int total_nr_elements;
+                       struct flex_array_part *parts[];
+               };
+               /*
+                * This little trick makes sure that
+                * sizeof(flex_array) == PAGE_SIZE
+                */
+               char padding[FLEX_ARRAY_BASE_SIZE];
+       };
+};
+
+#define FLEX_ARRAY_INIT(size, total) { { {\
+       .element_size = (size),         \
+       .total_nr_elements = (total),   \
+} } }
+
+struct flex_array *flex_array_alloc(int element_size, unsigned int total,
+               gfp_t flags);
+int flex_array_prealloc(struct flex_array *fa, unsigned int start,
+               unsigned int end, gfp_t flags);
+void flex_array_free(struct flex_array *fa);
+void flex_array_free_parts(struct flex_array *fa);
+int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src,
+               gfp_t flags);
+void *flex_array_get(struct flex_array *fa, unsigned int element_nr);
+
+#endif /* _FLEX_ARRAY_H */
index 0872372184fe159a62475b48a99a1a6a26d8f1cd..3972ffb597c58c1a41bf9483c231593bd43783e5 100644 (file)
@@ -1946,6 +1946,7 @@ extern void putname(const char *name);
 extern int register_blkdev(unsigned int, const char *);
 extern void unregister_blkdev(unsigned int, const char *);
 extern struct block_device *bdget(dev_t);
+extern struct block_device *bdgrab(struct block_device *bdev);
 extern void bd_set_size(struct block_device *, loff_t size);
 extern void bd_forget(struct inode *inode);
 extern void bdput(struct block_device *);
@@ -1997,12 +1998,25 @@ extern void bd_release_from_disk(struct block_device *, struct gendisk *);
 #define CHRDEV_MAJOR_HASH_SIZE 255
 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 *,
-                          const struct file_operations *);
-extern void unregister_chrdev(unsigned int, const char *);
+extern int __register_chrdev(unsigned int major, unsigned int baseminor,
+                            unsigned int count, const char *name,
+                            const struct file_operations *fops);
+extern void __unregister_chrdev(unsigned int major, unsigned int baseminor,
+                               unsigned int count, const char *name);
 extern void unregister_chrdev_region(dev_t, unsigned);
 extern void chrdev_show(struct seq_file *,off_t);
 
+static inline int register_chrdev(unsigned int major, const char *name,
+                                 const struct file_operations *fops)
+{
+       return __register_chrdev(major, 0, 256, name, fops);
+}
+
+static inline void unregister_chrdev(unsigned int major, const char *name)
+{
+       __unregister_chrdev(major, 0, 256, name);
+}
+
 /* fs/block_dev.c */
 #define BDEVNAME_SIZE  32      /* Largest string for a blockdev identifier */
 #define BDEVT_SIZE     10      /* Largest string for MAJ:MIN for blkdev */
@@ -2122,7 +2136,7 @@ extern struct file *do_filp_open(int dfd, const char *pathname,
                int open_flag, int mode, int acc_mode);
 extern int may_open(struct path *, int, int);
 
-extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
+extern int kernel_read(struct file *, loff_t, char *, unsigned long);
 extern struct file * open_exec(const char *);
  
 /* fs/dcache.c -- generic fs support functions */
@@ -2136,7 +2150,7 @@ extern loff_t default_llseek(struct file *file, loff_t offset, int origin);
 
 extern loff_t vfs_llseek(struct file *file, loff_t offset, int origin);
 
-extern struct inode * inode_init_always(struct super_block *, struct inode *);
+extern int inode_init_always(struct super_block *, struct inode *);
 extern void inode_init_once(struct inode *);
 extern void inode_add_to_lists(struct super_block *, struct inode *);
 extern void iput(struct inode *);
@@ -2163,6 +2177,7 @@ extern void __iget(struct inode * inode);
 extern void iget_failed(struct inode *);
 extern void clear_inode(struct inode *);
 extern void destroy_inode(struct inode *);
+extern void __destroy_inode(struct inode *);
 extern struct inode *new_inode(struct super_block *);
 extern int should_remove_suid(struct dentry *);
 extern int file_remove_suid(struct file *);
index 44848aa830dcd9def22f98785df0fda957bce1d4..4d6f47b51189742aedf4c5ef3f379ff2db7aead5 100644 (file)
@@ -280,7 +280,7 @@ static inline void __fsnotify_update_dcache_flags(struct dentry *dentry)
        assert_spin_locked(&dentry->d_lock);
 
        parent = dentry->d_parent;
-       if (fsnotify_inode_watches_children(parent->d_inode))
+       if (parent->d_inode && fsnotify_inode_watches_children(parent->d_inode))
                dentry->d_flags |= DCACHE_FSNOTIFY_PARENT_WATCHED;
        else
                dentry->d_flags &= ~DCACHE_FSNOTIFY_PARENT_WATCHED;
@@ -352,7 +352,7 @@ extern void fsnotify_unmount_inodes(struct list_head *list);
 /* put here because inotify does some weird stuff when destroying watches */
 extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
                                                    void *data, int data_is, const char *name,
-                                                   u32 cookie);
+                                                   u32 cookie, gfp_t gfp);
 
 #else
 
index 5c093ffc655bfd36c1579f539d5520a0ded30c15..a81170de7f6bf4907faf644495831aad0c8fc30a 100644 (file)
@@ -89,7 +89,9 @@ enum print_line_t {
        TRACE_TYPE_NO_CONSUME   = 3     /* Handled but ask to not consume */
 };
 
-
+void tracing_generic_entry_update(struct trace_entry *entry,
+                                 unsigned long flags,
+                                 int pc);
 struct ring_buffer_event *
 trace_current_buffer_lock_reserve(int type, unsigned long len,
                                  unsigned long flags, int pc);
@@ -119,11 +121,9 @@ struct ftrace_event_call {
        void                    *filter;
        void                    *mod;
 
-#ifdef CONFIG_EVENT_PROFILE
-       atomic_t        profile_count;
-       int             (*profile_enable)(struct ftrace_event_call *);
-       void            (*profile_disable)(struct ftrace_event_call *);
-#endif
+       atomic_t                profile_count;
+       int                     (*profile_enable)(struct ftrace_event_call *);
+       void                    (*profile_disable)(struct ftrace_event_call *);
 };
 
 #define MAX_FILTER_PRED                32
index d41ed593f79fe01f8cc5ea25b3e6ea000cdc0e4c..cf593bf9fd3253a3fbc2ae963ff95f1b3a5c3ccf 100644 (file)
  *  - add IOCTL message
  *  - add unsolicited notification support
  *  - add POLL message and NOTIFY_POLL notification
+ *
+ * 7.12
+ *  - add umask flag to input argument of open, mknod and mkdir
+ *  - add notification messages for invalidation of inodes and
+ *    directory entries
  */
 
 #ifndef _LINUX_FUSE_H
@@ -36,7 +41,7 @@
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 11
+#define FUSE_KERNEL_MINOR_VERSION 12
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -112,6 +117,7 @@ struct fuse_file_lock {
  * INIT request/reply flags
  *
  * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".."
+ * FUSE_DONT_MASK: don't apply umask to file mode on create operations
  */
 #define FUSE_ASYNC_READ                (1 << 0)
 #define FUSE_POSIX_LOCKS       (1 << 1)
@@ -119,6 +125,7 @@ struct fuse_file_lock {
 #define FUSE_ATOMIC_O_TRUNC    (1 << 3)
 #define FUSE_EXPORT_SUPPORT    (1 << 4)
 #define FUSE_BIG_WRITES                (1 << 5)
+#define FUSE_DONT_MASK         (1 << 6)
 
 /**
  * CUSE INIT request/reply flags
@@ -224,6 +231,8 @@ enum fuse_opcode {
 
 enum fuse_notify_code {
        FUSE_NOTIFY_POLL   = 1,
+       FUSE_NOTIFY_INVAL_INODE = 2,
+       FUSE_NOTIFY_INVAL_ENTRY = 3,
        FUSE_NOTIFY_CODE_MAX,
 };
 
@@ -262,14 +271,18 @@ struct fuse_attr_out {
        struct fuse_attr attr;
 };
 
+#define FUSE_COMPAT_MKNOD_IN_SIZE 8
+
 struct fuse_mknod_in {
        __u32   mode;
        __u32   rdev;
+       __u32   umask;
+       __u32   padding;
 };
 
 struct fuse_mkdir_in {
        __u32   mode;
-       __u32   padding;
+       __u32   umask;
 };
 
 struct fuse_rename_in {
@@ -300,8 +313,15 @@ struct fuse_setattr_in {
 };
 
 struct fuse_open_in {
+       __u32   flags;
+       __u32   unused;
+};
+
+struct fuse_create_in {
        __u32   flags;
        __u32   mode;
+       __u32   umask;
+       __u32   padding;
 };
 
 struct fuse_open_out {
@@ -508,4 +528,16 @@ struct fuse_dirent {
 #define FUSE_DIRENT_SIZE(d) \
        FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
 
+struct fuse_notify_inval_inode_out {
+       __u64   ino;
+       __s64   off;
+       __s64   len;
+};
+
+struct fuse_notify_inval_entry_out {
+       __u64   parent;
+       __u32   namelen;
+       __u32   padding;
+};
+
 #endif /* _LINUX_FUSE_H */
index 0ffa41df0ee8ca007d9cda5b40fdbe315ee0a845..710e901085d0237195ca7a3d30b91b537287dc77 100644 (file)
@@ -19,6 +19,11 @@ enum {
  * @packets: number of seen packets
  */
 struct gnet_stats_basic
+{
+       __u64   bytes;
+       __u32   packets;
+};
+struct gnet_stats_basic_packed
 {
        __u64   bytes;
        __u32   packets;
index 45257475623cad94c90304d82b4b5cd68bc498d8..8246c697863d72cec6bae27889d0149a88ab830f 100644 (file)
@@ -2,7 +2,9 @@
 #define LINUX_HARDIRQ_H
 
 #include <linux/preempt.h>
+#ifdef CONFIG_PREEMPT
 #include <linux/smp_lock.h>
+#endif
 #include <linux/lockdep.h>
 #include <linux/ftrace_irq.h>
 #include <asm/hardirq.h>
index 7400900de94a692320c771e8881661e10ebe51b7..4759917adc71ae371da1cc3a45d46b22a55d4015 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/list.h>
 #include <linux/wait.h>
 #include <linux/percpu.h>
+#include <linux/timer.h>
 
 
 struct hrtimer_clock_base;
@@ -447,6 +448,8 @@ extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
 
 static inline void timer_stats_account_hrtimer(struct hrtimer *timer)
 {
+       if (likely(!timer->start_site))
+               return;
        timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
                                 timer->function, timer->start_comm, 0);
 }
@@ -456,6 +459,8 @@ extern void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer,
 
 static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer)
 {
+       if (likely(!timer_stats_active))
+               return;
        __timer_stats_hrtimer_set_start_info(timer, __builtin_return_address(0));
 }
 
index 2723513a5651b493a27c41191aa7be3e04b5af60..5cbc620bdfe060dba93399143b5d76e354093dc7 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/tlbflush.h>
 
 struct ctl_table;
+struct user_struct;
 
 int PageHuge(struct page *page);
 
@@ -146,7 +147,8 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb)
 
 extern const struct file_operations hugetlbfs_file_operations;
 extern struct vm_operations_struct hugetlb_vm_ops;
-struct file *hugetlb_file_setup(const char *name, size_t, int);
+struct file *hugetlb_file_setup(const char *name, size_t size, int acct,
+                                               struct user_struct **user);
 int hugetlb_get_quota(struct address_space *mapping, long delta);
 void hugetlb_put_quota(struct address_space *mapping, long delta);
 
@@ -168,7 +170,7 @@ static inline void set_file_hugepages(struct file *file)
 
 #define is_file_hugepages(file)                        0
 #define set_file_hugepages(file)               BUG()
-#define hugetlb_file_setup(name,size,acctflag) ERR_PTR(-ENOSYS)
+#define hugetlb_file_setup(name,size,acct,user)        ERR_PTR(-ENOSYS)
 
 #endif /* !CONFIG_HUGETLBFS */
 
index 95c6e00a72e826e709258734554a8d70091247c5..edc93a6d931db45fecc9ba3064aecb0619ea6115 100644 (file)
@@ -1062,7 +1062,6 @@ int generic_ide_ioctl(ide_drive_t *, struct block_device *, unsigned, unsigned l
 extern int ide_vlb_clk;
 extern int ide_pci_clk;
 
-unsigned int ide_rq_bytes(struct request *);
 int ide_end_rq(ide_drive_t *, struct request *, int, unsigned int);
 void ide_kill_rq(ide_drive_t *, struct request *);
 
@@ -1361,7 +1360,6 @@ int ide_in_drive_list(u16 *, const struct drive_list_entry *);
 #ifdef CONFIG_BLK_DEV_IDEDMA
 int ide_dma_good_drive(ide_drive_t *);
 int __ide_dma_bad_drive(ide_drive_t *);
-int ide_id_dma_bug(ide_drive_t *);
 
 u8 ide_find_dma_mode(ide_drive_t *, u8);
 
@@ -1402,7 +1400,6 @@ void ide_dma_lost_irq(ide_drive_t *);
 ide_startstop_t ide_dma_timeout_retry(ide_drive_t *, int);
 
 #else
-static inline int ide_id_dma_bug(ide_drive_t *drive) { return 0; }
 static inline u8 ide_find_dma_mode(ide_drive_t *drive, u8 speed) { return 0; }
 static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; }
 static inline void ide_dma_off_quietly(ide_drive_t *drive) { ; }
@@ -1422,6 +1419,7 @@ static inline void ide_dma_unmap_sg(ide_drive_t *drive,
 
 #ifdef CONFIG_BLK_DEV_IDEACPI
 int ide_acpi_init(void);
+bool ide_port_acpi(ide_hwif_t *hwif);
 extern int ide_acpi_exec_tfs(ide_drive_t *drive);
 extern void ide_acpi_get_timing(ide_hwif_t *hwif);
 extern void ide_acpi_push_timing(ide_hwif_t *hwif);
@@ -1430,6 +1428,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *);
 extern void ide_acpi_set_state(ide_hwif_t *hwif, int on);
 #else
 static inline int ide_acpi_init(void) { return 0; }
+static inline bool ide_port_acpi(ide_hwif_t *hwif) { return 0; }
 static inline int ide_acpi_exec_tfs(ide_drive_t *drive) { return 0; }
 static inline void ide_acpi_get_timing(ide_hwif_t *hwif) { ; }
 static inline void ide_acpi_push_timing(ide_hwif_t *hwif) { ; }
index ae3a1871413dd031b41edcd9e4159f92a1363081..70fdba2bbf7160788c5876462500d553da8bf710 100644 (file)
@@ -78,6 +78,7 @@
 #define ETH_P_PAE      0x888E          /* Port Access Entity (IEEE 802.1X) */
 #define ETH_P_AOE      0x88A2          /* ATA over Ethernet            */
 #define ETH_P_TIPC     0x88CA          /* TIPC                         */
+#define ETH_P_1588     0x88F7          /* IEEE 1588 Timesync */
 #define ETH_P_FCOE     0x8906          /* Fibre Channel over Ethernet  */
 #define ETH_P_FIP      0x8914          /* FCoE Initialization Protocol */
 #define ETH_P_EDSA     0xDADA          /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
index b1b827d091a995e3d5b2e4a0d1e7f18e975e9319..0e3f2a4c25f6ef0270f8e007a985a21cb74d6234 100644 (file)
@@ -24,6 +24,7 @@ extern int ima_path_check(struct path *path, int mask, int update_counts);
 extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
 extern void ima_counts_get(struct file *file);
+extern void ima_counts_put(struct path *path, int mask);
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -60,5 +61,10 @@ static inline void ima_counts_get(struct file *file)
 {
        return;
 }
+
+static inline void ima_counts_put(struct path *path, int mask)
+{
+       return;
+}
 #endif /* CONFIG_IMA_H */
 #endif /* _LINUX_IMA_H */
index acef2a770b6bce589b2cf6e84680e892b235a351..ad27c7da87986da346da3d62f29e88bec957280a 100644 (file)
@@ -82,7 +82,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
 
 #define IN_DEV_FORWARD(in_dev)         IN_DEV_CONF_GET((in_dev), FORWARDING)
 #define IN_DEV_MFORWARD(in_dev)                IN_DEV_ANDCONF((in_dev), MC_FORWARDING)
-#define IN_DEV_RPFILTER(in_dev)                IN_DEV_ANDCONF((in_dev), RP_FILTER)
+#define IN_DEV_RPFILTER(in_dev)                IN_DEV_MAXCONF((in_dev), RP_FILTER)
 #define IN_DEV_SOURCE_ROUTE(in_dev)    IN_DEV_ANDCONF((in_dev), \
                                                       ACCEPT_SOURCE_ROUTE)
 #define IN_DEV_BOOTP_RELAY(in_dev)     IN_DEV_ANDCONF((in_dev), BOOTP_RELAY)
index 5368fbdc78018c573c9f20a1dab76adbc8cb0f24..7fc01b13be43cfdd7b089b2e8498971f6440d253 100644 (file)
@@ -183,5 +183,8 @@ extern struct cred init_cred;
        LIST_HEAD_INIT(cpu_timers[2]),                                  \
 }
 
+/* Attach to the init_task data structure for proper alignment */
+#define __init_task_data __attribute__((__section__(".data.init_task")))
+
 
 #endif
diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h
new file mode 100644 (file)
index 0000000..15d5903
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef _MATRIX_KEYPAD_H
+#define _MATRIX_KEYPAD_H
+
+#include <linux/types.h>
+#include <linux/input.h>
+
+#define MATRIX_MAX_ROWS                16
+#define MATRIX_MAX_COLS                16
+
+#define KEY(row, col, val)     ((((row) & (MATRIX_MAX_ROWS - 1)) << 24) |\
+                                (((col) & (MATRIX_MAX_COLS - 1)) << 16) |\
+                                (val & 0xffff))
+
+#define KEY_ROW(k)             (((k) >> 24) & 0xff)
+#define KEY_COL(k)             (((k) >> 16) & 0xff)
+#define KEY_VAL(k)             ((k) & 0xffff)
+
+#define MATRIX_SCAN_CODE(row, col, row_shift)  (((row) << (row_shift)) + (col))
+
+/**
+ * struct matrix_keymap_data - keymap for matrix keyboards
+ * @keymap: pointer to array of uint32 values encoded with KEY() macro
+ *     representing keymap
+ * @keymap_size: number of entries (initialized) in this keymap
+ *
+ * This structure is supposed to be used by platform code to supply
+ * keymaps to drivers that implement matrix-like keypads/keyboards.
+ */
+struct matrix_keymap_data {
+       const uint32_t *keymap;
+       unsigned int    keymap_size;
+};
+
+/**
+ * struct matrix_keypad_platform_data - platform-dependent keypad data
+ * @keymap_data: pointer to &matrix_keymap_data
+ * @row_gpios: pointer to array of gpio numbers representing rows
+ * @col_gpios: pointer to array of gpio numbers reporesenting colums
+ * @num_row_gpios: actual number of row gpios used by device
+ * @num_col_gpios: actual number of col gpios used by device
+ * @col_scan_delay_us: delay, measured in microseconds, that is
+ *     needed before we can keypad after activating column gpio
+ * @debounce_ms: debounce interval in milliseconds
+ *
+ * This structure represents platform-specific data that use used by
+ * matrix_keypad driver to perform proper initialization.
+ */
+struct matrix_keypad_platform_data {
+       const struct matrix_keymap_data *keymap_data;
+
+       const unsigned int *row_gpios;
+       const unsigned int *col_gpios;
+
+       unsigned int    num_row_gpios;
+       unsigned int    num_col_gpios;
+
+       unsigned int    col_scan_delay_us;
+
+       /* key debounce interval in milli-second */
+       unsigned int    debounce_ms;
+
+       bool            active_low;
+       bool            wakeup;
+};
+
+#endif /* _MATRIX_KEYPAD_H */
index 2721f07e93548150a195123bb13e02e1bfa4664b..35e7df1e9f309c7d1ee1aadce99660e969222980 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/irqflags.h>
 #include <linux/smp.h>
 #include <linux/percpu.h>
+#include <linux/hrtimer.h>
 
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
  * IRQTF_RUNTHREAD - signals that the interrupt handler thread should run
  * IRQTF_DIED      - handler thread died
  * IRQTF_WARNED    - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed
+ * IRQTF_AFFINITY  - irq thread is requested to adjust affinity
  */
 enum {
        IRQTF_RUNTHREAD,
        IRQTF_DIED,
        IRQTF_WARNED,
+       IRQTF_AFFINITY,
 };
 
 typedef irqreturn_t (*irq_handler_t)(int, void *);
@@ -517,6 +520,31 @@ extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu);
 extern void tasklet_init(struct tasklet_struct *t,
                         void (*func)(unsigned long), unsigned long data);
 
+struct tasklet_hrtimer {
+       struct hrtimer          timer;
+       struct tasklet_struct   tasklet;
+       enum hrtimer_restart    (*function)(struct hrtimer *);
+};
+
+extern void
+tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
+                    enum hrtimer_restart (*function)(struct hrtimer *),
+                    clockid_t which_clock, enum hrtimer_mode mode);
+
+static inline
+int tasklet_hrtimer_start(struct tasklet_hrtimer *ttimer, ktime_t time,
+                         const enum hrtimer_mode mode)
+{
+       return hrtimer_start(&ttimer->timer, time, mode);
+}
+
+static inline
+void tasklet_hrtimer_cancel(struct tasklet_hrtimer *ttimer)
+{
+       hrtimer_cancel(&ttimer->timer);
+       tasklet_kill(&ttimer->tasklet);
+}
+
 /*
  * Autoprobing for irqs:
  *
index dd05434fa45f206f1e7c18995bcbe49fbb741a85..4da4a75c3f1e7df3690f83c102bef5cdd824f7b5 100644 (file)
@@ -92,7 +92,7 @@ static inline struct io_context *ioc_task_link(struct io_context *ioc)
         * a race).
         */
        if (ioc && atomic_long_inc_not_zero(&ioc->refcount)) {
-               atomic_long_inc(&ioc->refcount);
+               atomic_inc(&ioc->nr_tasks);
                return ioc;
        }
 
index fac104e7186ae0bb13ef19ceaaf87022446af966..d6320a3e8def0fc22a9595d8ff03f52c08983404 100644 (file)
@@ -303,6 +303,7 @@ extern int oops_in_progress;                /* If set, an oops, panic(), BUG() or die() is in
 extern int panic_timeout;
 extern int panic_on_oops;
 extern int panic_on_unrecovered_nmi;
+extern int panic_on_io_nmi;
 extern const char *print_tainted(void);
 extern void add_taint(unsigned flag);
 extern int test_taint(unsigned flag);
index 7796aed6cdd5fdbb47a67b95b9a610f6417a384b..6a63807f714e197b59ad639149803af270e20e93 100644 (file)
@@ -27,6 +27,7 @@ extern void kmemleak_init(void);
 extern void kmemleak_alloc(const void *ptr, size_t size, int min_count,
                           gfp_t gfp);
 extern void kmemleak_free(const void *ptr);
+extern void kmemleak_free_part(const void *ptr, size_t size);
 extern void kmemleak_padding(const void *ptr, unsigned long offset,
                             size_t size);
 extern void kmemleak_not_leak(const void *ptr);
@@ -71,6 +72,9 @@ static inline void kmemleak_alloc_recursive(const void *ptr, size_t size,
 static inline void kmemleak_free(const void *ptr)
 {
 }
+static inline void kmemleak_free_part(const void *ptr, size_t size)
+{
+}
 static inline void kmemleak_free_recursive(const void *ptr, unsigned long flags)
 {
 }
index aacc5449f586376a6551518c2a946a7a151ada46..3060bdc35ffe86ab3c8e5edfaa5c7fc68020a0ed 100644 (file)
@@ -110,6 +110,7 @@ struct kvm_memory_slot {
 
 struct kvm_kernel_irq_routing_entry {
        u32 gsi;
+       u32 type;
        int (*set)(struct kvm_kernel_irq_routing_entry *e,
                    struct kvm *kvm, int level);
        union {
@@ -125,6 +126,7 @@ struct kvm_kernel_irq_routing_entry {
 struct kvm {
        struct mutex lock; /* protects the vcpus array and APIC accesses */
        spinlock_t mmu_lock;
+       spinlock_t requests_lock;
        struct rw_semaphore slots_lock;
        struct mm_struct *mm; /* userspace tied to this vm */
        int nmemslots;
diff --git a/include/linux/leds-lp3944.h b/include/linux/leds-lp3944.h
new file mode 100644 (file)
index 0000000..afc9f9f
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * leds-lp3944.h - platform data structure for lp3944 led controller
+ *
+ * Copyright (C) 2009 Antonio Ospite <ospite@studenti.unina.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.
+ *
+ */
+
+#ifndef __LINUX_LEDS_LP3944_H
+#define __LINUX_LEDS_LP3944_H
+
+#include <linux/leds.h>
+#include <linux/workqueue.h>
+
+#define LP3944_LED0 0
+#define LP3944_LED1 1
+#define LP3944_LED2 2
+#define LP3944_LED3 3
+#define LP3944_LED4 4
+#define LP3944_LED5 5
+#define LP3944_LED6 6
+#define LP3944_LED7 7
+#define LP3944_LEDS_MAX 8
+
+#define LP3944_LED_STATUS_MASK 0x03
+enum lp3944_status {
+       LP3944_LED_STATUS_OFF  = 0x0,
+       LP3944_LED_STATUS_ON   = 0x1,
+       LP3944_LED_STATUS_DIM0 = 0x2,
+       LP3944_LED_STATUS_DIM1 = 0x3
+};
+
+enum lp3944_type {
+       LP3944_LED_TYPE_NONE,
+       LP3944_LED_TYPE_LED,
+       LP3944_LED_TYPE_LED_INVERTED,
+};
+
+struct lp3944_led {
+       char *name;
+       enum lp3944_type type;
+       enum lp3944_status status;
+};
+
+struct lp3944_platform_data {
+       struct lp3944_led leds[LP3944_LEDS_MAX];
+       u8 leds_size;
+};
+
+#endif /* __LINUX_LEDS_LP3944_H */
index 376fe07732ea9261dc81f3ff7411d49ac9051fb3..d8bf9665e70cc09b40d781a82c638e1b95dd82af 100644 (file)
@@ -45,7 +45,10 @@ struct led_classdev {
        /* Get LED brightness level */
        enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);
 
-       /* Activate hardware accelerated blink */
+       /* Activate hardware accelerated blink, delays are in
+        * miliseconds and if none is provided then a sensible default
+        * should be chosen. The call can adjust the timings if it can't
+        * match the values specified exactly. */
        int             (*blink_set)(struct led_classdev *led_cdev,
                                     unsigned long *delay_on,
                                     unsigned long *delay_off);
@@ -141,9 +144,14 @@ struct gpio_led {
        const char *name;
        const char *default_trigger;
        unsigned        gpio;
-       u8              active_low : 1;
-       u8              retain_state_suspended : 1;
+       unsigned        active_low : 1;
+       unsigned        retain_state_suspended : 1;
+       unsigned        default_state : 2;
+       /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */
 };
+#define LEDS_GPIO_DEFSTATE_OFF 0
+#define LEDS_GPIO_DEFSTATE_ON  1
+#define LEDS_GPIO_DEFSTATE_KEEP        2
 
 struct gpio_led_platform_data {
        int             num_leds;
index 7bc1440fc47305418967134e2f65e0e23ea24572..2fb1dcbcb5aa8fbdbbd05d8d071aac9b650334b8 100644 (file)
@@ -1,5 +1,7 @@
-/* Things the lguest guest needs to know.  Note: like all lguest interfaces,
- * this is subject to wild and random change between versions. */
+/*
+ * Things the lguest guest needs to know.  Note: like all lguest interfaces,
+ * this is subject to wild and random change between versions.
+ */
 #ifndef _LINUX_LGUEST_H
 #define _LINUX_LGUEST_H
 
 #define LG_CLOCK_MIN_DELTA     100UL
 #define LG_CLOCK_MAX_DELTA     ULONG_MAX
 
-/*G:032 The second method of communicating with the Host is to via "struct
+/*G:031
+ * The second method of communicating with the Host is to via "struct
  * lguest_data".  Once the Guest's initialization hypercall tells the Host where
- * this is, the Guest and Host both publish information in it. :*/
-struct lguest_data
-{
-       /* 512 == enabled (same as eflags in normal hardware).  The Guest
-        * changes interrupts so often that a hypercall is too slow. */
+ * this is, the Guest and Host both publish information in it.
+:*/
+struct lguest_data {
+       /*
+        * 512 == enabled (same as eflags in normal hardware).  The Guest
+        * changes interrupts so often that a hypercall is too slow.
+        */
        unsigned int irq_enabled;
        /* Fine-grained interrupt disabling by the Guest */
        DECLARE_BITMAP(blocked_interrupts, LGUEST_IRQS);
 
-       /* The Host writes the virtual address of the last page fault here,
+       /*
+        * The Host writes the virtual address of the last page fault here,
         * which saves the Guest a hypercall.  CR2 is the native register where
-        * this address would normally be found. */
+        * this address would normally be found.
+        */
        unsigned long cr2;
 
        /* Wallclock time set by the Host. */
        struct timespec time;
 
-       /* Interrupt pending set by the Host.  The Guest should do a hypercall
-        * if it re-enables interrupts and sees this set (to X86_EFLAGS_IF). */
+       /*
+        * Interrupt pending set by the Host.  The Guest should do a hypercall
+        * if it re-enables interrupts and sees this set (to X86_EFLAGS_IF).
+        */
        int irq_pending;
 
-       /* Async hypercall ring.  Instead of directly making hypercalls, we can
+       /*
+        * Async hypercall ring.  Instead of directly making hypercalls, we can
         * place them in here for processing the next time the Host wants.
-        * This batching can be quite efficient. */
+        * This batching can be quite efficient.
+        */
 
        /* 0xFF == done (set by Host), 0 == pending (set by Guest). */
        u8 hcall_status[LHCALL_RING_SIZE];
index bfefbdf7498a925856ec5e8425a5df24eb4cbac7..495203ff221c3e4039557fffafa56b22d38882c3 100644 (file)
@@ -29,8 +29,10 @@ struct lguest_device_desc {
        __u8 type;
        /* The number of virtqueues (first in config array) */
        __u8 num_vq;
-       /* The number of bytes of feature bits.  Multiply by 2: one for host
-        * features and one for Guest acknowledgements. */
+       /*
+        * The number of bytes of feature bits.  Multiply by 2: one for host
+        * features and one for Guest acknowledgements.
+        */
        __u8 feature_len;
        /* The number of bytes of the config array after virtqueues. */
        __u8 config_len;
@@ -39,8 +41,10 @@ struct lguest_device_desc {
        __u8 config[0];
 };
 
-/*D:135 This is how we expect the device configuration field for a virtqueue
- * to be laid out in config space. */
+/*D:135
+ * This is how we expect the device configuration field for a virtqueue
+ * to be laid out in config space.
+ */
 struct lguest_vqconfig {
        /* The number of entries in the virtio_ring */
        __u16 num;
@@ -61,7 +65,9 @@ enum lguest_req
        LHREQ_EVENTFD, /* + address, fd. */
 };
 
-/* The alignment to use between consumer and producer parts of vring.
- * x86 pagesize for historical reasons. */
+/*
+ * The alignment to use between consumer and producer parts of vring.
+ * x86 pagesize for historical reasons.
+ */
 #define LGUEST_VRING_ALIGN     4096
 #endif /* _LINUX_LGUEST_LAUNCHER */
index 3d501db36a26a52f0f960e59fc8e1a1504356c58..e5b6e33c65710a6f82593387e1f8e18663394ff4 100644 (file)
@@ -385,6 +385,7 @@ enum {
                                                    not multiple of 16 bytes */
        ATA_HORKAGE_FIRMWARE_WARN = (1 << 12),  /* firmware update warning */
        ATA_HORKAGE_1_5_GBPS    = (1 << 13),    /* force 1.5 Gbps */
+       ATA_HORKAGE_NOSETXFER   = (1 << 14),    /* skip SETXFER, SATA only */
 
         /* DMA mask for user DMA control: User visible values; DO NOT
            renumber */
@@ -588,6 +589,7 @@ struct ata_device {
 #endif
        /* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */
        u64                     n_sectors;      /* size of device, if ATA */
+       u64                     n_native_sectors; /* native size, if ATA */
        unsigned int            class;          /* ATA_DEV_xxx */
        unsigned long           unpark_deadline;
 
index fee9e59649c12faee1a8bb573b51fa5758ca884b..691f59171c6c722e52faaeaed4e086d46f646eb2 100644 (file)
 #define __page_aligned_data    __section(.data.page_aligned) __aligned(PAGE_SIZE)
 #define __page_aligned_bss     __section(.bss.page_aligned) __aligned(PAGE_SIZE)
 
+/*
+ * For assembly routines.
+ *
+ * Note when using these that you must specify the appropriate
+ * alignment directives yourself
+ */
+#define __PAGE_ALIGNED_DATA    .section ".data.page_aligned", "aw"
+#define __PAGE_ALIGNED_BSS     .section ".bss.page_aligned", "aw"
+
 /*
  * This is used by architectures to keep arguments on the stack
  * untouched by the compiler by keeping them live until the end.
index c46c89505dac3721e4e337d26c283419cc01a68c..2442e3f3d03335ff5e515d0876f64cadfa3f6dbe 100644 (file)
@@ -51,7 +51,7 @@ extern u64 __init lmb_alloc_base(u64 size,
 extern u64 __init __lmb_alloc_base(u64 size,
                u64 align, u64 max_addr);
 extern u64 __init lmb_phys_mem_size(void);
-extern u64 __init lmb_end_of_DRAM(void);
+extern u64 lmb_end_of_DRAM(void);
 extern void __init lmb_enforce_memory_limit(u64 memory_limit);
 extern int __init lmb_is_reserved(u64 addr);
 extern int lmb_find(struct lmb_property *res);
index d006e93d5c93c3323da45ebd14d0f7920722120b..9a72cc78e6b817d2b7c24b076eef7bd0061235f2 100644 (file)
@@ -34,8 +34,6 @@ extern int sysctl_legacy_va_layout;
 #define sysctl_legacy_va_layout 0
 #endif
 
-extern unsigned long mmap_min_addr;
-
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -574,19 +572,6 @@ static inline void set_page_links(struct page *page, enum zone_type zone,
        set_page_section(page, pfn_to_section_nr(pfn));
 }
 
-/*
- * If a hint addr is less than mmap_min_addr change hint to be as
- * low as possible but still greater than mmap_min_addr
- */
-static inline unsigned long round_hint_to_min(unsigned long hint)
-{
-       hint &= PAGE_MASK;
-       if (((void *)hint != NULL) &&
-           (hint < mmap_min_addr))
-               return PAGE_ALIGN(mmap_min_addr);
-       return hint;
-}
-
 /*
  * Some inline functions in vmstat.h depend on page_zone()
  */
@@ -826,7 +811,7 @@ extern int make_pages_present(unsigned long addr, unsigned long end);
 extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write);
 
 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
-                       unsigned long start, int len, int write, int force,
+                       unsigned long start, int nr_pages, int write, int force,
                        struct page **pages, struct vm_area_struct **vmas);
 int get_user_pages_fast(unsigned long start, int nr_pages, int write,
                        struct page **pages);
index 7acc8439d9b305caad3d8354ee7ad43e0a3de465..0042090a4d70cd839a97c6b436ea91f8ddf51d40 100644 (file)
@@ -240,8 +240,6 @@ struct mm_struct {
 
        unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
 
-       s8 oom_adj;     /* OOM kill score adjustment (bit shift) */
-
        cpumask_t cpu_vm_mask;
 
        /* Architecture-specific MM context */
index 3beb2592b03f54a09a4d2c8cb922951f8cc3fcd5..d74785c2393ad03976925e8ea6b63e3716718b79 100644 (file)
@@ -2,10 +2,9 @@
 #define _NAMESPACE_H_
 #ifdef __KERNEL__
 
-#include <linux/mount.h>
-#include <linux/sched.h>
-#include <linux/nsproxy.h>
+#include <linux/path.h>
 #include <linux/seq_file.h>
+#include <linux/wait.h>
 
 struct mnt_namespace {
        atomic_t                count;
@@ -28,14 +27,6 @@ extern struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt);
 extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
                struct fs_struct *);
 extern void put_mnt_ns(struct mnt_namespace *ns);
-
-static inline void exit_mnt_ns(struct task_struct *p)
-{
-       struct mnt_namespace *ns = p->nsproxy->mnt_ns;
-       if (ns)
-               put_mnt_ns(ns);
-}
-
 static inline void get_mnt_ns(struct mnt_namespace *ns)
 {
        atomic_inc(&ns->count);
index 5675b63a0631fd46b54f5e3f6781b4b9b87c6936..0f32a9b6ff554ac2a59468e8b17bb37d15de6339 100644 (file)
@@ -251,7 +251,7 @@ struct mtd_info {
 
 static inline struct mtd_info *dev_to_mtd(struct device *dev)
 {
-       return dev ? container_of(dev, struct mtd_info, dev) : NULL;
+       return dev ? dev_get_drvdata(dev) : NULL;
 }
 
 static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
index af6dcb992bc35896a131d58c4871570436c5b795..b70313d33ff8ba0390889c7a87b8415ac6f3b27c 100644 (file)
@@ -47,6 +47,8 @@ struct mtd_partition {
 #define MTDPART_SIZ_FULL       (0)
 
 
+struct mtd_info;
+
 int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
 int del_mtd_partitions(struct mtd_info *);
 
index 3430c775194828b6cea57984d14c6c80d45c5fe4..7ae05338e94c3bce924c3dac8eb87875abe237a6 100644 (file)
@@ -81,4 +81,17 @@ struct xt_conntrack_mtinfo1 {
        __u8 state_mask, status_mask;
 };
 
+struct xt_conntrack_mtinfo2 {
+       union nf_inet_addr origsrc_addr, origsrc_mask;
+       union nf_inet_addr origdst_addr, origdst_mask;
+       union nf_inet_addr replsrc_addr, replsrc_mask;
+       union nf_inet_addr repldst_addr, repldst_mask;
+       __u32 expires_min, expires_max;
+       __u16 l4proto;
+       __be16 origsrc_port, origdst_port;
+       __be16 replsrc_port, repldst_port;
+       __u16 match_flags, invert_flags;
+       __u16 state_mask, status_mask;
+};
+
 #endif /*_XT_CONNTRACK_H*/
index fd2272e0959a4377cc54bf65b03cdd1cf57caed7..18afa495f9737b9915732b953729ee7f2dd91459 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef _XT_OSF_H
 #define _XT_OSF_H
 
+#include <linux/types.h>
+
 #define MAXGENRELEN            32
 
 #define XT_OSF_GENRE           (1<<0)
index fdffb413b19276e7f7c9a2cc49bf7ec84e80a7cf..f6b90240dd41fc9c43b624c3b844b6f3879ce2c8 100644 (file)
@@ -473,7 +473,6 @@ 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 int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
-extern void nfs_writedata_release(void *);
 
 /*
  * Try to write back everything synchronously (but check the
@@ -488,7 +487,6 @@ extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
 extern int  nfs_commit_inode(struct inode *, int);
 extern struct nfs_write_data *nfs_commitdata_alloc(void);
 extern void nfs_commit_free(struct nfs_write_data *wdata);
-extern void nfs_commitdata_release(void *wdata);
 #else
 static inline int
 nfs_commit_inode(struct inode *inode, int how)
@@ -507,6 +505,7 @@ nfs_have_writebacks(struct inode *inode)
  * Allocate nfs_write_data structures
  */
 extern struct nfs_write_data *nfs_writedata_alloc(unsigned int npages);
+extern void nfs_writedata_free(struct nfs_write_data *);
 
 /*
  * linux/fs/nfs/read.c
@@ -515,7 +514,6 @@ extern int  nfs_readpage(struct file *, struct page *);
 extern int  nfs_readpages(struct file *, struct address_space *,
                struct list_head *, unsigned);
 extern int  nfs_readpage_result(struct rpc_task *, struct nfs_read_data *);
-extern void nfs_readdata_release(void *data);
 extern int  nfs_readpage_async(struct nfs_open_context *, struct inode *,
                               struct page *);
 
@@ -523,6 +521,7 @@ extern int  nfs_readpage_async(struct nfs_open_context *, struct inode *,
  * Allocate nfs_read_data structures
  */
 extern struct nfs_read_data *nfs_readdata_alloc(unsigned int npages);
+extern void nfs_readdata_free(struct nfs_read_data *);
 
 /*
  * linux/fs/nfs3proc.c
index 829b94b156f28ec0ed7c0d8dbc2dfeab4ea6825b..b359c4a9ec9e8decdaef46083c78d045dc5d156e 100644 (file)
  *    to generate slightly worse code.  So use a simple one-line #define
  *    for node_isset(), instead of wrapping an inline inside a macro, the
  *    way we do the other calls.
+ *
+ * NODEMASK_SCRATCH
+ * When doing above logical AND, OR, XOR, Remap operations the callers tend to
+ * need temporary nodemask_t's on the stack. But if NODES_SHIFT is large,
+ * nodemask_t's consume too much stack space.  NODEMASK_SCRATCH is a helper
+ * for such situations. See below and CPUMASK_ALLOC also.
  */
 
 #include <linux/kernel.h>
@@ -473,4 +479,26 @@ static inline int num_node_state(enum node_states state)
 #define for_each_node(node)       for_each_node_state(node, N_POSSIBLE)
 #define for_each_online_node(node) for_each_node_state(node, N_ONLINE)
 
+/*
+ * For nodemask scrach area.(See CPUMASK_ALLOC() in cpumask.h)
+ */
+
+#if NODES_SHIFT > 8 /* nodemask_t > 64 bytes */
+#define NODEMASK_ALLOC(x, m) struct x *m = kmalloc(sizeof(*m), GFP_KERNEL)
+#define NODEMASK_FREE(m) kfree(m)
+#else
+#define NODEMASK_ALLOC(x, m) struct x _m, *m = &_m
+#define NODEMASK_FREE(m)
+#endif
+
+/* A example struture for using NODEMASK_ALLOC, used in mempolicy. */
+struct nodemask_scratch {
+       nodemask_t      mask1;
+       nodemask_t      mask2;
+};
+
+#define NODEMASK_SCRATCH(x) NODEMASK_ALLOC(nodemask_scratch, x)
+#define NODEMASK_SCRATCH_FREE(x)  NODEMASK_FREE(x)
+
+
 #endif /* __LINUX_NODEMASK_H */
index c9663c6903033bb95378bf567b91f8b6ca16242b..53b94e025c7c7ae7b167ecd1cdf836fe51c09897 100644 (file)
@@ -18,5 +18,8 @@ extern struct phy_device *of_phy_connect(struct net_device *dev,
                                         struct device_node *phy_np,
                                         void (*hndlr)(struct net_device *),
                                         u32 flags, phy_interface_t iface);
+extern struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
+                                        void (*hndlr)(struct net_device *),
+                                        phy_interface_t iface);
 
 #endif /* __LINUX_OF_MDIO_H */
index d304ddf412d064750956d9ee689fcb42a4b86706..115fb7ba508907ce85704f1f2a9eb7bac5b9be4c 100644 (file)
@@ -1145,7 +1145,7 @@ static inline void pci_set_drvdata(struct pci_dev *pdev, void *data)
 /* If you want to know what to call your pci_dev, ask this function.
  * Again, it's a wrapper around the generic device.
  */
-static inline const char *pci_name(struct pci_dev *pdev)
+static inline const char *pci_name(const struct pci_dev *pdev)
 {
        return dev_name(&pdev->dev);
 }
index a3b0003657955da3651542059572387fda381308..73b46b6b904fc87b977ceeaae2b462c5ac0f5e60 100644 (file)
 #define PCI_DEVICE_ID_NETMOS_9835      0x9835
 #define PCI_DEVICE_ID_NETMOS_9845      0x9845
 #define PCI_DEVICE_ID_NETMOS_9855      0x9855
+#define PCI_DEVICE_ID_NETMOS_9901      0x9901
 
 #define PCI_VENDOR_ID_3COM_2           0xa727
 
index 8f921d74f49f12d2922dc492943bb7aa2356ea86..68438e18fff4fde80a80af87a00748a3a69b44b7 100644 (file)
@@ -24,7 +24,8 @@
 
 #define DEFINE_PER_CPU_SECTION(type, name, section)                    \
        __attribute__((__section__(PER_CPU_BASE_SECTION section)))      \
-       PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name
+       PER_CPU_ATTRIBUTES PER_CPU_DEF_ATTRIBUTES                       \
+       __typeof__(type) per_cpu__##name
 
 /*
  * Variant on the per-CPU variable declaration/definition theme used for
index 89698d8aba5c1dc1f92dbc6cbf6addd8f96790f4..b53f7006cc4e0bb5e1ad5f09ae76249d150d2ca4 100644 (file)
@@ -115,26 +115,44 @@ enum perf_counter_sample_format {
        PERF_SAMPLE_TID                         = 1U << 1,
        PERF_SAMPLE_TIME                        = 1U << 2,
        PERF_SAMPLE_ADDR                        = 1U << 3,
-       PERF_SAMPLE_GROUP                       = 1U << 4,
+       PERF_SAMPLE_READ                        = 1U << 4,
        PERF_SAMPLE_CALLCHAIN                   = 1U << 5,
        PERF_SAMPLE_ID                          = 1U << 6,
        PERF_SAMPLE_CPU                         = 1U << 7,
        PERF_SAMPLE_PERIOD                      = 1U << 8,
+       PERF_SAMPLE_STREAM_ID                   = 1U << 9,
+       PERF_SAMPLE_RAW                         = 1U << 10,
 
-       PERF_SAMPLE_MAX = 1U << 9,              /* non-ABI */
+       PERF_SAMPLE_MAX = 1U << 11,             /* non-ABI */
 };
 
 /*
- * Bits that can be set in attr.read_format to request that
- * reads on the counter should return the indicated quantities,
- * in increasing order of bit value, after the counter value.
+ * The format of the data returned by read() on a perf counter fd,
+ * as specified by attr.read_format:
+ *
+ * struct read_format {
+ *     { u64           value;
+ *       { u64         time_enabled; } && PERF_FORMAT_ENABLED
+ *       { u64         time_running; } && PERF_FORMAT_RUNNING
+ *       { u64         id;           } && PERF_FORMAT_ID
+ *     } && !PERF_FORMAT_GROUP
+ *
+ *     { u64           nr;
+ *       { u64         time_enabled; } && PERF_FORMAT_ENABLED
+ *       { u64         time_running; } && PERF_FORMAT_RUNNING
+ *       { u64         value;
+ *         { u64       id;           } && PERF_FORMAT_ID
+ *       }             cntr[nr];
+ *     } && PERF_FORMAT_GROUP
+ * };
  */
 enum perf_counter_read_format {
        PERF_FORMAT_TOTAL_TIME_ENABLED          = 1U << 0,
        PERF_FORMAT_TOTAL_TIME_RUNNING          = 1U << 1,
        PERF_FORMAT_ID                          = 1U << 2,
+       PERF_FORMAT_GROUP                       = 1U << 3,
 
-       PERF_FORMAT_MAX = 1U << 3,              /* non-ABI */
+       PERF_FORMAT_MAX = 1U << 4,              /* non-ABI */
 };
 
 #define PERF_ATTR_SIZE_VER0    64      /* sizeof first published struct */
@@ -178,8 +196,11 @@ struct perf_counter_attr {
                                mmap           :  1, /* include mmap data     */
                                comm           :  1, /* include comm data     */
                                freq           :  1, /* use freq, not period  */
+                               inherit_stat   :  1, /* per task counts       */
+                               enable_on_exec :  1, /* next exec enables     */
+                               task           :  1, /* trace fork/exit       */
 
-                               __reserved_1   : 53;
+                               __reserved_1   : 50;
 
        __u32                   wakeup_events;  /* wakeup every n events */
        __u32                   __reserved_2;
@@ -232,6 +253,14 @@ struct perf_counter_mmap_page {
        __u32   lock;                   /* seqlock for synchronization */
        __u32   index;                  /* hardware counter identifier */
        __s64   offset;                 /* add to hardware counter value */
+       __u64   time_enabled;           /* time counter active */
+       __u64   time_running;           /* time counter on cpu */
+
+               /*
+                * Hole for extension of the self monitor capabilities
+                */
+
+       __u64   __reserved[123];        /* align to 1k */
 
        /*
         * Control data for the mmap() data buffer.
@@ -253,7 +282,6 @@ struct perf_counter_mmap_page {
 #define PERF_EVENT_MISC_KERNEL                 (1 << 0)
 #define PERF_EVENT_MISC_USER                   (2 << 0)
 #define PERF_EVENT_MISC_HYPERVISOR             (3 << 0)
-#define PERF_EVENT_MISC_OVERFLOW               (1 << 2)
 
 struct perf_event_header {
        __u32   type;
@@ -301,18 +329,18 @@ enum perf_event_type {
        /*
         * struct {
         *      struct perf_event_header        header;
-        *      u64                             time;
-        *      u64                             id;
-        *      u64                             sample_period;
+        *      u32                             pid, ppid;
+        *      u32                             tid, ptid;
         * };
         */
-       PERF_EVENT_PERIOD               = 4,
+       PERF_EVENT_EXIT                 = 4,
 
        /*
         * struct {
         *      struct perf_event_header        header;
         *      u64                             time;
         *      u64                             id;
+        *      u64                             stream_id;
         * };
         */
        PERF_EVENT_THROTTLE             = 5,
@@ -322,14 +350,22 @@ enum perf_event_type {
         * struct {
         *      struct perf_event_header        header;
         *      u32                             pid, ppid;
+        *      u32                             tid, ptid;
         * };
         */
        PERF_EVENT_FORK                 = 7,
 
        /*
-        * When header.misc & PERF_EVENT_MISC_OVERFLOW the event_type field
-        * will be PERF_SAMPLE_*
+        * struct {
+        *      struct perf_event_header        header;
+        *      u32                             pid, tid;
         *
+        *      struct read_format              values;
+        * };
+        */
+       PERF_EVENT_READ                 = 8,
+
+       /*
         * struct {
         *      struct perf_event_header        header;
         *
@@ -337,16 +373,34 @@ enum perf_event_type {
         *      { u32                   pid, tid; } && PERF_SAMPLE_TID
         *      { u64                   time;     } && PERF_SAMPLE_TIME
         *      { u64                   addr;     } && PERF_SAMPLE_ADDR
-        *      { u64                   config;   } && PERF_SAMPLE_CONFIG
+        *      { u64                   id;       } && PERF_SAMPLE_ID
+        *      { u64                   stream_id;} && PERF_SAMPLE_STREAM_ID
         *      { u32                   cpu, res; } && PERF_SAMPLE_CPU
+        *      { u64                   period;   } && PERF_SAMPLE_PERIOD
         *
-        *      { u64                   nr;
-        *        { u64 id, val; }      cnt[nr];  } && PERF_SAMPLE_GROUP
+        *      { struct read_format    values;   } && PERF_SAMPLE_READ
         *
         *      { u64                   nr,
         *        u64                   ips[nr];  } && PERF_SAMPLE_CALLCHAIN
+        *
+        *      #
+        *      # The RAW record below is opaque data wrt the ABI
+        *      #
+        *      # That is, the ABI doesn't make any promises wrt to
+        *      # the stability of its content, it may vary depending
+        *      # on event, hardware, kernel version and phase of
+        *      # the moon.
+        *      #
+        *      # In other words, PERF_SAMPLE_RAW contents are not an ABI.
+        *      #
+        *
+        *      { u32                   size;
+        *        char                  data[size];}&& PERF_SAMPLE_RAW
         * };
         */
+       PERF_EVENT_SAMPLE               = 9,
+
+       PERF_EVENT_MAX,                 /* non-ABI */
 };
 
 enum perf_callchain_context {
@@ -387,6 +441,11 @@ struct perf_callchain_entry {
        __u64                           ip[PERF_MAX_STACK_DEPTH];
 };
 
+struct perf_raw_record {
+       u32                             size;
+       void                            *data;
+};
+
 struct task_struct;
 
 /**
@@ -582,6 +641,7 @@ struct perf_counter_context {
        int                             nr_counters;
        int                             nr_active;
        int                             is_active;
+       int                             nr_stat;
        atomic_t                        refcount;
        struct task_struct              *task;
 
@@ -654,10 +714,13 @@ struct perf_sample_data {
        struct pt_regs                  *regs;
        u64                             addr;
        u64                             period;
+       struct perf_raw_record          *raw;
 };
 
 extern int perf_counter_overflow(struct perf_counter *counter, int nmi,
                                 struct perf_sample_data *data);
+extern void perf_counter_output(struct perf_counter *counter, int nmi,
+                               struct perf_sample_data *data);
 
 /*
  * Return 1 for a software counter, 0 for a hardware counter
@@ -669,7 +732,16 @@ static inline int is_software_counter(struct perf_counter *counter)
                (counter->attr.type != PERF_TYPE_HW_CACHE);
 }
 
-extern void perf_swcounter_event(u32, u64, int, struct pt_regs *, u64);
+extern atomic_t perf_swcounter_enabled[PERF_COUNT_SW_MAX];
+
+extern void __perf_swcounter_event(u32, u64, int, struct pt_regs *, u64);
+
+static inline void
+perf_swcounter_event(u32 event, u64 nr, int nmi, struct pt_regs *regs, u64 addr)
+{
+       if (atomic_read(&perf_swcounter_enabled[event]))
+               __perf_swcounter_event(event, nr, nmi, regs, addr);
+}
 
 extern void __perf_counter_mmap(struct vm_area_struct *vma);
 
index a84e9ff9b27e9d59cfd1f2d0e8b3403e21b07ca0..126120819a0dba4aeb931094094c27d3d80f9aa0 100644 (file)
@@ -40,7 +40,10 @@ enum {
  * Security-relevant compatibility flags that must be
  * cleared upon setuid or setgid exec:
  */
-#define PER_CLEAR_ON_SETID (READ_IMPLIES_EXEC|ADDR_NO_RANDOMIZE)
+#define PER_CLEAR_ON_SETID (READ_IMPLIES_EXEC  | \
+                           ADDR_NO_RANDOMIZE  | \
+                           ADDR_COMPAT_LAYOUT | \
+                           MMAP_PAGE_ZERO)
 
 /*
  * Personality types.
index cfe5c7214ec61f10e3ff5b011ec4ab2e677426e4..0194ab06177b4015203c4e92cca80bbe386356ac 100644 (file)
@@ -22,6 +22,8 @@
 #ifndef _PPS_H_
 #define _PPS_H_
 
+#include <linux/types.h>
+
 #define PPS_VERSION            "5.3.6"
 #define PPS_MAX_SOURCES                16              /* should be enough... */
 
index 7bc457593684aaad13a4e27b0759066832f130f0..26361c4c037a15f24feb2952070de8d1a9b2eab5 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef _LINUX_QUOTAOPS_
 #define _LINUX_QUOTAOPS_
 
-#include <linux/smp_lock.h>
 #include <linux/fs.h>
 
 static inline struct quota_info *sb_dqopt(struct super_block *sb)
index e73e2429a1b1cab128e1561865b3f12ca822a8e8..278777fa8a3a98fcad50cf0c17e8457e48328679 100644 (file)
@@ -99,7 +99,6 @@ enum rfkill_user_states {
 #undef RFKILL_STATE_UNBLOCKED
 #undef RFKILL_STATE_HARD_BLOCKED
 
-#include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
@@ -225,7 +224,7 @@ void rfkill_destroy(struct rfkill *rfkill);
  * should be blocked) so that drivers need not keep track of the soft
  * block state -- which they might not be able to.
  */
-bool __must_check rfkill_set_hw_state(struct rfkill *rfkill, bool blocked);
+bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked);
 
 /**
  * rfkill_set_sw_state - Set the internal rfkill software block state
index e5996984ddd0f9d8b242f9b7219e6f9006c35548..9aaf5bfdad1afcb5e85b39482ea0458a0ea6b83c 100644 (file)
@@ -242,6 +242,8 @@ size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
  */
 
 #define SG_MITER_ATOMIC                (1 << 0)         /* use kmap_atomic */
+#define SG_MITER_TO_SG         (1 << 1)        /* flush back to phys on unmap */
+#define SG_MITER_FROM_SG       (1 << 2)        /* nop */
 
 struct sg_mapping_iter {
        /* the following three fields can be accessed directly */
index 4d075426988428820aae1f451015744bc2e50440..0f1ea4a6695763debe7a6e87bf586c36efcc0c76 100644 (file)
@@ -209,7 +209,7 @@ extern unsigned long long time_sync_thresh;
                        ((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0)
 #define task_contributes_to_load(task) \
                                ((task->state & TASK_UNINTERRUPTIBLE) != 0 && \
-                                (task->flags & PF_FROZEN) == 0)
+                                (task->flags & PF_FREEZING) == 0)
 
 #define __set_task_state(tsk, state_value)             \
        do { (tsk)->state = (state_value); } while (0)
@@ -349,8 +349,20 @@ extern int mutex_spin_on_owner(struct mutex *lock, struct thread_info *owner);
 struct nsproxy;
 struct user_namespace;
 
-/* Maximum number of active map areas.. This is a random (large) number */
-#define DEFAULT_MAX_MAP_COUNT  65536
+/*
+ * Default maximum number of active map areas, this limits the number of vmas
+ * per mm struct. Users can overwrite this number by sysctl but there is a
+ * problem.
+ *
+ * When a program's coredump is generated as ELF format, a section is created
+ * per a vma. In ELF, the number of sections is represented in unsigned short.
+ * This means the number of sections should be smaller than 65535 at coredump.
+ * Because the kernel adds some informative sections to a image of program at
+ * generating coredump, we need some margin. The number of extra sections is
+ * 1-3 now and depends on arch. We use "5" as safe margin, here.
+ */
+#define MAPCOUNT_ELF_CORE_MARGIN       (5)
+#define DEFAULT_MAX_MAP_COUNT  (USHORT_MAX - MAPCOUNT_ELF_CORE_MARGIN)
 
 extern int sysctl_max_map_count;
 
@@ -486,6 +498,15 @@ struct task_cputime {
                .sum_exec_runtime = 0,                          \
        }
 
+/*
+ * Disable preemption until the scheduler is running.
+ * Reset by start_kernel()->sched_init()->init_idle().
+ *
+ * We include PREEMPT_ACTIVE to avoid cond_resched() from working
+ * before the scheduler is active -- see should_resched().
+ */
+#define INIT_PREEMPT_COUNT     (1 + PREEMPT_ACTIVE)
+
 /**
  * struct thread_group_cputimer - thread group interval timer counts
  * @cputime:           thread group interval timers.
@@ -1177,6 +1198,7 @@ struct task_struct {
         * a short time
         */
        unsigned char fpu_counter;
+       s8 oomkilladj; /* OOM kill score adjustment (bit shift). */
 #ifdef CONFIG_BLK_DEV_IO_TRACE
        unsigned int btrace_seq;
 #endif
@@ -1659,6 +1681,7 @@ extern cputime_t task_gtime(struct task_struct *p);
 #define PF_MEMALLOC    0x00000800      /* Allocating memory */
 #define PF_FLUSHER     0x00001000      /* responsible for disk writeback */
 #define PF_USED_MATH   0x00002000      /* if unset the fpu must be initialized before use */
+#define PF_FREEZING    0x00004000      /* freeze in progress. do not account to load */
 #define PF_NOFREEZE    0x00008000      /* this thread should not be frozen */
 #define PF_FROZEN      0x00010000      /* frozen for system suspend */
 #define PF_FSTRANS     0x00020000      /* inside a filesystem transaction */
index 5eff459b38338ace06bb7d9e83d10a462b906203..1f16eea2017b1062caf0be4540c4e0cb19a2bb27 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/resource.h>
 #include <linux/sem.h>
 #include <linux/shm.h>
+#include <linux/mm.h> /* PAGE_ALIGN */
 #include <linux/msg.h>
 #include <linux/sched.h>
 #include <linux/key.h>
@@ -66,6 +67,9 @@ extern int cap_inode_setxattr(struct dentry *dentry, const char *name,
 extern int cap_inode_removexattr(struct dentry *dentry, const char *name);
 extern int cap_inode_need_killpriv(struct dentry *dentry);
 extern int cap_inode_killpriv(struct dentry *dentry);
+extern int cap_file_mmap(struct file *file, unsigned long reqprot,
+                        unsigned long prot, unsigned long flags,
+                        unsigned long addr, unsigned long addr_only);
 extern int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags);
 extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
                          unsigned long arg4, unsigned long arg5);
@@ -92,6 +96,7 @@ extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
 
 extern unsigned long mmap_min_addr;
+extern unsigned long dac_mmap_min_addr;
 /*
  * Values used in the task_security_ops calls
  */
@@ -116,6 +121,21 @@ struct request_sock;
 #define LSM_UNSAFE_PTRACE      2
 #define LSM_UNSAFE_PTRACE_CAP  4
 
+/*
+ * If a hint addr is less than mmap_min_addr change hint to be as
+ * low as possible but still greater than mmap_min_addr
+ */
+static inline unsigned long round_hint_to_min(unsigned long hint)
+{
+       hint &= PAGE_MASK;
+       if (((void *)hint != NULL) &&
+           (hint < mmap_min_addr))
+               return PAGE_ALIGN(mmap_min_addr);
+       return hint;
+}
+extern int mmap_min_addr_handler(struct ctl_table *table, int write, struct file *filp,
+                                void __user *buffer, size_t *lenp, loff_t *ppos);
+
 #ifdef CONFIG_SECURITY
 
 struct security_mnt_opts {
@@ -2197,9 +2217,7 @@ static inline int security_file_mmap(struct file *file, unsigned long reqprot,
                                     unsigned long addr,
                                     unsigned long addr_only)
 {
-       if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO))
-               return -EACCES;
-       return 0;
+       return cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
 }
 
 static inline int security_file_mprotect(struct vm_area_struct *vma,
index b47b3f039d147ee63cd4dbb1f99201c1e1814bb7..f2c69a2cca172aff841e6ce97656d5fa9cb412a9 100644 (file)
@@ -1342,12 +1342,12 @@ static inline int skb_network_offset(const struct sk_buff *skb)
  * shifting the start of the packet by 2 bytes. Drivers should do this
  * with:
  *
- * skb_reserve(NET_IP_ALIGN);
+ * skb_reserve(skb, NET_IP_ALIGN);
  *
  * The downside to this alignment of the IP header is that the DMA is now
  * unaligned. On some architectures the cost of an unaligned DMA is high
  * and this cost outweighs the gains made by aligning the IP header.
- * 
+ *
  * Since this trade off varies between architectures, we allow NET_IP_ALIGN
  * to be overridden.
  */
index 4dcbc2c71491ec9dc736b83c1eeedb03f4650a95..c1c862b1d01a2b41cccce3f462262ad4564ab782 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/workqueue.h>
 #include <linux/kobject.h>
 #include <linux/kmemtrace.h>
+#include <linux/kmemleak.h>
 
 enum stat_item {
        ALLOC_FASTPATH,         /* Allocation from cpu slab */
@@ -233,6 +234,7 @@ static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
        unsigned int order = get_order(size);
        void *ret = (void *) __get_free_pages(flags | __GFP_COMP, order);
 
+       kmemleak_alloc(ret, size, 1, flags);
        trace_kmalloc(_THIS_IP_, ret, size, PAGE_SIZE << order, flags);
 
        return ret;
index 9c4cd27f4685250c274c375951ec695615dbe8ea..c47c4b4da97e5a606ab2823d3126a32f42e446f0 100644 (file)
@@ -80,6 +80,8 @@ struct spi_device {
 #define        SPI_LSB_FIRST   0x08                    /* per-word bits-on-wire */
 #define        SPI_3WIRE       0x10                    /* SI/SO signals shared */
 #define        SPI_LOOP        0x20                    /* loopback mode */
+#define        SPI_NO_CS       0x40                    /* 1 dev/bus, no chipselect */
+#define        SPI_READY       0x80                    /* slave pulls low to pause */
        u8                      bits_per_word;
        int                     irq;
        void                    *controller_state;
@@ -248,6 +250,10 @@ struct spi_master {
        /* spi_device.mode flags understood by this controller driver */
        u16                     mode_bits;
 
+       /* other constraints relevant to this driver */
+       u16                     flags;
+#define SPI_MASTER_HALF_DUPLEX BIT(0)          /* can't do full duplex */
+
        /* Setup mode and clock, etc (spi driver may call many times).
         *
         * IMPORTANT:  this may be called when transfers to another
index 95251ccd5a07072ac3421f6566e4a89658e1f578..bf0570a84f7a4aeb83e76d8e842b9f17b89c1143 100644 (file)
@@ -40,6 +40,8 @@
 #define SPI_LSB_FIRST          0x08
 #define SPI_3WIRE              0x10
 #define SPI_LOOP               0x20
+#define SPI_NO_CS              0x40
+#define SPI_READY              0x80
 
 /*---------------------------------------------------------------------------*/
 
index 252b245cfcf4cb098658da65f60f02436b12902f..4be57ab03478c837bf470e7f9d9a04fccf5fad27 100644 (file)
@@ -132,6 +132,11 @@ do {                                                               \
 #endif /*__raw_spin_is_contended*/
 #endif
 
+/* The lock does not imply full memory barrier. */
+#ifndef ARCH_HAS_SMP_MB_AFTER_LOCK
+static inline void smp_mb__after_lock(void) { smp_mb(); }
+#endif
+
 /**
  * spin_unlock_wait - wait until the spinlock gets unlocked
  * @lock: the spinlock in question.
index d8910b68e1bdd981cabe3ac8c34150ae85fa0627..b99c625fddfe764754b5005d44ea79933b74fc09 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/uio.h>
 #include <asm/byteorder.h>
 #include <linux/scatterlist.h>
-#include <linux/smp_lock.h>
 
 /*
  * Buffer adjustment
index fa4242cdade86f9b956c949b5253e965e7aa74c9..80de7003d8c2340f7a71d98614eaa3ba2baa7c18 100644 (file)
@@ -321,6 +321,8 @@ asmlinkage long sys_rt_sigtimedwait(const sigset_t __user *uthese,
                                siginfo_t __user *uinfo,
                                const struct timespec __user *uts,
                                size_t sigsetsize);
+asmlinkage long sys_rt_tgsigqueueinfo(pid_t tgid, pid_t  pid, int sig,
+               siginfo_t __user *uinfo);
 asmlinkage long sys_kill(int pid, int sig);
 asmlinkage long sys_tgkill(int tgid, int pid, int sig);
 asmlinkage long sys_tkill(int pid, int sig);
index 98a1d8cfb73d1902d7f55466bc9aa034e8436b2b..99adcdc0d3ca9062173f976cb27cd7f8bf8a0a91 100644 (file)
@@ -14,6 +14,8 @@
 #ifndef _LINUX_SYSRQ_H
 #define _LINUX_SYSRQ_H
 
+#include <linux/errno.h>
+
 struct pt_regs;
 struct tty_struct;
 
index ccf882eed8f8d5c35852ec65151c5b4112e8b564..be62ec2ebea54fc0c9bd97f3b630882385fa2943 100644 (file)
@@ -190,6 +190,8 @@ extern unsigned long get_next_timer_interrupt(unsigned long now);
  */
 #ifdef CONFIG_TIMER_STATS
 
+extern int timer_stats_active;
+
 #define TIMER_STATS_FLAG_DEFERRABLE    0x1
 
 extern void init_timer_stats(void);
@@ -203,6 +205,8 @@ extern void __timer_stats_timer_set_start_info(struct timer_list *timer,
 
 static inline void timer_stats_timer_set_start_info(struct timer_list *timer)
 {
+       if (likely(!timer_stats_active))
+               return;
        __timer_stats_timer_set_start_info(timer, __builtin_return_address(0));
 }
 
index 1488d8c81aac6587c9edc8002f39f89d104391cf..0d3974f59c53e2dcfec0f7d1ae8f36dfc5ea210a 100644 (file)
@@ -23,7 +23,7 @@
  */
 #define NR_UNIX98_PTY_DEFAULT  4096      /* Default maximum for Unix98 ptys */
 #define NR_UNIX98_PTY_MAX      (1 << MINORBITS) /* Absolute limit */
-#define NR_LDISCS              19
+#define NR_LDISCS              20
 
 /* line disciplines */
 #define N_TTY          0
@@ -47,6 +47,8 @@
 #define N_SLCAN                17      /* Serial / USB serial CAN Adaptors */
 #define N_PPS          18      /* Pulse per Second */
 
+#define N_V253         19      /* Codec control over voice modem */
+
 /*
  * This character is the same as _POSIX_VDISABLE: it cannot be used as
  * a c_cc[] character, but indicates that a particular special character
@@ -394,6 +396,7 @@ extern void __do_SAK(struct tty_struct *tty);
 extern void disassociate_ctty(int priv);
 extern void no_tty(void);
 extern void tty_flip_buffer_push(struct tty_struct *tty);
+extern void tty_flush_to_ldisc(struct tty_struct *tty);
 extern void tty_buffer_free_all(struct tty_struct *tty);
 extern void tty_buffer_flush(struct tty_struct *tty);
 extern void tty_buffer_init(struct tty_struct *tty);
index 40f38d896777400f1bcbb56c36063eed22db45fe..0c4ee9b88f8551d51c308840a7f3c7ba7fb83d13 100644 (file)
@@ -144,7 +144,7 @@ struct tty_ldisc_ops {
 
 struct tty_ldisc {
        struct tty_ldisc_ops *ops;
-       int refcount;
+       atomic_t users;
 };
 
 #define TTY_LDISC_MAGIC        0x5403
index ed889f4168f301a877c4e7384e207cb6fae2bb4d..ae779bb8cc0f7fb3d710be1916f1006e43f95c60 100644 (file)
 
 #define UCB_ADC_DATA           0x68
 #define UCB_ADC_DAT_VALID      (1 << 15)
+
+#define UCB_FCSR               0x6c
+#define UCB_FCSR_AVE           (1 << 12)
+
 #define UCB_ADC_DAT_MASK       0x3ff
 
 #define UCB_ID                 0x7e
index b7fe13883bdb1ba2682b503cff268c7e3618df9b..98c114323a8be51299300bf440ec6ff167ac2fdb 100644 (file)
@@ -19,15 +19,6 @@ struct iovec
        __kernel_size_t iov_len; /* Must be size_t (1003.1g) */
 };
 
-#ifdef __KERNEL__
-
-struct kvec {
-       void *iov_base; /* and that should *never* hold a userland pointer */
-       size_t iov_len;
-};
-
-#endif
-
 /*
  *     UIO_MAXIOV shall be at least 16 1003.1g (5.4.1.1)
  */
@@ -35,6 +26,13 @@ struct kvec {
 #define UIO_FASTIOV    8
 #define UIO_MAXIOV     1024
 
+#ifdef __KERNEL__
+
+struct kvec {
+       void *iov_base; /* and that should *never* hold a userland pointer */
+       size_t iov_len;
+};
+
 /*
  * Total number of bytes covered by an iovec.
  *
@@ -53,5 +51,6 @@ static inline size_t iov_length(const struct iovec *iov, unsigned long nr_segs)
 }
 
 unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to);
+#endif
 
 #endif
index 84929e9140341583cbc8fd7050c4e5e5a12b8d29..b1e3c2fbfe1170fdd8fc4cdb023d628b1a0b4a43 100644 (file)
@@ -888,8 +888,6 @@ struct usb_driver {
  * struct usb_device_driver - identifies USB device driver to usbcore
  * @name: The driver name should be unique among USB drivers,
  *     and should normally be the same as the module name.
- * @nodename: Callback to provide a naming hint for a possible
- *     device node to create.
  * @probe: Called to see if the driver is willing to manage a particular
  *     device.  If it is, probe returns zero and uses dev_set_drvdata()
  *     to associate driver-specific data with the device.  If unwilling
@@ -924,6 +922,8 @@ extern struct bus_type usb_bus_type;
 /**
  * struct usb_class_driver - identifies a USB driver that wants to use the USB major number
  * @name: the usb class device name for this driver.  Will show up in sysfs.
+ * @nodename: Callback to provide a naming hint for a possible
+ *     device node to create.
  * @fops: pointer to the struct file_operations of this driver.
  * @minor_base: the start of the minor range for this driver.
  *
@@ -1046,6 +1046,8 @@ typedef void (*usb_complete_t)(struct urb *);
  *     the device driver is saying that it provided this DMA address,
  *     which the host controller driver should use in preference to the
  *     transfer_buffer.
+ * @sg: scatter gather buffer list
+ * @num_sgs: number of entries in the sg list
  * @transfer_buffer_length: How big is transfer_buffer.  The transfer may
  *     be broken up into chunks according to the current maximum packet
  *     size for the endpoint, which is a function of the configuration
diff --git a/include/linux/usb/langwell_otg.h b/include/linux/usb/langwell_otg.h
deleted file mode 100644 (file)
index e115ae6..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Intel Langwell USB OTG transceiver driver
- * Copyright (C) 2008, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef __LANGWELL_OTG_H__
-#define __LANGWELL_OTG_H__
-
-/* notify transceiver driver about OTG events */
-extern void langwell_update_transceiver(void);
-/* HCD register bus driver */
-extern int langwell_register_host(struct pci_driver *host_driver);
-/* HCD unregister bus driver */
-extern void langwell_unregister_host(struct pci_driver *host_driver);
-/* DCD register bus driver */
-extern int langwell_register_peripheral(struct pci_driver *client_driver);
-/* DCD unregister bus driver */
-extern void langwell_unregister_peripheral(struct pci_driver *client_driver);
-/* No silent failure, output warning message */
-extern void langwell_otg_nsf_msg(unsigned long message);
-
-#define CI_USBCMD              0x30
-#      define USBCMD_RST               BIT(1)
-#      define USBCMD_RS                BIT(0)
-#define CI_USBSTS              0x34
-#      define USBSTS_SLI               BIT(8)
-#      define USBSTS_URI               BIT(6)
-#      define USBSTS_PCI               BIT(2)
-#define CI_PORTSC1             0x74
-#      define PORTSC_PP                BIT(12)
-#      define PORTSC_LS                (BIT(11) | BIT(10))
-#      define PORTSC_SUSP              BIT(7)
-#      define PORTSC_CCS               BIT(0)
-#define CI_HOSTPC1             0xb4
-#      define HOSTPC1_PHCD             BIT(22)
-#define CI_OTGSC               0xf4
-#      define OTGSC_DPIE               BIT(30)
-#      define OTGSC_1MSE               BIT(29)
-#      define OTGSC_BSEIE              BIT(28)
-#      define OTGSC_BSVIE              BIT(27)
-#      define OTGSC_ASVIE              BIT(26)
-#      define OTGSC_AVVIE              BIT(25)
-#      define OTGSC_IDIE               BIT(24)
-#      define OTGSC_DPIS               BIT(22)
-#      define OTGSC_1MSS               BIT(21)
-#      define OTGSC_BSEIS              BIT(20)
-#      define OTGSC_BSVIS              BIT(19)
-#      define OTGSC_ASVIS              BIT(18)
-#      define OTGSC_AVVIS              BIT(17)
-#      define OTGSC_IDIS               BIT(16)
-#      define OTGSC_DPS                BIT(14)
-#      define OTGSC_1MST               BIT(13)
-#      define OTGSC_BSE                BIT(12)
-#      define OTGSC_BSV                BIT(11)
-#      define OTGSC_ASV                BIT(10)
-#      define OTGSC_AVV                BIT(9)
-#      define OTGSC_ID                 BIT(8)
-#      define OTGSC_HABA               BIT(7)
-#      define OTGSC_HADP               BIT(6)
-#      define OTGSC_IDPU               BIT(5)
-#      define OTGSC_DP                 BIT(4)
-#      define OTGSC_OT                 BIT(3)
-#      define OTGSC_HAAR               BIT(2)
-#      define OTGSC_VC                 BIT(1)
-#      define OTGSC_VD                 BIT(0)
-#      define OTGSC_INTEN_MASK         (0x7f << 24)
-#      define OTGSC_INTSTS_MASK        (0x7f << 16)
-#define CI_USBMODE             0xf8
-#      define USBMODE_CM               (BIT(1) | BIT(0))
-#      define USBMODE_IDLE             0
-#      define USBMODE_DEVICE           0x2
-#      define USBMODE_HOST             0x3
-
-#define INTR_DUMMY_MASK (USBSTS_SLI | USBSTS_URI | USBSTS_PCI)
-
-struct otg_hsm {
-       /* Input */
-       int a_bus_resume;
-       int a_bus_suspend;
-       int a_conn;
-       int a_sess_vld;
-       int a_srp_det;
-       int a_vbus_vld;
-       int b_bus_resume;
-       int b_bus_suspend;
-       int b_conn;
-       int b_se0_srp;
-       int b_sess_end;
-       int b_sess_vld;
-       int id;
-
-       /* Internal variables */
-       int a_set_b_hnp_en;
-       int b_srp_done;
-       int b_hnp_enable;
-
-       /* Timeout indicator for timers */
-       int a_wait_vrise_tmout;
-       int a_wait_bcon_tmout;
-       int a_aidl_bdis_tmout;
-       int b_ase0_brst_tmout;
-       int b_bus_suspend_tmout;
-       int b_srp_res_tmout;
-
-       /* Informative variables */
-       int a_bus_drop;
-       int a_bus_req;
-       int a_clr_err;
-       int a_suspend_req;
-       int b_bus_req;
-
-       /* Output */
-       int drv_vbus;
-       int loc_conn;
-       int loc_sof;
-
-       /* Others */
-       int b_bus_suspend_vld;
-};
-
-#define TA_WAIT_VRISE  100
-#define TA_WAIT_BCON   30000
-#define TA_AIDL_BDIS   15000
-#define TB_ASE0_BRST   5000
-#define TB_SE0_SRP     2
-#define TB_SRP_RES     100
-#define TB_BUS_SUSPEND 500
-
-struct langwell_otg_timer {
-       unsigned long expires;  /* Number of count increase to timeout */
-       unsigned long count;    /* Tick counter */
-       void (*function)(unsigned long);        /* Timeout function */
-       unsigned long data;     /* Data passed to function */
-       struct list_head list;
-};
-
-struct langwell_otg {
-       struct otg_transceiver  otg;
-       struct otg_hsm          hsm;
-       void __iomem            *regs;
-       unsigned                region;
-       struct pci_driver       *host_ops;
-       struct pci_driver       *client_ops;
-       struct pci_dev          *pdev;
-       struct work_struct      work;
-       struct workqueue_struct *qwork;
-       spinlock_t              lock;
-       spinlock_t              wq_lock;
-};
-
-static inline struct langwell_otg *otg_to_langwell(struct otg_transceiver *otg)
-{
-       return container_of(otg, struct langwell_otg, otg);
-}
-
-#ifdef DEBUG
-#define otg_dbg(fmt, args...) \
-       printk(KERN_DEBUG fmt , ## args)
-#else
-#define otg_dbg(fmt, args...) \
-       do { } while (0)
-#endif /* DEBUG */
-#endif /* __LANGWELL_OTG_H__ */
index 44801d26a37a7888d7ebd88dbb5cf0e4a1836de0..0ec50ba62139e5bde97db61a10b8585c2882c916 100644 (file)
@@ -317,7 +317,8 @@ extern int usb_serial_generic_register(int debug);
 extern void usb_serial_generic_deregister(void);
 extern void usb_serial_generic_resubmit_read_urb(struct usb_serial_port *port,
                                                 gfp_t mem_flags);
-extern int usb_serial_handle_sysrq_char(struct usb_serial_port *port,
+extern int usb_serial_handle_sysrq_char(struct tty_struct *tty,
+                                       struct usb_serial_port *port,
                                        unsigned int ch);
 extern int usb_serial_handle_break(struct usb_serial_port *port);
 
index 5d44059f6d63feb02dbc8f2defc3d6ffb1d9cfba..310e18a880fff5da371f000225a871008afbb84e 100644 (file)
@@ -42,7 +42,6 @@ struct usbnet {
 
        /* protocol/interface state */
        struct net_device       *net;
-       struct net_device_stats stats;
        int                     msg_enable;
        unsigned long           data [5];
        u32                     xid;
index 8a025d510904609ec4b1b244f10a0d8cd7bdff8b..74f16876f38d643eb6b9df7c548b1b90131c6794 100644 (file)
@@ -318,6 +318,8 @@ struct v4l2_pix_format {
 /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
 #define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B', 'A', '8', '1') /*  8  BGBG.. GRGR.. */
 #define V4L2_PIX_FMT_SGBRG8  v4l2_fourcc('G', 'B', 'R', 'G') /*  8  GBGB.. RGRG.. */
+#define V4L2_PIX_FMT_SGRBG8  v4l2_fourcc('G', 'R', 'B', 'G') /*  8  GRGR.. BGBG.. */
+
 /*
  * 10bit raw bayer, expanded to 16 bits
  * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb...
@@ -336,6 +338,7 @@ struct v4l2_pix_format {
 /*  Vendor-specific formats   */
 #define V4L2_PIX_FMT_WNVA     v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */
 #define V4L2_PIX_FMT_SN9C10X  v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */
+#define V4L2_PIX_FMT_SN9C20X_I420 v4l2_fourcc('S', '9', '2', '0') /* SN9C20x YUV 4:2:0 */
 #define V4L2_PIX_FMT_PWC1     v4l2_fourcc('P', 'W', 'C', '1') /* pwc older webcam */
 #define V4L2_PIX_FMT_PWC2     v4l2_fourcc('P', 'W', 'C', '2') /* pwc newer webcam */
 #define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E', '6', '2', '5') /* ET61X251 compression */
index be7d255fc7cfbfc644fc5381fac0aaf9ee3e59e3..8dab9f2b8832db74569f668a70edfd853274414c 100644 (file)
@@ -20,8 +20,7 @@
 
 #define VIRTIO_BLK_ID_BYTES    (sizeof(__u16[256]))    /* IDENTIFY DATA */
 
-struct virtio_blk_config
-{
+struct virtio_blk_config {
        /* The capacity (in 512-byte sectors). */
        __u64 capacity;
        /* The maximum segment size (if VIRTIO_BLK_F_SIZE_MAX) */
@@ -50,8 +49,7 @@ struct virtio_blk_config
 #define VIRTIO_BLK_T_BARRIER   0x80000000
 
 /* This is the first element of the read scatter-gather list. */
-struct virtio_blk_outhdr
-{
+struct virtio_blk_outhdr {
        /* VIRTIO_BLK_T* */
        __u32 type;
        /* io priority. */
index 99f514575f6afa1fe0e6ceeb4c50c7fb4e6520a5..e547e3c8ee9a55412e52dabaa9ddc67a423b01ab 100644 (file)
@@ -79,8 +79,7 @@
  *     the dev->feature bits if it wants.
  */
 typedef void vq_callback_t(struct virtqueue *);
-struct virtio_config_ops
-{
+struct virtio_config_ops {
        void (*get)(struct virtio_device *vdev, unsigned offset,
                    void *buf, unsigned len);
        void (*set)(struct virtio_device *vdev, unsigned offset,
index cec79adbe3ea60934ad69f3ef00484f12b97b065..d8dd539c9f48e602019c0b184087635c042e3b3d 100644 (file)
 #define VIRTIO_NET_F_CTRL_VQ   17      /* Control channel available */
 #define VIRTIO_NET_F_CTRL_RX   18      /* Control channel RX mode support */
 #define VIRTIO_NET_F_CTRL_VLAN 19      /* Control channel VLAN filtering */
+#define VIRTIO_NET_F_CTRL_RX_EXTRA 20  /* Extra RX mode control support */
 
 #define VIRTIO_NET_S_LINK_UP   1       /* Link is up */
 
-struct virtio_net_config
-{
+struct virtio_net_config {
        /* The config defining mac address (if VIRTIO_NET_F_MAC) */
        __u8 mac[6];
        /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
@@ -40,8 +40,7 @@ struct virtio_net_config
 
 /* This is the first element of the scatter-gather list.  If you don't
  * specify GSO or CSUM features, you can simply ignore the header. */
-struct virtio_net_hdr
-{
+struct virtio_net_hdr {
 #define VIRTIO_NET_HDR_F_NEEDS_CSUM    1       // Use csum_start, csum_offset
        __u8 flags;
 #define VIRTIO_NET_HDR_GSO_NONE                0       // Not a GSO frame
@@ -81,14 +80,19 @@ typedef __u8 virtio_net_ctrl_ack;
 #define VIRTIO_NET_ERR    1
 
 /*
- * Control the RX mode, ie. promisucous and allmulti.  PROMISC and
- * ALLMULTI commands require an "out" sg entry containing a 1 byte
- * state value, zero = disable, non-zero = enable.  These commands
- * are supported with the VIRTIO_NET_F_CTRL_RX feature.
+ * Control the RX mode, ie. promisucous, allmulti, etc...
+ * All commands require an "out" sg entry containing a 1 byte
+ * state value, zero = disable, non-zero = enable.  Commands
+ * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature.
+ * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA.
  */
 #define VIRTIO_NET_CTRL_RX    0
  #define VIRTIO_NET_CTRL_RX_PROMISC      0
  #define VIRTIO_NET_CTRL_RX_ALLMULTI     1
+ #define VIRTIO_NET_CTRL_RX_ALLUNI       2
+ #define VIRTIO_NET_CTRL_RX_NOMULTI      3
+ #define VIRTIO_NET_CTRL_RX_NOUNI        4
+ #define VIRTIO_NET_CTRL_RX_NOBCAST      5
 
 /*
  * Control the MAC filter table.
index 693e0ec5afa67f9ec2c18d48563cccdba3261409..e4d144b132b5e27d3c4713738acfc63ce6262781 100644 (file)
@@ -30,8 +30,7 @@
 #define VIRTIO_RING_F_INDIRECT_DESC    28
 
 /* Virtio ring descriptors: 16 bytes.  These can chain together via "next". */
-struct vring_desc
-{
+struct vring_desc {
        /* Address (guest-physical). */
        __u64 addr;
        /* Length. */
@@ -42,24 +41,21 @@ struct vring_desc
        __u16 next;
 };
 
-struct vring_avail
-{
+struct vring_avail {
        __u16 flags;
        __u16 idx;
        __u16 ring[];
 };
 
 /* u32 is used here for ids for padding reasons. */
-struct vring_used_elem
-{
+struct vring_used_elem {
        /* Index of start of used descriptor chain. */
        __u32 id;
        /* Total length of the descriptor chain which was used (written to) */
        __u32 len;
 };
 
-struct vring_used
-{
+struct vring_used {
        __u16 flags;
        __u16 idx;
        struct vring_used_elem ring[];
index 6788e1a4d4ca63e8cfc3b288f87d456334064c29..cf3c2f5dba51834215b137e5385b2654f220fc42 100644 (file)
@@ -77,7 +77,14 @@ struct task_struct;
 #define __WAIT_BIT_KEY_INITIALIZER(word, bit)                          \
        { .flags = word, .bit_nr = bit, }
 
-extern void init_waitqueue_head(wait_queue_head_t *q);
+extern void __init_waitqueue_head(wait_queue_head_t *q, struct lock_class_key *);
+
+#define init_waitqueue_head(q)                         \
+       do {                                            \
+               static struct lock_class_key __key;     \
+                                                       \
+               __init_waitqueue_head((q), &__key);     \
+       } while (0)
 
 #ifdef CONFIG_LOCKDEP
 # define __WAIT_QUEUE_HEAD_INIT_ONSTACK(name) \
index 13e1adf55c4c7c0ba30d81bbc54abe6d56b93b5e..6273fa97b527e4d8c415ebbda74c0ac68303532e 100644 (file)
@@ -240,6 +240,21 @@ static inline int cancel_delayed_work(struct delayed_work *work)
        return ret;
 }
 
+/*
+ * Like above, but uses del_timer() instead of del_timer_sync(). This means,
+ * if it returns 0 the timer function may be running and the queueing is in
+ * progress.
+ */
+static inline int __cancel_delayed_work(struct delayed_work *work)
+{
+       int ret;
+
+       ret = del_timer(&work->timer);
+       if (ret)
+               work_clear_pending(&work->work);
+       return ret;
+}
+
 extern int cancel_delayed_work_sync(struct delayed_work *work);
 
 /* Obsolete. use cancel_delayed_work_sync() */
index 4d7e2272c42f0c37e0aabb5dbc912c6c24361a34..94e908c0d7a0e4ff2e51428b85136ef38a5c51b7 100644 (file)
@@ -60,6 +60,10 @@ enum {
        V4L2_IDENT_OV7670 = 250,
        V4L2_IDENT_OV7720 = 251,
        V4L2_IDENT_OV7725 = 252,
+       V4L2_IDENT_OV7660 = 253,
+       V4L2_IDENT_OV9650 = 254,
+       V4L2_IDENT_OV9655 = 255,
+       V4L2_IDENT_SOI968 = 256,
 
        /* module saa7146: reserved range 300-309 */
        V4L2_IDENT_SAA7146 = 300,
@@ -155,9 +159,15 @@ enum {
        /* module cafe_ccic, just ident 8801 */
        V4L2_IDENT_CAFE = 8801,
 
+       /* module mt9v011, just ident 8243 */
+       V4L2_IDENT_MT9V011 = 8243,
+
        /* module tw9910: just ident 9910 */
        V4L2_IDENT_TW9910 = 9910,
 
+       /* module sn9c20x: just ident 10000 */
+       V4L2_IDENT_SN9C20X = 10000,
+
        /* module msp3400: reserved range 34000-34999 and 44000-44999 */
        V4L2_IDENT_MSPX4XX  = 34000, /* generic MSPX4XX identifier, only
                                        use internally (tveeprom.c). */
@@ -234,6 +244,11 @@ enum {
        V4L2_IDENT_MT9V022IX7ATC        = 45010, /* No way to detect "normal" I77ATx */
        V4L2_IDENT_MT9V022IX7ATM        = 45015, /* and "lead free" IA7ATx chips */
        V4L2_IDENT_MT9T031              = 45020,
+       V4L2_IDENT_MT9V111              = 45031,
+       V4L2_IDENT_MT9V112              = 45032,
+
+       /* HV7131R CMOS sensor: just ident 46000 */
+       V4L2_IDENT_HV7131R              = 46000,
 
        /* module cs53132a: just ident 53132 */
        V4L2_IDENT_CS53l32A = 53132,
index 565eed8fe496d55c81c3454564eb5605e27afd71..c05fd717c588801a72c4fe7a18a000b4bf46e35c 100644 (file)
@@ -16,7 +16,7 @@ struct tcf_common {
        u32                             tcfc_capab;
        int                             tcfc_action;
        struct tcf_t                    tcfc_tm;
-       struct gnet_stats_basic         tcfc_bstats;
+       struct gnet_stats_basic_packed  tcfc_bstats;
        struct gnet_stats_queue         tcfc_qstats;
        struct gnet_stats_rate_est      tcfc_rate_est;
        spinlock_t                      tcfc_lock;
index 80072611d26a44820304593292398f0e3d67d7eb..c274993234e32dc8c6ea88b7d61e0f332227e6cb 100644 (file)
@@ -355,7 +355,17 @@ struct rfcomm_dev_list_req {
 };
 
 int  rfcomm_dev_ioctl(struct sock *sk, unsigned int cmd, void __user *arg);
+
+#ifdef CONFIG_BT_RFCOMM_TTY
 int  rfcomm_init_ttys(void);
 void rfcomm_cleanup_ttys(void);
-
+#else
+static inline int rfcomm_init_ttys(void)
+{
+       return 0;
+}
+static inline void rfcomm_cleanup_ttys(void)
+{
+}
+#endif
 #endif /* __RFCOMM_H */
index 1a21895b732bbd5821b419a0a6e239dbd5c3b904..d1892d66701abf2d085ab9f2bfa7ba364e657de0 100644 (file)
@@ -979,6 +979,10 @@ struct cfg80211_ops {
  *     channels at a later time. This can be used for devices which do not
  *     have calibration information gauranteed for frequencies or settings
  *     outside of its regulatory domain.
+ * @disable_beacon_hints: enable this if your driver needs to ensure that
+ *     passive scan flags and beaconing flags may not be lifted by cfg80211
+ *     due to regulatory beacon hints. For more information on beacon
+ *     hints read the documenation for regulatory_hint_found_beacon()
  * @reg_notifier: the driver's regulatory notification callback
  * @regd: the driver's regulatory domain, if one was requested via
  *     the regulatory_hint() API. This can be used by the driver
@@ -1004,6 +1008,7 @@ struct wiphy {
 
        bool custom_regulatory;
        bool strict_regulatory;
+       bool disable_beacon_hints;
 
        enum cfg80211_signal_type signal_type;
 
index d136b5240ef24a2e41cb6843b27d724295b4b9d3..c1488553e34964b9dbd4a3a66334d4c1f04f16bd 100644 (file)
@@ -28,7 +28,7 @@ extern int gnet_stats_start_copy_compat(struct sk_buff *skb, int type,
                                        spinlock_t *lock, struct gnet_dump *d);
 
 extern int gnet_stats_copy_basic(struct gnet_dump *d,
-                                struct gnet_stats_basic *b);
+                                struct gnet_stats_basic_packed *b);
 extern int gnet_stats_copy_rate_est(struct gnet_dump *d,
                                    struct gnet_stats_rate_est *r);
 extern int gnet_stats_copy_queue(struct gnet_dump *d,
@@ -37,14 +37,14 @@ extern int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len);
 
 extern int gnet_stats_finish_copy(struct gnet_dump *d);
 
-extern int gen_new_estimator(struct gnet_stats_basic *bstats,
+extern int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
                             struct gnet_stats_rate_est *rate_est,
                             spinlock_t *stats_lock, struct nlattr *opt);
-extern void gen_kill_estimator(struct gnet_stats_basic *bstats,
+extern void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
                               struct gnet_stats_rate_est *rate_est);
-extern int gen_replace_estimator(struct gnet_stats_basic *bstats,
+extern int gen_replace_estimator(struct gnet_stats_basic_packed *bstats,
                                 struct gnet_stats_rate_est *rate_est,
                                 spinlock_t *stats_lock, struct nlattr *opt);
-extern bool gen_estimator_active(const struct gnet_stats_basic *bstats,
+extern bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
                                 const struct gnet_stats_rate_est *rate_est);
 #endif
index a632689b61b40f581e4cc1d25fe65ebcac053995..cbdd6284996d3cd29732c0ae406833a678a3fb80 100644 (file)
@@ -258,8 +258,8 @@ static inline bool nf_ct_kill(struct nf_conn *ct)
 /* Update TCP window tracking data when NAT mangles the packet */
 extern void nf_conntrack_tcp_update(const struct sk_buff *skb,
                                    unsigned int dataoff,
-                                   struct nf_conn *ct,
-                                   int dir);
+                                   struct nf_conn *ct, int dir,
+                                   s16 offset);
 
 /* Fake conntrack entry for untracked connections */
 extern struct nf_conn nf_conntrack_untracked;
index 65d594dffbff431e35a0ac7ec29a051bb022c8b6..ddbf37e19616a486b73b15a7e5314c47e1ed80a8 100644 (file)
@@ -8,7 +8,7 @@ struct xt_rateest {
        spinlock_t                      lock;
        struct gnet_estimator           params;
        struct gnet_stats_rate_est      rstats;
-       struct gnet_stats_basic         bstats;
+       struct gnet_stats_basic_packed  bstats;
 };
 
 extern struct xt_rateest *xt_rateest_lookup(const char *name);
index 5054dc5ea2c260439277a6c252f51df68cd72a39..29d126736611c7ad693f9e84439d3bab56f012ad 100644 (file)
@@ -45,6 +45,7 @@ int phonet_address_add(struct net_device *dev, u8 addr);
 int phonet_address_del(struct net_device *dev, u8 addr);
 u8 phonet_address_get(struct net_device *dev, u8 addr);
 int phonet_address_lookup(struct net *net, u8 addr);
+void phonet_address_notify(int event, struct net_device *dev, u8 addr);
 
 #define PN_NO_ADDR     0xff
 
index cbd5364b2c8a94237d4554818a7fcd87783c1a8b..5ba9f02731eb353921854816bd503bb04978c298 100644 (file)
@@ -156,7 +156,7 @@ extern int  sysctl_rose_maximum_vcs;
 extern int  sysctl_rose_window_size;
 extern int  rosecmp(rose_address *, rose_address *);
 extern int  rosecmpm(rose_address *, rose_address *, unsigned short);
-extern const char *rose2asc(const rose_address *);
+extern char *rose2asc(char *buf, const rose_address *);
 extern struct sock *rose_find_socket(unsigned int, struct rose_neigh *);
 extern void rose_kill_by_neigh(struct rose_neigh *);
 extern unsigned int rose_new_lci(struct rose_neigh *);
index 964ffa0d8815139ae22d351590b5673a4dd38850..5482e9582f555ea9bae1d2a8e5f42bd571f97819 100644 (file)
@@ -72,7 +72,7 @@ struct Qdisc
         */
        unsigned long           state;
        struct sk_buff_head     q;
-       struct gnet_stats_basic bstats;
+       struct gnet_stats_basic_packed bstats;
        struct gnet_stats_queue qstats;
 };
 
index 352f06bbd7a9b14b0257b8014d4ecf3027aad44e..950409dcec3d5763bf4822c4fb8599e20808c728 100644 (file)
@@ -54,6 +54,7 @@
 
 #include <linux/filter.h>
 #include <linux/rculist_nulls.h>
+#include <linux/poll.h>
 
 #include <asm/atomic.h>
 #include <net/dst.h>
@@ -103,15 +104,15 @@ struct net;
 
 /**
  *     struct sock_common - minimal network layer representation of sockets
+ *     @skc_node: main hash linkage for various protocol lookup tables
+ *     @skc_nulls_node: main hash linkage for UDP/UDP-Lite protocol
+ *     @skc_refcnt: reference count
+ *     @skc_hash: hash value used with various protocol lookup tables
  *     @skc_family: network address family
  *     @skc_state: Connection state
  *     @skc_reuse: %SO_REUSEADDR setting
  *     @skc_bound_dev_if: bound device index if != 0
- *     @skc_node: main hash linkage for various protocol lookup tables
- *     @skc_nulls_node: main hash linkage for UDP/UDP-Lite protocol
  *     @skc_bind_node: bind hash linkage for various protocol lookup tables
- *     @skc_refcnt: reference count
- *     @skc_hash: hash value used with various protocol lookup tables
  *     @skc_prot: protocol handlers inside a network family
  *     @skc_net: reference to the network namespace of this socket
  *
@@ -119,17 +120,21 @@ struct net;
  *     for struct sock and struct inet_timewait_sock.
  */
 struct sock_common {
-       unsigned short          skc_family;
-       volatile unsigned char  skc_state;
-       unsigned char           skc_reuse;
-       int                     skc_bound_dev_if;
+       /*
+        * first fields are not copied in sock_copy()
+        */
        union {
                struct hlist_node       skc_node;
                struct hlist_nulls_node skc_nulls_node;
        };
-       struct hlist_node       skc_bind_node;
        atomic_t                skc_refcnt;
+
        unsigned int            skc_hash;
+       unsigned short          skc_family;
+       volatile unsigned char  skc_state;
+       unsigned char           skc_reuse;
+       int                     skc_bound_dev_if;
+       struct hlist_node       skc_bind_node;
        struct proto            *skc_prot;
 #ifdef CONFIG_NET_NS
        struct net              *skc_net;
@@ -207,15 +212,17 @@ struct sock {
         * don't add nothing before this first member (__sk_common) --acme
         */
        struct sock_common      __sk_common;
+#define sk_node                        __sk_common.skc_node
+#define sk_nulls_node          __sk_common.skc_nulls_node
+#define sk_refcnt              __sk_common.skc_refcnt
+
+#define sk_copy_start          __sk_common.skc_hash
+#define sk_hash                        __sk_common.skc_hash
 #define sk_family              __sk_common.skc_family
 #define sk_state               __sk_common.skc_state
 #define sk_reuse               __sk_common.skc_reuse
 #define sk_bound_dev_if                __sk_common.skc_bound_dev_if
-#define sk_node                        __sk_common.skc_node
-#define sk_nulls_node          __sk_common.skc_nulls_node
 #define sk_bind_node           __sk_common.skc_bind_node
-#define sk_refcnt              __sk_common.skc_refcnt
-#define sk_hash                        __sk_common.skc_hash
 #define sk_prot                        __sk_common.skc_prot
 #define sk_net                 __sk_common.skc_net
        kmemcheck_bitfield_begin(flags);
@@ -1241,6 +1248,74 @@ static inline int sk_has_allocations(const struct sock *sk)
        return sk_wmem_alloc_get(sk) || sk_rmem_alloc_get(sk);
 }
 
+/**
+ * sk_has_sleeper - check if there are any waiting processes
+ * @sk: socket
+ *
+ * Returns true if socket has waiting processes
+ *
+ * The purpose of the sk_has_sleeper and sock_poll_wait is to wrap the memory
+ * barrier call. They were added due to the race found within the tcp code.
+ *
+ * Consider following tcp code paths:
+ *
+ * CPU1                  CPU2
+ *
+ * sys_select            receive packet
+ *   ...                 ...
+ *   __add_wait_queue    update tp->rcv_nxt
+ *   ...                 ...
+ *   tp->rcv_nxt check   sock_def_readable
+ *   ...                 {
+ *   schedule               ...
+ *                          if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+ *                              wake_up_interruptible(sk->sk_sleep)
+ *                          ...
+ *                       }
+ *
+ * The race for tcp fires when the __add_wait_queue changes done by CPU1 stay
+ * in its cache, and so does the tp->rcv_nxt update on CPU2 side.  The CPU1
+ * could then endup calling schedule and sleep forever if there are no more
+ * data on the socket.
+ *
+ * The sk_has_sleeper is always called right after a call to read_lock, so we
+ * can use smp_mb__after_lock barrier.
+ */
+static inline int sk_has_sleeper(struct sock *sk)
+{
+       /*
+        * We need to be sure we are in sync with the
+        * add_wait_queue modifications to the wait queue.
+        *
+        * This memory barrier is paired in the sock_poll_wait.
+        */
+       smp_mb__after_lock();
+       return sk->sk_sleep && waitqueue_active(sk->sk_sleep);
+}
+
+/**
+ * sock_poll_wait - place memory barrier behind the poll_wait call.
+ * @filp:           file
+ * @wait_address:   socket wait queue
+ * @p:              poll_table
+ *
+ * See the comments in the sk_has_sleeper function.
+ */
+static inline void sock_poll_wait(struct file *filp,
+               wait_queue_head_t *wait_address, poll_table *p)
+{
+       if (p && wait_address) {
+               poll_wait(filp, wait_address, p);
+               /*
+                * We need to be sure we are in sync with the
+                * socket flags modification.
+                *
+                * This memory barrier is paired in the sk_has_sleeper.
+               */
+               smp_mb();
+       }
+}
+
 /*
  *     Queue a received datagram if it will fit. Stream and sequenced
  *     protocols can't normally use this as they need to fit buffers in
index 19f4150f4d4d166380f95079c1877af28e6d62a5..88af843064710bf43e25cb6932aa40479c19e07e 100644 (file)
@@ -1425,6 +1425,11 @@ struct tcp_request_sock_ops {
 #ifdef CONFIG_TCP_MD5SIG
        struct tcp_md5sig_key   *(*md5_lookup) (struct sock *sk,
                                                struct request_sock *req);
+       int                     (*calc_md5_hash) (char *location,
+                                                 struct tcp_md5sig_key *md5,
+                                                 struct sock *sk,
+                                                 struct request_sock *req,
+                                                 struct sk_buff *skb);
 #endif
 };
 
index 251fc1cd5002db04a7c0d5bddbdb3891542a6665..3dae3f799b9bb91e3abd12e2577401fe976da938 100644 (file)
@@ -32,6 +32,9 @@
 #include "control.h"
 #include "info.h"
 
+/* maximum number of devices on the AC97 bus */
+#define        AC97_BUS_MAX_DEVICES    4
+
 /*
  *  AC'97 codec registers
  */
@@ -642,4 +645,10 @@ int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime);
 /* ad hoc AC97 device driver access */
 extern struct bus_type ac97_bus_type;
 
+/* AC97 platform_data adding function */
+static inline void snd_ac97_dev_add_pdata(struct snd_ac97 *ac97, void *data)
+{
+       ac97->dev.platform_data = data;
+}
+
 #endif /* __SOUND_AC97_CODEC_H */
index 82aed3f47534f3d47d53930e4869c9285de5652d..1f57bb92eb5a60fe985970b5bdb9712b24e98905 100644 (file)
@@ -138,7 +138,7 @@ struct snd_hwdep_dsp_image {
  *                                                                           *
  *****************************************************************************/
 
-#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 9)
+#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 10)
 
 typedef unsigned long snd_pcm_uframes_t;
 typedef signed long snd_pcm_sframes_t;
index 309cb9659a05907576fb933b822b100afd3e56bb..a61499c22b0b96044314048791b3152e5249d98e 100644 (file)
@@ -93,15 +93,6 @@ struct snd_device {
 
 #define snd_device(n) list_entry(n, struct snd_device, list)
 
-/* monitor files for graceful shutdown (hotplug) */
-
-struct snd_monitor_file {
-       struct file *file;
-       const struct file_operations *disconnected_f_op;
-       struct list_head shutdown_list; /* still need to shutdown */
-       struct list_head list;  /* link of monitor files */
-};
-
 /* main structure for soundcard */
 
 struct snd_card {
@@ -311,9 +302,7 @@ int snd_component_add(struct snd_card *card, const char *component);
 int snd_card_file_add(struct snd_card *card, struct file *file);
 int snd_card_file_remove(struct snd_card *card, struct file *file);
 
-#ifndef snd_card_set_dev
 #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr))
-#endif
 
 /* device.c */
 
@@ -340,18 +329,17 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size);
 struct resource;
 void release_and_free_resource(struct resource *res);
 
-#ifdef CONFIG_SND_VERBOSE_PRINTK
-void snd_verbose_printk(const char *file, int line, const char *format, ...)
-     __attribute__ ((format (printf, 3, 4)));
-#endif
-#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK)
-void snd_verbose_printd(const char *file, int line, const char *format, ...)
-     __attribute__ ((format (printf, 3, 4)));
-#endif
-
 /* --- */
 
-#ifdef CONFIG_SND_VERBOSE_PRINTK
+#if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK)
+void __snd_printk(unsigned int level, const char *file, int line,
+                 const char *format, ...)
+     __attribute__ ((format (printf, 4, 5)));
+#else
+#define __snd_printk(level, file, line, format, args...) \
+       printk(format, ##args)
+#endif
+
 /**
  * snd_printk - printk wrapper
  * @fmt: format string
@@ -360,15 +348,9 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
  * when configured with CONFIG_SND_VERBOSE_PRINTK.
  */
 #define snd_printk(fmt, args...) \
-       snd_verbose_printk(__FILE__, __LINE__, fmt ,##args)
-#else
-#define snd_printk(fmt, args...) \
-       printk(fmt ,##args)
-#endif
+       __snd_printk(0, __FILE__, __LINE__, fmt, ##args)
 
 #ifdef CONFIG_SND_DEBUG
-
-#ifdef CONFIG_SND_VERBOSE_PRINTK
 /**
  * snd_printd - debug printk
  * @fmt: format string
@@ -377,11 +359,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
  * Ignored when CONFIG_SND_DEBUG is not set.
  */
 #define snd_printd(fmt, args...) \
-       snd_verbose_printd(__FILE__, __LINE__, fmt ,##args)
-#else
-#define snd_printd(fmt, args...) \
-       printk(fmt ,##args)
-#endif
+       __snd_printk(1, __FILE__, __LINE__, fmt, ##args)
 
 /**
  * snd_BUG - give a BUG warning message and stack trace
@@ -428,9 +406,10 @@ static inline int __snd_bug_on(int cond)
  * Works like snd_printk() for debugging purposes.
  * Ignored when CONFIG_SND_DEBUG_VERBOSE is not set.
  */
-#define snd_printdd(format, args...) snd_printk(format, ##args)
+#define snd_printdd(format, args...) \
+       __snd_printk(2, __FILE__, __LINE__, format, ##args)
 #else
-#define snd_printdd(format, args...) /* nothing */
+#define snd_printdd(format, args...)   do { } while (0)
 #endif
 
 
@@ -438,12 +417,10 @@ static inline int __snd_bug_on(int cond)
 
 /* for easier backward-porting */
 #if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
-#ifndef gameport_set_dev_parent
 #define gameport_set_dev_parent(gp,xdev) ((gp)->dev.parent = (xdev))
 #define gameport_set_port_data(gp,r) ((gp)->port_data = (r))
 #define gameport_get_port_data(gp) (gp)->port_data
 #endif
-#endif
 
 /* PCI quirk list helper */
 struct snd_pci_quirk {
index 7c2ee1a21b00b05a8476c168d737a009ba1fce57..112e8949e1a7d020af20607acc9609d14a066fb3 100644 (file)
@@ -110,13 +110,13 @@ void snd_card_info_read_oss(struct snd_info_buffer *buffer);
 static inline void snd_card_info_read_oss(struct snd_info_buffer *buffer) {}
 #endif
 
-int snd_iprintf(struct snd_info_buffer *buffer, char *fmt, ...) \
+int snd_iprintf(struct snd_info_buffer *buffer, const char *fmt, ...) \
                                __attribute__ ((format (printf, 2, 3)));
 int snd_info_init(void);
 int snd_info_done(void);
 
 int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len);
-char *snd_info_get_str(char *dest, char *src, int len);
+const char *snd_info_get_str(char *dest, const char *src, int len);
 struct snd_info_entry *snd_info_create_module_entry(struct module *module,
                                               const char *name,
                                               struct snd_info_entry *parent);
index 7ccce94a5255edc09b28413ede92178c10230055..c42506212649938d73c3cf611e3325ed95af7e4e 100644 (file)
@@ -47,7 +47,11 @@ struct snd_dma_device {
 #define SNDRV_DMA_TYPE_UNKNOWN         0       /* not defined */
 #define SNDRV_DMA_TYPE_CONTINUOUS      1       /* continuous no-DMA memory */
 #define SNDRV_DMA_TYPE_DEV             2       /* generic device continuous */
+#ifdef CONFIG_SND_DMA_SGBUF
 #define SNDRV_DMA_TYPE_DEV_SG          3       /* generic device SG-buffer */
+#else
+#define SNDRV_DMA_TYPE_DEV_SG  SNDRV_DMA_TYPE_DEV /* no SG-buf support */
+#endif
 
 /*
  * info for buffer allocation
@@ -60,6 +64,7 @@ struct snd_dma_buffer {
        void *private_data;     /* private for allocator; don't touch */
 };
 
+#ifdef CONFIG_SND_DMA_SGBUF
 /*
  * Scatter-Gather generic device pages
  */
@@ -107,6 +112,7 @@ static inline void *snd_sgbuf_get_ptr(struct snd_sg_buf *sgbuf, size_t offset)
 {
        return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE;
 }
+#endif /* CONFIG_SND_DMA_SGBUF */
 
 /* allocate/release a buffer */
 int snd_dma_alloc_pages(int type, struct device *dev, size_t size,
index 23893523dc8ce16023cc347dcd3672f3c6be4033..de6d981de5d60170e522815482be939343c05f33 100644 (file)
@@ -902,6 +902,7 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
 int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size);
 int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream);
 
+#ifdef CONFIG_SND_DMA_SGBUF
 /*
  * SG-buffer handling
  */
@@ -927,6 +928,28 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream,
 unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream,
                                          unsigned int ofs, unsigned int size);
 
+#else /* !SND_DMA_SGBUF */
+/*
+ * fake using a continuous buffer
+ */
+static inline dma_addr_t
+snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs)
+{
+       return substream->runtime->dma_addr + ofs;
+}
+
+static inline void *
+snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs)
+{
+       return substream->runtime->dma_area + ofs;
+}
+
+#define snd_pcm_sgbuf_ops_page NULL
+
+#define snd_pcm_sgbuf_get_chunk_size(subs, ofs, size)  (size)
+
+#endif /* SND_DMA_SGBUF */
+
 /* handle mmap counter - PCM mmap callback should handle this counter properly */
 static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area)
 {
@@ -965,4 +988,6 @@ static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
 
 #define PCM_RUNTIME_CHECK(sub) snd_BUG_ON(!(sub) || !(sub)->runtime)
 
+const char *snd_pcm_format_name(snd_pcm_format_t format);
+
 #endif /* __SOUND_PCM_H */
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
new file mode 100644 (file)
index 0000000..c022736
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __SOUND_FSI_H
+#define __SOUND_FSI_H
+
+/*
+ * Fifo-attached Serial Interface (FSI) support for SH7724
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.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.
+ */
+
+/* flags format
+
+ * 0xABCDEEFF
+ *
+ * A:  channel size for TDM (input)
+ * B:  channel size for TDM (ooutput)
+ * C:  inversion
+ * D:  mode
+ * E:  input format
+ * F:  output format
+ */
+
+#include <linux/clk.h>
+#include <sound/soc.h>
+
+/* TDM channel */
+#define SH_FSI_SET_CH_I(x)     ((x & 0xF) << 28)
+#define SH_FSI_SET_CH_O(x)     ((x & 0xF) << 24)
+
+#define SH_FSI_CH_IMASK                0xF0000000
+#define SH_FSI_CH_OMASK                0x0F000000
+#define SH_FSI_GET_CH_I(x)     ((x & SH_FSI_CH_IMASK) >> 28)
+#define SH_FSI_GET_CH_O(x)     ((x & SH_FSI_CH_OMASK) >> 24)
+
+/* clock inversion */
+#define SH_FSI_INVERSION_MASK  0x00F00000
+#define SH_FSI_LRM_INV         (1 << 20)
+#define SH_FSI_BRM_INV         (1 << 21)
+#define SH_FSI_LRS_INV         (1 << 22)
+#define SH_FSI_BRS_INV         (1 << 23)
+
+/* mode */
+#define SH_FSI_MODE_MASK       0x000F0000
+#define SH_FSI_IN_SLAVE_MODE   (1 << 16)  /* default master mode */
+#define SH_FSI_OUT_SLAVE_MODE  (1 << 17)  /* default master mode */
+
+/* DI format */
+#define SH_FSI_FMT_MASK                0x000000FF
+#define SH_FSI_IFMT(x)         (((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 8)
+#define SH_FSI_OFMT(x)         (((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 0)
+#define SH_FSI_GET_IFMT(x)     ((x >> 8) & SH_FSI_FMT_MASK)
+#define SH_FSI_GET_OFMT(x)     ((x >> 0) & SH_FSI_FMT_MASK)
+
+#define SH_FSI_FMT_MONO                (1 << 0)
+#define SH_FSI_FMT_MONO_DELAY  (1 << 1)
+#define SH_FSI_FMT_PCM         (1 << 2)
+#define SH_FSI_FMT_I2S         (1 << 3)
+#define SH_FSI_FMT_TDM         (1 << 4)
+#define SH_FSI_FMT_TDM_DELAY   (1 << 5)
+
+#define SH_FSI_IFMT_TDM_CH(x) \
+       (SH_FSI_IFMT(TDM)       | SH_FSI_SET_CH_I(x))
+#define SH_FSI_IFMT_TDM_DELAY_CH(x) \
+       (SH_FSI_IFMT(TDM_DELAY) | SH_FSI_SET_CH_I(x))
+
+#define SH_FSI_OFMT_TDM_CH(x) \
+       (SH_FSI_OFMT(TDM)       | SH_FSI_SET_CH_O(x))
+#define SH_FSI_OFMT_TDM_DELAY_CH(x) \
+       (SH_FSI_OFMT(TDM_DELAY) | SH_FSI_SET_CH_O(x))
+
+struct sh_fsi_platform_info {
+       unsigned long porta_flags;
+       unsigned long portb_flags;
+};
+
+extern struct snd_soc_dai fsi_soc_dai[2];
+extern struct snd_soc_platform fsi_soc_platform;
+
+#endif /* __SOUND_FSI_H */
index 352d7eee9b6d912739fecbf48ec20aef0485a0d0..97ca9af414dc095b5786f785b5c46475c810f7a8 100644 (file)
@@ -27,8 +27,8 @@ struct snd_pcm_substream;
 #define SND_SOC_DAIFMT_I2S             0 /* I2S mode */
 #define SND_SOC_DAIFMT_RIGHT_J         1 /* Right Justified mode */
 #define SND_SOC_DAIFMT_LEFT_J          2 /* Left Justified mode */
-#define SND_SOC_DAIFMT_DSP_A           3 /* L data msb after FRM LRC */
-#define SND_SOC_DAIFMT_DSP_B           4 /* L data msb during FRM LRC */
+#define SND_SOC_DAIFMT_DSP_A           3 /* L data MSB after FRM LRC */
+#define SND_SOC_DAIFMT_DSP_B           4 /* L data MSB during FRM LRC */
 #define SND_SOC_DAIFMT_AC97            5 /* AC97 */
 
 /* left and right justified also known as MSB and LSB respectively */
@@ -38,7 +38,7 @@ struct snd_pcm_substream;
 /*
  * DAI Clock gating.
  *
- * DAI bit clocks can be be gated (disabled) when not the DAI is not
+ * DAI bit clocks can be be gated (disabled) when the DAI is not
  * sending or receiving PCM data in a frame. This can be used to save power.
  */
 #define SND_SOC_DAIFMT_CONT            (0 << 4) /* continuous clock */
@@ -51,21 +51,21 @@ struct snd_pcm_substream;
  * format.
  */
 #define SND_SOC_DAIFMT_NB_NF           (0 << 8) /* normal bit clock + frame */
-#define SND_SOC_DAIFMT_NB_IF           (1 << 8) /* normal bclk + inv frm */
-#define SND_SOC_DAIFMT_IB_NF           (2 << 8) /* invert bclk + nor frm */
-#define SND_SOC_DAIFMT_IB_IF           (3 << 8) /* invert bclk + frm */
+#define SND_SOC_DAIFMT_NB_IF           (1 << 8) /* normal BCLK + inv FRM */
+#define SND_SOC_DAIFMT_IB_NF           (2 << 8) /* invert BCLK + nor FRM */
+#define SND_SOC_DAIFMT_IB_IF           (3 << 8) /* invert BCLK + FRM */
 
 /*
  * DAI hardware clock masters.
  *
  * This is wrt the codec, the inverse is true for the interface
- * i.e. if the codec is clk and frm master then the interface is
+ * i.e. if the codec is clk and FRM master then the interface is
  * clk and frame slave.
  */
-#define SND_SOC_DAIFMT_CBM_CFM         (0 << 12) /* codec clk & frm master */
-#define SND_SOC_DAIFMT_CBS_CFM         (1 << 12) /* codec clk slave & frm master */
+#define SND_SOC_DAIFMT_CBM_CFM         (0 << 12) /* codec clk & FRM master */
+#define SND_SOC_DAIFMT_CBS_CFM         (1 << 12) /* codec clk slave & FRM master */
 #define SND_SOC_DAIFMT_CBM_CFS         (2 << 12) /* codec clk master & frame slave */
-#define SND_SOC_DAIFMT_CBS_CFS         (3 << 12) /* codec clk & frm slave */
+#define SND_SOC_DAIFMT_CBS_CFS         (3 << 12) /* codec clk & FRM slave */
 
 #define SND_SOC_DAIFMT_FORMAT_MASK     0x000f
 #define SND_SOC_DAIFMT_CLOCK_MASK      0x00f0
@@ -78,7 +78,13 @@ struct snd_pcm_substream;
 #define SND_SOC_CLOCK_IN               0
 #define SND_SOC_CLOCK_OUT              1
 
-#define SND_SOC_STD_AC97_FMTS (SNDRV_PCM_FMTBIT_S16_LE |\
+#define SND_SOC_STD_AC97_FMTS (SNDRV_PCM_FMTBIT_S8 |\
+                              SNDRV_PCM_FMTBIT_S16_LE |\
+                              SNDRV_PCM_FMTBIT_S16_BE |\
+                              SNDRV_PCM_FMTBIT_S20_3LE |\
+                              SNDRV_PCM_FMTBIT_S20_3BE |\
+                              SNDRV_PCM_FMTBIT_S24_3LE |\
+                              SNDRV_PCM_FMTBIT_S24_3BE |\
                                SNDRV_PCM_FMTBIT_S32_LE |\
                                SNDRV_PCM_FMTBIT_S32_BE)
 
@@ -106,7 +112,7 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
 int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
 
 int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
-       unsigned int mask, int slots);
+       unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width);
 
 int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
 
@@ -116,12 +122,12 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute);
 /*
  * Digital Audio Interface.
  *
- * Describes the Digital Audio Interface in terms of it's ALSA, DAI and AC97
- * operations an capabilities. Codec and platfom drivers will register a this
+ * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97
+ * operations and capabilities. Codec and platform drivers will register this
  * structure for every DAI they have.
  *
  * This structure covers the clocking, formating and ALSA operations for each
- * interface a
+ * interface.
  */
 struct snd_soc_dai_ops {
        /*
@@ -140,7 +146,8 @@ struct snd_soc_dai_ops {
         */
        int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
        int (*set_tdm_slot)(struct snd_soc_dai *dai,
-               unsigned int mask, int slots);
+               unsigned int tx_mask, unsigned int rx_mask,
+               int slots, int slot_width);
        int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
 
        /*
@@ -179,6 +186,7 @@ struct snd_soc_dai {
        int ac97_control;
 
        struct device *dev;
+       void *ac97_pdata;       /* platform_data for the ac97 codec */
 
        /* DAI callbacks */
        int (*probe)(struct platform_device *pdev,
index ec8a45f9a06950f6bf1cfa0ea0d46ed3ca5200f0..c1410e3191e3f6a43987efe818537a096401470e 100644 (file)
        .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD}
 
 /* stream domain */
+#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \
+{      .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
+       .reg = wreg, .shift = wshift, .invert = winvert }
+#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \
+{      .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
+       .reg = wreg, .shift = wshift, .invert = winvert }
 #define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
 {      .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \
        .shift = wshift, .invert = winvert}
@@ -279,9 +285,11 @@ int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
 /* dapm events */
 int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream,
        int event);
+void snd_soc_dapm_shutdown(struct snd_soc_device *socdev);
 
 /* dapm sys fs - used by the core */
 int snd_soc_dapm_sys_add(struct device *dev);
+void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec);
 
 /* dapm audio pin control and status */
 int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin);
@@ -311,6 +319,8 @@ enum snd_soc_dapm_type {
        snd_soc_dapm_pre,                       /* machine specific pre widget - exec first */
        snd_soc_dapm_post,                      /* machine specific post widget - exec last */
        snd_soc_dapm_supply,            /* power/clock supply */
+       snd_soc_dapm_aif_in,            /* audio interface input */
+       snd_soc_dapm_aif_out,           /* audio interface output */
 };
 
 /*
index cf6111d72b17015572a131a26c4c7913378adcd0..475cb7ed6beccb8cadc8fd952aaf48516e766929 100644 (file)
        .info = snd_soc_info_volsw, \
        .get = xhandler_get, .put = xhandler_put, \
        .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
+#define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\
+        xhandler_get, xhandler_put, tlv_array) \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+                SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+       .tlv.p = (tlv_array), \
+       .info = snd_soc_info_volsw, \
+       .get = xhandler_get, .put = xhandler_put, \
+       .private_value = (unsigned long)&(struct soc_mixer_control) \
+               {.reg = xreg, .shift = shift_left, .rshift = shift_right, \
+               .max = xmax, .invert = xinvert} }
+#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
+        xhandler_get, xhandler_put, tlv_array) \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+                SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+       .tlv.p = (tlv_array), \
+       .info = snd_soc_info_volsw_2r, \
+       .get = xhandler_get, .put = xhandler_put, \
+       .private_value = (unsigned long)&(struct soc_mixer_control) \
+               {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
+               .max = xmax, .invert = xinvert} }
 #define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
 {      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
        .info = snd_soc_info_bool_ext, \
@@ -183,14 +205,28 @@ struct snd_soc_jack_gpio;
 #endif
 
 typedef int (*hw_write_t)(void *,const char* ,int);
-typedef int (*hw_read_t)(void *,char* ,int);
 
 extern struct snd_ac97_bus_ops soc_ac97_ops;
 
+enum snd_soc_control_type {
+       SND_SOC_CUSTOM,
+       SND_SOC_I2C,
+       SND_SOC_SPI,
+};
+
 int snd_soc_register_platform(struct snd_soc_platform *platform);
 void snd_soc_unregister_platform(struct snd_soc_platform *platform);
 int snd_soc_register_codec(struct snd_soc_codec *codec);
 void snd_soc_unregister_codec(struct snd_soc_codec *codec);
+int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg);
+int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
+                              int addr_bits, int data_bits,
+                              enum snd_soc_control_type control);
+
+#ifdef CONFIG_PM
+int snd_soc_suspend_device(struct device *dev);
+int snd_soc_resume_device(struct device *dev);
+#endif
 
 /* pcm <-> DAI connect */
 void snd_soc_free_pcms(struct snd_soc_device *socdev);
@@ -216,9 +252,9 @@ void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
 
 /* codec register bit access */
 int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
-                               unsigned short mask, unsigned short value);
+                               unsigned int mask, unsigned int value);
 int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
-                               unsigned short mask, unsigned short value);
+                               unsigned int mask, unsigned int value);
 
 int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
        struct snd_ac97_bus_ops *ops, int num);
@@ -356,8 +392,10 @@ struct snd_soc_codec {
        int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
        int (*display_register)(struct snd_soc_codec *, char *,
                                size_t, unsigned int);
+       int (*volatile_register)(unsigned int);
+       int (*readable_register)(unsigned int);
        hw_write_t hw_write;
-       hw_read_t hw_read;
+       unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int);
        void *reg_cache;
        short reg_cache_size;
        short reg_cache_step;
@@ -369,8 +407,6 @@ struct snd_soc_codec {
        enum snd_soc_bias_level bias_level;
        enum snd_soc_bias_level suspend_bias_level;
        struct delayed_work delayed_work;
-       struct list_head up_list;
-       struct list_head down_list;
 
        /* codec DAI's */
        struct snd_soc_dai *dai;
@@ -379,6 +415,7 @@ struct snd_soc_codec {
 #ifdef CONFIG_DEBUG_FS
        struct dentry *debugfs_reg;
        struct dentry *debugfs_pop_time;
+       struct dentry *debugfs_dapm;
 #endif
 };
 
index d136ea2181ed4f2fc0b92dd25b7cd0ac8e6c2860..9fd5b19ccf5c05a7002440588041e49b3e9a8e18 100644 (file)
@@ -35,6 +35,8 @@
 #define SNDRV_CTL_TLVT_DB_SCALE        1       /* dB scale */
 #define SNDRV_CTL_TLVT_DB_LINEAR 2     /* linear volume */
 #define SNDRV_CTL_TLVT_DB_RANGE 3      /* dB range container */
+#define SNDRV_CTL_TLVT_DB_MINMAX 4     /* dB scale with min/max */
+#define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5        /* dB scale with min/max with mute */
 
 #define TLV_DB_SCALE_ITEM(min, step, mute)                     \
        SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int),      \
 #define DECLARE_TLV_DB_SCALE(name, min, step, mute) \
        unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) }
 
+/* dB scale specified with min/max values instead of step */
+#define TLV_DB_MINMAX_ITEM(min_dB, max_dB)                     \
+       SNDRV_CTL_TLVT_DB_MINMAX, 2 * sizeof(unsigned int),     \
+       (min_dB), (max_dB)
+#define TLV_DB_MINMAX_MUTE_ITEM(min_dB, max_dB)                        \
+       SNDRV_CTL_TLVT_DB_MINMAX_MUTE, 2 * sizeof(unsigned int),        \
+       (min_dB), (max_dB)
+#define DECLARE_TLV_DB_MINMAX(name, min_dB, max_dB) \
+       unsigned int name[] = { TLV_DB_MINMAX_ITEM(min_dB, max_dB) }
+#define DECLARE_TLV_DB_MINMAX_MUTE(name, min_dB, max_dB) \
+       unsigned int name[] = { TLV_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) }
+
 /* linear volume between min_dB and max_dB (.01dB unit) */
 #define TLV_DB_LINEAR_ITEM(min_dB, max_dB)                 \
        SNDRV_CTL_TLVT_DB_LINEAR, 2 * sizeof(unsigned int), \
diff --git a/include/sound/uda1380.h b/include/sound/uda1380.h
new file mode 100644 (file)
index 0000000..381319c
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * UDA1380 ALSA SoC Codec driver
+ *
+ * Copyright 2009 Philipp Zabel
+ *
+ * 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 __UDA1380_H
+#define __UDA1380_H
+
+struct uda1380_platform_data {
+       int gpio_power;
+       int gpio_reset;
+       int dac_clk;
+#define UDA1380_DAC_CLK_SYSCLK 0
+#define UDA1380_DAC_CLK_WSPLL  1
+};
+
+#endif /* __UDA1380_H */
index 456f1359e1c0f03a2a4c368f82286046e3e04bf2..22939142dd236627796a248425702ffa6f413758 100644 (file)
@@ -1,3 +1,3 @@
 /* include/version.h */
-#define CONFIG_SND_VERSION "1.0.20"
+#define CONFIG_SND_VERSION "1.0.21"
 #define CONFIG_SND_DATE ""
diff --git a/include/sound/wm8993.h b/include/sound/wm8993.h
new file mode 100644 (file)
index 0000000..9c661f2
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * linux/sound/wm8993.h -- Platform data for WM8993
+ *
+ * Copyright 2009 Wolfson Microelectronics. PLC.
+ *
+ * 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 __LINUX_SND_WM8993_H
+#define __LINUX_SND_WM8993_H
+
+/* Note that EQ1 only contains the enable/disable bit so will be
+   ignored but is included for simplicity.
+ */
+struct wm8993_retune_mobile_setting {
+       const char *name;
+       unsigned int rate;
+       u16 config[24];
+};
+
+struct wm8993_platform_data {
+       struct wm8993_retune_mobile_setting *retune_configs;
+       int num_retune_configs;
+
+       /* LINEOUT can be differential or single ended */
+       unsigned int lineout1_diff:1;
+       unsigned int lineout2_diff:1;
+
+       /* Common mode feedback */
+       unsigned int lineout1fb:1;
+       unsigned int lineout2fb:1;
+
+       /* Microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */
+       unsigned int micbias1_lvl:1;
+       unsigned int micbias2_lvl:1;
+
+       /* Jack detect threashold levels, see datasheet for values */
+       unsigned int jd_scthr:2;
+       unsigned int jd_thr:2;
+};
+
+#endif
index 05ead66984347be76872c0bf0e5da507cc53b760..444cd6ba0ba70645c8652089d39250e58d30f8cf 100644 (file)
@@ -331,6 +331,7 @@ struct snd_ymfpci {
        struct snd_ac97 *ac97;
        struct snd_rawmidi *rawmidi;
        struct snd_timer *timer;
+       unsigned int timer_ticks;
 
        struct pci_dev *pci;
        struct snd_card *card;
index d6b05f42dd44d85e488eaa65c67a105e1e7ad36c..9a74b468a2291dd19e0ee3b8ad364943b3a8b4bb 100644 (file)
@@ -1,3 +1,6 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM block
+
 #if !defined(_TRACE_BLOCK_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_BLOCK_H
 
@@ -5,9 +8,6 @@
 #include <linux/blkdev.h>
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM block
-
 TRACE_EVENT(block_rq_abort,
 
        TP_PROTO(struct request_queue *q, struct request *rq),
index acf4cc9cd36d015e877887e13b79802eb9e8590d..7d8b5bc741857401acf0ee81f8eaa9b98b52c1cd 100644 (file)
@@ -1,9 +1,9 @@
-#if !defined(_TRACE_EXT4_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_EXT4_H
-
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM ext4
 
+#if !defined(_TRACE_EXT4_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_EXT4_H
+
 #include <linux/writeback.h>
 #include "../../../fs/ext4/ext4.h"
 #include "../../../fs/ext4/mballoc.h"
@@ -34,7 +34,8 @@ TRACE_EVENT(ext4_free_inode,
 
        TP_printk("dev %s ino %lu mode %d uid %u gid %u blocks %llu",
                  jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->mode,
-                 __entry->uid, __entry->gid, __entry->blocks)
+                 __entry->uid, __entry->gid,
+                 (unsigned long long) __entry->blocks)
 );
 
 TRACE_EVENT(ext4_request_inode,
@@ -189,7 +190,7 @@ TRACE_EVENT(ext4_journalled_write_end,
                  __entry->copied)
 );
 
-TRACE_EVENT(ext4_da_writepage,
+TRACE_EVENT(ext4_writepage,
        TP_PROTO(struct inode *inode, struct page *page),
 
        TP_ARGS(inode, page),
@@ -341,49 +342,6 @@ TRACE_EVENT(ext4_da_write_end,
                  __entry->copied)
 );
 
-TRACE_EVENT(ext4_normal_writepage,
-       TP_PROTO(struct inode *inode, struct page *page),
-
-       TP_ARGS(inode, page),
-
-       TP_STRUCT__entry(
-               __field(        dev_t,  dev                     )
-               __field(        ino_t,  ino                     )
-               __field(        pgoff_t, index                  )
-       ),
-
-       TP_fast_assign(
-               __entry->dev    = inode->i_sb->s_dev;
-               __entry->ino    = inode->i_ino;
-               __entry->index  = page->index;
-       ),
-
-       TP_printk("dev %s ino %lu page_index %lu",
-                 jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->index)
-);
-
-TRACE_EVENT(ext4_journalled_writepage,
-       TP_PROTO(struct inode *inode, struct page *page),
-
-       TP_ARGS(inode, page),
-
-       TP_STRUCT__entry(
-               __field(        dev_t,  dev                     )
-               __field(        ino_t,  ino                     )
-               __field(        pgoff_t, index                  )
-
-       ),
-
-       TP_fast_assign(
-               __entry->dev    = inode->i_sb->s_dev;
-               __entry->ino    = inode->i_ino;
-               __entry->index  = page->index;
-       ),
-
-       TP_printk("dev %s ino %lu page_index %lu",
-                 jbd2_dev_to_name(__entry->dev), __entry->ino, __entry->index)
-);
-
 TRACE_EVENT(ext4_discard_blocks,
        TP_PROTO(struct super_block *sb, unsigned long long blk,
                        unsigned long long count),
index b0c7ede55eb156c0d4880dee2555dc4b35577887..1cb0c3aa11e613659a0a87cc9c72ea4d14f69a3f 100644 (file)
@@ -1,12 +1,12 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM irq
+
 #if !defined(_TRACE_IRQ_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_IRQ_H
 
 #include <linux/tracepoint.h>
 #include <linux/interrupt.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM irq
-
 #define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq }
 #define show_softirq_name(val)                 \
        __print_symbolic(val,                   \
index 845b0b4b48fda1077b851f44a99042d79f2e7591..10813fa0c8d07b68035b3bdc287fe0e0304a7788 100644 (file)
@@ -1,12 +1,12 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM jbd2
+
 #if !defined(_TRACE_JBD2_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_JBD2_H
 
 #include <linux/jbd2.h>
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM jbd2
-
 TRACE_EVENT(jbd2_checkpoint,
 
        TP_PROTO(journal_t *journal, int result),
index 9baba50d6512e594658485779244bbdde751916b..1493c541f9c44566a21553c5947aa1fa93fc702e 100644 (file)
@@ -1,12 +1,12 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM kmem
+
 #if !defined(_TRACE_KMEM_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_KMEM_H
 
 #include <linux/types.h>
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM kmem
-
 /*
  * The order of these masks is important. Matching masks will be seen
  * first and the left over flags will end up showing by themselves.
index 0e956c9dfd7eed1676d049ab2f1c6375983ba556..bcf1d209a00dabf7838aae49c2e5edcc5fc6dde8 100644 (file)
@@ -1,12 +1,12 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM lockdep
+
 #if !defined(_TRACE_LOCKDEP_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_LOCKDEP_H
 
 #include <linux/lockdep.h>
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM lockdep
-
 #ifdef CONFIG_LOCKDEP
 
 TRACE_EVENT(lock_acquire,
index 24ab5bcff7b2bfaebfe7ed4d544f286c43c416a3..8949bb7eb08278bbe30d6785a1e6c1902db8a99a 100644 (file)
@@ -1,12 +1,12 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM sched
+
 #if !defined(_TRACE_SCHED_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_SCHED_H
 
 #include <linux/sched.h>
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM sched
-
 /*
  * Tracepoint for calling kthread_stop, performed to end a kthread:
  */
index 1e8fabb57c06e4db8f46704153642bf873f87f77..e499863b96693b108fef4c2bc5b07fd52624ba63 100644 (file)
@@ -1,12 +1,12 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM skb
+
 #if !defined(_TRACE_SKB_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_SKB_H
 
 #include <linux/skbuff.h>
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM skb
-
 /*
  * Tracepoint for free an sk_buff:
  */
index 035f1bff288e66586c2d4697e1bc8d5e0ee9329e..fcfd9a1e4b9640a7c4d3e26c44f2aac38e3b6810 100644 (file)
@@ -1,3 +1,6 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM workqueue
+
 #if !defined(_TRACE_WORKQUEUE_H) || defined(TRACE_HEADER_MULTI_READ)
 #define _TRACE_WORKQUEUE_H
 
@@ -5,9 +8,6 @@
 #include <linux/sched.h>
 #include <linux/tracepoint.h>
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM workqueue
-
 TRACE_EVENT(workqueue_insertion,
 
        TP_PROTO(struct task_struct *wq_thread, struct work_struct *work),
index 1867553c61e595839428e2c394787e205228297d..f64fbaae781aa0e8fa78cf5848b2bb81add4721b 100644 (file)
 #undef TP_fast_assign
 #define TP_fast_assign(args...) args
 
+#undef TP_perf_assign
+#define TP_perf_assign(args...)
+
 #undef TRACE_EVENT
 #define TRACE_EVENT(call, proto, args, tstruct, func, print)           \
 static int                                                             \
@@ -345,6 +348,56 @@ static inline int ftrace_get_offsets_##call(                               \
 
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
+#ifdef CONFIG_EVENT_PROFILE
+
+/*
+ * Generate the functions needed for tracepoint perf_counter support.
+ *
+ * NOTE: The insertion profile callback (ftrace_profile_<call>) is defined later
+ *
+ * static int ftrace_profile_enable_<call>(struct ftrace_event_call *event_call)
+ * {
+ *     int ret = 0;
+ *
+ *     if (!atomic_inc_return(&event_call->profile_count))
+ *             ret = register_trace_<call>(ftrace_profile_<call>);
+ *
+ *     return ret;
+ * }
+ *
+ * static void ftrace_profile_disable_<call>(struct ftrace_event_call *event_call)
+ * {
+ *     if (atomic_add_negative(-1, &event->call->profile_count))
+ *             unregister_trace_<call>(ftrace_profile_<call>);
+ * }
+ *
+ */
+
+#undef TRACE_EVENT
+#define TRACE_EVENT(call, proto, args, tstruct, assign, print)         \
+                                                                       \
+static void ftrace_profile_##call(proto);                              \
+                                                                       \
+static int ftrace_profile_enable_##call(struct ftrace_event_call *event_call) \
+{                                                                      \
+       int ret = 0;                                                    \
+                                                                       \
+       if (!atomic_inc_return(&event_call->profile_count))             \
+               ret = register_trace_##call(ftrace_profile_##call);     \
+                                                                       \
+       return ret;                                                     \
+}                                                                      \
+                                                                       \
+static void ftrace_profile_disable_##call(struct ftrace_event_call *event_call)\
+{                                                                      \
+       if (atomic_add_negative(-1, &event_call->profile_count))        \
+               unregister_trace_##call(ftrace_profile_##call);         \
+}
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+#endif
+
 /*
  * Stage 4 of the trace events.
  *
@@ -447,28 +500,6 @@ static inline int ftrace_get_offsets_##call(                               \
 #define TP_FMT(fmt, args...)   fmt "\n", ##args
 
 #ifdef CONFIG_EVENT_PROFILE
-#define _TRACE_PROFILE(call, proto, args)                              \
-static void ftrace_profile_##call(proto)                               \
-{                                                                      \
-       extern void perf_tpcounter_event(int);                          \
-       perf_tpcounter_event(event_##call.id);                          \
-}                                                                      \
-                                                                       \
-static int ftrace_profile_enable_##call(struct ftrace_event_call *event_call) \
-{                                                                      \
-       int ret = 0;                                                    \
-                                                                       \
-       if (!atomic_inc_return(&event_call->profile_count))             \
-               ret = register_trace_##call(ftrace_profile_##call);     \
-                                                                       \
-       return ret;                                                     \
-}                                                                      \
-                                                                       \
-static void ftrace_profile_disable_##call(struct ftrace_event_call *event_call)\
-{                                                                      \
-       if (atomic_add_negative(-1, &event_call->profile_count))        \
-               unregister_trace_##call(ftrace_profile_##call);         \
-}
 
 #define _TRACE_PROFILE_INIT(call)                                      \
        .profile_count = ATOMIC_INIT(-1),                               \
@@ -476,7 +507,6 @@ static void ftrace_profile_disable_##call(struct ftrace_event_call *event_call)\
        .profile_disable = ftrace_profile_disable_##call,
 
 #else
-#define _TRACE_PROFILE(call, proto, args)
 #define _TRACE_PROFILE_INIT(call)
 #endif
 
@@ -502,7 +532,6 @@ static void ftrace_profile_disable_##call(struct ftrace_event_call *event_call)\
 
 #undef TRACE_EVENT
 #define TRACE_EVENT(call, proto, args, tstruct, assign, print)         \
-_TRACE_PROFILE(call, PARAMS(proto), PARAMS(args))                      \
                                                                        \
 static struct ftrace_event_call event_##call;                          \
                                                                        \
@@ -586,6 +615,110 @@ __attribute__((section("_ftrace_events"))) event_##call = {               \
 
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
-#undef _TRACE_PROFILE
+/*
+ * Define the insertion callback to profile events
+ *
+ * The job is very similar to ftrace_raw_event_<call> except that we don't
+ * insert in the ring buffer but in a perf counter.
+ *
+ * static void ftrace_profile_<call>(proto)
+ * {
+ *     struct ftrace_data_offsets_<call> __maybe_unused __data_offsets;
+ *     struct ftrace_event_call *event_call = &event_<call>;
+ *     extern void perf_tpcounter_event(int, u64, u64, void *, int);
+ *     struct ftrace_raw_##call *entry;
+ *     u64 __addr = 0, __count = 1;
+ *     unsigned long irq_flags;
+ *     int __entry_size;
+ *     int __data_size;
+ *     int pc;
+ *
+ *     local_save_flags(irq_flags);
+ *     pc = preempt_count();
+ *
+ *     __data_size = ftrace_get_offsets_<call>(&__data_offsets, args);
+ *
+ *     // Below we want to get the aligned size by taking into account
+ *     // the u32 field that will later store the buffer size
+ *     __entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),
+ *                          sizeof(u64));
+ *     __entry_size -= sizeof(u32);
+ *
+ *     do {
+ *             char raw_data[__entry_size]; <- allocate our sample in the stack
+ *             struct trace_entry *ent;
+ *
+ *             zero dead bytes from alignment to avoid stack leak to userspace:
+ *
+ *             *(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL;
+ *             entry = (struct ftrace_raw_<call> *)raw_data;
+ *             ent = &entry->ent;
+ *             tracing_generic_entry_update(ent, irq_flags, pc);
+ *             ent->type = event_call->id;
+ *
+ *             <tstruct> <- do some jobs with dynamic arrays
+ *
+ *             <assign>  <- affect our values
+ *
+ *             perf_tpcounter_event(event_call->id, __addr, __count, entry,
+ *                          __entry_size);  <- submit them to perf counter
+ *     } while (0);
+ *
+ * }
+ */
+
+#ifdef CONFIG_EVENT_PROFILE
+
+#undef __perf_addr
+#define __perf_addr(a) __addr = (a)
+
+#undef __perf_count
+#define __perf_count(c) __count = (c)
+
+#undef TRACE_EVENT
+#define TRACE_EVENT(call, proto, args, tstruct, assign, print)         \
+static void ftrace_profile_##call(proto)                               \
+{                                                                      \
+       struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\
+       struct ftrace_event_call *event_call = &event_##call;           \
+       extern void perf_tpcounter_event(int, u64, u64, void *, int);   \
+       struct ftrace_raw_##call *entry;                                \
+       u64 __addr = 0, __count = 1;                                    \
+       unsigned long irq_flags;                                        \
+       int __entry_size;                                               \
+       int __data_size;                                                \
+       int pc;                                                         \
+                                                                       \
+       local_save_flags(irq_flags);                                    \
+       pc = preempt_count();                                           \
+                                                                       \
+       __data_size = ftrace_get_offsets_##call(&__data_offsets, args); \
+       __entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),\
+                            sizeof(u64));                              \
+       __entry_size -= sizeof(u32);                                    \
+                                                                       \
+       do {                                                            \
+               char raw_data[__entry_size];                            \
+               struct trace_entry *ent;                                \
+                                                                       \
+               *(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL; \
+               entry = (struct ftrace_raw_##call *)raw_data;           \
+               ent = &entry->ent;                                      \
+               tracing_generic_entry_update(ent, irq_flags, pc);       \
+               ent->type = event_call->id;                             \
+                                                                       \
+               tstruct                                                 \
+                                                                       \
+               { assign; }                                             \
+                                                                       \
+               perf_tpcounter_event(event_call->id, __addr, __count, entry,\
+                            __entry_size);                             \
+       } while (0);                                                    \
+                                                                       \
+}
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+#endif /* CONFIG_EVENT_PROFILE */
+
 #undef _TRACE_PROFILE_INIT
 
index 1ce05a4cb5f6ffb945391dd93c8e7e172d511d8f..3f7e60995c80714888df391cd8b91ef0f5982306 100644 (file)
@@ -940,6 +940,7 @@ menu "Performance Counters"
 
 config PERF_COUNTERS
        bool "Kernel Performance Counters"
+       default y if PROFILING
        depends on HAVE_PERF_COUNTERS
        select ANON_INODES
        help
@@ -961,9 +962,17 @@ config PERF_COUNTERS
          Say Y if unsure.
 
 config EVENT_PROFILE
-       bool "Tracepoint profile sources"
-       depends on PERF_COUNTERS && EVENT_TRACER
+       bool "Tracepoint profiling sources"
+       depends on PERF_COUNTERS && EVENT_TRACING
        default y
+       help
+        Allow the use of tracepoints as software performance counters.
+
+        When this is enabled, you can create perf counters based on
+        tracepoints using PERF_TYPE_TRACEPOINT and the tracepoint ID
+        found in debugfs://tracing/events/*/*/id. (The -e/--events
+        option to the perf tool can parse and interpret symbolic
+        tracepoints, in the subsystem:tracepoint_name format.)
 
 endmenu
 
index 2c5ade79eb81718702dd1fdf44e8b129e69f88a9..11f4f145be3fd9461cfdcd9ee1087c30fa1c48c8 100644 (file)
@@ -584,8 +584,8 @@ asmlinkage void __init start_kernel(void)
        setup_arch(&command_line);
        mm_init_owner(&init_mm, &init_task);
        setup_command_line(command_line);
-       setup_per_cpu_areas();
        setup_nr_cpu_ids();
+       setup_per_cpu_areas();
        smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
 
        build_all_zonelists();
@@ -733,13 +733,14 @@ static void __init do_ctors(void)
 int initcall_debug;
 core_param(initcall_debug, initcall_debug, bool, 0644);
 
+static char msgbuf[64];
+static struct boot_trace_call call;
+static struct boot_trace_ret ret;
+
 int do_one_initcall(initcall_t fn)
 {
        int count = preempt_count();
        ktime_t calltime, delta, rettime;
-       char msgbuf[64];
-       struct boot_trace_call call;
-       struct boot_trace_ret ret;
 
        if (initcall_debug) {
                call.caller = task_pid_nr(current);
index e35ba2c3a8d770abd7fa97403616dbd8289d26e3..c5e68adc673248b03758bb59d81a5b88f71ef561 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/nsproxy.h>
 #include <linux/pid.h>
 #include <linux/ipc_namespace.h>
+#include <linux/ima.h>
 
 #include <net/sock.h>
 #include "util.h"
@@ -733,6 +734,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
                error = PTR_ERR(filp);
                goto out_putfd;
        }
+       ima_counts_get(filp);
 
        fd_install(fd, filp);
        goto out_upsem;
index 15dd238e533887b1e84f17b070bb64f0b4660961..1bc4701ef4f0d2b214e57f73a1b1096d2f5346e1 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -174,7 +174,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
        shm_unlock(shp);
        if (!is_file_hugepages(shp->shm_file))
                shmem_lock(shp->shm_file, 0, shp->mlock_user);
-       else
+       else if (shp->mlock_user)
                user_shm_unlock(shp->shm_file->f_path.dentry->d_inode->i_size,
                                                shp->mlock_user);
        fput (shp->shm_file);
@@ -369,8 +369,8 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
                /* hugetlb_file_setup applies strict accounting */
                if (shmflg & SHM_NORESERVE)
                        acctflag = VM_NORESERVE;
-               file = hugetlb_file_setup(name, size, acctflag);
-               shp->mlock_user = current_user();
+               file = hugetlb_file_setup(name, size, acctflag,
+                                                       &shp->mlock_user);
        } else {
                /*
                 * Do not allow no accounting for OVERCOMMIT_NEVER, even
@@ -410,6 +410,8 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
        return error;
 
 no_id:
+       if (shp->mlock_user)    /* shmflg & SHM_HUGETLB case */
+               user_shm_unlock(size, shp->mlock_user);
        fput(file);
 no_file:
        security_shm_free(shp);
index 780c8dcf45168ece4ae23ca1917afdff935024d9..2093a691f1c25159ec9f13d58257b21b824cce04 100644 (file)
@@ -96,6 +96,7 @@ obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
 obj-$(CONFIG_FUNCTION_TRACER) += trace/
 obj-$(CONFIG_TRACING) += trace/
 obj-$(CONFIG_X86_DS) += trace/
+obj-$(CONFIG_RING_BUFFER) += trace/
 obj-$(CONFIG_SMP) += sched_cpupri.o
 obj-$(CONFIG_SLOW_WORK) += slow-work.o
 obj-$(CONFIG_PERF_COUNTERS) += perf_counter.o
index 7afa31564162d4acc03bd4ed34144ba459e11bdf..9f3391090b3e826d1d7cb935e58f7d01aa054b37 100644 (file)
@@ -215,6 +215,7 @@ static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file,
 static int acct_on(char *name)
 {
        struct file *file;
+       struct vfsmount *mnt;
        int error;
        struct pid_namespace *ns;
        struct bsd_acct_struct *acct = NULL;
@@ -256,11 +257,12 @@ static int acct_on(char *name)
                acct = NULL;
        }
 
-       mnt_pin(file->f_path.mnt);
+       mnt = file->f_path.mnt;
+       mnt_pin(mnt);
        acct_file_reopen(ns->bacct, file, ns);
        spin_unlock(&acct_lock);
 
-       mntput(file->f_path.mnt); /* it's pinned, now give up active reference */
+       mntput(mnt); /* it's pinned, now give up active reference */
        kfree(acct);
 
        return 0;
index 3737a682cdf52229ee78efa5c637164ba60dcc28..b6eadfe30e7be1627e81b8158e1d581c4575b11f 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/hash.h>
 #include <linux/namei.h>
 #include <linux/smp_lock.h>
+#include <linux/pid_namespace.h>
 
 #include <asm/atomic.h>
 
@@ -734,16 +735,28 @@ static void cgroup_d_remove_dir(struct dentry *dentry)
  * reference to css->refcnt. In general, this refcnt is expected to goes down
  * to zero, soon.
  *
- * CGRP_WAIT_ON_RMDIR flag is modified under cgroup's inode->i_mutex;
+ * CGRP_WAIT_ON_RMDIR flag is set under cgroup's inode->i_mutex;
  */
 DECLARE_WAIT_QUEUE_HEAD(cgroup_rmdir_waitq);
 
-static void cgroup_wakeup_rmdir_waiters(const struct cgroup *cgrp)
+static void cgroup_wakeup_rmdir_waiter(struct cgroup *cgrp)
 {
-       if (unlikely(test_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags)))
+       if (unlikely(test_and_clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags)))
                wake_up_all(&cgroup_rmdir_waitq);
 }
 
+void cgroup_exclude_rmdir(struct cgroup_subsys_state *css)
+{
+       css_get(css);
+}
+
+void cgroup_release_and_wakeup_rmdir(struct cgroup_subsys_state *css)
+{
+       cgroup_wakeup_rmdir_waiter(css->cgroup);
+       css_put(css);
+}
+
+
 static int rebind_subsystems(struct cgroupfs_root *root,
                              unsigned long final_bits)
 {
@@ -960,6 +973,7 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp)
        INIT_LIST_HEAD(&cgrp->children);
        INIT_LIST_HEAD(&cgrp->css_sets);
        INIT_LIST_HEAD(&cgrp->release_list);
+       INIT_LIST_HEAD(&cgrp->pids_list);
        init_rwsem(&cgrp->pids_mutex);
 }
 static void init_cgroup_root(struct cgroupfs_root *root)
@@ -1357,7 +1371,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
         * wake up rmdir() waiter. the rmdir should fail since the cgroup
         * is no longer empty.
         */
-       cgroup_wakeup_rmdir_waiters(cgrp);
+       cgroup_wakeup_rmdir_waiter(cgrp);
        return 0;
 }
 
@@ -2201,12 +2215,30 @@ err:
        return ret;
 }
 
+/*
+ * Cache pids for all threads in the same pid namespace that are
+ * opening the same "tasks" file.
+ */
+struct cgroup_pids {
+       /* The node in cgrp->pids_list */
+       struct list_head list;
+       /* The cgroup those pids belong to */
+       struct cgroup *cgrp;
+       /* The namepsace those pids belong to */
+       struct pid_namespace *ns;
+       /* Array of process ids in the cgroup */
+       pid_t *tasks_pids;
+       /* How many files are using the this tasks_pids array */
+       int use_count;
+       /* Length of the current tasks_pids array */
+       int length;
+};
+
 static int cmppid(const void *a, const void *b)
 {
        return *(pid_t *)a - *(pid_t *)b;
 }
 
-
 /*
  * seq_file methods for the "tasks" file. The seq_file position is the
  * next pid to display; the seq_file iterator is a pointer to the pid
@@ -2221,45 +2253,47 @@ static void *cgroup_tasks_start(struct seq_file *s, loff_t *pos)
         * after a seek to the start). Use a binary-search to find the
         * next pid to display, if any
         */
-       struct cgroup *cgrp = s->private;
+       struct cgroup_pids *cp = s->private;
+       struct cgroup *cgrp = cp->cgrp;
        int index = 0, pid = *pos;
        int *iter;
 
        down_read(&cgrp->pids_mutex);
        if (pid) {
-               int end = cgrp->pids_length;
+               int end = cp->length;
 
                while (index < end) {
                        int mid = (index + end) / 2;
-                       if (cgrp->tasks_pids[mid] == pid) {
+                       if (cp->tasks_pids[mid] == pid) {
                                index = mid;
                                break;
-                       } else if (cgrp->tasks_pids[mid] <= pid)
+                       } else if (cp->tasks_pids[mid] <= pid)
                                index = mid + 1;
                        else
                                end = mid;
                }
        }
        /* If we're off the end of the array, we're done */
-       if (index >= cgrp->pids_length)
+       if (index >= cp->length)
                return NULL;
        /* Update the abstract position to be the actual pid that we found */
-       iter = cgrp->tasks_pids + index;
+       iter = cp->tasks_pids + index;
        *pos = *iter;
        return iter;
 }
 
 static void cgroup_tasks_stop(struct seq_file *s, void *v)
 {
-       struct cgroup *cgrp = s->private;
+       struct cgroup_pids *cp = s->private;
+       struct cgroup *cgrp = cp->cgrp;
        up_read(&cgrp->pids_mutex);
 }
 
 static void *cgroup_tasks_next(struct seq_file *s, void *v, loff_t *pos)
 {
-       struct cgroup *cgrp = s->private;
+       struct cgroup_pids *cp = s->private;
        int *p = v;
-       int *end = cgrp->tasks_pids + cgrp->pids_length;
+       int *end = cp->tasks_pids + cp->length;
 
        /*
         * Advance to the next pid in the array. If this goes off the
@@ -2286,26 +2320,33 @@ static struct seq_operations cgroup_tasks_seq_operations = {
        .show = cgroup_tasks_show,
 };
 
-static void release_cgroup_pid_array(struct cgroup *cgrp)
+static void release_cgroup_pid_array(struct cgroup_pids *cp)
 {
+       struct cgroup *cgrp = cp->cgrp;
+
        down_write(&cgrp->pids_mutex);
-       BUG_ON(!cgrp->pids_use_count);
-       if (!--cgrp->pids_use_count) {
-               kfree(cgrp->tasks_pids);
-               cgrp->tasks_pids = NULL;
-               cgrp->pids_length = 0;
+       BUG_ON(!cp->use_count);
+       if (!--cp->use_count) {
+               list_del(&cp->list);
+               put_pid_ns(cp->ns);
+               kfree(cp->tasks_pids);
+               kfree(cp);
        }
        up_write(&cgrp->pids_mutex);
 }
 
 static int cgroup_tasks_release(struct inode *inode, struct file *file)
 {
-       struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent);
+       struct seq_file *seq;
+       struct cgroup_pids *cp;
 
        if (!(file->f_mode & FMODE_READ))
                return 0;
 
-       release_cgroup_pid_array(cgrp);
+       seq = file->private_data;
+       cp = seq->private;
+
+       release_cgroup_pid_array(cp);
        return seq_release(inode, file);
 }
 
@@ -2324,6 +2365,8 @@ static struct file_operations cgroup_tasks_operations = {
 static int cgroup_tasks_open(struct inode *unused, struct file *file)
 {
        struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent);
+       struct pid_namespace *ns = current->nsproxy->pid_ns;
+       struct cgroup_pids *cp;
        pid_t *pidarray;
        int npids;
        int retval;
@@ -2350,20 +2393,37 @@ static int cgroup_tasks_open(struct inode *unused, struct file *file)
         * array if necessary
         */
        down_write(&cgrp->pids_mutex);
-       kfree(cgrp->tasks_pids);
-       cgrp->tasks_pids = pidarray;
-       cgrp->pids_length = npids;
-       cgrp->pids_use_count++;
+
+       list_for_each_entry(cp, &cgrp->pids_list, list) {
+               if (ns == cp->ns)
+                       goto found;
+       }
+
+       cp = kzalloc(sizeof(*cp), GFP_KERNEL);
+       if (!cp) {
+               up_write(&cgrp->pids_mutex);
+               kfree(pidarray);
+               return -ENOMEM;
+       }
+       cp->cgrp = cgrp;
+       cp->ns = ns;
+       get_pid_ns(ns);
+       list_add(&cp->list, &cgrp->pids_list);
+found:
+       kfree(cp->tasks_pids);
+       cp->tasks_pids = pidarray;
+       cp->length = npids;
+       cp->use_count++;
        up_write(&cgrp->pids_mutex);
 
        file->f_op = &cgroup_tasks_operations;
 
        retval = seq_open(file, &cgroup_tasks_seq_operations);
        if (retval) {
-               release_cgroup_pid_array(cgrp);
+               release_cgroup_pid_array(cp);
                return retval;
        }
-       ((struct seq_file *)file->private_data)->private = cgrp;
+       ((struct seq_file *)file->private_data)->private = cp;
        return 0;
 }
 
@@ -2695,34 +2755,43 @@ again:
        }
        mutex_unlock(&cgroup_mutex);
 
+       /*
+        * In general, subsystem has no css->refcnt after pre_destroy(). But
+        * in racy cases, subsystem may have to get css->refcnt after
+        * pre_destroy() and it makes rmdir return with -EBUSY. This sometimes
+        * make rmdir return -EBUSY too often. To avoid that, we use waitqueue
+        * for cgroup's rmdir. CGRP_WAIT_ON_RMDIR is for synchronizing rmdir
+        * and subsystem's reference count handling. Please see css_get/put
+        * and css_tryget() and cgroup_wakeup_rmdir_waiter() implementation.
+        */
+       set_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags);
+
        /*
         * Call pre_destroy handlers of subsys. Notify subsystems
         * that rmdir() request comes.
         */
        ret = cgroup_call_pre_destroy(cgrp);
-       if (ret)
+       if (ret) {
+               clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags);
                return ret;
+       }
 
        mutex_lock(&cgroup_mutex);
        parent = cgrp->parent;
        if (atomic_read(&cgrp->count) || !list_empty(&cgrp->children)) {
+               clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags);
                mutex_unlock(&cgroup_mutex);
                return -EBUSY;
        }
-       /*
-        * css_put/get is provided for subsys to grab refcnt to css. In typical
-        * case, subsystem has no reference after pre_destroy(). But, under
-        * hierarchy management, some *temporal* refcnt can be hold.
-        * To avoid returning -EBUSY to a user, waitqueue is used. If subsys
-        * is really busy, it should return -EBUSY at pre_destroy(). wake_up
-        * is called when css_put() is called and refcnt goes down to 0.
-        */
-       set_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags);
        prepare_to_wait(&cgroup_rmdir_waitq, &wait, TASK_INTERRUPTIBLE);
-
        if (!cgroup_clear_css_refs(cgrp)) {
                mutex_unlock(&cgroup_mutex);
-               schedule();
+               /*
+                * Because someone may call cgroup_wakeup_rmdir_waiter() before
+                * prepare_to_wait(), we need to check this flag.
+                */
+               if (test_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags))
+                       schedule();
                finish_wait(&cgroup_rmdir_waitq, &wait);
                clear_bit(CGRP_WAIT_ON_RMDIR, &cgrp->flags);
                if (signal_pending(current))
@@ -3294,7 +3363,7 @@ void __css_put(struct cgroup_subsys_state *css)
                        set_bit(CGRP_RELEASABLE, &cgrp->flags);
                        check_for_release(cgrp);
                }
-               cgroup_wakeup_rmdir_waiters(cgrp);
+               cgroup_wakeup_rmdir_waiter(cgrp);
        }
        rcu_read_unlock();
 }
index 628d41f0dd54ed163e32f2d4d2e9ec6909ccd2ab..869dc221733e27701c275a0bdf283404507108f6 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/completion.h>
 #include <linux/personality.h>
 #include <linux/tty.h>
-#include <linux/mnt_namespace.h>
 #include <linux/iocontext.h>
 #include <linux/key.h>
 #include <linux/security.h>
index 467746b3f0aa2eec5970c42f56a71d8ae1583b7f..e6c04d462ab250b806cd2e7d76d84fd1729d121e 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/completion.h>
-#include <linux/mnt_namespace.h>
 #include <linux/personality.h>
 #include <linux/mempolicy.h>
 #include <linux/sem.h>
@@ -568,18 +567,18 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm)
         * the value intact in a core dump, and to save the unnecessary
         * trouble otherwise.  Userland only wants this done for a sys_exit.
         */
-       if (tsk->clear_child_tid
-           && !(tsk->flags & PF_SIGNALED)
-           && atomic_read(&mm->mm_users) > 1) {
-               u32 __user * tidptr = tsk->clear_child_tid;
+       if (tsk->clear_child_tid) {
+               if (!(tsk->flags & PF_SIGNALED) &&
+                   atomic_read(&mm->mm_users) > 1) {
+                       /*
+                        * We don't check the error code - if userspace has
+                        * not set up a proper pointer then tough luck.
+                        */
+                       put_user(0, tsk->clear_child_tid);
+                       sys_futex(tsk->clear_child_tid, FUTEX_WAKE,
+                                       1, NULL, NULL, 0);
+               }
                tsk->clear_child_tid = NULL;
-
-               /*
-                * We don't check the error code - if userspace has
-                * not set up a proper pointer then tough luck.
-                */
-               put_user(0, tidptr);
-               sys_futex(tidptr, FUTEX_WAKE, 1, NULL, NULL, 0);
        }
 }
 
@@ -816,11 +815,8 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 {
        struct signal_struct *sig;
 
-       if (clone_flags & CLONE_THREAD) {
-               atomic_inc(&current->signal->count);
-               atomic_inc(&current->signal->live);
+       if (clone_flags & CLONE_THREAD)
                return 0;
-       }
 
        sig = kmem_cache_alloc(signal_cachep, GFP_KERNEL);
        tsk->signal = sig;
@@ -878,16 +874,6 @@ void __cleanup_signal(struct signal_struct *sig)
        kmem_cache_free(signal_cachep, sig);
 }
 
-static 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 void copy_flags(unsigned long clone_flags, struct task_struct *p)
 {
        unsigned long new_flags = p->flags;
@@ -1240,6 +1226,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        }
 
        if (clone_flags & CLONE_THREAD) {
+               atomic_inc(&current->signal->count);
+               atomic_inc(&current->signal->live);
                p->group_leader = current->group_leader;
                list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);
        }
@@ -1269,6 +1257,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        write_unlock_irq(&tasklist_lock);
        proc_fork_connector(p);
        cgroup_post_fork(p);
+       perf_counter_fork(p);
        return p;
 
 bad_fork_free_pid:
@@ -1282,7 +1271,8 @@ bad_fork_cleanup_mm:
        if (p->mm)
                mmput(p->mm);
 bad_fork_cleanup_signal:
-       cleanup_signal(p);
+       if (!(clone_flags & CLONE_THREAD))
+               __cleanup_signal(p->signal);
 bad_fork_cleanup_sighand:
        __cleanup_sighand(p->sighand);
 bad_fork_cleanup_fs:
@@ -1408,12 +1398,6 @@ long do_fork(unsigned long clone_flags,
                if (clone_flags & CLONE_VFORK) {
                        p->vfork_done = &vfork;
                        init_completion(&vfork);
-               } else if (!(clone_flags & CLONE_VM)) {
-                       /*
-                        * vfork will do an exec which will call
-                        * set_task_comm()
-                        */
-                       perf_counter_fork(p);
                }
 
                audit_finish_fork(p);
index 2f4936cf708367c90f3d16fe5a4d9b49ec66e90e..bd1d42b17cb2f52f5156506ba25d75376102af7f 100644 (file)
@@ -44,12 +44,19 @@ void refrigerator(void)
        recalc_sigpending(); /* We sent fake signal, clean it up */
        spin_unlock_irq(&current->sighand->siglock);
 
+       /* prevent accounting of that task to load */
+       current->flags |= PF_FREEZING;
+
        for (;;) {
                set_current_state(TASK_UNINTERRUPTIBLE);
                if (!frozen(current))
                        break;
                schedule();
        }
+
+       /* Remove the accounting blocker */
+       current->flags &= ~PF_FREEZING;
+
        pr_debug("%s left refrigerator\n", current->comm);
        __set_current_state(save);
 }
index 1c337112335c60d6831d7b5cf1ee9a26cba54a77..e18cfbdc71904d0260d505bd73a41d06a38982d9 100644 (file)
@@ -247,6 +247,7 @@ again:
        if (err < 0)
                return err;
 
+       page = compound_head(page);
        lock_page(page);
        if (!page->mapping) {
                unlock_page(page);
@@ -299,7 +300,7 @@ void put_futex_key(int fshared, union futex_key *key)
 static int fault_in_user_writeable(u32 __user *uaddr)
 {
        int ret = get_user_pages(current, current->mm, (unsigned long)uaddr,
-                                sizeof(*uaddr), 1, 0, NULL, NULL);
+                                1, 1, 0, NULL, NULL);
        return ret < 0 ? ret : 0;
 }
 
@@ -1009,15 +1010,19 @@ void requeue_futex(struct futex_q *q, struct futex_hash_bucket *hb1,
  * requeue_pi_wake_futex() - Wake a task that acquired the lock during requeue
  * q:  the futex_q
  * key:        the key of the requeue target futex
+ * hb:  the hash_bucket of the requeue target futex
  *
  * During futex_requeue, with requeue_pi=1, it is possible to acquire the
  * target futex if it is uncontended or via a lock steal.  Set the futex_q key
  * to the requeue target futex so the waiter can detect the wakeup on the right
  * futex, but remove it from the hb and NULL the rt_waiter so it can detect
- * atomic lock acquisition.  Must be called with the q->lock_ptr held.
+ * atomic lock acquisition.  Set the q->lock_ptr to the requeue target hb->lock
+ * to protect access to the pi_state to fixup the owner later.  Must be called
+ * with both q->lock_ptr and hb->lock held.
  */
 static inline
-void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key)
+void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
+                          struct futex_hash_bucket *hb)
 {
        drop_futex_key_refs(&q->key);
        get_futex_key_refs(key);
@@ -1029,6 +1034,11 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key)
        WARN_ON(!q->rt_waiter);
        q->rt_waiter = NULL;
 
+       q->lock_ptr = &hb->lock;
+#ifdef CONFIG_DEBUG_PI_LIST
+       q->list.plist.lock = &hb->lock;
+#endif
+
        wake_up_state(q->task, TASK_NORMAL);
 }
 
@@ -1087,7 +1097,7 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
        ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task,
                                   set_waiters);
        if (ret == 1)
-               requeue_pi_wake_futex(top_waiter, key2);
+               requeue_pi_wake_futex(top_waiter, key2, hb2);
 
        return ret;
 }
@@ -1246,8 +1256,15 @@ retry_private:
                if (!match_futex(&this->key, &key1))
                        continue;
 
-               WARN_ON(!requeue_pi && this->rt_waiter);
-               WARN_ON(requeue_pi && !this->rt_waiter);
+               /*
+                * FUTEX_WAIT_REQEUE_PI and FUTEX_CMP_REQUEUE_PI should always
+                * be paired with each other and no other futex ops.
+                */
+               if ((requeue_pi && !this->rt_waiter) ||
+                   (!requeue_pi && this->rt_waiter)) {
+                       ret = -EINVAL;
+                       break;
+               }
 
                /*
                 * Wake nr_wake waiters.  For requeue_pi, if we acquired the
@@ -1272,7 +1289,7 @@ retry_private:
                                                        this->task, 1);
                        if (ret == 1) {
                                /* We got the lock. */
-                               requeue_pi_wake_futex(this, &key2);
+                               requeue_pi_wake_futex(this, &key2, hb2);
                                continue;
                        } else if (ret) {
                                /* -EDEADLK */
index d607a5b9ee29923617d462288e9853327c7d1527..235716556bf16ed9b97c19a9578ef24dec19edb1 100644 (file)
@@ -180,7 +180,8 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
        int cmd = op & FUTEX_CMD_MASK;
 
        if (utime && (cmd == FUTEX_WAIT || cmd == FUTEX_LOCK_PI ||
-                     cmd == FUTEX_WAIT_BITSET)) {
+                     cmd == FUTEX_WAIT_BITSET ||
+                     cmd == FUTEX_WAIT_REQUEUE_PI)) {
                if (get_compat_timespec(&ts, utime))
                        return -EFAULT;
                if (!timespec_valid(&ts))
@@ -191,7 +192,8 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val,
                        t = ktime_add_safe(ktime_get(), t);
                tp = &t;
        }
-       if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE)
+       if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE ||
+           cmd == FUTEX_CMP_REQUEUE_PI || cmd == FUTEX_WAKE_OP)
                val2 = (int) (unsigned long) utime;
 
        return do_futex(uaddr, op, val, tp, uaddr2, val2, val3);
index 9002958a96e70ef0f8acc70ceeccac5327efae9e..49da79ab8486df682bc7f252674b4a01b810c108 100644 (file)
@@ -191,6 +191,46 @@ struct hrtimer_clock_base *lock_hrtimer_base(const struct hrtimer *timer,
        }
 }
 
+
+/*
+ * Get the preferred target CPU for NOHZ
+ */
+static int hrtimer_get_target(int this_cpu, int pinned)
+{
+#ifdef CONFIG_NO_HZ
+       if (!pinned && get_sysctl_timer_migration() && idle_cpu(this_cpu)) {
+               int preferred_cpu = get_nohz_load_balancer();
+
+               if (preferred_cpu >= 0)
+                       return preferred_cpu;
+       }
+#endif
+       return this_cpu;
+}
+
+/*
+ * With HIGHRES=y we do not migrate the timer when it is expiring
+ * before the next event on the target cpu because we cannot reprogram
+ * the target cpu hardware and we would cause it to fire late.
+ *
+ * Called with cpu_base->lock of target cpu held.
+ */
+static int
+hrtimer_check_target(struct hrtimer *timer, struct hrtimer_clock_base *new_base)
+{
+#ifdef CONFIG_HIGH_RES_TIMERS
+       ktime_t expires;
+
+       if (!new_base->cpu_base->hres_active)
+               return 0;
+
+       expires = ktime_sub(hrtimer_get_expires(timer), new_base->offset);
+       return expires.tv64 <= new_base->cpu_base->expires_next.tv64;
+#else
+       return 0;
+#endif
+}
+
 /*
  * Switch the timer base to the current CPU when possible.
  */
@@ -200,16 +240,8 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
 {
        struct hrtimer_clock_base *new_base;
        struct hrtimer_cpu_base *new_cpu_base;
-       int cpu, preferred_cpu = -1;
-
-       cpu = smp_processor_id();
-#if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP)
-       if (!pinned && get_sysctl_timer_migration() && idle_cpu(cpu)) {
-               preferred_cpu = get_nohz_load_balancer();
-               if (preferred_cpu >= 0)
-                       cpu = preferred_cpu;
-       }
-#endif
+       int this_cpu = smp_processor_id();
+       int cpu = hrtimer_get_target(this_cpu, pinned);
 
 again:
        new_cpu_base = &per_cpu(hrtimer_bases, cpu);
@@ -217,7 +249,7 @@ again:
 
        if (base != new_base) {
                /*
-                * We are trying to schedule the timer on the local CPU.
+                * We are trying to move timer to new_base.
                 * However we can't change timer's base while it is running,
                 * so we keep it on the same CPU. No hassle vs. reprogramming
                 * the event source in the high resolution case. The softirq
@@ -233,38 +265,12 @@ again:
                spin_unlock(&base->cpu_base->lock);
                spin_lock(&new_base->cpu_base->lock);
 
-               /* Optimized away for NOHZ=n SMP=n */
-               if (cpu == preferred_cpu) {
-                       /* Calculate clock monotonic expiry time */
-#ifdef CONFIG_HIGH_RES_TIMERS
-                       ktime_t expires = ktime_sub(hrtimer_get_expires(timer),
-                                                       new_base->offset);
-#else
-                       ktime_t expires = hrtimer_get_expires(timer);
-#endif
-
-                       /*
-                        * Get the next event on target cpu from the
-                        * clock events layer.
-                        * This covers the highres=off nohz=on case as well.
-                        */
-                       ktime_t next = clockevents_get_next_event(cpu);
-
-                       ktime_t delta = ktime_sub(expires, next);
-
-                       /*
-                        * We do not migrate the timer when it is expiring
-                        * before the next event on the target cpu because
-                        * we cannot reprogram the target cpu hardware and
-                        * we would cause it to fire late.
-                        */
-                       if (delta.tv64 < 0) {
-                               cpu = smp_processor_id();
-                               spin_unlock(&new_base->cpu_base->lock);
-                               spin_lock(&base->cpu_base->lock);
-                               timer->base = base;
-                               goto again;
-                       }
+               if (cpu != this_cpu && hrtimer_check_target(timer, new_base)) {
+                       cpu = this_cpu;
+                       spin_unlock(&new_base->cpu_base->lock);
+                       spin_lock(&base->cpu_base->lock);
+                       timer->base = base;
+                       goto again;
                }
                timer->base = new_base;
        }
@@ -1276,14 +1282,22 @@ void hrtimer_interrupt(struct clock_event_device *dev)
 
        expires_next.tv64 = KTIME_MAX;
 
+       spin_lock(&cpu_base->lock);
+       /*
+        * We set expires_next to KTIME_MAX here with cpu_base->lock
+        * held to prevent that a timer is enqueued in our queue via
+        * the migration code. This does not affect enqueueing of
+        * timers which run their callback and need to be requeued on
+        * this CPU.
+        */
+       cpu_base->expires_next.tv64 = KTIME_MAX;
+
        base = cpu_base->clock_base;
 
        for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
                ktime_t basenow;
                struct rb_node *node;
 
-               spin_lock(&cpu_base->lock);
-
                basenow = ktime_add(now, base->offset);
 
                while ((node = base->first)) {
@@ -1316,11 +1330,15 @@ void hrtimer_interrupt(struct clock_event_device *dev)
 
                        __run_hrtimer(timer);
                }
-               spin_unlock(&cpu_base->lock);
                base++;
        }
 
+       /*
+        * Store the new expiry value so the migration code can verify
+        * against it.
+        */
        cpu_base->expires_next = expires_next;
+       spin_unlock(&cpu_base->lock);
 
        /* Reprogramming necessary ? */
        if (expires_next.tv64 != KTIME_MAX) {
index 73468253143ba55883072d1020791c11b1e30210..e70ed5592eb90e406c201e5d2881be679a5fc278 100644 (file)
@@ -42,8 +42,7 @@ static inline void unregister_handler_proc(unsigned int irq,
 
 extern int irq_select_affinity_usr(unsigned int irq);
 
-extern void
-irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask);
+extern void irq_set_thread_affinity(struct irq_desc *desc);
 
 /*
  * Debugging printout:
index 50da676729013dfe8dbc7929a4fdec16412f7780..0ec9ed831737bead620104312249d893e3a606bc 100644 (file)
@@ -80,14 +80,22 @@ int irq_can_set_affinity(unsigned int irq)
        return 1;
 }
 
-void
-irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask)
+/**
+ *     irq_set_thread_affinity - Notify irq threads to adjust affinity
+ *     @desc:          irq descriptor which has affitnity changed
+ *
+ *     We just set IRQTF_AFFINITY and delegate the affinity setting
+ *     to the interrupt thread itself. We can not call
+ *     set_cpus_allowed_ptr() here as we hold desc->lock and this
+ *     code can be called from hard interrupt context.
+ */
+void irq_set_thread_affinity(struct irq_desc *desc)
 {
        struct irqaction *action = desc->action;
 
        while (action) {
                if (action->thread)
-                       set_cpus_allowed_ptr(action->thread, cpumask);
+                       set_bit(IRQTF_AFFINITY, &action->thread_flags);
                action = action->next;
        }
 }
@@ -112,7 +120,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
        if (desc->status & IRQ_MOVE_PCNTXT) {
                if (!desc->chip->set_affinity(irq, cpumask)) {
                        cpumask_copy(desc->affinity, cpumask);
-                       irq_set_thread_affinity(desc, cpumask);
+                       irq_set_thread_affinity(desc);
                }
        }
        else {
@@ -122,7 +130,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
 #else
        if (!desc->chip->set_affinity(irq, cpumask)) {
                cpumask_copy(desc->affinity, cpumask);
-               irq_set_thread_affinity(desc, cpumask);
+               irq_set_thread_affinity(desc);
        }
 #endif
        desc->status |= IRQ_AFFINITY_SET;
@@ -176,7 +184,7 @@ int irq_select_affinity_usr(unsigned int irq)
        spin_lock_irqsave(&desc->lock, flags);
        ret = setup_affinity(irq, desc);
        if (!ret)
-               irq_set_thread_affinity(desc, desc->affinity);
+               irq_set_thread_affinity(desc);
        spin_unlock_irqrestore(&desc->lock, flags);
 
        return ret;
@@ -443,6 +451,39 @@ static int irq_wait_for_interrupt(struct irqaction *action)
        return -1;
 }
 
+#ifdef CONFIG_SMP
+/*
+ * Check whether we need to change the affinity of the interrupt thread.
+ */
+static void
+irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
+{
+       cpumask_var_t mask;
+
+       if (!test_and_clear_bit(IRQTF_AFFINITY, &action->thread_flags))
+               return;
+
+       /*
+        * In case we are out of memory we set IRQTF_AFFINITY again and
+        * try again next time
+        */
+       if (!alloc_cpumask_var(&mask, GFP_KERNEL)) {
+               set_bit(IRQTF_AFFINITY, &action->thread_flags);
+               return;
+       }
+
+       spin_lock_irq(&desc->lock);
+       cpumask_copy(mask, desc->affinity);
+       spin_unlock_irq(&desc->lock);
+
+       set_cpus_allowed_ptr(current, mask);
+       free_cpumask_var(mask);
+}
+#else
+static inline void
+irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { }
+#endif
+
 /*
  * Interrupt handler thread
  */
@@ -458,6 +499,8 @@ static int irq_thread(void *data)
 
        while (!irq_wait_for_interrupt(action)) {
 
+               irq_thread_check_affinity(desc, action);
+
                atomic_inc(&desc->threads_active);
 
                spin_lock_irq(&desc->lock);
@@ -564,7 +607,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
                 */
                get_task_struct(t);
                new->thread = t;
-               wake_up_process(t);
        }
 
        /*
@@ -647,6 +689,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
                                (int)(new->flags & IRQF_TRIGGER_MASK));
        }
 
+       new->irq = irq;
        *old_ptr = new;
 
        /* Reset broken irq detection when installing new handler */
@@ -664,7 +707,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 
        spin_unlock_irqrestore(&desc->lock, flags);
 
-       new->irq = irq;
+       /*
+        * Strictly no need to wake it up, but hung_task complains
+        * when no hard interrupt wakes the thread up.
+        */
+       if (new->thread)
+               wake_up_process(new->thread);
+
        register_irq_proc(irq, desc);
        new->dir = NULL;
        register_handler_proc(irq, new);
@@ -718,7 +767,6 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
 {
        struct irq_desc *desc = irq_to_desc(irq);
        struct irqaction *action, **action_ptr;
-       struct task_struct *irqthread;
        unsigned long flags;
 
        WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq);
@@ -766,9 +814,6 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
                        desc->chip->disable(irq);
        }
 
-       irqthread = action->thread;
-       action->thread = NULL;
-
        spin_unlock_irqrestore(&desc->lock, flags);
 
        unregister_handler_proc(irq, action);
@@ -776,12 +821,6 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
        /* Make sure it's not being used on another CPU: */
        synchronize_irq(irq);
 
-       if (irqthread) {
-               if (!test_bit(IRQTF_DIED, &action->thread_flags))
-                       kthread_stop(irqthread);
-               put_task_struct(irqthread);
-       }
-
 #ifdef CONFIG_DEBUG_SHIRQ
        /*
         * It's a shared IRQ -- the driver ought to be prepared for an IRQ
@@ -797,6 +836,13 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
                local_irq_restore(flags);
        }
 #endif
+
+       if (action->thread) {
+               if (!test_bit(IRQTF_DIED, &action->thread_flags))
+                       kthread_stop(action->thread);
+               put_task_struct(action->thread);
+       }
+
        return action;
 }
 
index cfe767ca154501460f9f7e757c08d881611e9c95..fcb6c96f2627297654e9c3336e7f349846205752 100644 (file)
@@ -45,7 +45,7 @@ void move_masked_irq(int irq)
                   < nr_cpu_ids))
                if (!desc->chip->set_affinity(irq, desc->pending_mask)) {
                        cpumask_copy(desc->affinity, desc->pending_mask);
-                       irq_set_thread_affinity(desc, desc->pending_mask);
+                       irq_set_thread_affinity(desc);
                }
 
        cpumask_clear(desc->pending_mask);
index 2f69bee57bf21ca5a42027834ddccee96670d989..3fd30197da2e285d1cdc6f10f037bff9cbc6f25d 100644 (file)
@@ -107,8 +107,8 @@ out_unlock:
 
 struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
 {
-       /* those all static, do move them */
-       if (desc->irq < NR_IRQS_LEGACY)
+       /* those static or target node is -1, do not move them */
+       if (desc->irq < NR_IRQS_LEGACY || node == -1)
                return desc;
 
        if (desc->node != node)
index ae1c35201cc873d697921cb2c5da95896d89493d..f336e2107f980e2546ecc118d2dd3239f655ebae 100644 (file)
@@ -1228,7 +1228,7 @@ static int __init parse_crashkernel_mem(char                      *cmdline,
        } while (*cur++ == ',');
 
        if (*crash_size > 0) {
-               while (*cur != ' ' && *cur != '@')
+               while (*cur && *cur != ' ' && *cur != '@')
                        cur++;
                if (*cur == '@') {
                        cur++;
index 7e95bedb2bfc19bc1d10eaed1337cd02c1ffdb1c..385c31a1bdbf3118b3d82d44b6720af727738bcb 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/unistd.h>
 #include <linux/kmod.h>
 #include <linux/slab.h>
-#include <linux/mnt_namespace.h>
 #include <linux/completion.h>
 #include <linux/file.h>
 #include <linux/fdtable.h>
index c0fa54b276d951042f69febb6df8c27190850dd9..0540948e29abf0217fc7e4edded97874aa26605c 100644 (file)
@@ -237,13 +237,9 @@ static int __kprobes collect_garbage_slots(void)
 {
        struct kprobe_insn_page *kip;
        struct hlist_node *pos, *next;
-       int safety;
 
        /* Ensure no-one is preepmted on the garbages */
-       mutex_unlock(&kprobe_insn_mutex);
-       safety = check_safety();
-       mutex_lock(&kprobe_insn_mutex);
-       if (safety != 0)
+       if (check_safety())
                return -EAGAIN;
 
        hlist_for_each_entry_safe(kip, pos, next, &kprobe_insn_pages, hlist) {
@@ -698,7 +694,7 @@ int __kprobes register_kprobe(struct kprobe *p)
        p->addr = addr;
 
        preempt_disable();
-       if (!__kernel_text_address((unsigned long) p->addr) ||
+       if (!kernel_text_address((unsigned long) p->addr) ||
            in_kprobes_functions((unsigned long) p->addr)) {
                preempt_enable();
                return -EINVAL;
index 9b1a7de26979a7d02abc5f2e68025a5acea0bdfd..eb8751aa0418d448f2b46d364074d39bf622ec6b 100644 (file)
@@ -180,10 +180,12 @@ EXPORT_SYMBOL(kthread_bind);
  * @k: thread created by kthread_create().
  *
  * Sets kthread_should_stop() for @k to return true, wakes it, and
- * waits for it to exit.  Your threadfn() must not call do_exit()
- * itself if you use this function!  This can also be called after
- * kthread_create() instead of calling wake_up_process(): the thread
- * will exit without calling threadfn().
+ * waits for it to exit. This can also be called after kthread_create()
+ * instead of calling wake_up_process(): the thread will exit without
+ * calling threadfn().
+ *
+ * If threadfn() may call do_exit() itself, the caller must ensure
+ * task_struct can't go away.
  *
  * Returns the result of threadfn(), or %-EINTR if wake_up_process()
  * was never called.
index d7135aa2d2c4ccc0f3638cfa6fb3b2742e33c43c..e94caa666dba0876c6128801e3915285a797e78e 100644 (file)
@@ -758,7 +758,8 @@ static int __init lockdep_proc_init(void)
                    &proc_lockdep_stats_operations);
 
 #ifdef CONFIG_LOCK_STAT
-       proc_create("lock_stat", S_IRUSR, NULL, &proc_lock_stat_operations);
+       proc_create("lock_stat", S_IRUSR | S_IWUSR, NULL,
+                   &proc_lock_stat_operations);
 #endif
 
        return 0;
index 38928fcaff2bcb517375c3e6b19d398e4d423c05..2d537186191f1c93ba39a2df1990741f690f3aac 100644 (file)
@@ -909,16 +909,18 @@ void __symbol_put(const char *symbol)
 }
 EXPORT_SYMBOL(__symbol_put);
 
+/* Note this assumes addr is a function, which it currently always is. */
 void symbol_put_addr(void *addr)
 {
        struct module *modaddr;
+       unsigned long a = (unsigned long)dereference_function_descriptor(addr);
 
-       if (core_kernel_text((unsigned long)addr))
+       if (core_kernel_text(a))
                return;
 
        /* module_text_address is safe here: we're supposed to have reference
         * to module from symbol_get, so it can't go away. */
-       modaddr = __module_text_address((unsigned long)addr);
+       modaddr = __module_text_address(a);
        BUG_ON(!modaddr);
        module_put(modaddr);
 }
@@ -1068,7 +1070,8 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
 {
        const unsigned long *crc;
 
-       if (!find_symbol("module_layout", NULL, &crc, true, false))
+       if (!find_symbol(MODULE_SYMBOL_PREFIX "module_layout", NULL,
+                        &crc, true, false))
                BUG();
        return check_version(sechdrs, versindex, "module_layout", mod, crc);
 }
@@ -1271,6 +1274,10 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect,
        struct module_notes_attrs *notes_attrs;
        struct bin_attribute *nattr;
 
+       /* failed to create section attributes, so can't create notes */
+       if (!mod->sect_attrs)
+               return;
+
        /* Count notes sections and allocate structures.  */
        notes = 0;
        for (i = 0; i < nsect; i++)
@@ -2451,9 +2458,9 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
                return ret;
        }
        if (ret > 0) {
-               printk(KERN_WARNING "%s: '%s'->init suspiciously returned %d, "
-                                   "it should follow 0/-E convention\n"
-                      KERN_WARNING "%s: loading module anyway...\n",
+               printk(KERN_WARNING
+"%s: '%s'->init suspiciously returned %d, it should follow 0/-E convention\n"
+"%s: loading module anyway...\n",
                       __func__, mod->name, ret,
                       __func__);
                dump_stack();
index 984b3ecbd72c5ca791e501e18d09c47862b677ad..512ab73b0ca3afed1553b5e01218c92d17630a4c 100644 (file)
@@ -301,6 +301,7 @@ int oops_may_print(void)
  */
 void oops_enter(void)
 {
+       tracing_off();
        /* can't trust the integrity of the kernel anymore: */
        debug_locks_off();
        do_oops_enter_exit();
index 1a933a221ea4a299922f4db98d62de86c7e5ea0b..d7cbc579fc8016603f0d0644c339a470224ad0b9 100644 (file)
@@ -42,6 +42,7 @@ static int perf_overcommit __read_mostly = 1;
 static atomic_t nr_counters __read_mostly;
 static atomic_t nr_mmap_counters __read_mostly;
 static atomic_t nr_comm_counters __read_mostly;
+static atomic_t nr_task_counters __read_mostly;
 
 /*
  * perf counter paranoia level:
@@ -49,7 +50,7 @@ static atomic_t nr_comm_counters __read_mostly;
  *  1 - disallow cpu counters to unpriv
  *  2 - disallow kernel profiling to unpriv
  */
-int sysctl_perf_counter_paranoid __read_mostly;
+int sysctl_perf_counter_paranoid __read_mostly = 1;
 
 static inline bool perf_paranoid_cpu(void)
 {
@@ -87,6 +88,7 @@ void __weak hw_perf_disable(void)             { barrier(); }
 void __weak hw_perf_enable(void)               { barrier(); }
 
 void __weak hw_perf_counter_setup(int cpu)     { barrier(); }
+void __weak hw_perf_counter_setup_online(int cpu)      { barrier(); }
 
 int __weak
 hw_perf_group_sched_in(struct perf_counter *group_leader,
@@ -146,6 +148,28 @@ static void put_ctx(struct perf_counter_context *ctx)
        }
 }
 
+static void unclone_ctx(struct perf_counter_context *ctx)
+{
+       if (ctx->parent_ctx) {
+               put_ctx(ctx->parent_ctx);
+               ctx->parent_ctx = NULL;
+       }
+}
+
+/*
+ * If we inherit counters we want to return the parent counter id
+ * to userspace.
+ */
+static u64 primary_counter_id(struct perf_counter *counter)
+{
+       u64 id = counter->id;
+
+       if (counter->parent)
+               id = counter->parent->id;
+
+       return id;
+}
+
 /*
  * Get the perf_counter_context for a task and lock it.
  * This has to cope with with the fact that until it is locked,
@@ -236,6 +260,8 @@ list_add_counter(struct perf_counter *counter, struct perf_counter_context *ctx)
 
        list_add_rcu(&counter->event_entry, &ctx->event_list);
        ctx->nr_counters++;
+       if (counter->attr.inherit_stat)
+               ctx->nr_stat++;
 }
 
 /*
@@ -250,6 +276,8 @@ list_del_counter(struct perf_counter *counter, struct perf_counter_context *ctx)
        if (list_empty(&counter->list_entry))
                return;
        ctx->nr_counters--;
+       if (counter->attr.inherit_stat)
+               ctx->nr_stat--;
 
        list_del_init(&counter->list_entry);
        list_del_rcu(&counter->event_entry);
@@ -279,6 +307,10 @@ counter_sched_out(struct perf_counter *counter,
                return;
 
        counter->state = PERF_COUNTER_STATE_INACTIVE;
+       if (counter->pending_disable) {
+               counter->pending_disable = 0;
+               counter->state = PERF_COUNTER_STATE_OFF;
+       }
        counter->tstamp_stopped = ctx->time;
        counter->pmu->disable(counter);
        counter->oncpu = -1;
@@ -1006,6 +1038,81 @@ static int context_equiv(struct perf_counter_context *ctx1,
                && !ctx1->pin_count && !ctx2->pin_count;
 }
 
+static void __perf_counter_read(void *counter);
+
+static void __perf_counter_sync_stat(struct perf_counter *counter,
+                                    struct perf_counter *next_counter)
+{
+       u64 value;
+
+       if (!counter->attr.inherit_stat)
+               return;
+
+       /*
+        * Update the counter value, we cannot use perf_counter_read()
+        * because we're in the middle of a context switch and have IRQs
+        * disabled, which upsets smp_call_function_single(), however
+        * we know the counter must be on the current CPU, therefore we
+        * don't need to use it.
+        */
+       switch (counter->state) {
+       case PERF_COUNTER_STATE_ACTIVE:
+               __perf_counter_read(counter);
+               break;
+
+       case PERF_COUNTER_STATE_INACTIVE:
+               update_counter_times(counter);
+               break;
+
+       default:
+               break;
+       }
+
+       /*
+        * In order to keep per-task stats reliable we need to flip the counter
+        * values when we flip the contexts.
+        */
+       value = atomic64_read(&next_counter->count);
+       value = atomic64_xchg(&counter->count, value);
+       atomic64_set(&next_counter->count, value);
+
+       swap(counter->total_time_enabled, next_counter->total_time_enabled);
+       swap(counter->total_time_running, next_counter->total_time_running);
+
+       /*
+        * Since we swizzled the values, update the user visible data too.
+        */
+       perf_counter_update_userpage(counter);
+       perf_counter_update_userpage(next_counter);
+}
+
+#define list_next_entry(pos, member) \
+       list_entry(pos->member.next, typeof(*pos), member)
+
+static void perf_counter_sync_stat(struct perf_counter_context *ctx,
+                                  struct perf_counter_context *next_ctx)
+{
+       struct perf_counter *counter, *next_counter;
+
+       if (!ctx->nr_stat)
+               return;
+
+       counter = list_first_entry(&ctx->event_list,
+                                  struct perf_counter, event_entry);
+
+       next_counter = list_first_entry(&next_ctx->event_list,
+                                       struct perf_counter, event_entry);
+
+       while (&counter->event_entry != &ctx->event_list &&
+              &next_counter->event_entry != &next_ctx->event_list) {
+
+               __perf_counter_sync_stat(counter, next_counter);
+
+               counter = list_next_entry(counter, event_entry);
+               next_counter = list_next_entry(next_counter, event_entry);
+       }
+}
+
 /*
  * Called from scheduler to remove the counters of the current task,
  * with interrupts disabled.
@@ -1061,6 +1168,8 @@ void perf_counter_task_sched_out(struct task_struct *task,
                        ctx->task = next;
                        next_ctx->task = task;
                        do_switch = 0;
+
+                       perf_counter_sync_stat(ctx, next_ctx);
                }
                spin_unlock(&next_ctx->lock);
                spin_unlock(&ctx->lock);
@@ -1207,7 +1316,6 @@ static void perf_counter_cpu_sched_in(struct perf_cpu_context *cpuctx, int cpu)
 #define MAX_INTERRUPTS (~0ULL)
 
 static void perf_log_throttle(struct perf_counter *counter, int enable);
-static void perf_log_period(struct perf_counter *counter, u64 period);
 
 static void perf_adjust_period(struct perf_counter *counter, u64 events)
 {
@@ -1226,8 +1334,6 @@ static void perf_adjust_period(struct perf_counter *counter, u64 events)
        if (!sample_period)
                sample_period = 1;
 
-       perf_log_period(counter, sample_period);
-
        hwc->sample_period = sample_period;
 }
 
@@ -1347,15 +1453,71 @@ void perf_counter_task_tick(struct task_struct *curr, int cpu)
                perf_counter_task_sched_in(curr, cpu);
 }
 
+/*
+ * Enable all of a task's counters that have been marked enable-on-exec.
+ * This expects task == current.
+ */
+static void perf_counter_enable_on_exec(struct task_struct *task)
+{
+       struct perf_counter_context *ctx;
+       struct perf_counter *counter;
+       unsigned long flags;
+       int enabled = 0;
+
+       local_irq_save(flags);
+       ctx = task->perf_counter_ctxp;
+       if (!ctx || !ctx->nr_counters)
+               goto out;
+
+       __perf_counter_task_sched_out(ctx);
+
+       spin_lock(&ctx->lock);
+
+       list_for_each_entry(counter, &ctx->counter_list, list_entry) {
+               if (!counter->attr.enable_on_exec)
+                       continue;
+               counter->attr.enable_on_exec = 0;
+               if (counter->state >= PERF_COUNTER_STATE_INACTIVE)
+                       continue;
+               counter->state = PERF_COUNTER_STATE_INACTIVE;
+               counter->tstamp_enabled =
+                       ctx->time - counter->total_time_enabled;
+               enabled = 1;
+       }
+
+       /*
+        * Unclone this context if we enabled any counter.
+        */
+       if (enabled)
+               unclone_ctx(ctx);
+
+       spin_unlock(&ctx->lock);
+
+       perf_counter_task_sched_in(task, smp_processor_id());
+ out:
+       local_irq_restore(flags);
+}
+
 /*
  * Cross CPU call to read the hardware counter
  */
-static void __read(void *info)
+static void __perf_counter_read(void *info)
 {
+       struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
        struct perf_counter *counter = info;
        struct perf_counter_context *ctx = counter->ctx;
        unsigned long flags;
 
+       /*
+        * If this is a task context, we need to check whether it is
+        * the current task context of this cpu.  If not it has been
+        * scheduled out before the smp call arrived.  In that case
+        * counter->count would have been updated to a recent sample
+        * when the counter was scheduled out.
+        */
+       if (ctx->task && cpuctx->task_ctx != ctx)
+               return;
+
        local_irq_save(flags);
        if (ctx->is_active)
                update_context_time(ctx);
@@ -1372,7 +1534,7 @@ static u64 perf_counter_read(struct perf_counter *counter)
         */
        if (counter->state == PERF_COUNTER_STATE_ACTIVE) {
                smp_call_function_single(counter->oncpu,
-                                        __read, counter, 1);
+                                        __perf_counter_read, counter, 1);
        } else if (counter->state == PERF_COUNTER_STATE_INACTIVE) {
                update_counter_times(counter);
        }
@@ -1398,7 +1560,6 @@ __perf_counter_init_context(struct perf_counter_context *ctx,
 
 static struct perf_counter_context *find_get_context(pid_t pid, int cpu)
 {
-       struct perf_counter_context *parent_ctx;
        struct perf_counter_context *ctx;
        struct perf_cpu_context *cpuctx;
        struct task_struct *task;
@@ -1458,11 +1619,7 @@ static struct perf_counter_context *find_get_context(pid_t pid, int cpu)
  retry:
        ctx = perf_lock_task_context(task, &flags);
        if (ctx) {
-               parent_ctx = ctx->parent_ctx;
-               if (parent_ctx) {
-                       put_ctx(parent_ctx);
-                       ctx->parent_ctx = NULL;         /* no longer a clone */
-               }
+               unclone_ctx(ctx);
                spin_unlock_irqrestore(&ctx->lock, flags);
        }
 
@@ -1508,11 +1665,15 @@ static void free_counter(struct perf_counter *counter)
 {
        perf_pending_sync(counter);
 
-       atomic_dec(&nr_counters);
-       if (counter->attr.mmap)
-               atomic_dec(&nr_mmap_counters);
-       if (counter->attr.comm)
-               atomic_dec(&nr_comm_counters);
+       if (!counter->parent) {
+               atomic_dec(&nr_counters);
+               if (counter->attr.mmap)
+                       atomic_dec(&nr_mmap_counters);
+               if (counter->attr.comm)
+                       atomic_dec(&nr_comm_counters);
+               if (counter->attr.task)
+                       atomic_dec(&nr_task_counters);
+       }
 
        if (counter->destroy)
                counter->destroy(counter);
@@ -1546,14 +1707,133 @@ static int perf_release(struct inode *inode, struct file *file)
        return 0;
 }
 
+static int perf_counter_read_size(struct perf_counter *counter)
+{
+       int entry = sizeof(u64); /* value */
+       int size = 0;
+       int nr = 1;
+
+       if (counter->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
+               size += sizeof(u64);
+
+       if (counter->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
+               size += sizeof(u64);
+
+       if (counter->attr.read_format & PERF_FORMAT_ID)
+               entry += sizeof(u64);
+
+       if (counter->attr.read_format & PERF_FORMAT_GROUP) {
+               nr += counter->group_leader->nr_siblings;
+               size += sizeof(u64);
+       }
+
+       size += entry * nr;
+
+       return size;
+}
+
+static u64 perf_counter_read_value(struct perf_counter *counter)
+{
+       struct perf_counter *child;
+       u64 total = 0;
+
+       total += perf_counter_read(counter);
+       list_for_each_entry(child, &counter->child_list, child_list)
+               total += perf_counter_read(child);
+
+       return total;
+}
+
+static int perf_counter_read_entry(struct perf_counter *counter,
+                                  u64 read_format, char __user *buf)
+{
+       int n = 0, count = 0;
+       u64 values[2];
+
+       values[n++] = perf_counter_read_value(counter);
+       if (read_format & PERF_FORMAT_ID)
+               values[n++] = primary_counter_id(counter);
+
+       count = n * sizeof(u64);
+
+       if (copy_to_user(buf, values, count))
+               return -EFAULT;
+
+       return count;
+}
+
+static int perf_counter_read_group(struct perf_counter *counter,
+                                  u64 read_format, char __user *buf)
+{
+       struct perf_counter *leader = counter->group_leader, *sub;
+       int n = 0, size = 0, err = -EFAULT;
+       u64 values[3];
+
+       values[n++] = 1 + leader->nr_siblings;
+       if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
+               values[n++] = leader->total_time_enabled +
+                       atomic64_read(&leader->child_total_time_enabled);
+       }
+       if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
+               values[n++] = leader->total_time_running +
+                       atomic64_read(&leader->child_total_time_running);
+       }
+
+       size = n * sizeof(u64);
+
+       if (copy_to_user(buf, values, size))
+               return -EFAULT;
+
+       err = perf_counter_read_entry(leader, read_format, buf + size);
+       if (err < 0)
+               return err;
+
+       size += err;
+
+       list_for_each_entry(sub, &leader->sibling_list, list_entry) {
+               err = perf_counter_read_entry(sub, read_format,
+                               buf + size);
+               if (err < 0)
+                       return err;
+
+               size += err;
+       }
+
+       return size;
+}
+
+static int perf_counter_read_one(struct perf_counter *counter,
+                                u64 read_format, char __user *buf)
+{
+       u64 values[4];
+       int n = 0;
+
+       values[n++] = perf_counter_read_value(counter);
+       if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
+               values[n++] = counter->total_time_enabled +
+                       atomic64_read(&counter->child_total_time_enabled);
+       }
+       if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
+               values[n++] = counter->total_time_running +
+                       atomic64_read(&counter->child_total_time_running);
+       }
+       if (read_format & PERF_FORMAT_ID)
+               values[n++] = primary_counter_id(counter);
+
+       if (copy_to_user(buf, values, n * sizeof(u64)))
+               return -EFAULT;
+
+       return n * sizeof(u64);
+}
+
 /*
  * Read the performance counter - simple non blocking version for now
  */
 static ssize_t
 perf_read_hw(struct perf_counter *counter, char __user *buf, size_t count)
 {
-       u64 values[4];
-       int n;
+       u64 read_format = counter->attr.read_format;
+       int ret;
 
        /*
         * Return end-of-file for a read on a counter that is in
@@ -1563,28 +1843,18 @@ perf_read_hw(struct perf_counter *counter, char __user *buf, size_t count)
        if (counter->state == PERF_COUNTER_STATE_ERROR)
                return 0;
 
+       if (count < perf_counter_read_size(counter))
+               return -ENOSPC;
+
        WARN_ON_ONCE(counter->ctx->parent_ctx);
        mutex_lock(&counter->child_mutex);
-       values[0] = perf_counter_read(counter);
-       n = 1;
-       if (counter->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
-               values[n++] = counter->total_time_enabled +
-                       atomic64_read(&counter->child_total_time_enabled);
-       if (counter->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
-               values[n++] = counter->total_time_running +
-                       atomic64_read(&counter->child_total_time_running);
-       if (counter->attr.read_format & PERF_FORMAT_ID)
-               values[n++] = counter->id;
+       if (read_format & PERF_FORMAT_GROUP)
+               ret = perf_counter_read_group(counter, read_format, buf);
+       else
+               ret = perf_counter_read_one(counter, read_format, buf);
        mutex_unlock(&counter->child_mutex);
 
-       if (count < n * sizeof(u64))
-               return -EINVAL;
-       count = n * sizeof(u64);
-
-       if (copy_to_user(buf, values, count))
-               return -EFAULT;
-
-       return count;
+       return ret;
 }
 
 static ssize_t
@@ -1681,8 +1951,6 @@ static int perf_counter_period(struct perf_counter *counter, u64 __user *arg)
 
                counter->attr.sample_freq = value;
        } else {
-               perf_log_period(counter, value);
-
                counter->attr.sample_period = value;
                counter->hw.sample_period = value;
        }
@@ -1751,6 +2019,18 @@ int perf_counter_task_disable(void)
        return 0;
 }
 
+#ifndef PERF_COUNTER_INDEX_OFFSET
+# define PERF_COUNTER_INDEX_OFFSET 0
+#endif
+
+static int perf_counter_index(struct perf_counter *counter)
+{
+       if (counter->state != PERF_COUNTER_STATE_ACTIVE)
+               return 0;
+
+       return counter->hw.idx + 1 - PERF_COUNTER_INDEX_OFFSET;
+}
+
 /*
  * Callers need to ensure there can be no nesting of this function, otherwise
  * the seqlock logic goes bad. We can not serialize this because the arch
@@ -1775,11 +2055,17 @@ void perf_counter_update_userpage(struct perf_counter *counter)
        preempt_disable();
        ++userpg->lock;
        barrier();
-       userpg->index = counter->hw.idx;
+       userpg->index = perf_counter_index(counter);
        userpg->offset = atomic64_read(&counter->count);
        if (counter->state == PERF_COUNTER_STATE_ACTIVE)
                userpg->offset -= atomic64_read(&counter->hw.prev_count);
 
+       userpg->time_enabled = counter->total_time_enabled +
+                       atomic64_read(&counter->child_total_time_enabled);
+
+       userpg->time_running = counter->total_time_running +
+                       atomic64_read(&counter->child_total_time_running);
+
        barrier();
        ++userpg->lock;
        preempt_enable();
@@ -1876,7 +2162,7 @@ fail:
 
 static void perf_mmap_free_page(unsigned long addr)
 {
-       struct page *page = virt_to_page(addr);
+       struct page *page = virt_to_page((void *)addr);
 
        page->mapping = NULL;
        __free_page(page);
@@ -2076,7 +2362,7 @@ static void perf_pending_counter(struct perf_pending_entry *entry)
 
        if (counter->pending_disable) {
                counter->pending_disable = 0;
-               perf_counter_disable(counter);
+               __perf_counter_disable(counter);
        }
 
        if (counter->pending_wakeup) {
@@ -2461,7 +2747,80 @@ static u32 perf_counter_tid(struct perf_counter *counter, struct task_struct *p)
        return task_pid_nr_ns(p, counter->ns);
 }
 
-static void perf_counter_output(struct perf_counter *counter, int nmi,
+static void perf_output_read_one(struct perf_output_handle *handle,
+                                struct perf_counter *counter)
+{
+       u64 read_format = counter->attr.read_format;
+       u64 values[4];
+       int n = 0;
+
+       values[n++] = atomic64_read(&counter->count);
+       if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
+               values[n++] = counter->total_time_enabled +
+                       atomic64_read(&counter->child_total_time_enabled);
+       }
+       if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
+               values[n++] = counter->total_time_running +
+                       atomic64_read(&counter->child_total_time_running);
+       }
+       if (read_format & PERF_FORMAT_ID)
+               values[n++] = primary_counter_id(counter);
+
+       perf_output_copy(handle, values, n * sizeof(u64));
+}
+
+/*
+ * XXX PERF_FORMAT_GROUP vs inherited counters seems difficult.
+ */
+static void perf_output_read_group(struct perf_output_handle *handle,
+                           struct perf_counter *counter)
+{
+       struct perf_counter *leader = counter->group_leader, *sub;
+       u64 read_format = counter->attr.read_format;
+       u64 values[5];
+       int n = 0;
+
+       values[n++] = 1 + leader->nr_siblings;
+
+       if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
+               values[n++] = leader->total_time_enabled;
+
+       if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
+               values[n++] = leader->total_time_running;
+
+       if (leader != counter)
+               leader->pmu->read(leader);
+
+       values[n++] = atomic64_read(&leader->count);
+       if (read_format & PERF_FORMAT_ID)
+               values[n++] = primary_counter_id(leader);
+
+       perf_output_copy(handle, values, n * sizeof(u64));
+
+       list_for_each_entry(sub, &leader->sibling_list, list_entry) {
+               n = 0;
+
+               if (sub != counter)
+                       sub->pmu->read(sub);
+
+               values[n++] = atomic64_read(&sub->count);
+               if (read_format & PERF_FORMAT_ID)
+                       values[n++] = primary_counter_id(sub);
+
+               perf_output_copy(handle, values, n * sizeof(u64));
+       }
+}
+
+static void perf_output_read(struct perf_output_handle *handle,
+                            struct perf_counter *counter)
+{
+       if (counter->attr.read_format & PERF_FORMAT_GROUP)
+               perf_output_read_group(handle, counter);
+       else
+               perf_output_read_one(handle, counter);
+}
+
+void perf_counter_output(struct perf_counter *counter, int nmi,
                                struct perf_sample_data *data)
 {
        int ret;
@@ -2472,10 +2831,6 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
        struct {
                u32 pid, tid;
        } tid_entry;
-       struct {
-               u64 id;
-               u64 counter;
-       } group_entry;
        struct perf_callchain_entry *callchain = NULL;
        int callchain_size = 0;
        u64 time;
@@ -2483,15 +2838,14 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
                u32 cpu, reserved;
        } cpu_entry;
 
-       header.type = 0;
+       header.type = PERF_EVENT_SAMPLE;
        header.size = sizeof(header);
 
-       header.misc = PERF_EVENT_MISC_OVERFLOW;
+       header.misc = 0;
        header.misc |= perf_misc_flags(data->regs);
 
        if (sample_type & PERF_SAMPLE_IP) {
                ip = perf_instruction_pointer(data->regs);
-               header.type |= PERF_SAMPLE_IP;
                header.size += sizeof(ip);
        }
 
@@ -2500,7 +2854,6 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
                tid_entry.pid = perf_counter_pid(counter, current);
                tid_entry.tid = perf_counter_tid(counter, current);
 
-               header.type |= PERF_SAMPLE_TID;
                header.size += sizeof(tid_entry);
        }
 
@@ -2510,47 +2863,51 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
                 */
                time = sched_clock();
 
-               header.type |= PERF_SAMPLE_TIME;
                header.size += sizeof(u64);
        }
 
-       if (sample_type & PERF_SAMPLE_ADDR) {
-               header.type |= PERF_SAMPLE_ADDR;
+       if (sample_type & PERF_SAMPLE_ADDR)
                header.size += sizeof(u64);
-       }
 
-       if (sample_type & PERF_SAMPLE_ID) {
-               header.type |= PERF_SAMPLE_ID;
+       if (sample_type & PERF_SAMPLE_ID)
+               header.size += sizeof(u64);
+
+       if (sample_type & PERF_SAMPLE_STREAM_ID)
                header.size += sizeof(u64);
-       }
 
        if (sample_type & PERF_SAMPLE_CPU) {
-               header.type |= PERF_SAMPLE_CPU;
                header.size += sizeof(cpu_entry);
 
                cpu_entry.cpu = raw_smp_processor_id();
+               cpu_entry.reserved = 0;
        }
 
-       if (sample_type & PERF_SAMPLE_PERIOD) {
-               header.type |= PERF_SAMPLE_PERIOD;
+       if (sample_type & PERF_SAMPLE_PERIOD)
                header.size += sizeof(u64);
-       }
 
-       if (sample_type & PERF_SAMPLE_GROUP) {
-               header.type |= PERF_SAMPLE_GROUP;
-               header.size += sizeof(u64) +
-                       counter->nr_siblings * sizeof(group_entry);
-       }
+       if (sample_type & PERF_SAMPLE_READ)
+               header.size += perf_counter_read_size(counter);
 
        if (sample_type & PERF_SAMPLE_CALLCHAIN) {
                callchain = perf_callchain(data->regs);
 
                if (callchain) {
                        callchain_size = (1 + callchain->nr) * sizeof(u64);
-
-                       header.type |= PERF_SAMPLE_CALLCHAIN;
                        header.size += callchain_size;
-               }
+               } else
+                       header.size += sizeof(u64);
+       }
+
+       if (sample_type & PERF_SAMPLE_RAW) {
+               int size = sizeof(u32);
+
+               if (data->raw)
+                       size += data->raw->size;
+               else
+                       size += sizeof(u32);
+
+               WARN_ON_ONCE(size & (sizeof(u64)-1));
+               header.size += size;
        }
 
        ret = perf_output_begin(&handle, counter, header.size, nmi, 1);
@@ -2571,7 +2928,13 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
        if (sample_type & PERF_SAMPLE_ADDR)
                perf_output_put(&handle, data->addr);
 
-       if (sample_type & PERF_SAMPLE_ID)
+       if (sample_type & PERF_SAMPLE_ID) {
+               u64 id = primary_counter_id(counter);
+
+               perf_output_put(&handle, id);
+       }
+
+       if (sample_type & PERF_SAMPLE_STREAM_ID)
                perf_output_put(&handle, counter->id);
 
        if (sample_type & PERF_SAMPLE_CPU)
@@ -2580,76 +2943,125 @@ static void perf_counter_output(struct perf_counter *counter, int nmi,
        if (sample_type & PERF_SAMPLE_PERIOD)
                perf_output_put(&handle, data->period);
 
-       /*
-        * XXX PERF_SAMPLE_GROUP vs inherited counters seems difficult.
-        */
-       if (sample_type & PERF_SAMPLE_GROUP) {
-               struct perf_counter *leader, *sub;
-               u64 nr = counter->nr_siblings;
-
-               perf_output_put(&handle, nr);
+       if (sample_type & PERF_SAMPLE_READ)
+               perf_output_read(&handle, counter);
 
-               leader = counter->group_leader;
-               list_for_each_entry(sub, &leader->sibling_list, list_entry) {
-                       if (sub != counter)
-                               sub->pmu->read(sub);
-
-                       group_entry.id = sub->id;
-                       group_entry.counter = atomic64_read(&sub->count);
+       if (sample_type & PERF_SAMPLE_CALLCHAIN) {
+               if (callchain)
+                       perf_output_copy(&handle, callchain, callchain_size);
+               else {
+                       u64 nr = 0;
+                       perf_output_put(&handle, nr);
+               }
+       }
 
-                       perf_output_put(&handle, group_entry);
+       if (sample_type & PERF_SAMPLE_RAW) {
+               if (data->raw) {
+                       perf_output_put(&handle, data->raw->size);
+                       perf_output_copy(&handle, data->raw->data, data->raw->size);
+               } else {
+                       struct {
+                               u32     size;
+                               u32     data;
+                       } raw = {
+                               .size = sizeof(u32),
+                               .data = 0,
+                       };
+                       perf_output_put(&handle, raw);
                }
        }
 
-       if (callchain)
-               perf_output_copy(&handle, callchain, callchain_size);
+       perf_output_end(&handle);
+}
+
+/*
+ * read event
+ */
+
+struct perf_read_event {
+       struct perf_event_header        header;
+
+       u32                             pid;
+       u32                             tid;
+};
+
+static void
+perf_counter_read_event(struct perf_counter *counter,
+                       struct task_struct *task)
+{
+       struct perf_output_handle handle;
+       struct perf_read_event event = {
+               .header = {
+                       .type = PERF_EVENT_READ,
+                       .misc = 0,
+                       .size = sizeof(event) + perf_counter_read_size(counter),
+               },
+               .pid = perf_counter_pid(counter, task),
+               .tid = perf_counter_tid(counter, task),
+       };
+       int ret;
+
+       ret = perf_output_begin(&handle, counter, event.header.size, 0, 0);
+       if (ret)
+               return;
+
+       perf_output_put(&handle, event);
+       perf_output_read(&handle, counter);
 
        perf_output_end(&handle);
 }
 
 /*
- * fork tracking
+ * task tracking -- fork/exit
+ *
+ * enabled by: attr.comm | attr.mmap | attr.task
  */
 
-struct perf_fork_event {
-       struct task_struct      *task;
+struct perf_task_event {
+       struct task_struct              *task;
+       struct perf_counter_context     *task_ctx;
 
        struct {
                struct perf_event_header        header;
 
                u32                             pid;
                u32                             ppid;
+               u32                             tid;
+               u32                             ptid;
        } event;
 };
 
-static void perf_counter_fork_output(struct perf_counter *counter,
-                                    struct perf_fork_event *fork_event)
+static void perf_counter_task_output(struct perf_counter *counter,
+                                    struct perf_task_event *task_event)
 {
        struct perf_output_handle handle;
-       int size = fork_event->event.header.size;
-       struct task_struct *task = fork_event->task;
+       int size = task_event->event.header.size;
+       struct task_struct *task = task_event->task;
        int ret = perf_output_begin(&handle, counter, size, 0, 0);
 
        if (ret)
                return;
 
-       fork_event->event.pid = perf_counter_pid(counter, task);
-       fork_event->event.ppid = perf_counter_pid(counter, task->real_parent);
+       task_event->event.pid = perf_counter_pid(counter, task);
+       task_event->event.ppid = perf_counter_pid(counter, current);
+
+       task_event->event.tid = perf_counter_tid(counter, task);
+       task_event->event.ptid = perf_counter_tid(counter, current);
 
-       perf_output_put(&handle, fork_event->event);
+       perf_output_put(&handle, task_event->event);
        perf_output_end(&handle);
 }
 
-static int perf_counter_fork_match(struct perf_counter *counter)
+static int perf_counter_task_match(struct perf_counter *counter)
 {
-       if (counter->attr.comm || counter->attr.mmap)
+       if (counter->attr.comm || counter->attr.mmap || counter->attr.task)
                return 1;
 
        return 0;
 }
 
-static void perf_counter_fork_ctx(struct perf_counter_context *ctx,
-                                 struct perf_fork_event *fork_event)
+static void perf_counter_task_ctx(struct perf_counter_context *ctx,
+                                 struct perf_task_event *task_event)
 {
        struct perf_counter *counter;
 
@@ -2658,51 +3070,62 @@ static void perf_counter_fork_ctx(struct perf_counter_context *ctx,
 
        rcu_read_lock();
        list_for_each_entry_rcu(counter, &ctx->event_list, event_entry) {
-               if (perf_counter_fork_match(counter))
-                       perf_counter_fork_output(counter, fork_event);
+               if (perf_counter_task_match(counter))
+                       perf_counter_task_output(counter, task_event);
        }
        rcu_read_unlock();
 }
 
-static void perf_counter_fork_event(struct perf_fork_event *fork_event)
+static void perf_counter_task_event(struct perf_task_event *task_event)
 {
        struct perf_cpu_context *cpuctx;
-       struct perf_counter_context *ctx;
+       struct perf_counter_context *ctx = task_event->task_ctx;
 
        cpuctx = &get_cpu_var(perf_cpu_context);
-       perf_counter_fork_ctx(&cpuctx->ctx, fork_event);
+       perf_counter_task_ctx(&cpuctx->ctx, task_event);
        put_cpu_var(perf_cpu_context);
 
        rcu_read_lock();
-       /*
-        * doesn't really matter which of the child contexts the
-        * events ends up in.
-        */
-       ctx = rcu_dereference(current->perf_counter_ctxp);
+       if (!ctx)
+               ctx = rcu_dereference(task_event->task->perf_counter_ctxp);
        if (ctx)
-               perf_counter_fork_ctx(ctx, fork_event);
+               perf_counter_task_ctx(ctx, task_event);
        rcu_read_unlock();
 }
 
-void perf_counter_fork(struct task_struct *task)
+static void perf_counter_task(struct task_struct *task,
+                             struct perf_counter_context *task_ctx,
+                             int new)
 {
-       struct perf_fork_event fork_event;
+       struct perf_task_event task_event;
 
        if (!atomic_read(&nr_comm_counters) &&
-           !atomic_read(&nr_mmap_counters))
+           !atomic_read(&nr_mmap_counters) &&
+           !atomic_read(&nr_task_counters))
                return;
 
-       fork_event = (struct perf_fork_event){
-               .task   = task,
-               .event  = {
+       task_event = (struct perf_task_event){
+               .task     = task,
+               .task_ctx = task_ctx,
+               .event    = {
                        .header = {
-                               .type = PERF_EVENT_FORK,
-                               .size = sizeof(fork_event.event),
+                               .type = new ? PERF_EVENT_FORK : PERF_EVENT_EXIT,
+                               .misc = 0,
+                               .size = sizeof(task_event.event),
                        },
+                       /* .pid  */
+                       /* .ppid */
+                       /* .tid  */
+                       /* .ptid */
                },
        };
 
-       perf_counter_fork_event(&fork_event);
+       perf_counter_task_event(&task_event);
+}
+
+void perf_counter_fork(struct task_struct *task)
+{
+       perf_counter_task(task, NULL, 1);
 }
 
 /*
@@ -2770,8 +3193,10 @@ static void perf_counter_comm_event(struct perf_comm_event *comm_event)
        struct perf_cpu_context *cpuctx;
        struct perf_counter_context *ctx;
        unsigned int size;
-       char *comm = comm_event->task->comm;
+       char comm[TASK_COMM_LEN];
 
+       memset(comm, 0, sizeof(comm));
+       strncpy(comm, comm_event->task->comm, sizeof(comm));
        size = ALIGN(strlen(comm)+1, sizeof(u64));
 
        comm_event->comm = comm;
@@ -2798,13 +3223,24 @@ void perf_counter_comm(struct task_struct *task)
 {
        struct perf_comm_event comm_event;
 
+       if (task->perf_counter_ctxp)
+               perf_counter_enable_on_exec(task);
+
        if (!atomic_read(&nr_comm_counters))
                return;
 
        comm_event = (struct perf_comm_event){
                .task   = task,
+               /* .comm      */
+               /* .comm_size */
                .event  = {
-                       .header = { .type = PERF_EVENT_COMM, },
+                       .header = {
+                               .type = PERF_EVENT_COMM,
+                               .misc = 0,
+                               /* .size */
+                       },
+                       /* .pid */
+                       /* .tid */
                },
        };
 
@@ -2887,8 +3323,15 @@ static void perf_counter_mmap_event(struct perf_mmap_event *mmap_event)
        char *buf = NULL;
        const char *name;
 
+       memset(tmp, 0, sizeof(tmp));
+
        if (file) {
-               buf = kzalloc(PATH_MAX, GFP_KERNEL);
+               /*
+                * d_path works from the end of the buffer backwards, so we
+                * need to add enough zero bytes after the string to handle
+                * the 64bit alignment we do later.
+                */
+               buf = kzalloc(PATH_MAX + sizeof(u64), GFP_KERNEL);
                if (!buf) {
                        name = strncpy(tmp, "//enomem", sizeof(tmp));
                        goto got_name;
@@ -2899,9 +3342,11 @@ static void perf_counter_mmap_event(struct perf_mmap_event *mmap_event)
                        goto got_name;
                }
        } else {
-               name = arch_vma_name(mmap_event->vma);
-               if (name)
+               if (arch_vma_name(mmap_event->vma)) {
+                       name = strncpy(tmp, arch_vma_name(mmap_event->vma),
+                                      sizeof(tmp));
                        goto got_name;
+               }
 
                if (!vma->vm_mm) {
                        name = strncpy(tmp, "[vdso]", sizeof(tmp));
@@ -2946,8 +3391,16 @@ void __perf_counter_mmap(struct vm_area_struct *vma)
 
        mmap_event = (struct perf_mmap_event){
                .vma    = vma,
+               /* .file_name */
+               /* .file_size */
                .event  = {
-                       .header = { .type = PERF_EVENT_MMAP, },
+                       .header = {
+                               .type = PERF_EVENT_MMAP,
+                               .misc = 0,
+                               /* .size */
+                       },
+                       /* .pid */
+                       /* .tid */
                        .start  = vma->vm_start,
                        .len    = vma->vm_end - vma->vm_start,
                        .pgoff  = vma->vm_pgoff,
@@ -2957,49 +3410,6 @@ void __perf_counter_mmap(struct vm_area_struct *vma)
        perf_counter_mmap_event(&mmap_event);
 }
 
-/*
- * Log sample_period changes so that analyzing tools can re-normalize the
- * event flow.
- */
-
-struct freq_event {
-       struct perf_event_header        header;
-       u64                             time;
-       u64                             id;
-       u64                             period;
-};
-
-static void perf_log_period(struct perf_counter *counter, u64 period)
-{
-       struct perf_output_handle handle;
-       struct freq_event event;
-       int ret;
-
-       if (counter->hw.sample_period == period)
-               return;
-
-       if (counter->attr.sample_type & PERF_SAMPLE_PERIOD)
-               return;
-
-       event = (struct freq_event) {
-               .header = {
-                       .type = PERF_EVENT_PERIOD,
-                       .misc = 0,
-                       .size = sizeof(event),
-               },
-               .time = sched_clock(),
-               .id = counter->id,
-               .period = period,
-       };
-
-       ret = perf_output_begin(&handle, counter, sizeof(event), 1, 0);
-       if (ret)
-               return;
-
-       perf_output_put(&handle, event);
-       perf_output_end(&handle);
-}
-
 /*
  * IRQ throttle logging
  */
@@ -3013,16 +3423,21 @@ static void perf_log_throttle(struct perf_counter *counter, int enable)
                struct perf_event_header        header;
                u64                             time;
                u64                             id;
+               u64                             stream_id;
        } throttle_event = {
                .header = {
-                       .type = PERF_EVENT_THROTTLE + 1,
+                       .type = PERF_EVENT_THROTTLE,
                        .misc = 0,
                        .size = sizeof(throttle_event),
                },
-               .time   = sched_clock(),
-               .id     = counter->id,
+               .time           = sched_clock(),
+               .id             = primary_counter_id(counter),
+               .stream_id      = counter->id,
        };
 
+       if (enable)
+               throttle_event.header.type = PERF_EVENT_UNTHROTTLE;
+
        ret = perf_output_begin(&handle, counter, sizeof(throttle_event), 1, 0);
        if (ret)
                return;
@@ -3099,125 +3514,111 @@ int perf_counter_overflow(struct perf_counter *counter, int nmi,
  * Generic software counter infrastructure
  */
 
-static void perf_swcounter_update(struct perf_counter *counter)
+/*
+ * We directly increment counter->count and keep a second value in
+ * counter->hw.period_left to count intervals. This period counter
+ * is kept in the range [-sample_period, 0] so that we can use the
+ * sign as trigger.
+ */
+
+static u64 perf_swcounter_set_period(struct perf_counter *counter)
 {
        struct hw_perf_counter *hwc = &counter->hw;
-       u64 prev, now;
-       s64 delta;
+       u64 period = hwc->last_period;
+       u64 nr, offset;
+       s64 old, val;
+
+       hwc->last_period = hwc->sample_period;
 
 again:
-       prev = atomic64_read(&hwc->prev_count);
-       now = atomic64_read(&hwc->count);
-       if (atomic64_cmpxchg(&hwc->prev_count, prev, now) != prev)
-               goto again;
+       old = val = atomic64_read(&hwc->period_left);
+       if (val < 0)
+               return 0;
 
-       delta = now - prev;
+       nr = div64_u64(period + val, period);
+       offset = nr * period;
+       val -= offset;
+       if (atomic64_cmpxchg(&hwc->period_left, old, val) != old)
+               goto again;
 
-       atomic64_add(delta, &counter->count);
-       atomic64_sub(delta, &hwc->period_left);
+       return nr;
 }
 
-static void perf_swcounter_set_period(struct perf_counter *counter)
+static void perf_swcounter_overflow(struct perf_counter *counter,
+                                   int nmi, struct perf_sample_data *data)
 {
        struct hw_perf_counter *hwc = &counter->hw;
-       s64 left = atomic64_read(&hwc->period_left);
-       s64 period = hwc->sample_period;
+       u64 overflow;
 
-       if (unlikely(left <= -period)) {
-               left = period;
-               atomic64_set(&hwc->period_left, left);
-               hwc->last_period = period;
-       }
+       data->period = counter->hw.last_period;
+       overflow = perf_swcounter_set_period(counter);
 
-       if (unlikely(left <= 0)) {
-               left += period;
-               atomic64_add(period, &hwc->period_left);
-               hwc->last_period = period;
-       }
+       if (hwc->interrupts == MAX_INTERRUPTS)
+               return;
 
-       atomic64_set(&hwc->prev_count, -left);
-       atomic64_set(&hwc->count, -left);
+       for (; overflow; overflow--) {
+               if (perf_counter_overflow(counter, nmi, data)) {
+                       /*
+                        * We inhibit the overflow from happening when
+                        * hwc->interrupts == MAX_INTERRUPTS.
+                        */
+                       break;
+               }
+       }
 }
 
-static enum hrtimer_restart perf_swcounter_hrtimer(struct hrtimer *hrtimer)
+static void perf_swcounter_unthrottle(struct perf_counter *counter)
 {
-       enum hrtimer_restart ret = HRTIMER_RESTART;
-       struct perf_sample_data data;
-       struct perf_counter *counter;
-       u64 period;
-
-       counter = container_of(hrtimer, struct perf_counter, hw.hrtimer);
-       counter->pmu->read(counter);
-
-       data.addr = 0;
-       data.regs = get_irq_regs();
        /*
-        * In case we exclude kernel IPs or are somehow not in interrupt
-        * context, provide the next best thing, the user IP.
+        * Nothing to do, we already reset hwc->interrupts.
         */
-       if ((counter->attr.exclude_kernel || !data.regs) &&
-                       !counter->attr.exclude_user)
-               data.regs = task_pt_regs(current);
+}
 
-       if (data.regs) {
-               if (perf_counter_overflow(counter, 0, &data))
-                       ret = HRTIMER_NORESTART;
-       }
+static void perf_swcounter_add(struct perf_counter *counter, u64 nr,
+                              int nmi, struct perf_sample_data *data)
+{
+       struct hw_perf_counter *hwc = &counter->hw;
 
-       period = max_t(u64, 10000, counter->hw.sample_period);
-       hrtimer_forward_now(hrtimer, ns_to_ktime(period));
+       atomic64_add(nr, &counter->count);
 
-       return ret;
-}
+       if (!hwc->sample_period)
+               return;
 
-static void perf_swcounter_overflow(struct perf_counter *counter,
-                                   int nmi, struct perf_sample_data *data)
-{
-       data->period = counter->hw.last_period;
+       if (!data->regs)
+               return;
 
-       perf_swcounter_update(counter);
-       perf_swcounter_set_period(counter);
-       if (perf_counter_overflow(counter, nmi, data))
-               /* soft-disable the counter */
-               ;
+       if (!atomic64_add_negative(nr, &hwc->period_left))
+               perf_swcounter_overflow(counter, nmi, data);
 }
 
 static int perf_swcounter_is_counting(struct perf_counter *counter)
 {
-       struct perf_counter_context *ctx;
-       unsigned long flags;
-       int count;
-
+       /*
+        * The counter is active, we're good!
+        */
        if (counter->state == PERF_COUNTER_STATE_ACTIVE)
                return 1;
 
+       /*
+        * The counter is off/error, not counting.
+        */
        if (counter->state != PERF_COUNTER_STATE_INACTIVE)
                return 0;
 
        /*
-        * If the counter is inactive, it could be just because
-        * its task is scheduled out, or because it's in a group
-        * which could not go on the PMU.  We want to count in
-        * the first case but not the second.  If the context is
-        * currently active then an inactive software counter must
-        * be the second case.  If it's not currently active then
-        * we need to know whether the counter was active when the
-        * context was last active, which we can determine by
-        * comparing counter->tstamp_stopped with ctx->time.
-        *
-        * We are within an RCU read-side critical section,
-        * which protects the existence of *ctx.
+        * The counter is inactive, if the context is active
+        * we're part of a group that didn't make it on the 'pmu',
+        * not counting.
         */
-       ctx = counter->ctx;
-       spin_lock_irqsave(&ctx->lock, flags);
-       count = 1;
-       /* Re-check state now we have the lock */
-       if (counter->state < PERF_COUNTER_STATE_INACTIVE ||
-           counter->ctx->is_active ||
-           counter->tstamp_stopped < ctx->time)
-               count = 0;
-       spin_unlock_irqrestore(&ctx->lock, flags);
-       return count;
+       if (counter->ctx->is_active)
+               return 0;
+
+       /*
+        * We're inactive and the context is too, this means the
+        * task is scheduled out, we're counting events that happen
+        * to us, like migration events.
+        */
+       return 1;
 }
 
 static int perf_swcounter_match(struct perf_counter *counter,
@@ -3243,15 +3644,6 @@ static int perf_swcounter_match(struct perf_counter *counter,
        return 1;
 }
 
-static void perf_swcounter_add(struct perf_counter *counter, u64 nr,
-                              int nmi, struct perf_sample_data *data)
-{
-       int neg = atomic64_add_negative(nr, &counter->hw.count);
-
-       if (counter->hw.sample_period && !neg && data->regs)
-               perf_swcounter_overflow(counter, nmi, data);
-}
-
 static void perf_swcounter_ctx_event(struct perf_counter_context *ctx,
                                     enum perf_type_id type,
                                     u32 event, u64 nr, int nmi,
@@ -3317,8 +3709,8 @@ out:
        put_cpu_var(perf_cpu_context);
 }
 
-void
-perf_swcounter_event(u32 event, u64 nr, int nmi, struct pt_regs *regs, u64 addr)
+void __perf_swcounter_event(u32 event, u64 nr, int nmi,
+                           struct pt_regs *regs, u64 addr)
 {
        struct perf_sample_data data = {
                .regs = regs,
@@ -3330,26 +3722,65 @@ perf_swcounter_event(u32 event, u64 nr, int nmi, struct pt_regs *regs, u64 addr)
 
 static void perf_swcounter_read(struct perf_counter *counter)
 {
-       perf_swcounter_update(counter);
 }
 
 static int perf_swcounter_enable(struct perf_counter *counter)
 {
-       perf_swcounter_set_period(counter);
+       struct hw_perf_counter *hwc = &counter->hw;
+
+       if (hwc->sample_period) {
+               hwc->last_period = hwc->sample_period;
+               perf_swcounter_set_period(counter);
+       }
        return 0;
 }
 
 static void perf_swcounter_disable(struct perf_counter *counter)
 {
-       perf_swcounter_update(counter);
 }
 
 static const struct pmu perf_ops_generic = {
        .enable         = perf_swcounter_enable,
        .disable        = perf_swcounter_disable,
        .read           = perf_swcounter_read,
+       .unthrottle     = perf_swcounter_unthrottle,
 };
 
+/*
+ * hrtimer based swcounter callback
+ */
+
+static enum hrtimer_restart perf_swcounter_hrtimer(struct hrtimer *hrtimer)
+{
+       enum hrtimer_restart ret = HRTIMER_RESTART;
+       struct perf_sample_data data;
+       struct perf_counter *counter;
+       u64 period;
+
+       counter = container_of(hrtimer, struct perf_counter, hw.hrtimer);
+       counter->pmu->read(counter);
+
+       data.addr = 0;
+       data.regs = get_irq_regs();
+       /*
+        * In case we exclude kernel IPs or are somehow not in interrupt
+        * context, provide the next best thing, the user IP.
+        */
+       if ((counter->attr.exclude_kernel || !data.regs) &&
+                       !counter->attr.exclude_user)
+               data.regs = task_pt_regs(current);
+
+       if (data.regs) {
+               if (perf_counter_overflow(counter, 0, &data))
+                       ret = HRTIMER_NORESTART;
+       }
+
+       period = max_t(u64, 10000, counter->hw.sample_period);
+       hrtimer_forward_now(hrtimer, ns_to_ktime(period));
+
+       return ret;
+}
+
 /*
  * Software counter: cpu wall time clock
  */
@@ -3467,17 +3898,24 @@ static const struct pmu perf_ops_task_clock = {
 };
 
 #ifdef CONFIG_EVENT_PROFILE
-void perf_tpcounter_event(int event_id)
+void perf_tpcounter_event(int event_id, u64 addr, u64 count, void *record,
+                         int entry_size)
 {
+       struct perf_raw_record raw = {
+               .size = entry_size,
+               .data = record,
+       };
+
        struct perf_sample_data data = {
-               .regs = get_irq_regs();
-               .addr = 0,
+               .regs = get_irq_regs(),
+               .addr = addr,
+               .raw = &raw,
        };
 
        if (!data.regs)
                data.regs = task_pt_regs(current);
 
-       do_perf_swcounter_event(PERF_TYPE_TRACEPOINT, event_id, 1, 1, &data);
+       do_perf_swcounter_event(PERF_TYPE_TRACEPOINT, event_id, count, 1, &data);
 }
 EXPORT_SYMBOL_GPL(perf_tpcounter_event);
 
@@ -3486,16 +3924,20 @@ extern void ftrace_profile_disable(int);
 
 static void tp_perf_counter_destroy(struct perf_counter *counter)
 {
-       ftrace_profile_disable(perf_event_id(&counter->attr));
+       ftrace_profile_disable(counter->attr.config);
 }
 
 static const struct pmu *tp_perf_counter_init(struct perf_counter *counter)
 {
-       int event_id = perf_event_id(&counter->attr);
-       int ret;
+       /*
+        * Raw tracepoint data is a severe data leak, only allow root to
+        * have these.
+        */
+       if ((counter->attr.sample_type & PERF_SAMPLE_RAW) &&
+                       !capable(CAP_SYS_ADMIN))
+               return ERR_PTR(-EPERM);
 
-       ret = ftrace_profile_enable(event_id);
-       if (ret)
+       if (ftrace_profile_enable(counter->attr.config))
                return NULL;
 
        counter->destroy = tp_perf_counter_destroy;
@@ -3509,9 +3951,21 @@ static const struct pmu *tp_perf_counter_init(struct perf_counter *counter)
 }
 #endif
 
+atomic_t perf_swcounter_enabled[PERF_COUNT_SW_MAX];
+
+static void sw_perf_counter_destroy(struct perf_counter *counter)
+{
+       u64 event = counter->attr.config;
+
+       WARN_ON(counter->parent);
+
+       atomic_dec(&perf_swcounter_enabled[event]);
+}
+
 static const struct pmu *sw_perf_counter_init(struct perf_counter *counter)
 {
        const struct pmu *pmu = NULL;
+       u64 event = counter->attr.config;
 
        /*
         * Software counters (currently) can't in general distinguish
@@ -3520,7 +3974,7 @@ static const struct pmu *sw_perf_counter_init(struct perf_counter *counter)
         * to be kernel events, and page faults are never hypervisor
         * events.
         */
-       switch (counter->attr.config) {
+       switch (event) {
        case PERF_COUNT_SW_CPU_CLOCK:
                pmu = &perf_ops_cpu_clock;
 
@@ -3541,6 +3995,10 @@ static const struct pmu *sw_perf_counter_init(struct perf_counter *counter)
        case PERF_COUNT_SW_PAGE_FAULTS_MAJ:
        case PERF_COUNT_SW_CONTEXT_SWITCHES:
        case PERF_COUNT_SW_CPU_MIGRATIONS:
+               if (!counter->parent) {
+                       atomic_inc(&perf_swcounter_enabled[event]);
+                       counter->destroy = sw_perf_counter_destroy;
+               }
                pmu = &perf_ops_generic;
                break;
        }
@@ -3556,6 +4014,7 @@ perf_counter_alloc(struct perf_counter_attr *attr,
                   int cpu,
                   struct perf_counter_context *ctx,
                   struct perf_counter *group_leader,
+                  struct perf_counter *parent_counter,
                   gfp_t gfpflags)
 {
        const struct pmu *pmu;
@@ -3591,6 +4050,8 @@ perf_counter_alloc(struct perf_counter_attr *attr,
        counter->ctx            = ctx;
        counter->oncpu          = -1;
 
+       counter->parent         = parent_counter;
+
        counter->ns             = get_pid_ns(current->nsproxy->pid_ns);
        counter->id             = atomic64_inc_return(&perf_counter_id);
 
@@ -3605,13 +4066,14 @@ perf_counter_alloc(struct perf_counter_attr *attr,
        hwc->sample_period = attr->sample_period;
        if (attr->freq && attr->sample_freq)
                hwc->sample_period = 1;
+       hwc->last_period = hwc->sample_period;
 
        atomic64_set(&hwc->period_left, hwc->sample_period);
 
        /*
-        * we currently do not support PERF_SAMPLE_GROUP on inherited counters
+        * we currently do not support PERF_FORMAT_GROUP on inherited counters
         */
-       if (attr->inherit && (attr->sample_type & PERF_SAMPLE_GROUP))
+       if (attr->inherit && (attr->read_format & PERF_FORMAT_GROUP))
                goto done;
 
        switch (attr->type) {
@@ -3648,11 +4110,15 @@ done:
 
        counter->pmu = pmu;
 
-       atomic_inc(&nr_counters);
-       if (counter->attr.mmap)
-               atomic_inc(&nr_mmap_counters);
-       if (counter->attr.comm)
-               atomic_inc(&nr_comm_counters);
+       if (!counter->parent) {
+               atomic_inc(&nr_counters);
+               if (counter->attr.mmap)
+                       atomic_inc(&nr_mmap_counters);
+               if (counter->attr.comm)
+                       atomic_inc(&nr_comm_counters);
+               if (counter->attr.task)
+                       atomic_inc(&nr_task_counters);
+       }
 
        return counter;
 }
@@ -3815,7 +4281,7 @@ SYSCALL_DEFINE5(perf_counter_open,
        }
 
        counter = perf_counter_alloc(&attr, cpu, ctx, group_leader,
-                                    GFP_KERNEL);
+                                    NULL, GFP_KERNEL);
        ret = PTR_ERR(counter);
        if (IS_ERR(counter))
                goto err_put_context;
@@ -3881,7 +4347,8 @@ inherit_counter(struct perf_counter *parent_counter,
 
        child_counter = perf_counter_alloc(&parent_counter->attr,
                                           parent_counter->cpu, child_ctx,
-                                          group_leader, GFP_KERNEL);
+                                          group_leader, parent_counter,
+                                          GFP_KERNEL);
        if (IS_ERR(child_counter))
                return child_counter;
        get_ctx(child_ctx);
@@ -3904,12 +4371,6 @@ inherit_counter(struct perf_counter *parent_counter,
         */
        add_counter_to_ctx(child_counter, child_ctx);
 
-       child_counter->parent = parent_counter;
-       /*
-        * inherit into child's child as well:
-        */
-       child_counter->attr.inherit = 1;
-
        /*
         * Get a reference to the parent filp - we will fput it
         * when the child counter exits. This is safe to do because
@@ -3953,10 +4414,14 @@ static int inherit_group(struct perf_counter *parent_counter,
 }
 
 static void sync_child_counter(struct perf_counter *child_counter,
-                              struct perf_counter *parent_counter)
+                              struct task_struct *child)
 {
+       struct perf_counter *parent_counter = child_counter->parent;
        u64 child_val;
 
+       if (child_counter->attr.inherit_stat)
+               perf_counter_read_event(child_counter, child);
+
        child_val = atomic64_read(&child_counter->count);
 
        /*
@@ -3985,7 +4450,8 @@ static void sync_child_counter(struct perf_counter *child_counter,
 
 static void
 __perf_counter_exit_task(struct perf_counter *child_counter,
-                        struct perf_counter_context *child_ctx)
+                        struct perf_counter_context *child_ctx,
+                        struct task_struct *child)
 {
        struct perf_counter *parent_counter;
 
@@ -3999,7 +4465,7 @@ __perf_counter_exit_task(struct perf_counter *child_counter,
         * counters need to be zapped - but otherwise linger.
         */
        if (parent_counter) {
-               sync_child_counter(child_counter, parent_counter);
+               sync_child_counter(child_counter, child);
                free_counter(child_counter);
        }
 }
@@ -4013,8 +4479,10 @@ void perf_counter_exit_task(struct task_struct *child)
        struct perf_counter_context *child_ctx;
        unsigned long flags;
 
-       if (likely(!child->perf_counter_ctxp))
+       if (likely(!child->perf_counter_ctxp)) {
+               perf_counter_task(child, NULL, 0);
                return;
+       }
 
        local_irq_save(flags);
        /*
@@ -4033,17 +4501,20 @@ void perf_counter_exit_task(struct task_struct *child)
         */
        spin_lock(&child_ctx->lock);
        child->perf_counter_ctxp = NULL;
-       if (child_ctx->parent_ctx) {
-               /*
-                * This context is a clone; unclone it so it can't get
-                * swapped to another process while we're removing all
-                * the counters from it.
-                */
-               put_ctx(child_ctx->parent_ctx);
-               child_ctx->parent_ctx = NULL;
-       }
-       spin_unlock(&child_ctx->lock);
-       local_irq_restore(flags);
+       /*
+        * If this context is a clone; unclone it so it can't get
+        * swapped to another process while we're removing all
+        * the counters from it.
+        */
+       unclone_ctx(child_ctx);
+       spin_unlock_irqrestore(&child_ctx->lock, flags);
+
+       /*
+        * Report the task dead after unscheduling the counters so that we
+        * won't get any samples after PERF_EVENT_EXIT. We can however still
+        * get a few PERF_EVENT_READ events.
+        */
+       perf_counter_task(child, child_ctx, 0);
 
        /*
         * We can recurse on the same lock type through:
@@ -4061,7 +4532,7 @@ void perf_counter_exit_task(struct task_struct *child)
 again:
        list_for_each_entry_safe(child_counter, tmp, &child_ctx->counter_list,
                                 list_entry)
-               __perf_counter_exit_task(child_counter, child_ctx);
+               __perf_counter_exit_task(child_counter, child_ctx, child);
 
        /*
         * If the last counter was a group counter, it will have appended all
@@ -4264,6 +4735,11 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
                perf_counter_init_cpu(cpu);
                break;
 
+       case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
+               hw_perf_counter_setup_online(cpu);
+               break;
+
        case CPU_DOWN_PREPARE:
        case CPU_DOWN_PREPARE_FROZEN:
                perf_counter_exit_cpu(cpu);
@@ -4288,6 +4764,8 @@ void __init perf_counter_init(void)
 {
        perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_UP_PREPARE,
                        (void *)(long)smp_processor_id());
+       perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_ONLINE,
+                       (void *)(long)smp_processor_id());
        register_cpu_notifier(&perf_cpu_nb);
 }
 
index bece7c0b67b29d42c3c425d053bd76087b7684f3..e33a21cb9407987a0aa9b46c32baba590302862b 100644 (file)
@@ -521,11 +521,12 @@ void posix_cpu_timers_exit(struct task_struct *tsk)
 }
 void posix_cpu_timers_exit_group(struct task_struct *tsk)
 {
-       struct task_cputime cputime;
+       struct signal_struct *const sig = tsk->signal;
 
-       thread_group_cputimer(tsk, &cputime);
        cleanup_timers(tsk->signal->cpu_timers,
-                      cputime.utime, cputime.stime, cputime.sum_exec_runtime);
+                      cputime_add(tsk->utime, sig->utime),
+                      cputime_add(tsk->stime, sig->stime),
+                      tsk->se.sum_exec_runtime + sig->sum_sched_runtime);
 }
 
 static void clear_dead_task(struct k_itimer *timer, union cpu_time_count now)
index 052ec4d195c7d1ee68fc3b5f9eeb422b932bb3b5..d089d052c4a90f18bb908724e93806f86d0e11aa 100644 (file)
@@ -202,6 +202,12 @@ static int no_timer_create(struct k_itimer *new_timer)
        return -EOPNOTSUPP;
 }
 
+static int no_nsleep(const clockid_t which_clock, int flags,
+                    struct timespec *tsave, struct timespec __user *rmtp)
+{
+       return -EOPNOTSUPP;
+}
+
 /*
  * Return nonzero if we know a priori this clockid_t value is bogus.
  */
@@ -254,6 +260,7 @@ static __init int init_posix_timers(void)
                .clock_get = posix_get_monotonic_raw,
                .clock_set = do_posix_clock_nosettime,
                .timer_create = no_timer_create,
+               .nsleep = no_nsleep,
        };
 
        register_posix_clock(CLOCK_REALTIME, &clock_realtime);
index ed97375daae9326ecf2b4864ff9368f1491f642a..bf0014d6a5f0972a1b2352d35a09eb82296164d1 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/console.h>
 #include <linux/cpu.h>
 #include <linux/freezer.h>
-#include <linux/smp_lock.h>
 #include <scsi/scsi_scan.h>
 
 #include <asm/uaccess.h>
index 69911b5745eb1a9fd406e7bf3ef4a653033898a2..419250ebec4d63b913130a2f533cc2adf95f359a 100644 (file)
@@ -117,11 +117,12 @@ int __ref profile_init(void)
 
        cpumask_copy(prof_cpu_mask, cpu_possible_mask);
 
-       prof_buffer = kzalloc(buffer_bytes, GFP_KERNEL);
+       prof_buffer = kzalloc(buffer_bytes, GFP_KERNEL|__GFP_NOWARN);
        if (prof_buffer)
                return 0;
 
-       prof_buffer = alloc_pages_exact(buffer_bytes, GFP_KERNEL|__GFP_ZERO);
+       prof_buffer = alloc_pages_exact(buffer_bytes,
+                                       GFP_KERNEL|__GFP_ZERO|__GFP_NOWARN);
        if (prof_buffer)
                return 0;
 
index 61c78b2c07baefd768aed903f482ea08d9672200..082c320e4dbf0a4538b064f55814c72246852877 100644 (file)
@@ -181,8 +181,8 @@ int ptrace_attach(struct task_struct *task)
         * interference; SUID, SGID and LSM creds get determined differently
         * under ptrace.
         */
-       retval = mutex_lock_interruptible(&task->cred_guard_mutex);
-       if (retval < 0)
+       retval = -ERESTARTNOINTR;
+       if (mutex_lock_interruptible(&task->cred_guard_mutex))
                goto out;
 
        task_lock(task);
index 0dccfbba6d267ad59b62314d665a3a91b3104252..7717b95c202782d2af38837fc09dc475a5f845bb 100644 (file)
@@ -1533,7 +1533,7 @@ void __init __rcu_init(void)
        int j;
        struct rcu_node *rnp;
 
-       printk(KERN_WARNING "Experimental hierarchical RCU implementation.\n");
+       printk(KERN_INFO "Hierarchical RCU implementation.\n");
 #ifdef CONFIG_RCU_CPU_STALL_DETECTOR
        printk(KERN_INFO "RCU-based detection of stalled CPUs is enabled.\n");
 #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */
@@ -1546,7 +1546,6 @@ void __init __rcu_init(void)
                rcu_cpu_notify(&rcu_nb, CPU_UP_PREPARE, (void *)(long)i);
        /* Register notifier for non-boot CPUs */
        register_cpu_notifier(&rcu_nb);
-       printk(KERN_WARNING "Experimental hierarchical RCU init done.\n");
 }
 
 module_param(blimit, int, 0);
index ac5f3a36923fccf5abaee447a2ab6db6bbe71a4d..78b087221c156640f901b8eb59a9ad716155bc7b 100644 (file)
@@ -787,7 +787,7 @@ static int __init reserve_setup(char *str)
        static struct resource reserve[MAXRESERVE];
 
        for (;;) {
-               int io_start, io_num;
+               unsigned int io_start, io_num;
                int x = reserved;
 
                if (get_option (&str, &io_start) != 2)
index fcd107a78c5a1070c96ace2719d12bfe59a825f0..29bd4baf9e756d848895a868bd25c103f6ee1f85 100644 (file)
@@ -1039,16 +1039,14 @@ int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
        if (!rt_mutex_owner(lock) || try_to_steal_lock(lock, task)) {
                /* We got the lock for task. */
                debug_rt_mutex_lock(lock);
-
                rt_mutex_set_owner(lock, task, 0);
-
+               spin_unlock(&lock->wait_lock);
                rt_mutex_deadlock_account_lock(lock, task);
                return 1;
        }
 
        ret = task_blocks_on_rt_mutex(lock, waiter, task, detect_deadlock);
 
-
        if (ret && !waiter->task) {
                /*
                 * Reset the return value. We might have
index 7c9098d186e6f8e398c0cb9500c1efa2120293e2..1b59e265273b032d6aac2baec9b059646ca563bf 100644 (file)
@@ -493,6 +493,7 @@ struct rt_rq {
 #endif
 #ifdef CONFIG_SMP
        unsigned long rt_nr_migratory;
+       unsigned long rt_nr_total;
        int overloaded;
        struct plist_head pushable_tasks;
 #endif
@@ -2571,15 +2572,37 @@ static void __sched_fork(struct task_struct *p)
        p->se.avg_wakeup                = sysctl_sched_wakeup_granularity;
 
 #ifdef CONFIG_SCHEDSTATS
-       p->se.wait_start                = 0;
-       p->se.sum_sleep_runtime         = 0;
-       p->se.sleep_start               = 0;
-       p->se.block_start               = 0;
-       p->se.sleep_max                 = 0;
-       p->se.block_max                 = 0;
-       p->se.exec_max                  = 0;
-       p->se.slice_max                 = 0;
-       p->se.wait_max                  = 0;
+       p->se.wait_start                        = 0;
+       p->se.wait_max                          = 0;
+       p->se.wait_count                        = 0;
+       p->se.wait_sum                          = 0;
+
+       p->se.sleep_start                       = 0;
+       p->se.sleep_max                         = 0;
+       p->se.sum_sleep_runtime                 = 0;
+
+       p->se.block_start                       = 0;
+       p->se.block_max                         = 0;
+       p->se.exec_max                          = 0;
+       p->se.slice_max                         = 0;
+
+       p->se.nr_migrations_cold                = 0;
+       p->se.nr_failed_migrations_affine       = 0;
+       p->se.nr_failed_migrations_running      = 0;
+       p->se.nr_failed_migrations_hot          = 0;
+       p->se.nr_forced_migrations              = 0;
+       p->se.nr_forced2_migrations             = 0;
+
+       p->se.nr_wakeups                        = 0;
+       p->se.nr_wakeups_sync                   = 0;
+       p->se.nr_wakeups_migrate                = 0;
+       p->se.nr_wakeups_local                  = 0;
+       p->se.nr_wakeups_remote                 = 0;
+       p->se.nr_wakeups_affine                 = 0;
+       p->se.nr_wakeups_affine_attempts        = 0;
+       p->se.nr_wakeups_passive                = 0;
+       p->se.nr_wakeups_idle                   = 0;
+
 #endif
 
        INIT_LIST_HEAD(&p->rt.run_list);
@@ -6541,6 +6564,11 @@ SYSCALL_DEFINE0(sched_yield)
        return 0;
 }
 
+static inline int should_resched(void)
+{
+       return need_resched() && !(preempt_count() & PREEMPT_ACTIVE);
+}
+
 static void __cond_resched(void)
 {
 #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
@@ -6560,8 +6588,7 @@ static void __cond_resched(void)
 
 int __sched _cond_resched(void)
 {
-       if (need_resched() && !(preempt_count() & PREEMPT_ACTIVE) &&
-                                       system_state == SYSTEM_RUNNING) {
+       if (should_resched()) {
                __cond_resched();
                return 1;
        }
@@ -6579,12 +6606,12 @@ EXPORT_SYMBOL(_cond_resched);
  */
 int cond_resched_lock(spinlock_t *lock)
 {
-       int resched = need_resched() && system_state == SYSTEM_RUNNING;
+       int resched = should_resched();
        int ret = 0;
 
        if (spin_needbreak(lock) || resched) {
                spin_unlock(lock);
-               if (resched && need_resched())
+               if (resched)
                        __cond_resched();
                else
                        cpu_relax();
@@ -6599,7 +6626,7 @@ int __sched cond_resched_softirq(void)
 {
        BUG_ON(!in_softirq());
 
-       if (need_resched() && system_state == SYSTEM_RUNNING) {
+       if (should_resched()) {
                local_bh_enable();
                __cond_resched();
                local_bh_disable();
@@ -7262,6 +7289,7 @@ static void migrate_dead_tasks(unsigned int dead_cpu)
 static void calc_global_load_remove(struct rq *rq)
 {
        atomic_long_sub(rq->calc_load_active, &calc_load_tasks);
+       rq->calc_load_active = 0;
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
@@ -7488,6 +7516,7 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
                task_rq_unlock(rq, &flags);
                get_task_struct(p);
                cpu_rq(cpu)->migration_thread = p;
+               rq->calc_load_update = calc_load_update;
                break;
 
        case CPU_ONLINE:
@@ -7498,8 +7527,6 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
                /* Update our root-domain */
                rq = cpu_rq(cpu);
                spin_lock_irqsave(&rq->lock, flags);
-               rq->calc_load_update = calc_load_update;
-               rq->calc_load_active = 0;
                if (rq->rd) {
                        BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
 
@@ -9070,7 +9097,7 @@ static void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq)
 #ifdef CONFIG_SMP
        rt_rq->rt_nr_migratory = 0;
        rt_rq->overloaded = 0;
-       plist_head_init(&rq->rt.pushable_tasks, &rq->lock);
+       plist_head_init(&rt_rq->pushable_tasks, &rq->lock);
 #endif
 
        rt_rq->rt_time = 0;
index e6c251790dde973712918e3d1676c665c511f23e..d014efbf947a26a9eb241df6c462893c0d00d9cf 100644 (file)
@@ -81,8 +81,21 @@ int cpupri_find(struct cpupri *cp, struct task_struct *p,
                if (cpumask_any_and(&p->cpus_allowed, vec->mask) >= nr_cpu_ids)
                        continue;
 
-               if (lowest_mask)
+               if (lowest_mask) {
                        cpumask_and(lowest_mask, &p->cpus_allowed, vec->mask);
+
+                       /*
+                        * We have to ensure that we have at least one bit
+                        * still set in the array, since the map could have
+                        * been concurrently emptied between the first and
+                        * second reads of vec->mask.  If we hit this
+                        * condition, simply act as though we never hit this
+                        * priority level and continue on.
+                        */
+                       if (cpumask_any(lowest_mask) >= nr_cpu_ids)
+                               continue;
+               }
+
                return 1;
        }
 
index ba7fd6e9556f892dd941ecdd9e77be225929c251..652e8bdef9aadb294b2e094a5d9620d95c26d873 100644 (file)
@@ -266,6 +266,12 @@ static inline u64 min_vruntime(u64 min_vruntime, u64 vruntime)
        return min_vruntime;
 }
 
+static inline int entity_before(struct sched_entity *a,
+                               struct sched_entity *b)
+{
+       return (s64)(a->vruntime - b->vruntime) < 0;
+}
+
 static inline s64 entity_key(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
        return se->vruntime - cfs_rq->min_vruntime;
@@ -605,9 +611,13 @@ account_entity_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se)
 static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
 #ifdef CONFIG_SCHEDSTATS
+       struct task_struct *tsk = NULL;
+
+       if (entity_is_task(se))
+               tsk = task_of(se);
+
        if (se->sleep_start) {
                u64 delta = rq_of(cfs_rq)->clock - se->sleep_start;
-               struct task_struct *tsk = task_of(se);
 
                if ((s64)delta < 0)
                        delta = 0;
@@ -618,11 +628,11 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
                se->sleep_start = 0;
                se->sum_sleep_runtime += delta;
 
-               account_scheduler_latency(tsk, delta >> 10, 1);
+               if (tsk)
+                       account_scheduler_latency(tsk, delta >> 10, 1);
        }
        if (se->block_start) {
                u64 delta = rq_of(cfs_rq)->clock - se->block_start;
-               struct task_struct *tsk = task_of(se);
 
                if ((s64)delta < 0)
                        delta = 0;
@@ -633,17 +643,19 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se)
                se->block_start = 0;
                se->sum_sleep_runtime += delta;
 
-               /*
-                * Blocking time is in units of nanosecs, so shift by 20 to
-                * get a milliseconds-range estimation of the amount of
-                * time that the task spent sleeping:
-                */
-               if (unlikely(prof_on == SLEEP_PROFILING)) {
-
-                       profile_hits(SLEEP_PROFILING, (void *)get_wchan(tsk),
-                                    delta >> 20);
+               if (tsk) {
+                       /*
+                        * Blocking time is in units of nanosecs, so shift by
+                        * 20 to get a milliseconds-range estimation of the
+                        * amount of time that the task spent sleeping:
+                        */
+                       if (unlikely(prof_on == SLEEP_PROFILING)) {
+                               profile_hits(SLEEP_PROFILING,
+                                               (void *)get_wchan(tsk),
+                                               delta >> 20);
+                       }
+                       account_scheduler_latency(tsk, delta >> 10, 0);
                }
-               account_scheduler_latency(tsk, delta >> 10, 0);
        }
 #endif
 }
@@ -687,7 +699,8 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial)
                         * all of which have the same weight.
                         */
                        if (sched_feat(NORMALIZED_SLEEPER) &&
-                                       task_of(se)->policy != SCHED_IDLE)
+                                       (!entity_is_task(se) ||
+                                        task_of(se)->policy != SCHED_IDLE))
                                thresh = calc_delta_fair(thresh, se);
 
                        vruntime -= thresh;
@@ -1016,7 +1029,7 @@ static void yield_task_fair(struct rq *rq)
        /*
         * Already in the rightmost position?
         */
-       if (unlikely(!rightmost || rightmost->vruntime < se->vruntime))
+       if (unlikely(!rightmost || entity_before(rightmost, se)))
                return;
 
        /*
@@ -1712,7 +1725,7 @@ static void task_new_fair(struct rq *rq, struct task_struct *p)
 
        /* 'curr' will be NULL if the child belongs to a different group */
        if (sysctl_sched_child_runs_first && this_cpu == task_cpu(p) &&
-                       curr && curr->vruntime < se->vruntime) {
+                       curr && entity_before(curr, se)) {
                /*
                 * Upon rescheduling, sched_class::put_prev_task() will place
                 * 'current' within the tree based on its new key value.
index 9bf0d2a7304569a87ba4aa0c919bbb2531c39c06..3918e01994e0a92bd734d22eebef7047e0a17a57 100644 (file)
@@ -10,6 +10,8 @@ static inline struct task_struct *rt_task_of(struct sched_rt_entity *rt_se)
 
 #ifdef CONFIG_RT_GROUP_SCHED
 
+#define rt_entity_is_task(rt_se) (!(rt_se)->my_q)
+
 static inline struct rq *rq_of_rt_rq(struct rt_rq *rt_rq)
 {
        return rt_rq->rq;
@@ -22,6 +24,8 @@ static inline struct rt_rq *rt_rq_of_se(struct sched_rt_entity *rt_se)
 
 #else /* CONFIG_RT_GROUP_SCHED */
 
+#define rt_entity_is_task(rt_se) (1)
+
 static inline struct rq *rq_of_rt_rq(struct rt_rq *rt_rq)
 {
        return container_of(rt_rq, struct rq, rt);
@@ -73,7 +77,7 @@ static inline void rt_clear_overload(struct rq *rq)
 
 static void update_rt_migration(struct rt_rq *rt_rq)
 {
-       if (rt_rq->rt_nr_migratory && (rt_rq->rt_nr_running > 1)) {
+       if (rt_rq->rt_nr_migratory && rt_rq->rt_nr_total > 1) {
                if (!rt_rq->overloaded) {
                        rt_set_overload(rq_of_rt_rq(rt_rq));
                        rt_rq->overloaded = 1;
@@ -86,6 +90,12 @@ static void update_rt_migration(struct rt_rq *rt_rq)
 
 static void inc_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
 {
+       if (!rt_entity_is_task(rt_se))
+               return;
+
+       rt_rq = &rq_of_rt_rq(rt_rq)->rt;
+
+       rt_rq->rt_nr_total++;
        if (rt_se->nr_cpus_allowed > 1)
                rt_rq->rt_nr_migratory++;
 
@@ -94,6 +104,12 @@ static void inc_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
 
 static void dec_rt_migration(struct sched_rt_entity *rt_se, struct rt_rq *rt_rq)
 {
+       if (!rt_entity_is_task(rt_se))
+               return;
+
+       rt_rq = &rq_of_rt_rq(rt_rq)->rt;
+
+       rt_rq->rt_nr_total--;
        if (rt_se->nr_cpus_allowed > 1)
                rt_rq->rt_nr_migratory--;
 
index ccf1ceedaebef64b137553e2e82250dbfe6a7707..64c5deeaca5d9a70f64f391bc73fde46e300bff1 100644 (file)
@@ -2454,11 +2454,9 @@ do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long s
        stack_t oss;
        int error;
 
-       if (uoss) {
-               oss.ss_sp = (void __user *) current->sas_ss_sp;
-               oss.ss_size = current->sas_ss_size;
-               oss.ss_flags = sas_ss_flags(sp);
-       }
+       oss.ss_sp = (void __user *) current->sas_ss_sp;
+       oss.ss_size = current->sas_ss_size;
+       oss.ss_flags = sas_ss_flags(sp);
 
        if (uss) {
                void __user *ss_sp;
@@ -2466,10 +2464,12 @@ do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long s
                int ss_flags;
 
                error = -EFAULT;
-               if (!access_ok(VERIFY_READ, uss, sizeof(*uss))
-                   || __get_user(ss_sp, &uss->ss_sp)
-                   || __get_user(ss_flags, &uss->ss_flags)
-                   || __get_user(ss_size, &uss->ss_size))
+               if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
+                       goto out;
+               error = __get_user(ss_sp, &uss->ss_sp) |
+                       __get_user(ss_flags, &uss->ss_flags) |
+                       __get_user(ss_size, &uss->ss_size);
+               if (error)
                        goto out;
 
                error = -EPERM;
@@ -2501,13 +2501,16 @@ do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long s
                current->sas_ss_size = ss_size;
        }
 
+       error = 0;
        if (uoss) {
                error = -EFAULT;
-               if (copy_to_user(uoss, &oss, sizeof(oss)))
+               if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
                        goto out;
+               error = __put_user(oss.ss_sp, &uoss->ss_sp) |
+                       __put_user(oss.ss_size, &uoss->ss_size) |
+                       __put_user(oss.ss_flags, &uoss->ss_flags);
        }
 
-       error = 0;
 out:
        return error;
 }
index ad63d8501207836353ad91d15f94fb3aaa4c0c1b..94188b8ecc33ea2bc7a232cd0ca362aa15f753fb 100644 (file)
@@ -57,7 +57,7 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
                        return NOTIFY_BAD;
                break;
 
-#ifdef CONFIG_CPU_HOTPLUG
+#ifdef CONFIG_HOTPLUG_CPU
        case CPU_UP_CANCELED:
        case CPU_UP_CANCELED_FROZEN:
 
index 3a94905fa5d27c4d0ef59ad56e83ad353e14f1fa..eb5e131a048528163c01930a413db3b4676e5c7c 100644 (file)
@@ -345,7 +345,9 @@ void open_softirq(int nr, void (*action)(struct softirq_action *))
        softirq_vec[nr].action = action;
 }
 
-/* Tasklets */
+/*
+ * Tasklets
+ */
 struct tasklet_head
 {
        struct tasklet_struct *head;
@@ -493,6 +495,66 @@ void tasklet_kill(struct tasklet_struct *t)
 
 EXPORT_SYMBOL(tasklet_kill);
 
+/*
+ * tasklet_hrtimer
+ */
+
+/*
+ * The trampoline is called when the hrtimer expires. If this is
+ * called from the hrtimer interrupt then we schedule the tasklet as
+ * the timer callback function expects to run in softirq context. If
+ * it's called in softirq context anyway (i.e. high resolution timers
+ * disabled) then the hrtimer callback is called right away.
+ */
+static enum hrtimer_restart __hrtimer_tasklet_trampoline(struct hrtimer *timer)
+{
+       struct tasklet_hrtimer *ttimer =
+               container_of(timer, struct tasklet_hrtimer, timer);
+
+       if (hrtimer_is_hres_active(timer)) {
+               tasklet_hi_schedule(&ttimer->tasklet);
+               return HRTIMER_NORESTART;
+       }
+       return ttimer->function(timer);
+}
+
+/*
+ * Helper function which calls the hrtimer callback from
+ * tasklet/softirq context
+ */
+static void __tasklet_hrtimer_trampoline(unsigned long data)
+{
+       struct tasklet_hrtimer *ttimer = (void *)data;
+       enum hrtimer_restart restart;
+
+       restart = ttimer->function(&ttimer->timer);
+       if (restart != HRTIMER_NORESTART)
+               hrtimer_restart(&ttimer->timer);
+}
+
+/**
+ * tasklet_hrtimer_init - Init a tasklet/hrtimer combo for softirq callbacks
+ * @ttimer:     tasklet_hrtimer which is initialized
+ * @function:   hrtimer callback funtion which gets called from softirq context
+ * @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME)
+ * @mode:       hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL)
+ */
+void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
+                         enum hrtimer_restart (*function)(struct hrtimer *),
+                         clockid_t which_clock, enum hrtimer_mode mode)
+{
+       hrtimer_init(&ttimer->timer, which_clock, mode);
+       ttimer->timer.function = __hrtimer_tasklet_trampoline;
+       tasklet_init(&ttimer->tasklet, __tasklet_hrtimer_trampoline,
+                    (unsigned long)ttimer);
+       ttimer->function = function;
+}
+EXPORT_SYMBOL_GPL(tasklet_hrtimer_init);
+
+/*
+ * Remote softirq bits
+ */
+
 DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);
 EXPORT_PER_CPU_SYMBOL(softirq_work_list);
 
index 62e4ff9968b5fe64a06c9f8735af10d3b6a304b9..58be76017fd000f3b019c0acab6d3cdeb672afda 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/acpi.h>
 #include <linux/reboot.h>
 #include <linux/ftrace.h>
+#include <linux/security.h>
 #include <linux/slow-work.h>
 #include <linux/perf_counter.h>
 
@@ -335,7 +336,10 @@ static struct ctl_table kern_table[] = {
                .data           = &sysctl_timer_migration,
                .maxlen         = sizeof(unsigned int),
                .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &zero,
+               .extra2         = &one,
        },
 #endif
        {
@@ -743,6 +747,14 @@ static struct ctl_table kern_table[] = {
                .mode           = 0644,
                .proc_handler   = &proc_dointvec,
        },
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "panic_on_io_nmi",
+               .data           = &panic_on_io_nmi,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
        {
                .ctl_name       = KERN_BOOTLOADER_TYPE,
                .procname       = "bootloader_type",
@@ -1295,10 +1307,10 @@ static struct ctl_table vm_table[] = {
        {
                .ctl_name       = CTL_UNNUMBERED,
                .procname       = "mmap_min_addr",
-               .data           = &mmap_min_addr,
-               .maxlen         = sizeof(unsigned long),
+               .data           = &dac_mmap_min_addr,
+               .maxlen         = sizeof(unsigned long),
                .mode           = 0644,
-               .proc_handler   = &proc_doulongvec_minmax,
+               .proc_handler   = &mmap_min_addr_handler,
        },
 #ifdef CONFIG_NUMA
        {
index 1ad6dd46111920d10c5d83f2f90c1aeeb81ca66d..620b58abdc3295307990978671b81173feb8ff47 100644 (file)
@@ -137,11 +137,12 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
  */
 int clockevents_register_notifier(struct notifier_block *nb)
 {
+       unsigned long flags;
        int ret;
 
-       spin_lock(&clockevents_lock);
+       spin_lock_irqsave(&clockevents_lock, flags);
        ret = raw_notifier_chain_register(&clockevents_chain, nb);
-       spin_unlock(&clockevents_lock);
+       spin_unlock_irqrestore(&clockevents_lock, flags);
 
        return ret;
 }
@@ -178,16 +179,18 @@ static void clockevents_notify_released(void)
  */
 void clockevents_register_device(struct clock_event_device *dev)
 {
+       unsigned long flags;
+
        BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
        BUG_ON(!dev->cpumask);
 
-       spin_lock(&clockevents_lock);
+       spin_lock_irqsave(&clockevents_lock, flags);
 
        list_add(&dev->list, &clockevent_devices);
        clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev);
        clockevents_notify_released();
 
-       spin_unlock(&clockevents_lock);
+       spin_unlock_irqrestore(&clockevents_lock, flags);
 }
 EXPORT_SYMBOL_GPL(clockevents_register_device);
 
@@ -235,8 +238,9 @@ void clockevents_exchange_device(struct clock_event_device *old,
 void clockevents_notify(unsigned long reason, void *arg)
 {
        struct list_head *node, *tmp;
+       unsigned long flags;
 
-       spin_lock(&clockevents_lock);
+       spin_lock_irqsave(&clockevents_lock, flags);
        clockevents_do_notify(reason, arg);
 
        switch (reason) {
@@ -251,18 +255,7 @@ void clockevents_notify(unsigned long reason, void *arg)
        default:
                break;
        }
-       spin_unlock(&clockevents_lock);
+       spin_unlock_irqrestore(&clockevents_lock, flags);
 }
 EXPORT_SYMBOL_GPL(clockevents_notify);
-
-ktime_t clockevents_get_next_event(int cpu)
-{
-       struct tick_device *td;
-       struct clock_event_device *dev;
-
-       td = &per_cpu(tick_cpu_device, cpu);
-       dev = td->evtdev;
-
-       return dev->next_event;
-}
 #endif
index 592bf584d1d2b5fa86a7fb605e4f5cf2901eda11..7466cb8112517b3bbc8869e4c2c91438ee74608c 100644 (file)
@@ -513,7 +513,7 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev,
         * Check to make sure we don't switch to a non-highres capable
         * clocksource if the tick code is in oneshot mode (highres or nohz)
         */
-       if (tick_oneshot_mode_active() &&
+       if (tick_oneshot_mode_active() && ovr &&
            !(ovr->flags & CLOCK_SOURCE_VALID_FOR_HRES)) {
                printk(KERN_WARNING "%s clocksource is not HRT compatible. "
                        "Cannot switch while in HRT/NOHZ mode\n", ovr->name);
index 877dbedc3118275ac77f34c2b63a655f6c1a7617..c2ec25087a35a0cbf265258caf953d83424314f9 100644 (file)
@@ -205,11 +205,11 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
  * Powerstate information: The system enters/leaves a state, where
  * affected devices might stop
  */
-static void tick_do_broadcast_on_off(void *why)
+static void tick_do_broadcast_on_off(unsigned long *reason)
 {
        struct clock_event_device *bc, *dev;
        struct tick_device *td;
-       unsigned long flags, *reason = why;
+       unsigned long flags;
        int cpu, bc_stopped;
 
        spin_lock_irqsave(&tick_broadcast_lock, flags);
@@ -276,8 +276,7 @@ void tick_broadcast_on_off(unsigned long reason, int *oncpu)
                printk(KERN_ERR "tick-broadcast: ignoring broadcast for "
                       "offline CPU #%d\n", *oncpu);
        else
-               smp_call_function_single(*oncpu, tick_do_broadcast_on_off,
-                                        &reason, 1);
+               tick_do_broadcast_on_off(&reason);
 }
 
 /*
index a999b92a12773750daded0c912a822b6f0eebe84..fddd69d16e039a5d75f9093856d4abec8c6d10b6 100644 (file)
@@ -286,7 +286,7 @@ static int __init init_timer_list_procfs(void)
 {
        struct proc_dir_entry *pe;
 
-       pe = proc_create("timer_list", 0644, NULL, &timer_list_fops);
+       pe = proc_create("timer_list", 0444, NULL, &timer_list_fops);
        if (!pe)
                return -ENOMEM;
        return 0;
index c994530d166da4fde2bed268f7a3ecfe661e93a8..4cde8b9c716f39b778ab7dfe5ead8985c0eb2c97 100644 (file)
@@ -96,7 +96,7 @@ static DEFINE_MUTEX(show_mutex);
 /*
  * Collection status, active/inactive:
  */
-static int __read_mostly active;
+int __read_mostly timer_stats_active;
 
 /*
  * Beginning/end timestamps of measurement:
@@ -242,7 +242,7 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
        struct entry *entry, input;
        unsigned long flags;
 
-       if (likely(!active))
+       if (likely(!timer_stats_active))
                return;
 
        lock = &per_cpu(lookup_lock, raw_smp_processor_id());
@@ -254,7 +254,7 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
        input.timer_flag = timer_flag;
 
        spin_lock_irqsave(lock, flags);
-       if (!active)
+       if (!timer_stats_active)
                goto out_unlock;
 
        entry = tstat_lookup(&input, comm);
@@ -290,7 +290,7 @@ static int tstats_show(struct seq_file *m, void *v)
        /*
         * If still active then calculate up to now:
         */
-       if (active)
+       if (timer_stats_active)
                time_stop = ktime_get();
 
        time = ktime_sub(time_stop, time_start);
@@ -368,18 +368,18 @@ static ssize_t tstats_write(struct file *file, const char __user *buf,
        mutex_lock(&show_mutex);
        switch (ctl[0]) {
        case '0':
-               if (active) {
-                       active = 0;
+               if (timer_stats_active) {
+                       timer_stats_active = 0;
                        time_stop = ktime_get();
                        sync_access();
                }
                break;
        case '1':
-               if (!active) {
+               if (!timer_stats_active) {
                        reset_entries();
                        time_start = ktime_get();
                        smp_mb();
-                       active = 1;
+                       timer_stats_active = 1;
                }
                break;
        default:
index 54d3912f8cadd497d09546ad8b9b1ba42369634d..a7f07d5a6241d882af4466ec3280a89f2681e8c9 100644 (file)
@@ -380,6 +380,8 @@ static void timer_stats_account_timer(struct timer_list *timer)
 {
        unsigned int flag = 0;
 
+       if (likely(!timer->start_site))
+               return;
        if (unlikely(tbase_get_deferrable(timer->base)))
                flag |= TIMER_STATS_FLAG_DEFERRABLE;
 
@@ -712,7 +714,7 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
         * networking code - if the timer is re-modified
         * to be the same thing then just return:
         */
-       if (timer->expires == expires && timer_pending(timer))
+       if (timer_pending(timer) && timer->expires == expires)
                return 1;
 
        return __mod_timer(timer, expires, false, TIMER_NOT_PINNED);
index 1551f47e7669ba06f5e010410e9408cb9de07eb4..019f380fd764c80354ed277cfc72b7a2e4906b19 100644 (file)
@@ -226,13 +226,13 @@ config BOOT_TRACER
          the timings of the initcalls and traces key events and the identity
          of tasks that can cause boot delays, such as context-switches.
 
-         Its aim is to be parsed by the /scripts/bootgraph.pl tool to
+         Its aim is to be parsed by the scripts/bootgraph.pl tool to
          produce pretty graphics about boot inefficiencies, giving a visual
          representation of the delays during initcalls - but the raw
          /debug/tracing/trace text output is readable too.
 
-         You must pass in ftrace=initcall to the kernel command line
-         to enable this on bootup.
+         You must pass in initcall_debug and ftrace=initcall to the kernel
+         command line to enable this on bootup.
 
 config TRACE_BRANCH_PROFILING
        bool
index 39af8af6fc302c981226ab8c8f277026b319ca4a..7a34cb563fec4cef90ebbf1d6bcc71dd4af4fef4 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/debugfs.h>
+#include <linux/smp_lock.h>
 #include <linux/time.h>
 #include <linux/uaccess.h>
 
@@ -266,8 +267,8 @@ static void blk_trace_free(struct blk_trace *bt)
 {
        debugfs_remove(bt->msg_file);
        debugfs_remove(bt->dropped_file);
-       debugfs_remove(bt->dir);
        relay_close(bt->rchan);
+       debugfs_remove(bt->dir);
        free_percpu(bt->sequence);
        free_percpu(bt->msg_data);
        kfree(bt);
@@ -377,18 +378,8 @@ static int blk_subbuf_start_callback(struct rchan_buf *buf, void *subbuf,
 
 static int blk_remove_buf_file_callback(struct dentry *dentry)
 {
-       struct dentry *parent = dentry->d_parent;
        debugfs_remove(dentry);
 
-       /*
-       * this will fail for all but the last file, but that is ok. what we
-       * care about is the top level buts->name directory going away, when
-       * the last trace file is gone. Then we don't have to rmdir() that
-       * manually on trace stop, so it nicely solves the issue with
-       * force killing of running traces.
-       */
-
-       debugfs_remove(parent);
        return 0;
 }
 
index 3718d55fb4c372a826932011ec82e64d9fde40df..25edd5cc5935cae5d76342cf04e2bed40c22f00d 100644 (file)
@@ -291,7 +291,9 @@ function_stat_next(void *v, int idx)
        pg = (struct ftrace_profile_page *)((unsigned long)rec & PAGE_MASK);
 
  again:
-       rec++;
+       if (idx != 0)
+               rec++;
+
        if ((void *)rec >= (void *)&pg->records[pg->index]) {
                pg = pg->next;
                if (!pg)
@@ -766,7 +768,7 @@ static struct tracer_stat function_stats __initdata = {
        .stat_show      = function_stat_show
 };
 
-static void ftrace_profile_debugfs(struct dentry *d_tracer)
+static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
 {
        struct ftrace_profile_stat *stat;
        struct dentry *entry;
@@ -784,7 +786,6 @@ static void ftrace_profile_debugfs(struct dentry *d_tracer)
                         * The files created are permanent, if something happens
                         * we still do not free memory.
                         */
-                       kfree(stat);
                        WARN(1,
                             "Could not allocate stat file for cpu %d\n",
                             cpu);
@@ -811,7 +812,7 @@ static void ftrace_profile_debugfs(struct dentry *d_tracer)
 }
 
 #else /* CONFIG_FUNCTION_PROFILER */
-static void ftrace_profile_debugfs(struct dentry *d_tracer)
+static __init void ftrace_profile_debugfs(struct dentry *d_tracer)
 {
 }
 #endif /* CONFIG_FUNCTION_PROFILER */
@@ -1417,10 +1418,20 @@ static void *t_hash_start(struct seq_file *m, loff_t *pos)
 {
        struct ftrace_iterator *iter = m->private;
        void *p = NULL;
+       loff_t l;
+
+       if (!(iter->flags & FTRACE_ITER_HASH))
+               *pos = 0;
 
        iter->flags |= FTRACE_ITER_HASH;
 
-       return t_hash_next(m, p, pos);
+       iter->hidx = 0;
+       for (l = 0; l <= *pos; ) {
+               p = t_hash_next(m, p, &l);
+               if (!p)
+                       break;
+       }
+       return p;
 }
 
 static int t_hash_show(struct seq_file *m, void *v)
@@ -1467,8 +1478,6 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
                        iter->pg = iter->pg->next;
                        iter->idx = 0;
                        goto retry;
-               } else {
-                       iter->idx = -1;
                }
        } else {
                rec = &iter->pg->records[iter->idx++];
@@ -1497,6 +1506,7 @@ static void *t_start(struct seq_file *m, loff_t *pos)
 {
        struct ftrace_iterator *iter = m->private;
        void *p = NULL;
+       loff_t l;
 
        mutex_lock(&ftrace_lock);
        /*
@@ -1508,23 +1518,21 @@ static void *t_start(struct seq_file *m, loff_t *pos)
                if (*pos > 0)
                        return t_hash_start(m, pos);
                iter->flags |= FTRACE_ITER_PRINTALL;
-               (*pos)++;
                return iter;
        }
 
        if (iter->flags & FTRACE_ITER_HASH)
                return t_hash_start(m, pos);
 
-       if (*pos > 0) {
-               if (iter->idx < 0)
-                       return p;
-               (*pos)--;
-               iter->idx--;
+       iter->pg = ftrace_pages_start;
+       iter->idx = 0;
+       for (l = 0; l <= *pos; ) {
+               p = t_next(m, p, &l);
+               if (!p)
+                       break;
        }
 
-       p = t_next(m, p, pos);
-
-       if (!p)
+       if (!p && iter->flags & FTRACE_ITER_FILTER)
                return t_hash_start(m, pos);
 
        return p;
@@ -1654,7 +1662,7 @@ ftrace_regex_open(struct inode *inode, struct file *file, int enable)
 
        mutex_lock(&ftrace_regex_lock);
        if ((file->f_mode & FMODE_WRITE) &&
-           !(file->f_flags & O_APPEND))
+           (file->f_flags & O_TRUNC))
                ftrace_filter_reset(enable);
 
        if (file->f_mode & FMODE_READ) {
@@ -2270,7 +2278,11 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
        read++;
        cnt--;
 
-       if (!(iter->flags & ~FTRACE_ITER_CONT)) {
+       /*
+        * If the parser haven't finished with the last write,
+        * continue reading the user input without skipping spaces.
+        */
+       if (!(iter->flags & FTRACE_ITER_CONT)) {
                /* skip white space */
                while (cnt && isspace(ch)) {
                        ret = get_user(ch, ubuf++);
@@ -2280,8 +2292,9 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
                        cnt--;
                }
 
+               /* only spaces were written */
                if (isspace(ch)) {
-                       file->f_pos += read;
+                       *ppos += read;
                        ret = read;
                        goto out;
                }
@@ -2311,12 +2324,12 @@ ftrace_regex_write(struct file *file, const char __user *ubuf,
                if (ret)
                        goto out;
                iter->buffer_idx = 0;
-       } else
+       } else {
                iter->flags |= FTRACE_ITER_CONT;
+               iter->buffer[iter->buffer_idx++] = ch;
+       }
 
-
-       file->f_pos += read;
-
+       *ppos += read;
        ret = read;
  out:
        mutex_unlock(&ftrace_regex_lock);
@@ -2500,32 +2513,31 @@ int ftrace_graph_count;
 unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly;
 
 static void *
-g_next(struct seq_file *m, void *v, loff_t *pos)
+__g_next(struct seq_file *m, loff_t *pos)
 {
        unsigned long *array = m->private;
-       int index = *pos;
 
-       (*pos)++;
-
-       if (index >= ftrace_graph_count)
+       if (*pos >= ftrace_graph_count)
                return NULL;
+       return &array[*pos];
+}
 
-       return &array[index];
+static void *
+g_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       (*pos)++;
+       return __g_next(m, pos);
 }
 
 static void *g_start(struct seq_file *m, loff_t *pos)
 {
-       void *p = NULL;
-
        mutex_lock(&graph_lock);
 
        /* Nothing, tell g_show to print all functions are enabled */
        if (!ftrace_graph_count && !*pos)
                return (void *)1;
 
-       p = g_next(m, p, pos);
-
-       return p;
+       return __g_next(m, pos);
 }
 
 static void g_stop(struct seq_file *m, void *p)
@@ -2570,7 +2582,7 @@ ftrace_graph_open(struct inode *inode, struct file *file)
 
        mutex_lock(&graph_lock);
        if ((file->f_mode & FMODE_WRITE) &&
-           !(file->f_flags & O_APPEND)) {
+           (file->f_flags & O_TRUNC)) {
                ftrace_graph_count = 0;
                memset(ftrace_graph_funcs, 0, sizeof(ftrace_graph_funcs));
        }
@@ -2588,6 +2600,14 @@ ftrace_graph_open(struct inode *inode, struct file *file)
        return ret;
 }
 
+static int
+ftrace_graph_release(struct inode *inode, struct file *file)
+{
+       if (file->f_mode & FMODE_READ)
+               seq_release(inode, file);
+       return 0;
+}
+
 static int
 ftrace_set_func(unsigned long *array, int *idx, char *buffer)
 {
@@ -2717,9 +2737,10 @@ ftrace_graph_write(struct file *file, const char __user *ubuf,
 }
 
 static const struct file_operations ftrace_graph_fops = {
-       .open = ftrace_graph_open,
-       .read = seq_read,
-       .write = ftrace_graph_write,
+       .open           = ftrace_graph_open,
+       .read           = seq_read,
+       .write          = ftrace_graph_write,
+       .release        = ftrace_graph_release,
 };
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
@@ -3152,10 +3173,10 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
 
        ret  = proc_dointvec(table, write, file, buffer, lenp, ppos);
 
-       if (ret || !write || (last_ftrace_enabled == ftrace_enabled))
+       if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled))
                goto out;
 
-       last_ftrace_enabled = ftrace_enabled;
+       last_ftrace_enabled = !!ftrace_enabled;
 
        if (ftrace_enabled) {
 
index 04dac263825874d69f104df2f33cbd54433a2e40..a330513d96ce321ae0ea50e9fa648d6e9cbfc7e5 100644 (file)
@@ -735,6 +735,7 @@ ring_buffer_free(struct ring_buffer *buffer)
 
        put_online_cpus();
 
+       kfree(buffer->buffers);
        free_cpumask_var(buffer->cpumask);
 
        kfree(buffer);
@@ -1563,6 +1564,8 @@ rb_reserve_next_event(struct ring_buffer_per_cpu *cpu_buffer,
        return NULL;
 }
 
+#ifdef CONFIG_TRACING
+
 #define TRACE_RECURSIVE_DEPTH 16
 
 static int trace_recursive_lock(void)
@@ -1593,6 +1596,13 @@ static void trace_recursive_unlock(void)
        current->trace_recursion--;
 }
 
+#else
+
+#define trace_recursive_lock()         (0)
+#define trace_recursive_unlock()       do { } while (0)
+
+#endif
+
 static DEFINE_PER_CPU(int, rb_need_resched);
 
 /**
@@ -1776,7 +1786,7 @@ void ring_buffer_discard_commit(struct ring_buffer *buffer,
         */
        RB_WARN_ON(buffer, !local_read(&cpu_buffer->committing));
 
-       if (!rb_try_to_discard(cpu_buffer, event))
+       if (rb_try_to_discard(cpu_buffer, event))
                goto out;
 
        /*
@@ -2374,7 +2384,6 @@ rb_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts)
                 * the box. Return the padding, and we will release
                 * the current locks, and try again.
                 */
-               rb_advance_reader(cpu_buffer);
                return event;
 
        case RINGBUF_TYPE_TIME_EXTEND:
@@ -2477,7 +2486,7 @@ static inline int rb_ok_to_lock(void)
         * buffer too. A one time deal is all you get from reading
         * the ring buffer from an NMI.
         */
-       if (likely(!in_nmi() && !oops_in_progress))
+       if (likely(!in_nmi()))
                return 1;
 
        tracing_off_permanent();
@@ -2510,6 +2519,8 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts)
        if (dolock)
                spin_lock(&cpu_buffer->reader_lock);
        event = rb_buffer_peek(buffer, cpu, ts);
+       if (event && event->type_len == RINGBUF_TYPE_PADDING)
+               rb_advance_reader(cpu_buffer);
        if (dolock)
                spin_unlock(&cpu_buffer->reader_lock);
        local_irq_restore(flags);
@@ -2581,12 +2592,9 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts)
                spin_lock(&cpu_buffer->reader_lock);
 
        event = rb_buffer_peek(buffer, cpu, ts);
-       if (!event)
-               goto out_unlock;
-
-       rb_advance_reader(cpu_buffer);
+       if (event)
+               rb_advance_reader(cpu_buffer);
 
- out_unlock:
        if (dolock)
                spin_unlock(&cpu_buffer->reader_lock);
        local_irq_restore(flags);
@@ -3104,6 +3112,7 @@ int ring_buffer_read_page(struct ring_buffer *buffer,
 }
 EXPORT_SYMBOL_GPL(ring_buffer_read_page);
 
+#ifdef CONFIG_TRACING
 static ssize_t
 rb_simple_read(struct file *filp, char __user *ubuf,
               size_t cnt, loff_t *ppos)
@@ -3171,6 +3180,7 @@ static __init int rb_init_debugfs(void)
 }
 
 fs_initcall(rb_init_debugfs);
+#endif
 
 #ifdef CONFIG_HOTPLUG_CPU
 static int rb_cpu_notify(struct notifier_block *self,
index 076fa6f0ee480b6dbdabeaee8ac0bbe650a86628..8c358395d33828f1b3b6f0023027bf9e06638296 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/writeback.h>
 #include <linux/kallsyms.h>
 #include <linux/seq_file.h>
+#include <linux/smp_lock.h>
 #include <linux/notifier.h>
 #include <linux/irqflags.h>
 #include <linux/debugfs.h>
@@ -284,13 +285,12 @@ void trace_wake_up(void)
 static int __init set_buf_size(char *str)
 {
        unsigned long buf_size;
-       int ret;
 
        if (!str)
                return 0;
-       ret = strict_strtoul(str, 0, &buf_size);
+       buf_size = memparse(str, &str);
        /* nr_entries can not be zero */
-       if (ret < 0 || buf_size == 0)
+       if (buf_size == 0)
                return 0;
        trace_buf_size = buf_size;
        return 1;
@@ -848,6 +848,7 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags,
                ((pc & SOFTIRQ_MASK) ? TRACE_FLAG_SOFTIRQ : 0) |
                (need_resched() ? TRACE_FLAG_NEED_RESCHED : 0);
 }
+EXPORT_SYMBOL_GPL(tracing_generic_entry_update);
 
 struct ring_buffer_event *trace_buffer_lock_reserve(struct trace_array *tr,
                                                    int type,
@@ -2031,7 +2032,7 @@ static int tracing_open(struct inode *inode, struct file *file)
 
        /* If this file was open for write, then erase contents */
        if ((file->f_mode & FMODE_WRITE) &&
-           !(file->f_flags & O_APPEND)) {
+           (file->f_flags & O_TRUNC)) {
                long cpu = (long) inode->i_private;
 
                if (cpu == TRACE_PIPE_ALL_CPU)
@@ -2053,25 +2054,23 @@ static int tracing_open(struct inode *inode, struct file *file)
 static void *
 t_next(struct seq_file *m, void *v, loff_t *pos)
 {
-       struct tracer *t = m->private;
+       struct tracer *t = v;
 
        (*pos)++;
 
        if (t)
                t = t->next;
 
-       m->private = t;
-
        return t;
 }
 
 static void *t_start(struct seq_file *m, loff_t *pos)
 {
-       struct tracer *t = m->private;
+       struct tracer *t;
        loff_t l = 0;
 
        mutex_lock(&trace_types_lock);
-       for (; t && l < *pos; t = t_next(m, t, &l))
+       for (t = trace_types; t && l < *pos; t = t_next(m, t, &l))
                ;
 
        return t;
@@ -2107,18 +2106,10 @@ static struct seq_operations show_traces_seq_ops = {
 
 static int show_traces_open(struct inode *inode, struct file *file)
 {
-       int ret;
-
        if (tracing_disabled)
                return -ENODEV;
 
-       ret = seq_open(file, &show_traces_seq_ops);
-       if (!ret) {
-               struct seq_file *m = file->private_data;
-               m->private = trace_types;
-       }
-
-       return ret;
+       return seq_open(file, &show_traces_seq_ops);
 }
 
 static ssize_t
@@ -3095,7 +3086,8 @@ tracing_fill_pipe_page(size_t rem, struct trace_iterator *iter)
                        break;
                }
 
-               trace_consume(iter);
+               if (ret != TRACE_TYPE_NO_CONSUME)
+                       trace_consume(iter);
                rem -= count;
                if (!find_next_entry_inc(iter)) {
                        rem = 0;
@@ -3904,17 +3896,9 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
        if (ret < 0)
                return ret;
 
-       switch (val) {
-       case 0:
-               trace_flags &= ~(1 << index);
-               break;
-       case 1:
-               trace_flags |= 1 << index;
-               break;
-
-       default:
+       if (val != 0 && val != 1)
                return -EINVAL;
-       }
+       set_tracer_flags(1 << index, val);
 
        *ppos += cnt;
 
@@ -4243,8 +4227,11 @@ static void __ftrace_dump(bool disable_tracing)
                iter.pos = -1;
 
                if (find_next_entry_inc(&iter) != NULL) {
-                       print_trace_line(&iter);
-                       trace_consume(&iter);
+                       int ret;
+
+                       ret = print_trace_line(&iter);
+                       if (ret != TRACE_TYPE_NO_CONSUME)
+                               trace_consume(&iter);
                }
 
                trace_printk_seq(&iter.seq);
index 6e735d4771f8ad9ddd971ee1806f904d7e44e176..8b9f4f6e9559a6d152e874f24f75dae235638fc9 100644 (file)
@@ -438,10 +438,6 @@ struct trace_entry *tracing_get_trace_entry(struct trace_array *tr,
 struct trace_entry *trace_find_next_entry(struct trace_iterator *iter,
                                          int *ent_cpu, u64 *ent_ts);
 
-void tracing_generic_entry_update(struct trace_entry *entry,
-                                 unsigned long flags,
-                                 int pc);
-
 void default_wait_pipe(struct trace_iterator *iter);
 void poll_wait_pipe(struct trace_iterator *iter);
 
@@ -597,6 +593,7 @@ print_graph_function(struct trace_iterator *iter)
 
 extern struct pid *ftrace_pid_trace;
 
+#ifdef CONFIG_FUNCTION_TRACER
 static inline int ftrace_trace_task(struct task_struct *task)
 {
        if (!ftrace_pid_trace)
@@ -604,6 +601,12 @@ static inline int ftrace_trace_task(struct task_struct *task)
 
        return test_tsk_trace_trace(task);
 }
+#else
+static inline int ftrace_trace_task(struct task_struct *task)
+{
+       return 1;
+}
+#endif
 
 /*
  * trace_iterator_flags is an enumeration that defines bit
index 5b5895afecfe425f5c917af29b13d29ff4acf918..11ba5bb4ed0a71f0c3da5e8a2ce73471456aec47 100644 (file)
@@ -14,7 +14,7 @@ int ftrace_profile_enable(int event_id)
 
        mutex_lock(&event_mutex);
        list_for_each_entry(event, &ftrace_events, list) {
-               if (event->id == event_id) {
+               if (event->id == event_id && event->profile_enable) {
                        ret = event->profile_enable(event);
                        break;
                }
index 5e32e375134d976183bb0ae5df79abda3f029a54..6db005e12487cd943fb23d3978f4be71ce3cf9ec 100644 (file)
@@ -26,6 +26,9 @@ TRACE_EVENT_FORMAT(funcgraph_exit, TRACE_GRAPH_RET,
                   ftrace_graph_ret_entry, ignore,
        TRACE_STRUCT(
                TRACE_FIELD(unsigned long, ret.func, func)
+               TRACE_FIELD(unsigned long long, ret.calltime, calltime)
+               TRACE_FIELD(unsigned long long, ret.rettime, rettime)
+               TRACE_FIELD(unsigned long, ret.overrun, overrun)
                TRACE_FIELD(int, ret.depth, depth)
        ),
        TP_RAW_FMT("<-- %lx (%d)")
index aa08be69a1b6c1fcc026359ece8613812ad1a492..e75276a49cf5cfa2fb968609602621fa8e5a5da3 100644 (file)
@@ -300,10 +300,18 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
 
 static void *t_start(struct seq_file *m, loff_t *pos)
 {
+       struct ftrace_event_call *call = NULL;
+       loff_t l;
+
        mutex_lock(&event_mutex);
-       if (*pos == 0)
-               m->private = ftrace_events.next;
-       return t_next(m, NULL, pos);
+
+       m->private = ftrace_events.next;
+       for (l = 0; l <= *pos; ) {
+               call = t_next(m, NULL, &l);
+               if (!call)
+                       break;
+       }
+       return call;
 }
 
 static void *
@@ -332,10 +340,18 @@ s_next(struct seq_file *m, void *v, loff_t *pos)
 
 static void *s_start(struct seq_file *m, loff_t *pos)
 {
+       struct ftrace_event_call *call = NULL;
+       loff_t l;
+
        mutex_lock(&event_mutex);
-       if (*pos == 0)
-               m->private = ftrace_events.next;
-       return s_next(m, NULL, pos);
+
+       m->private = ftrace_events.next;
+       for (l = 0; l <= *pos; ) {
+               call = s_next(m, NULL, &l);
+               if (!call)
+                       break;
+       }
+       return call;
 }
 
 static int t_show(struct seq_file *m, void *v)
@@ -360,7 +376,7 @@ ftrace_event_seq_open(struct inode *inode, struct file *file)
        const struct seq_operations *seq_ops;
 
        if ((file->f_mode & FMODE_WRITE) &&
-           !(file->f_flags & O_APPEND))
+           (file->f_flags & O_TRUNC))
                ftrace_clear_events();
 
        seq_ops = inode->i_private;
@@ -924,7 +940,7 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,
                entry = trace_create_file("enable", 0644, call->dir, call,
                                          enable);
 
-       if (call->id)
+       if (call->id && call->profile_enable)
                entry = trace_create_file("id", 0444, call->dir, call,
                                          id);
 
index 936c621bbf462395cc7f814cd6bbe01d7c841514..f32dc9d1ea7b51bb5c469b7778fc198079f5c499 100644 (file)
@@ -624,9 +624,6 @@ static int filter_add_subsystem_pred(struct filter_parse_state *ps,
                return -ENOSPC;
        }
 
-       filter->preds[filter->n_preds] = pred;
-       filter->n_preds++;
-
        list_for_each_entry(call, &ftrace_events, list) {
 
                if (!call->define_fields)
@@ -643,6 +640,9 @@ static int filter_add_subsystem_pred(struct filter_parse_state *ps,
                }
                replace_filter_string(call->filter, filter_string);
        }
+
+       filter->preds[filter->n_preds] = pred;
+       filter->n_preds++;
 out:
        return err;
 }
@@ -1029,12 +1029,17 @@ static int replace_preds(struct event_subsystem *system,
 
                if (elt->op == OP_AND || elt->op == OP_OR) {
                        pred = create_logical_pred(elt->op);
+                       if (!pred)
+                               return -ENOMEM;
                        if (call) {
                                err = filter_add_pred(ps, call, pred);
                                filter_free_pred(pred);
-                       } else
+                       } else {
                                err = filter_add_subsystem_pred(ps, system,
                                                        pred, filter_string);
+                               if (err)
+                                       filter_free_pred(pred);
+                       }
                        if (err)
                                return err;
 
@@ -1048,12 +1053,17 @@ static int replace_preds(struct event_subsystem *system,
                }
 
                pred = create_pred(elt->op, operand1, operand2);
+               if (!pred)
+                       return -ENOMEM;
                if (call) {
                        err = filter_add_pred(ps, call, pred);
                        filter_free_pred(pred);
-               } else
+               } else {
                        err = filter_add_subsystem_pred(ps, system, pred,
                                                        filter_string);
+                       if (err)
+                               filter_free_pred(pred);
+               }
                if (err)
                        return err;
 
index 90f134764837e80f38d4c4f09caa5ab8ee1ce17a..75ef000613c35db5c7cb8ae71b2f4169f0bfd6d8 100644 (file)
@@ -302,8 +302,7 @@ ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip,
        if (count == -1)
                seq_printf(m, ":unlimited\n");
        else
-               seq_printf(m, ":count=%ld", count);
-       seq_putc(m, '\n');
+               seq_printf(m, ":count=%ld\n", count);
 
        return 0;
 }
@@ -364,7 +363,7 @@ ftrace_trace_onoff_callback(char *glob, char *cmd, char *param, int enable)
  out_reg:
        ret = register_ftrace_function_probe(glob, ops, count);
 
-       return ret;
+       return ret < 0 ? ret : 0;
 }
 
 static struct ftrace_func_command ftrace_traceon_cmd = {
index d2249abafb53ed66430678f99d7d7642962e7d90..420ec34875795e42e3abc403596e4d98e8fb9c25 100644 (file)
@@ -843,9 +843,16 @@ print_graph_function(struct trace_iterator *iter)
 
        switch (entry->type) {
        case TRACE_GRAPH_ENT: {
-               struct ftrace_graph_ent_entry *field;
+               /*
+                * print_graph_entry() may consume the current event,
+                * thus @field may become invalid, so we need to save it.
+                * sizeof(struct ftrace_graph_ent_entry) is very small,
+                * it can be safely saved at the stack.
+                */
+               struct ftrace_graph_ent_entry *field, saved;
                trace_assign_type(field, entry);
-               return print_graph_entry(field, s, iter);
+               saved = *field;
+               return print_graph_entry(&saved, s, iter);
        }
        case TRACE_GRAPH_RET: {
                struct ftrace_graph_ret_entry *field;
index 7938f3ae93e3dbe9d898e037c47027c4908a8d94..e0c2545622e8f7617b3e32bcb8c3df235aa3a929 100644 (file)
@@ -27,8 +27,7 @@ void trace_print_seq(struct seq_file *m, struct trace_seq *s)
 {
        int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len;
 
-       s->buffer[len] = 0;
-       seq_puts(m, s->buffer);
+       seq_write(m, s->buffer, len);
 
        trace_seq_init(s);
 }
index 9bece9687b62a8d2ab6b59199017ef0ad7898b98..687699d365aeb328eddaf619f04ccf10b1cc6b6c 100644 (file)
@@ -155,25 +155,19 @@ int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap)
 EXPORT_SYMBOL_GPL(__ftrace_vprintk);
 
 static void *
-t_next(struct seq_file *m, void *v, loff_t *pos)
+t_start(struct seq_file *m, loff_t *pos)
 {
-       const char **fmt = m->private;
-       const char **next = fmt;
-
-       (*pos)++;
+       const char **fmt = __start___trace_bprintk_fmt + *pos;
 
        if ((unsigned long)fmt >= (unsigned long)__stop___trace_bprintk_fmt)
                return NULL;
-
-       next = fmt;
-       m->private = ++next;
-
        return fmt;
 }
 
-static void *t_start(struct seq_file *m, loff_t *pos)
+static void *t_next(struct seq_file *m, void * v, loff_t *pos)
 {
-       return t_next(m, NULL, pos);
+       (*pos)++;
+       return t_start(m, pos);
 }
 
 static int t_show(struct seq_file *m, void *v)
@@ -182,7 +176,7 @@ static int t_show(struct seq_file *m, void *v)
        const char *str = *fmt;
        int i;
 
-       seq_printf(m, "0x%lx : \"", (unsigned long)fmt);
+       seq_printf(m, "0x%lx : \"", *(unsigned long *)fmt);
 
        /*
         * Tabs and new lines need to be converted.
@@ -224,15 +218,7 @@ static const struct seq_operations show_format_seq_ops = {
 static int
 ftrace_formats_open(struct inode *inode, struct file *file)
 {
-       int ret;
-
-       ret = seq_open(file, &show_format_seq_ops);
-       if (!ret) {
-               struct seq_file *m = file->private_data;
-
-               m->private = __start___trace_bprintk_fmt;
-       }
-       return ret;
+       return seq_open(file, &show_format_seq_ops);
 }
 
 static const struct file_operations ftrace_formats_fops = {
index 2d7aebd71dbd4e3489b8bf59fd29585b422be8e9..6a2a9d484cd6bb950a11b99910649e2cec4c42ff 100644 (file)
@@ -301,17 +301,14 @@ static const struct seq_operations stack_trace_seq_ops = {
 
 static int stack_trace_open(struct inode *inode, struct file *file)
 {
-       int ret;
-
-       ret = seq_open(file, &stack_trace_seq_ops);
-
-       return ret;
+       return seq_open(file, &stack_trace_seq_ops);
 }
 
 static const struct file_operations stack_trace_fops = {
        .open           = stack_trace_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
+       .release        = seq_release,
 };
 
 int
@@ -326,10 +323,10 @@ stack_trace_sysctl(struct ctl_table *table, int write,
        ret = proc_dointvec(table, write, file, buffer, lenp, ppos);
 
        if (ret || !write ||
-           (last_stack_tracer_enabled == stack_tracer_enabled))
+           (last_stack_tracer_enabled == !!stack_tracer_enabled))
                goto out;
 
-       last_stack_tracer_enabled = stack_tracer_enabled;
+       last_stack_tracer_enabled = !!stack_tracer_enabled;
 
        if (stack_tracer_enabled)
                register_ftrace_function(&trace_ops);
index c00643733f4ccca7be15b22ef311ec03711edc48..aea321c82fa098fa01d7b7fd8c7f21ea59ebbf0c 100644 (file)
@@ -73,7 +73,7 @@ static struct rb_node *release_next(struct rb_node *node)
        }
 }
 
-static void reset_stat_session(struct stat_session *session)
+static void __reset_stat_session(struct stat_session *session)
 {
        struct rb_node *node = session->stat_root.rb_node;
 
@@ -83,10 +83,17 @@ static void reset_stat_session(struct stat_session *session)
        session->stat_root = RB_ROOT;
 }
 
+static void reset_stat_session(struct stat_session *session)
+{
+       mutex_lock(&session->stat_mutex);
+       __reset_stat_session(session);
+       mutex_unlock(&session->stat_mutex);
+}
+
 static void destroy_session(struct stat_session *session)
 {
        debugfs_remove(session->file);
-       reset_stat_session(session);
+       __reset_stat_session(session);
        mutex_destroy(&session->stat_mutex);
        kfree(session);
 }
@@ -150,7 +157,7 @@ static int stat_seq_init(struct stat_session *session)
        int i;
 
        mutex_lock(&session->stat_mutex);
-       reset_stat_session(session);
+       __reset_stat_session(session);
 
        if (!ts->stat_cmp)
                ts->stat_cmp = dummy_cmp;
@@ -183,7 +190,7 @@ exit:
        return ret;
 
 exit_free_rbtree:
-       reset_stat_session(session);
+       __reset_stat_session(session);
        mutex_unlock(&session->stat_mutex);
        return ret;
 }
@@ -199,17 +206,13 @@ static void *stat_seq_start(struct seq_file *s, loff_t *pos)
        mutex_lock(&session->stat_mutex);
 
        /* If we are in the beginning of the file, print the headers */
-       if (!*pos && session->ts->stat_headers) {
-               (*pos)++;
+       if (!*pos && session->ts->stat_headers)
                return SEQ_START_TOKEN;
-       }
 
        node = rb_first(&session->stat_root);
        for (i = 0; node && i < *pos; i++)
                node = rb_next(node);
 
-       (*pos)++;
-
        return node;
 }
 
@@ -254,16 +257,21 @@ static const struct seq_operations trace_stat_seq_ops = {
 static int tracing_stat_open(struct inode *inode, struct file *file)
 {
        int ret;
-
+       struct seq_file *m;
        struct stat_session *session = inode->i_private;
 
+       ret = stat_seq_init(session);
+       if (ret)
+               return ret;
+
        ret = seq_open(file, &trace_stat_seq_ops);
-       if (!ret) {
-               struct seq_file *m = file->private_data;
-               m->private = session;
-               ret = stat_seq_init(session);
+       if (ret) {
+               reset_stat_session(session);
+               return ret;
        }
 
+       m = file->private_data;
+       m->private = session;
        return ret;
 }
 
@@ -274,11 +282,9 @@ static int tracing_stat_release(struct inode *i, struct file *f)
 {
        struct stat_session *session = i->i_private;
 
-       mutex_lock(&session->stat_mutex);
        reset_stat_session(session);
-       mutex_unlock(&session->stat_mutex);
 
-       return 0;
+       return seq_release(i, f);
 }
 
 static const struct file_operations tracing_stat_fops = {
index ea7c3b4275cf362f75cee939aa7861f7673b95cc..c4bd3d825f35c8c8dd7ed4831cd5fee5fe6a6b9a 100644 (file)
 #include <linux/wait.h>
 #include <linux/hash.h>
 
-void init_waitqueue_head(wait_queue_head_t *q)
+void __init_waitqueue_head(wait_queue_head_t *q, struct lock_class_key *key)
 {
        spin_lock_init(&q->lock);
+       lockdep_set_class(&q->lock, key);
        INIT_LIST_HEAD(&q->task_list);
 }
 
-EXPORT_SYMBOL(init_waitqueue_head);
+EXPORT_SYMBOL(__init_waitqueue_head);
 
 void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
 {
index 4c32b1a1a06e393ad5d8844cdbefa00994965c2a..12327b2bb785c256a59cb864a2c2b8976c33e5aa 100644 (file)
@@ -359,6 +359,18 @@ config DEBUG_KMEMLEAK
          In order to access the kmemleak file, debugfs needs to be
          mounted (usually at /sys/kernel/debug).
 
+config DEBUG_KMEMLEAK_EARLY_LOG_SIZE
+       int "Maximum kmemleak early log entries"
+       depends on DEBUG_KMEMLEAK
+       range 200 2000
+       default 400
+       help
+         Kmemleak must track all the memory allocations to avoid
+         reporting false positives. Since memory may be allocated or
+         freed before kmemleak is initialised, an early log buffer is
+         used to store these actions. If kmemleak reports "early log
+         buffer exceeded", please increase this value.
+
 config DEBUG_KMEMLEAK_TEST
        tristate "Simple test for the kernel memory leak detector"
        depends on DEBUG_KMEMLEAK
index b6d1857bbf08fd98804e4993cd934b6dbd9812cb..2e78277eff9da8caef24be177ab48ec1ecce7bc5 100644 (file)
@@ -12,7 +12,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
         idr.o int_sqrt.o extable.o prio_tree.o \
         sha1.o irq_regs.o reciprocal_div.o argv_split.o \
         proportions.o prio_heap.o ratelimit.o show_mem.o \
-        is_single_threaded.o plist.o decompress.o
+        is_single_threaded.o plist.o decompress.o flex_array.o
 
 lib-$(CONFIG_MMU) += ioremap.o
 lib-$(CONFIG_SMP) += cpumask.o
index c5e725562416db1c3c161fde093404d280bb991b..8bee16ec75242d756e19dd67a2173520468474db 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/cache.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <asm/atomic.h>
 
 /*
@@ -52,6 +53,7 @@ long long atomic64_read(const atomic64_t *v)
        spin_unlock_irqrestore(lock, flags);
        return val;
 }
+EXPORT_SYMBOL(atomic64_read);
 
 void atomic64_set(atomic64_t *v, long long i)
 {
@@ -62,6 +64,7 @@ void atomic64_set(atomic64_t *v, long long i)
        v->counter = i;
        spin_unlock_irqrestore(lock, flags);
 }
+EXPORT_SYMBOL(atomic64_set);
 
 void atomic64_add(long long a, atomic64_t *v)
 {
@@ -72,6 +75,7 @@ void atomic64_add(long long a, atomic64_t *v)
        v->counter += a;
        spin_unlock_irqrestore(lock, flags);
 }
+EXPORT_SYMBOL(atomic64_add);
 
 long long atomic64_add_return(long long a, atomic64_t *v)
 {
@@ -84,6 +88,7 @@ long long atomic64_add_return(long long a, atomic64_t *v)
        spin_unlock_irqrestore(lock, flags);
        return val;
 }
+EXPORT_SYMBOL(atomic64_add_return);
 
 void atomic64_sub(long long a, atomic64_t *v)
 {
@@ -94,6 +99,7 @@ void atomic64_sub(long long a, atomic64_t *v)
        v->counter -= a;
        spin_unlock_irqrestore(lock, flags);
 }
+EXPORT_SYMBOL(atomic64_sub);
 
 long long atomic64_sub_return(long long a, atomic64_t *v)
 {
@@ -106,6 +112,7 @@ long long atomic64_sub_return(long long a, atomic64_t *v)
        spin_unlock_irqrestore(lock, flags);
        return val;
 }
+EXPORT_SYMBOL(atomic64_sub_return);
 
 long long atomic64_dec_if_positive(atomic64_t *v)
 {
@@ -120,6 +127,7 @@ long long atomic64_dec_if_positive(atomic64_t *v)
        spin_unlock_irqrestore(lock, flags);
        return val;
 }
+EXPORT_SYMBOL(atomic64_dec_if_positive);
 
 long long atomic64_cmpxchg(atomic64_t *v, long long o, long long n)
 {
@@ -134,6 +142,7 @@ long long atomic64_cmpxchg(atomic64_t *v, long long o, long long n)
        spin_unlock_irqrestore(lock, flags);
        return val;
 }
+EXPORT_SYMBOL(atomic64_cmpxchg);
 
 long long atomic64_xchg(atomic64_t *v, long long new)
 {
@@ -147,6 +156,7 @@ long long atomic64_xchg(atomic64_t *v, long long new)
        spin_unlock_irqrestore(lock, flags);
        return val;
 }
+EXPORT_SYMBOL(atomic64_xchg);
 
 int atomic64_add_unless(atomic64_t *v, long long a, long long u)
 {
@@ -162,6 +172,7 @@ int atomic64_add_unless(atomic64_t *v, long long a, long long u)
        spin_unlock_irqrestore(lock, flags);
        return ret;
 }
+EXPORT_SYMBOL(atomic64_add_unless);
 
 static int init_atomic64_lock(void)
 {
index 35a1f7ff414988d86c6c081d7bbf3671733a15d6..702565821c9976fb4588dac793d84008bf93b229 100644 (file)
@@ -179,14 +179,16 @@ void __bitmap_shift_left(unsigned long *dst,
 }
 EXPORT_SYMBOL(__bitmap_shift_left);
 
-void __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
+int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
                                const unsigned long *bitmap2, int bits)
 {
        int k;
        int nr = BITS_TO_LONGS(bits);
+       unsigned long result = 0;
 
        for (k = 0; k < nr; k++)
-               dst[k] = bitmap1[k] & bitmap2[k];
+               result |= (dst[k] = bitmap1[k] & bitmap2[k]);
+       return result != 0;
 }
 EXPORT_SYMBOL(__bitmap_and);
 
@@ -212,14 +214,16 @@ void __bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
 }
 EXPORT_SYMBOL(__bitmap_xor);
 
-void __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
+int __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
                                const unsigned long *bitmap2, int bits)
 {
        int k;
        int nr = BITS_TO_LONGS(bits);
+       unsigned long result = 0;
 
        for (k = 0; k < nr; k++)
-               dst[k] = bitmap1[k] & ~bitmap2[k];
+               result |= (dst[k] = bitmap1[k] & ~bitmap2[k]);
+       return result != 0;
 }
 EXPORT_SYMBOL(__bitmap_andnot);
 
index 708e2a86d87be8b8cc19cff2dd4671293eabb555..600f473a5610a5fb8ccf90b84089fc029d7b412b 100644 (file)
 */
 
 
-#ifndef STATIC
+#ifdef STATIC
+#define PREBOOT
+#else
 #include <linux/decompress/bunzip2.h>
-#endif /* !STATIC */
+#include <linux/slab.h>
+#endif /* STATIC */
 
 #include <linux/decompress/mm.h>
-#include <linux/slab.h>
 
 #ifndef INT_MAX
 #define INT_MAX 0x7fffffff
@@ -681,9 +683,7 @@ STATIC int INIT bunzip2(unsigned char *buf, int len,
        set_error_fn(error_fn);
        if (flush)
                outbuf = malloc(BZIP2_IOBUF_SIZE);
-       else
-               len -= 4; /* Uncompressed size hack active in pre-boot
-                            environment */
+
        if (!outbuf) {
                error("Could not allocate output bufer");
                return -1;
@@ -733,4 +733,14 @@ exit_0:
        return i;
 }
 
-#define decompress bunzip2
+#ifdef PREBOOT
+STATIC int INIT decompress(unsigned char *buf, int len,
+                       int(*fill)(void*, unsigned int),
+                       int(*flush)(void*, unsigned int),
+                       unsigned char *outbuf,
+                       int *pos,
+                       void(*error_fn)(char *x))
+{
+       return bunzip2(buf, len - 4, fill, flush, outbuf, pos, error_fn);
+}
+#endif
index e36b296fc9f8e5819ca461ab99b4f476b73328ba..68dfce59c1b80be510544c0effc3f87669527b8f 100644 (file)
 #include "zlib_inflate/inflate.h"
 
 #include "zlib_inflate/infutil.h"
+#include <linux/slab.h>
 
 #endif /* STATIC */
 
 #include <linux/decompress/mm.h>
-#include <linux/slab.h>
 
-#define INBUF_LEN (16*1024)
+#define GZIP_IOBUF_SIZE (16*1024)
 
 /* Included from initramfs et al code */
 STATIC int INIT gunzip(unsigned char *buf, int len,
@@ -55,7 +55,7 @@ STATIC int INIT gunzip(unsigned char *buf, int len,
        if (buf)
                zbuf = buf;
        else {
-               zbuf = malloc(INBUF_LEN);
+               zbuf = malloc(GZIP_IOBUF_SIZE);
                len = 0;
        }
        if (!zbuf) {
@@ -77,7 +77,7 @@ STATIC int INIT gunzip(unsigned char *buf, int len,
        }
 
        if (len == 0)
-               len = fill(zbuf, INBUF_LEN);
+               len = fill(zbuf, GZIP_IOBUF_SIZE);
 
        /* verify the gzip header */
        if (len < 10 ||
@@ -113,7 +113,7 @@ STATIC int INIT gunzip(unsigned char *buf, int len,
        while (rc == Z_OK) {
                if (strm->avail_in == 0) {
                        /* TODO: handle case where both pos and fill are set */
-                       len = fill(zbuf, INBUF_LEN);
+                       len = fill(zbuf, GZIP_IOBUF_SIZE);
                        if (len < 0) {
                                rc = -1;
                                error("read error");
index 32123a1340e6bdb2125004def332daa5499c02f7..0b954e04bd3015bb08332b2a30a13e1ff6414fea 100644 (file)
  *Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#ifndef STATIC
+#ifdef STATIC
+#define PREBOOT
+#else
 #include <linux/decompress/unlzma.h>
+#include <linux/slab.h>
 #endif /* STATIC */
 
 #include <linux/decompress/mm.h>
-#include <linux/slab.h>
 
 #define        MIN(a, b) (((a) < (b)) ? (a) : (b))
 
@@ -543,9 +545,7 @@ STATIC inline int INIT unlzma(unsigned char *buf, int in_len,
        int ret = -1;
 
        set_error_fn(error_fn);
-       if (!flush)
-               in_len -= 4; /* Uncompressed size hack active in pre-boot
-                               environment */
+
        if (buf)
                inbuf = buf;
        else
@@ -645,4 +645,15 @@ exit_0:
        return ret;
 }
 
-#define decompress unlzma
+#ifdef PREBOOT
+STATIC int INIT decompress(unsigned char *buf, int in_len,
+                             int(*fill)(void*, unsigned int),
+                             int(*flush)(void*, unsigned int),
+                             unsigned char *output,
+                             int *posp,
+                             void(*error_fn)(char *x)
+       )
+{
+       return unlzma(buf, in_len - 4, fill, flush, output, posp, error_fn);
+}
+#endif
index 3b93129a968c73b1d6eeff421abb76b38bc668dd..58a9f9fc609afaf561aa582b9d14270fe2cb3872 100644 (file)
@@ -156,9 +156,13 @@ static bool driver_filter(struct device *dev)
                return true;
 
        /* driver filter on and initialized */
-       if (current_driver && dev->driver == current_driver)
+       if (current_driver && dev && dev->driver == current_driver)
                return true;
 
+       /* driver filter on, but we can't filter on a NULL device... */
+       if (!dev)
+               return false;
+
        if (current_driver || !current_driver_name[0])
                return false;
 
@@ -183,17 +187,17 @@ static bool driver_filter(struct device *dev)
        return ret;
 }
 
-#define err_printk(dev, entry, format, arg...) do {            \
-               error_count += 1;                               \
-               if (driver_filter(dev) &&                       \
-                   (show_all_errors || show_num_errors > 0)) { \
-                       WARN(1, "%s %s: " format,               \
-                            dev_driver_string(dev),            \
-                            dev_name(dev) , ## arg);           \
-                       dump_entry_trace(entry);                \
-               }                                               \
-               if (!show_all_errors && show_num_errors > 0)    \
-                       show_num_errors -= 1;                   \
+#define err_printk(dev, entry, format, arg...) do {                    \
+               error_count += 1;                                       \
+               if (driver_filter(dev) &&                               \
+                   (show_all_errors || show_num_errors > 0)) {         \
+                       WARN(1, "%s %s: " format,                       \
+                            dev ? dev_driver_string(dev) : "NULL",     \
+                            dev ? dev_name(dev) : "NULL", ## arg);     \
+                       dump_entry_trace(entry);                        \
+               }                                                       \
+               if (!show_all_errors && show_num_errors > 0)            \
+                       show_num_errors -= 1;                           \
        } while (0);
 
 /*
@@ -716,7 +720,7 @@ void dma_debug_init(u32 num_entries)
 
        for (i = 0; i < HASH_SIZE; ++i) {
                INIT_LIST_HEAD(&dma_entry_hash[i].list);
-               dma_entry_hash[i].lock = SPIN_LOCK_UNLOCKED;
+               spin_lock_init(&dma_entry_hash[i].lock);
        }
 
        if (dma_debug_fs_init() != 0) {
@@ -856,22 +860,21 @@ static void check_for_stack(struct device *dev, void *addr)
                                "stack [addr=%p]\n", addr);
 }
 
-static inline bool overlap(void *addr, u64 size, void *start, void *end)
+static inline bool overlap(void *addr, unsigned long len, void *start, void *end)
 {
-       void *addr2 = (char *)addr + size;
+       unsigned long a1 = (unsigned long)addr;
+       unsigned long b1 = a1 + len;
+       unsigned long a2 = (unsigned long)start;
+       unsigned long b2 = (unsigned long)end;
 
-       return ((addr >= start && addr < end) ||
-               (addr2 >= start && addr2 < end) ||
-               ((addr < start) && (addr2 >= end)));
+       return !(b1 <= a2 || a1 >= b2);
 }
 
-static void check_for_illegal_area(struct device *dev, void *addr, u64 size)
+static void check_for_illegal_area(struct device *dev, void *addr, unsigned long len)
 {
-       if (overlap(addr, size, _text, _etext) ||
-           overlap(addr, size, __start_rodata, __end_rodata))
-               err_printk(dev, NULL, "DMA-API: device driver maps "
-                               "memory from kernel text or rodata "
-                               "[addr=%p] [size=%llu]\n", addr, size);
+       if (overlap(addr, len, _text, _etext) ||
+           overlap(addr, len, __start_rodata, __end_rodata))
+               err_printk(dev, NULL, "DMA-API: device driver maps memory from kernel text or rodata [addr=%p] [len=%lu]\n", addr, len);
 }
 
 static void check_sync(struct device *dev,
@@ -969,7 +972,8 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
                entry->type = dma_debug_single;
 
        if (!PageHighMem(page)) {
-               void *addr = ((char *)page_address(page)) + offset;
+               void *addr = page_address(page) + offset;
+
                check_for_stack(dev, addr);
                check_for_illegal_area(dev, addr, size);
        }
index 833139ce1e225cc1bef2286b3e04d2133219f8ef..e22c148e4b7fff7605e605689561df66d018c6fa 100644 (file)
@@ -164,7 +164,7 @@ static void ddebug_change(const struct ddebug_query *query,
 
                        if (!newflags)
                                dt->num_enabled--;
-                       else if (!dp-flags)
+                       else if (!dp->flags)
                                dt->num_enabled++;
                        dp->flags = newflags;
                        if (newflags) {
diff --git a/lib/flex_array.c b/lib/flex_array.c
new file mode 100644 (file)
index 0000000..7baed2f
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Flexible array managed in PAGE_SIZE parts
+ *
+ * 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.
+ *
+ * Copyright IBM Corporation, 2009
+ *
+ * Author: Dave Hansen <dave@linux.vnet.ibm.com>
+ */
+
+#include <linux/flex_array.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+
+struct flex_array_part {
+       char elements[FLEX_ARRAY_PART_SIZE];
+};
+
+static inline int __elements_per_part(int element_size)
+{
+       return FLEX_ARRAY_PART_SIZE / element_size;
+}
+
+static inline int bytes_left_in_base(void)
+{
+       int element_offset = offsetof(struct flex_array, parts);
+       int bytes_left = FLEX_ARRAY_BASE_SIZE - element_offset;
+       return bytes_left;
+}
+
+static inline int nr_base_part_ptrs(void)
+{
+       return bytes_left_in_base() / sizeof(struct flex_array_part *);
+}
+
+/*
+ * If a user requests an allocation which is small
+ * enough, we may simply use the space in the
+ * flex_array->parts[] array to store the user
+ * data.
+ */
+static inline int elements_fit_in_base(struct flex_array *fa)
+{
+       int data_size = fa->element_size * fa->total_nr_elements;
+       if (data_size <= bytes_left_in_base())
+               return 1;
+       return 0;
+}
+
+/**
+ * flex_array_alloc - allocate a new flexible array
+ * @element_size:      the size of individual elements in the array
+ * @total:             total number of elements that this should hold
+ *
+ * Note: all locking must be provided by the caller.
+ *
+ * @total is used to size internal structures.  If the user ever
+ * accesses any array indexes >=@total, it will produce errors.
+ *
+ * The maximum number of elements is defined as: the number of
+ * elements that can be stored in a page times the number of
+ * page pointers that we can fit in the base structure or (using
+ * integer math):
+ *
+ *     (PAGE_SIZE/element_size) * (PAGE_SIZE-8)/sizeof(void *)
+ *
+ * Here's a table showing example capacities.  Note that the maximum
+ * index that the get/put() functions is just nr_objects-1.   This
+ * basically means that you get 4MB of storage on 32-bit and 2MB on
+ * 64-bit.
+ *
+ *
+ * Element size | Objects | Objects |
+ * PAGE_SIZE=4k |  32-bit |  64-bit |
+ * ---------------------------------|
+ *      1 bytes | 4186112 | 2093056 |
+ *      2 bytes | 2093056 | 1046528 |
+ *      3 bytes | 1395030 |  697515 |
+ *      4 bytes | 1046528 |  523264 |
+ *     32 bytes |  130816 |   65408 |
+ *     33 bytes |  126728 |   63364 |
+ *   2048 bytes |    2044 |    1022 |
+ *   2049 bytes |    1022 |     511 |
+ *       void * | 1046528 |  261632 |
+ *
+ * Since 64-bit pointers are twice the size, we lose half the
+ * capacity in the base structure.  Also note that no effort is made
+ * to efficiently pack objects across page boundaries.
+ */
+struct flex_array *flex_array_alloc(int element_size, unsigned int total,
+                                       gfp_t flags)
+{
+       struct flex_array *ret;
+       int max_size = nr_base_part_ptrs() * __elements_per_part(element_size);
+
+       /* max_size will end up 0 if element_size > PAGE_SIZE */
+       if (total > max_size)
+               return NULL;
+       ret = kzalloc(sizeof(struct flex_array), flags);
+       if (!ret)
+               return NULL;
+       ret->element_size = element_size;
+       ret->total_nr_elements = total;
+       return ret;
+}
+
+static int fa_element_to_part_nr(struct flex_array *fa,
+                                       unsigned int element_nr)
+{
+       return element_nr / __elements_per_part(fa->element_size);
+}
+
+/**
+ * flex_array_free_parts - just free the second-level pages
+ *
+ * This is to be used in cases where the base 'struct flex_array'
+ * has been statically allocated and should not be free.
+ */
+void flex_array_free_parts(struct flex_array *fa)
+{
+       int part_nr;
+       int max_part = nr_base_part_ptrs();
+
+       if (elements_fit_in_base(fa))
+               return;
+       for (part_nr = 0; part_nr < max_part; part_nr++)
+               kfree(fa->parts[part_nr]);
+}
+
+void flex_array_free(struct flex_array *fa)
+{
+       flex_array_free_parts(fa);
+       kfree(fa);
+}
+
+static unsigned int index_inside_part(struct flex_array *fa,
+                                       unsigned int element_nr)
+{
+       unsigned int part_offset;
+
+       part_offset = element_nr % __elements_per_part(fa->element_size);
+       return part_offset * fa->element_size;
+}
+
+static struct flex_array_part *
+__fa_get_part(struct flex_array *fa, int part_nr, gfp_t flags)
+{
+       struct flex_array_part *part = fa->parts[part_nr];
+       if (!part) {
+               /*
+                * This leaves the part pages uninitialized
+                * and with potentially random data, just
+                * as if the user had kmalloc()'d the whole.
+                * __GFP_ZERO can be used to zero it.
+                */
+               part = kmalloc(FLEX_ARRAY_PART_SIZE, flags);
+               if (!part)
+                       return NULL;
+               fa->parts[part_nr] = part;
+       }
+       return part;
+}
+
+/**
+ * flex_array_put - copy data into the array at @element_nr
+ * @src:       address of data to copy into the array
+ * @element_nr:        index of the position in which to insert
+ *             the new element.
+ *
+ * Note that this *copies* the contents of @src into
+ * the array.  If you are trying to store an array of
+ * pointers, make sure to pass in &ptr instead of ptr.
+ *
+ * Locking must be provided by the caller.
+ */
+int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src,
+                       gfp_t flags)
+{
+       int part_nr = fa_element_to_part_nr(fa, element_nr);
+       struct flex_array_part *part;
+       void *dst;
+
+       if (element_nr >= fa->total_nr_elements)
+               return -ENOSPC;
+       if (elements_fit_in_base(fa))
+               part = (struct flex_array_part *)&fa->parts[0];
+       else {
+               part = __fa_get_part(fa, part_nr, flags);
+               if (!part)
+                       return -ENOMEM;
+       }
+       dst = &part->elements[index_inside_part(fa, element_nr)];
+       memcpy(dst, src, fa->element_size);
+       return 0;
+}
+
+/**
+ * flex_array_prealloc - guarantee that array space exists
+ * @start:     index of first array element for which space is allocated
+ * @end:       index of last (inclusive) element for which space is allocated
+ *
+ * This will guarantee that no future calls to flex_array_put()
+ * will allocate memory.  It can be used if you are expecting to
+ * be holding a lock or in some atomic context while writing
+ * data into the array.
+ *
+ * Locking must be provided by the caller.
+ */
+int flex_array_prealloc(struct flex_array *fa, unsigned int start,
+                       unsigned int end, gfp_t flags)
+{
+       int start_part;
+       int end_part;
+       int part_nr;
+       struct flex_array_part *part;
+
+       if (start >= fa->total_nr_elements || end >= fa->total_nr_elements)
+               return -ENOSPC;
+       if (elements_fit_in_base(fa))
+               return 0;
+       start_part = fa_element_to_part_nr(fa, start);
+       end_part = fa_element_to_part_nr(fa, end);
+       for (part_nr = start_part; part_nr <= end_part; part_nr++) {
+               part = __fa_get_part(fa, part_nr, flags);
+               if (!part)
+                       return -ENOMEM;
+       }
+       return 0;
+}
+
+/**
+ * flex_array_get - pull data back out of the array
+ * @element_nr:        index of the element to fetch from the array
+ *
+ * Returns a pointer to the data at index @element_nr.  Note
+ * that this is a copy of the data that was passed in.  If you
+ * are using this to store pointers, you'll get back &ptr.
+ *
+ * Locking must be provided by the caller.
+ */
+void *flex_array_get(struct flex_array *fa, unsigned int element_nr)
+{
+       int part_nr = fa_element_to_part_nr(fa, element_nr);
+       struct flex_array_part *part;
+
+       if (element_nr >= fa->total_nr_elements)
+               return NULL;
+       if (elements_fit_in_base(fa))
+               part = (struct flex_array_part *)&fa->parts[0];
+       else {
+               part = fa->parts[part_nr];
+               if (!part)
+                       return NULL;
+       }
+       return &part->elements[index_inside_part(fa, element_nr)];
+}
index e4a6482d8b26e5034805a401905480974e6dcd8c..0343c05609f0d62f9b48b259bf3018db728b11a5 100644 (file)
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -429,7 +429,7 @@ u64 __init lmb_phys_mem_size(void)
        return lmb.memory.size;
 }
 
-u64 __init lmb_end_of_DRAM(void)
+u64 lmb_end_of_DRAM(void)
 {
        int idx = lmb.memory.cnt - 1;
 
index a295e404e9087edc5eb5dff3d4a9746c07f59e63..0d475d8167bfd7f4f9909424ea29a72653b581fe 100644 (file)
@@ -314,6 +314,7 @@ void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl,
        miter->__sg = sgl;
        miter->__nents = nents;
        miter->__offset = 0;
+       WARN_ON(!(flags & (SG_MITER_TO_SG | SG_MITER_FROM_SG)));
        miter->__flags = flags;
 }
 EXPORT_SYMBOL(sg_miter_start);
@@ -394,6 +395,9 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
        if (miter->addr) {
                miter->__offset += miter->consumed;
 
+               if (miter->__flags & SG_MITER_TO_SG)
+                       flush_kernel_dcache_page(miter->page);
+
                if (miter->__flags & SG_MITER_ATOMIC) {
                        WARN_ON(!irqs_disabled());
                        kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ);
@@ -426,8 +430,14 @@ static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
        unsigned int offset = 0;
        struct sg_mapping_iter miter;
        unsigned long flags;
+       unsigned int sg_flags = SG_MITER_ATOMIC;
+
+       if (to_buffer)
+               sg_flags |= SG_MITER_FROM_SG;
+       else
+               sg_flags |= SG_MITER_TO_SG;
 
-       sg_miter_start(&miter, sgl, nents, SG_MITER_ATOMIC);
+       sg_miter_start(&miter, sgl, nents, sg_flags);
 
        local_irq_save(flags);
 
@@ -438,10 +448,8 @@ static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
 
                if (to_buffer)
                        memcpy(buf + offset, miter.addr, len);
-               else {
+               else
                        memcpy(miter.addr, buf + offset, len);
-                       flush_kernel_dcache_page(miter.page);
-               }
 
                offset += len;
        }
index c948d4ca8bde0dc0d73ba1c40b984d395a73b4d8..fe5f674d7a7d571a1f456d2df3d5a31bb965db2e 100644 (file)
@@ -225,9 +225,9 @@ config DEFAULT_MMAP_MIN_ADDR
          For most ia64, ppc64 and x86 users with lots of address space
          a value of 65536 is reasonable and should cause no problems.
          On arm and other archs it should not be higher than 32768.
-         Programs which use vm86 functionality would either need additional
-         permissions from either the LSM or the capabilities module or have
-         this protection disabled.
+         Programs which use vm86 functionality or have some need to map
+         this low address space will need CAP_SYS_RAWIO or disable this
+         protection by setting the value to 0.
 
          This value can be changed after boot using the
          /proc/sys/vm/mmap_min_addr tunable.
index 493b468a503541fd65b64872eece6fb7228e36fa..c86edd2442944ec2532bdde3e2087b56519a224d 100644 (file)
@@ -283,7 +283,6 @@ static wait_queue_head_t congestion_wqh[2] = {
                __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1])
        };
 
-
 void clear_bdi_congested(struct backing_dev_info *bdi, int sync)
 {
        enum bdi_state bit;
@@ -308,18 +307,18 @@ EXPORT_SYMBOL(set_bdi_congested);
 
 /**
  * congestion_wait - wait for a backing_dev to become uncongested
- * @rw: READ or WRITE
+ * @sync: SYNC or ASYNC IO
  * @timeout: timeout in jiffies
  *
  * Waits for up to @timeout jiffies for a backing_dev (any backing_dev) to exit
  * write congestion.  If no backing_devs are congested then just wait for the
  * next write to be completed.
  */
-long congestion_wait(int rw, long timeout)
+long congestion_wait(int sync, long timeout)
 {
        long ret;
        DEFINE_WAIT(wait);
-       wait_queue_head_t *wqh = &congestion_wqh[rw];
+       wait_queue_head_t *wqh = &congestion_wqh[sync];
 
        prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
        ret = io_schedule_timeout(timeout);
index d2a9ce952768fbcb88f559077d9878cb15e1d03c..701740c9e81bdf967062b340e53cff8b7913427a 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/pfn.h>
 #include <linux/bootmem.h>
 #include <linux/module.h>
+#include <linux/kmemleak.h>
 
 #include <asm/bug.h>
 #include <asm/io.h>
@@ -335,6 +336,8 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
 {
        unsigned long start, end;
 
+       kmemleak_free_part(__va(physaddr), size);
+
        start = PFN_UP(physaddr);
        end = PFN_DOWN(physaddr + size);
 
@@ -354,6 +357,8 @@ void __init free_bootmem(unsigned long addr, unsigned long size)
 {
        unsigned long start, end;
 
+       kmemleak_free_part(__va(addr), size);
+
        start = PFN_UP(addr);
        end = PFN_DOWN(addr + size);
 
@@ -516,6 +521,7 @@ find_block:
                region = phys_to_virt(PFN_PHYS(bdata->node_min_pfn) +
                                start_off);
                memset(region, 0, size);
+               kmemleak_alloc(region, size, 1, 0);
                return region;
        }
 
index b1f0885dda2275b09baa7d82205f6529efd093b1..3df063706f53e6d579ec0acabace3503a471ba29 100644 (file)
@@ -86,10 +86,12 @@ show_pools(struct device *dev, struct device_attribute *attr, char *buf)
                unsigned pages = 0;
                unsigned blocks = 0;
 
+               spin_lock_irq(&pool->lock);
                list_for_each_entry(page, &pool->page_list, page_list) {
                        pages++;
                        blocks += page->in_use;
                }
+               spin_unlock_irq(&pool->lock);
 
                /* per-pool info, no real statistics yet */
                temp = scnprintf(next, size, "%-16s %4u %4Zu %4Zu %2u\n",
index 22396713feb9684647aa5c90a3b18e6661b2f798..ccea3b665c12571ac32d6d936b3862e103f7b995 100644 (file)
@@ -2272,6 +2272,7 @@ again:
                pagefault_enable();
                flush_dcache_page(page);
 
+               mark_page_accessed(page);
                status = a_ops->write_end(file, mapping, pos, bytes, copied,
                                                page, fsdata);
                if (unlikely(status < 0))
index d0351e31f474aa15a275c303b2f797e5d437c226..cafdcee154e8dba53fbc15806b623a2fb131376e 100644 (file)
@@ -2370,7 +2370,7 @@ void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
        long chg = region_truncate(&inode->i_mapping->private_list, offset);
 
        spin_lock(&inode->i_lock);
-       inode->i_blocks -= blocks_per_huge_page(h);
+       inode->i_blocks -= (blocks_per_huge_page(h) * freed);
        spin_unlock(&inode->i_lock);
 
        hugetlb_put_quota(inode->i_mapping, (chg - freed));
index c96f2c8700aa687f5726eaed2e26a5ccd9d35d87..487267310a8447a175ede900f69c35ca55d63dba 100644 (file)
  *   scanned. This list is only modified during a scanning episode when the
  *   scan_mutex is held. At the end of a scan, the gray_list is always empty.
  *   Note that the kmemleak_object.use_count is incremented when an object is
- *   added to the gray_list and therefore cannot be freed
- * - kmemleak_mutex (mutex): prevents multiple users of the "kmemleak" debugfs
- *   file together with modifications to the memory scanning parameters
- *   including the scan_thread pointer
+ *   added to the gray_list and therefore cannot be freed. This mutex also
+ *   prevents multiple users of the "kmemleak" debugfs file together with
+ *   modifications to the memory scanning parameters including the scan_thread
+ *   pointer
  *
  * The kmemleak_object structures have a use_count incremented or decremented
  * using the get_object()/put_object() functions. When the use_count becomes
  * Kmemleak configuration and common defines.
  */
 #define MAX_TRACE              16      /* stack trace length */
-#define REPORTS_NR             50      /* maximum number of reported leaks */
 #define MSECS_MIN_AGE          5000    /* minimum object age for reporting */
-#define MSECS_SCAN_YIELD       10      /* CPU yielding period */
 #define SECS_FIRST_SCAN                60      /* delay before the first scan */
 #define SECS_SCAN_WAIT         600     /* subsequent auto scanning delay */
+#define GRAY_LIST_PASSES       25      /* maximum number of gray list scans */
 
 #define BYTES_PER_POINTER      sizeof(void *)
 
@@ -159,6 +158,8 @@ struct kmemleak_object {
 #define OBJECT_REPORTED                (1 << 1)
 /* flag set to not scan the object */
 #define OBJECT_NO_SCAN         (1 << 2)
+/* flag set on newly allocated objects */
+#define OBJECT_NEW             (1 << 3)
 
 /* the list of all allocated objects */
 static LIST_HEAD(object_list);
@@ -186,22 +187,16 @@ static atomic_t kmemleak_error = ATOMIC_INIT(0);
 static unsigned long min_addr = ULONG_MAX;
 static unsigned long max_addr;
 
-/* used for yielding the CPU to other tasks during scanning */
-static unsigned long next_scan_yield;
 static struct task_struct *scan_thread;
-static unsigned long jiffies_scan_yield;
+/* used to avoid reporting of recently allocated objects */
 static unsigned long jiffies_min_age;
+static unsigned long jiffies_last_scan;
 /* delay between automatic memory scannings */
 static signed long jiffies_scan_wait;
 /* enables or disables the task stacks scanning */
-static int kmemleak_stack_scan;
-/* mutex protecting the memory scanning */
+static int kmemleak_stack_scan = 1;
+/* protects the memory scanning, parameters and debug/kmemleak file access */
 static DEFINE_MUTEX(scan_mutex);
-/* mutex protecting the access to the /sys/kernel/debug/kmemleak file */
-static DEFINE_MUTEX(kmemleak_mutex);
-
-/* number of leaks reported (for limitation purposes) */
-static int reported_leaks;
 
 /*
  * Early object allocation/freeing logging. Kmemleak is initialized after the
@@ -215,6 +210,7 @@ static int reported_leaks;
 enum {
        KMEMLEAK_ALLOC,
        KMEMLEAK_FREE,
+       KMEMLEAK_FREE_PART,
        KMEMLEAK_NOT_LEAK,
        KMEMLEAK_IGNORE,
        KMEMLEAK_SCAN_AREA,
@@ -235,7 +231,7 @@ struct early_log {
 };
 
 /* early logging buffer and current position */
-static struct early_log early_log[200];
+static struct early_log early_log[CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE];
 static int crt_early_log;
 
 static void kmemleak_disable(void);
@@ -278,13 +274,9 @@ static int color_gray(const struct kmemleak_object *object)
        return object->min_count != -1 && object->count >= object->min_count;
 }
 
-/*
- * Objects are considered referenced if their color is gray and they have not
- * been deleted.
- */
-static int referenced_object(struct kmemleak_object *object)
+static int color_black(const struct kmemleak_object *object)
 {
-       return (object->flags & OBJECT_ALLOCATED) && color_gray(object);
+       return object->min_count == -1;
 }
 
 /*
@@ -295,42 +287,28 @@ static int referenced_object(struct kmemleak_object *object)
 static int unreferenced_object(struct kmemleak_object *object)
 {
        return (object->flags & OBJECT_ALLOCATED) && color_white(object) &&
-               time_is_before_eq_jiffies(object->jiffies + jiffies_min_age);
+               time_before_eq(object->jiffies + jiffies_min_age,
+                              jiffies_last_scan);
 }
 
 /*
- * Printing of the (un)referenced objects information, either to the seq file
- * or to the kernel log. The print_referenced/print_unreferenced functions
- * must be called with the object->lock held.
+ * Printing of the unreferenced objects information to the seq file. The
+ * print_unreferenced function must be called with the object->lock held.
  */
-#define print_helper(seq, x...)        do {    \
-       struct seq_file *s = (seq);     \
-       if (s)                          \
-               seq_printf(s, x);       \
-       else                            \
-               pr_info(x);             \
-} while (0)
-
-static void print_referenced(struct kmemleak_object *object)
-{
-       pr_info("referenced object 0x%08lx (size %zu)\n",
-               object->pointer, object->size);
-}
-
 static void print_unreferenced(struct seq_file *seq,
                               struct kmemleak_object *object)
 {
        int i;
 
-       print_helper(seq, "unreferenced object 0x%08lx (size %zu):\n",
-                    object->pointer, object->size);
-       print_helper(seq, "  comm \"%s\", pid %d, jiffies %lu\n",
-                    object->comm, object->pid, object->jiffies);
-       print_helper(seq, "  backtrace:\n");
+       seq_printf(seq, "unreferenced object 0x%08lx (size %zu):\n",
+                  object->pointer, object->size);
+       seq_printf(seq, "  comm \"%s\", pid %d, jiffies %lu\n",
+                  object->comm, object->pid, object->jiffies);
+       seq_printf(seq, "  backtrace:\n");
 
        for (i = 0; i < object->trace_len; i++) {
                void *ptr = (void *)object->trace[i];
-               print_helper(seq, "    [<%p>] %pS\n", ptr, ptr);
+               seq_printf(seq, "    [<%p>] %pS\n", ptr, ptr);
        }
 }
 
@@ -478,7 +456,7 @@ static void create_object(unsigned long ptr, size_t size, int min_count,
        INIT_HLIST_HEAD(&object->area_list);
        spin_lock_init(&object->lock);
        atomic_set(&object->use_count, 1);
-       object->flags = OBJECT_ALLOCATED;
+       object->flags = OBJECT_ALLOCATED | OBJECT_NEW;
        object->pointer = ptr;
        object->size = size;
        object->min_count = min_count;
@@ -546,38 +524,86 @@ out:
  * Remove the metadata (struct kmemleak_object) for a memory block from the
  * object_list and object_tree_root and decrement its use_count.
  */
-static void delete_object(unsigned long ptr)
+static void __delete_object(struct kmemleak_object *object)
 {
        unsigned long flags;
-       struct kmemleak_object *object;
 
        write_lock_irqsave(&kmemleak_lock, flags);
-       object = lookup_object(ptr, 0);
-       if (!object) {
-               kmemleak_warn("Freeing unknown object at 0x%08lx\n",
-                             ptr);
-               write_unlock_irqrestore(&kmemleak_lock, flags);
-               return;
-       }
        prio_tree_remove(&object_tree_root, &object->tree_node);
        list_del_rcu(&object->object_list);
        write_unlock_irqrestore(&kmemleak_lock, flags);
 
        WARN_ON(!(object->flags & OBJECT_ALLOCATED));
-       WARN_ON(atomic_read(&object->use_count) < 1);
+       WARN_ON(atomic_read(&object->use_count) < 2);
 
        /*
         * Locking here also ensures that the corresponding memory block
         * cannot be freed when it is being scanned.
         */
        spin_lock_irqsave(&object->lock, flags);
-       if (object->flags & OBJECT_REPORTED)
-               print_referenced(object);
        object->flags &= ~OBJECT_ALLOCATED;
        spin_unlock_irqrestore(&object->lock, flags);
        put_object(object);
 }
 
+/*
+ * Look up the metadata (struct kmemleak_object) corresponding to ptr and
+ * delete it.
+ */
+static void delete_object_full(unsigned long ptr)
+{
+       struct kmemleak_object *object;
+
+       object = find_and_get_object(ptr, 0);
+       if (!object) {
+#ifdef DEBUG
+               kmemleak_warn("Freeing unknown object at 0x%08lx\n",
+                             ptr);
+#endif
+               return;
+       }
+       __delete_object(object);
+       put_object(object);
+}
+
+/*
+ * Look up the metadata (struct kmemleak_object) corresponding to ptr and
+ * delete it. If the memory block is partially freed, the function may create
+ * additional metadata for the remaining parts of the block.
+ */
+static void delete_object_part(unsigned long ptr, size_t size)
+{
+       struct kmemleak_object *object;
+       unsigned long start, end;
+
+       object = find_and_get_object(ptr, 1);
+       if (!object) {
+#ifdef DEBUG
+               kmemleak_warn("Partially freeing unknown object at 0x%08lx "
+                             "(size %zu)\n", ptr, size);
+#endif
+               return;
+       }
+       __delete_object(object);
+
+       /*
+        * Create one or two objects that may result from the memory block
+        * split. Note that partial freeing is only done by free_bootmem() and
+        * this happens before kmemleak_init() is called. The path below is
+        * only executed during early log recording in kmemleak_init(), so
+        * GFP_KERNEL is enough.
+        */
+       start = object->pointer;
+       end = object->pointer + object->size;
+       if (ptr > start)
+               create_object(start, ptr - start, object->min_count,
+                             GFP_KERNEL);
+       if (ptr + size < end)
+               create_object(ptr + size, end - ptr - size, object->min_count,
+                             GFP_KERNEL);
+
+       put_object(object);
+}
 /*
  * Make a object permanently as gray-colored so that it can no longer be
  * reported as a leak. This is used in general to mark a false positive.
@@ -696,7 +722,8 @@ static void log_early(int op_type, const void *ptr, size_t size,
        struct early_log *log;
 
        if (crt_early_log >= ARRAY_SIZE(early_log)) {
-               kmemleak_stop("Early log buffer exceeded\n");
+               pr_warning("Early log buffer exceeded\n");
+               kmemleak_disable();
                return;
        }
 
@@ -741,12 +768,27 @@ void kmemleak_free(const void *ptr)
        pr_debug("%s(0x%p)\n", __func__, ptr);
 
        if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
-               delete_object((unsigned long)ptr);
+               delete_object_full((unsigned long)ptr);
        else if (atomic_read(&kmemleak_early_log))
                log_early(KMEMLEAK_FREE, ptr, 0, 0, 0, 0);
 }
 EXPORT_SYMBOL_GPL(kmemleak_free);
 
+/*
+ * Partial memory freeing function callback. This function is usually called
+ * from bootmem allocator when (part of) a memory block is freed.
+ */
+void kmemleak_free_part(const void *ptr, size_t size)
+{
+       pr_debug("%s(0x%p)\n", __func__, ptr);
+
+       if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
+               delete_object_part((unsigned long)ptr, size);
+       else if (atomic_read(&kmemleak_early_log))
+               log_early(KMEMLEAK_FREE_PART, ptr, size, 0, 0, 0);
+}
+EXPORT_SYMBOL_GPL(kmemleak_free_part);
+
 /*
  * Mark an already allocated memory block as a false positive. This will cause
  * the block to no longer be reported as leak and always be scanned.
@@ -807,21 +849,6 @@ void kmemleak_no_scan(const void *ptr)
 }
 EXPORT_SYMBOL(kmemleak_no_scan);
 
-/*
- * Yield the CPU so that other tasks get a chance to run.  The yielding is
- * rate-limited to avoid excessive number of calls to the schedule() function
- * during memory scanning.
- */
-static void scan_yield(void)
-{
-       might_sleep();
-
-       if (time_is_before_eq_jiffies(next_scan_yield)) {
-               schedule();
-               next_scan_yield = jiffies + jiffies_scan_yield;
-       }
-}
-
 /*
  * Memory scanning is a long process and it needs to be interruptable. This
  * function checks whether such interrupt condition occured.
@@ -848,7 +875,7 @@ static int scan_should_stop(void)
  * found to the gray list.
  */
 static void scan_block(void *_start, void *_end,
-                      struct kmemleak_object *scanned)
+                      struct kmemleak_object *scanned, int allow_resched)
 {
        unsigned long *ptr;
        unsigned long *start = PTR_ALIGN(_start, BYTES_PER_POINTER);
@@ -859,18 +886,11 @@ static void scan_block(void *_start, void *_end,
                unsigned long pointer = *ptr;
                struct kmemleak_object *object;
 
+               if (allow_resched)
+                       cond_resched();
                if (scan_should_stop())
                        break;
 
-               /*
-                * When scanning a memory block with a corresponding
-                * kmemleak_object, the CPU yielding is handled in the calling
-                * code since it holds the object->lock to avoid the block
-                * freeing.
-                */
-               if (!scanned)
-                       scan_yield();
-
                object = find_and_get_object(pointer, 1);
                if (!object)
                        continue;
@@ -931,12 +951,12 @@ static void scan_object(struct kmemleak_object *object)
                goto out;
        if (hlist_empty(&object->area_list))
                scan_block((void *)object->pointer,
-                          (void *)(object->pointer + object->size), object);
+                          (void *)(object->pointer + object->size), object, 0);
        else
                hlist_for_each_entry(area, elem, &object->area_list, node)
                        scan_block((void *)(object->pointer + area->offset),
                                   (void *)(object->pointer + area->offset
-                                           + area->length), object);
+                                           + area->length), object, 0);
 out:
        spin_unlock_irqrestore(&object->lock, flags);
 }
@@ -952,6 +972,10 @@ static void kmemleak_scan(void)
        struct kmemleak_object *object, *tmp;
        struct task_struct *task;
        int i;
+       int new_leaks = 0;
+       int gray_list_pass = 0;
+
+       jiffies_last_scan = jiffies;
 
        /* prepare the kmemleak_object's */
        rcu_read_lock();
@@ -970,6 +994,7 @@ static void kmemleak_scan(void)
 #endif
                /* reset the reference count (whiten the object) */
                object->count = 0;
+               object->flags &= ~OBJECT_NEW;
                if (color_gray(object) && get_object(object))
                        list_add_tail(&object->gray_list, &gray_list);
 
@@ -978,14 +1003,14 @@ static void kmemleak_scan(void)
        rcu_read_unlock();
 
        /* data/bss scanning */
-       scan_block(_sdata, _edata, NULL);
-       scan_block(__bss_start, __bss_stop, NULL);
+       scan_block(_sdata, _edata, NULL, 1);
+       scan_block(__bss_start, __bss_stop, NULL, 1);
 
 #ifdef CONFIG_SMP
        /* per-cpu sections scanning */
        for_each_possible_cpu(i)
                scan_block(__per_cpu_start + per_cpu_offset(i),
-                          __per_cpu_end + per_cpu_offset(i), NULL);
+                          __per_cpu_end + per_cpu_offset(i), NULL, 1);
 #endif
 
        /*
@@ -1007,7 +1032,7 @@ static void kmemleak_scan(void)
                        /* only scan if page is in use */
                        if (page_count(page) == 0)
                                continue;
-                       scan_block(page, page + 1, NULL);
+                       scan_block(page, page + 1, NULL, 1);
                }
        }
 
@@ -1019,7 +1044,8 @@ static void kmemleak_scan(void)
                read_lock(&tasklist_lock);
                for_each_process(task)
                        scan_block(task_stack_page(task),
-                                  task_stack_page(task) + THREAD_SIZE, NULL);
+                                  task_stack_page(task) + THREAD_SIZE,
+                                  NULL, 0);
                read_unlock(&tasklist_lock);
        }
 
@@ -1031,9 +1057,10 @@ static void kmemleak_scan(void)
         * kmemleak objects cannot be freed from outside the loop because their
         * use_count was increased.
         */
+repeat:
        object = list_entry(gray_list.next, typeof(*object), gray_list);
        while (&object->gray_list != &gray_list) {
-               scan_yield();
+               cond_resched();
 
                /* may add new objects to the list */
                if (!scan_should_stop())
@@ -1048,7 +1075,59 @@ static void kmemleak_scan(void)
 
                object = tmp;
        }
+
+       if (scan_should_stop() || ++gray_list_pass >= GRAY_LIST_PASSES)
+               goto scan_end;
+
+       /*
+        * Check for new objects allocated during this scanning and add them
+        * to the gray list.
+        */
+       rcu_read_lock();
+       list_for_each_entry_rcu(object, &object_list, object_list) {
+               spin_lock_irqsave(&object->lock, flags);
+               if ((object->flags & OBJECT_NEW) && !color_black(object) &&
+                   get_object(object)) {
+                       object->flags &= ~OBJECT_NEW;
+                       list_add_tail(&object->gray_list, &gray_list);
+               }
+               spin_unlock_irqrestore(&object->lock, flags);
+       }
+       rcu_read_unlock();
+
+       if (!list_empty(&gray_list))
+               goto repeat;
+
+scan_end:
        WARN_ON(!list_empty(&gray_list));
+
+       /*
+        * If scanning was stopped or new objects were being allocated at a
+        * higher rate than gray list scanning, do not report any new
+        * unreferenced objects.
+        */
+       if (scan_should_stop() || gray_list_pass >= GRAY_LIST_PASSES)
+               return;
+
+       /*
+        * Scanning result reporting.
+        */
+       rcu_read_lock();
+       list_for_each_entry_rcu(object, &object_list, object_list) {
+               spin_lock_irqsave(&object->lock, flags);
+               if (unreferenced_object(object) &&
+                   !(object->flags & OBJECT_REPORTED)) {
+                       object->flags |= OBJECT_REPORTED;
+                       new_leaks++;
+               }
+               spin_unlock_irqrestore(&object->lock, flags);
+       }
+       rcu_read_unlock();
+
+       if (new_leaks)
+               pr_info("%d new suspected memory leaks (see "
+                       "/sys/kernel/debug/kmemleak)\n", new_leaks);
+
 }
 
 /*
@@ -1060,6 +1139,7 @@ static int kmemleak_scan_thread(void *arg)
        static int first_run = 1;
 
        pr_info("Automatic memory scanning thread started\n");
+       set_user_nice(current, 10);
 
        /*
         * Wait before the first scan to allow the system to fully initialize.
@@ -1070,36 +1150,12 @@ static int kmemleak_scan_thread(void *arg)
        }
 
        while (!kthread_should_stop()) {
-               struct kmemleak_object *object;
                signed long timeout = jiffies_scan_wait;
 
                mutex_lock(&scan_mutex);
-
                kmemleak_scan();
-               reported_leaks = 0;
-
-               rcu_read_lock();
-               list_for_each_entry_rcu(object, &object_list, object_list) {
-                       unsigned long flags;
-
-                       if (reported_leaks >= REPORTS_NR)
-                               break;
-                       spin_lock_irqsave(&object->lock, flags);
-                       if (!(object->flags & OBJECT_REPORTED) &&
-                           unreferenced_object(object)) {
-                               print_unreferenced(NULL, object);
-                               object->flags |= OBJECT_REPORTED;
-                               reported_leaks++;
-                       } else if ((object->flags & OBJECT_REPORTED) &&
-                                  referenced_object(object)) {
-                               print_referenced(object);
-                               object->flags &= ~OBJECT_REPORTED;
-                       }
-                       spin_unlock_irqrestore(&object->lock, flags);
-               }
-               rcu_read_unlock();
-
                mutex_unlock(&scan_mutex);
+
                /* wait before the next scan */
                while (timeout && !kthread_should_stop())
                        timeout = schedule_timeout_interruptible(timeout);
@@ -1112,7 +1168,7 @@ static int kmemleak_scan_thread(void *arg)
 
 /*
  * Start the automatic memory scanning thread. This function must be called
- * with the kmemleak_mutex held.
+ * with the scan_mutex held.
  */
 void start_scan_thread(void)
 {
@@ -1127,7 +1183,7 @@ void start_scan_thread(void)
 
 /*
  * Stop the automatic memory scanning thread. This function must be called
- * with the kmemleak_mutex held.
+ * with the scan_mutex held.
  */
 void stop_scan_thread(void)
 {
@@ -1146,13 +1202,11 @@ static void *kmemleak_seq_start(struct seq_file *seq, loff_t *pos)
 {
        struct kmemleak_object *object;
        loff_t n = *pos;
+       int err;
 
-       if (!n) {
-               kmemleak_scan();
-               reported_leaks = 0;
-       }
-       if (reported_leaks >= REPORTS_NR)
-               return NULL;
+       err = mutex_lock_interruptible(&scan_mutex);
+       if (err < 0)
+               return ERR_PTR(err);
 
        rcu_read_lock();
        list_for_each_entry_rcu(object, &object_list, object_list) {
@@ -1163,7 +1217,6 @@ static void *kmemleak_seq_start(struct seq_file *seq, loff_t *pos)
        }
        object = NULL;
 out:
-       rcu_read_unlock();
        return object;
 }
 
@@ -1178,17 +1231,13 @@ static void *kmemleak_seq_next(struct seq_file *seq, void *v, loff_t *pos)
        struct list_head *n = &prev_obj->object_list;
 
        ++(*pos);
-       if (reported_leaks >= REPORTS_NR)
-               goto out;
 
-       rcu_read_lock();
        list_for_each_continue_rcu(n, &object_list) {
                next_obj = list_entry(n, struct kmemleak_object, object_list);
                if (get_object(next_obj))
                        break;
        }
-       rcu_read_unlock();
-out:
+
        put_object(prev_obj);
        return next_obj;
 }
@@ -1198,8 +1247,16 @@ out:
  */
 static void kmemleak_seq_stop(struct seq_file *seq, void *v)
 {
-       if (v)
-               put_object(v);
+       if (!IS_ERR(v)) {
+               /*
+                * kmemleak_seq_start may return ERR_PTR if the scan_mutex
+                * waiting was interrupted, so only release it if !IS_ERR.
+                */
+               rcu_read_unlock();
+               mutex_unlock(&scan_mutex);
+               if (v)
+                       put_object(v);
+       }
 }
 
 /*
@@ -1211,11 +1268,8 @@ static int kmemleak_seq_show(struct seq_file *seq, void *v)
        unsigned long flags;
 
        spin_lock_irqsave(&object->lock, flags);
-       if (!unreferenced_object(object))
-               goto out;
-       print_unreferenced(seq, object);
-       reported_leaks++;
-out:
+       if ((object->flags & OBJECT_REPORTED) && unreferenced_object(object))
+               print_unreferenced(seq, object);
        spin_unlock_irqrestore(&object->lock, flags);
        return 0;
 }
@@ -1229,43 +1283,15 @@ static const struct seq_operations kmemleak_seq_ops = {
 
 static int kmemleak_open(struct inode *inode, struct file *file)
 {
-       int ret = 0;
-
        if (!atomic_read(&kmemleak_enabled))
                return -EBUSY;
 
-       ret = mutex_lock_interruptible(&kmemleak_mutex);
-       if (ret < 0)
-               goto out;
-       if (file->f_mode & FMODE_READ) {
-               ret = mutex_lock_interruptible(&scan_mutex);
-               if (ret < 0)
-                       goto kmemleak_unlock;
-               ret = seq_open(file, &kmemleak_seq_ops);
-               if (ret < 0)
-                       goto scan_unlock;
-       }
-       return ret;
-
-scan_unlock:
-       mutex_unlock(&scan_mutex);
-kmemleak_unlock:
-       mutex_unlock(&kmemleak_mutex);
-out:
-       return ret;
+       return seq_open(file, &kmemleak_seq_ops);
 }
 
 static int kmemleak_release(struct inode *inode, struct file *file)
 {
-       int ret = 0;
-
-       if (file->f_mode & FMODE_READ) {
-               seq_release(inode, file);
-               mutex_unlock(&scan_mutex);
-       }
-       mutex_unlock(&kmemleak_mutex);
-
-       return ret;
+       return seq_release(inode, file);
 }
 
 /*
@@ -1278,21 +1304,24 @@ static int kmemleak_release(struct inode *inode, struct file *file)
  *   scan=off  - stop the automatic memory scanning thread
  *   scan=...  - set the automatic memory scanning period in seconds (0 to
  *               disable it)
+ *   scan      - trigger a memory scan
  */
 static ssize_t kmemleak_write(struct file *file, const char __user *user_buf,
                              size_t size, loff_t *ppos)
 {
        char buf[64];
        int buf_size;
-
-       if (!atomic_read(&kmemleak_enabled))
-               return -EBUSY;
+       int ret;
 
        buf_size = min(size, (sizeof(buf) - 1));
        if (strncpy_from_user(buf, user_buf, buf_size) < 0)
                return -EFAULT;
        buf[buf_size] = 0;
 
+       ret = mutex_lock_interruptible(&scan_mutex);
+       if (ret < 0)
+               return ret;
+
        if (strncmp(buf, "off", 3) == 0)
                kmemleak_disable();
        else if (strncmp(buf, "stack=on", 8) == 0)
@@ -1305,18 +1334,24 @@ static ssize_t kmemleak_write(struct file *file, const char __user *user_buf,
                stop_scan_thread();
        else if (strncmp(buf, "scan=", 5) == 0) {
                unsigned long secs;
-               int err;
 
-               err = strict_strtoul(buf + 5, 0, &secs);
-               if (err < 0)
-                       return err;
+               ret = strict_strtoul(buf + 5, 0, &secs);
+               if (ret < 0)
+                       goto out;
                stop_scan_thread();
                if (secs) {
                        jiffies_scan_wait = msecs_to_jiffies(secs * 1000);
                        start_scan_thread();
                }
-       } else
-               return -EINVAL;
+       } else if (strncmp(buf, "scan", 4) == 0)
+               kmemleak_scan();
+       else
+               ret = -EINVAL;
+
+out:
+       mutex_unlock(&scan_mutex);
+       if (ret < 0)
+               return ret;
 
        /* ignore the rest of the buffer, only one command at a time */
        *ppos += size;
@@ -1340,14 +1375,12 @@ static int kmemleak_cleanup_thread(void *arg)
 {
        struct kmemleak_object *object;
 
-       mutex_lock(&kmemleak_mutex);
+       mutex_lock(&scan_mutex);
        stop_scan_thread();
-       mutex_unlock(&kmemleak_mutex);
 
-       mutex_lock(&scan_mutex);
        rcu_read_lock();
        list_for_each_entry_rcu(object, &object_list, object_list)
-               delete_object(object->pointer);
+               delete_object_full(object->pointer);
        rcu_read_unlock();
        mutex_unlock(&scan_mutex);
 
@@ -1411,7 +1444,6 @@ void __init kmemleak_init(void)
        int i;
        unsigned long flags;
 
-       jiffies_scan_yield = msecs_to_jiffies(MSECS_SCAN_YIELD);
        jiffies_min_age = msecs_to_jiffies(MSECS_MIN_AGE);
        jiffies_scan_wait = msecs_to_jiffies(SECS_SCAN_WAIT * 1000);
 
@@ -1443,6 +1475,9 @@ void __init kmemleak_init(void)
                case KMEMLEAK_FREE:
                        kmemleak_free(log->ptr);
                        break;
+               case KMEMLEAK_FREE_PART:
+                       kmemleak_free_part(log->ptr, log->size);
+                       break;
                case KMEMLEAK_NOT_LEAK:
                        kmemleak_not_leak(log->ptr);
                        break;
@@ -1486,9 +1521,9 @@ static int __init kmemleak_late_init(void)
                                     &kmemleak_fops);
        if (!dentry)
                pr_warning("Failed to create the debugfs kmemleak file\n");
-       mutex_lock(&kmemleak_mutex);
+       mutex_lock(&scan_mutex);
        start_scan_thread();
-       mutex_unlock(&kmemleak_mutex);
+       mutex_unlock(&scan_mutex);
 
        pr_info("Kernel memory leak detector initialized\n");
 
index e2fa20dadf408e2d38e6b5a4a61ed4fb9febd3a1..fd4529d86de59cbfc7093a433752e9b9b604dc93 100644 (file)
@@ -1207,6 +1207,12 @@ static int mem_cgroup_move_account(struct page_cgroup *pc,
        ret = 0;
 out:
        unlock_page_cgroup(pc);
+       /*
+        * We charges against "to" which may not have any tasks. Then, "to"
+        * can be under rmdir(). But in current implementation, caller of
+        * this function is just force_empty() and it's garanteed that
+        * "to" is never removed. So, we don't check rmdir status here.
+        */
        return ret;
 }
 
@@ -1428,6 +1434,7 @@ __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr,
                return;
        if (!ptr)
                return;
+       cgroup_exclude_rmdir(&ptr->css);
        pc = lookup_page_cgroup(page);
        mem_cgroup_lru_del_before_commit_swapcache(page);
        __mem_cgroup_commit_charge(ptr, pc, ctype);
@@ -1457,8 +1464,12 @@ __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr,
                }
                rcu_read_unlock();
        }
-       /* add this page(page_cgroup) to the LRU we want. */
-
+       /*
+        * At swapin, we may charge account against cgroup which has no tasks.
+        * So, rmdir()->pre_destroy() can be called while we do this charge.
+        * In that case, we need to call pre_destroy() again. check it here.
+        */
+       cgroup_release_and_wakeup_rmdir(&ptr->css);
 }
 
 void mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr)
@@ -1664,7 +1675,7 @@ void mem_cgroup_end_migration(struct mem_cgroup *mem,
 
        if (!mem)
                return;
-
+       cgroup_exclude_rmdir(&mem->css);
        /* at migration success, oldpage->mapping is NULL. */
        if (oldpage->mapping) {
                target = oldpage;
@@ -1704,6 +1715,12 @@ void mem_cgroup_end_migration(struct mem_cgroup *mem,
         */
        if (ctype == MEM_CGROUP_CHARGE_TYPE_MAPPED)
                mem_cgroup_uncharge_page(target);
+       /*
+        * At migration, we may charge account against cgroup which has no tasks
+        * So, rmdir()->pre_destroy() can be called while we do this charge.
+        * In that case, we need to call pre_destroy() again. check it here.
+        */
+       cgroup_release_and_wakeup_rmdir(&mem->css);
 }
 
 /*
@@ -1973,7 +1990,7 @@ try_to_free:
                if (!progress) {
                        nr_retries--;
                        /* maybe some writeback is necessary */
-                       congestion_wait(WRITE, HZ/10);
+                       congestion_wait(BLK_RW_ASYNC, HZ/10);
                }
 
        }
index f46ac18ba2311e7e63de8d61b2b7353b283f7b72..aede2ce3aba4fdf1159946cffc7b6acaf8b534d3 100644 (file)
@@ -135,11 +135,12 @@ void pmd_clear_bad(pmd_t *pmd)
  * Note: this doesn't free the actual pages themselves. That
  * has been handled earlier when unmapping all the memory regions.
  */
-static void free_pte_range(struct mmu_gather *tlb, pmd_t *pmd)
+static void free_pte_range(struct mmu_gather *tlb, pmd_t *pmd,
+                          unsigned long addr)
 {
        pgtable_t token = pmd_pgtable(*pmd);
        pmd_clear(pmd);
-       pte_free_tlb(tlb, token);
+       pte_free_tlb(tlb, token, addr);
        tlb->mm->nr_ptes--;
 }
 
@@ -157,7 +158,7 @@ static inline void free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
                next = pmd_addr_end(addr, end);
                if (pmd_none_or_clear_bad(pmd))
                        continue;
-               free_pte_range(tlb, pmd);
+               free_pte_range(tlb, pmd, addr);
        } while (pmd++, addr = next, addr != end);
 
        start &= PUD_MASK;
@@ -173,7 +174,7 @@ static inline void free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
 
        pmd = pmd_offset(pud, start);
        pud_clear(pud);
-       pmd_free_tlb(tlb, pmd);
+       pmd_free_tlb(tlb, pmd, start);
 }
 
 static inline void free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
@@ -206,7 +207,7 @@ static inline void free_pud_range(struct mmu_gather *tlb, pgd_t *pgd,
 
        pud = pud_offset(pgd, start);
        pgd_clear(pgd);
-       pud_free_tlb(tlb, pud);
+       pud_free_tlb(tlb, pud, start);
 }
 
 /*
@@ -1207,8 +1208,8 @@ static inline int use_zero_page(struct vm_area_struct *vma)
 
 
 int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
-                    unsigned long start, int len, int flags,
-               struct page **pages, struct vm_area_struct **vmas)
+                    unsigned long start, int nr_pages, int flags,
+                    struct page **pages, struct vm_area_struct **vmas)
 {
        int i;
        unsigned int vm_flags = 0;
@@ -1217,7 +1218,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
        int ignore = !!(flags & GUP_FLAGS_IGNORE_VMA_PERMISSIONS);
        int ignore_sigkill = !!(flags & GUP_FLAGS_IGNORE_SIGKILL);
 
-       if (len <= 0)
+       if (nr_pages <= 0)
                return 0;
        /* 
         * Require read or write permissions.
@@ -1269,7 +1270,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                                vmas[i] = gate_vma;
                        i++;
                        start += PAGE_SIZE;
-                       len--;
+                       nr_pages--;
                        continue;
                }
 
@@ -1280,7 +1281,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 
                if (is_vm_hugetlb_page(vma)) {
                        i = follow_hugetlb_page(mm, vma, pages, vmas,
-                                               &start, &len, i, write);
+                                               &start, &nr_pages, i, write);
                        continue;
                }
 
@@ -1357,9 +1358,9 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                                vmas[i] = vma;
                        i++;
                        start += PAGE_SIZE;
-                       len--;
-               } while (len && start < vma->vm_end);
-       } while (len);
+                       nr_pages--;
+               } while (nr_pages && start < vma->vm_end);
+       } while (nr_pages);
        return i;
 }
 
@@ -1368,7 +1369,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
  * @tsk:       task_struct of target task
  * @mm:                mm_struct of target mm
  * @start:     starting user address
- * @len:       number of pages from start to pin
+ * @nr_pages:  number of pages from start to pin
  * @write:     whether pages will be written to by the caller
  * @force:     whether to force write access even if user mapping is
  *             readonly. This will result in the page being COWed even
@@ -1380,7 +1381,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
  *             Or NULL if the caller does not require them.
  *
  * Returns number of pages pinned. This may be fewer than the number
- * requested. If len is 0 or negative, returns 0. If no pages
+ * requested. If nr_pages is 0 or negative, returns 0. If no pages
  * were pinned, returns -errno. Each page returned must be released
  * with a put_page() call when it is finished with. vmas will only
  * remain valid while mmap_sem is held.
@@ -1414,7 +1415,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
  * See also get_user_pages_fast, for performance critical applications.
  */
 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
-               unsigned long start, int len, int write, int force,
+               unsigned long start, int nr_pages, int write, int force,
                struct page **pages, struct vm_area_struct **vmas)
 {
        int flags = 0;
@@ -1424,9 +1425,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
        if (force)
                flags |= GUP_FLAGS_FORCE;
 
-       return __get_user_pages(tsk, mm,
-                               start, len, flags,
-                               pages, vmas);
+       return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas);
 }
 
 EXPORT_SYMBOL(get_user_pages);
index e08e2c4da63a5dc45bfcfb9f56cd440d557d0772..7dd9d9f806948e23a7f0be04dac209bfc1c584f5 100644 (file)
@@ -191,25 +191,27 @@ static int mpol_new_bind(struct mempolicy *pol, const nodemask_t *nodes)
  * Must be called holding task's alloc_lock to protect task's mems_allowed
  * and mempolicy.  May also be called holding the mmap_semaphore for write.
  */
-static int mpol_set_nodemask(struct mempolicy *pol, const nodemask_t *nodes)
+static int mpol_set_nodemask(struct mempolicy *pol,
+                    const nodemask_t *nodes, struct nodemask_scratch *nsc)
 {
-       nodemask_t cpuset_context_nmask;
        int ret;
 
        /* if mode is MPOL_DEFAULT, pol is NULL. This is right. */
        if (pol == NULL)
                return 0;
+       /* Check N_HIGH_MEMORY */
+       nodes_and(nsc->mask1,
+                 cpuset_current_mems_allowed, node_states[N_HIGH_MEMORY]);
 
        VM_BUG_ON(!nodes);
        if (pol->mode == MPOL_PREFERRED && nodes_empty(*nodes))
                nodes = NULL;   /* explicit local allocation */
        else {
                if (pol->flags & MPOL_F_RELATIVE_NODES)
-                       mpol_relative_nodemask(&cpuset_context_nmask, nodes,
-                                              &cpuset_current_mems_allowed);
+                       mpol_relative_nodemask(&nsc->mask2, nodes,&nsc->mask1);
                else
-                       nodes_and(cpuset_context_nmask, *nodes,
-                                 cpuset_current_mems_allowed);
+                       nodes_and(nsc->mask2, *nodes, nsc->mask1);
+
                if (mpol_store_user_nodemask(pol))
                        pol->w.user_nodemask = *nodes;
                else
@@ -217,8 +219,10 @@ static int mpol_set_nodemask(struct mempolicy *pol, const nodemask_t *nodes)
                                                cpuset_current_mems_allowed;
        }
 
-       ret = mpol_ops[pol->mode].create(pol,
-                               nodes ? &cpuset_context_nmask : NULL);
+       if (nodes)
+               ret = mpol_ops[pol->mode].create(pol, &nsc->mask2);
+       else
+               ret = mpol_ops[pol->mode].create(pol, NULL);
        return ret;
 }
 
@@ -620,12 +624,17 @@ static long do_set_mempolicy(unsigned short mode, unsigned short flags,
 {
        struct mempolicy *new, *old;
        struct mm_struct *mm = current->mm;
+       NODEMASK_SCRATCH(scratch);
        int ret;
 
-       new = mpol_new(mode, flags, nodes);
-       if (IS_ERR(new))
-               return PTR_ERR(new);
+       if (!scratch)
+               return -ENOMEM;
 
+       new = mpol_new(mode, flags, nodes);
+       if (IS_ERR(new)) {
+               ret = PTR_ERR(new);
+               goto out;
+       }
        /*
         * prevent changing our mempolicy while show_numa_maps()
         * is using it.
@@ -635,13 +644,13 @@ static long do_set_mempolicy(unsigned short mode, unsigned short flags,
        if (mm)
                down_write(&mm->mmap_sem);
        task_lock(current);
-       ret = mpol_set_nodemask(new, nodes);
+       ret = mpol_set_nodemask(new, nodes, scratch);
        if (ret) {
                task_unlock(current);
                if (mm)
                        up_write(&mm->mmap_sem);
                mpol_put(new);
-               return ret;
+               goto out;
        }
        old = current->mempolicy;
        current->mempolicy = new;
@@ -654,7 +663,10 @@ static long do_set_mempolicy(unsigned short mode, unsigned short flags,
                up_write(&mm->mmap_sem);
 
        mpol_put(old);
-       return 0;
+       ret = 0;
+out:
+       NODEMASK_SCRATCH_FREE(scratch);
+       return ret;
 }
 
 /*
@@ -1014,12 +1026,20 @@ static long do_mbind(unsigned long start, unsigned long len,
                if (err)
                        return err;
        }
-       down_write(&mm->mmap_sem);
-       task_lock(current);
-       err = mpol_set_nodemask(new, nmask);
-       task_unlock(current);
+       {
+               NODEMASK_SCRATCH(scratch);
+               if (scratch) {
+                       down_write(&mm->mmap_sem);
+                       task_lock(current);
+                       err = mpol_set_nodemask(new, nmask, scratch);
+                       task_unlock(current);
+                       if (err)
+                               up_write(&mm->mmap_sem);
+               } else
+                       err = -ENOMEM;
+               NODEMASK_SCRATCH_FREE(scratch);
+       }
        if (err) {
-               up_write(&mm->mmap_sem);
                mpol_put(new);
                return err;
        }
@@ -1891,6 +1911,7 @@ restart:
  * Install non-NULL @mpol in inode's shared policy rb-tree.
  * On entry, the current task has a reference on a non-NULL @mpol.
  * This must be released on exit.
+ * This is called at get_inode() calls and we can use GFP_KERNEL.
  */
 void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol)
 {
@@ -1902,19 +1923,24 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol)
        if (mpol) {
                struct vm_area_struct pvma;
                struct mempolicy *new;
+               NODEMASK_SCRATCH(scratch);
 
+               if (!scratch)
+                       return;
                /* contextualize the tmpfs mount point mempolicy */
                new = mpol_new(mpol->mode, mpol->flags, &mpol->w.user_nodemask);
                if (IS_ERR(new)) {
                        mpol_put(mpol); /* drop our ref on sb mpol */
+                       NODEMASK_SCRATCH_FREE(scratch);
                        return;         /* no valid nodemask intersection */
                }
 
                task_lock(current);
-               ret = mpol_set_nodemask(new, &mpol->w.user_nodemask);
+               ret = mpol_set_nodemask(new, &mpol->w.user_nodemask, scratch);
                task_unlock(current);
                mpol_put(mpol); /* drop our ref on sb mpol */
                if (ret) {
+                       NODEMASK_SCRATCH_FREE(scratch);
                        mpol_put(new);
                        return;
                }
@@ -1924,6 +1950,7 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol)
                pvma.vm_end = TASK_SIZE;        /* policy covers entire file */
                mpol_set_shared_policy(sp, &pvma, new); /* adds ref */
                mpol_put(new);                  /* drop initial ref */
+               NODEMASK_SCRATCH_FREE(scratch);
        }
 }
 
@@ -2140,13 +2167,18 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
                err = 1;
        else {
                int ret;
-
-               task_lock(current);
-               ret = mpol_set_nodemask(new, &nodes);
-               task_unlock(current);
-               if (ret)
+               NODEMASK_SCRATCH(scratch);
+               if (scratch) {
+                       task_lock(current);
+                       ret = mpol_set_nodemask(new, &nodes, scratch);
+                       task_unlock(current);
+               } else
+                       ret = -ENOMEM;
+               NODEMASK_SCRATCH_FREE(scratch);
+               if (ret) {
                        err = 1;
-               else if (no_context) {
+                       mpol_put(new);
+               } else if (no_context) {
                        /* save for contextualization */
                        new->w.user_nodemask = nodes;
                }
index a46eb1b4bb661e12a6f752964ad2df190bc763aa..32e75d4005032620e8f9cb9161a8c66f025470bb 100644 (file)
@@ -303,14 +303,14 @@ EXPORT_SYMBOL(mempool_free_slab);
  */
 void *mempool_kmalloc(gfp_t gfp_mask, void *pool_data)
 {
-       size_t size = (size_t)(long)pool_data;
+       size_t size = (size_t)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;
+       size_t size = (size_t)pool_data;
        return kzalloc(size, gfp_mask);
 }
 EXPORT_SYMBOL(mempool_kzalloc);
index 34579b23ebd55ebed1a99a5473c6ca0693b559e2..8101de490c73941ab8815733a3899c614cdb8cb7 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -88,9 +88,6 @@ int sysctl_overcommit_ratio = 50;     /* default is 50% */
 int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
 struct percpu_counter vm_committed_as;
 
-/* amount of vm to protect from userspace access */
-unsigned long mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
-
 /*
  * Check that a process has enough memory to allocate a new virtual
  * mapping. 0 means there is enough memory for the allocation to
index 2fd2ad5da98e5d82e751b76f4e6369c57f20e6db..66e81e7e9fe98f6871cb0d159e13c6942ff8e44f 100644 (file)
@@ -69,9 +69,6 @@ int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
 int sysctl_nr_trim_pages = CONFIG_NOMMU_INITIAL_TRIM_EXCESS;
 int heap_stack_gap = 0;
 
-/* amount of vm to protect from userspace access */
-unsigned long mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
-
 atomic_long_t mmap_pages_allocated;
 
 EXPORT_SYMBOL(mem_map);
@@ -173,8 +170,8 @@ unsigned int kobjsize(const void *objp)
 }
 
 int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
-                    unsigned long start, int len, int flags,
-               struct page **pages, struct vm_area_struct **vmas)
+                    unsigned long start, int nr_pages, int flags,
+                    struct page **pages, struct vm_area_struct **vmas)
 {
        struct vm_area_struct *vma;
        unsigned long vm_flags;
@@ -189,7 +186,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
        vm_flags  = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
        vm_flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
 
-       for (i = 0; i < len; i++) {
+       for (i = 0; i < nr_pages; i++) {
                vma = find_vma(mm, start);
                if (!vma)
                        goto finish_or_fault;
@@ -224,7 +221,7 @@ finish_or_fault:
  * - don't permit access to VMAs that don't support it, such as I/O mappings
  */
 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
-       unsigned long start, int len, int write, int force,
+       unsigned long start, int nr_pages, int write, int force,
        struct page **pages, struct vm_area_struct **vmas)
 {
        int flags = 0;
@@ -234,12 +231,31 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
        if (force)
                flags |= GUP_FLAGS_FORCE;
 
-       return __get_user_pages(tsk, mm,
-                               start, len, flags,
-                               pages, vmas);
+       return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas);
 }
 EXPORT_SYMBOL(get_user_pages);
 
+/**
+ * follow_pfn - look up PFN at a user virtual address
+ * @vma: memory mapping
+ * @address: user virtual address
+ * @pfn: location to store found PFN
+ *
+ * Only IO mappings and raw PFN mappings are allowed.
+ *
+ * Returns zero and the pfn at @pfn on success, -ve otherwise.
+ */
+int follow_pfn(struct vm_area_struct *vma, unsigned long address,
+       unsigned long *pfn)
+{
+       if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
+               return -EINVAL;
+
+       *pfn = address >> PAGE_SHIFT;
+       return 0;
+}
+EXPORT_SYMBOL(follow_pfn);
+
 DEFINE_RWLOCK(vmlist_lock);
 struct vm_struct *vmlist;
 
@@ -903,6 +919,10 @@ static int validate_mmap_request(struct file *file,
                if (!file->f_op->read)
                        capabilities &= ~BDI_CAP_MAP_COPY;
 
+               /* The file shall have been opened with read permission. */
+               if (!(file->f_mode & FMODE_READ))
+                       return -EACCES;
+
                if (flags & MAP_SHARED) {
                        /* do checks for writing, appending and locking */
                        if ((prot & PROT_WRITE) &&
@@ -1332,6 +1352,7 @@ unsigned long do_mmap_pgoff(struct file *file,
        }
 
        vma->vm_region = region;
+       add_nommu_region(region);
 
        /* set up the mapping */
        if (file && vma->vm_flags & VM_SHARED)
@@ -1341,8 +1362,6 @@ unsigned long do_mmap_pgoff(struct file *file,
        if (ret < 0)
                goto error_put_region;
 
-       add_nommu_region(region);
-
        /* okay... we have a mapping; now we have to register it */
        result = vma->vm_start;
 
index 175a67a78a99e7b0368dfba11edf9888bc049674..a7b2460e922b779252ebcc225cecaf6060b0e964 100644 (file)
@@ -58,7 +58,6 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
        unsigned long points, cpu_time, run_time;
        struct mm_struct *mm;
        struct task_struct *child;
-       int oom_adj;
 
        task_lock(p);
        mm = p->mm;
@@ -66,11 +65,6 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
                task_unlock(p);
                return 0;
        }
-       oom_adj = mm->oom_adj;
-       if (oom_adj == OOM_DISABLE) {
-               task_unlock(p);
-               return 0;
-       }
 
        /*
         * The memory size of the process is the basis for the badness.
@@ -154,15 +148,15 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
                points /= 8;
 
        /*
-        * Adjust the score by oom_adj.
+        * Adjust the score by oomkilladj.
         */
-       if (oom_adj) {
-               if (oom_adj > 0) {
+       if (p->oomkilladj) {
+               if (p->oomkilladj > 0) {
                        if (!points)
                                points = 1;
-                       points <<= oom_adj;
+                       points <<= p->oomkilladj;
                } else
-                       points >>= -(oom_adj);
+                       points >>= -(p->oomkilladj);
        }
 
 #ifdef DEBUG
@@ -257,8 +251,11 @@ static struct task_struct *select_bad_process(unsigned long *ppoints,
                        *ppoints = ULONG_MAX;
                }
 
+               if (p->oomkilladj == OOM_DISABLE)
+                       continue;
+
                points = badness(p, uptime.tv_sec);
-               if (points > *ppoints) {
+               if (points > *ppoints || !chosen) {
                        chosen = p;
                        *ppoints = points;
                }
@@ -307,7 +304,8 @@ static void dump_tasks(const struct mem_cgroup *mem)
                }
                printk(KERN_INFO "[%5d] %5d %5d %8lu %8lu %3d     %3d %s\n",
                       p->pid, __task_cred(p)->uid, p->tgid, mm->total_vm,
-                      get_mm_rss(mm), (int)task_cpu(p), mm->oom_adj, p->comm);
+                      get_mm_rss(mm), (int)task_cpu(p), p->oomkilladj,
+                      p->comm);
                task_unlock(p);
        } while_each_thread(g, p);
 }
@@ -325,8 +323,11 @@ static void __oom_kill_task(struct task_struct *p, int verbose)
                return;
        }
 
-       if (!p->mm)
+       if (!p->mm) {
+               WARN_ON(1);
+               printk(KERN_WARNING "tried to kill an mm-less task!\n");
                return;
+       }
 
        if (verbose)
                printk(KERN_ERR "Killed process %d (%s)\n",
@@ -348,13 +349,28 @@ static int oom_kill_task(struct task_struct *p)
        struct mm_struct *mm;
        struct task_struct *g, *q;
 
-       task_lock(p);
        mm = p->mm;
-       if (!mm || mm->oom_adj == OOM_DISABLE) {
-               task_unlock(p);
+
+       /* WARNING: mm may not be dereferenced since we did not obtain its
+        * value from get_task_mm(p).  This is OK since all we need to do is
+        * compare mm to q->mm below.
+        *
+        * Furthermore, even if mm contains a non-NULL value, p->mm may
+        * change to NULL at any time since we do not hold task_lock(p).
+        * However, this is of no concern to us.
+        */
+
+       if (mm == NULL)
                return 1;
-       }
-       task_unlock(p);
+
+       /*
+        * Don't kill the process if any threads are set to OOM_DISABLE
+        */
+       do_each_thread(g, q) {
+               if (q->mm == mm && q->oomkilladj == OOM_DISABLE)
+                       return 1;
+       } while_each_thread(g, q);
+
        __oom_kill_task(p, 1);
 
        /*
@@ -377,11 +393,10 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
        struct task_struct *c;
 
        if (printk_ratelimit()) {
-               task_lock(current);
                printk(KERN_WARNING "%s invoked oom-killer: "
-                       "gfp_mask=0x%x, order=%d, oom_adj=%d\n",
-                       current->comm, gfp_mask, order,
-                       current->mm ? current->mm->oom_adj : OOM_DISABLE);
+                       "gfp_mask=0x%x, order=%d, oomkilladj=%d\n",
+                       current->comm, gfp_mask, order, current->oomkilladj);
+               task_lock(current);
                cpuset_print_task_mems_allowed(current);
                task_unlock(current);
                dump_stack();
@@ -394,9 +409,8 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
        /*
         * If the task is already exiting, don't alarm the sysadmin or kill
         * its children or threads, just set TIF_MEMDIE so it can die quickly
-        * if its mm is still attached.
         */
-       if (p->mm && (p->flags & PF_EXITING)) {
+       if (p->flags & PF_EXITING) {
                __oom_kill_task(p, 0);
                return 0;
        }
index 7b0dcea4935bea292730ce7d1926fc0ea00df062..81627ebcd313fcd5ee3545a0996d2802fab36085 100644 (file)
@@ -541,8 +541,11 @@ static void balance_dirty_pages(struct address_space *mapping)
                 * filesystems (i.e. NFS) in which data may have been
                 * written to the server's write cache, but has not yet
                 * been flushed to permanent storage.
+                * Only move pages to writeback if this bdi is over its
+                * threshold otherwise wait until the disk writes catch
+                * up.
                 */
-               if (bdi_nr_reclaimable) {
+               if (bdi_nr_reclaimable > bdi_thresh) {
                        writeback_inodes(&wbc);
                        pages_written += write_chunk - wbc.nr_to_write;
                        get_dirty_limits(&background_thresh, &dirty_thresh,
@@ -572,7 +575,7 @@ static void balance_dirty_pages(struct address_space *mapping)
                if (pages_written >= write_chunk)
                        break;          /* We've done our duty */
 
-               congestion_wait(WRITE, HZ/10);
+               congestion_wait(BLK_RW_ASYNC, HZ/10);
        }
 
        if (bdi_nr_reclaimable + bdi_nr_writeback < bdi_thresh &&
@@ -666,7 +669,7 @@ void throttle_vm_writeout(gfp_t gfp_mask)
                 if (global_page_state(NR_UNSTABLE_NFS) +
                        global_page_state(NR_WRITEBACK) <= dirty_thresh)
                                break;
-                congestion_wait(WRITE, HZ/10);
+                congestion_wait(BLK_RW_ASYNC, HZ/10);
 
                /*
                 * The caller might hold locks which can prevent IO completion
@@ -712,7 +715,7 @@ static void background_writeout(unsigned long _min_pages)
                if (wbc.nr_to_write > 0 || wbc.pages_skipped > 0) {
                        /* Wrote less than expected */
                        if (wbc.encountered_congestion || wbc.more_io)
-                               congestion_wait(WRITE, HZ/10);
+                               congestion_wait(BLK_RW_ASYNC, HZ/10);
                        else
                                break;
                }
@@ -784,7 +787,7 @@ static void wb_kupdate(unsigned long arg)
                writeback_inodes(&wbc);
                if (wbc.nr_to_write > 0) {
                        if (wbc.encountered_congestion || wbc.more_io)
-                               congestion_wait(WRITE, HZ/10);
+                               congestion_wait(BLK_RW_ASYNC, HZ/10);
                        else
                                break;  /* All the old data is written */
                }
index 5d714f8fb30333f6de336e555f944658bfa1dc16..a0de15f46987f65249bd60d4cad45e129fbddf29 100644 (file)
@@ -817,13 +817,15 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype)
                         * agressive about taking ownership of free pages
                         */
                        if (unlikely(current_order >= (pageblock_order >> 1)) ||
-                                       start_migratetype == MIGRATE_RECLAIMABLE) {
+                                       start_migratetype == MIGRATE_RECLAIMABLE ||
+                                       page_group_by_mobility_disabled) {
                                unsigned long pages;
                                pages = move_freepages_block(zone, page,
                                                                start_migratetype);
 
                                /* Claim the whole block if over half of it is free */
-                               if (pages >= (1 << (pageblock_order-1)))
+                               if (pages >= (1 << (pageblock_order-1)) ||
+                                               page_group_by_mobility_disabled)
                                        set_pageblock_migratetype(page,
                                                                start_migratetype);
 
@@ -882,7 +884,7 @@ retry_reserve:
  */
 static int rmqueue_bulk(struct zone *zone, unsigned int order, 
                        unsigned long count, struct list_head *list,
-                       int migratetype)
+                       int migratetype, int cold)
 {
        int i;
        
@@ -901,7 +903,10 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
                 * merge IO requests if the physical pages are ordered
                 * properly.
                 */
-               list_add(&page->lru, list);
+               if (likely(cold == 0))
+                       list_add(&page->lru, list);
+               else
+                       list_add_tail(&page->lru, list);
                set_page_private(page, migratetype);
                list = &page->lru;
        }
@@ -1119,7 +1124,8 @@ again:
                local_irq_save(flags);
                if (!pcp->count) {
                        pcp->count = rmqueue_bulk(zone, 0,
-                                       pcp->batch, &pcp->list, migratetype);
+                                       pcp->batch, &pcp->list,
+                                       migratetype, cold);
                        if (unlikely(!pcp->count))
                                goto failed;
                }
@@ -1138,7 +1144,8 @@ again:
                /* Allocate more to the pcp list if necessary */
                if (unlikely(&page->lru == &pcp->list)) {
                        pcp->count += rmqueue_bulk(zone, 0,
-                                       pcp->batch, &pcp->list, migratetype);
+                                       pcp->batch, &pcp->list,
+                                       migratetype, cold);
                        page = list_entry(pcp->list.next, struct page, lru);
                }
 
@@ -1666,7 +1673,7 @@ __alloc_pages_high_priority(gfp_t gfp_mask, unsigned int order,
                        preferred_zone, migratetype);
 
                if (!page && gfp_mask & __GFP_NOFAIL)
-                       congestion_wait(WRITE, HZ/50);
+                       congestion_wait(BLK_RW_ASYNC, HZ/50);
        } while (!page && (gfp_mask & __GFP_NOFAIL));
 
        return page;
@@ -1740,8 +1747,10 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
         * be using allocators in order of preference for an area that is
         * too large.
         */
-       if (WARN_ON_ONCE(order >= MAX_ORDER))
+       if (order >= MAX_ORDER) {
+               WARN_ON_ONCE(!(gfp_mask & __GFP_NOWARN));
                return NULL;
+       }
 
        /*
         * GFP_THISNODE (meaning __GFP_THISNODE, __GFP_NORETRY and
@@ -1789,6 +1798,10 @@ rebalance:
        if (p->flags & PF_MEMALLOC)
                goto nopage;
 
+       /* Avoid allocations with no watermarks from looping endlessly */
+       if (test_thread_flag(TIF_MEMDIE) && !(gfp_mask & __GFP_NOFAIL))
+               goto nopage;
+
        /* Try direct reclaim and then allocating */
        page = __alloc_pages_direct_reclaim(gfp_mask, order,
                                        zonelist, high_zoneidx,
@@ -1831,7 +1844,7 @@ rebalance:
        pages_reclaimed += did_some_progress;
        if (should_alloc_retry(gfp_mask, order, pages_reclaimed)) {
                /* Wait for some write requests to complete then retry */
-               congestion_wait(WRITE, HZ/50);
+               congestion_wait(BLK_RW_ASYNC, HZ/50);
                goto rebalance;
        }
 
@@ -1983,7 +1996,7 @@ void *alloc_pages_exact(size_t size, gfp_t gfp_mask)
                unsigned long alloc_end = addr + (PAGE_SIZE << order);
                unsigned long used = addr + PAGE_ALIGN(size);
 
-               split_page(virt_to_page(addr), order);
+               split_page(virt_to_page((void *)addr), order);
                while (used < alloc_end) {
                        free_page(used);
                        used += PAGE_SIZE;
@@ -2533,7 +2546,6 @@ static void build_zonelists(pg_data_t *pgdat)
        prev_node = local_node;
        nodes_clear(used_mask);
 
-       memset(node_load, 0, sizeof(node_load));
        memset(node_order, 0, sizeof(node_order));
        j = 0;
 
@@ -2642,6 +2654,9 @@ static int __build_all_zonelists(void *dummy)
 {
        int nid;
 
+#ifdef CONFIG_NUMA
+       memset(node_load, 0, sizeof(node_load));
+#endif
        for_each_online_node(nid) {
                pg_data_t *pgdat = NODE_DATA(nid);
 
@@ -4032,6 +4047,8 @@ static void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn)
        int i, nid;
        unsigned long usable_startpfn;
        unsigned long kernelcore_node, kernelcore_remaining;
+       /* save the state before borrow the nodemask */
+       nodemask_t saved_node_state = node_states[N_HIGH_MEMORY];
        unsigned long totalpages = early_calculate_totalpages();
        int usable_nodes = nodes_weight(node_states[N_HIGH_MEMORY]);
 
@@ -4059,7 +4076,7 @@ static void __init find_zone_movable_pfns_for_nodes(unsigned long *movable_pfn)
 
        /* If kernelcore was not specified, there is no ZONE_MOVABLE */
        if (!required_kernelcore)
-               return;
+               goto out;
 
        /* usable_startpfn is the lowest possible pfn ZONE_MOVABLE can be at */
        find_usable_zone_for_movable();
@@ -4158,6 +4175,10 @@ restart:
        for (nid = 0; nid < MAX_NUMNODES; nid++)
                zone_movable_pfn[nid] =
                        roundup(zone_movable_pfn[nid], MAX_ORDER_NR_PAGES);
+
+out:
+       /* restore the node_state */
+       node_states[N_HIGH_MEMORY] = saved_node_state;
 }
 
 /* Any regular memory on that node ? */
@@ -4242,11 +4263,6 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
                                                early_node_map[i].start_pfn,
                                                early_node_map[i].end_pfn);
 
-       /*
-        * find_zone_movable_pfns_for_nodes/early_calculate_totalpages init
-        * that node_mask, clear it at first
-        */
-       nodes_clear(node_states[N_HIGH_MEMORY]);
        /* Initialise every node */
        mminit_verify_pageflags_layout();
        setup_nr_node_ids();
@@ -4744,8 +4760,10 @@ void *__init alloc_large_system_hash(const char *tablename,
                         * some pages at the end of hash table which
                         * alloc_pages_exact() automatically does
                         */
-                       if (get_order(size) < MAX_ORDER)
+                       if (get_order(size) < MAX_ORDER) {
                                table = alloc_pages_exact(size, GFP_ATOMIC);
+                               kmemleak_alloc(table, size, 1, GFP_ATOMIC);
+                       }
                }
        } while (!table && size > PAGE_SIZE && --log2qty);
 
@@ -4763,16 +4781,6 @@ void *__init alloc_large_system_hash(const char *tablename,
        if (_hash_mask)
                *_hash_mask = (1 << log2qty) - 1;
 
-       /*
-        * If hashdist is set, the table allocation is done with __vmalloc()
-        * which invokes the kmemleak_alloc() callback. This function may also
-        * be called before the slab and kmemleak are initialised when
-        * kmemleak simply buffers the request to be executed later
-        * (GFP_ATOMIC flag ignored in this case).
-        */
-       if (!hashdist)
-               kmemleak_alloc(table, size, 1, GFP_ATOMIC);
-
        return table;
 }
 
index c0b2c1a76e81c280398b27ed310b1e03500e3a23..3311c8919f375fa062faad78b2439176f436301a 100644 (file)
@@ -8,12 +8,12 @@
  *
  * This is percpu allocator which can handle both static and dynamic
  * areas.  Percpu areas are allocated in chunks in vmalloc area.  Each
- * chunk is consisted of num_possible_cpus() units and the first chunk
- * is used for static percpu variables in the kernel image (special
- * boot time alloc/init handling necessary as these areas need to be
- * brought up before allocation services are running).  Unit grows as
- * necessary and all units grow or shrink in unison.  When a chunk is
- * filled up, another chunk is allocated.  ie. in vmalloc area
+ * chunk is consisted of nr_cpu_ids units and the first chunk is used
+ * for static percpu variables in the kernel image (special boot time
+ * alloc/init handling necessary as these areas need to be brought up
+ * before allocation services are running).  Unit grows as necessary
+ * and all units grow or shrink in unison.  When a chunk is filled up,
+ * another chunk is allocated.  ie. in vmalloc area
  *
  *  c0                           c1                         c2
  *  -------------------          -------------------        ------------
@@ -197,7 +197,12 @@ static unsigned long pcpu_chunk_addr(struct pcpu_chunk *chunk,
 static bool pcpu_chunk_page_occupied(struct pcpu_chunk *chunk,
                                     int page_idx)
 {
-       return *pcpu_chunk_pagep(chunk, 0, page_idx) != NULL;
+       /*
+        * Any possible cpu id can be used here, so there's no need to
+        * worry about preemption or cpu hotplug.
+        */
+       return *pcpu_chunk_pagep(chunk, raw_smp_processor_id(),
+                                page_idx) != NULL;
 }
 
 /* set the pointer to a chunk in a page struct */
@@ -297,6 +302,14 @@ static struct pcpu_chunk *pcpu_chunk_addr_search(void *addr)
                return pcpu_first_chunk;
        }
 
+       /*
+        * The address is relative to unit0 which might be unused and
+        * thus unmapped.  Offset the address to the unit space of the
+        * current processor before looking it up in the vmalloc
+        * space.  Note that any possible cpu id can be used here, so
+        * there's no need to worry about preemption or cpu hotplug.
+        */
+       addr += raw_smp_processor_id() * pcpu_unit_size;
        return pcpu_get_page_chunk(vmalloc_to_page(addr));
 }
 
@@ -549,16 +562,16 @@ static void pcpu_free_area(struct pcpu_chunk *chunk, int freeme)
  * @chunk: chunk of interest
  * @page_start: page index of the first page to unmap
  * @page_end: page index of the last page to unmap + 1
- * @flush: whether to flush cache and tlb or not
+ * @flush_tlb: whether to flush tlb or not
  *
  * For each cpu, unmap pages [@page_start,@page_end) out of @chunk.
  * If @flush is true, vcache is flushed before unmapping and tlb
  * after.
  */
 static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end,
-                      bool flush)
+                      bool flush_tlb)
 {
-       unsigned int last = num_possible_cpus() - 1;
+       unsigned int last = nr_cpu_ids - 1;
        unsigned int cpu;
 
        /* unmap must not be done on immutable chunk */
@@ -569,9 +582,8 @@ static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end,
         * the whole region at once rather than doing it for each cpu.
         * This could be an overkill but is more scalable.
         */
-       if (flush)
-               flush_cache_vunmap(pcpu_chunk_addr(chunk, 0, page_start),
-                                  pcpu_chunk_addr(chunk, last, page_end));
+       flush_cache_vunmap(pcpu_chunk_addr(chunk, 0, page_start),
+                          pcpu_chunk_addr(chunk, last, page_end));
 
        for_each_possible_cpu(cpu)
                unmap_kernel_range_noflush(
@@ -579,7 +591,7 @@ static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end,
                                (page_end - page_start) << PAGE_SHIFT);
 
        /* ditto as flush_cache_vunmap() */
-       if (flush)
+       if (flush_tlb)
                flush_tlb_kernel_range(pcpu_chunk_addr(chunk, 0, page_start),
                                       pcpu_chunk_addr(chunk, last, page_end));
 }
@@ -644,7 +656,7 @@ static void pcpu_depopulate_chunk(struct pcpu_chunk *chunk, int off, int size,
  */
 static int pcpu_map(struct pcpu_chunk *chunk, int page_start, int page_end)
 {
-       unsigned int last = num_possible_cpus() - 1;
+       unsigned int last = nr_cpu_ids - 1;
        unsigned int cpu;
        int err;
 
@@ -750,7 +762,7 @@ static struct pcpu_chunk *alloc_pcpu_chunk(void)
        chunk->map[chunk->map_used++] = pcpu_unit_size;
        chunk->page = chunk->page_ar;
 
-       chunk->vm = get_vm_area(pcpu_chunk_size, GFP_KERNEL);
+       chunk->vm = get_vm_area(pcpu_chunk_size, VM_ALLOC);
        if (!chunk->vm) {
                free_pcpu_chunk(chunk);
                return NULL;
@@ -1068,9 +1080,9 @@ size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn,
                                        PFN_UP(size_sum));
 
        pcpu_unit_size = pcpu_unit_pages << PAGE_SHIFT;
-       pcpu_chunk_size = num_possible_cpus() * pcpu_unit_size;
+       pcpu_chunk_size = nr_cpu_ids * pcpu_unit_size;
        pcpu_chunk_struct_size = sizeof(struct pcpu_chunk)
-               + num_possible_cpus() * pcpu_unit_pages * sizeof(struct page *);
+               + nr_cpu_ids * pcpu_unit_pages * sizeof(struct page *);
 
        if (dyn_size < 0)
                dyn_size = pcpu_unit_size - static_size - reserved_size;
@@ -1234,6 +1246,7 @@ static struct page * __init pcpue_get_page(unsigned int cpu, int pageno)
 ssize_t __init pcpu_embed_first_chunk(size_t static_size, size_t reserved_size,
                                      ssize_t dyn_size, ssize_t unit_size)
 {
+       size_t chunk_size;
        unsigned int cpu;
 
        /* determine parameters and allocate */
@@ -1248,19 +1261,26 @@ ssize_t __init pcpu_embed_first_chunk(size_t static_size, size_t reserved_size,
        } else
                pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE);
 
-       pcpue_ptr = __alloc_bootmem_nopanic(
-                                       num_possible_cpus() * pcpue_unit_size,
-                                       PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
-       if (!pcpue_ptr)
+       chunk_size = pcpue_unit_size * nr_cpu_ids;
+
+       pcpue_ptr = __alloc_bootmem_nopanic(chunk_size, PAGE_SIZE,
+                                           __pa(MAX_DMA_ADDRESS));
+       if (!pcpue_ptr) {
+               pr_warning("PERCPU: failed to allocate %zu bytes for "
+                          "embedding\n", chunk_size);
                return -ENOMEM;
+       }
 
        /* return the leftover and copy */
-       for_each_possible_cpu(cpu) {
+       for (cpu = 0; cpu < nr_cpu_ids; cpu++) {
                void *ptr = pcpue_ptr + cpu * pcpue_unit_size;
 
-               free_bootmem(__pa(ptr + pcpue_size),
-                            pcpue_unit_size - pcpue_size);
-               memcpy(ptr, __per_cpu_load, static_size);
+               if (cpu_possible(cpu)) {
+                       free_bootmem(__pa(ptr + pcpue_size),
+                                    pcpue_unit_size - pcpue_size);
+                       memcpy(ptr, __per_cpu_load, static_size);
+               } else
+                       free_bootmem(__pa(ptr), pcpue_unit_size);
        }
 
        /* we're ready, commit */
index 836c6c63e1f2dbee16a922f7195da2f3ac237d83..0895b5c7cbff35fc2e5eb8dbe4b2ee8eeacf27da 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -358,6 +358,7 @@ static int page_referenced_one(struct page *page,
         */
        if (vma->vm_flags & VM_LOCKED) {
                *mapcount = 1;  /* break early from loop */
+               *vm_flags |= VM_LOCKED;
                goto out_unmap;
        }
 
index e74a16e4ced605111bd0f84154273c038bb0d9e3..7b5d4deacfcd96f79460e3e91d159f22b47dec5f 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1544,9 +1544,6 @@ void __init kmem_cache_init(void)
        }
 
        g_cpucache_up = EARLY;
-
-       /* Annotate slab for lockdep -- annotate the malloc caches */
-       init_lock_keys();
 }
 
 void __init kmem_cache_init_late(void)
@@ -1563,6 +1560,9 @@ void __init kmem_cache_init_late(void)
        /* Done! */
        g_cpucache_up = FULL;
 
+       /* Annotate slab for lockdep -- annotate the malloc caches */
+       init_lock_keys();
+
        /*
         * Register a cpu startup notifier callback that initializes
         * cpu_cache_get for all new cpus
@@ -2547,7 +2547,7 @@ void kmem_cache_destroy(struct kmem_cache *cachep)
        }
 
        if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
-               synchronize_rcu();
+               rcu_barrier();
 
        __kmem_cache_destroy(cachep);
        mutex_unlock(&cache_chain_mutex);
index c78742defdc6477ef7474ebc1fc8117173aaabfc..9641da3d5e58dfca1d7c79dbef99760364fa98b2 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -595,6 +595,8 @@ EXPORT_SYMBOL(kmem_cache_create);
 void kmem_cache_destroy(struct kmem_cache *c)
 {
        kmemleak_free(c);
+       if (c->flags & SLAB_DESTROY_BY_RCU)
+               rcu_barrier();
        slob_free(c, sizeof(struct kmem_cache));
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
index 819f056b39c6f27100e8b89f91acc42b3c5f5bd6..b6276753626e9ade2e8bec661e980fcfc3c95374 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -21,7 +21,6 @@
 #include <linux/kmemcheck.h>
 #include <linux/cpu.h>
 #include <linux/cpuset.h>
-#include <linux/kmemleak.h>
 #include <linux/mempolicy.h>
 #include <linux/ctype.h>
 #include <linux/debugobjects.h>
@@ -2605,6 +2604,8 @@ void kmem_cache_destroy(struct kmem_cache *s)
                                "still has objects.\n", s->name, __func__);
                        dump_stack();
                }
+               if (s->flags & SLAB_DESTROY_BY_RCU)
+                       rcu_barrier();
                sysfs_slab_remove(s);
        } else
                up_write(&slub_lock);
@@ -2833,13 +2834,15 @@ EXPORT_SYMBOL(__kmalloc);
 static void *kmalloc_large_node(size_t size, gfp_t flags, int node)
 {
        struct page *page;
+       void *ptr = NULL;
 
        flags |= __GFP_COMP | __GFP_NOTRACK;
        page = alloc_pages_node(node, flags, get_order(size));
        if (page)
-               return page_address(page);
-       else
-               return NULL;
+               ptr = page_address(page);
+
+       kmemleak_alloc(ptr, size, 1, flags);
+       return ptr;
 }
 
 #ifdef CONFIG_NUMA
@@ -2924,6 +2927,7 @@ void kfree(const void *x)
        page = virt_to_head_page(x);
        if (unlikely(!PageSlab(page))) {
                BUG_ON(!PageCompound(page));
+               kmemleak_free(x);
                put_page(page);
                return;
        }
index d1ade1a48ee7b962852c7645bc08b15c67924050..8ffdc0d23c536fe04779a9c559af68f6d9470997 100644 (file)
@@ -753,7 +753,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
 
                if (!bdev) {
                        if (bdev_p)
-                               *bdev_p = bdget(sis->bdev->bd_dev);
+                               *bdev_p = bdgrab(sis->bdev);
 
                        spin_unlock(&swap_lock);
                        return i;
@@ -765,7 +765,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
                                        struct swap_extent, list);
                        if (se->start_block == offset) {
                                if (bdev_p)
-                                       *bdev_p = bdget(sis->bdev->bd_dev);
+                                       *bdev_p = bdgrab(sis->bdev);
 
                                spin_unlock(&swap_lock);
                                bdput(bdev);
index 54155268dfcae49634dc016bb168845600a866a0..94e86dd6954c295830478011fd8e71465f1a9f2d 100644 (file)
@@ -630,9 +630,14 @@ static unsigned long shrink_page_list(struct list_head *page_list,
 
                referenced = page_referenced(page, 1,
                                                sc->mem_cgroup, &vm_flags);
-               /* In active use or really unfreeable?  Activate it. */
+               /*
+                * In active use or really unfreeable?  Activate it.
+                * If page which have PG_mlocked lost isoltation race,
+                * try_to_unmap moves it to unevictable list
+                */
                if (sc->order <= PAGE_ALLOC_COSTLY_ORDER &&
-                                       referenced && page_mapping_inuse(page))
+                                       referenced && page_mapping_inuse(page)
+                                       && !(vm_flags & VM_LOCKED))
                        goto activate_locked;
 
                /*
@@ -1104,7 +1109,7 @@ static unsigned long shrink_inactive_list(unsigned long max_scan,
                 */
                if (nr_freed < nr_taken && !current_is_kswapd() &&
                    lumpy_reclaim) {
-                       congestion_wait(WRITE, HZ/10);
+                       congestion_wait(BLK_RW_ASYNC, HZ/10);
 
                        /*
                         * The attempt at page out may have made some
@@ -1721,7 +1726,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
 
                /* Take a nap, wait for some writeback to complete */
                if (sc->nr_scanned && priority < DEF_PRIORITY - 2)
-                       congestion_wait(WRITE, HZ/10);
+                       congestion_wait(BLK_RW_ASYNC, HZ/10);
        }
        /* top priority shrink_zones still had more to do? don't OOM, then */
        if (!sc->all_unreclaimable && scanning_global_lru(sc))
@@ -1960,7 +1965,7 @@ loop_again:
                 * another pass across the zones.
                 */
                if (total_scanned && priority < DEF_PRIORITY - 2)
-                       congestion_wait(WRITE, HZ/10);
+                       congestion_wait(BLK_RW_ASYNC, HZ/10);
 
                /*
                 * We do this so kswapd doesn't build up large priorities for
@@ -2233,7 +2238,7 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
                                goto out;
 
                        if (sc.nr_scanned && prio < DEF_PRIORITY - 2)
-                               congestion_wait(WRITE, HZ / 10);
+                               congestion_wait(BLK_RW_ASYNC, HZ / 10);
                }
        }
 
index dd43a8289b0d9ecaf74aadc205063d2e2eaf8b3a..5bf5f227dbe0d83eaf28cc400a665594c6452a22 100644 (file)
@@ -60,9 +60,9 @@ static struct p9_req_t *
 p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...);
 
 /**
- * v9fs_parse_options - parse mount options into session structure
- * @options: options string passed from mount
- * @v9ses: existing v9fs session information
+ * parse_options - parse mount options into client structure
+ * @opts: options string passed from mount
+ * @clnt: existing v9fs client information
  *
  * Return 0 upon success, -ERRNO upon failure
  */
@@ -117,9 +117,6 @@ static int parse_opts(char *opts, struct p9_client *clnt)
                }
        }
 
-       if (!clnt->trans_mod)
-               clnt->trans_mod = v9fs_get_default_trans();
-
        kfree(options);
        return ret;
 }
@@ -235,7 +232,7 @@ EXPORT_SYMBOL(p9_tag_lookup);
 
 /**
  * p9_tag_init - setup tags structure and contents
- * @tags: tags structure from the client struct
+ * @c:  v9fs client struct
  *
  * This initializes the tags structure for each client instance.
  *
@@ -261,7 +258,7 @@ error:
 
 /**
  * p9_tag_cleanup - cleans up tags structure and reclaims resources
- * @tags: tags structure from the client struct
+ * @c:  v9fs client struct
  *
  * This frees resources associated with the tags structure
  *
@@ -414,14 +411,9 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
                if (c->dotu)
                        err = -ecode;
 
-               if (!err) {
+               if (!err || !IS_ERR_VALUE(err))
                        err = p9_errstr2errno(ename, strlen(ename));
 
-                       /* string match failed */
-                       if (!err)
-                               err = -ESERVERFAULT;
-               }
-
                P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename);
 
                kfree(ename);
@@ -433,8 +425,8 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
 
 /**
  * p9_client_flush - flush (cancel) a request
- * c: client state
- * req: request to cancel
+ * @c: client state
+ * @oldreq: request to cancel
  *
  * This sents a flush for a particular requests and links
  * the flush request to the original request.  The current
@@ -689,6 +681,9 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
        if (err < 0)
                goto error;
 
+       if (!clnt->trans_mod)
+               clnt->trans_mod = v9fs_get_default_trans();
+
        if (clnt->trans_mod == NULL) {
                err = -EPROTONOSUPPORT;
                P9_DPRINTK(P9_DEBUG_ERROR,
@@ -1098,7 +1093,6 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
 
        if (data) {
                memmove(data, dataptr, count);
-               data += count;
        }
 
        if (udata) {
@@ -1192,9 +1186,9 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
 
        err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret);
        if (err) {
-               ret = ERR_PTR(err);
                p9pdu_dump(1, req->rc);
-               goto free_and_error;
+               p9_free_req(clnt, req);
+               goto error;
        }
 
        P9_DPRINTK(P9_DEBUG_9P,
@@ -1211,8 +1205,6 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
        p9_free_req(clnt, req);
        return ret;
 
-free_and_error:
-       p9_free_req(clnt, req);
 error:
        kfree(ret);
        return ERR_PTR(err);
index fdebe4314062c01e02636d5201a2068ee57a640c..52518512a93e86eb261b34af3dddf6778a9ea50f 100644 (file)
@@ -239,7 +239,7 @@ int p9_errstr2errno(char *errstr, int len)
                errstr[len] = 0;
                printk(KERN_ERR "%s: server reported unknown error %s\n",
                        __func__, errstr);
-               errno = 1;
+               errno = ESERVERFAULT;
        }
 
        return -errno;
index a2a1814c7a8d639d6ccd76e9fdd966b7a6431fa6..8d934dd7fd5424049a811906e0467da91da208c3 100644 (file)
@@ -119,8 +119,8 @@ struct p9_poll_wait {
  * @wpos: write position for current frame
  * @wsize: amount of data to write for current frame
  * @wbuf: current write buffer
+ * @poll_pending_link: pending links to be polled per conn
  * @poll_wait: array of wait_q's for various worker threads
- * @poll_waddr: ????
  * @pt: poll state
  * @rq: current read work
  * @wq: current write work
@@ -700,9 +700,9 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
 }
 
 /**
- * parse_options - parse mount options into session structure
- * @options: options string passed from mount
- * @opts: transport-specific structure to parse options into
+ * parse_opts - parse mount options into p9_fd_opts structure
+ * @params: options string passed from mount
+ * @opts: fd transport-specific structure to parse options into
  *
  * Returns 0 upon success, -ERRNO upon failure
  */
@@ -735,12 +735,14 @@ static int parse_opts(char *params, struct p9_fd_opts *opts)
                if (!*p)
                        continue;
                token = match_token(p, tokens, args);
-               r = match_int(&args[0], &option);
-               if (r < 0) {
-                       P9_DPRINTK(P9_DEBUG_ERROR,
-                        "integer field, but no integer?\n");
-                       ret = r;
-                       continue;
+               if (token != Opt_err) {
+                       r = match_int(&args[0], &option);
+                       if (r < 0) {
+                               P9_DPRINTK(P9_DEBUG_ERROR,
+                               "integer field, but no integer?\n");
+                               ret = r;
+                               continue;
+                       }
                }
                switch (token) {
                case Opt_port:
index ac4990041ebb94d9935126f4cd76430fb7fa7201..65cb29db03f8cbd1440e62dfece699e4c8ff4c4f 100644 (file)
  * @pd: Protection Domain pointer
  * @qp: Queue Pair pointer
  * @cq: Completion Queue pointer
+ * @dm_mr: DMA Memory Region pointer
  * @lkey: The local access only memory region key
  * @timeout: Number of uSecs to wait for connection management events
  * @sq_depth: The depth of the Send Queue
  * @sq_sem: Semaphore for the SQ
  * @rq_depth: The depth of the Receive Queue.
+ * @rq_count: Count of requests in the Receive Queue.
  * @addr: The remote peer's address
  * @req_lock: Protects the active request list
- * @send_wait: Wait list when the SQ fills up
  * @cm_done: Completion event for connection management tracking
  */
 struct p9_trans_rdma {
@@ -154,9 +155,9 @@ static match_table_t tokens = {
 };
 
 /**
- * parse_options - parse mount options into session structure
- * @options: options string passed from mount
- * @opts: transport-specific structure to parse options into
+ * parse_opts - parse mount options into rdma options structure
+ * @params: options string passed from mount
+ * @opts: rdma transport-specific structure to parse options into
  *
  * Returns 0 upon success, -ERRNO upon failure
  */
index a49484e67e1ddf2b1dcd2ae1ed0ee71a8872521f..9bf0b737aa517fde7bee51821be494e743a67cce 100644 (file)
@@ -57,11 +57,9 @@ static int chan_index;
  * @initialized: whether the channel is initialized
  * @inuse: whether the channel is in use
  * @lock: protects multiple elements within this structure
+ * @client: client instance
  * @vdev: virtio dev associated with this channel
  * @vq: virtio queue associated with this channel
- * @tagpool: accounting for tag ids (and request slots)
- * @reqs: array of request slots
- * @max_tag: current number of request_slots allocated
  * @sg: scatter gather list which is used to pack a request (protected?)
  *
  * We keep all per-channel information in a structure.
@@ -92,7 +90,7 @@ static unsigned int rest_of_page(void *data)
 
 /**
  * p9_virtio_close - reclaim resources of a channel
- * @trans: transport state
+ * @client: client instance
  *
  * This reclaims a channel by freeing its resources and
  * reseting its inuse flag.
@@ -181,9 +179,8 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req)
 
 /**
  * p9_virtio_request - issue a request
- * @t: transport state
- * @tc: &p9_fcall request to transmit
- * @rc: &p9_fcall to put reponse into
+ * @client: client instance issuing the request
+ * @req: request to be issued
  *
  */
 
index 590b8396362237e62b82965b2f6e95fb1c167591..875eda5dbad7777949fcbdc848d6ee29ed0d7cec 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/if_arp.h>
+#include <linux/smp_lock.h>
 #include <linux/termios.h>     /* For TIOCOUTQ/INQ */
 #include <net/datalink.h>
 #include <net/psnap.h>
@@ -1237,6 +1238,7 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
                        return -ENOBUFS;
 
        *uaddr_len = sizeof(struct sockaddr_at);
+       memset(&sat.sat_zero, 0, sizeof(sat.sat_zero));
 
        if (peer) {
                if (sk->sk_state != TCP_ESTABLISHED)
index c1c97936192c730d8f68431a782f8695c43504a3..8c4d843eb17f46bbec50847aa1352580adcd1c26 100644 (file)
@@ -92,7 +92,7 @@ static void vcc_sock_destruct(struct sock *sk)
 static void vcc_def_wakeup(struct sock *sk)
 {
        read_lock(&sk->sk_callback_lock);
-       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+       if (sk_has_sleeper(sk))
                wake_up(sk->sk_sleep);
        read_unlock(&sk->sk_callback_lock);
 }
@@ -110,7 +110,7 @@ static void vcc_write_space(struct sock *sk)
        read_lock(&sk->sk_callback_lock);
 
        if (vcc_writable(sk)) {
-               if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+               if (sk_has_sleeper(sk))
                        wake_up_interruptible(sk->sk_sleep);
 
                sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
@@ -594,7 +594,7 @@ unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait)
        struct atm_vcc *vcc;
        unsigned int mask;
 
-       poll_wait(file, sk->sk_sleep, wait);
+       sock_poll_wait(file, sk->sk_sleep, wait);
        mask = 0;
 
        vcc = ATM_SD(sock);
index e50566ebf9f909af1c54409a02ea25b9b252e809..94b3388c188b4363aaac56a0a9d8f6e2c1d741cd 100644 (file)
@@ -2080,28 +2080,41 @@ static CLASS_ATTR(rfcomm_dlc, S_IRUGO, rfcomm_dlc_sysfs_show, NULL);
 /* ---- Initialization ---- */
 static int __init rfcomm_init(void)
 {
+       int ret;
+
        l2cap_load();
 
        hci_register_cb(&rfcomm_cb);
 
        rfcomm_thread = kthread_run(rfcomm_run, NULL, "krfcommd");
        if (IS_ERR(rfcomm_thread)) {
-               hci_unregister_cb(&rfcomm_cb);
-               return PTR_ERR(rfcomm_thread);
+               ret = PTR_ERR(rfcomm_thread);
+               goto out_thread;
        }
 
        if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0)
                BT_ERR("Failed to create RFCOMM info file");
 
-       rfcomm_init_sockets();
+       ret = rfcomm_init_ttys();
+       if (ret)
+               goto out_tty;
 
-#ifdef CONFIG_BT_RFCOMM_TTY
-       rfcomm_init_ttys();
-#endif
+       ret = rfcomm_init_sockets();
+       if (ret)
+               goto out_sock;
 
        BT_INFO("RFCOMM ver %s", VERSION);
 
        return 0;
+
+out_sock:
+       rfcomm_cleanup_ttys();
+out_tty:
+       kthread_stop(rfcomm_thread);
+out_thread:
+       hci_unregister_cb(&rfcomm_cb);
+
+       return ret;
 }
 
 static void __exit rfcomm_exit(void)
@@ -2112,9 +2125,7 @@ static void __exit rfcomm_exit(void)
 
        kthread_stop(rfcomm_thread);
 
-#ifdef CONFIG_BT_RFCOMM_TTY
        rfcomm_cleanup_ttys();
-#endif
 
        rfcomm_cleanup_sockets();
 }
index 7f482784e9f7b3a3e2033c58459e0d9136053701..0b85e8116859b21592d52d09f32e1ceb1bdad1f7 100644 (file)
@@ -1132,7 +1132,7 @@ error:
        return err;
 }
 
-void __exit rfcomm_cleanup_sockets(void)
+void rfcomm_cleanup_sockets(void)
 {
        class_remove_file(bt_class, &class_attr_rfcomm);
 
index 9aac5213105aaf031e5ca1fcc993a051800e1475..e1241c76239a96fb3e4d027ba071b640c2904ceb 100644 (file)
@@ -93,7 +93,7 @@ static void __exit br_deinit(void)
 
        unregister_pernet_subsys(&br_net_ops);
 
-       synchronize_net();
+       rcu_barrier(); /* Wait for completion of call_rcu()'s */
 
        br_netfilter_fini();
 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
index 8a96672e2c5c462fb3f575df3ba4d8c25a03727d..eb404dc3ed6e213e4148ba1f7b13bb1d0570a4e1 100644 (file)
@@ -424,7 +424,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 err2:
        br_fdb_delete_by_port(br, p, 1);
 err1:
-       kobject_del(&p->kobj);
+       kobject_put(&p->kobj);
 err0:
        dev_set_promiscuity(dev, -1);
 put_back:
index 95d7f32643aef3a3e0b3830200ea592bb1b54849..72720c7103515d6211da62c387f48f37ad69c56f 100644 (file)
@@ -75,6 +75,7 @@ static __initdata const char banner[] = KERN_INFO
 MODULE_DESCRIPTION("PF_CAN broadcast manager protocol");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
+MODULE_ALIAS("can-proto-2");
 
 /* easy access to can_frame payload */
 static inline u64 GET_U64(const struct can_frame *cp)
@@ -1469,6 +1470,9 @@ static int bcm_release(struct socket *sock)
                bo->ifindex = 0;
        }
 
+       sock_orphan(sk);
+       sock->sk = NULL;
+
        release_sock(sk);
        sock_put(sk);
 
index 6aa154e806ae722c53e71603c0b22865526452a0..db3152df7d2b627fd2484c14734e9a084d3e93a0 100644 (file)
@@ -62,6 +62,7 @@ static __initdata const char banner[] =
 MODULE_DESCRIPTION("PF_CAN raw protocol");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>");
+MODULE_ALIAS("can-proto-1");
 
 #define MASK_ALL 0
 
@@ -306,6 +307,9 @@ static int raw_release(struct socket *sock)
        ro->bound   = 0;
        ro->count   = 0;
 
+       sock_orphan(sk);
+       sock->sk = NULL;
+
        release_sock(sk);
        sock_put(sk);
 
@@ -397,6 +401,7 @@ static int raw_getname(struct socket *sock, struct sockaddr *uaddr,
        if (peer)
                return -EOPNOTSUPP;
 
+       memset(addr, 0, sizeof(*addr));
        addr->can_family  = AF_CAN;
        addr->can_ifindex = ro->ifindex;
 
index 58abee1f1df1b044514079f9245dc7c1b96978a3..b0fe69211eefef1e18224fa123d2b13498bffefa 100644 (file)
@@ -712,7 +712,7 @@ unsigned int datagram_poll(struct file *file, struct socket *sock,
        struct sock *sk = sock->sk;
        unsigned int mask;
 
-       poll_wait(file, sk->sk_sleep, wait);
+       sock_poll_wait(file, sk->sk_sleep, wait);
        mask = 0;
 
        /* exceptional events? */
index 60b5728122784a66562da3a4aec075692252382a..6a94475aee8594279eb90d94cc164c5169e533c5 100644 (file)
@@ -2823,9 +2823,11 @@ static void net_rx_action(struct softirq_action *h)
                 * move the instance around on the list at-will.
                 */
                if (unlikely(work == weight)) {
-                       if (unlikely(napi_disable_pending(n)))
-                               __napi_complete(n);
-                       else
+                       if (unlikely(napi_disable_pending(n))) {
+                               local_irq_enable();
+                               napi_complete(n);
+                               local_irq_disable();
+                       } else
                                list_move_tail(&n->poll_list, list);
                }
 
@@ -3863,10 +3865,12 @@ int dev_unicast_delete(struct net_device *dev, void *addr)
 
        ASSERT_RTNL();
 
+       netif_addr_lock_bh(dev);
        err = __hw_addr_del(&dev->uc, addr, dev->addr_len,
                            NETDEV_HW_ADDR_T_UNICAST);
        if (!err)
                __dev_set_rx_mode(dev);
+       netif_addr_unlock_bh(dev);
        return err;
 }
 EXPORT_SYMBOL(dev_unicast_delete);
@@ -3887,10 +3891,12 @@ int dev_unicast_add(struct net_device *dev, void *addr)
 
        ASSERT_RTNL();
 
+       netif_addr_lock_bh(dev);
        err = __hw_addr_add(&dev->uc, addr, dev->addr_len,
                            NETDEV_HW_ADDR_T_UNICAST);
        if (!err)
                __dev_set_rx_mode(dev);
+       netif_addr_unlock_bh(dev);
        return err;
 }
 EXPORT_SYMBOL(dev_unicast_add);
@@ -3947,7 +3953,8 @@ void __dev_addr_unsync(struct dev_addr_list **to, int *to_count,
  *     @from: source device
  *
  *     Add newly added addresses to the destination device and release
- *     addresses that have no users left.
+ *     addresses that have no users left. The source device must be
+ *     locked by netif_tx_lock_bh.
  *
  *     This function is intended to be called from the dev->set_rx_mode
  *     function of layered software devices.
@@ -3956,14 +3963,14 @@ int dev_unicast_sync(struct net_device *to, struct net_device *from)
 {
        int err = 0;
 
-       ASSERT_RTNL();
-
        if (to->addr_len != from->addr_len)
                return -EINVAL;
 
+       netif_addr_lock_bh(to);
        err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len);
        if (!err)
                __dev_set_rx_mode(to);
+       netif_addr_unlock_bh(to);
        return err;
 }
 EXPORT_SYMBOL(dev_unicast_sync);
@@ -3979,27 +3986,27 @@ EXPORT_SYMBOL(dev_unicast_sync);
  */
 void dev_unicast_unsync(struct net_device *to, struct net_device *from)
 {
-       ASSERT_RTNL();
-
        if (to->addr_len != from->addr_len)
                return;
 
+       netif_addr_lock_bh(from);
+       netif_addr_lock(to);
        __hw_addr_unsync(&to->uc, &from->uc, to->addr_len);
        __dev_set_rx_mode(to);
+       netif_addr_unlock(to);
+       netif_addr_unlock_bh(from);
 }
 EXPORT_SYMBOL(dev_unicast_unsync);
 
 static void dev_unicast_flush(struct net_device *dev)
 {
-       /* rtnl_mutex must be held here */
-
+       netif_addr_lock_bh(dev);
        __hw_addr_flush(&dev->uc);
+       netif_addr_unlock_bh(dev);
 }
 
 static void dev_unicast_init(struct net_device *dev)
 {
-       /* rtnl_mutex must be held here */
-
        __hw_addr_init(&dev->uc);
 }
 
index 78e5bfc454ae00e627705515cbd857cd3d9c67d9..493775f4f2f1d7c19b618640e186aae7195ded53 100644 (file)
@@ -81,7 +81,7 @@
 struct gen_estimator
 {
        struct list_head        list;
-       struct gnet_stats_basic *bstats;
+       struct gnet_stats_basic_packed  *bstats;
        struct gnet_stats_rate_est      *rate_est;
        spinlock_t              *stats_lock;
        int                     ewma_log;
@@ -165,7 +165,7 @@ static void gen_add_node(struct gen_estimator *est)
 }
 
 static
-struct gen_estimator *gen_find_node(const struct gnet_stats_basic *bstats,
+struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats,
                                    const struct gnet_stats_rate_est *rate_est)
 {
        struct rb_node *p = est_root.rb_node;
@@ -202,7 +202,7 @@ struct gen_estimator *gen_find_node(const struct gnet_stats_basic *bstats,
  *
  * NOTE: Called under rtnl_mutex
  */
-int gen_new_estimator(struct gnet_stats_basic *bstats,
+int gen_new_estimator(struct gnet_stats_basic_packed *bstats,
                      struct gnet_stats_rate_est *rate_est,
                      spinlock_t *stats_lock,
                      struct nlattr *opt)
@@ -262,7 +262,7 @@ static void __gen_kill_estimator(struct rcu_head *head)
  *
  * NOTE: Called under rtnl_mutex
  */
-void gen_kill_estimator(struct gnet_stats_basic *bstats,
+void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,
                        struct gnet_stats_rate_est *rate_est)
 {
        struct gen_estimator *e;
@@ -292,7 +292,7 @@ EXPORT_SYMBOL(gen_kill_estimator);
  *
  * Returns 0 on success or a negative error code.
  */
-int gen_replace_estimator(struct gnet_stats_basic *bstats,
+int gen_replace_estimator(struct gnet_stats_basic_packed *bstats,
                          struct gnet_stats_rate_est *rate_est,
                          spinlock_t *stats_lock, struct nlattr *opt)
 {
@@ -308,7 +308,7 @@ EXPORT_SYMBOL(gen_replace_estimator);
  *
  * Returns true if estimator is active, and false if not.
  */
-bool gen_estimator_active(const struct gnet_stats_basic *bstats,
+bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,
                          const struct gnet_stats_rate_est *rate_est)
 {
        ASSERT_RTNL();
index c3d0ffeac24342417bca0017e3d55e7c05100018..8569310268ab76ba786402e6b2e6dc994621a7fd 100644 (file)
@@ -106,16 +106,21 @@ gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock,
  * if the room in the socket buffer was not sufficient.
  */
 int
-gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic *b)
+gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic_packed *b)
 {
        if (d->compat_tc_stats) {
                d->tc_stats.bytes = b->bytes;
                d->tc_stats.packets = b->packets;
        }
 
-       if (d->tail)
-               return gnet_stats_copy(d, TCA_STATS_BASIC, b, sizeof(*b));
+       if (d->tail) {
+               struct gnet_stats_basic sb;
 
+               memset(&sb, 0, sizeof(sb));
+               sb.bytes = b->bytes;
+               sb.packets = b->packets;
+               return gnet_stats_copy(d, TCA_STATS_BASIC, &sb, sizeof(sb));
+       }
        return 0;
 }
 
index b7292a2719dc046bd6772cbd8ee4926e811d0254..197283072cc88a9981f21adc9b59d4df8a66557a 100644 (file)
@@ -488,7 +488,7 @@ int net_assign_generic(struct net *net, int id, void *data)
         */
 
        ng->len = id;
-       memcpy(&ng->ptr, &old_ng->ptr, old_ng->len);
+       memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*));
 
        rcu_assign_pointer(net->gen, ng);
        call_rcu(&old_ng->rcu, net_generic_release);
index 9675f312830dd762bcd530eee90569de5a89b320..1b76eb11deb4a2632a9daca75a414a2906123db4 100644 (file)
@@ -319,6 +319,11 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
 
                        udelay(USEC_PER_POLL);
                }
+
+               WARN_ONCE(!irqs_disabled(),
+                       "netpoll_send_skb(): %s enabled interrupts in poll (%pF)\n",
+                       dev->name, ops->ndo_start_xmit);
+
                local_irq_restore(flags);
        }
 
@@ -740,7 +745,7 @@ int netpoll_setup(struct netpoll *np)
                                       np->name);
                                break;
                        }
-                       cond_resched();
+                       msleep(1);
                }
 
                /* If carrier appears to come up instantly, we don't
index b0ba569bc97361dec5b2619a46ffbeab50331dc2..76334228ed1c36e93513a3236957476c1e13291e 100644 (file)
@@ -631,7 +631,7 @@ set_rcvbuf:
 
        case SO_TIMESTAMPING:
                if (val & ~SOF_TIMESTAMPING_MASK) {
-                       ret = EINVAL;
+                       ret = -EINVAL;
                        break;
                }
                sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE,
@@ -919,13 +919,19 @@ static inline void sock_lock_init(struct sock *sk)
                        af_family_keys + sk->sk_family);
 }
 
+/*
+ * Copy all fields from osk to nsk but nsk->sk_refcnt must not change yet,
+ * even temporarly, because of RCU lookups. sk_node should also be left as is.
+ */
 static void sock_copy(struct sock *nsk, const struct sock *osk)
 {
 #ifdef CONFIG_SECURITY_NETWORK
        void *sptr = nsk->sk_security;
 #endif
-
-       memcpy(nsk, osk, osk->sk_prot->obj_size);
+       BUILD_BUG_ON(offsetof(struct sock, sk_copy_start) !=
+                    sizeof(osk->sk_node) + sizeof(osk->sk_refcnt));
+       memcpy(&nsk->sk_copy_start, &osk->sk_copy_start,
+              osk->sk_prot->obj_size - offsetof(struct sock, sk_copy_start));
 #ifdef CONFIG_SECURITY_NETWORK
        nsk->sk_security = sptr;
        security_sk_clone(osk, nsk);
@@ -939,8 +945,23 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
        struct kmem_cache *slab;
 
        slab = prot->slab;
-       if (slab != NULL)
-               sk = kmem_cache_alloc(slab, priority);
+       if (slab != NULL) {
+               sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO);
+               if (!sk)
+                       return sk;
+               if (priority & __GFP_ZERO) {
+                       /*
+                        * caches using SLAB_DESTROY_BY_RCU should let
+                        * sk_node.next un-modified. Special care is taken
+                        * when initializing object to zero.
+                        */
+                       if (offsetof(struct sock, sk_node.next) != 0)
+                               memset(sk, 0, offsetof(struct sock, sk_node.next));
+                       memset(&sk->sk_node.pprev, 0,
+                              prot->obj_size - offsetof(struct sock,
+                                                        sk_node.pprev));
+               }
+       }
        else
                sk = kmalloc(prot->obj_size, priority);
 
@@ -1004,6 +1025,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
                sk->sk_prot = sk->sk_prot_creator = prot;
                sock_lock_init(sk);
                sock_net_set(sk, get_net(net));
+               atomic_set(&sk->sk_wmem_alloc, 1);
        }
 
        return sk;
@@ -1125,6 +1147,11 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
 
                newsk->sk_err      = 0;
                newsk->sk_priority = 0;
+               /*
+                * Before updating sk_refcnt, we must commit prior changes to memory
+                * (Documentation/RCU/rculist_nulls.txt for details)
+                */
+               smp_wmb();
                atomic_set(&newsk->sk_refcnt, 2);
 
                /*
@@ -1715,7 +1742,7 @@ EXPORT_SYMBOL(sock_no_sendpage);
 static void sock_def_wakeup(struct sock *sk)
 {
        read_lock(&sk->sk_callback_lock);
-       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+       if (sk_has_sleeper(sk))
                wake_up_interruptible_all(sk->sk_sleep);
        read_unlock(&sk->sk_callback_lock);
 }
@@ -1723,7 +1750,7 @@ static void sock_def_wakeup(struct sock *sk)
 static void sock_def_error_report(struct sock *sk)
 {
        read_lock(&sk->sk_callback_lock);
-       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+       if (sk_has_sleeper(sk))
                wake_up_interruptible_poll(sk->sk_sleep, POLLERR);
        sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR);
        read_unlock(&sk->sk_callback_lock);
@@ -1732,7 +1759,7 @@ static void sock_def_error_report(struct sock *sk)
 static void sock_def_readable(struct sock *sk, int len)
 {
        read_lock(&sk->sk_callback_lock);
-       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+       if (sk_has_sleeper(sk))
                wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN |
                                                POLLRDNORM | POLLRDBAND);
        sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
@@ -1747,7 +1774,7 @@ static void sock_def_write_space(struct sock *sk)
         * progress.  --DaveM
         */
        if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) {
-               if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+               if (sk_has_sleeper(sk))
                        wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT |
                                                POLLWRNORM | POLLWRBAND);
 
@@ -1840,8 +1867,12 @@ void sock_init_data(struct socket *sock, struct sock *sk)
 
        sk->sk_stamp = ktime_set(-1L, 0);
 
+       /*
+        * Before updating sk_refcnt, we must commit prior changes to memory
+        * (Documentation/RCU/rculist_nulls.txt for details)
+        */
+       smp_wmb();
        atomic_set(&sk->sk_refcnt, 1);
-       atomic_set(&sk->sk_wmem_alloc, 1);
        atomic_set(&sk->sk_drops, 0);
 }
 EXPORT_SYMBOL(sock_init_data);
index c0e88c16d0888b5222ca250c01a27bf3078a7e2a..c96119fda6885fd6b6bdc5487ff5cca7d2dd1574 100644 (file)
@@ -196,7 +196,7 @@ void dccp_write_space(struct sock *sk)
 {
        read_lock(&sk->sk_callback_lock);
 
-       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+       if (sk_has_sleeper(sk))
                wake_up_interruptible(sk->sk_sleep);
        /* Should agree with poll, otherwise some programs break */
        if (sock_writeable(sk))
index 314a1b5c033c88950ddf73eccf30a34bcaf60191..1bca9205104e6c5ff41b4e3562825f9cf1079e9b 100644 (file)
@@ -311,7 +311,7 @@ unsigned int dccp_poll(struct file *file, struct socket *sock,
        unsigned int mask;
        struct sock *sk = sock->sk;
 
-       poll_wait(file, sk->sk_sleep, wait);
+       sock_poll_wait(file, sk->sk_sleep, wait);
        if (sk->sk_state == DCCP_LISTEN)
                return inet_csk_listen_poll(sk);
 
@@ -1066,7 +1066,7 @@ static int __init dccp_init(void)
                       (dccp_hashinfo.ehash_size - 1))
                        dccp_hashinfo.ehash_size--;
                dccp_hashinfo.ehash = (struct inet_ehash_bucket *)
-                       __get_free_pages(GFP_ATOMIC, ehash_order);
+                       __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, ehash_order);
        } while (!dccp_hashinfo.ehash && --ehash_order > 0);
 
        if (!dccp_hashinfo.ehash) {
@@ -1091,7 +1091,7 @@ static int __init dccp_init(void)
                    bhash_order > 0)
                        continue;
                dccp_hashinfo.bhash = (struct inet_bind_hashbucket *)
-                       __get_free_pages(GFP_ATOMIC, bhash_order);
+                       __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, bhash_order);
        } while (!dccp_hashinfo.bhash && --bhash_order >= 0);
 
        if (!dccp_hashinfo.bhash) {
@@ -1159,6 +1159,7 @@ static void __exit dccp_fini(void)
        kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
        dccp_ackvec_exit();
        dccp_sysctl_exit();
+       percpu_counter_destroy(&dccp_orphan_count);
 }
 
 module_init(dccp_init);
index d351b8db0df5ceac6f6c566bb82cb9a700d78d2a..77d40289653cf0e739e5893e0e053c2145d6156a 100644 (file)
@@ -2413,6 +2413,8 @@ static void __exit decnet_exit(void)
        proc_net_remove(&init_net, "decnet");
 
        proto_unregister(&dn_proto);
+
+       rcu_barrier_bh(); /* Wait for completion of call_rcu_bh()'s */
 }
 module_exit(decnet_exit);
 #endif
index 4e4d8b5ad03d3b58fe6c0e353e147b2b78fa5144..efe661a9def4db3644d0e8402e2b00295a3cd0c6 100644 (file)
@@ -418,7 +418,7 @@ static int mv88e6xxx_stats_wait(struct dsa_switch *ds)
        int i;
 
        for (i = 0; i < 10; i++) {
-               ret = REG_READ(REG_GLOBAL2, 0x1d);
+               ret = REG_READ(REG_GLOBAL, 0x1d);
                if ((ret & 0x8000) == 0)
                        return 0;
        }
index 2e1f836d424064ffe346321e053c136f86682545..f0bbc57926cdbbb8d70b3e2e59cbdd4f090800f3 100644 (file)
@@ -520,6 +520,7 @@ static int econet_getname(struct socket *sock, struct sockaddr *uaddr,
        if (peer)
                return -EOPNOTSUPP;
 
+       memset(sec, 0, sizeof(*sec));
        mutex_lock(&econet_mutex);
 
        sk = sock->sk;
index 3bb6bdb1dac1d95b537af4752b4039acfd1d52e2..af661805b9fa2a916f4a670ff3c96223e26a03d2 100644 (file)
@@ -136,7 +136,7 @@ static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg,
                unsigned int cmd)
 {
        struct ifreq ifr;
-       int ret = -EINVAL;
+       int ret = -ENOIOCTLCMD;
        struct net_device *dev;
 
        if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
@@ -146,8 +146,10 @@ static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg,
 
        dev_load(sock_net(sk), ifr.ifr_name);
        dev = dev_get_by_name(sock_net(sk), ifr.ifr_name);
-       if (dev->type == ARPHRD_IEEE802154 ||
-           dev->type == ARPHRD_IEEE802154_PHY)
+
+       if ((dev->type == ARPHRD_IEEE802154 ||
+            dev->type == ARPHRD_IEEE802154_PHY) &&
+           dev->netdev_ops->ndo_do_ioctl)
                ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd);
 
        if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq)))
index 14d39840dd62e736e9dfb96efc011c5b41dd92ab..ba8b214dda8fc027c802fcc65c9845be40d0c562 100644 (file)
@@ -377,6 +377,18 @@ int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb)
        return ret;
 }
 
+static int dgram_getsockopt(struct sock *sk, int level, int optname,
+                   char __user *optval, int __user *optlen)
+{
+       return -EOPNOTSUPP;
+}
+
+static int dgram_setsockopt(struct sock *sk, int level, int optname,
+                   char __user *optval, int __user optlen)
+{
+       return -EOPNOTSUPP;
+}
+
 struct proto ieee802154_dgram_prot = {
        .name           = "IEEE-802.15.4-MAC",
        .owner          = THIS_MODULE,
@@ -391,5 +403,7 @@ struct proto ieee802154_dgram_prot = {
        .connect        = dgram_connect,
        .disconnect     = dgram_disconnect,
        .ioctl          = dgram_ioctl,
+       .getsockopt     = dgram_getsockopt,
+       .setsockopt     = dgram_setsockopt,
 };
 
index 105ad10876afe3dc06d2a5d2002900b297601879..27eda9fdf3c207f371864fa7ee81c2480f6999e9 100644 (file)
@@ -276,6 +276,9 @@ static struct net_device *ieee802154_nl_get_dev(struct genl_info *info)
        else
                return NULL;
 
+       if (!dev)
+               return NULL;
+
        if (dev->type != ARPHRD_IEEE802154) {
                dev_put(dev);
                return NULL;
@@ -521,3 +524,6 @@ static void __exit ieee802154_nl_exit(void)
 }
 module_exit(ieee802154_nl_exit);
 
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ieee 802.15.4 configuration interface");
+
index fca44d59f97ec05ca02d9221da22d5b6b9fea3dc..9315977c4c61de127499d9e151586f82cd8a61f4 100644 (file)
@@ -238,6 +238,18 @@ void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb)
        read_unlock(&raw_lock);
 }
 
+static int raw_getsockopt(struct sock *sk, int level, int optname,
+                   char __user *optval, int __user *optlen)
+{
+       return -EOPNOTSUPP;
+}
+
+static int raw_setsockopt(struct sock *sk, int level, int optname,
+                   char __user *optval, int __user optlen)
+{
+       return -EOPNOTSUPP;
+}
+
 struct proto ieee802154_raw_prot = {
        .name           = "IEEE-802.15.4-RAW",
        .owner          = THIS_MODULE,
@@ -250,5 +262,7 @@ struct proto ieee802154_raw_prot = {
        .unhash         = raw_unhash,
        .connect        = raw_connect,
        .disconnect     = raw_disconnect,
+       .getsockopt     = raw_getsockopt,
+       .setsockopt     = raw_setsockopt,
 };
 
index 8a3881e28aca42d5066970276085bfdbe1535499..090e9991ac2a288f31f378ad327b4c18a2b8ecba 100644 (file)
@@ -801,11 +801,8 @@ static int arp_process(struct sk_buff *skb)
  *  cache.
  */
 
-       /*
-        *  Special case: IPv4 duplicate address detection packet (RFC2131)
-        *  and Gratuitous ARP/ARP Announce. (RFC3927, Section 2.4)
-        */
-       if (sip == 0 || tip == sip) {
+       /* Special case: IPv4 duplicate address detection packet (RFC2131) */
+       if (sip == 0) {
                if (arp->ar_op == htons(ARPOP_REQUEST) &&
                    inet_addr_type(net, tip) == RTN_LOCAL &&
                    !arp_ignore(in_dev, sip, tip))
@@ -1307,7 +1304,9 @@ static void arp_format_neigh_entry(struct seq_file *seq,
                hbuffer[k++] = hex_asc_lo(n->ha[j]);
                hbuffer[k++] = ':';
        }
-       hbuffer[--k] = 0;
+       if (k != 0)
+               --k;
+       hbuffer[k] = 0;
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
        }
 #endif
index 012cf5a685814bdff7c538ccbdc8805519ed0939..63c2fa7b68c4b922840fe883bd9bdf0e9a6c21c7 100644 (file)
@@ -316,8 +316,8 @@ static inline void check_tnode(const struct tnode *tn)
 
 static const int halve_threshold = 25;
 static const int inflate_threshold = 50;
-static const int halve_threshold_root = 8;
-static const int inflate_threshold_root = 15;
+static const int halve_threshold_root = 15;
+static const int inflate_threshold_root = 25;
 
 
 static void __alias_free_mem(struct rcu_head *head)
@@ -1021,6 +1021,9 @@ static void trie_rebalance(struct trie *t, struct tnode *tn)
                                      (struct node *)tn, wasfull);
 
                tp = node_parent((struct node *) tn);
+               if (!tp)
+                       rcu_assign_pointer(t->trie, (struct node *)tn);
+
                tnode_free_flush();
                if (!tp)
                        break;
index 44e2a3d2359afd99da1324022c221e811d83a0a9..82c11dd10a628947e1486e300918acd848e0d718 100644 (file)
@@ -735,10 +735,10 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        tos = tiph->tos;
-       if (tos&1) {
+       if (tos == 1) {
+               tos = 0;
                if (skb->protocol == htons(ETH_P_IP))
                        tos = old_iph->tos;
-               tos &= ~1;
        }
 
        {
@@ -951,7 +951,7 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev)
                        addend += 4;
        }
        dev->needed_headroom = addend + hlen;
-       mtu -= dev->hard_header_len - addend;
+       mtu -= dev->hard_header_len + addend;
 
        if (mtu < 68)
                mtu = 68;
index 490ce20faf38b8bbe47aa60d1c7b1b1847fe1059..db46b4b5b2b9429db018b1abcadaf26d92316048 100644 (file)
@@ -440,6 +440,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
        /* Remove any debris in the socket control block */
        memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
 
+       /* Must drop socket now because of tproxy. */
+       skb_orphan(skb);
+
        return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, dev, NULL,
                       ip_rcv_finish);
 
index 2470262826694d122b5457d6ef4144b66429d7a2..7ffcd96fe591921bd139a1de925991b97f9a74f0 100644 (file)
@@ -813,6 +813,8 @@ int ip_append_data(struct sock *sk,
                        inet->cork.addr = ipc->addr;
                }
                rt = *rtp;
+               if (unlikely(!rt))
+                       return -EFAULT;
                /*
                 * We steal reference to this route, caller should not release it
                 */
@@ -1243,7 +1245,6 @@ int ip_push_pending_frames(struct sock *sk)
                skb->len += tmp_skb->len;
                skb->data_len += tmp_skb->len;
                skb->truesize += tmp_skb->truesize;
-               __sock_put(tmp_skb->sk);
                tmp_skb->destructor = NULL;
                tmp_skb->sk = NULL;
        }
index 155c008626c825729e5ac09fa45740e0bd8486c8..09172a65d9b61ea8de3cd52301e5c1e064d5b123 100644 (file)
@@ -191,7 +191,8 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb,
                                    ct, ctinfo);
                /* Tell TCP window tracking about seq change */
                nf_conntrack_tcp_update(skb, ip_hdrlen(skb),
-                                       ct, CTINFO2DIR(ctinfo));
+                                       ct, CTINFO2DIR(ctinfo),
+                                       (int)rep_len - (int)match_len);
 
                nf_conntrack_event_cache(IPCT_NATSEQADJ, ct);
        }
@@ -377,6 +378,7 @@ nf_nat_seq_adjust(struct sk_buff *skb,
        struct tcphdr *tcph;
        int dir;
        __be32 newseq, newack;
+       s16 seqoff, ackoff;
        struct nf_conn_nat *nat = nfct_nat(ct);
        struct nf_nat_seq *this_way, *other_way;
 
@@ -390,15 +392,18 @@ nf_nat_seq_adjust(struct sk_buff *skb,
 
        tcph = (void *)skb->data + ip_hdrlen(skb);
        if (after(ntohl(tcph->seq), this_way->correction_pos))
-               newseq = htonl(ntohl(tcph->seq) + this_way->offset_after);
+               seqoff = this_way->offset_after;
        else
-               newseq = htonl(ntohl(tcph->seq) + this_way->offset_before);
+               seqoff = this_way->offset_before;
 
        if (after(ntohl(tcph->ack_seq) - other_way->offset_before,
                  other_way->correction_pos))
-               newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_after);
+               ackoff = other_way->offset_after;
        else
-               newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before);
+               ackoff = other_way->offset_before;
+
+       newseq = htonl(ntohl(tcph->seq) + seqoff);
+       newack = htonl(ntohl(tcph->ack_seq) - ackoff);
 
        inet_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0);
        inet_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0);
@@ -413,7 +418,7 @@ nf_nat_seq_adjust(struct sk_buff *skb,
        if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo))
                return 0;
 
-       nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir);
+       nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir, seqoff);
 
        return 1;
 }
index 17b89c523f9d1ac590dbc575c8d6be7664851cbb..91145244ea630777e7e4a2e7f112f3c31bc7f90e 100644 (file)
@@ -339,7 +339,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
        struct sock *sk = sock->sk;
        struct tcp_sock *tp = tcp_sk(sk);
 
-       poll_wait(file, sk->sk_sleep, wait);
+       sock_poll_wait(file, sk->sk_sleep, wait);
        if (sk->sk_state == TCP_LISTEN)
                return inet_csk_listen_poll(sk);
 
@@ -903,13 +903,17 @@ int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
                iov++;
 
                while (seglen > 0) {
-                       int copy;
+                       int copy = 0;
+                       int max = size_goal;
 
                        skb = tcp_write_queue_tail(sk);
+                       if (tcp_send_head(sk)) {
+                               if (skb->ip_summed == CHECKSUM_NONE)
+                                       max = mss_now;
+                               copy = max - skb->len;
+                       }
 
-                       if (!tcp_send_head(sk) ||
-                           (copy = size_goal - skb->len) <= 0) {
-
+                       if (copy <= 0) {
 new_segment:
                                /* Allocate new segment. If the interface is SG,
                                 * allocate skb fitting to single page.
@@ -930,6 +934,7 @@ new_segment:
 
                                skb_entail(sk, skb);
                                copy = size_goal;
+                               max = size_goal;
                        }
 
                        /* Try to append data to the end of skb. */
@@ -1028,7 +1033,7 @@ new_segment:
                        if ((seglen -= copy) == 0 && iovlen == 0)
                                goto out;
 
-                       if (skb->len < size_goal || (flags & MSG_OOB))
+                       if (skb->len < max || (flags & MSG_OOB))
                                continue;
 
                        if (forced_push(tp)) {
index 5a1ca2698c885775914f05fe17ae45d485cbddd2..6d88219c5e22bd4bf752a543bebfb5af4ae36a1f 100644 (file)
@@ -1160,6 +1160,7 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = {
 #ifdef CONFIG_TCP_MD5SIG
 static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
        .md5_lookup     =       tcp_v4_reqsk_md5_lookup,
+       .calc_md5_hash  =       tcp_v4_md5_hash_skb,
 };
 #endif
 
@@ -1373,7 +1374,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                 */
                char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC);
                if (newkey != NULL)
-                       tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr,
+                       tcp_v4_md5_do_add(newsk, newinet->daddr,
                                          newkey, key->keylen);
                newsk->sk_route_caps &= ~NETIF_F_GSO_MASK;
        }
index 43bbba7926ee40be929849921a7c950e27e10e5a..f8d67ccc64f3254c1080008df83b234e3853d976 100644 (file)
@@ -128,7 +128,8 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
                        goto kill_with_rst;
 
                /* Dup ACK? */
-               if (!after(TCP_SKB_CB(skb)->end_seq, tcptw->tw_rcv_nxt) ||
+               if (!th->ack ||
+                   !after(TCP_SKB_CB(skb)->end_seq, tcptw->tw_rcv_nxt) ||
                    TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq) {
                        inet_twsk_put(tw);
                        return TCP_TW_SUCCESS;
index 416fc4c2e7ebdc7367959407ef99c386d6428c20..bd62712848fad8f1a116364002c23cfab903d49e 100644 (file)
@@ -725,7 +725,8 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb)
 static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb,
                                 unsigned int mss_now)
 {
-       if (skb->len <= mss_now || !sk_can_gso(sk)) {
+       if (skb->len <= mss_now || !sk_can_gso(sk) ||
+           skb->ip_summed == CHECKSUM_NONE) {
                /* Avoid the costly divide in the normal
                 * non-TSO case.
                 */
@@ -2260,7 +2261,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 #ifdef CONFIG_TCP_MD5SIG
        /* Okay, we have all we need - do the md5 hash if needed */
        if (md5) {
-               tp->af_specific->calc_md5_hash(md5_hash_location,
+               tcp_rsk(req)->af_specific->calc_md5_hash(md5_hash_location,
                                               md5, NULL, req, skb);
        }
 #endif
index 60d918c96a4fff19c0d4062558ea8c594fa9bef2..0071ee6f441f1236d953f6a2f0f6b3cd8d67e758 100644 (file)
@@ -136,7 +136,8 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
                case IPPROTO_TCP:
                case IPPROTO_SCTP:
                case IPPROTO_DCCP:
-                       if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
+                       if (xprth + 4 < skb->data ||
+                           pskb_may_pull(skb, xprth + 4 - skb->data)) {
                                __be16 *ports = (__be16 *)xprth;
 
                                fl->fl_ip_sport = ports[!!reverse];
index 8c1e86afbbf5208c4eeadee48ce407dbf3b0016f..43b3c9f89c12c5dfac56d70eac73b8718ea73650 100644 (file)
@@ -1916,8 +1916,32 @@ ok:
                                        update_lft = 1;
                                else if (stored_lft <= MIN_VALID_LIFETIME) {
                                        /* valid_lft <= stored_lft is always true */
-                                       /* XXX: IPsec */
-                                       update_lft = 0;
+                                       /*
+                                        * RFC 4862 Section 5.5.3e:
+                                        * "Note that the preferred lifetime of
+                                        *  the corresponding address is always
+                                        *  reset to the Preferred Lifetime in
+                                        *  the received Prefix Information
+                                        *  option, regardless of whether the
+                                        *  valid lifetime is also reset or
+                                        *  ignored."
+                                        *
+                                        *  So if the preferred lifetime in
+                                        *  this advertisement is different
+                                        *  than what we have stored, but the
+                                        *  valid lifetime is invalid, just
+                                        *  reset prefered_lft.
+                                        *
+                                        *  We must set the valid lifetime
+                                        *  to the stored lifetime since we'll
+                                        *  be updating the timestamp below,
+                                        *  else we'll set it back to the
+                                        *  minumum.
+                                        */
+                                       if (prefered_lft != ifp->prefered_lft) {
+                                               valid_lft = stored_lft;
+                                               update_lft = 1;
+                                       }
                                } else {
                                        valid_lft = MIN_VALID_LIFETIME;
                                        if (valid_lft < prefered_lft)
@@ -3085,7 +3109,7 @@ restart:
                                spin_unlock(&ifp->lock);
                                continue;
                        } else if (age >= ifp->prefered_lft) {
-                               /* jiffies - ifp->tsamp > age >= ifp->prefered_lft */
+                               /* jiffies - ifp->tstamp > age >= ifp->prefered_lft */
                                int deprecate = 0;
 
                                if (!(ifp->flags&IFA_F_DEPRECATED)) {
@@ -3362,7 +3386,10 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
                valid = ifa->valid_lft;
                if (preferred != INFINITY_LIFE_TIME) {
                        long tval = (jiffies - ifa->tstamp)/HZ;
-                       preferred -= tval;
+                       if (preferred > tval)
+                               preferred -= tval;
+                       else
+                               preferred = 0;
                        if (valid != INFINITY_LIFE_TIME)
                                valid -= tval;
                }
index 85b3d0036afdeff08efc32d1179dbabf7a58f9b3..45f9a2a42d564391134797ac5df3e72c59a60621 100644 (file)
@@ -306,8 +306,10 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                    v4addr != htonl(INADDR_ANY) &&
                    chk_addr_ret != RTN_LOCAL &&
                    chk_addr_ret != RTN_MULTICAST &&
-                   chk_addr_ret != RTN_BROADCAST)
+                   chk_addr_ret != RTN_BROADCAST) {
+                       err = -EADDRNOTAVAIL;
                        goto out;
+               }
        } else {
                if (addr_type != IPV6_ADDR_ANY) {
                        struct net_device *dev = NULL;
@@ -1284,6 +1286,8 @@ static void __exit inet6_exit(void)
        proto_unregister(&udplitev6_prot);
        proto_unregister(&udpv6_prot);
        proto_unregister(&tcpv6_prot);
+
+       rcu_barrier(); /* Wait for completion of call_rcu()'s */
 }
 module_exit(inet6_exit);
 
index c3a07d75b5f50bafb987a7359c168f504ac81828..6d6a4277c67728f0e25a27f854904686f2eb1156 100644 (file)
@@ -139,6 +139,9 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
 
        rcu_read_unlock();
 
+       /* Must drop socket now because of tproxy. */
+       skb_orphan(skb);
+
        return NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, dev, NULL,
                       ip6_rcv_finish);
 err:
index 7c76e3d1821551c42acc16d3e2210404a553b4d0..87f8419a68fdf888b37a2643345d89b85005671d 100644 (file)
@@ -1484,7 +1484,6 @@ int ip6_push_pending_frames(struct sock *sk)
                skb->len += tmp_skb->len;
                skb->data_len += tmp_skb->len;
                skb->truesize += tmp_skb->truesize;
-               __sock_put(tmp_skb->sk);
                tmp_skb->destructor = NULL;
                tmp_skb->sk = NULL;
        }
index 68e52308e5520f7180e22c0230aea51133fad265..98b7327d0949aa993751411f6512ebdf304f326f 100644 (file)
@@ -1018,6 +1018,7 @@ static void ipip6_tunnel_setup(struct net_device *dev)
        dev->hard_header_len    = LL_MAX_HEADER + sizeof(struct iphdr);
        dev->mtu                = ETH_DATA_LEN - sizeof(struct iphdr);
        dev->flags              = IFF_NOARP;
+       dev->priv_flags        &= ~IFF_XMIT_DST_RELEASE;
        dev->iflink             = 0;
        dev->addr_len           = 4;
        dev->features           |= NETIF_F_NETNS_LOCAL;
index 58810c65b6359524b171fa9ca0678b9a6a21241c..d849dd53b78810623e62555a85eff50af60d84d1 100644 (file)
@@ -896,6 +896,7 @@ struct request_sock_ops tcp6_request_sock_ops __read_mostly = {
 #ifdef CONFIG_TCP_MD5SIG
 static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
        .md5_lookup     =       tcp_v6_reqsk_md5_lookup,
+       .calc_md5_hash  =       tcp_v6_md5_hash_skb,
 };
 #endif
 
@@ -1441,7 +1442,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                 */
                char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC);
                if (newkey != NULL)
-                       tcp_v6_md5_do_add(newsk, &inet6_sk(sk)->daddr,
+                       tcp_v6_md5_do_add(newsk, &newnp->daddr,
                                          newkey, key->keylen);
        }
 #endif
index b4b16a43f2771bd62558a2cd8ca3af60b0d99808..3a3c677bc0f2571b9679e5b9015ec15c6951e3b2 100644 (file)
@@ -157,7 +157,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
        ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr);
        ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr);
 
-       while (pskb_may_pull(skb, nh + offset + 1 - skb->data)) {
+       while (nh + offset + 1 < skb->data ||
+              pskb_may_pull(skb, nh + offset + 1 - skb->data)) {
                nh = skb_network_header(skb);
                exthdr = (struct ipv6_opt_hdr *)(nh + offset);
 
@@ -177,7 +178,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
                case IPPROTO_TCP:
                case IPPROTO_SCTP:
                case IPPROTO_DCCP:
-                       if (!onlyproto && pskb_may_pull(skb, nh + offset + 4 - skb->data)) {
+                       if (!onlyproto && (nh + offset + 4 < skb->data ||
+                            pskb_may_pull(skb, nh + offset + 4 - skb->data))) {
                                __be16 *ports = (__be16 *)exthdr;
 
                                fl->fl_ip_sport = ports[!!reverse];
index 417b0e30949551de04cc6e1f8087ca9a7809da08..f1118d92a191dc07acd9bfda34ce81c7df8613f0 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/netdevice.h>
 #include <linux/uio.h>
 #include <linux/skbuff.h>
+#include <linux/smp_lock.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
 #include <linux/string.h>
index cb762c8723ea7a90f98b9e34074d98bc3b716742..50b43c57d5d8e01c94796b988fa6e98a7f4aee2b 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/smp_lock.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
 #include <linux/init.h>
@@ -714,6 +715,7 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
        struct sock *sk = sock->sk;
        struct irda_sock *self = irda_sk(sk);
 
+       memset(&saddr, 0, sizeof(saddr));
        if (peer) {
                if (sk->sk_state != TCP_ESTABLISHED)
                        return -ENOTCONN;
index bccf4d0059f0a6a629bbd5913015b0453caaa5e9..b001c361ad30976ff3a1de5bfe80fe2f0142b6f9 100644 (file)
 #include <linux/module.h>
 
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
 #include <linux/skbuff.h>
 #include <linux/tty.h>
 #include <linux/proc_fs.h>
index 6d8ae03c14f5b8e3dc12af9906a14e1b0ae3b666..68cbcb19cbd8a084dc0121997c2701f970c99aa1 100644 (file)
@@ -13,6 +13,7 @@
  *     2) as a control channel (write commands, read events)
  */
 
+#include <linux/smp_lock.h>
 #include "irnet_ppp.h"         /* Private header */
 /* Please put other headers in irnet.h - Thanks */
 
index ecf4eb2717cb0c4d75b77aa006c8d15235c7d867..9cb79f95bf63953c9bcdf2b379b4ccbb37089ff5 100644 (file)
@@ -1453,6 +1453,7 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
        }
        /* Dup */
        memcpy(new, orig, sizeof(struct tsap_cb));
+       spin_lock_init(&new->lock);
 
        /* We don't need the old instance any more */
        spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
index 6be5f92d10943d383ce252242233e61770b2e528..49c15b48408e5617a5405ba396f1f9b9e427dd5d 100644 (file)
@@ -306,7 +306,7 @@ static inline int iucv_below_msglim(struct sock *sk)
 static void iucv_sock_wake_msglim(struct sock *sk)
 {
        read_lock(&sk->sk_callback_lock);
-       if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+       if (sk_has_sleeper(sk))
                wake_up_interruptible_all(sk->sk_sleep);
        sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
        read_unlock(&sk->sk_callback_lock);
@@ -1256,7 +1256,7 @@ unsigned int iucv_sock_poll(struct file *file, struct socket *sock,
        struct sock *sk = sock->sk;
        unsigned int mask = 0;
 
-       poll_wait(file, sk->sk_sleep, wait);
+       sock_poll_wait(file, sk->sk_sleep, wait);
 
        if (sk->sk_state == IUCV_LISTEN)
                return iucv_accept_poll(sk);
index 9208cf5f2bd554fb4d66fba51c327bcc3d7a5aae..c45eee1c0e8d46719df66883caa4d874f806ec5f 100644 (file)
@@ -914,6 +914,7 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr,
        struct llc_sock *llc = llc_sk(sk);
        int rc = 0;
 
+       memset(&sllc, 0, sizeof(sllc));
        lock_sock(sk);
        if (sock_flag(sk, SOCK_ZAPPED))
                goto out;
index ba2643a43c73c662236ad8f79144dba39d5dcfad..7836ee92898369a7aa6e2c7f67539c48bf93ec11 100644 (file)
@@ -83,6 +83,7 @@ endmenu
 config MAC80211_MESH
        bool "Enable mac80211 mesh networking (pre-802.11s) support"
        depends on MAC80211 && EXPERIMENTAL
+       depends on BROKEN
        ---help---
         This options enables support of Draft 802.11s mesh networking.
         The implementation is based on Draft 1.08 of the Mesh Networking
index 9e5762ad307d9faa55d4bd11400c5d76e7852dcc..a24e59816b9370018d9a01be95f065f9eb2a5745 100644 (file)
@@ -381,6 +381,14 @@ static void ieee80211_agg_splice_packets(struct ieee80211_local *local,
                &local->hw, queue,
                IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
 
+       if (!(sta->ampdu_mlme.tid_state_tx[tid] & HT_ADDBA_REQUESTED_MSK))
+               return;
+
+       if (WARN(!sta->ampdu_mlme.tid_tx[tid],
+                "TID %d gone but expected when splicing aggregates from"
+                "the pending queue\n", tid))
+               return;
+
        if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) {
                spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
                /* mark queue as pending, it is stopped already */
index ce267565e18076ec4a852e52aa54bcdc418c0bbf..659a42d529e3cbcd20100452e018b5584fa970a9 100644 (file)
@@ -67,6 +67,8 @@ static DECLARE_WORK(todo_work, key_todo);
  *
  * @key: key to add to do item for
  * @flag: todo flag(s)
+ *
+ * Must be called with IRQs or softirqs disabled.
  */
 static void add_todo(struct ieee80211_key *key, u32 flag)
 {
@@ -140,9 +142,9 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
        ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf);
 
        if (!ret) {
-               spin_lock(&todo_lock);
+               spin_lock_bh(&todo_lock);
                key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
-               spin_unlock(&todo_lock);
+               spin_unlock_bh(&todo_lock);
        }
 
        if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
@@ -164,12 +166,12 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
        if (!key || !key->local->ops->set_key)
                return;
 
-       spin_lock(&todo_lock);
+       spin_lock_bh(&todo_lock);
        if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
-               spin_unlock(&todo_lock);
+               spin_unlock_bh(&todo_lock);
                return;
        }
-       spin_unlock(&todo_lock);
+       spin_unlock_bh(&todo_lock);
 
        sta = get_sta_for_key(key);
        sdata = key->sdata;
@@ -188,9 +190,9 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
                       wiphy_name(key->local->hw.wiphy),
                       key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
 
-       spin_lock(&todo_lock);
+       spin_lock_bh(&todo_lock);
        key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
-       spin_unlock(&todo_lock);
+       spin_unlock_bh(&todo_lock);
 }
 
 static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
@@ -437,14 +439,14 @@ void ieee80211_key_link(struct ieee80211_key *key,
 
        __ieee80211_key_replace(sdata, sta, old_key, key);
 
-       spin_unlock_irqrestore(&sdata->local->key_lock, flags);
-
        /* free old key later */
        add_todo(old_key, KEY_FLAG_TODO_DELETE);
 
        add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
        if (netif_running(sdata->dev))
                add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
+
+       spin_unlock_irqrestore(&sdata->local->key_lock, flags);
 }
 
 static void __ieee80211_key_free(struct ieee80211_key *key)
@@ -547,7 +549,7 @@ static void __ieee80211_key_todo(void)
         */
        synchronize_rcu();
 
-       spin_lock(&todo_lock);
+       spin_lock_bh(&todo_lock);
        while (!list_empty(&todo_list)) {
                key = list_first_entry(&todo_list, struct ieee80211_key, todo);
                list_del_init(&key->todo);
@@ -558,7 +560,7 @@ static void __ieee80211_key_todo(void)
                                          KEY_FLAG_TODO_HWACCEL_REMOVE |
                                          KEY_FLAG_TODO_DELETE);
                key->flags &= ~todoflags;
-               spin_unlock(&todo_lock);
+               spin_unlock_bh(&todo_lock);
 
                work_done = false;
 
@@ -591,9 +593,9 @@ static void __ieee80211_key_todo(void)
 
                WARN_ON(!work_done);
 
-               spin_lock(&todo_lock);
+               spin_lock_bh(&todo_lock);
        }
-       spin_unlock(&todo_lock);
+       spin_unlock_bh(&todo_lock);
 }
 
 void ieee80211_key_todo(void)
index fc712e60705da4b8a8785b305cec79300be955c7..11cf45bce38a36cf17c4592b5b0991a489a28c5e 100644 (file)
@@ -494,7 +494,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
         * should it be using the interface and enqueuing
         * frames at this very time on another CPU.
         */
-       synchronize_rcu();
+       rcu_barrier(); /* Wait for RX path and call_rcu()'s */
        skb_queue_purge(&sdata->u.mesh.skb_queue);
 }
 
index 003cb470ac8478c84329bf29a0687484a2e6acb1..f49ef288e2e28841a2e6308c2ab94e83cf2d1717 100644 (file)
@@ -637,7 +637,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
        struct mesh_preq_queue *preq_node;
 
-       preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL);
+       preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC);
        if (!preq_node) {
                printk(KERN_DEBUG "Mesh HWMP: could not allocate PREQ node\n");
                return;
index 3c72557df45adee87cba306b2d560089e71cdb49..479597e885832d539f4774e157e48deff8d22da2 100644 (file)
@@ -175,6 +175,8 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
        int err = 0;
        u32 hash_idx;
 
+       might_sleep();
+
        if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
                /* never add ourselves as neighbours */
                return -ENOTSUPP;
@@ -265,6 +267,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
        int err = 0;
        u32 hash_idx;
 
+       might_sleep();
 
        if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
                /* never add ourselves as neighbours */
@@ -491,8 +494,10 @@ void mesh_path_tx_pending(struct mesh_path *mpath)
  * @skb: frame to discard
  * @sdata: network subif the frame was to be sent through
  *
- * If the frame was beign forwarded from another MP, a PERR frame will be sent
- * to the precursor.
+ * If the frame was being forwarded from another MP, a PERR frame will be sent
+ * to the precursor.  The precursor's address (i.e. the previous hop) was saved
+ * in addr1 of the frame-to-be-forwarded, and would only be overwritten once
+ * the destination is successfully resolved.
  *
  * Locking: the function must me called within a rcu_read_lock region
  */
@@ -507,7 +512,7 @@ void mesh_path_discard_frame(struct sk_buff *skb,
                u8 *ra, *da;
 
                da = hdr->addr3;
-               ra = hdr->addr2;
+               ra = hdr->addr1;
                mpath = mesh_path_lookup(da, sdata);
                if (mpath)
                        dsn = ++mpath->dsn;
index aca22b00b6a327873ee5ffc5a443ae541fdab5ed..07e7e41816be31cdd210f0dca41219525624c22b 100644 (file)
@@ -721,7 +721,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
 {
        struct ieee80211_local *local = (void *) data;
 
-       if (local->quiescing)
+       if (local->quiescing || local->suspended)
                return;
 
        queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work);
index 7a549f9deb967c1acbcf4ce1dbc41d28bcbefb4d..5e3d476972f916f741ea44d5c1d62fb60acf83dc 100644 (file)
@@ -55,15 +55,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
 
        rcu_read_unlock();
 
-       /* flush again, in case driver queued work */
-       flush_workqueue(local->hw.workqueue);
-
-       /* stop hardware - this must stop RX */
-       if (local->open_count) {
-               ieee80211_led_radio(local, false);
-               drv_stop(local);
-       }
-
        /* remove STAs */
        spin_lock_irqsave(&local->sta_lock, flags);
        list_for_each_entry(sta, &local->sta_list, list) {
@@ -111,7 +102,22 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
                drv_remove_interface(local, &conf);
        }
 
+       /* stop hardware - this must stop RX */
+       if (local->open_count) {
+               ieee80211_led_radio(local, false);
+               drv_stop(local);
+       }
+
+       /*
+        * flush again, in case driver queued work -- it
+        * shouldn't be doing (or cancel everything in the
+        * stop callback) that but better safe than sorry.
+        */
+       flush_workqueue(local->hw.workqueue);
+
        local->suspended = true;
+       /* need suspended to be visible before quiescing is false */
+       barrier();
        local->quiescing = false;
 
        return 0;
index b218b98fba7fbeb573d420ca0829af99f47584c5..37771abd8f5a5bcd85d9d94fa558f0e69649defb 100644 (file)
@@ -66,7 +66,7 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix)
        for (i = rix; i >= 0; i--)
                if (mi->r[i].rix == rix)
                        break;
-       WARN_ON(mi->r[i].rix != rix);
+       WARN_ON(i < 0);
        return i;
 }
 
@@ -181,6 +181,9 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
                        break;
 
                ndx = rix_to_ndx(mi, ar[i].idx);
+               if (ndx < 0)
+                       continue;
+
                mi->r[ndx].attempts += ar[i].count;
 
                if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0))
index de5bba7f910ae876637c3002544a6963eebccdfd..0936fc24942deddd8ea69f66f29c1b8c35d1e468 100644 (file)
@@ -2453,6 +2453,18 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
                return;
        }
 
+       /*
+        * If we're suspending, it is possible although not too likely
+        * that we'd be receiving frames after having already partially
+        * quiesced the stack. We can't process such frames then since
+        * that might, for example, cause stations to be added or other
+        * driver callbacks be invoked.
+        */
+       if (unlikely(local->quiescing || local->suspended)) {
+               kfree_skb(skb);
+               return;
+       }
+
        if (status->flag & RX_FLAG_HT) {
                /* rate_idx is MCS index */
                if (WARN_ON(status->rate_idx < 0 ||
index d238a8939a094de63e1f9782a68b908a4340b998..3a8922cd1038ceaef3c4e4ddb433ac3e5c672e66 100644 (file)
@@ -1455,7 +1455,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
                monitor_iface = UNKNOWN_ADDRESS;
 
                len_rthdr = ieee80211_get_radiotap_len(skb->data);
-               hdr = (struct ieee80211_hdr *)skb->data + len_rthdr;
+               hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
                hdrlen = ieee80211_hdrlen(hdr->frame_control);
 
                /* check the header is complete in the frame */
index 7508f11c5b3952a05ed9b41682f50d7827b3c4e6..b5869b9574b08a52c4c16f04cdb3f17336f9d762 100644 (file)
@@ -561,23 +561,38 @@ struct nf_conn *nf_conntrack_alloc(struct net *net,
                }
        }
 
-       ct = kmem_cache_zalloc(nf_conntrack_cachep, gfp);
+       /*
+        * Do not use kmem_cache_zalloc(), as this cache uses
+        * SLAB_DESTROY_BY_RCU.
+        */
+       ct = kmem_cache_alloc(nf_conntrack_cachep, gfp);
        if (ct == NULL) {
                pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n");
                atomic_dec(&net->ct.count);
                return ERR_PTR(-ENOMEM);
        }
-
+       /*
+        * Let ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.next
+        * and ct->tuplehash[IP_CT_DIR_REPLY].hnnode.next unchanged.
+        */
+       memset(&ct->tuplehash[IP_CT_DIR_MAX], 0,
+              sizeof(*ct) - offsetof(struct nf_conn, tuplehash[IP_CT_DIR_MAX]));
        spin_lock_init(&ct->lock);
-       atomic_set(&ct->ct_general.use, 1);
        ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig;
+       ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.pprev = NULL;
        ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl;
+       ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev = NULL;
        /* Don't set timer yet: wait for confirmation */
        setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct);
 #ifdef CONFIG_NET_NS
        ct->ct_net = net;
 #endif
 
+       /*
+        * changes to lookup keys must be done before setting refcnt to 1
+        */
+       smp_wmb();
+       atomic_set(&ct->ct_general.use, 1);
        return ct;
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_alloc);
index afde8f991646eadfa6afc72d6390fb27b5ecaf61..2032dfe25ca85a64daab1760fb1ce6b01fc96c7e 100644 (file)
@@ -617,8 +617,10 @@ err1:
 void nf_conntrack_expect_fini(struct net *net)
 {
        exp_proc_remove(net);
-       if (net_eq(net, &init_net))
+       if (net_eq(net, &init_net)) {
+               rcu_barrier(); /* Wait for call_rcu() before destroy */
                kmem_cache_destroy(nf_ct_expect_cachep);
+       }
        nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc,
                             nf_ct_expect_hsize);
 }
index 4b2c769d555fce4d6131b08f5aac6d53b3a48be6..fef95be334bd8b834335afe8bbef0cdb9f62dc37 100644 (file)
@@ -186,6 +186,6 @@ void nf_ct_extend_unregister(struct nf_ct_ext_type *type)
        rcu_assign_pointer(nf_ct_ext_types[type->id], NULL);
        update_alloc_size(type);
        mutex_unlock(&nf_ct_ext_type_mutex);
-       synchronize_rcu();
+       rcu_barrier(); /* Wait for completion of call_rcu()'s */
 }
 EXPORT_SYMBOL_GPL(nf_ct_extend_unregister);
index 33fc0a443f3de755772f5be4f686c1f44adf9cb1..97a82ba75376aff182fecb1ac37b97e6ca1bf021 100644 (file)
@@ -720,8 +720,8 @@ static bool tcp_in_window(const struct nf_conn *ct,
 /* Caller must linearize skb at tcp header. */
 void nf_conntrack_tcp_update(const struct sk_buff *skb,
                             unsigned int dataoff,
-                            struct nf_conn *ct,
-                            int dir)
+                            struct nf_conn *ct, int dir,
+                            s16 offset)
 {
        const struct tcphdr *tcph = (const void *)skb->data + dataoff;
        const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[dir];
@@ -734,7 +734,7 @@ void nf_conntrack_tcp_update(const struct sk_buff *skb,
        /*
         * We have to worry for the ack in the reply packet only...
         */
-       if (after(end, ct->proto.tcp.seen[dir].td_end))
+       if (ct->proto.tcp.seen[dir].td_end + offset == end)
                ct->proto.tcp.seen[dir].td_end = end;
        ct->proto.tcp.last_end = end;
        spin_unlock_bh(&ct->lock);
index 43f5676b1af405d1a0c12a374710ae543d06346a..d80b8192e0d423a2f66ec27ea06efbcaf174d681 100644 (file)
@@ -74,7 +74,7 @@ static unsigned int
 xt_rateest_tg(struct sk_buff *skb, const struct xt_target_param *par)
 {
        const struct xt_rateest_target_info *info = par->targinfo;
-       struct gnet_stats_basic *stats = &info->est->bstats;
+       struct gnet_stats_basic_packed *stats = &info->est->bstats;
 
        spin_lock_bh(&info->est->lock);
        stats->bytes += skb->len;
index 0b7139f3dd786b3b4fa9ac416ca20fb9fbfe47c4..fc581800698e6885ee9c6ccb71ccc4be6eb9f594 100644 (file)
@@ -129,7 +129,7 @@ conntrack_addrcmp(const union nf_inet_addr *kaddr,
 
 static inline bool
 conntrack_mt_origsrc(const struct nf_conn *ct,
-                     const struct xt_conntrack_mtinfo1 *info,
+                     const struct xt_conntrack_mtinfo2 *info,
                     u_int8_t family)
 {
        return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3,
@@ -138,7 +138,7 @@ conntrack_mt_origsrc(const struct nf_conn *ct,
 
 static inline bool
 conntrack_mt_origdst(const struct nf_conn *ct,
-                     const struct xt_conntrack_mtinfo1 *info,
+                     const struct xt_conntrack_mtinfo2 *info,
                     u_int8_t family)
 {
        return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3,
@@ -147,7 +147,7 @@ conntrack_mt_origdst(const struct nf_conn *ct,
 
 static inline bool
 conntrack_mt_replsrc(const struct nf_conn *ct,
-                     const struct xt_conntrack_mtinfo1 *info,
+                     const struct xt_conntrack_mtinfo2 *info,
                     u_int8_t family)
 {
        return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3,
@@ -156,7 +156,7 @@ conntrack_mt_replsrc(const struct nf_conn *ct,
 
 static inline bool
 conntrack_mt_repldst(const struct nf_conn *ct,
-                     const struct xt_conntrack_mtinfo1 *info,
+                     const struct xt_conntrack_mtinfo2 *info,
                     u_int8_t family)
 {
        return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3,
@@ -164,7 +164,7 @@ conntrack_mt_repldst(const struct nf_conn *ct,
 }
 
 static inline bool
-ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info,
+ct_proto_port_check(const struct xt_conntrack_mtinfo2 *info,
                     const struct nf_conn *ct)
 {
        const struct nf_conntrack_tuple *tuple;
@@ -204,7 +204,7 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info,
 static bool
 conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par)
 {
-       const struct xt_conntrack_mtinfo1 *info = par->matchinfo;
+       const struct xt_conntrack_mtinfo2 *info = par->matchinfo;
        enum ip_conntrack_info ctinfo;
        const struct nf_conn *ct;
        unsigned int statebit;
@@ -278,6 +278,16 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par)
        return true;
 }
 
+static bool
+conntrack_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par)
+{
+       const struct xt_conntrack_mtinfo2 *const *info = par->matchinfo;
+       struct xt_match_param newpar = *par;
+
+       newpar.matchinfo = *info;
+       return conntrack_mt(skb, &newpar);
+}
+
 static bool conntrack_mt_check(const struct xt_mtchk_param *par)
 {
        if (nf_ct_l3proto_try_module_get(par->family) < 0) {
@@ -288,11 +298,45 @@ static bool conntrack_mt_check(const struct xt_mtchk_param *par)
        return true;
 }
 
+static bool conntrack_mt_check_v1(const struct xt_mtchk_param *par)
+{
+       struct xt_conntrack_mtinfo1 *info = par->matchinfo;
+       struct xt_conntrack_mtinfo2 *up;
+       int ret = conntrack_mt_check(par);
+
+       if (ret < 0)
+               return ret;
+
+       up = kmalloc(sizeof(*up), GFP_KERNEL);
+       if (up == NULL) {
+               nf_ct_l3proto_module_put(par->family);
+               return -ENOMEM;
+       }
+
+       /*
+        * The strategy here is to minimize the overhead of v1 matching,
+        * by prebuilding a v2 struct and putting the pointer into the
+        * v1 dataspace.
+        */
+       memcpy(up, info, offsetof(typeof(*info), state_mask));
+       up->state_mask  = info->state_mask;
+       up->status_mask = info->status_mask;
+       *(void **)info  = up;
+       return true;
+}
+
 static void conntrack_mt_destroy(const struct xt_mtdtor_param *par)
 {
        nf_ct_l3proto_module_put(par->family);
 }
 
+static void conntrack_mt_destroy_v1(const struct xt_mtdtor_param *par)
+{
+       struct xt_conntrack_mtinfo2 **info = par->matchinfo;
+       kfree(*info);
+       conntrack_mt_destroy(par);
+}
+
 #ifdef CONFIG_COMPAT
 struct compat_xt_conntrack_info
 {
@@ -363,6 +407,16 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = {
                .revision   = 1,
                .family     = NFPROTO_UNSPEC,
                .matchsize  = sizeof(struct xt_conntrack_mtinfo1),
+               .match      = conntrack_mt_v1,
+               .checkentry = conntrack_mt_check_v1,
+               .destroy    = conntrack_mt_destroy_v1,
+               .me         = THIS_MODULE,
+       },
+       {
+               .name       = "conntrack",
+               .revision   = 2,
+               .family     = NFPROTO_UNSPEC,
+               .matchsize  = sizeof(struct xt_conntrack_mtinfo2),
                .match      = conntrack_mt,
                .checkentry = conntrack_mt_check,
                .destroy    = conntrack_mt_destroy,
index 863e40977a4db6d0b37fcc670137032afec85839..0f482e2440b432434ac96bbf38a942340ef56350 100644 (file)
@@ -330,7 +330,8 @@ static bool xt_osf_match_packet(const struct sk_buff *skb,
                        fcount++;
 
                        if (info->flags & XT_OSF_LOG)
-                               nf_log_packet(p->hooknum, 0, skb, p->in, p->out, NULL,
+                               nf_log_packet(p->family, p->hooknum, skb,
+                                       p->in, p->out, NULL,
                                        "%s [%s:%s] : %pi4:%d -> %pi4:%d hops=%d\n",
                                        f->genre, f->version, f->subtype,
                                        &ip->saddr, ntohs(tcp->source),
@@ -345,7 +346,7 @@ static bool xt_osf_match_packet(const struct sk_buff *skb,
        rcu_read_unlock();
 
        if (!fcount && (info->flags & XT_OSF_LOG))
-               nf_log_packet(p->hooknum, 0, skb, p->in, p->out, NULL,
+               nf_log_packet(p->family, p->hooknum, skb, p->in, p->out, NULL,
                        "Remote OS is not known: %pi4:%u -> %pi4:%u\n",
                                &ip->saddr, ntohs(tcp->source),
                                &ip->daddr, ntohs(tcp->dest));
index 98fc190e8f0eed8683e9836b6be1567ecea74382..390b7d09fe512f2957769ace3b8a579b64f64086 100644 (file)
@@ -52,7 +52,7 @@ static bool quota_mt_check(const struct xt_mtchk_param *par)
 
        q->master = kmalloc(sizeof(*q->master), GFP_KERNEL);
        if (q->master == NULL)
-               return -ENOMEM;
+               return false;
 
        q->master->quota = q->quota;
        return true;
index b0e582f2d37aa5a9bf52c8efc86384fe0439472b..16e6c4378ff18907e486d5625f09af57b27e153e 100644 (file)
@@ -151,7 +151,7 @@ int netlbl_cfg_unlbl_map_add(const char *domain,
                        addr6 = addr;
                        mask6 = mask;
                        map6 = kzalloc(sizeof(*map6), GFP_ATOMIC);
-                       if (map4 == NULL)
+                       if (map6 == NULL)
                                goto cfg_unlbl_map_add_failure;
                        map6->type = NETLBL_NLTYPE_UNLABELED;
                        ipv6_addr_copy(&map6->list.addr, addr6);
index ce51ce012cdab48e4c0bbfd99c3053a0bfcaa636..ce1a34b99c2328f16648d5cf96cb8ff5edc25ed6 100644 (file)
@@ -847,6 +847,7 @@ static int nr_getname(struct socket *sock, struct sockaddr *uaddr,
                sax->fsa_ax25.sax25_family = AF_NETROM;
                sax->fsa_ax25.sax25_ndigis = 1;
                sax->fsa_ax25.sax25_call   = nr->user_addr;
+               memset(sax->fsa_digipeater, 0, sizeof(sax->fsa_digipeater));
                sax->fsa_digipeater[0]     = nr->dest_addr;
                *uaddr_len = sizeof(struct full_sockaddr_ax25);
        } else {
index e943c16552a204badf0737b3550d11f6d85df663..4eb1ac9a7679ca3c14c0d9c651fbbf1d4fe76694 100644 (file)
@@ -630,23 +630,23 @@ out:
        return dev;
 }
 
-static ax25_digi *nr_call_to_digi(int ndigis, ax25_address *digipeaters)
+static ax25_digi *nr_call_to_digi(ax25_digi *digi, int ndigis,
+       ax25_address *digipeaters)
 {
-       static ax25_digi ax25_digi;
        int i;
 
        if (ndigis == 0)
                return NULL;
 
        for (i = 0; i < ndigis; i++) {
-               ax25_digi.calls[i]    = digipeaters[i];
-               ax25_digi.repeated[i] = 0;
+               digi->calls[i]    = digipeaters[i];
+               digi->repeated[i] = 0;
        }
 
-       ax25_digi.ndigi      = ndigis;
-       ax25_digi.lastrepeat = -1;
+       digi->ndigi      = ndigis;
+       digi->lastrepeat = -1;
 
-       return &ax25_digi;
+       return digi;
 }
 
 /*
@@ -656,6 +656,7 @@ int nr_rt_ioctl(unsigned int cmd, void __user *arg)
 {
        struct nr_route_struct nr_route;
        struct net_device *dev;
+       ax25_digi digi;
        int ret;
 
        switch (cmd) {
@@ -673,13 +674,15 @@ int nr_rt_ioctl(unsigned int cmd, void __user *arg)
                        ret = nr_add_node(&nr_route.callsign,
                                nr_route.mnemonic,
                                &nr_route.neighbour,
-                               nr_call_to_digi(nr_route.ndigis, nr_route.digipeaters),
+                               nr_call_to_digi(&digi, nr_route.ndigis,
+                                               nr_route.digipeaters),
                                dev, nr_route.quality,
                                nr_route.obs_count);
                        break;
                case NETROM_NEIGH:
                        ret = nr_add_neigh(&nr_route.callsign,
-                               nr_call_to_digi(nr_route.ndigis, nr_route.digipeaters),
+                               nr_call_to_digi(&digi, nr_route.ndigis,
+                                               nr_route.digipeaters),
                                dev, nr_route.quality);
                        break;
                default:
index 80a322d77909ac0d96000486580f20d2946fcbd3..c2b77a698695371a5b08d2da94876ff2a71f50c7 100644 (file)
@@ -69,17 +69,34 @@ static struct phonet_device *__phonet_get(struct net_device *dev)
        return NULL;
 }
 
-static void __phonet_device_free(struct phonet_device *pnd)
+static void phonet_device_destroy(struct net_device *dev)
 {
-       list_del(&pnd->list);
-       kfree(pnd);
+       struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev));
+       struct phonet_device *pnd;
+
+       ASSERT_RTNL();
+
+       spin_lock_bh(&pndevs->lock);
+       pnd = __phonet_get(dev);
+       if (pnd)
+               list_del(&pnd->list);
+       spin_unlock_bh(&pndevs->lock);
+
+       if (pnd) {
+               u8 addr;
+
+               for (addr = find_first_bit(pnd->addrs, 64); addr < 64;
+                       addr = find_next_bit(pnd->addrs, 64, 1+addr))
+                       phonet_address_notify(RTM_DELADDR, dev, addr);
+               kfree(pnd);
+       }
 }
 
 struct net_device *phonet_device_get(struct net *net)
 {
        struct phonet_device_list *pndevs = phonet_device_list(net);
        struct phonet_device *pnd;
-       struct net_device *dev;
+       struct net_device *dev = NULL;
 
        spin_lock_bh(&pndevs->lock);
        list_for_each_entry(pnd, &pndevs->list, list) {
@@ -126,8 +143,10 @@ int phonet_address_del(struct net_device *dev, u8 addr)
        pnd = __phonet_get(dev);
        if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs))
                err = -EADDRNOTAVAIL;
-       else if (bitmap_empty(pnd->addrs, 64))
-               __phonet_device_free(pnd);
+       else if (bitmap_empty(pnd->addrs, 64)) {
+               list_del(&pnd->list);
+               kfree(pnd);
+       }
        spin_unlock_bh(&pndevs->lock);
        return err;
 }
@@ -181,18 +200,8 @@ static int phonet_device_notify(struct notifier_block *me, unsigned long what,
 {
        struct net_device *dev = arg;
 
-       if (what == NETDEV_UNREGISTER) {
-               struct phonet_device_list *pndevs;
-               struct phonet_device *pnd;
-
-               /* Destroy phonet-specific device data */
-               pndevs = phonet_device_list(dev_net(dev));
-               spin_lock_bh(&pndevs->lock);
-               pnd = __phonet_get(dev);
-               if (pnd)
-                       __phonet_device_free(pnd);
-               spin_unlock_bh(&pndevs->lock);
-       }
+       if (what == NETDEV_UNREGISTER)
+               phonet_device_destroy(dev);
        return 0;
 
 }
@@ -218,11 +227,12 @@ static int phonet_init_net(struct net *net)
 static void phonet_exit_net(struct net *net)
 {
        struct phonet_net *pnn = net_generic(net, phonet_net_id);
-       struct phonet_device *pnd, *n;
-
-       list_for_each_entry_safe(pnd, n, &pnn->pndevs.list, list)
-               __phonet_device_free(pnd);
+       struct net_device *dev;
 
+       rtnl_lock();
+       for_each_netdev(net, dev)
+               phonet_device_destroy(dev);
+       rtnl_unlock();
        kfree(pnn);
 }
 
index cec4e59516817ecc0b64a8fdaa04c11de52aa0b2..f8b4cee434c232614665523ac4608cbed543f86b 100644 (file)
@@ -32,7 +32,7 @@
 static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr,
                     u32 pid, u32 seq, int event);
 
-static void rtmsg_notify(int event, struct net_device *dev, u8 addr)
+void phonet_address_notify(int event, struct net_device *dev, u8 addr)
 {
        struct sk_buff *skb;
        int err = -ENOBUFS;
@@ -94,7 +94,7 @@ static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)
        else
                err = phonet_address_del(dev, pnaddr);
        if (!err)
-               rtmsg_notify(nlh->nlmsg_type, dev, pnaddr);
+               phonet_address_notify(nlh->nlmsg_type, dev, pnaddr);
        return err;
 }
 
index 79693fe2001e50df79d259a41dec1f6aa28b9370..2fc4a1724eb8e2e1fcacd6f0f55ea16c4afbd674 100644 (file)
@@ -549,6 +549,10 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw)
        swprev = !!(rfkill->state & RFKILL_BLOCK_SW);
        hwprev = !!(rfkill->state & RFKILL_BLOCK_HW);
        __rfkill_set_sw_state(rfkill, sw);
+       if (hw)
+               rfkill->state |= RFKILL_BLOCK_HW;
+       else
+               rfkill->state &= ~RFKILL_BLOCK_HW;
 
        spin_unlock_irqrestore(&rfkill->lock, flags);
 
@@ -648,15 +652,26 @@ static ssize_t rfkill_state_store(struct device *dev,
                                  struct device_attribute *attr,
                                  const char *buf, size_t count)
 {
-       /*
-        * The intention was that userspace can only take control over
-        * a given device when/if rfkill-input doesn't control it due
-        * to user_claim. Since user_claim is currently unsupported,
-        * we never support changing the state from userspace -- this
-        * can be implemented again later.
-        */
+       struct rfkill *rfkill = to_rfkill(dev);
+       unsigned long state;
+       int err;
+
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
+       err = strict_strtoul(buf, 0, &state);
+       if (err)
+               return err;
+
+       if (state != RFKILL_USER_STATE_SOFT_BLOCKED &&
+           state != RFKILL_USER_STATE_UNBLOCKED)
+               return -EINVAL;
+
+       mutex_lock(&rfkill_global_mutex);
+       rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED);
+       mutex_unlock(&rfkill_global_mutex);
 
-       return -EPERM;
+       return err ?: count;
 }
 
 static ssize_t rfkill_claim_show(struct device *dev,
index 6bd8e93869eda9d6d5732bcf502ba32d7ca041db..e5f478ca3d61574e01bc74bad58cfdc910a33b4a 100644 (file)
@@ -92,23 +92,21 @@ static void rose_set_lockdep_key(struct net_device *dev)
 /*
  *     Convert a ROSE address into text.
  */
-const char *rose2asc(const rose_address *addr)
+char *rose2asc(char *buf, const rose_address *addr)
 {
-       static char buffer[11];
-
        if (addr->rose_addr[0] == 0x00 && addr->rose_addr[1] == 0x00 &&
            addr->rose_addr[2] == 0x00 && addr->rose_addr[3] == 0x00 &&
            addr->rose_addr[4] == 0x00) {
-               strcpy(buffer, "*");
+               strcpy(buf, "*");
        } else {
-               sprintf(buffer, "%02X%02X%02X%02X%02X", addr->rose_addr[0] & 0xFF,
+               sprintf(buf, "%02X%02X%02X%02X%02X", addr->rose_addr[0] & 0xFF,
                                                addr->rose_addr[1] & 0xFF,
                                                addr->rose_addr[2] & 0xFF,
                                                addr->rose_addr[3] & 0xFF,
                                                addr->rose_addr[4] & 0xFF);
        }
 
-       return buffer;
+       return buf;
 }
 
 /*
@@ -956,6 +954,7 @@ static int rose_getname(struct socket *sock, struct sockaddr *uaddr,
        struct rose_sock *rose = rose_sk(sk);
        int n;
 
+       memset(srose, 0, sizeof(*srose));
        if (peer != 0) {
                if (sk->sk_state != TCP_ESTABLISHED)
                        return -ENOTCONN;
@@ -1437,7 +1436,7 @@ static void rose_info_stop(struct seq_file *seq, void *v)
 
 static int rose_info_show(struct seq_file *seq, void *v)
 {
-       char buf[11];
+       char buf[11], rsbuf[11];
 
        if (v == SEQ_START_TOKEN)
                seq_puts(seq,
@@ -1455,8 +1454,8 @@ static int rose_info_show(struct seq_file *seq, void *v)
                        devname = dev->name;
 
                seq_printf(seq, "%-10s %-9s ",
-                       rose2asc(&rose->dest_addr),
-                       ax2asc(buf, &rose->dest_call));
+                          rose2asc(rsbuf, &rose->dest_addr),
+                          ax2asc(buf, &rose->dest_call));
 
                if (ax25cmp(&rose->source_call, &null_ax25_address) == 0)
                        callsign = "??????-?";
@@ -1465,7 +1464,7 @@ static int rose_info_show(struct seq_file *seq, void *v)
 
                seq_printf(seq,
                           "%-10s %-9s %-5s %3.3X %05d  %d  %d  %d  %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d %ld\n",
-                       rose2asc(&rose->source_addr),
+                       rose2asc(rsbuf, &rose->source_addr),
                        callsign,
                        devname,
                        rose->lci & 0x0FFF,
index a81066a1010a869fa4885d7f3334df3195cfec25..9478d9b3d9777643bcd821fed4a380f8a4123553 100644 (file)
@@ -1104,6 +1104,7 @@ static void rose_node_stop(struct seq_file *seq, void *v)
 
 static int rose_node_show(struct seq_file *seq, void *v)
 {
+       char rsbuf[11];
        int i;
 
        if (v == SEQ_START_TOKEN)
@@ -1112,13 +1113,13 @@ static int rose_node_show(struct seq_file *seq, void *v)
                const struct rose_node *rose_node = v;
                /* if (rose_node->loopback) {
                        seq_printf(seq, "%-10s %04d 1 loopback\n",
-                               rose2asc(&rose_node->address),
-                               rose_node->mask);
+                                  rose2asc(rsbuf, &rose_node->address),
+                                  rose_node->mask);
                } else { */
                        seq_printf(seq, "%-10s %04d %d",
-                               rose2asc(&rose_node->address),
-                               rose_node->mask,
-                               rose_node->count);
+                                  rose2asc(rsbuf, &rose_node->address),
+                                  rose_node->mask,
+                                  rose_node->count);
 
                        for (i = 0; i < rose_node->count; i++)
                                seq_printf(seq, " %05d",
@@ -1267,7 +1268,7 @@ static void rose_route_stop(struct seq_file *seq, void *v)
 
 static int rose_route_show(struct seq_file *seq, void *v)
 {
-       char buf[11];
+       char buf[11], rsbuf[11];
 
        if (v == SEQ_START_TOKEN)
                seq_puts(seq,
@@ -1279,7 +1280,7 @@ static int rose_route_show(struct seq_file *seq, void *v)
                        seq_printf(seq,
                                   "%3.3X  %-10s  %-9s  %05d      ",
                                   rose_route->lci1,
-                                  rose2asc(&rose_route->src_addr),
+                                  rose2asc(rsbuf, &rose_route->src_addr),
                                   ax2asc(buf, &rose_route->src_call),
                                   rose_route->neigh1->number);
                else
@@ -1289,10 +1290,10 @@ static int rose_route_show(struct seq_file *seq, void *v)
                if (rose_route->neigh2)
                        seq_printf(seq,
                                   "%3.3X  %-10s  %-9s  %05d\n",
-                               rose_route->lci2,
-                               rose2asc(&rose_route->dest_addr),
-                               ax2asc(buf, &rose_route->dest_call),
-                               rose_route->neigh2->number);
+                                  rose_route->lci2,
+                                  rose2asc(rsbuf, &rose_route->dest_addr),
+                                  ax2asc(buf, &rose_route->dest_call),
+                                  rose_route->neigh2->number);
                 else
                         seq_puts(seq,
                                  "000  *           *          00000\n");
index eac5e7bb73659c3b951bd7fc9f564e7d380e4d9b..bfe493ebf27c36a7a82974af5a596ee8f75528c9 100644 (file)
@@ -63,7 +63,7 @@ static void rxrpc_write_space(struct sock *sk)
        _enter("%p", sk);
        read_lock(&sk->sk_callback_lock);
        if (rxrpc_writable(sk)) {
-               if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+               if (sk_has_sleeper(sk))
                        wake_up_interruptible(sk->sk_sleep);
                sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
        }
@@ -588,7 +588,7 @@ static unsigned int rxrpc_poll(struct file *file, struct socket *sock,
        unsigned int mask;
        struct sock *sk = sock->sk;
 
-       poll_wait(file, sk->sk_sleep, wait);
+       sock_poll_wait(file, sk->sk_sleep, wait);
        mask = 0;
 
        /* the socket is readable if there are any messages waiting on the Rx
index 24d17ce9c294f384f1a638b7888540455479f3aa..fdb694e9f75938bafad249723c9318b2e4750c3f 100644 (file)
@@ -1456,6 +1456,8 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q,
        nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);
        tcm = NLMSG_DATA(nlh);
        tcm->tcm_family = AF_UNSPEC;
+       tcm->tcm__pad1 = 0;
+       tcm->tcm__pad2 = 0;
        tcm->tcm_ifindex = qdisc_dev(q)->ifindex;
        tcm->tcm_parent = q->handle;
        tcm->tcm_handle = q->handle;
index 2a8b83af7c47a4bbee4471cc62894d46ca1d233a..ab82f145f68937a9c722322517fd2dd479550db0 100644 (file)
@@ -49,7 +49,7 @@ struct atm_flow_data {
        struct socket           *sock;          /* for closing */
        u32                     classid;        /* x:y type ID */
        int                     ref;            /* reference count */
-       struct gnet_stats_basic bstats;
+       struct gnet_stats_basic_packed  bstats;
        struct gnet_stats_queue qstats;
        struct atm_flow_data    *next;
        struct atm_flow_data    *excess;        /* flow for excess traffic;
index 23a167670fd5f11ed1affcfb07b9ad766b381b81..d5798e17a83205f3a44ac09d3c4b5318801d24d4 100644 (file)
@@ -128,7 +128,7 @@ struct cbq_class
        long                    avgidle;
        long                    deficit;        /* Saved deficit for WRR */
        psched_time_t           penalized;
-       struct gnet_stats_basic bstats;
+       struct gnet_stats_basic_packed bstats;
        struct gnet_stats_queue qstats;
        struct gnet_stats_rate_est rate_est;
        struct tc_cbq_xstats    xstats;
index 7597fe14686600e6fa2584544b69ebdfb1144edf..12b2fb04b29b6d4d873e6fe28981dabd7de039b6 100644 (file)
@@ -22,7 +22,7 @@ struct drr_class {
        unsigned int                    refcnt;
        unsigned int                    filter_cnt;
 
-       struct gnet_stats_basic         bstats;
+       struct gnet_stats_basic_packed          bstats;
        struct gnet_stats_queue         qstats;
        struct gnet_stats_rate_est      rate_est;
        struct list_head                alist;
index 362c2811b2dfe95b93daf0d3f10cf98a06373cd6..dad0144423da5a87be4d18c76333cca56f05af84 100644 (file)
@@ -116,7 +116,7 @@ struct hfsc_class
        struct Qdisc_class_common cl_common;
        unsigned int    refcnt;         /* usage count */
 
-       struct gnet_stats_basic bstats;
+       struct gnet_stats_basic_packed bstats;
        struct gnet_stats_queue qstats;
        struct gnet_stats_rate_est rate_est;
        unsigned int    level;          /* class level in hierarchy */
index 88cd0262662138f02fa18393a72667fc172e91c1..ec4d46399d59fbdfa638394b54136a294bf200bc 100644 (file)
@@ -74,7 +74,7 @@ enum htb_cmode {
 struct htb_class {
        struct Qdisc_class_common common;
        /* general class parameters */
-       struct gnet_stats_basic bstats;
+       struct gnet_stats_basic_packed bstats;
        struct gnet_stats_queue qstats;
        struct gnet_stats_rate_est rate_est;
        struct tc_htb_xstats xstats;    /* our special stats */
index b764114445156dc69146856c118cbf1a725addca..b94c2119056661aaa61073a29bd429f069f7923f 100644 (file)
@@ -407,7 +407,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
        }
        dst = dst_clone(tp->dst);
        skb_dst_set(nskb, dst);
-       if (dst)
+       if (!dst)
                goto no_route;
 
        /* Build the SCTP header.  */
index 79cbd47f4df7482b08e11c976d290b5b94ee545b..a76da657244a8e38fdb692426857130034da5fd0 100644 (file)
@@ -160,6 +160,7 @@ static void sctp_proc_exit(void)
                remove_proc_entry("sctp", init_net.proc_net);
        }
 #endif
+       percpu_counter_destroy(&sctp_sockets_allocated);
 }
 
 /* Private helper to extract ipv4 address and stash them in
index 35ba035970a2ace360d9e5498a35e02a7f8a68e6..971890dbfea020be8f75b72269bcf34456abc102 100644 (file)
@@ -6652,21 +6652,6 @@ static void sctp_wait_for_close(struct sock *sk, long timeout)
        finish_wait(sk->sk_sleep, &wait);
 }
 
-static void sctp_sock_rfree_frag(struct sk_buff *skb)
-{
-       struct sk_buff *frag;
-
-       if (!skb->data_len)
-               goto done;
-
-       /* Don't forget the fragments. */
-       skb_walk_frags(skb, frag)
-               sctp_sock_rfree_frag(frag);
-
-done:
-       sctp_sock_rfree(skb);
-}
-
 static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk)
 {
        struct sk_buff *frag;
@@ -6776,7 +6761,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
        sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
                event = sctp_skb2event(skb);
                if (event->asoc == assoc) {
-                       sctp_sock_rfree_frag(skb);
                        __skb_unlink(skb, &oldsk->sk_receive_queue);
                        __skb_queue_tail(&newsk->sk_receive_queue, skb);
                        sctp_skb_set_owner_r_frag(skb, newsk);
@@ -6807,7 +6791,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
                sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
                        event = sctp_skb2event(skb);
                        if (event->asoc == assoc) {
-                               sctp_sock_rfree_frag(skb);
                                __skb_unlink(skb, &oldsp->pd_lobby);
                                __skb_queue_tail(queue, skb);
                                sctp_skb_set_owner_r_frag(skb, newsk);
@@ -6822,15 +6805,11 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
 
        }
 
-       sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) {
-               sctp_sock_rfree_frag(skb);
+       sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp)
                sctp_skb_set_owner_r_frag(skb, newsk);
-       }
 
-       sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) {
-               sctp_sock_rfree_frag(skb);
+       sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp)
                sctp_skb_set_owner_r_frag(skb, newsk);
-       }
 
        /* Set the type of socket to indicate that it is peeled off from the
         * original UDP-style socket or created with the accept() call on a
index 791d71a36a93dfec5166fe05e2e0cb394cfa904b..6d47165590473daa4990bf69b0435d5c49b41302 100644 (file)
@@ -736,7 +736,7 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
        if (more)
                flags |= MSG_MORE;
 
-       return sock->ops->sendpage(sock, page, offset, size, flags);
+       return kernel_sendpage(sock, page, offset, size, flags);
 }
 
 static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
index 5bc2f45bddf0051a90f73274707b2697cc53b5d0..df1039f077c257840c27dacdecdb29443089b3a6 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/kallsyms.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/utsname.h>
 #include <linux/workqueue.h>
 #include <linux/in6.h>
@@ -938,6 +937,7 @@ static inline void
 rpc_task_force_reencode(struct rpc_task *task)
 {
        task->tk_rqstp->rq_snd_buf.len = 0;
+       task->tk_rqstp->rq_bytes_sent = 0;
 }
 
 static inline void
index 1102ce1251f7b61ad7d6a70a7df8826ce2a420c2..8f459abe97cff614525775560ec355f9d4c69246 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/slab.h>
 #include <linux/mempool.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
 
index 843629f557630d07b0b4b0e29eb5a6f9feddce88..adaa81982f7469a31c0aa4af418ea74014312f9e 100644 (file)
@@ -66,6 +66,7 @@ cleanup_sunrpc(void)
 #ifdef CONFIG_PROC_FS
        rpc_proc_exit();
 #endif
+       rcu_barrier(); /* Wait for completion of call_rcu()'s */
 }
 MODULE_LICENSE("GPL");
 module_init(init_sunrpc);
index 6f33d33cc064e0f39f3232c910aff09fd53b3a67..27d44332f0175968c0729646ae4641321104bbd6 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/freezer.h>
 #include <linux/kthread.h>
index 36d4e44d62334275ffbfaa8e3b837e95bcdace5f..fc3ebb906911b955b33b39af1a6a2e729d4695c9 100644 (file)
@@ -315,7 +315,7 @@ static void unix_write_space(struct sock *sk)
 {
        read_lock(&sk->sk_callback_lock);
        if (unix_writable(sk)) {
-               if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
+               if (sk_has_sleeper(sk))
                        wake_up_interruptible_sync(sk->sk_sleep);
                sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
        }
@@ -1985,7 +1985,7 @@ static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table
        struct sock *sk = sock->sk;
        unsigned int mask;
 
-       poll_wait(file, sk->sk_sleep, wait);
+       sock_poll_wait(file, sk->sk_sleep, wait);
        mask = 0;
 
        /* exceptional events? */
@@ -2022,7 +2022,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
        struct sock *sk = sock->sk, *other;
        unsigned int mask, writable;
 
-       poll_wait(file, sk->sk_sleep, wait);
+       sock_poll_wait(file, sk->sk_sleep, wait);
        mask = 0;
 
        /* exceptional events? */
@@ -2053,7 +2053,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
                other = unix_peer_get(sk);
                if (other) {
                        if (unix_peer(other) != sk) {
-                               poll_wait(file, &unix_sk(other)->peer_wait,
+                               sock_poll_wait(file, &unix_sk(other)->peer_wait,
                                          wait);
                                if (unix_recvq_full(other))
                                        writable = 0;
index 466e2d22d256de7151551575607999ff6f1e95a9..258daa80ad926d80d86abcf06aaeb177514d1791 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>      /* support for loadable modules */
 #include <linux/slab.h>                /* kmalloc(), kfree() */
+#include <linux/smp_lock.h>
 #include <linux/mm.h>
 #include <linux/string.h>      /* inline mem*, str* functions */
 
index 241bddd0b4f19b2bb17009a295bf023345bfdc7c..634496b3ed77cb7adf5e1ec1356a307b6b897356 100644 (file)
@@ -447,6 +447,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 
        rdev = __cfg80211_drv_from_info(info);
        if (IS_ERR(rdev)) {
+               mutex_unlock(&cfg80211_mutex);
                result = PTR_ERR(rdev);
                goto unlock;
        }
@@ -996,7 +997,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
 
        if (IS_ERR(hdr)) {
                err = PTR_ERR(hdr);
-               goto out;
+               goto free_msg;
        }
 
        cookie.msg = msg;
@@ -1010,7 +1011,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
                                &cookie, get_key_callback);
 
        if (err)
-               goto out;
+               goto free_msg;
 
        if (cookie.error)
                goto nla_put_failure;
@@ -1021,6 +1022,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
 
  nla_put_failure:
        err = -ENOBUFS;
+ free_msg:
        nlmsg_free(msg);
  out:
        cfg80211_put_dev(drv);
index 5e14371cda704c2c103df0449f929069752148f8..75a406d33619698ecb00b3be5dbbfb75f6d33f31 100644 (file)
@@ -1089,17 +1089,18 @@ static void handle_reg_beacon(struct wiphy *wiphy,
 
        chan->beacon_found = true;
 
+       if (wiphy->disable_beacon_hints)
+               return;
+
        chan_before.center_freq = chan->center_freq;
        chan_before.flags = chan->flags;
 
-       if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) &&
-           !(chan->orig_flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
+       if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) {
                chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
                channel_changed = true;
        }
 
-       if ((chan->flags & IEEE80211_CHAN_NO_IBSS) &&
-           !(chan->orig_flags & IEEE80211_CHAN_NO_IBSS)) {
+       if (chan->flags & IEEE80211_CHAN_NO_IBSS) {
                chan->flags &= ~IEEE80211_CHAN_NO_IBSS;
                channel_changed = true;
        }
index e37829a49dc466fad9a6aff92361afcc26371ad7..4e167a8e11be9352edf259070cd3c390a79a76da 100644 (file)
@@ -30,7 +30,8 @@ int set_regdom(const struct ieee80211_regdomain *rd);
  * non-radar 5 GHz channels.
  *
  * Drivers do not need to call this, cfg80211 will do it for after a scan
- * on a newly found BSS.
+ * on a newly found BSS. If you cannot make use of this feature you can
+ * set the wiphy->disable_beacon_hints to true.
  */
 int regulatory_hint_found_beacon(struct wiphy *wiphy,
                                        struct ieee80211_channel *beacon_chan,
index e95b638b919f5dba4203a0959c0437fd612f239e..7e595ce24eeb71c5da0f8715a80b9af8fbcddc26 100644 (file)
@@ -35,8 +35,6 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
        else
                nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev);
 
-       wiphy_to_dev(request->wiphy)->scan_req = NULL;
-
 #ifdef CONFIG_WIRELESS_EXT
        if (!aborted) {
                memset(&wrqu, 0, sizeof(wrqu));
@@ -48,6 +46,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
        dev_put(dev);
 
  out:
+       wiphy_to_dev(request->wiphy)->scan_req = NULL;
        kfree(request);
 }
 EXPORT_SYMBOL(cfg80211_scan_done);
@@ -119,7 +118,7 @@ static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2)
 
        if (!ie1 && !ie2)
                return 0;
-       if (!ie1)
+       if (!ie1 || !ie2)
                return -1;
 
        r = memcmp(ie1 + 2, ie2 + 2, min(ie1[1], ie2[1]));
@@ -172,6 +171,8 @@ static bool is_mesh(struct cfg80211_bss *a,
        ie = find_ie(WLAN_EID_MESH_CONFIG,
                     a->information_elements,
                     a->len_information_elements);
+       if (!ie)
+               return false;
        if (ie[1] != IEEE80211_MESH_CONFIG_LEN)
                return false;
 
@@ -366,7 +367,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
        found = rb_find_bss(dev, res);
 
        if (found) {
-               kref_get(&found->ref);
                found->pub.beacon_interval = res->pub.beacon_interval;
                found->pub.tsf = res->pub.tsf;
                found->pub.signal = res->pub.signal;
index 21cdc872004edbb4acba70070eadaa0ad8102e27..5e6c072c64d3d8b3380cc68247565fa291237952 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/net.h>
index d31ccb487730b174a44ae0cc15d53d7fe9106822..faf54c6bf96bed9a25402d4ab728a21af120a207 100644 (file)
@@ -292,8 +292,8 @@ static struct xfrm_algo_desc ealg_list[] = {
        }
 },
 {
-       .name = "cbc(cast128)",
-       .compat = "cast128",
+       .name = "cbc(cast5)",
+       .compat = "cast5",
 
        .uinfo = {
                .encr = {
index d401dc8f05ed4b16ddde802bf3d2190d72cd2cf3..e5195c99f71e267e70cb62b3689f7e6f02a809dd 100644 (file)
@@ -16,7 +16,7 @@ static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr)
 
 static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr)
 {
-       return ntohl(daddr->a4 ^ saddr->a4);
+       return ntohl(daddr->a4 + saddr->a4);
 }
 
 static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr)
index 5f1f86565f162e4bccf4bcc215ef78a8272bbae3..f2f7c638083e321b8500e449f9a84c19bf903d97 100644 (file)
@@ -668,22 +668,10 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *d
        hlist_for_each_entry(x, entry, net->xfrm.state_byspi+h, byspi) {
                if (x->props.family != family ||
                    x->id.spi       != spi ||
-                   x->id.proto     != proto)
+                   x->id.proto     != proto ||
+                   xfrm_addr_cmp(&x->id.daddr, daddr, family))
                        continue;
 
-               switch (family) {
-               case AF_INET:
-                       if (x->id.daddr.a4 != daddr->a4)
-                               continue;
-                       break;
-               case AF_INET6:
-                       if (!ipv6_addr_equal((struct in6_addr *)daddr,
-                                            (struct in6_addr *)
-                                            x->id.daddr.a6))
-                               continue;
-                       break;
-               }
-
                xfrm_state_hold(x);
                return x;
        }
@@ -699,26 +687,11 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_addre
 
        hlist_for_each_entry(x, entry, net->xfrm.state_bysrc+h, bysrc) {
                if (x->props.family != family ||
-                   x->id.proto     != proto)
+                   x->id.proto     != proto ||
+                   xfrm_addr_cmp(&x->id.daddr, daddr, family) ||
+                   xfrm_addr_cmp(&x->props.saddr, saddr, family))
                        continue;
 
-               switch (family) {
-               case AF_INET:
-                       if (x->id.daddr.a4 != daddr->a4 ||
-                           x->props.saddr.a4 != saddr->a4)
-                               continue;
-                       break;
-               case AF_INET6:
-                       if (!ipv6_addr_equal((struct in6_addr *)daddr,
-                                            (struct in6_addr *)
-                                            x->id.daddr.a6) ||
-                           !ipv6_addr_equal((struct in6_addr *)saddr,
-                                            (struct in6_addr *)
-                                            x->props.saddr.a6))
-                               continue;
-                       break;
-               }
-
                xfrm_state_hold(x);
                return x;
        }
@@ -1001,25 +974,11 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family
                    x->props.family != family ||
                    x->km.state     != XFRM_STATE_ACQ ||
                    x->id.spi       != 0 ||
-                   x->id.proto     != proto)
+                   x->id.proto     != proto ||
+                   xfrm_addr_cmp(&x->id.daddr, daddr, family) ||
+                   xfrm_addr_cmp(&x->props.saddr, saddr, family))
                        continue;
 
-               switch (family) {
-               case AF_INET:
-                       if (x->id.daddr.a4    != daddr->a4 ||
-                           x->props.saddr.a4 != saddr->a4)
-                               continue;
-                       break;
-               case AF_INET6:
-                       if (!ipv6_addr_equal((struct in6_addr *)x->id.daddr.a6,
-                                            (struct in6_addr *)daddr) ||
-                           !ipv6_addr_equal((struct in6_addr *)
-                                            x->props.saddr.a6,
-                                            (struct in6_addr *)saddr))
-                               continue;
-                       break;
-               }
-
                xfrm_state_hold(x);
                return x;
        }
index 9977a756fb32102dae7b7e4eedf3130c20546e6f..f24ae370e514f77f04342c78d0d180e89e4001f4 100644 (file)
@@ -1,20 +1,3 @@
-/*
- * Notice that this file is not protected like a normal header.
- * We also must allow for rereading of this file. The
- *
- *  || defined(TRACE_HEADER_MULTI_READ)
- *
- * serves this purpose.
- */
-#if !defined(_TRACE_EVENT_SAMPLE_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_EVENT_SAMPLE_H
-
-/*
- * All trace headers should include tracepoint.h, until we finally
- * make it into a standard header.
- */
-#include <linux/tracepoint.h>
-
 /*
  * If TRACE_SYSTEM is defined, that will be the directory created
  * in the ftrace directory under /debugfs/tracing/events/<system>
  * #define TRACE_INCLUDE_FILE trace-events-sample
  *
  * As we do an the bottom of this file.
+ *
+ * Notice that TRACE_SYSTEM should be defined outside of #if
+ * protection, just like TRACE_INCLUDE_FILE.
  */
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM sample
 
+/*
+ * Notice that this file is not protected like a normal header.
+ * We also must allow for rereading of this file. The
+ *
+ *  || defined(TRACE_HEADER_MULTI_READ)
+ *
+ * serves this purpose.
+ */
+#if !defined(_TRACE_EVENT_SAMPLE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_EVENT_SAMPLE_H
+
+/*
+ * All trace headers should include tracepoint.h, until we finally
+ * make it into a standard header.
+ */
+#include <linux/tracepoint.h>
+
 /*
  * The TRACE_EVENT macro is broken up into 5 parts.
  *
index b939fbd0119539f38b6c4f34e211223d9d8b4a45..52cab46ae35a3be5a6a1869ce2b01aa9c4e06190 100644 (file)
@@ -7,3 +7,4 @@ pnmtologo
 bin2c
 unifdef
 binoffset
+ihex2fw
diff --git a/scripts/dtc/.gitignore b/scripts/dtc/.gitignore
new file mode 100644 (file)
index 0000000..095acb4
--- /dev/null
@@ -0,0 +1,5 @@
+dtc
+dtc-lexer.lex.c
+dtc-parser.tab.c
+dtc-parser.tab.h
+
index 3e733146cd51c01acd792503162cc43e4b7a3d74..278a45bd45a5ea705b3d5bdb36e72a52b41ac08c 100755 (executable)
@@ -13,7 +13,7 @@
 use strict;
 
 my $P = $0;
-my $V = '0.16';
+my $V = '0.17';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -27,6 +27,7 @@ my $email_git = 1;
 my $email_git_penguin_chiefs = 0;
 my $email_git_min_signatures = 1;
 my $email_git_max_maintainers = 5;
+my $email_git_min_percent = 5;
 my $email_git_since = "1-year-ago";
 my $output_multiline = 1;
 my $output_separator = ", ";
@@ -65,6 +66,7 @@ if (!GetOptions(
                'git-chief-penguins!' => \$email_git_penguin_chiefs,
                'git-min-signatures=i' => \$email_git_min_signatures,
                'git-max-maintainers=i' => \$email_git_max_maintainers,
+               'git-min-percent=i' => \$email_git_min_percent,
                'git-since=s' => \$email_git_since,
                'm!' => \$email_maintainer,
                'n!' => \$email_usename,
@@ -132,6 +134,10 @@ while (<MAINT>) {
            $value =~ s@\.@\\\.@g;       ##Convert . to \.
            $value =~ s/\*/\.\*/g;       ##Convert * to .*
            $value =~ s/\?/\./g;         ##Convert ? to .
+           ##if pattern is a directory and it lacks a trailing slash, add one
+           if ((-d $value)) {
+               $value =~ s@([^/])$@$1/@;
+           }
        }
        push(@typevalue, "$type:$value");
     } elsif (!/^(\s)*$/) {
@@ -146,8 +152,10 @@ close(MAINT);
 my @files = ();
 
 foreach my $file (@ARGV) {
-    next if ((-d $file));
-    if (!(-f $file)) {
+    ##if $file is a directory and it lacks a trailing slash, add one
+    if ((-d $file)) {
+       $file =~ s@([^/])$@$1/@;
+    } elsif (!(-f $file)) {
        die "$P: file '${file}' not found\n";
     }
     if ($from_filename) {
@@ -292,7 +300,7 @@ sub file_match_pattern {
 sub usage {
     print <<EOT;
 usage: $P [options] patchfile
-       $P [options] -f file
+       $P [options] -f file|directory
 version: $V
 
 MAINTAINER field selection options:
@@ -301,6 +309,7 @@ MAINTAINER field selection options:
     --git-chief-penguins => include ${penguin_chiefs}
     --git-min-signatures => number of signatures required (default: 1)
     --git-max-maintainers => maximum maintainers to add (default: 5)
+    --git-min-percent => minimum percentage of commits required (default: 5)
     --git-since => git history to use (default: 1-year-ago)
     --m => include maintainer(s) if any
     --n => include name 'Full Name <addr\@domain.tld>'
@@ -322,6 +331,15 @@ Other options:
   --version => show version
   --help => show this help information
 
+Notes:
+  Using "-f directory" may give unexpected results:
+
+  Used with "--git", git signators for _all_ files in and below
+     directory are examined as git recurses directories.
+     Any specified X: (exclude) pattern matches are _not_ ignored.
+  Used with "--nogit", directory is used as a pattern match,
+     no individual file within the directory or subdirectory
+     is matched.
 EOT
 }
 
@@ -482,6 +500,7 @@ sub recent_git_signoffs {
     my $output = "";
     my $count = 0;
     my @lines = ();
+    my $total_sign_offs;
 
     if (which("git") eq "") {
        warn("$P: git not found.  Add --nogit to options?\n");
@@ -505,17 +524,26 @@ sub recent_git_signoffs {
     $output =~ s/^\s*//gm;
 
     @lines = split("\n", $output);
+
+    $total_sign_offs = 0;
+    foreach my $line (@lines) {
+       if ($line =~ m/([0-9]+)\s+(.*)/) {
+           $total_sign_offs += $1;
+       } else {
+           die("$P: Unexpected git output: ${line}\n");
+       }
+    }
+
     foreach my $line (@lines) {
        if ($line =~ m/([0-9]+)\s+(.*)/) {
            my $sign_offs = $1;
            $line = $2;
            $count++;
            if ($sign_offs < $email_git_min_signatures ||
-               $count > $email_git_max_maintainers) {
+               $count > $email_git_max_maintainers ||
+               $sign_offs * 100 / $total_sign_offs < $email_git_min_percent) {
                last;
            }
-       } else {
-           die("$P: Unexpected git output: ${line}\n");
        }
        if ($line =~ m/(.+)<(.+)>/) {
            my $git_name = $1;
index 86d95cca46a7cfc57922e50d8fd91b74fc8da745..f2375ad7ebc9bf07d306fc8de611f631b36cd7bf 100644 (file)
@@ -19,6 +19,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <stdarg.h>
+
 #include "dialog.h"
 
 struct dialog_info dlg;
index 3bcacb4bfd3af8284293a21fa202c886d3339126..25b60bc117f738fabc26efb9a2e8f4f7546cd8d1 100644 (file)
@@ -888,6 +888,8 @@ int main(int ac, char **av)
                        single_menu_mode = 1;
        }
 
+       initscr();
+
        getyx(stdscr, saved_y, saved_x);
        if (init_dialog(NULL)) {
                fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
index ed591e9b7d1de8945040bef790bb2a540bcc09d2..b52d340d759da1123b94cdc441feb83e9458b3c0 100755 (executable)
@@ -1426,6 +1426,8 @@ sub dump_struct($$) {
        # strip comments:
        $members =~ s/\/\*.*?\*\///gos;
        $nested =~ s/\/\*.*?\*\///gos;
+       # strip kmemcheck_bitfield_{begin,end}.*;
+       $members =~ s/kmemcheck_bitfield_.*?;//gos;
 
        create_parameterlist($members, ';', $file);
        check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested);
@@ -1468,8 +1470,6 @@ sub dump_enum($$) {
            }
 
        }
-       # strip kmemcheck_bitfield_{begin,end}.*;
-       $members =~ s/kmemcheck_bitfield_.*?;//gos;
 
        output_declaration($declaration_name,
                           'enum',
index 528492bcba5bf73e8f809490c9d6d8c8ea821ec8..89774011965d7f17289b09af086c1651e9cf7ef1 100644 (file)
@@ -1,6 +1,7 @@
 #!/usr/bin/perl
 
 use File::Basename;
+use Math::BigInt;
 
 # Copyright 2008, Intel Corporation
 #
@@ -172,8 +173,8 @@ while (<STDIN>) {
        parse_x86_regs($line);
 }
 
-my $decodestart = hex($target) - hex($func_offset);
-my $decodestop = hex($target) + 8192;
+my $decodestart = Math::BigInt->from_hex("0x$target") - Math::BigInt->from_hex("0x$func_offset");
+my $decodestop = Math::BigInt->from_hex("0x$target") + 8192;
 if ($target eq "0") {
        print "No oops found!\n";
        print "Usage: \n";
index 01c2d13dd0204367b9655ee1c202f0a437ed2398..8b357b0bd250b0e04012a08815c01cd3f95f22a3 100644 (file)
@@ -16,6 +16,8 @@ create_package() {
        local pname="$1" pdir="$2"
 
        cp debian/copyright "$pdir/usr/share/doc/$pname/"
+       cp debian/changelog "$pdir/usr/share/doc/$pname/changelog.Debian"
+       gzip -9 "$pdir/usr/share/doc/$pname/changelog.Debian"
 
        # Fix ownership and permissions
        chown -R root:root "$pdir"
@@ -87,7 +89,7 @@ for script in postinst postrm preinst prerm ; do
 set -e
 
 # Pass maintainer script parameters to hook scripts
-export DEB_MAINT_PARAMS="\$@"
+export DEB_MAINT_PARAMS="\$*"
 
 test -d $debhookdir/$script.d && run-parts --arg="$version" $debhookdir/$script.d
 exit 0
index 64f5ddb09ea626de131090d68aa5aeac10de060e..5c113123ed9f208840d5af7283e6df4769a4bc12 100644 (file)
@@ -237,7 +237,7 @@ static void write_header(void)
     fprintf(out, " *  Linux logo %s\n", logoname);
     fputs(" */\n\n", out);
     fputs("#include <linux/linux_logo.h>\n\n", out);
-    fprintf(out, "static const unsigned char %s_data[] __initconst = {\n",
+    fprintf(out, "static unsigned char %s_data[] __initdata = {\n",
            logoname);
 }
 
@@ -374,7 +374,7 @@ static void write_logo_clut224(void)
     fputs("\n};\n\n", out);
 
     /* write logo clut */
-    fprintf(out, "static const unsigned char %s_clut[] __initconst = {\n",
+    fprintf(out, "static unsigned char %s_clut[] __initdata = {\n",
            logoname);
     write_hex_cnt = 0;
     for (i = 0; i < logo_clutsize; i++) {
index 7109e2b5bc0acf61e39c24aff4b2074016e6078c..911ba7ffab842dd3017229e269851501f19c145f 100755 (executable)
@@ -393,7 +393,7 @@ while (<IN>) {
            $read_function = 0;
        }
        # print out any recorded offsets
-       update_funcs() if ($text_found);
+       update_funcs() if (defined($ref_func));
 
        # reset all markers and arrays
        $text_found = 0;
@@ -403,7 +403,6 @@ while (<IN>) {
     # section found, now is this a start of a function?
     } elsif ($read_function && /$function_regex/) {
        $text_found = 1;
-       $offset = hex $1;
        $text = $2;
 
        # if this is either a local function or a weak function
@@ -412,10 +411,15 @@ while (<IN>) {
        if (!defined($locals{$text}) && !defined($weak{$text})) {
            $ref_func = $text;
            $read_function = 0;
+           $offset = hex $1;
        } else {
            # if we already have a function, and this is weak, skip it
-           if (!defined($ref_func) || !defined($weak{$text})) {
+           if (!defined($ref_func) && !defined($weak{$text}) &&
+                # PPC64 can have symbols that start with .L and
+                # gcc considers these special. Don't use them!
+                $text !~ /^\.L/) {
                $ref_func = $text;
+               $offset = hex $1;
            }
        }
     } elsif ($read_headers && /$mcount_section/) {
@@ -440,7 +444,7 @@ while (<IN>) {
 }
 
 # dump out anymore offsets that may have been found
-update_funcs() if ($text_found);
+update_funcs() if (defined($ref_func));
 
 # If we did not find any mcount callers, we are done (do nothing).
 if (!$opened) {
index d23c839038f00836cb96a51e53e27db8b8ec163c..4c865345caa01700451dd5aa7f8e290a2389690a 100644 (file)
@@ -113,6 +113,22 @@ config SECURITY_ROOTPLUG
 
          If you are unsure how to answer this question, answer N.
 
+config LSM_MMAP_MIN_ADDR
+       int "Low address space for LSM to protect from user allocation"
+       depends on SECURITY && SECURITY_SELINUX
+       default 65536
+       help
+         This is the portion of low virtual memory which should be protected
+         from userspace allocation.  Keeping a user from writing to low pages
+         can help reduce the impact of kernel NULL pointer bugs.
+
+         For most ia64, ppc64 and x86 users with lots of address space
+         a value of 65536 is reasonable and should cause no problems.
+         On arm and other archs it should not be higher than 32768.
+         Programs which use vm86 functionality or have some need to map
+         this low address space will need the permission specific to the
+         systems running LSM.
+
 source security/selinux/Kconfig
 source security/smack/Kconfig
 source security/tomoyo/Kconfig
index c67557cdaa857f9046d30cacb7f3ecc42196f9bb..b56e7f9ecbc2adf22706a849d704d8761dfa91dd 100644 (file)
@@ -8,7 +8,7 @@ subdir-$(CONFIG_SECURITY_SMACK)         += smack
 subdir-$(CONFIG_SECURITY_TOMOYO)        += tomoyo
 
 # always enable default capabilities
-obj-y          += commoncap.o
+obj-y          += commoncap.o min_addr.o
 
 # Object file lists
 obj-$(CONFIG_SECURITY)                 += security.o capability.o
index 21b6cead6a8ed38927abab1bd8cd9c491194c1bf..88f752e8152cbe1ea888747121181035fcb8fbbb 100644 (file)
@@ -330,15 +330,6 @@ static int cap_file_ioctl(struct file *file, unsigned int command,
        return 0;
 }
 
-static int cap_file_mmap(struct file *file, unsigned long reqprot,
-                        unsigned long prot, unsigned long flags,
-                        unsigned long addr, unsigned long addr_only)
-{
-       if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO))
-               return -EACCES;
-       return 0;
-}
-
 static int cap_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
                             unsigned long prot)
 {
index 48b7e0228fa38455ee6c2bf0cb37876e96c99afb..e3097c0a1311205cc231cee85cb012b271db1ed8 100644 (file)
@@ -984,3 +984,33 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
                cap_sys_admin = 1;
        return __vm_enough_memory(mm, pages, cap_sys_admin);
 }
+
+/*
+ * cap_file_mmap - check if able to map given addr
+ * @file: unused
+ * @reqprot: unused
+ * @prot: unused
+ * @flags: unused
+ * @addr: address attempting to be mapped
+ * @addr_only: unused
+ *
+ * If the process is attempting to map memory below mmap_min_addr they need
+ * CAP_SYS_RAWIO.  The other parameters to this function are unused by the
+ * capability security module.  Returns 0 if this mapping should be allowed
+ * -EPERM if not.
+ */
+int cap_file_mmap(struct file *file, unsigned long reqprot,
+                 unsigned long prot, unsigned long flags,
+                 unsigned long addr, unsigned long addr_only)
+{
+       int ret = 0;
+
+       if (addr < dac_mmap_min_addr) {
+               ret = cap_capable(current, current_cred(), CAP_SYS_RAWIO,
+                                 SECURITY_CAP_AUDIT);
+               /* set PF_SUPERPRIV if it turns out we allow the low mmap */
+               if (ret == 0)
+                       current->flags |= PF_SUPERPRIV;
+       }
+       return ret;
+}
index 63003a63aaeedbc6fd6e6badaa3eaa5a705b67a8..46642a19bc78928759aaf753429c10c07e1bcb54 100644 (file)
@@ -45,9 +45,9 @@ int ima_calc_hash(struct file *file, char *digest)
 {
        struct hash_desc desc;
        struct scatterlist sg[1];
-       loff_t i_size;
+       loff_t i_size, offset = 0;
        char *rbuf;
-       int rc, offset = 0;
+       int rc;
 
        rc = init_desc(&desc);
        if (rc != 0)
@@ -67,6 +67,8 @@ int ima_calc_hash(struct file *file, char *digest)
                        rc = rbuf_len;
                        break;
                }
+               if (rbuf_len == 0)
+                       break;
                offset += rbuf_len;
                sg_init_one(sg, rbuf, rbuf_len);
 
index 6f611874d10e9f7bbea81fab4fc537d68a711b75..b85e61bcf246c45be863baff63420012d6c765c1 100644 (file)
@@ -238,7 +238,40 @@ out:
 }
 
 /*
- * ima_opens_get - increment file counts
+ * ima_counts_put - decrement file counts
+ *
+ * File counts are incremented in ima_path_check. On file open
+ * error, such as ETXTBSY, decrement the counts to prevent
+ * unnecessary imbalance messages.
+ */
+void ima_counts_put(struct path *path, int mask)
+{
+       struct inode *inode = path->dentry->d_inode;
+       struct ima_iint_cache *iint;
+
+       /* The inode may already have been freed, freeing the iint
+        * with it. Verify the inode is not NULL before dereferencing
+        * it.
+        */
+       if (!ima_initialized || !inode || !S_ISREG(inode->i_mode))
+               return;
+       iint = ima_iint_find_insert_get(inode);
+       if (!iint)
+               return;
+
+       mutex_lock(&iint->mutex);
+       iint->opencount--;
+       if ((mask & MAY_WRITE) || (mask == 0))
+               iint->writecount--;
+       else if (mask & (MAY_READ | MAY_EXEC))
+               iint->readcount--;
+       mutex_unlock(&iint->mutex);
+
+       kref_put(&iint->refcount, iint_free);
+}
+
+/*
+ * ima_counts_get - increment file counts
  *
  * - for IPC shm and shmat file.
  * - for nfsd exported files.
@@ -264,6 +297,8 @@ void ima_counts_get(struct file *file)
        if (file->f_mode & FMODE_WRITE)
                iint->writecount++;
        mutex_unlock(&iint->mutex);
+
+       kref_put(&iint->refcount, iint_free);
 }
 EXPORT_SYMBOL_GPL(ima_counts_get);
 
index 7ec94314ac0ca28126b7c051d8663bbd1319f9de..a0880e9c8e054695c757818b7991b2c37daf38ab 100644 (file)
@@ -134,7 +134,8 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
        }
 out:
        mutex_unlock(&ima_extend_list_mutex);
-       integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, entry->template_name,
+       integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
+                           entry->template.file_name,
                            op, audit_cause, result, audit_info);
        return result;
 }
diff --git a/security/min_addr.c b/security/min_addr.c
new file mode 100644 (file)
index 0000000..14cc7b3
--- /dev/null
@@ -0,0 +1,49 @@
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/security.h>
+#include <linux/sysctl.h>
+
+/* amount of vm to protect from userspace access by both DAC and the LSM*/
+unsigned long mmap_min_addr;
+/* amount of vm to protect from userspace using CAP_SYS_RAWIO (DAC) */
+unsigned long dac_mmap_min_addr = CONFIG_DEFAULT_MMAP_MIN_ADDR;
+/* amount of vm to protect from userspace using the LSM = CONFIG_LSM_MMAP_MIN_ADDR */
+
+/*
+ * Update mmap_min_addr = max(dac_mmap_min_addr, CONFIG_LSM_MMAP_MIN_ADDR)
+ */
+static void update_mmap_min_addr(void)
+{
+#ifdef CONFIG_LSM_MMAP_MIN_ADDR
+       if (dac_mmap_min_addr > CONFIG_LSM_MMAP_MIN_ADDR)
+               mmap_min_addr = dac_mmap_min_addr;
+       else
+               mmap_min_addr = CONFIG_LSM_MMAP_MIN_ADDR;
+#else
+       mmap_min_addr = dac_mmap_min_addr;
+#endif
+}
+
+/*
+ * sysctl handler which just sets dac_mmap_min_addr = the new value and then
+ * calls update_mmap_min_addr() so non MAP_FIXED hints get rounded properly
+ */
+int mmap_min_addr_handler(struct ctl_table *table, int write, struct file *filp,
+                         void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int ret;
+
+       ret = proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos);
+
+       update_mmap_min_addr();
+
+       return ret;
+}
+
+int __init init_mmap_min_addr(void)
+{
+       update_mmap_min_addr();
+
+       return 0;
+}
+pure_initcall(init_mmap_min_addr);
index 15c2a08a66f1217e92028a38e861ad4981ab3fdd..8d8b69c5664ef7f1eaa89c8a19139152ca159477 100644 (file)
@@ -1285,6 +1285,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
                rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
                                           context, len);
                if (rc == -ERANGE) {
+                       kfree(context);
+
                        /* Need a larger buffer.  Query for the right size. */
                        rc = inode->i_op->getxattr(dentry, XATTR_NAME_SELINUX,
                                                   NULL, 0);
@@ -1292,7 +1294,6 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
                                dput(dentry);
                                goto out_unlock;
                        }
-                       kfree(context);
                        len = rc;
                        context = kmalloc(len+1, GFP_NOFS);
                        if (!context) {
@@ -3029,9 +3030,21 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot,
        int rc = 0;
        u32 sid = current_sid();
 
-       if (addr < mmap_min_addr)
+       /*
+        * notice that we are intentionally putting the SELinux check before
+        * the secondary cap_file_mmap check.  This is such a likely attempt
+        * at bad behaviour/exploit that we always want to get the AVC, even
+        * if DAC would have also denied the operation.
+        */
+       if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
                rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
                                  MEMPROTECT__MMAP_ZERO, NULL);
+               if (rc)
+                       return rc;
+       }
+
+       /* do DAC check on address space usage */
+       rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
        if (rc || addr_only)
                return rc;
 
index 1eceb85287c5f8197a25fe4a326c25b5dbf8e5be..439e15c8faa3d5f3ee7ef3b101bd9933c6ac6140 100644 (file)
@@ -32,6 +32,34 @@ config SOUND_OSS_CORE
        bool
        default n
 
+config SOUND_OSS_CORE_PRECLAIM
+       bool "Preclaim OSS device numbers"
+       depends on SOUND_OSS_CORE
+       default y
+       help
+         With this option enabled, the kernel will claim all OSS device
+         numbers if any OSS support (native or emulation) is enabled
+         whether the respective module is loaded or not and try to load the
+         appropriate module using sound-slot/service-* and char-major-*
+         module aliases when one of the device numbers is opened.  With
+         this option disabled, kernel will only claim actually in-use
+         device numbers and opening a missing device will generate only the
+         standard char-major-* aliases.
+
+         The only visible difference is use of additional module aliases
+         and whether OSS sound devices appear multiple times in
+         /proc/devices.  sound-slot/service-* module aliases are scheduled
+         to be removed (ie. PRECLAIM won't be available) and this option is
+         to make the transition easier.  This option can be overridden
+         during boot using the kernel parameter soundcore.preclaim_oss.
+
+         Disabling this allows alternative OSS implementations.
+
+         Please read Documentation/feature-removal-schedule.txt for
+         details.
+
+         If unusre, say Y.
+
 source "sound/oss/dmasound/Kconfig"
 
 if !M68K
index f0ebc971c6865041855e27b9b3cc3423e20c1cfa..1dd66ddffcaf6b97cf46ef2fe2f055a7ca317d37 100644 (file)
@@ -897,6 +897,15 @@ static int tas_create(struct i2c_adapter *adapter,
        client = i2c_new_device(adapter, &info);
        if (!client)
                return -ENODEV;
+       /*
+        * We know the driver is already loaded, so the device should be
+        * already bound. If not it means binding failed, and then there
+        * is no point in keeping the device instantiated.
+        */
+       if (!client->driver) {
+               i2c_unregister_device(client);
+               return -ENODEV;
+       }
 
        /*
         * Let i2c-core delete that device on driver removal.
index 5ca2220eac7d648a598488aca8858ef45f1e6afd..1dd0c28d1fb72c6bfb85858afc1f665917b94f86 100644 (file)
@@ -182,6 +182,10 @@ static int pmf_set_notify(struct gpio_runtime *rt,
        if (!old && notify) {
                irq_client = kzalloc(sizeof(struct pmf_irq_client),
                                     GFP_KERNEL);
+               if (!irq_client) {
+                       err = -ENOMEM;
+                       goto out_unlock;
+               }
                irq_client->data = notif;
                irq_client->handler = pmf_handle_notify_irq;
                irq_client->owner = THIS_MODULE;
index c570ebd9d1774fff9fa4e452a70bf9c15b5c93fe..4e34d19ddbc0acb9e519e441f2d2a6a5246e0b99 100644 (file)
@@ -170,6 +170,13 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
        struct snd_ac97_bus *ac97_bus;
        struct snd_ac97_template ac97_template;
        int ret;
+       pxa2xx_audio_ops_t *pdata = dev->dev.platform_data;
+
+       if (dev->id >= 0) {
+               dev_err(&dev->dev, "PXA2xx has only one AC97 port.\n");
+               ret = -ENXIO;
+               goto err_dev;
+       }
 
        ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
                              THIS_MODULE, 0, &card);
@@ -200,6 +207,8 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
        snprintf(card->longname, sizeof(card->longname),
                 "%s (%s)", dev->dev.driver->name, card->mixername);
 
+       if (pdata && pdata->codec_pdata[0])
+               snd_ac97_dev_add_pdata(ac97_bus->codec[0], pdata->codec_pdata[0]);
        snd_card_set_dev(card, &dev->dev);
        ret = snd_card_register(card);
        if (ret == 0) {
@@ -212,6 +221,7 @@ err_remove:
 err:
        if (card)
                snd_card_free(card);
+err_dev:
        return ret;
 }
 
index 108b643229baecc3ec592eb300fbd4f332936c8c..743ac6a2906598fdbd70a04f6a3c6910fd86fdfe 100644 (file)
@@ -75,7 +75,7 @@ int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
 {
        struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
 
-       if (rtd && rtd->params)
+       if (rtd && rtd->params && rtd->params->drcmr)
                *rtd->params->drcmr = 0;
 
        snd_pcm_set_runtime_buffer(substream, NULL);
@@ -136,6 +136,9 @@ int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
 {
        struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
 
+       if (!prtd || !prtd->params)
+               return 0;
+
        DCSR(prtd->dma_ch) &= ~DCSR_RUN;
        DCSR(prtd->dma_ch) = 0;
        DCMD(prtd->dma_ch) = 0;
index 6061fb5f4e1c14a8d1cc4b38ec3babe68f17a92d..c15682a2f9dbd743db935ca682be3ba1a669bb63 100644 (file)
@@ -206,4 +206,8 @@ config SND_PCM_XRUN_DEBUG
 config SND_VMASTER
        bool
 
+config SND_DMA_SGBUF
+       def_bool y
+       depends on X86
+
 source "sound/core/seq/Kconfig"
index 4229052e7b9113fcf82facba4a480efee996385f..350a08d277f42ba41fd4c96ead6c7900c1ec9824 100644 (file)
@@ -13,7 +13,7 @@ snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
                pcm_memory.o
 
 snd-page-alloc-y := memalloc.o
-snd-page-alloc-$(CONFIG_HAS_DMA) += sgbuf.o
+snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o
 
 snd-rawmidi-objs  := rawmidi.o
 snd-timer-objs    := timer.o
index 17b8d47a5cd07f2fca53ec7ef31d935a8958b327..a8b7fabe645ef1d0bf7fc82f4d15e4cd7024b1ed 100644 (file)
@@ -414,7 +414,7 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id)
 EXPORT_SYMBOL(snd_ctl_remove_id);
 
 /**
- * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it
+ * snd_ctl_remove_user_ctl - remove and release the unlocked user control
  * @file: active control handle
  * @id: the control id to remove
  *
@@ -423,8 +423,8 @@ EXPORT_SYMBOL(snd_ctl_remove_id);
  * 
  * Returns 0 if successful, or a negative error code on failure.
  */
-static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file,
-                                     struct snd_ctl_elem_id *id)
+static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file,
+                                  struct snd_ctl_elem_id *id)
 {
        struct snd_card *card = file->card;
        struct snd_kcontrol *kctl;
@@ -433,15 +433,23 @@ static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file,
        down_write(&card->controls_rwsem);
        kctl = snd_ctl_find_id(card, id);
        if (kctl == NULL) {
-               up_write(&card->controls_rwsem);
-               return -ENOENT;
+               ret = -ENOENT;
+               goto error;
+       }
+       if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) {
+               ret = -EINVAL;
+               goto error;
        }
        for (idx = 0; idx < kctl->count; idx++)
                if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) {
-                       up_write(&card->controls_rwsem);
-                       return -EBUSY;
+                       ret = -EBUSY;
+                       goto error;
                }
        ret = snd_ctl_remove(card, kctl);
+       if (ret < 0)
+               goto error;
+       card->user_ctl_count--;
+error:
        up_write(&card->controls_rwsem);
        return ret;
 }
@@ -951,7 +959,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
        
        if (card->user_ctl_count >= MAX_USER_CONTROLS)
                return -ENOMEM;
-       if (info->count > 1024)
+       if (info->count < 1)
                return -EINVAL;
        access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
                (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|
@@ -1052,18 +1060,10 @@ static int snd_ctl_elem_remove(struct snd_ctl_file *file,
                               struct snd_ctl_elem_id __user *_id)
 {
        struct snd_ctl_elem_id id;
-       int err;
 
        if (copy_from_user(&id, _id, sizeof(id)))
                return -EFAULT;
-       err = snd_ctl_remove_unlocked_id(file, &id);
-       if (! err) {
-               struct snd_card *card = file->card;
-               down_write(&card->controls_rwsem);
-               card->user_ctl_count--;
-               up_write(&card->controls_rwsem);
-       }
-       return err;
+       return snd_ctl_remove_user_ctl(file, &id);
 }
 
 static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr)
index 35df614f6c5599329a403beb7295f3ffe3a51d2e..d749a0d394a7fb5d2327e4e659dc42d194edd9b5 100644 (file)
@@ -88,12 +88,10 @@ static int resize_info_buffer(struct snd_info_buffer *buffer,
        char *nbuf;
 
        nsize = PAGE_ALIGN(nsize);
-       nbuf = kmalloc(nsize, GFP_KERNEL);
+       nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL);
        if (! nbuf)
                return -ENOMEM;
 
-       memcpy(nbuf, buffer->buffer, buffer->len);
-       kfree(buffer->buffer);
        buffer->buffer = nbuf;
        buffer->len = nsize;
        return 0;
@@ -108,7 +106,7 @@ static int resize_info_buffer(struct snd_info_buffer *buffer,
  *
  * Returns the size of output string.
  */
-int snd_iprintf(struct snd_info_buffer *buffer, char *fmt,...)
+int snd_iprintf(struct snd_info_buffer *buffer, const char *fmt, ...)
 {
        va_list args;
        int len, res;
@@ -727,7 +725,7 @@ EXPORT_SYMBOL(snd_info_get_line);
  * Returns the updated pointer of the original string so that
  * it can be used for the next call.
  */
-char *snd_info_get_str(char *dest, char *src, int len)
+const char *snd_info_get_str(char *dest, const char *src, int len)
 {
        int c;
 
index d5d40d78c409e6b865f0b420683ddd0c3f41d324..ec4a50ce56560372eb957eeaa8f66d4e8508b9a6 100644 (file)
 #include <sound/control.h>
 #include <sound/info.h>
 
+/* monitor files for graceful shutdown (hotplug) */
+struct snd_monitor_file {
+       struct file *file;
+       const struct file_operations *disconnected_f_op;
+       struct list_head shutdown_list; /* still need to shutdown */
+       struct list_head list;  /* link of monitor files */
+};
+
 static DEFINE_SPINLOCK(shutdown_lock);
 static LIST_HEAD(shutdown_files);
 
index 1b3534d67686d407992b7f712306c43d87e29863..9e92441f9b78fb3b51c5924ae1052e980629d1cc 100644 (file)
@@ -199,6 +199,8 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
        case SNDRV_DMA_TYPE_DEV:
                dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr);
                break;
+#endif
+#ifdef CONFIG_SND_DMA_SGBUF
        case SNDRV_DMA_TYPE_DEV_SG:
                snd_malloc_sgbuf_pages(device, size, dmab, NULL);
                break;
@@ -269,6 +271,8 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
        case SNDRV_DMA_TYPE_DEV:
                snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr);
                break;
+#endif
+#ifdef CONFIG_SND_DMA_SGBUF
        case SNDRV_DMA_TYPE_DEV_SG:
                snd_free_sgbuf_pages(dmab);
                break;
index a9710e0c97afe74e800660fe1697c9d100c18539..23a032c6d4873a53b6c95b06ef08f6523332bae4 100644 (file)
 #include <linux/ioport.h>
 #include <sound/core.h>
 
+#ifdef CONFIG_SND_DEBUG
+
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+#define DEFAULT_DEBUG_LEVEL    2
+#else
+#define DEFAULT_DEBUG_LEVEL    1
+#endif
+
+static int debug = DEFAULT_DEBUG_LEVEL;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0 = disable)");
+
+#endif /* CONFIG_SND_DEBUG */
+
 void release_and_free_resource(struct resource *res)
 {
        if (res) {
@@ -35,46 +49,53 @@ void release_and_free_resource(struct resource *res)
 EXPORT_SYMBOL(release_and_free_resource);
 
 #ifdef CONFIG_SND_VERBOSE_PRINTK
-void snd_verbose_printk(const char *file, int line, const char *format, ...)
+/* strip the leading path if the given path is absolute */
+static const char *sanity_file_name(const char *path)
 {
-       va_list args;
-       
-       if (format[0] == '<' && format[1] >= '0' && format[1] <= '7' && format[2] == '>') {
-               char tmp[] = "<0>";
+       if (*path == '/')
+               return strrchr(path, '/') + 1;
+       else
+               return path;
+}
+
+/* print file and line with a certain printk prefix */
+static int print_snd_pfx(unsigned int level, const char *path, int line,
+                        const char *format)
+{
+       const char *file = sanity_file_name(path);
+       char tmp[] = "<0>";
+       const char *pfx = level ? KERN_DEBUG : KERN_DEFAULT;
+       int ret = 0;
+
+       if (format[0] == '<' && format[2] == '>') {
                tmp[1] = format[1];
-               printk("%sALSA %s:%d: ", tmp, file, line);
-               format += 3;
-       } else {
-               printk("ALSA %s:%d: ", file, line);
+               pfx = tmp;
+               ret = 1;
        }
-       va_start(args, format);
-       vprintk(format, args);
-       va_end(args);
+       printk("%sALSA %s:%d: ", pfx, file, line);
+       return ret;
 }
-
-EXPORT_SYMBOL(snd_verbose_printk);
+#else
+#define print_snd_pfx(level, path, line, format)       0
 #endif
 
-#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK)
-void snd_verbose_printd(const char *file, int line, const char *format, ...)
+#if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK)
+void __snd_printk(unsigned int level, const char *path, int line,
+                 const char *format, ...)
 {
        va_list args;
        
-       if (format[0] == '<' && format[1] >= '0' && format[1] <= '7' && format[2] == '>') {
-               char tmp[] = "<0>";
-               tmp[1] = format[1];
-               printk("%sALSA %s:%d: ", tmp, file, line);
-               format += 3;
-       } else {
-               printk(KERN_DEBUG "ALSA %s:%d: ", file, line);
-       }
+#ifdef CONFIG_SND_DEBUG        
+       if (debug < level)
+               return;
+#endif
        va_start(args, format);
+       if (print_snd_pfx(level, path, line, format))
+               format += 3; /* skip the printk level-prefix */
        vprintk(format, args);
        va_end(args);
-
 }
-
-EXPORT_SYMBOL(snd_verbose_printd);
+EXPORT_SYMBOL_GPL(__snd_printk);
 #endif
 
 #ifdef CONFIG_PCI
index 5dcd8a526970002bb1113d6cd16f9c9b2cc30f27..772423889eb37e25d95a775d798979c5a46cfa33 100644 (file)
@@ -1154,7 +1154,8 @@ static void snd_mixer_oss_proc_write(struct snd_info_entry *entry,
                                     struct snd_info_buffer *buffer)
 {
        struct snd_mixer_oss *mixer = entry->private_data;
-       char line[128], str[32], idxstr[16], *cptr;
+       char line[128], str[32], idxstr[16];
+       const char *cptr;
        int ch, idx;
        struct snd_mixer_oss_assign_table *tbl;
        struct slot *slot;
index dbe406b82591058dd515686d8d13eb800418b416..d9c96353121a567b53f040dc1b87207aac40cac4 100644 (file)
@@ -1043,10 +1043,15 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
        runtime->oss.channels = params_channels(params);
        runtime->oss.rate = params_rate(params);
 
-       runtime->oss.params = 0;
-       runtime->oss.prepare = 1;
        vfree(runtime->oss.buffer);
        runtime->oss.buffer = vmalloc(runtime->oss.period_bytes);
+       if (!runtime->oss.buffer) {
+               err = -ENOMEM;
+               goto failure;
+       }
+
+       runtime->oss.params = 0;
+       runtime->oss.prepare = 1;
        runtime->oss.buffer_used = 0;
        if (runtime->dma_area)
                snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes));
@@ -2836,7 +2841,8 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
                                   struct snd_info_buffer *buffer)
 {
        struct snd_pcm_str *pstr = entry->private_data;
-       char line[128], str[32], task_name[32], *ptr;
+       char line[128], str[32], task_name[32];
+       const char *ptr;
        int idx1;
        struct snd_pcm_oss_setup *setup, *setup1, template;
 
index 145931a9ff302fa6b696a137b1036d8a125c540a..0c1440121c22c2f4ed8df37615c1241c17c5314e 100644 (file)
@@ -162,18 +162,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
        return -ENOIOCTLCMD;
 }
 
-#ifdef CONFIG_SND_VERBOSE_PROCFS
-
-#define STATE(v) [SNDRV_PCM_STATE_##v] = #v
-#define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v
-#define READY(v) [SNDRV_PCM_READY_##v] = #v
-#define XRUN(v) [SNDRV_PCM_XRUN_##v] = #v
-#define SILENCE(v) [SNDRV_PCM_SILENCE_##v] = #v
-#define TSTAMP(v) [SNDRV_PCM_TSTAMP_##v] = #v
-#define ACCESS(v) [SNDRV_PCM_ACCESS_##v] = #v
-#define START(v) [SNDRV_PCM_START_##v] = #v
 #define FORMAT(v) [SNDRV_PCM_FORMAT_##v] = #v
-#define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v 
 
 static char *snd_pcm_format_names[] = {
        FORMAT(S8),
@@ -216,10 +205,23 @@ static char *snd_pcm_format_names[] = {
        FORMAT(U18_3BE),
 };
 
-static const char *snd_pcm_format_name(snd_pcm_format_t format)
+const char *snd_pcm_format_name(snd_pcm_format_t format)
 {
        return snd_pcm_format_names[format];
 }
+EXPORT_SYMBOL_GPL(snd_pcm_format_name);
+
+#ifdef CONFIG_SND_VERBOSE_PROCFS
+
+#define STATE(v) [SNDRV_PCM_STATE_##v] = #v
+#define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v
+#define READY(v) [SNDRV_PCM_READY_##v] = #v
+#define XRUN(v) [SNDRV_PCM_XRUN_##v] = #v
+#define SILENCE(v) [SNDRV_PCM_SILENCE_##v] = #v
+#define TSTAMP(v) [SNDRV_PCM_TSTAMP_##v] = #v
+#define ACCESS(v) [SNDRV_PCM_ACCESS_##v] = #v
+#define START(v) [SNDRV_PCM_START_##v] = #v
+#define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v 
 
 static char *snd_pcm_stream_names[] = {
        STREAM(PLAYBACK),
index 333e4dd29450c7e9e823ebec46b7af4bcb6c62fc..30f410832a25991c44e2f71efcebb63abdb2b232 100644 (file)
@@ -197,12 +197,16 @@ static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
                avail = snd_pcm_capture_avail(runtime);
        if (avail > runtime->avail_max)
                runtime->avail_max = avail;
-       if (avail >= runtime->stop_threshold) {
-               if (substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+       if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
+               if (avail >= runtime->buffer_size) {
                        snd_pcm_drain_done(substream);
-               else
+                       return -EPIPE;
+               }
+       } else {
+               if (avail >= runtime->stop_threshold) {
                        xrun(substream);
-               return -EPIPE;
+                       return -EPIPE;
+               }
        }
        if (avail >= runtime->control->avail_min)
                wake_up(&runtime->sleep);
@@ -233,6 +237,18 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
                xrun(substream);
                return -EPIPE;
        }
+       if (xrun_debug(substream, 8)) {
+               char name[16];
+               pcm_debug_name(substream, name, sizeof(name));
+               snd_printd("period_update: %s: pos=0x%x/0x%x/0x%x, "
+                          "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
+                          name, (unsigned int)pos,
+                          (unsigned int)runtime->period_size,
+                          (unsigned int)runtime->buffer_size,
+                          (unsigned long)old_hw_ptr,
+                          (unsigned long)runtime->hw_ptr_base,
+                          (unsigned long)runtime->hw_ptr_interrupt);
+       }
        hw_base = runtime->hw_ptr_base;
        new_hw_ptr = hw_base + pos;
        hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size;
@@ -244,18 +260,27 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
                        delta = new_hw_ptr - hw_ptr_interrupt;
        }
        if (delta < 0) {
-               delta += runtime->buffer_size;
+               if (runtime->periods == 1 || new_hw_ptr < old_hw_ptr)
+                       delta += runtime->buffer_size;
                if (delta < 0) {
                        hw_ptr_error(substream, 
                                     "Unexpected hw_pointer value "
                                     "(stream=%i, pos=%ld, intr_ptr=%ld)\n",
                                     substream->stream, (long)pos,
                                     (long)hw_ptr_interrupt);
+#if 1
+                       /* simply skipping the hwptr update seems more
+                        * robust in some cases, e.g. on VMware with
+                        * inaccurate timer source
+                        */
+                       return 0; /* skip this update */
+#else
                        /* rebase to interrupt position */
                        hw_base = new_hw_ptr = hw_ptr_interrupt;
                        /* align hw_base to buffer_size */
                        hw_base -= hw_base % runtime->buffer_size;
                        delta = 0;
+#endif
                } else {
                        hw_base += runtime->buffer_size;
                        if (hw_base >= runtime->boundary)
@@ -344,6 +369,19 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
                xrun(substream);
                return -EPIPE;
        }
+       if (xrun_debug(substream, 16)) {
+               char name[16];
+               pcm_debug_name(substream, name, sizeof(name));
+               snd_printd("hw_update: %s: pos=0x%x/0x%x/0x%x, "
+                          "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
+                          name, (unsigned int)pos,
+                          (unsigned int)runtime->period_size,
+                          (unsigned int)runtime->buffer_size,
+                          (unsigned long)old_hw_ptr,
+                          (unsigned long)runtime->hw_ptr_base,
+                          (unsigned long)runtime->hw_ptr_interrupt);
+       }
+
        hw_base = runtime->hw_ptr_base;
        new_hw_ptr = hw_base + pos;
 
@@ -909,47 +947,24 @@ static int snd_interval_ratden(struct snd_interval *i,
 int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask)
 {
         unsigned int k;
-       int changed = 0;
+       struct snd_interval list_range;
 
        if (!count) {
                i->empty = 1;
                return -EINVAL;
        }
+       snd_interval_any(&list_range);
+       list_range.min = UINT_MAX;
+       list_range.max = 0;
         for (k = 0; k < count; k++) {
                if (mask && !(mask & (1 << k)))
                        continue;
-                if (i->min == list[k] && !i->openmin)
-                        goto _l1;
-                if (i->min < list[k]) {
-                        i->min = list[k];
-                       i->openmin = 0;
-                       changed = 1;
-                        goto _l1;
-                }
-        }
-        i->empty = 1;
-        return -EINVAL;
- _l1:
-        for (k = count; k-- > 0;) {
-               if (mask && !(mask & (1 << k)))
+               if (!snd_interval_test(i, list[k]))
                        continue;
-                if (i->max == list[k] && !i->openmax)
-                        goto _l2;
-                if (i->max > list[k]) {
-                        i->max = list[k];
-                       i->openmax = 0;
-                       changed = 1;
-                        goto _l2;
-                }
+               list_range.min = min(list_range.min, list[k]);
+               list_range.max = max(list_range.max, list[k]);
         }
-        i->empty = 1;
-        return -EINVAL;
- _l2:
-       if (snd_interval_checkempty(i)) {
-               i->empty = 1;
-               return -EINVAL;
-       }
-        return changed;
+       return snd_interval_refine(i, &list_range);
 }
 
 EXPORT_SYMBOL(snd_interval_list);
index a6d42808828c7d87d233f61782e753c7e99ba646..caa7796bc2f513e2bb2a73c1c26a8c866856894b 100644 (file)
@@ -304,6 +304,7 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm,
 
 EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
 
+#ifdef CONFIG_SND_DMA_SGBUF
 /**
  * snd_pcm_sgbuf_ops_page - get the page struct at the given offset
  * @substream: the pcm substream instance
@@ -349,6 +350,7 @@ unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream,
        return size;
 }
 EXPORT_SYMBOL(snd_pcm_sgbuf_get_chunk_size);
+#endif /* CONFIG_SND_DMA_SGBUF */
 
 /**
  * snd_pcm_lib_malloc_pages - allocate the DMA buffer
index ac2150e0670d8541e4023fb21fdb600e4bef6df8..561d6d95a2d33fef48b98ccfc29c32571cb9dddd 100644 (file)
@@ -1343,8 +1343,6 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
 
 static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
 {
-       if (substream->f_flags & O_NONBLOCK)
-               return -EAGAIN;
        substream->runtime->trigger_master = substream;
        return 0;
 }
@@ -1389,12 +1387,6 @@ static struct action_ops snd_pcm_action_drain_init = {
        .post_action = snd_pcm_post_drain_init
 };
 
-struct drain_rec {
-       struct snd_pcm_substream *substream;
-       wait_queue_t wait;
-       snd_pcm_uframes_t stop_threshold;
-};
-
 static int snd_pcm_drop(struct snd_pcm_substream *substream);
 
 /*
@@ -1404,14 +1396,15 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream);
  * After this call, all streams are supposed to be either SETUP or DRAINING
  * (capture only) state.
  */
-static int snd_pcm_drain(struct snd_pcm_substream *substream)
+static int snd_pcm_drain(struct snd_pcm_substream *substream,
+                        struct file *file)
 {
        struct snd_card *card;
        struct snd_pcm_runtime *runtime;
        struct snd_pcm_substream *s;
+       wait_queue_t wait;
        int result = 0;
-       int i, num_drecs;
-       struct drain_rec *drec, drec_tmp, *d;
+       int nonblock = 0;
 
        card = substream->pcm->card;
        runtime = substream->runtime;
@@ -1428,70 +1421,59 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
                }
        }
 
-       /* allocate temporary record for drain sync */
-       down_read(&snd_pcm_link_rwsem);
-       if (snd_pcm_stream_linked(substream)) {
-               drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL);
-               if (! drec) {
-                       up_read(&snd_pcm_link_rwsem);
-                       snd_power_unlock(card);
-                       return -ENOMEM;
-               }
-       } else
-               drec = &drec_tmp;
-
-       /* count only playback streams */
-       num_drecs = 0;
-       snd_pcm_group_for_each_entry(s, substream) {
-               runtime = s->runtime;
-               if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-                       d = &drec[num_drecs++];
-                       d->substream = s;
-                       init_waitqueue_entry(&d->wait, current);
-                       add_wait_queue(&runtime->sleep, &d->wait);
-                       /* stop_threshold fixup to avoid endless loop when
-                        * stop_threshold > buffer_size
-                        */
-                       d->stop_threshold = runtime->stop_threshold;
-                       if (runtime->stop_threshold > runtime->buffer_size)
-                               runtime->stop_threshold = runtime->buffer_size;
-               }
-       }
-       up_read(&snd_pcm_link_rwsem);
+       if (file) {
+               if (file->f_flags & O_NONBLOCK)
+                       nonblock = 1;
+       } else if (substream->f_flags & O_NONBLOCK)
+               nonblock = 1;
 
+       down_read(&snd_pcm_link_rwsem);
        snd_pcm_stream_lock_irq(substream);
        /* resume pause */
-       if (substream->runtime->status->state == SNDRV_PCM_STATE_PAUSED)
+       if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
                snd_pcm_pause(substream, 0);
 
        /* pre-start/stop - all running streams are changed to DRAINING state */
        result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
-       if (result < 0) {
-               snd_pcm_stream_unlock_irq(substream);
-               goto _error;
+       if (result < 0)
+               goto unlock;
+       /* in non-blocking, we don't wait in ioctl but let caller poll */
+       if (nonblock) {
+               result = -EAGAIN;
+               goto unlock;
        }
 
        for (;;) {
                long tout;
+               struct snd_pcm_runtime *to_check;
                if (signal_pending(current)) {
                        result = -ERESTARTSYS;
                        break;
                }
-               /* all finished? */
-               for (i = 0; i < num_drecs; i++) {
-                       runtime = drec[i].substream->runtime;
-                       if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+               /* find a substream to drain */
+               to_check = NULL;
+               snd_pcm_group_for_each_entry(s, substream) {
+                       if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
+                               continue;
+                       runtime = s->runtime;
+                       if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
+                               to_check = runtime;
                                break;
+                       }
                }
-               if (i == num_drecs)
-                       break; /* yes, all drained */
-
+               if (!to_check)
+                       break; /* all drained */
+               init_waitqueue_entry(&wait, current);
+               add_wait_queue(&to_check->sleep, &wait);
                set_current_state(TASK_INTERRUPTIBLE);
                snd_pcm_stream_unlock_irq(substream);
+               up_read(&snd_pcm_link_rwsem);
                snd_power_unlock(card);
                tout = schedule_timeout(10 * HZ);
                snd_power_lock(card);
+               down_read(&snd_pcm_link_rwsem);
                snd_pcm_stream_lock_irq(substream);
+               remove_wait_queue(&to_check->sleep, &wait);
                if (tout == 0) {
                        if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
                                result = -ESTRPIPE;
@@ -1504,18 +1486,9 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
                }
        }
 
+ unlock:
        snd_pcm_stream_unlock_irq(substream);
-
- _error:
-       for (i = 0; i < num_drecs; i++) {
-               d = &drec[i];
-               runtime = d->substream->runtime;
-               remove_wait_queue(&runtime->sleep, &d->wait);
-               runtime->stop_threshold = d->stop_threshold;
-       }
-
-       if (drec != &drec_tmp)
-               kfree(drec);
+       up_read(&snd_pcm_link_rwsem);
        snd_power_unlock(card);
 
        return result;
@@ -2208,6 +2181,9 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst
        case SNDRV_PCM_STATE_XRUN:
                ret = -EPIPE;
                goto __end;
+       case SNDRV_PCM_STATE_SUSPENDED:
+               ret = -ESTRPIPE;
+               goto __end;
        default:
                ret = -EBADFD;
                goto __end;
@@ -2253,6 +2229,9 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr
        case SNDRV_PCM_STATE_XRUN:
                ret = -EPIPE;
                goto __end;
+       case SNDRV_PCM_STATE_SUSPENDED:
+               ret = -ESTRPIPE;
+               goto __end;
        default:
                ret = -EBADFD;
                goto __end;
@@ -2299,6 +2278,9 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs
        case SNDRV_PCM_STATE_XRUN:
                ret = -EPIPE;
                goto __end;
+       case SNDRV_PCM_STATE_SUSPENDED:
+               ret = -ESTRPIPE;
+               goto __end;
        default:
                ret = -EBADFD;
                goto __end;
@@ -2345,6 +2327,9 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst
        case SNDRV_PCM_STATE_XRUN:
                ret = -EPIPE;
                goto __end;
+       case SNDRV_PCM_STATE_SUSPENDED:
+               ret = -ESTRPIPE;
+               goto __end;
        default:
                ret = -EBADFD;
                goto __end;
@@ -2544,7 +2529,7 @@ static int snd_pcm_common_ioctl1(struct file *file,
                return snd_pcm_hw_params_old_user(substream, arg);
 #endif
        case SNDRV_PCM_IOCTL_DRAIN:
-               return snd_pcm_drain(substream);
+               return snd_pcm_drain(substream, file);
        case SNDRV_PCM_IOCTL_DROP:
                return snd_pcm_drop(substream);
        case SNDRV_PCM_IOCTL_PAUSE:
index 473247c8e6d3e22c2e3466e80443e6e6e3054680..c0adc14c91f0ad31b2f42084c794d7f1a70957a5 100644 (file)
@@ -274,7 +274,7 @@ static int open_substream(struct snd_rawmidi *rmidi,
                return err;
        substream->opened = 1;
        if (substream->use_count++ == 0)
-               substream->active_sensing = 1;
+               substream->active_sensing = 0;
        if (mode & SNDRV_RAWMIDI_LFLG_APPEND)
                substream->append = 1;
        rmidi->streams[substream->stream].substream_opened++;
index 1bcb360330e521f37b82bca91452b7cbc0db8803..941f64a853ebea266d24141af7c4dc71a053165a 100644 (file)
@@ -3,10 +3,6 @@
 # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz>
 #
 
-ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
-  obj-$(CONFIG_SND_SEQUENCER) += oss/
-endif
-
 snd-seq-device-objs := seq_device.o
 snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \
                 seq_fifo.o seq_prioq.o seq_timer.o \
@@ -19,7 +15,8 @@ snd-seq-virmidi-objs := seq_virmidi.o
 
 obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o
 ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
-obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o
+  obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o
+  obj-$(CONFIG_SND_SEQUENCER) += oss/
 endif
 obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o
 
index 0a711d2d04f0f3736572844698b8bc0ff389b384..9dfb2f77be608368ff897c948742dbf806fa52cd 100644 (file)
@@ -20,6 +20,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#include <sound/asoundef.h>
 #include "seq_oss_midi.h"
 #include "seq_oss_readq.h"
 #include "seq_oss_timer.h"
@@ -476,19 +477,20 @@ snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev)
                ev.source.port = dp->port;
                if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_SYNTH) {
                        ev.type = SNDRV_SEQ_EVENT_SENSING;
-                       snd_seq_oss_dispatch(dp, &ev, 0, 0); /* active sensing */
+                       snd_seq_oss_dispatch(dp, &ev, 0, 0);
                }
                for (c = 0; c < 16; c++) {
                        ev.type = SNDRV_SEQ_EVENT_CONTROLLER;
                        ev.data.control.channel = c;
-                       ev.data.control.param = 123;
-                       snd_seq_oss_dispatch(dp, &ev, 0, 0); /* all notes off */
+                       ev.data.control.param = MIDI_CTL_ALL_NOTES_OFF;
+                       snd_seq_oss_dispatch(dp, &ev, 0, 0);
                        if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) {
-                               ev.data.control.param = 121;
-                               snd_seq_oss_dispatch(dp, &ev, 0, 0); /* reset all controllers */
+                               ev.data.control.param =
+                                       MIDI_CTL_RESET_CONTROLLERS;
+                               snd_seq_oss_dispatch(dp, &ev, 0, 0);
                                ev.type = SNDRV_SEQ_EVENT_PITCHBEND;
                                ev.data.control.value = 0;
-                               snd_seq_oss_dispatch(dp, &ev, 0, 0); /* bender off */
+                               snd_seq_oss_dispatch(dp, &ev, 0, 0);
                        }
                }
        }
index 4d26146a62ccd8fd2fff0c73ea25507ff4a6550f..ebaf1b541dcda7e2ccc39bc62416342cde6f8ead 100644 (file)
@@ -120,7 +120,8 @@ static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, i
                return -EINVAL;
        runtime = substream->runtime;
        if ((tmp = runtime->avail) < count) {
-               snd_printd("warning, output event was lost (count = %i, available = %i)\n", count, tmp);
+               if (printk_ratelimit())
+                       snd_printk(KERN_ERR "MIDI output buffer overrun\n");
                return -ENOMEM;
        }
        if (snd_rawmidi_kernel_write(substream, buf, count) < count)
@@ -236,6 +237,7 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
        memset(&params, 0, sizeof(params));
        params.avail_min = 1;
        params.buffer_size = output_buffer_size;
+       params.no_active_sensing = 1;
        if ((err = snd_rawmidi_output_params(msynth->output_rfile.output, &params)) < 0) {
                snd_rawmidi_kernel_release(&msynth->output_rfile);
                return err;
@@ -248,12 +250,9 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
 static int midisynth_unuse(void *private_data, struct snd_seq_port_subscribe *info)
 {
        struct seq_midisynth *msynth = private_data;
-       unsigned char buf = 0xff; /* MIDI reset */
 
        if (snd_BUG_ON(!msynth->output_rfile.output))
                return -EINVAL;
-       /* sending single MIDI reset message to shut the device up */
-       snd_rawmidi_kernel_write(msynth->output_rfile.output, &buf, 1);
        snd_rawmidi_drain_output(msynth->output_rfile.output);
        return snd_rawmidi_kernel_release(&msynth->output_rfile);
 }
index 257624bd199776c37ecc01815fd377e3150ac3ec..3b9b550109cb9fe4e59b60db5ee436546029867c 100644 (file)
@@ -353,7 +353,8 @@ static void master_free(struct snd_kcontrol *kcontrol)
  *
  * The optional argument @tlv can be used to specify the TLV information
  * for dB scale of the master control.  It should be a single element
- * with #SNDRV_CTL_TLVT_DB_SCALE type, and should be the max 0dB.
+ * with #SNDRV_CTL_TLVT_DB_SCALE, #SNDRV_CTL_TLV_DB_MINMAX or
+ * #SNDRV_CTL_TLVT_DB_MINMAX_MUTE type, and should be the max 0dB.
  */
 struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
                                                 const unsigned int *tlv)
@@ -384,7 +385,10 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
        kctl->private_free = master_free;
 
        /* additional (constant) TLV read */
-       if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) {
+       if (tlv &&
+           (tlv[0] == SNDRV_CTL_TLVT_DB_SCALE ||
+            tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX ||
+            tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX_MUTE)) {
                kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
                memcpy(master->tlv, tlv, sizeof(master->tlv));
                kctl->tlv.p = master->tlv;
index 54239d2e0997b7ac88e2e6c2e3898afc79a7c0f9..6ba066c41d2e9bd5ab8d7c8e6f1eba438bda62af 100644 (file)
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/wait.h>
+#include <linux/hrtimer.h>
+#include <linux/math64.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/tlv.h>
 #include <sound/pcm.h>
 #include <sound/rawmidi.h>
+#include <sound/info.h>
 #include <sound/initval.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
@@ -39,7 +42,7 @@ MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}");
 
 #define MAX_PCM_DEVICES                4
-#define MAX_PCM_SUBSTREAMS     16
+#define MAX_PCM_SUBSTREAMS     128
 #define MAX_MIDI_DEVICES       2
 
 #if 0 /* emu10k1 emulation */
@@ -148,6 +151,10 @@ static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
 static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
 static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8};
 //static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
+#ifdef CONFIG_HIGH_RES_TIMERS
+static int hrtimer = 1;
+#endif
+static int fake_buffer = 1;
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for dummy soundcard.");
@@ -161,6 +168,12 @@ module_param_array(pcm_substreams, int, NULL, 0444);
 MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-16) for dummy driver.");
 //module_param_array(midi_devs, int, NULL, 0444);
 //MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver.");
+module_param(fake_buffer, bool, 0444);
+MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations.");
+#ifdef CONFIG_HIGH_RES_TIMERS
+module_param(hrtimer, bool, 0644);
+MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source.");
+#endif
 
 static struct platform_device *devices[SNDRV_CARDS];
 
@@ -171,137 +184,324 @@ static struct platform_device *devices[SNDRV_CARDS];
 #define MIXER_ADDR_CD          4
 #define MIXER_ADDR_LAST                4
 
+struct dummy_timer_ops {
+       int (*create)(struct snd_pcm_substream *);
+       void (*free)(struct snd_pcm_substream *);
+       int (*prepare)(struct snd_pcm_substream *);
+       int (*start)(struct snd_pcm_substream *);
+       int (*stop)(struct snd_pcm_substream *);
+       snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *);
+};
+
 struct snd_dummy {
        struct snd_card *card;
        struct snd_pcm *pcm;
        spinlock_t mixer_lock;
        int mixer_volume[MIXER_ADDR_LAST+1][2];
        int capture_source[MIXER_ADDR_LAST+1][2];
+       const struct dummy_timer_ops *timer_ops;
 };
 
-struct snd_dummy_pcm {
-       struct snd_dummy *dummy;
+/*
+ * system timer interface
+ */
+
+struct dummy_systimer_pcm {
        spinlock_t lock;
        struct timer_list timer;
-       unsigned int pcm_buffer_size;
-       unsigned int pcm_period_size;
-       unsigned int pcm_bps;           /* bytes per second */
-       unsigned int pcm_hz;            /* HZ */
-       unsigned int pcm_irq_pos;       /* IRQ position */
-       unsigned int pcm_buf_pos;       /* position in buffer */
+       unsigned long base_time;
+       unsigned int frac_pos;  /* fractional sample position (based HZ) */
+       unsigned int frac_period_rest;
+       unsigned int frac_buffer_size;  /* buffer_size * HZ */
+       unsigned int frac_period_size;  /* period_size * HZ */
+       unsigned int rate;
+       int elapsed;
        struct snd_pcm_substream *substream;
 };
 
-
-static inline void snd_card_dummy_pcm_timer_start(struct snd_dummy_pcm *dpcm)
+static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm)
 {
-       dpcm->timer.expires = 1 + jiffies;
+       dpcm->timer.expires = jiffies +
+               (dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate;
        add_timer(&dpcm->timer);
 }
 
-static inline void snd_card_dummy_pcm_timer_stop(struct snd_dummy_pcm *dpcm)
+static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm)
 {
-       del_timer(&dpcm->timer);
+       unsigned long delta;
+
+       delta = jiffies - dpcm->base_time;
+       if (!delta)
+               return;
+       dpcm->base_time += delta;
+       delta *= dpcm->rate;
+       dpcm->frac_pos += delta;
+       while (dpcm->frac_pos >= dpcm->frac_buffer_size)
+               dpcm->frac_pos -= dpcm->frac_buffer_size;
+       while (dpcm->frac_period_rest <= delta) {
+               dpcm->elapsed++;
+               dpcm->frac_period_rest += dpcm->frac_period_size;
+       }
+       dpcm->frac_period_rest -= delta;
 }
 
-static int snd_card_dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+static int dummy_systimer_start(struct snd_pcm_substream *substream)
 {
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct snd_dummy_pcm *dpcm = runtime->private_data;
-       int err = 0;
+       struct dummy_systimer_pcm *dpcm = substream->runtime->private_data;
+       spin_lock(&dpcm->lock);
+       dpcm->base_time = jiffies;
+       dummy_systimer_rearm(dpcm);
+       spin_unlock(&dpcm->lock);
+       return 0;
+}
 
+static int dummy_systimer_stop(struct snd_pcm_substream *substream)
+{
+       struct dummy_systimer_pcm *dpcm = substream->runtime->private_data;
        spin_lock(&dpcm->lock);
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_RESUME:
-               snd_card_dummy_pcm_timer_start(dpcm);
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-               snd_card_dummy_pcm_timer_stop(dpcm);
-               break;
-       default:
-               err = -EINVAL;
-               break;
-       }
+       del_timer(&dpcm->timer);
        spin_unlock(&dpcm->lock);
        return 0;
 }
 
-static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream)
+static int dummy_systimer_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
-       struct snd_dummy_pcm *dpcm = runtime->private_data;
-       int bps;
-
-       bps = snd_pcm_format_width(runtime->format) * runtime->rate *
-               runtime->channels / 8;
-
-       if (bps <= 0)
-               return -EINVAL;
-
-       dpcm->pcm_bps = bps;
-       dpcm->pcm_hz = HZ;
-       dpcm->pcm_buffer_size = snd_pcm_lib_buffer_bytes(substream);
-       dpcm->pcm_period_size = snd_pcm_lib_period_bytes(substream);
-       dpcm->pcm_irq_pos = 0;
-       dpcm->pcm_buf_pos = 0;
+       struct dummy_systimer_pcm *dpcm = runtime->private_data;
 
-       snd_pcm_format_set_silence(runtime->format, runtime->dma_area,
-                       bytes_to_samples(runtime, runtime->dma_bytes));
+       dpcm->frac_pos = 0;
+       dpcm->rate = runtime->rate;
+       dpcm->frac_buffer_size = runtime->buffer_size * HZ;
+       dpcm->frac_period_size = runtime->period_size * HZ;
+       dpcm->frac_period_rest = dpcm->frac_period_size;
+       dpcm->elapsed = 0;
 
        return 0;
 }
 
-static void snd_card_dummy_pcm_timer_function(unsigned long data)
+static void dummy_systimer_callback(unsigned long data)
 {
-       struct snd_dummy_pcm *dpcm = (struct snd_dummy_pcm *)data;
+       struct dummy_systimer_pcm *dpcm = (struct dummy_systimer_pcm *)data;
        unsigned long flags;
+       int elapsed = 0;
        
        spin_lock_irqsave(&dpcm->lock, flags);
-       dpcm->timer.expires = 1 + jiffies;
-       add_timer(&dpcm->timer);
-       dpcm->pcm_irq_pos += dpcm->pcm_bps;
-       dpcm->pcm_buf_pos += dpcm->pcm_bps;
-       dpcm->pcm_buf_pos %= dpcm->pcm_buffer_size * dpcm->pcm_hz;
-       if (dpcm->pcm_irq_pos >= dpcm->pcm_period_size * dpcm->pcm_hz) {
-               dpcm->pcm_irq_pos %= dpcm->pcm_period_size * dpcm->pcm_hz;
-               spin_unlock_irqrestore(&dpcm->lock, flags);
+       dummy_systimer_update(dpcm);
+       dummy_systimer_rearm(dpcm);
+       elapsed = dpcm->elapsed;
+       dpcm->elapsed = 0;
+       spin_unlock_irqrestore(&dpcm->lock, flags);
+       if (elapsed)
+               snd_pcm_period_elapsed(dpcm->substream);
+}
+
+static snd_pcm_uframes_t
+dummy_systimer_pointer(struct snd_pcm_substream *substream)
+{
+       struct dummy_systimer_pcm *dpcm = substream->runtime->private_data;
+       snd_pcm_uframes_t pos;
+
+       spin_lock(&dpcm->lock);
+       dummy_systimer_update(dpcm);
+       pos = dpcm->frac_pos / HZ;
+       spin_unlock(&dpcm->lock);
+       return pos;
+}
+
+static int dummy_systimer_create(struct snd_pcm_substream *substream)
+{
+       struct dummy_systimer_pcm *dpcm;
+
+       dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
+       if (!dpcm)
+               return -ENOMEM;
+       substream->runtime->private_data = dpcm;
+       init_timer(&dpcm->timer);
+       dpcm->timer.data = (unsigned long) dpcm;
+       dpcm->timer.function = dummy_systimer_callback;
+       spin_lock_init(&dpcm->lock);
+       dpcm->substream = substream;
+       return 0;
+}
+
+static void dummy_systimer_free(struct snd_pcm_substream *substream)
+{
+       kfree(substream->runtime->private_data);
+}
+
+static struct dummy_timer_ops dummy_systimer_ops = {
+       .create =       dummy_systimer_create,
+       .free =         dummy_systimer_free,
+       .prepare =      dummy_systimer_prepare,
+       .start =        dummy_systimer_start,
+       .stop =         dummy_systimer_stop,
+       .pointer =      dummy_systimer_pointer,
+};
+
+#ifdef CONFIG_HIGH_RES_TIMERS
+/*
+ * hrtimer interface
+ */
+
+struct dummy_hrtimer_pcm {
+       ktime_t base_time;
+       ktime_t period_time;
+       atomic_t running;
+       struct hrtimer timer;
+       struct tasklet_struct tasklet;
+       struct snd_pcm_substream *substream;
+};
+
+static void dummy_hrtimer_pcm_elapsed(unsigned long priv)
+{
+       struct dummy_hrtimer_pcm *dpcm = (struct dummy_hrtimer_pcm *)priv;
+       if (atomic_read(&dpcm->running))
                snd_pcm_period_elapsed(dpcm->substream);
-       } else
-               spin_unlock_irqrestore(&dpcm->lock, flags);
 }
 
-static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *substream)
+static enum hrtimer_restart dummy_hrtimer_callback(struct hrtimer *timer)
+{
+       struct dummy_hrtimer_pcm *dpcm;
+
+       dpcm = container_of(timer, struct dummy_hrtimer_pcm, timer);
+       if (!atomic_read(&dpcm->running))
+               return HRTIMER_NORESTART;
+       tasklet_schedule(&dpcm->tasklet);
+       hrtimer_forward_now(timer, dpcm->period_time);
+       return HRTIMER_RESTART;
+}
+
+static int dummy_hrtimer_start(struct snd_pcm_substream *substream)
+{
+       struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data;
+
+       dpcm->base_time = hrtimer_cb_get_time(&dpcm->timer);
+       hrtimer_start(&dpcm->timer, dpcm->period_time, HRTIMER_MODE_REL);
+       atomic_set(&dpcm->running, 1);
+       return 0;
+}
+
+static int dummy_hrtimer_stop(struct snd_pcm_substream *substream)
+{
+       struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data;
+
+       atomic_set(&dpcm->running, 0);
+       hrtimer_cancel(&dpcm->timer);
+       return 0;
+}
+
+static inline void dummy_hrtimer_sync(struct dummy_hrtimer_pcm *dpcm)
+{
+       tasklet_kill(&dpcm->tasklet);
+}
+
+static snd_pcm_uframes_t
+dummy_hrtimer_pointer(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
-       struct snd_dummy_pcm *dpcm = runtime->private_data;
+       struct dummy_hrtimer_pcm *dpcm = runtime->private_data;
+       u64 delta;
+       u32 pos;
+
+       delta = ktime_us_delta(hrtimer_cb_get_time(&dpcm->timer),
+                              dpcm->base_time);
+       delta = div_u64(delta * runtime->rate + 999999, 1000000);
+       div_u64_rem(delta, runtime->buffer_size, &pos);
+       return pos;
+}
 
-       return bytes_to_frames(runtime, dpcm->pcm_buf_pos / dpcm->pcm_hz);
+static int dummy_hrtimer_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct dummy_hrtimer_pcm *dpcm = runtime->private_data;
+       unsigned int period, rate;
+       long sec;
+       unsigned long nsecs;
+
+       dummy_hrtimer_sync(dpcm);
+       period = runtime->period_size;
+       rate = runtime->rate;
+       sec = period / rate;
+       period %= rate;
+       nsecs = div_u64((u64)period * 1000000000UL + rate - 1, rate);
+       dpcm->period_time = ktime_set(sec, nsecs);
+
+       return 0;
 }
 
-static struct snd_pcm_hardware snd_card_dummy_playback =
+static int dummy_hrtimer_create(struct snd_pcm_substream *substream)
 {
-       .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-                                SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
-       .formats =              USE_FORMATS,
-       .rates =                USE_RATE,
-       .rate_min =             USE_RATE_MIN,
-       .rate_max =             USE_RATE_MAX,
-       .channels_min =         USE_CHANNELS_MIN,
-       .channels_max =         USE_CHANNELS_MAX,
-       .buffer_bytes_max =     MAX_BUFFER_SIZE,
-       .period_bytes_min =     64,
-       .period_bytes_max =     MAX_PERIOD_SIZE,
-       .periods_min =          USE_PERIODS_MIN,
-       .periods_max =          USE_PERIODS_MAX,
-       .fifo_size =            0,
+       struct dummy_hrtimer_pcm *dpcm;
+
+       dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
+       if (!dpcm)
+               return -ENOMEM;
+       substream->runtime->private_data = dpcm;
+       hrtimer_init(&dpcm->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       dpcm->timer.function = dummy_hrtimer_callback;
+       dpcm->substream = substream;
+       atomic_set(&dpcm->running, 0);
+       tasklet_init(&dpcm->tasklet, dummy_hrtimer_pcm_elapsed,
+                    (unsigned long)dpcm);
+       return 0;
+}
+
+static void dummy_hrtimer_free(struct snd_pcm_substream *substream)
+{
+       struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data;
+       dummy_hrtimer_sync(dpcm);
+       kfree(dpcm);
+}
+
+static struct dummy_timer_ops dummy_hrtimer_ops = {
+       .create =       dummy_hrtimer_create,
+       .free =         dummy_hrtimer_free,
+       .prepare =      dummy_hrtimer_prepare,
+       .start =        dummy_hrtimer_start,
+       .stop =         dummy_hrtimer_stop,
+       .pointer =      dummy_hrtimer_pointer,
 };
 
-static struct snd_pcm_hardware snd_card_dummy_capture =
+#endif /* CONFIG_HIGH_RES_TIMERS */
+
+/*
+ * PCM interface
+ */
+
+static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
-       .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-                                SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID),
+       struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+               return dummy->timer_ops->start(substream);
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               return dummy->timer_ops->stop(substream);
+       }
+       return -EINVAL;
+}
+
+static int dummy_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+
+       return dummy->timer_ops->prepare(substream);
+}
+
+static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+
+       return dummy->timer_ops->pointer(substream);
+}
+
+static struct snd_pcm_hardware dummy_pcm_hardware = {
+       .info =                 (SNDRV_PCM_INFO_MMAP |
+                                SNDRV_PCM_INFO_INTERLEAVED |
+                                SNDRV_PCM_INFO_RESUME |
+                                SNDRV_PCM_INFO_MMAP_VALID),
        .formats =              USE_FORMATS,
        .rates =                USE_RATE,
        .rate_min =             USE_RATE_MIN,
@@ -316,123 +516,152 @@ static struct snd_pcm_hardware snd_card_dummy_capture =
        .fifo_size =            0,
 };
 
-static void snd_card_dummy_runtime_free(struct snd_pcm_runtime *runtime)
-{
-       kfree(runtime->private_data);
-}
-
-static int snd_card_dummy_hw_params(struct snd_pcm_substream *substream,
-                                   struct snd_pcm_hw_params *hw_params)
+static int dummy_pcm_hw_params(struct snd_pcm_substream *substream,
+                              struct snd_pcm_hw_params *hw_params)
 {
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+       if (fake_buffer) {
+               /* runtime->dma_bytes has to be set manually to allow mmap */
+               substream->runtime->dma_bytes = params_buffer_bytes(hw_params);
+               return 0;
+       }
+       return snd_pcm_lib_malloc_pages(substream,
+                                       params_buffer_bytes(hw_params));
 }
 
-static int snd_card_dummy_hw_free(struct snd_pcm_substream *substream)
+static int dummy_pcm_hw_free(struct snd_pcm_substream *substream)
 {
+       if (fake_buffer)
+               return 0;
        return snd_pcm_lib_free_pages(substream);
 }
 
-static struct snd_dummy_pcm *new_pcm_stream(struct snd_pcm_substream *substream)
-{
-       struct snd_dummy_pcm *dpcm;
-
-       dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
-       if (! dpcm)
-               return dpcm;
-       init_timer(&dpcm->timer);
-       dpcm->timer.data = (unsigned long) dpcm;
-       dpcm->timer.function = snd_card_dummy_pcm_timer_function;
-       spin_lock_init(&dpcm->lock);
-       dpcm->substream = substream;
-       return dpcm;
-}
-
-static int snd_card_dummy_playback_open(struct snd_pcm_substream *substream)
+static int dummy_pcm_open(struct snd_pcm_substream *substream)
 {
+       struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
-       struct snd_dummy_pcm *dpcm;
        int err;
 
-       if ((dpcm = new_pcm_stream(substream)) == NULL)
-               return -ENOMEM;
-       runtime->private_data = dpcm;
-       /* makes the infrastructure responsible for freeing dpcm */
-       runtime->private_free = snd_card_dummy_runtime_free;
-       runtime->hw = snd_card_dummy_playback;
+       dummy->timer_ops = &dummy_systimer_ops;
+#ifdef CONFIG_HIGH_RES_TIMERS
+       if (hrtimer)
+               dummy->timer_ops = &dummy_hrtimer_ops;
+#endif
+
+       err = dummy->timer_ops->create(substream);
+       if (err < 0)
+               return err;
+
+       runtime->hw = dummy_pcm_hardware;
        if (substream->pcm->device & 1) {
                runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
                runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
        }
        if (substream->pcm->device & 2)
-               runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID);
-       err = add_playback_constraints(runtime);
-       if (err < 0)
+               runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP |
+                                     SNDRV_PCM_INFO_MMAP_VALID);
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               err = add_playback_constraints(substream->runtime);
+       else
+               err = add_capture_constraints(substream->runtime);
+       if (err < 0) {
+               dummy->timer_ops->free(substream);
                return err;
-
+       }
        return 0;
 }
 
-static int snd_card_dummy_capture_open(struct snd_pcm_substream *substream)
+static int dummy_pcm_close(struct snd_pcm_substream *substream)
 {
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct snd_dummy_pcm *dpcm;
-       int err;
+       struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+       dummy->timer_ops->free(substream);
+       return 0;
+}
 
-       if ((dpcm = new_pcm_stream(substream)) == NULL)
-               return -ENOMEM;
-       runtime->private_data = dpcm;
-       /* makes the infrastructure responsible for freeing dpcm */
-       runtime->private_free = snd_card_dummy_runtime_free;
-       runtime->hw = snd_card_dummy_capture;
-       if (substream->pcm->device == 1) {
-               runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
-               runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
+/*
+ * dummy buffer handling
+ */
+
+static void *dummy_page[2];
+
+static void free_fake_buffer(void)
+{
+       if (fake_buffer) {
+               int i;
+               for (i = 0; i < 2; i++)
+                       if (dummy_page[i]) {
+                               free_page((unsigned long)dummy_page[i]);
+                               dummy_page[i] = NULL;
+                       }
        }
-       if (substream->pcm->device & 2)
-               runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID);
-       err = add_capture_constraints(runtime);
-       if (err < 0)
-               return err;
+}
 
+static int alloc_fake_buffer(void)
+{
+       int i;
+
+       if (!fake_buffer)
+               return 0;
+       for (i = 0; i < 2; i++) {
+               dummy_page[i] = (void *)get_zeroed_page(GFP_KERNEL);
+               if (!dummy_page[i]) {
+                       free_fake_buffer();
+                       return -ENOMEM;
+               }
+       }
        return 0;
 }
 
-static int snd_card_dummy_playback_close(struct snd_pcm_substream *substream)
+static int dummy_pcm_copy(struct snd_pcm_substream *substream,
+                         int channel, snd_pcm_uframes_t pos,
+                         void __user *dst, snd_pcm_uframes_t count)
 {
-       return 0;
+       return 0; /* do nothing */
 }
 
-static int snd_card_dummy_capture_close(struct snd_pcm_substream *substream)
+static int dummy_pcm_silence(struct snd_pcm_substream *substream,
+                            int channel, snd_pcm_uframes_t pos,
+                            snd_pcm_uframes_t count)
 {
-       return 0;
+       return 0; /* do nothing */
+}
+
+static struct page *dummy_pcm_page(struct snd_pcm_substream *substream,
+                                  unsigned long offset)
+{
+       return virt_to_page(dummy_page[substream->stream]); /* the same page */
 }
 
-static struct snd_pcm_ops snd_card_dummy_playback_ops = {
-       .open =                 snd_card_dummy_playback_open,
-       .close =                snd_card_dummy_playback_close,
-       .ioctl =                snd_pcm_lib_ioctl,
-       .hw_params =            snd_card_dummy_hw_params,
-       .hw_free =              snd_card_dummy_hw_free,
-       .prepare =              snd_card_dummy_pcm_prepare,
-       .trigger =              snd_card_dummy_pcm_trigger,
-       .pointer =              snd_card_dummy_pcm_pointer,
+static struct snd_pcm_ops dummy_pcm_ops = {
+       .open =         dummy_pcm_open,
+       .close =        dummy_pcm_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    dummy_pcm_hw_params,
+       .hw_free =      dummy_pcm_hw_free,
+       .prepare =      dummy_pcm_prepare,
+       .trigger =      dummy_pcm_trigger,
+       .pointer =      dummy_pcm_pointer,
 };
 
-static struct snd_pcm_ops snd_card_dummy_capture_ops = {
-       .open =                 snd_card_dummy_capture_open,
-       .close =                snd_card_dummy_capture_close,
-       .ioctl =                snd_pcm_lib_ioctl,
-       .hw_params =            snd_card_dummy_hw_params,
-       .hw_free =              snd_card_dummy_hw_free,
-       .prepare =              snd_card_dummy_pcm_prepare,
-       .trigger =              snd_card_dummy_pcm_trigger,
-       .pointer =              snd_card_dummy_pcm_pointer,
+static struct snd_pcm_ops dummy_pcm_ops_no_buf = {
+       .open =         dummy_pcm_open,
+       .close =        dummy_pcm_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    dummy_pcm_hw_params,
+       .hw_free =      dummy_pcm_hw_free,
+       .prepare =      dummy_pcm_prepare,
+       .trigger =      dummy_pcm_trigger,
+       .pointer =      dummy_pcm_pointer,
+       .copy =         dummy_pcm_copy,
+       .silence =      dummy_pcm_silence,
+       .page =         dummy_pcm_page,
 };
 
 static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
                                        int substreams)
 {
        struct snd_pcm *pcm;
+       struct snd_pcm_ops *ops;
        int err;
 
        err = snd_pcm_new(dummy->card, "Dummy PCM", device,
@@ -440,17 +669,28 @@ static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
        if (err < 0)
                return err;
        dummy->pcm = pcm;
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_dummy_playback_ops);
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_dummy_capture_ops);
+       if (fake_buffer)
+               ops = &dummy_pcm_ops_no_buf;
+       else
+               ops = &dummy_pcm_ops;
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, ops);
        pcm->private_data = dummy;
        pcm->info_flags = 0;
        strcpy(pcm->name, "Dummy PCM");
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
-                                             snd_dma_continuous_data(GFP_KERNEL),
-                                             0, 64*1024);
+       if (!fake_buffer) {
+               snd_pcm_lib_preallocate_pages_for_all(pcm,
+                       SNDRV_DMA_TYPE_CONTINUOUS,
+                       snd_dma_continuous_data(GFP_KERNEL),
+                       0, 64*1024);
+       }
        return 0;
 }
 
+/*
+ * mixer interface
+ */
+
 #define DUMMY_VOLUME(xname, xindex, addr) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
   .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
@@ -581,6 +821,131 @@ static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy)
        return 0;
 }
 
+#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_PROC_FS)
+/*
+ * proc interface
+ */
+static void print_formats(struct snd_info_buffer *buffer)
+{
+       int i;
+
+       for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) {
+               if (dummy_pcm_hardware.formats & (1ULL << i))
+                       snd_iprintf(buffer, " %s", snd_pcm_format_name(i));
+       }
+}
+
+static void print_rates(struct snd_info_buffer *buffer)
+{
+       static int rates[] = {
+               5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000,
+               64000, 88200, 96000, 176400, 192000,
+       };
+       int i;
+
+       if (dummy_pcm_hardware.rates & SNDRV_PCM_RATE_CONTINUOUS)
+               snd_iprintf(buffer, " continuous");
+       if (dummy_pcm_hardware.rates & SNDRV_PCM_RATE_KNOT)
+               snd_iprintf(buffer, " knot");
+       for (i = 0; i < ARRAY_SIZE(rates); i++)
+               if (dummy_pcm_hardware.rates & (1 << i))
+                       snd_iprintf(buffer, " %d", rates[i]);
+}
+
+#define get_dummy_int_ptr(ofs) \
+       (unsigned int *)((char *)&dummy_pcm_hardware + (ofs))
+#define get_dummy_ll_ptr(ofs) \
+       (unsigned long long *)((char *)&dummy_pcm_hardware + (ofs))
+
+struct dummy_hw_field {
+       const char *name;
+       const char *format;
+       unsigned int offset;
+       unsigned int size;
+};
+#define FIELD_ENTRY(item, fmt) {                  \
+       .name = #item,                             \
+       .format = fmt,                             \
+       .offset = offsetof(struct snd_pcm_hardware, item), \
+       .size = sizeof(dummy_pcm_hardware.item) }
+
+static struct dummy_hw_field fields[] = {
+       FIELD_ENTRY(formats, "%#llx"),
+       FIELD_ENTRY(rates, "%#x"),
+       FIELD_ENTRY(rate_min, "%d"),
+       FIELD_ENTRY(rate_max, "%d"),
+       FIELD_ENTRY(channels_min, "%d"),
+       FIELD_ENTRY(channels_max, "%d"),
+       FIELD_ENTRY(buffer_bytes_max, "%ld"),
+       FIELD_ENTRY(period_bytes_min, "%ld"),
+       FIELD_ENTRY(period_bytes_max, "%ld"),
+       FIELD_ENTRY(periods_min, "%d"),
+       FIELD_ENTRY(periods_max, "%d"),
+};
+
+static void dummy_proc_read(struct snd_info_entry *entry,
+                           struct snd_info_buffer *buffer)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(fields); i++) {
+               snd_iprintf(buffer, "%s ", fields[i].name);
+               if (fields[i].size == sizeof(int))
+                       snd_iprintf(buffer, fields[i].format,
+                                   *get_dummy_int_ptr(fields[i].offset));
+               else
+                       snd_iprintf(buffer, fields[i].format,
+                                   *get_dummy_ll_ptr(fields[i].offset));
+               if (!strcmp(fields[i].name, "formats"))
+                       print_formats(buffer);
+               else if (!strcmp(fields[i].name, "rates"))
+                       print_rates(buffer);
+               snd_iprintf(buffer, "\n");
+       }
+}
+
+static void dummy_proc_write(struct snd_info_entry *entry,
+                            struct snd_info_buffer *buffer)
+{
+       char line[64];
+
+       while (!snd_info_get_line(buffer, line, sizeof(line))) {
+               char item[20];
+               const char *ptr;
+               unsigned long long val;
+               int i;
+
+               ptr = snd_info_get_str(item, line, sizeof(item));
+               for (i = 0; i < ARRAY_SIZE(fields); i++) {
+                       if (!strcmp(item, fields[i].name))
+                               break;
+               }
+               if (i >= ARRAY_SIZE(fields))
+                       continue;
+               snd_info_get_str(item, ptr, sizeof(item));
+               if (strict_strtoull(item, 0, &val))
+                       continue;
+               if (fields[i].size == sizeof(int))
+                       *get_dummy_int_ptr(fields[i].offset) = val;
+               else
+                       *get_dummy_ll_ptr(fields[i].offset) = val;
+       }
+}
+
+static void __devinit dummy_proc_init(struct snd_dummy *chip)
+{
+       struct snd_info_entry *entry;
+
+       if (!snd_card_proc_new(chip->card, "dummy_pcm", &entry)) {
+               snd_info_set_text_ops(entry, chip, dummy_proc_read);
+               entry->c.text.write = dummy_proc_write;
+               entry->mode |= S_IWUSR;
+       }
+}
+#else
+#define dummy_proc_init(x)
+#endif /* CONFIG_SND_DEBUG && CONFIG_PROC_FS */
+
 static int __devinit snd_dummy_probe(struct platform_device *devptr)
 {
        struct snd_card *card;
@@ -610,6 +975,8 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr)
        strcpy(card->shortname, "Dummy");
        sprintf(card->longname, "Dummy %i", dev + 1);
 
+       dummy_proc_init(dummy);
+
        snd_card_set_dev(card, &devptr->dev);
 
        err = snd_card_register(card);
@@ -670,6 +1037,7 @@ static void snd_dummy_unregister_all(void)
        for (i = 0; i < ARRAY_SIZE(devices); ++i)
                platform_device_unregister(devices[i]);
        platform_driver_unregister(&snd_dummy_driver);
+       free_fake_buffer();
 }
 
 static int __init alsa_card_dummy_init(void)
@@ -680,6 +1048,12 @@ static int __init alsa_card_dummy_init(void)
        if (err < 0)
                return err;
 
+       err = alloc_fake_buffer();
+       if (err < 0) {
+               platform_driver_unregister(&snd_dummy_driver);
+               return err;
+       }
+
        cards = 0;
        for (i = 0; i < SNDRV_CARDS; i++) {
                struct platform_device *device;
index de83608719ea23138a793e2c557444add2f4001e..02f79d2527189813d62a114f804f8400488f197b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Driver for C-Media's CMI8330 soundcards.
+ *  Driver for C-Media's CMI8330 and CMI8329 soundcards.
  *  Copyright (c) by George Talusan <gstalusan@uwaterloo.ca>
  *    http://www.undergrad.math.uwaterloo.ca/~gstalusa
  *
@@ -35,7 +35,7 @@
  *
  *  This card has two mixers and two PCM devices.  I've cheesed it such
  *  that recording and playback can be done through the same device.
- *  The driver "magically" routes the capturing to the CMI8330 codec,
+ *  The driver "magically" routes the capturing to the AD1848 codec,
  *  and playback to the SB16 codec.  This allows for full-duplex mode
  *  to some extent.
  *  The utilities in alsa-utils are aware of both devices, so passing
@@ -64,7 +64,7 @@
 /*
  */
 MODULE_AUTHOR("George Talusan <gstalusan@uwaterloo.ca>");
-MODULE_DESCRIPTION("C-Media CMI8330");
+MODULE_DESCRIPTION("C-Media CMI8330/CMI8329");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8330,isapnp:{CMI0001,@@@0001,@X@0001}}}");
 
@@ -86,38 +86,38 @@ static long mpuport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
 static int mpuirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
 
 module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for CMI8330 soundcard.");
+MODULE_PARM_DESC(index, "Index value for CMI8330/CMI8329 soundcard.");
 module_param_array(id, charp, NULL, 0444);
-MODULE_PARM_DESC(id, "ID string  for CMI8330 soundcard.");
+MODULE_PARM_DESC(id, "ID string  for CMI8330/CMI8329 soundcard.");
 module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable CMI8330 soundcard.");
+MODULE_PARM_DESC(enable, "Enable CMI8330/CMI8329 soundcard.");
 #ifdef CONFIG_PNP
 module_param_array(isapnp, bool, NULL, 0444);
 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
 #endif
 
 module_param_array(sbport, long, NULL, 0444);
-MODULE_PARM_DESC(sbport, "Port # for CMI8330 SB driver.");
+MODULE_PARM_DESC(sbport, "Port # for CMI8330/CMI8329 SB driver.");
 module_param_array(sbirq, int, NULL, 0444);
-MODULE_PARM_DESC(sbirq, "IRQ # for CMI8330 SB driver.");
+MODULE_PARM_DESC(sbirq, "IRQ # for CMI8330/CMI8329 SB driver.");
 module_param_array(sbdma8, int, NULL, 0444);
-MODULE_PARM_DESC(sbdma8, "DMA8 for CMI8330 SB driver.");
+MODULE_PARM_DESC(sbdma8, "DMA8 for CMI8330/CMI8329 SB driver.");
 module_param_array(sbdma16, int, NULL, 0444);
-MODULE_PARM_DESC(sbdma16, "DMA16 for CMI8330 SB driver.");
+MODULE_PARM_DESC(sbdma16, "DMA16 for CMI8330/CMI8329 SB driver.");
 
 module_param_array(wssport, long, NULL, 0444);
-MODULE_PARM_DESC(wssport, "Port # for CMI8330 WSS driver.");
+MODULE_PARM_DESC(wssport, "Port # for CMI8330/CMI8329 WSS driver.");
 module_param_array(wssirq, int, NULL, 0444);
-MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330 WSS driver.");
+MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330/CMI8329 WSS driver.");
 module_param_array(wssdma, int, NULL, 0444);
-MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver.");
+MODULE_PARM_DESC(wssdma, "DMA for CMI8330/CMI8329 WSS driver.");
 
 module_param_array(fmport, long, NULL, 0444);
-MODULE_PARM_DESC(fmport, "FM port # for CMI8330 driver.");
+MODULE_PARM_DESC(fmport, "FM port # for CMI8330/CMI8329 driver.");
 module_param_array(mpuport, long, NULL, 0444);
-MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8330 driver.");
+MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8330/CMI8329 driver.");
 module_param_array(mpuirq, int, NULL, 0444);
-MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8330 MPU-401 port.");
+MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8330/CMI8329 MPU-401 port.");
 #ifdef CONFIG_PNP
 static int isa_registered;
 static int pnp_registered;
@@ -156,6 +156,11 @@ static unsigned char snd_cmi8330_image[((CMI8330_CDINGAIN)-16) + 1] =
 
 typedef int (*snd_pcm_open_callback_t)(struct snd_pcm_substream *);
 
+enum card_type {
+       CMI8330,
+       CMI8329
+};
+
 struct snd_cmi8330 {
 #ifdef CONFIG_PNP
        struct pnp_dev *cap;
@@ -172,11 +177,14 @@ struct snd_cmi8330 {
                snd_pcm_open_callback_t open;
                void *private_data; /* sb or wss */
        } streams[2];
+
+       enum card_type type;
 };
 
 #ifdef CONFIG_PNP
 
 static struct pnp_card_device_id snd_cmi8330_pnpids[] = {
+       { .id = "CMI0001", .devs = { { "@X@0001" }, { "@@@0001" }, { "@H@0001" }, { "A@@0001" } } },
        { .id = "CMI0001", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } } },
        { .id = "" }
 };
@@ -304,7 +312,7 @@ static int __devinit snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330
        unsigned int idx;
        int err;
 
-       strcpy(card->mixername, "CMI8330/C3D");
+       strcpy(card->mixername, (acard->type == CMI8329) ? "CMI8329" : "CMI8330/C3D");
 
        for (idx = 0; idx < ARRAY_SIZE(snd_cmi8330_controls); idx++) {
                err = snd_ctl_add(card,
@@ -329,6 +337,9 @@ static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard,
        struct pnp_dev *pdev;
        int err;
 
+       /* CMI8329 has a device with ID A@@0001, CMI8330 does not */
+       acard->type = (id->devs[3].id[0]) ? CMI8329 : CMI8330;
+
        acard->cap = pnp_request_card_device(card, id->devs[0].id, NULL);
        if (acard->cap == NULL)
                return -EBUSY;
@@ -338,45 +349,52 @@ static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard,
                return -EBUSY;
 
        acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL);
-       if (acard->play == NULL)
+       if (acard->mpu == NULL)
                return -EBUSY;
 
        pdev = acard->cap;
 
        err = pnp_activate_dev(pdev);
        if (err < 0) {
-               snd_printk(KERN_ERR "CMI8330/C3D PnP configure failure\n");
+               snd_printk(KERN_ERR "AD1848 PnP configure failure\n");
                return -EBUSY;
        }
        wssport[dev] = pnp_port_start(pdev, 0);
        wssdma[dev] = pnp_dma(pdev, 0);
        wssirq[dev] = pnp_irq(pdev, 0);
-       fmport[dev] = pnp_port_start(pdev, 1);
+       if (pnp_port_start(pdev, 1))
+               fmport[dev] = pnp_port_start(pdev, 1);
 
        /* allocate SB16 resources */
        pdev = acard->play;
 
        err = pnp_activate_dev(pdev);
        if (err < 0) {
-               snd_printk(KERN_ERR "CMI8330/C3D (SB16) PnP configure failure\n");
+               snd_printk(KERN_ERR "SB16 PnP configure failure\n");
                return -EBUSY;
        }
        sbport[dev] = pnp_port_start(pdev, 0);
        sbdma8[dev] = pnp_dma(pdev, 0);
        sbdma16[dev] = pnp_dma(pdev, 1);
        sbirq[dev] = pnp_irq(pdev, 0);
+       /* On CMI8239, the OPL3 port might be present in SB16 PnP resources */
+       if (fmport[dev] == SNDRV_AUTO_PORT) {
+               if (pnp_port_start(pdev, 1))
+                       fmport[dev] = pnp_port_start(pdev, 1);
+               else
+                       fmport[dev] = 0x388;    /* Or hardwired */
+       }
 
        /* allocate MPU-401 resources */
        pdev = acard->mpu;
 
        err = pnp_activate_dev(pdev);
-       if (err < 0) {
-               snd_printk(KERN_ERR
-                          "CMI8330/C3D (MPU-401) PnP configure failure\n");
-               return -EBUSY;
+       if (err < 0)
+               snd_printk(KERN_ERR "MPU-401 PnP configure failure: will be disabled\n");
+       else {
+               mpuport[dev] = pnp_port_start(pdev, 0);
+               mpuirq[dev] = pnp_irq(pdev, 0);
        }
-       mpuport[dev] = pnp_port_start(pdev, 0);
-       mpuirq[dev] = pnp_irq(pdev, 0);
        return 0;
 }
 #endif
@@ -430,9 +448,9 @@ static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *
                snd_cmi8330_capture_open
        };
 
-       if ((err = snd_pcm_new(card, "CMI8330", 0, 1, 1, &pcm)) < 0)
+       if ((err = snd_pcm_new(card, (chip->type == CMI8329) ? "CMI8329" : "CMI8330", 0, 1, 1, &pcm)) < 0)
                return err;
-       strcpy(pcm->name, "CMI8330");
+       strcpy(pcm->name, (chip->type == CMI8329) ? "CMI8329" : "CMI8330");
        pcm->private_data = chip;
        
        /* SB16 */
@@ -527,11 +545,11 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
                             wssdma[dev], -1,
                             WSS_HW_DETECT, 0, &acard->wss);
        if (err < 0) {
-               snd_printk(KERN_ERR PFX "(CMI8330) device busy??\n");
+               snd_printk(KERN_ERR PFX "AD1848 device busy??\n");
                return err;
        }
        if (acard->wss->hardware != WSS_HW_CMI8330) {
-               snd_printk(KERN_ERR PFX "(CMI8330) not found during probe\n");
+               snd_printk(KERN_ERR PFX "AD1848 not found during probe\n");
                return -ENODEV;
        }
 
@@ -541,11 +559,11 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
                                    sbdma8[dev],
                                    sbdma16[dev],
                                    SB_HW_AUTO, &acard->sb)) < 0) {
-               snd_printk(KERN_ERR PFX "(SB16) device busy??\n");
+               snd_printk(KERN_ERR PFX "SB16 device busy??\n");
                return err;
        }
        if (acard->sb->hardware != SB_HW_16) {
-               snd_printk(KERN_ERR PFX "(SB16) not found during probe\n");
+               snd_printk(KERN_ERR PFX "SB16 not found during probe\n");
                return err;
        }
 
@@ -585,8 +603,8 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
                                mpuport[dev]);
        }
 
-       strcpy(card->driver, "CMI8330/C3D");
-       strcpy(card->shortname, "C-Media CMI8330/C3D");
+       strcpy(card->driver, (acard->type == CMI8329) ? "CMI8329" : "CMI8330/C3D");
+       strcpy(card->shortname, (acard->type == CMI8329) ? "C-Media CMI8329" : "C-Media CMI8330/C3D");
        sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
                card->shortname,
                acard->wss->port,
index edb11eefdfe3e2097f25037cd5bf507de817bdc7..2dcf45bf7293f1d68a3391226110ce34cc2b721d 100644 (file)
@@ -795,13 +795,13 @@ static int snd_gf1_pcm_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
                if (!(pcmp->flags & SNDRV_GF1_PCM_PFLG_ACTIVE))
                        continue;
                /* load real volume - better precision */
-               spin_lock_irqsave(&gus->reg_lock, flags);
+               spin_lock(&gus->reg_lock);
                snd_gf1_select_voice(gus, pvoice->number);
                snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL);
                vol = pvoice == pcmp->pvoices[0] ? gus->gf1.pcm_volume_level_left : gus->gf1.pcm_volume_level_right;
                snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, vol);
                pcmp->final_volume = 1;
-               spin_unlock_irqrestore(&gus->reg_lock, flags);
+               spin_unlock(&gus->reg_lock);
        }
        spin_unlock_irqrestore(&gus->voice_alloc, flags);
        return change;
index c52691c2fc46df746aee9136545f1c4ed6aa1447..9a88cdfd952a0c609847442b24da8746d8aee51e 100644 (file)
@@ -915,7 +915,7 @@ static int __devinit hal2_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __exit hal2_remove(struct platform_device *pdev)
+static int __devexit hal2_remove(struct platform_device *pdev)
 {
        struct snd_card *card = platform_get_drvdata(pdev);
 
index e497525bc11bcf50612c071bdfc3c5ba186bacf1..8691f4cf6191fc8500d4995c42e227bd8680a6c6 100644 (file)
@@ -973,7 +973,7 @@ static int __devinit snd_sgio2audio_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __exit snd_sgio2audio_remove(struct platform_device *pdev)
+static int __devexit snd_sgio2audio_remove(struct platform_device *pdev)
 {
        struct snd_card *card = platform_get_drvdata(pdev);
 
index 3ee9900ffd7b30c6b3a530b75f53a6353f012320..35b5912cf3f81fa36d181fdb44f1f35be5d92d79 100644 (file)
 /*
  * Size of character arrays that store name and version of sound card
  */
-#define CARDNAMELEN 15         /* Size of the card's name in chars     */
-#define CARDVERLEN  2          /* Size of the card's version in chars  */
+#define CARDNAMELEN    15      /* Size of the card's name in chars     */
+#define CARDVERLEN     10      /* Size of the card's version in chars  */
+#define CARDVERDIGITS  2       /* Number of digits in the version      */
 
 #if defined(CONFIG_SC6600)
 /*
 
 static int      soft_cfg __initdata = 0;       /* bitmapped config */
 static int      soft_cfg_mss __initdata = 0;   /* bitmapped mss config */
-static int      ver[CARDVERLEN] __initdata = {0, 0};   /* DSP Ver:
+static int      ver[CARDVERDIGITS] __initdata = {0, 0};        /* DSP Ver:
                                                   hi->ver[0] lo->ver[1] */
 
 #if defined(CONFIG_SC6600)
@@ -957,7 +958,7 @@ static int __init aedsp16_dsp_version(int port)
         * string is finished.
         */
                ver[len++] = ret;
-         } while (len < CARDVERLEN);
+         } while (len < CARDVERDIGITS);
        sprintf(DSPVersion, "%d.%d", ver[0], ver[1]);
 
        DBG(("success.\n"));
index c180598f1710498bf94ca0549622c798288fb675..89466b056be79c8f1515db39d517b3dede0d25c2 100644 (file)
@@ -199,7 +199,7 @@ MODULE_LICENSE("GPL");
  */
 
 static struct pci_device_id id_tbl[] = {
-       { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO), 0 },
        { }
 };
 
index a40be0cf1d97f42bf6a180312afbc10b15c7a5bc..782b3b84dac68ccd036c52ee3533336f243ac15b 100644 (file)
@@ -127,15 +127,16 @@ static void midi_poll(unsigned long dummy)
                for (dev = 0; dev < num_midis; dev++)
                        if (midi_devs[dev] != NULL && midi_out_buf[dev] != NULL)
                        {
-                               int ok = 1;
-
-                               while (DATA_AVAIL(midi_out_buf[dev]) && ok)
+                               while (DATA_AVAIL(midi_out_buf[dev]))
                                {
+                                       int ok;
                                        int c = midi_out_buf[dev]->queue[midi_out_buf[dev]->head];
 
                                        spin_unlock_irqrestore(&lock,flags);/* Give some time to others */
                                        ok = midi_devs[dev]->outputc(dev, c);
                                        spin_lock_irqsave(&lock, flags);
+                                       if (!ok)
+                                               break;
                                        midi_out_buf[dev]->head = (midi_out_buf[dev]->head + 1) % MAX_QUEUE_SIZE;
                                        midi_out_buf[dev]->len--;
                                }
index 6c0a770ed0543d62bdc26203244c1e730a106110..734b8f9e2f788a36ac54eccf680a02f32eb37a75 100644 (file)
@@ -926,31 +926,21 @@ static struct midi_operations mpu401_midi_operations[MAX_MIDI_DEV];
 static void mpu401_chk_version(int n, struct mpu_config *devc)
 {
        int tmp;
-       unsigned long flags;
 
        devc->version = devc->revision = 0;
 
-       spin_lock_irqsave(&devc->lock,flags);
-       if ((tmp = mpu_cmd(n, 0xAC, 0)) < 0)
-       {
-               spin_unlock_irqrestore(&devc->lock,flags);
+       tmp = mpu_cmd(n, 0xAC, 0);
+       if (tmp < 0)
                return;
-       }
        if ((tmp & 0xf0) > 0x20)        /* Why it's larger than 2.x ??? */
-       {
-               spin_unlock_irqrestore(&devc->lock,flags);
                return;
-       }
        devc->version = tmp;
 
-       if ((tmp = mpu_cmd(n, 0xAD, 0)) < 0)
-       {
+       if ((tmp = mpu_cmd(n, 0xAD, 0)) < 0) {
                devc->version = 0;
-               spin_unlock_irqrestore(&devc->lock,flags);
                return;
        }
        devc->revision = tmp;
-       spin_unlock_irqrestore(&devc->lock,flags);
 }
 
 int attach_mpu401(struct address_info *hw_config, struct module *owner)
@@ -1084,7 +1074,7 @@ int attach_mpu401(struct address_info *hw_config, struct module *owner)
                        sprintf(mpu_synth_info[m].name, "%s (MPU401)", hw_config->name);
                else
                        sprintf(mpu_synth_info[m].name,
-                               "MPU-401 %d.%d%c Midi interface #%d",
+                               "MPU-401 %d.%d%c MIDI #%d",
                                (int) (devc->version & 0xf0) >> 4,
                                devc->version & 0x0f,
                                revision_char,
index 187f72750e8f9796734bf34c511ab8791868f247..6713110bdc7506ed3b05a0259d626936c440a51b 100644 (file)
@@ -628,7 +628,7 @@ static void li_setup_dma(dma_chan_t *chan,
        ASSERT(!(buffer_paddr & 0xFF));
        chan->baseval = (buffer_paddr >> 8) | 1 << (37 - 8);
 
-       chan->cfgval = (!LI_CCFG_LOCK |
+       chan->cfgval = ((chan->cfgval & ~LI_CCFG_LOCK) |
                        SHIFT_FIELD(desc->ad1843_slot, LI_CCFG_SLOT) |
                        desc->direction |
                        mode |
@@ -638,9 +638,9 @@ static void li_setup_dma(dma_chan_t *chan,
        tmask = 13 - fragshift;         /* See Lithium DMA Notes above. */
        ASSERT(size >= 2 && size <= 7);
        ASSERT(tmask >= 1 && tmask <= 7);
-       chan->ctlval = (!LI_CCTL_RESET |
+       chan->ctlval = ((chan->ctlval & ~LI_CCTL_RESET) |
                        SHIFT_FIELD(size, LI_CCTL_SIZE) |
-                       !LI_CCTL_DMA_ENABLE |
+                       (chan->ctlval & ~LI_CCTL_DMA_ENABLE) |
                        SHIFT_FIELD(tmask, LI_CCTL_TMASK) |
                        SHIFT_FIELD(0, LI_CCTL_TPTR));
 
index 748f6b7d90b7715729d131e831f0299d0d8384fa..fb5ee3cc39682b2d412f9ce2059973f6570be9e5 100644 (file)
@@ -135,11 +135,11 @@ config SND_AW2
 
 
 config SND_AZT3328
-       tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       tristate "Aztech AZF3328 / PCI168"
        select SND_OPL3_LIB
        select SND_MPU401_UART
        select SND_PCM
+       select SND_RAWMIDI
        help
          Say Y here to include support for Aztech AZF3328 (PCI168)
          soundcards.
index c551006e292054088e5deeaae5baf277403e883a..b458d208720b1c6ac010ab235e122e3dd407f6e5 100644 (file)
@@ -310,12 +310,16 @@ static int snd_ali_codec_ready(struct snd_ali *codec,
        unsigned int res;
        
        end_time = jiffies + msecs_to_jiffies(250);
-       do {
+
+       for (;;) {
                res = snd_ali_5451_peek(codec,port);
                if (!(res & 0x8000))
                        return 0;
+               if (!time_after_eq(end_time, jiffies))
+                       break;
                schedule_timeout_uninterruptible(1);
-       } while (time_after_eq(end_time, jiffies));
+       }
+
        snd_ali_5451_poke(codec, port, res & ~0x8000);
        snd_printdd("ali_codec_ready: codec is not ready.\n ");
        return -EIO;
@@ -327,15 +331,17 @@ static int snd_ali_stimer_ready(struct snd_ali *codec)
        unsigned long dwChk1,dwChk2;
        
        dwChk1 = snd_ali_5451_peek(codec, ALI_STIMER);
-       dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER);
-
        end_time = jiffies + msecs_to_jiffies(250);
-       do {
+
+       for (;;) {
                dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER);
                if (dwChk2 != dwChk1)
                        return 0;
+               if (!time_after_eq(end_time, jiffies))
+                       break;
                schedule_timeout_uninterruptible(1);
-       } while (time_after_eq(end_time, jiffies));
+       }
+
        snd_printk(KERN_ERR "ali_stimer_read: stimer is not ready.\n");
        return -EIO;
 }
@@ -472,45 +478,6 @@ static int snd_ali_reset_5451(struct snd_ali *codec)
        return 0;
 }
 
-#ifdef CODEC_RESET
-
-static int snd_ali_reset_codec(struct snd_ali *codec)
-{
-       struct pci_dev *pci_dev;
-       unsigned char bVal;
-       unsigned int   dwVal;
-       unsigned short wCount, wReg;
-
-       pci_dev = codec->pci_m1533;
-       
-       pci_read_config_dword(pci_dev, 0x7c, &dwVal);
-       pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000);
-       udelay(5000);
-       pci_read_config_dword(pci_dev, 0x7c, &dwVal);
-       pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff);
-       udelay(5000);
-
-       bVal = inb(ALI_REG(codec,ALI_SCTRL));
-       bVal |= 0x02;
-       outb(ALI_REG(codec,ALI_SCTRL),bVal);
-       udelay(5000);
-       bVal = inb(ALI_REG(codec,ALI_SCTRL));
-       bVal &= 0xfd;
-       outb(ALI_REG(codec,ALI_SCTRL),bVal);
-       udelay(15000);
-
-       wCount = 200;
-       while (wCount--) {
-               wReg = snd_ali_codec_read(codec->ac97, AC97_POWERDOWN);
-               if ((wReg & 0x000f) == 0x000f)
-                       return 0;
-               udelay(5000);
-       }
-       return -1;
-}
-
-#endif
-
 /*
  *  ALI 5451 Controller
  */
@@ -555,22 +522,6 @@ static void snd_ali_disable_address_interrupt(struct snd_ali *codec)
        outl(gc, ALI_REG(codec, ALI_GC_CIR));
 }
 
-#if 0 /* not used */
-static void snd_ali_enable_voice_irq(struct snd_ali *codec,
-                                    unsigned int channel)
-{
-       unsigned int mask;
-       struct snd_ali_channel_control *pchregs = &(codec->chregs);
-
-       snd_ali_printk("enable_voice_irq channel=%d\n",channel);
-       
-       mask = 1 << (channel & 0x1f);
-       pchregs->data.ainten  = inl(ALI_REG(codec, pchregs->regs.ainten));
-       pchregs->data.ainten |= mask;
-       outl(pchregs->data.ainten, ALI_REG(codec, pchregs->regs.ainten));
-}
-#endif
-
 static void snd_ali_disable_voice_irq(struct snd_ali *codec,
                                      unsigned int channel)
 {
@@ -671,16 +622,6 @@ static void snd_ali_free_channel_pcm(struct snd_ali *codec, int channel)
        }
 }
 
-#if 0 /* not used */
-static void snd_ali_start_voice(struct snd_ali *codec, unsigned int channel)
-{
-       unsigned int mask = 1 << (channel & 0x1f);
-       
-       snd_ali_printk("start_voice: channel=%d\n",channel);
-       outl(mask, ALI_REG(codec,codec->chregs.regs.start));
-}
-#endif
-
 static void snd_ali_stop_voice(struct snd_ali *codec, unsigned int channel)
 {
        unsigned int mask = 1 << (channel & 0x1f);
index 71515ddb4593c71f75aa8f17d62d755034a4e181..d6752dff2a443df67a8b9cd3fa5a913e6dc7b68c 100644 (file)
@@ -287,10 +287,10 @@ struct atiixp {
 /*
  */
 static struct pci_device_id snd_atiixp_ids[] = {
-       { 0x1002, 0x4341, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */
-       { 0x1002, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB300 */
-       { 0x1002, 0x4370, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */
-       { 0x1002, 0x4382, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB600 */
+       { PCI_VDEVICE(ATI, 0x4341), 0 }, /* SB200 */
+       { PCI_VDEVICE(ATI, 0x4361), 0 }, /* SB300 */
+       { PCI_VDEVICE(ATI, 0x4370), 0 }, /* SB400 */
+       { PCI_VDEVICE(ATI, 0x4382), 0 }, /* SB600 */
        { 0, }
 };
 
index c3136cccc559e86f90f978d9bb922ae305c5d140..e7e147bf8eb2686cc98a629905f9589a0fb5357d 100644 (file)
@@ -262,8 +262,8 @@ struct atiixp_modem {
 /*
  */
 static struct pci_device_id snd_atiixp_ids[] = {
-       { 0x1002, 0x434d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB200 */
-       { 0x1002, 0x4378, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SB400 */
+       { PCI_VDEVICE(ATI, 0x434d), 0 }, /* SB200 */
+       { PCI_VDEVICE(ATI, 0x4378), 0 }, /* SB400 */
        { 0, }
 };
 
index fce22c7af0ea2a7d8c57af9910ae000d8f41db11..c0e8c6b295cb98df3fb8ef164f373cb35f81ba58 100644 (file)
@@ -1,8 +1,7 @@
 #include "au8810.h"
 #include "au88x0.h"
 static struct pci_device_id snd_vortex_ids[] = {
-       {PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_ADVANTAGE,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1,},
+       {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_ADVANTAGE), 1,},
        {0,}
 };
 
index d1fbcce0725731cc46d35b3946a17299acbf68ce..a6527330df584964b5b96b82632f747e22da89f2 100644 (file)
@@ -1,8 +1,7 @@
 #include "au8820.h"
 #include "au88x0.h"
 static struct pci_device_id snd_vortex_ids[] = {
-       {PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_1,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
+       {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_1), 0,},
        {0,}
 };
 
index d4f2717c14fb07a896c13cfd943c78b5a107bb32..6c702ad4352ad8198af4a062c75c9d93571f10fd 100644 (file)
@@ -1,8 +1,7 @@
 #include "au8830.h"
 #include "au88x0.h"
 static struct pci_device_id snd_vortex_ids[] = {
-       {PCI_VENDOR_ID_AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_2,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
+       {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_2), 0,},
        {0,}
 };
 
index f290bc56178f783726f98f5a4ad460492dee672d..8451a0169f327881a6da435b1ee86963707e4b74 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168).
- *  Copyright (C) 2002, 2005 - 2008 by Andreas Mohr <andi AT lisas.de>
+ *  Copyright (C) 2002, 2005 - 2009 by Andreas Mohr <andi AT lisas.de>
  *
  *  Framework borrowed from Bart Hartgers's als4000.c.
  *  Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801),
  *  PCI168 A/AP, sub ID 8000
  *  Please give me feedback in case you try my driver with one of these!!
  *
+ *  Keywords: Windows XP Vista 168nt4-125.zip 168win95-125.zip PCI 168 download
+ *  (XP/Vista do not support this card at all but every Linux distribution
+ *   has very good support out of the box;
+ *   just to make sure that the right people hit this and get to know that,
+ *   despite the high level of Internet ignorance - as usual :-P -
+ *   about very good support for this card - on Linux!)
+ *
  * GPL LICENSE
  *  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
  *  - built-in General DirectX timer having a 20 bits counter
  *    with 1us resolution (see below!)
  *  - I2S serial output port for external DAC
+ *    [FIXME: 3.3V or 5V level? maximum rate is 66.2kHz right?]
  *  - supports 33MHz PCI spec 2.1, PCI power management 1.0, compliant with ACPI
  *  - supports hardware volume control
  *  - single chip low cost solution (128 pin QFP)
- *  - supports programmable Sub-vendor and Sub-system ID
+ *  - supports programmable Sub-vendor and Sub-system ID [24C02 SEEPROM chip]
  *    required for Microsoft's logo compliance (FIXME: where?)
  *    At least the Trident 4D Wave DX has one bit somewhere
  *    to enable writes to PCI subsystem VID registers, that should be it.
@@ -82,6 +90,7 @@
  *    some custom data starting at 0x80. What kind of config settings
  *    are located in our extended PCI space anyway??
  *  - PCI168 AP(W) card: power amplifier with 4 Watts/channel at 4 Ohms
+ *    [TDA1517P chip]
  *
  *  Note that this driver now is actually *better* than the Windows driver,
  *  since it additionally supports the card's 1MHz DirectX timer - just try
  *    to read the Digital Enhanced Game Port. Not sure whether it is fixable.
  *
  * TODO
+ *  - use PCI_VDEVICE
+ *  - verify driver status on x86_64
+ *  - test multi-card driver operation
+ *  - (ab)use 1MHz DirectX timer as kernel clocksource
  *  - test MPU401 MIDI playback etc.
  *  - add more power micro-management (disable various units of the card
- *    as long as they're unused). However this requires more I/O ports which I
- *    haven't figured out yet and which thus might not even exist...
+ *    as long as they're unused, to improve audio quality and save power).
+ *    However this requires more I/O ports which I haven't figured out yet
+ *    and which thus might not even exist...
  *    The standard suspend/resume functionality could probably make use of
  *    some improvement, too...
  *  - figure out what all unknown port bits are responsible for
@@ -185,25 +199,46 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
 #define SUPPORT_GAMEPORT 1
 #endif
 
+/* === Debug settings ===
+  Further diagnostic functionality than the settings below
+  does not need to be provided, since one can easily write a bash script
+  to dump the card's I/O ports (those listed in lspci -v -v):
+  function dump()
+  {
+    local descr=$1; local addr=$2; local count=$3
+
+    echo "${descr}: ${count} @ ${addr}:"
+    dd if=/dev/port skip=$[${addr}] count=${count} bs=1 2>/dev/null| hexdump -C
+  }
+  and then use something like
+  "dump joy200 0x200 8", "dump mpu388 0x388 4", "dump joy 0xb400 8",
+  "dump codec00 0xa800 32", "dump mixer 0xb800 64", "dump synth 0xbc00 8",
+  possibly within a "while true; do ... sleep 1; done" loop.
+  Tweaking ports could be done using
+  VALSTRING="`printf "%02x" $value`"
+  printf "\x""$VALSTRING"|dd of=/dev/port seek=$[${addr}] bs=1 2>/dev/null
+*/
+
 #define DEBUG_MISC     0
 #define DEBUG_CALLS    0
 #define DEBUG_MIXER    0
-#define DEBUG_PLAY_REC 0
+#define DEBUG_CODEC    0
 #define DEBUG_IO       0
 #define DEBUG_TIMER    0
 #define DEBUG_GAME     0
+#define DEBUG_PM       0
 #define MIXER_TESTING  0
 
 #if DEBUG_MISC
-#define snd_azf3328_dbgmisc(format, args...) printk(KERN_ERR format, ##args)
+#define snd_azf3328_dbgmisc(format, args...) printk(KERN_DEBUG format, ##args)
 #else
 #define snd_azf3328_dbgmisc(format, args...)
 #endif
 
 #if DEBUG_CALLS
 #define snd_azf3328_dbgcalls(format, args...) printk(format, ##args)
-#define snd_azf3328_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__)
-#define snd_azf3328_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__)
+#define snd_azf3328_dbgcallenter() printk(KERN_DEBUG "--> %s\n", __func__)
+#define snd_azf3328_dbgcallleave() printk(KERN_DEBUG "<-- %s\n", __func__)
 #else
 #define snd_azf3328_dbgcalls(format, args...)
 #define snd_azf3328_dbgcallenter()
@@ -216,10 +251,10 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
 #define snd_azf3328_dbgmixer(format, args...)
 #endif
 
-#if DEBUG_PLAY_REC
-#define snd_azf3328_dbgplay(format, args...) printk(KERN_DEBUG format, ##args)
+#if DEBUG_CODEC
+#define snd_azf3328_dbgcodec(format, args...) printk(KERN_DEBUG format, ##args)
 #else
-#define snd_azf3328_dbgplay(format, args...)
+#define snd_azf3328_dbgcodec(format, args...)
 #endif
 
 #if DEBUG_MISC
@@ -234,6 +269,12 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}");
 #define snd_azf3328_dbggame(format, args...)
 #endif
 
+#if DEBUG_PM
+#define snd_azf3328_dbgpm(format, args...) printk(KERN_DEBUG format, ##args)
+#else
+#define snd_azf3328_dbgpm(format, args...)
+#endif
+
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for AZF3328 soundcard.");
@@ -250,22 +291,23 @@ static int seqtimer_scaling = 128;
 module_param(seqtimer_scaling, int, 0444);
 MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128.");
 
-struct snd_azf3328_audio_stream {
+struct snd_azf3328_codec_data {
+       unsigned long io_base;
        struct snd_pcm_substream *substream;
-       int enabled;
-       int running;
-       unsigned long portbase;
+       bool running;
+       const char *name;
 };
 
-enum snd_azf3328_stream_index {
-  AZF_PLAYBACK = 0,
-  AZF_CAPTURE = 1,
+enum snd_azf3328_codec_type {
+  AZF_CODEC_PLAYBACK = 0,
+  AZF_CODEC_CAPTURE = 1,
+  AZF_CODEC_I2S_OUT = 2,
 };
 
 struct snd_azf3328 {
        /* often-used fields towards beginning, then grouped */
 
-       unsigned long codec_io; /* usually 0xb000, size 128 */
+       unsigned long ctrl_io; /* usually 0xb000, size 128 */
        unsigned long game_io;  /* usually 0xb400, size 8 */
        unsigned long mpu_io;   /* usually 0xb800, size 4 */
        unsigned long opl3_io; /* usually 0xbc00, size 8 */
@@ -275,15 +317,17 @@ struct snd_azf3328 {
 
        struct snd_timer *timer;
 
-       struct snd_pcm *pcm;
-       struct snd_azf3328_audio_stream audio_stream[2];
+       struct snd_pcm *pcm[3];
+
+       /* playback, recording and I2S out codecs */
+       struct snd_azf3328_codec_data codecs[3];
 
        struct snd_card *card;
        struct snd_rawmidi *rmidi;
 
 #ifdef SUPPORT_GAMEPORT
        struct gameport *gameport;
-       int axes[4];
+       u16 axes[4];
 #endif
 
        struct pci_dev *pci;
@@ -293,16 +337,16 @@ struct snd_azf3328 {
         * If we need to add more registers here, then we might try to fold this
         * into some transparent combined shadow register handling with
         * CONFIG_PM register storage below, but that's slightly difficult. */
-       u16 shadow_reg_codec_6AH;
+       u16 shadow_reg_ctrl_6AH;
 
 #ifdef CONFIG_PM
        /* register value containers for power management
-        * Note: not always full I/O range preserved (just like Win driver!) */
-       u16 saved_regs_codec[AZF_IO_SIZE_CODEC_PM / 2];
-       u16 saved_regs_game [AZF_IO_SIZE_GAME_PM / 2];
-       u16 saved_regs_mpu  [AZF_IO_SIZE_MPU_PM / 2];
-       u16 saved_regs_opl3 [AZF_IO_SIZE_OPL3_PM / 2];
-       u16 saved_regs_mixer[AZF_IO_SIZE_MIXER_PM / 2];
+        * Note: not always full I/O range preserved (similar to Win driver!) */
+       u32 saved_regs_ctrl[AZF_ALIGN(AZF_IO_SIZE_CTRL_PM) / 4];
+       u32 saved_regs_game[AZF_ALIGN(AZF_IO_SIZE_GAME_PM) / 4];
+       u32 saved_regs_mpu[AZF_ALIGN(AZF_IO_SIZE_MPU_PM) / 4];
+       u32 saved_regs_opl3[AZF_ALIGN(AZF_IO_SIZE_OPL3_PM) / 4];
+       u32 saved_regs_mixer[AZF_ALIGN(AZF_IO_SIZE_MIXER_PM) / 4];
 #endif
 };
 
@@ -316,7 +360,7 @@ MODULE_DEVICE_TABLE(pci, snd_azf3328_ids);
 
 
 static int
-snd_azf3328_io_reg_setb(unsigned reg, u8 mask, int do_set)
+snd_azf3328_io_reg_setb(unsigned reg, u8 mask, bool do_set)
 {
        u8 prev = inb(reg), new;
 
@@ -331,39 +375,72 @@ snd_azf3328_io_reg_setb(unsigned reg, u8 mask, int do_set)
 }
 
 static inline void
-snd_azf3328_codec_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value)
+snd_azf3328_codec_outb(const struct snd_azf3328_codec_data *codec,
+                      unsigned reg,
+                      u8 value
+)
 {
-       outb(value, chip->codec_io + reg);
+       outb(value, codec->io_base + reg);
 }
 
 static inline u8
-snd_azf3328_codec_inb(const struct snd_azf3328 *chip, unsigned reg)
+snd_azf3328_codec_inb(const struct snd_azf3328_codec_data *codec, unsigned reg)
 {
-       return inb(chip->codec_io + reg);
+       return inb(codec->io_base + reg);
 }
 
 static inline void
-snd_azf3328_codec_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value)
+snd_azf3328_codec_outw(const struct snd_azf3328_codec_data *codec,
+                      unsigned reg,
+                      u16 value
+)
 {
-       outw(value, chip->codec_io + reg);
+       outw(value, codec->io_base + reg);
 }
 
 static inline u16
-snd_azf3328_codec_inw(const struct snd_azf3328 *chip, unsigned reg)
+snd_azf3328_codec_inw(const struct snd_azf3328_codec_data *codec, unsigned reg)
 {
-       return inw(chip->codec_io + reg);
+       return inw(codec->io_base + reg);
 }
 
 static inline void
-snd_azf3328_codec_outl(const struct snd_azf3328 *chip, unsigned reg, u32 value)
+snd_azf3328_codec_outl(const struct snd_azf3328_codec_data *codec,
+                      unsigned reg,
+                      u32 value
+)
 {
-       outl(value, chip->codec_io + reg);
+       outl(value, codec->io_base + reg);
 }
 
 static inline u32
-snd_azf3328_codec_inl(const struct snd_azf3328 *chip, unsigned reg)
+snd_azf3328_codec_inl(const struct snd_azf3328_codec_data *codec, unsigned reg)
+{
+       return inl(codec->io_base + reg);
+}
+
+static inline void
+snd_azf3328_ctrl_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value)
+{
+       outb(value, chip->ctrl_io + reg);
+}
+
+static inline u8
+snd_azf3328_ctrl_inb(const struct snd_azf3328 *chip, unsigned reg)
+{
+       return inb(chip->ctrl_io + reg);
+}
+
+static inline void
+snd_azf3328_ctrl_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value)
+{
+       outw(value, chip->ctrl_io + reg);
+}
+
+static inline void
+snd_azf3328_ctrl_outl(const struct snd_azf3328 *chip, unsigned reg, u32 value)
 {
-       return inl(chip->codec_io + reg);
+       outl(value, chip->ctrl_io + reg);
 }
 
 static inline void
@@ -404,13 +481,13 @@ snd_azf3328_mixer_inw(const struct snd_azf3328 *chip, unsigned reg)
 
 #define AZF_MUTE_BIT 0x80
 
-static int
+static bool
 snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip,
-                          unsigned reg, int do_mute
+                          unsigned reg, bool do_mute
 )
 {
        unsigned long portbase = chip->mixer_io + reg + 1;
-       int updated;
+       bool updated;
 
        /* the mute bit is on the *second* (i.e. right) register of a
         * left/right channel setting */
@@ -569,7 +646,7 @@ snd_azf3328_get_mixer(struct snd_kcontrol *kcontrol,
 {
        struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
        struct azf3328_mixer_reg reg;
-       unsigned int oreg, val;
+       u16 oreg, val;
 
        snd_azf3328_dbgcallenter();
        snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
@@ -600,7 +677,7 @@ snd_azf3328_put_mixer(struct snd_kcontrol *kcontrol,
 {
        struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
        struct azf3328_mixer_reg reg;
-       unsigned int oreg, nreg, val;
+       u16 oreg, nreg, val;
 
        snd_azf3328_dbgcallenter();
        snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
@@ -709,7 +786,7 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol,
 {
         struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol);
        struct azf3328_mixer_reg reg;
-       unsigned int oreg, nreg, val;
+       u16 oreg, nreg, val;
 
        snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
        oreg = snd_azf3328_mixer_inw(chip, reg.reg);
@@ -867,14 +944,15 @@ snd_azf3328_hw_free(struct snd_pcm_substream *substream)
 
 static void
 snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
-                              unsigned reg,
+                              enum snd_azf3328_codec_type codec_type,
                               enum azf_freq_t bitrate,
                               unsigned int format_width,
                               unsigned int channels
 )
 {
-       u16 val = 0xff00;
        unsigned long flags;
+       const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
+       u16 val = 0xff00;
 
        snd_azf3328_dbgcallenter();
        switch (bitrate) {
@@ -917,7 +995,7 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
        spin_lock_irqsave(&chip->reg_lock, flags);
 
        /* set bitrate/format */
-       snd_azf3328_codec_outw(chip, reg, val);
+       snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val);
 
        /* changing the bitrate/format settings switches off the
         * audio output with an annoying click in case of 8/16bit format change
@@ -926,11 +1004,11 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
         * (FIXME: yes, it works, but what exactly am I doing here?? :)
         * FIXME: does this have some side effects for full-duplex
         * or other dramatic side effects? */
-       if (reg == IDX_IO_PLAY_SOUNDFORMAT) /* only do it for playback */
-               snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,
-                       snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) |
-                       DMA_PLAY_SOMETHING1 |
-                       DMA_PLAY_SOMETHING2 |
+       if (codec_type == AZF_CODEC_PLAYBACK) /* only do it for playback */
+               snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
+                       snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS) |
+                       DMA_RUN_SOMETHING1 |
+                       DMA_RUN_SOMETHING2 |
                        SOMETHING_ALMOST_ALWAYS_SET |
                        DMA_EPILOGUE_SOMETHING |
                        DMA_SOMETHING_ELSE
@@ -942,112 +1020,134 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,
 
 static inline void
 snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328 *chip,
-                           unsigned reg
+                           enum snd_azf3328_codec_type codec_type
 )
 {
        /* choose lowest frequency for low power consumption.
         * While this will cause louder noise due to rather coarse frequency,
         * it should never matter since output should always
         * get disabled properly when idle anyway. */
-       snd_azf3328_codec_setfmt(chip, reg, AZF_FREQ_4000, 8, 1);
+       snd_azf3328_codec_setfmt(chip, codec_type, AZF_FREQ_4000, 8, 1);
 }
 
 static void
-snd_azf3328_codec_reg_6AH_update(struct snd_azf3328 *chip,
+snd_azf3328_ctrl_reg_6AH_update(struct snd_azf3328 *chip,
                                        unsigned bitmask,
-                                       int enable
+                                       bool enable
 )
 {
-       if (enable)
-               chip->shadow_reg_codec_6AH &= ~bitmask;
+       bool do_mask = !enable;
+       if (do_mask)
+               chip->shadow_reg_ctrl_6AH |= bitmask;
        else
-               chip->shadow_reg_codec_6AH |= bitmask;
-       snd_azf3328_dbgplay("6AH_update mask 0x%04x enable %d: val 0x%04x\n",
-                       bitmask, enable, chip->shadow_reg_codec_6AH);
-       snd_azf3328_codec_outw(chip, IDX_IO_6AH, chip->shadow_reg_codec_6AH);
+               chip->shadow_reg_ctrl_6AH &= ~bitmask;
+       snd_azf3328_dbgcodec("6AH_update mask 0x%04x do_mask %d: val 0x%04x\n",
+                       bitmask, do_mask, chip->shadow_reg_ctrl_6AH);
+       snd_azf3328_ctrl_outw(chip, IDX_IO_6AH, chip->shadow_reg_ctrl_6AH);
 }
 
 static inline void
-snd_azf3328_codec_enable(struct snd_azf3328 *chip, int enable)
+snd_azf3328_ctrl_enable_codecs(struct snd_azf3328 *chip, bool enable)
 {
-       snd_azf3328_dbgplay("codec_enable %d\n", enable);
+       snd_azf3328_dbgcodec("codec_enable %d\n", enable);
        /* no idea what exactly is being done here, but I strongly assume it's
         * PM related */
-       snd_azf3328_codec_reg_6AH_update(
+       snd_azf3328_ctrl_reg_6AH_update(
                chip, IO_6A_PAUSE_PLAYBACK_BIT8, enable
        );
 }
 
 static void
-snd_azf3328_codec_activity(struct snd_azf3328 *chip,
-                               enum snd_azf3328_stream_index stream_type,
-                               int enable
+snd_azf3328_ctrl_codec_activity(struct snd_azf3328 *chip,
+                               enum snd_azf3328_codec_type codec_type,
+                               bool enable
 )
 {
-       int need_change = (chip->audio_stream[stream_type].running != enable);
+       struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
+       bool need_change = (codec->running != enable);
 
-       snd_azf3328_dbgplay(
-               "codec_activity: type %d, enable %d, need_change %d\n",
-                               stream_type, enable, need_change
+       snd_azf3328_dbgcodec(
+               "codec_activity: %s codec, enable %d, need_change %d\n",
+                               codec->name, enable, need_change
        );
        if (need_change) {
-               enum snd_azf3328_stream_index other =
-                       (stream_type == AZF_PLAYBACK) ?
-                               AZF_CAPTURE : AZF_PLAYBACK;
-               /* small check to prevent shutting down the other party
-                * in case it's active */
-               if ((enable) || !(chip->audio_stream[other].running))
-                       snd_azf3328_codec_enable(chip, enable);
+               static const struct {
+                       enum snd_azf3328_codec_type other1;
+                       enum snd_azf3328_codec_type other2;
+               } peer_codecs[3] =
+                       { { AZF_CODEC_CAPTURE, AZF_CODEC_I2S_OUT },
+                         { AZF_CODEC_PLAYBACK, AZF_CODEC_I2S_OUT },
+                         { AZF_CODEC_PLAYBACK, AZF_CODEC_CAPTURE } };
+               bool call_function;
+
+               if (enable)
+                       /* if enable codec, call enable_codecs func
+                          to enable codec supply... */
+                       call_function = 1;
+               else {
+                       /* ...otherwise call enable_codecs func
+                          (which globally shuts down operation of codecs)
+                          only in case the other codecs are currently
+                          not active either! */
+                       call_function =
+                               ((!chip->codecs[peer_codecs[codec_type].other1]
+                                       .running)
+                            &&  (!chip->codecs[peer_codecs[codec_type].other2]
+                                       .running));
+                }
+                if (call_function)
+                       snd_azf3328_ctrl_enable_codecs(chip, enable);
 
                /* ...and adjust clock, too
                 * (reduce noise and power consumption) */
                if (!enable)
                        snd_azf3328_codec_setfmt_lowpower(
                                chip,
-                               chip->audio_stream[stream_type].portbase
-                                       + IDX_IO_PLAY_SOUNDFORMAT
+                               codec_type
                        );
+               codec->running = enable;
        }
-       chip->audio_stream[stream_type].running = enable;
 }
 
 static void
-snd_azf3328_setdmaa(struct snd_azf3328 *chip,
-                               long unsigned int addr,
-                                unsigned int count,
-                                unsigned int size,
-                               enum snd_azf3328_stream_index stream_type
+snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip,
+                               enum snd_azf3328_codec_type codec_type,
+                               unsigned long addr,
+                               unsigned int count,
+                               unsigned int size
 )
 {
+       const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
        snd_azf3328_dbgcallenter();
-       if (!chip->audio_stream[stream_type].running) {
-               /* AZF3328 uses a two buffer pointer DMA playback approach */
+       if (!codec->running) {
+               /* AZF3328 uses a two buffer pointer DMA transfer approach */
 
-               unsigned long flags, portbase, addr_area2;
+               unsigned long flags, addr_area2;
 
                /* width 32bit (prevent overflow): */
-               unsigned long count_areas, count_tmp;
+               u32 count_areas, lengths;
 
-               portbase = chip->audio_stream[stream_type].portbase;
                count_areas = size/2;
                addr_area2 = addr+count_areas;
                count_areas--; /* max. index */
-               snd_azf3328_dbgplay("set DMA: buf1 %08lx[%lu], buf2 %08lx[%lu]\n", addr, count_areas, addr_area2, count_areas);
+               snd_azf3328_dbgcodec("setdma: buffers %08lx[%u] / %08lx[%u]\n",
+                               addr, count_areas, addr_area2, count_areas);
 
                /* build combined I/O buffer length word */
-               count_tmp = count_areas;
-               count_areas |= (count_tmp << 16);
+               lengths = (count_areas << 16) | (count_areas);
                spin_lock_irqsave(&chip->reg_lock, flags);
-               outl(addr, portbase + IDX_IO_PLAY_DMA_START_1);
-               outl(addr_area2, portbase + IDX_IO_PLAY_DMA_START_2);
-               outl(count_areas, portbase + IDX_IO_PLAY_DMA_LEN_1);
+               snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_1, addr);
+               snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_2,
+                                                               addr_area2);
+               snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_LENGTHS,
+                                                               lengths);
                spin_unlock_irqrestore(&chip->reg_lock, flags);
        }
        snd_azf3328_dbgcallleave();
 }
 
 static int
-snd_azf3328_playback_prepare(struct snd_pcm_substream *substream)
+snd_azf3328_codec_prepare(struct snd_pcm_substream *substream)
 {
 #if 0
        struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
@@ -1058,157 +1158,161 @@ snd_azf3328_playback_prepare(struct snd_pcm_substream *substream)
 
        snd_azf3328_dbgcallenter();
 #if 0
-       snd_azf3328_codec_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT,
+       snd_azf3328_codec_setfmt(chip, AZF_CODEC_...,
                runtime->rate,
                snd_pcm_format_width(runtime->format),
                runtime->channels);
-       snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, AZF_PLAYBACK);
+       snd_azf3328_codec_setdmaa(chip, AZF_CODEC_...,
+                                       runtime->dma_addr, count, size);
 #endif
        snd_azf3328_dbgcallleave();
        return 0;
 }
 
 static int
-snd_azf3328_capture_prepare(struct snd_pcm_substream *substream)
-{
-#if 0
-       struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-        unsigned int size = snd_pcm_lib_buffer_bytes(substream);
-       unsigned int count = snd_pcm_lib_period_bytes(substream);
-#endif
-
-       snd_azf3328_dbgcallenter();
-#if 0
-       snd_azf3328_codec_setfmt(chip, IDX_IO_REC_SOUNDFORMAT,
-               runtime->rate,
-               snd_pcm_format_width(runtime->format),
-               runtime->channels);
-       snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, AZF_CAPTURE);
-#endif
-       snd_azf3328_dbgcallleave();
-       return 0;
-}
-
-static int
-snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd)
+snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,
+                       struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
+       const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
        struct snd_pcm_runtime *runtime = substream->runtime;
        int result = 0;
-       unsigned int status1;
-       int previously_muted;
+       u16 flags1;
+       bool previously_muted = 0;
+       bool is_playback_codec = (AZF_CODEC_PLAYBACK == codec_type);
 
-       snd_azf3328_dbgcalls("snd_azf3328_playback_trigger cmd %d\n", cmd);
+       snd_azf3328_dbgcalls("snd_azf3328_codec_trigger cmd %d\n", cmd);
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               snd_azf3328_dbgplay("START PLAYBACK\n");
-
-               /* mute WaveOut (avoid clicking during setup) */
-               previously_muted =
-                       snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
+               snd_azf3328_dbgcodec("START %s\n", codec->name);
+
+               if (is_playback_codec) {
+                       /* mute WaveOut (avoid clicking during setup) */
+                       previously_muted =
+                               snd_azf3328_mixer_set_mute(
+                                               chip, IDX_MIXER_WAVEOUT, 1
+                               );
+               }
 
-               snd_azf3328_codec_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT,
+               snd_azf3328_codec_setfmt(chip, codec_type,
                        runtime->rate,
                        snd_pcm_format_width(runtime->format),
                        runtime->channels);
 
                spin_lock(&chip->reg_lock);
                /* first, remember current value: */
-               status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS);
+               flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS);
 
-               /* stop playback */
-               status1 &= ~DMA_RESUME;
-               snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);
+               /* stop transfer */
+               flags1 &= ~DMA_RESUME;
+               snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
 
                /* FIXME: clear interrupts or what??? */
-               snd_azf3328_codec_outw(chip, IDX_IO_PLAY_IRQTYPE, 0xffff);
+               snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff);
                spin_unlock(&chip->reg_lock);
 
-               snd_azf3328_setdmaa(chip, runtime->dma_addr,
+               snd_azf3328_codec_setdmaa(chip, codec_type, runtime->dma_addr,
                        snd_pcm_lib_period_bytes(substream),
-                       snd_pcm_lib_buffer_bytes(substream),
-                       AZF_PLAYBACK);
+                       snd_pcm_lib_buffer_bytes(substream)
+               );
 
                spin_lock(&chip->reg_lock);
 #ifdef WIN9X
                /* FIXME: enable playback/recording??? */
-               status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2;
-               snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);
+               flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2;
+               snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
 
-               /* start playback again */
+               /* start transfer again */
                /* FIXME: what is this value (0x0010)??? */
-               status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING;
-               snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);
+               flags1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING;
+               snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
 #else /* NT4 */
-               snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,
+               snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
                        0x0000);
-               snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,
-                       DMA_PLAY_SOMETHING1);
-               snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,
-                       DMA_PLAY_SOMETHING1 |
-                       DMA_PLAY_SOMETHING2);
-               snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,
+               snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
+                       DMA_RUN_SOMETHING1);
+               snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
+                       DMA_RUN_SOMETHING1 |
+                       DMA_RUN_SOMETHING2);
+               snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
                        DMA_RESUME |
                        SOMETHING_ALMOST_ALWAYS_SET |
                        DMA_EPILOGUE_SOMETHING |
                        DMA_SOMETHING_ELSE);
 #endif
                spin_unlock(&chip->reg_lock);
-               snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 1);
-
-               /* now unmute WaveOut */
-               if (!previously_muted)
-                       snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0);
+               snd_azf3328_ctrl_codec_activity(chip, codec_type, 1);
+
+               if (is_playback_codec) {
+                       /* now unmute WaveOut */
+                       if (!previously_muted)
+                               snd_azf3328_mixer_set_mute(
+                                               chip, IDX_MIXER_WAVEOUT, 0
+                               );
+               }
 
-               snd_azf3328_dbgplay("STARTED PLAYBACK\n");
+               snd_azf3328_dbgcodec("STARTED %s\n", codec->name);
                break;
        case SNDRV_PCM_TRIGGER_RESUME:
-               snd_azf3328_dbgplay("RESUME PLAYBACK\n");
-               /* resume playback if we were active */
+               snd_azf3328_dbgcodec("RESUME %s\n", codec->name);
+               /* resume codec if we were active */
                spin_lock(&chip->reg_lock);
-               if (chip->audio_stream[AZF_PLAYBACK].running)
-                       snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,
-                               snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | DMA_RESUME);
+               if (codec->running)
+                       snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
+                               snd_azf3328_codec_inw(
+                                       codec, IDX_IO_CODEC_DMA_FLAGS
+                               ) | DMA_RESUME
+                       );
                spin_unlock(&chip->reg_lock);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
-               snd_azf3328_dbgplay("STOP PLAYBACK\n");
-
-               /* mute WaveOut (avoid clicking during setup) */
-               previously_muted =
-                       snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
+               snd_azf3328_dbgcodec("STOP %s\n", codec->name);
+
+               if (is_playback_codec) {
+                       /* mute WaveOut (avoid clicking during setup) */
+                       previously_muted =
+                               snd_azf3328_mixer_set_mute(
+                                               chip, IDX_MIXER_WAVEOUT, 1
+                               );
+               }
 
                spin_lock(&chip->reg_lock);
                /* first, remember current value: */
-               status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS);
+               flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS);
 
-               /* stop playback */
-               status1 &= ~DMA_RESUME;
-               snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);
+               /* stop transfer */
+               flags1 &= ~DMA_RESUME;
+               snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
 
                /* hmm, is this really required? we're resetting the same bit
                 * immediately thereafter... */
-               status1 |= DMA_PLAY_SOMETHING1;
-               snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);
+               flags1 |= DMA_RUN_SOMETHING1;
+               snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
 
-               status1 &= ~DMA_PLAY_SOMETHING1;
-               snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1);
+               flags1 &= ~DMA_RUN_SOMETHING1;
+               snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);
                spin_unlock(&chip->reg_lock);
-               snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 0);
-
-               /* now unmute WaveOut */
-               if (!previously_muted)
-                       snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0);
+               snd_azf3328_ctrl_codec_activity(chip, codec_type, 0);
+
+               if (is_playback_codec) {
+                       /* now unmute WaveOut */
+                       if (!previously_muted)
+                               snd_azf3328_mixer_set_mute(
+                                               chip, IDX_MIXER_WAVEOUT, 0
+                               );
+               }
 
-               snd_azf3328_dbgplay("STOPPED PLAYBACK\n");
+               snd_azf3328_dbgcodec("STOPPED %s\n", codec->name);
                break;
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               snd_azf3328_dbgplay("SUSPEND PLAYBACK\n");
-               /* make sure playback is stopped */
-               snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,
-                       snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) & ~DMA_RESUME);
+               snd_azf3328_dbgcodec("SUSPEND %s\n", codec->name);
+               /* make sure codec is stopped */
+               snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,
+                       snd_azf3328_codec_inw(
+                               codec, IDX_IO_CODEC_DMA_FLAGS
+                       ) & ~DMA_RESUME
+               );
                break;
         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n");
@@ -1217,7 +1321,7 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd)
                snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n");
                 break;
         default:
-               printk(KERN_ERR "FIXME: unknown trigger mode!\n");
+               snd_printk(KERN_ERR "FIXME: unknown trigger mode!\n");
                 return -EINVAL;
        }
 
@@ -1225,172 +1329,74 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd)
        return result;
 }
 
-/* this is just analogous to playback; I'm not quite sure whether recording
- * should actually be triggered like that */
 static int
-snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+snd_azf3328_codec_playback_trigger(struct snd_pcm_substream *substream, int cmd)
 {
-       struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       int result = 0;
-       unsigned int status1;
-
-       snd_azf3328_dbgcalls("snd_azf3328_capture_trigger cmd %d\n", cmd);
-
-        switch (cmd) {
-        case SNDRV_PCM_TRIGGER_START:
-
-               snd_azf3328_dbgplay("START CAPTURE\n");
-
-               snd_azf3328_codec_setfmt(chip, IDX_IO_REC_SOUNDFORMAT,
-                       runtime->rate,
-                       snd_pcm_format_width(runtime->format),
-                       runtime->channels);
-
-               spin_lock(&chip->reg_lock);
-               /* first, remember current value: */
-               status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS);
-
-               /* stop recording */
-               status1 &= ~DMA_RESUME;
-               snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
-
-               /* FIXME: clear interrupts or what??? */
-               snd_azf3328_codec_outw(chip, IDX_IO_REC_IRQTYPE, 0xffff);
-               spin_unlock(&chip->reg_lock);
-
-               snd_azf3328_setdmaa(chip, runtime->dma_addr,
-                       snd_pcm_lib_period_bytes(substream),
-                       snd_pcm_lib_buffer_bytes(substream),
-                       AZF_CAPTURE);
-
-               spin_lock(&chip->reg_lock);
-#ifdef WIN9X
-               /* FIXME: enable playback/recording??? */
-               status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2;
-               snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
-
-               /* start capture again */
-               /* FIXME: what is this value (0x0010)??? */
-               status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING;
-               snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
-#else
-               snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
-                       0x0000);
-               snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
-                       DMA_PLAY_SOMETHING1);
-               snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
-                       DMA_PLAY_SOMETHING1 |
-                       DMA_PLAY_SOMETHING2);
-               snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
-                       DMA_RESUME |
-                       SOMETHING_ALMOST_ALWAYS_SET |
-                       DMA_EPILOGUE_SOMETHING |
-                       DMA_SOMETHING_ELSE);
-#endif
-               spin_unlock(&chip->reg_lock);
-               snd_azf3328_codec_activity(chip, AZF_CAPTURE, 1);
-
-               snd_azf3328_dbgplay("STARTED CAPTURE\n");
-               break;
-       case SNDRV_PCM_TRIGGER_RESUME:
-               snd_azf3328_dbgplay("RESUME CAPTURE\n");
-               /* resume recording if we were active */
-               spin_lock(&chip->reg_lock);
-               if (chip->audio_stream[AZF_CAPTURE].running)
-                       snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
-                               snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) | DMA_RESUME);
-               spin_unlock(&chip->reg_lock);
-               break;
-        case SNDRV_PCM_TRIGGER_STOP:
-               snd_azf3328_dbgplay("STOP CAPTURE\n");
-
-               spin_lock(&chip->reg_lock);
-               /* first, remember current value: */
-               status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS);
-
-               /* stop recording */
-               status1 &= ~DMA_RESUME;
-               snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
-
-               status1 |= DMA_PLAY_SOMETHING1;
-               snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
-
-               status1 &= ~DMA_PLAY_SOMETHING1;
-               snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1);
-               spin_unlock(&chip->reg_lock);
-               snd_azf3328_codec_activity(chip, AZF_CAPTURE, 0);
+       return snd_azf3328_codec_trigger(AZF_CODEC_PLAYBACK, substream, cmd);
+}
 
-               snd_azf3328_dbgplay("STOPPED CAPTURE\n");
-               break;
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-               snd_azf3328_dbgplay("SUSPEND CAPTURE\n");
-               /* make sure recording is stopped */
-               snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
-                       snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) & ~DMA_RESUME);
-               break;
-        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n");
-                break;
-        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n");
-                break;
-        default:
-               printk(KERN_ERR "FIXME: unknown trigger mode!\n");
-                return -EINVAL;
-       }
+static int
+snd_azf3328_codec_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       return snd_azf3328_codec_trigger(AZF_CODEC_CAPTURE, substream, cmd);
+}
 
-       snd_azf3328_dbgcallleave();
-       return result;
+static int
+snd_azf3328_codec_i2s_out_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       return snd_azf3328_codec_trigger(AZF_CODEC_I2S_OUT, substream, cmd);
 }
 
 static snd_pcm_uframes_t
-snd_azf3328_playback_pointer(struct snd_pcm_substream *substream)
+snd_azf3328_codec_pointer(struct snd_pcm_substream *substream,
+                         enum snd_azf3328_codec_type codec_type
+)
 {
-       struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
+       const struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
+       const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];
        unsigned long bufptr, result;
        snd_pcm_uframes_t frmres;
 
 #ifdef QUERY_HARDWARE
-       bufptr = snd_azf3328_codec_inl(chip, IDX_IO_PLAY_DMA_START_1);
+       bufptr = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_START_1);
 #else
        bufptr = substream->runtime->dma_addr;
 #endif
-       result = snd_azf3328_codec_inl(chip, IDX_IO_PLAY_DMA_CURRPOS);
+       result = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_CURRPOS);
 
        /* calculate offset */
        result -= bufptr;
        frmres = bytes_to_frames( substream->runtime, result);
-       snd_azf3328_dbgplay("PLAY @ 0x%8lx, frames %8ld\n", result, frmres);
+       snd_azf3328_dbgcodec("%s @ 0x%8lx, frames %8ld\n",
+                               codec->name, result, frmres);
        return frmres;
 }
 
 static snd_pcm_uframes_t
-snd_azf3328_capture_pointer(struct snd_pcm_substream *substream)
+snd_azf3328_codec_playback_pointer(struct snd_pcm_substream *substream)
 {
-       struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
-       unsigned long bufptr, result;
-       snd_pcm_uframes_t frmres;
+       return snd_azf3328_codec_pointer(substream, AZF_CODEC_PLAYBACK);
+}
 
-#ifdef QUERY_HARDWARE
-       bufptr = snd_azf3328_codec_inl(chip, IDX_IO_REC_DMA_START_1);
-#else
-       bufptr = substream->runtime->dma_addr;
-#endif
-       result = snd_azf3328_codec_inl(chip, IDX_IO_REC_DMA_CURRPOS);
+static snd_pcm_uframes_t
+snd_azf3328_codec_capture_pointer(struct snd_pcm_substream *substream)
+{
+       return snd_azf3328_codec_pointer(substream, AZF_CODEC_CAPTURE);
+}
 
-       /* calculate offset */
-       result -= bufptr;
-       frmres = bytes_to_frames( substream->runtime, result);
-       snd_azf3328_dbgplay("REC  @ 0x%8lx, frames %8ld\n", result, frmres);
-       return frmres;
+static snd_pcm_uframes_t
+snd_azf3328_codec_i2s_out_pointer(struct snd_pcm_substream *substream)
+{
+       return snd_azf3328_codec_pointer(substream, AZF_CODEC_I2S_OUT);
 }
 
 /******************************************************************/
 
 #ifdef SUPPORT_GAMEPORT
 static inline void
-snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip, int enable)
+snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip,
+                               bool enable
+)
 {
        snd_azf3328_io_reg_setb(
                chip->game_io+IDX_GAME_HWCONFIG,
@@ -1400,7 +1406,9 @@ snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip, int enable)
 }
 
 static inline void
-snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip, int enable)
+snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip,
+                                          bool enable
+)
 {
        snd_azf3328_io_reg_setb(
                chip->game_io+IDX_GAME_HWCONFIG,
@@ -1409,10 +1417,27 @@ snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip, int enable)
        );
 }
 
+static void
+snd_azf3328_gameport_set_counter_frequency(struct snd_azf3328 *chip,
+                                          unsigned int freq_cfg
+)
+{
+       snd_azf3328_io_reg_setb(
+               chip->game_io+IDX_GAME_HWCONFIG,
+               0x02,
+               (freq_cfg & 1) != 0
+       );
+       snd_azf3328_io_reg_setb(
+               chip->game_io+IDX_GAME_HWCONFIG,
+               0x04,
+               (freq_cfg & 2) != 0
+       );
+}
+
 static inline void
-snd_azf3328_gameport_axis_circuit_enable(struct snd_azf3328 *chip, int enable)
+snd_azf3328_gameport_axis_circuit_enable(struct snd_azf3328 *chip, bool enable)
 {
-       snd_azf3328_codec_reg_6AH_update(
+       snd_azf3328_ctrl_reg_6AH_update(
                chip, IO_6A_SOMETHING2_GAMEPORT, enable
        );
 }
@@ -1447,6 +1472,8 @@ snd_azf3328_gameport_open(struct gameport *gameport, int mode)
                break;
        }
 
+       snd_azf3328_gameport_set_counter_frequency(chip,
+                               GAME_HWCFG_ADC_COUNTER_FREQ_STD);
        snd_azf3328_gameport_axis_circuit_enable(chip, (res == 0));
 
        return res;
@@ -1458,6 +1485,8 @@ snd_azf3328_gameport_close(struct gameport *gameport)
        struct snd_azf3328 *chip = gameport_get_port_data(gameport);
 
        snd_azf3328_dbggame("gameport_close\n");
+       snd_azf3328_gameport_set_counter_frequency(chip,
+                               GAME_HWCFG_ADC_COUNTER_FREQ_1_200);
        snd_azf3328_gameport_axis_circuit_enable(chip, 0);
 }
 
@@ -1491,7 +1520,7 @@ snd_azf3328_gameport_cooked_read(struct gameport *gameport,
 
        val = snd_azf3328_game_inb(chip, IDX_GAME_AXES_CONFIG);
        if (val & GAME_AXES_SAMPLING_READY) {
-               for (i = 0; i < 4; ++i) {
+               for (i = 0; i < ARRAY_SIZE(chip->axes); ++i) {
                        /* configure the axis to read */
                        val = (i << 4) | 0x0f;
                        snd_azf3328_game_outb(chip, IDX_GAME_AXES_CONFIG, val);
@@ -1514,7 +1543,7 @@ snd_azf3328_gameport_cooked_read(struct gameport *gameport,
        snd_azf3328_game_outw(chip, IDX_GAME_AXIS_VALUE, 0xffff);
        spin_unlock_irqrestore(&chip->reg_lock, flags);
 
-       for (i = 0; i < 4; i++) {
+       for (i = 0; i < ARRAY_SIZE(chip->axes); i++) {
                axes[i] = chip->axes[i];
                if (axes[i] == 0xffff)
                        axes[i] = -1;
@@ -1552,6 +1581,8 @@ snd_azf3328_gameport(struct snd_azf3328 *chip, int dev)
        /* DISABLE legacy address: we don't need it! */
        snd_azf3328_gameport_legacy_address_enable(chip, 0);
 
+       snd_azf3328_gameport_set_counter_frequency(chip,
+                               GAME_HWCFG_ADC_COUNTER_FREQ_1_200);
        snd_azf3328_gameport_axis_circuit_enable(chip, 0);
 
        gameport_register_port(chip->gameport);
@@ -1585,40 +1616,77 @@ snd_azf3328_gameport_interrupt(struct snd_azf3328 *chip)
 static inline void
 snd_azf3328_irq_log_unknown_type(u8 which)
 {
-       snd_azf3328_dbgplay(
+       snd_azf3328_dbgcodec(
        "azt3328: unknown IRQ type (%x) occurred, please report!\n",
                which
        );
 }
 
+static inline void
+snd_azf3328_codec_interrupt(struct snd_azf3328 *chip, u8 status)
+{
+       u8 which;
+       enum snd_azf3328_codec_type codec_type;
+       const struct snd_azf3328_codec_data *codec;
+
+       for (codec_type = AZF_CODEC_PLAYBACK;
+                codec_type <= AZF_CODEC_I2S_OUT;
+                        ++codec_type) {
+
+               /* skip codec if there's no interrupt for it */
+               if (!(status & (1 << codec_type)))
+                       continue;
+
+               codec = &chip->codecs[codec_type];
+
+               spin_lock(&chip->reg_lock);
+               which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE);
+               /* ack all IRQ types immediately */
+               snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which);
+               spin_unlock(&chip->reg_lock);
+
+               if ((chip->pcm[codec_type]) && (codec->substream)) {
+                       snd_pcm_period_elapsed(codec->substream);
+                       snd_azf3328_dbgcodec("%s period done (#%x), @ %x\n",
+                               codec->name,
+                               which,
+                               snd_azf3328_codec_inl(
+                                       codec, IDX_IO_CODEC_DMA_CURRPOS
+                               )
+                       );
+               } else
+                       printk(KERN_WARNING "azt3328: irq handler problem!\n");
+               if (which & IRQ_SOMETHING)
+                       snd_azf3328_irq_log_unknown_type(which);
+       }
+}
+
 static irqreturn_t
 snd_azf3328_interrupt(int irq, void *dev_id)
 {
        struct snd_azf3328 *chip = dev_id;
-       u8 status, which;
-#if DEBUG_PLAY_REC
+       u8 status;
+#if DEBUG_CODEC
        static unsigned long irq_count;
 #endif
 
-       status = snd_azf3328_codec_inb(chip, IDX_IO_IRQSTATUS);
+       status = snd_azf3328_ctrl_inb(chip, IDX_IO_IRQSTATUS);
 
         /* fast path out, to ease interrupt sharing */
        if (!(status &
-               (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_GAMEPORT|IRQ_MPU401|IRQ_TIMER)
+               (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT
+               |IRQ_GAMEPORT|IRQ_MPU401|IRQ_TIMER)
        ))
                return IRQ_NONE; /* must be interrupt for another device */
 
-       snd_azf3328_dbgplay(
-               "irq_count %ld! IDX_IO_PLAY_FLAGS %04x, "
-               "IDX_IO_PLAY_IRQTYPE %04x, IDX_IO_IRQSTATUS %04x\n",
+       snd_azf3328_dbgcodec(
+               "irq_count %ld! IDX_IO_IRQSTATUS %04x\n",
                        irq_count++ /* debug-only */,
-                       snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS),
-                       snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE),
                        status
        );
 
        if (status & IRQ_TIMER) {
-               /* snd_azf3328_dbgplay("timer %ld\n",
+               /* snd_azf3328_dbgcodec("timer %ld\n",
                        snd_azf3328_codec_inl(chip, IDX_IO_TIMER_VALUE)
                                & TIMER_VALUE_MASK
                ); */
@@ -1626,71 +1694,36 @@ snd_azf3328_interrupt(int irq, void *dev_id)
                        snd_timer_interrupt(chip->timer, chip->timer->sticks);
                /* ACK timer */
                 spin_lock(&chip->reg_lock);
-               snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07);
+               snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07);
                spin_unlock(&chip->reg_lock);
-               snd_azf3328_dbgplay("azt3328: timer IRQ\n");
+               snd_azf3328_dbgcodec("azt3328: timer IRQ\n");
        }
-       if (status & IRQ_PLAYBACK) {
-               spin_lock(&chip->reg_lock);
-               which = snd_azf3328_codec_inb(chip, IDX_IO_PLAY_IRQTYPE);
-               /* ack all IRQ types immediately */
-               snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which);
-                       spin_unlock(&chip->reg_lock);
 
-               if (chip->pcm && chip->audio_stream[AZF_PLAYBACK].substream) {
-                       snd_pcm_period_elapsed(
-                               chip->audio_stream[AZF_PLAYBACK].substream
-                       );
-                       snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n",
-                               which,
-                               snd_azf3328_codec_inl(
-                                       chip, IDX_IO_PLAY_DMA_CURRPOS
-                               )
-                       );
-               } else
-                       printk(KERN_WARNING "azt3328: irq handler problem!\n");
-               if (which & IRQ_PLAY_SOMETHING)
-                       snd_azf3328_irq_log_unknown_type(which);
-       }
-       if (status & IRQ_RECORDING) {
-                spin_lock(&chip->reg_lock);
-               which = snd_azf3328_codec_inb(chip, IDX_IO_REC_IRQTYPE);
-               /* ack all IRQ types immediately */
-               snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which);
-               spin_unlock(&chip->reg_lock);
+       if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT))
+               snd_azf3328_codec_interrupt(chip, status);
 
-               if (chip->pcm && chip->audio_stream[AZF_CAPTURE].substream) {
-                       snd_pcm_period_elapsed(
-                               chip->audio_stream[AZF_CAPTURE].substream
-                       );
-                       snd_azf3328_dbgplay("REC  period done (#%x), @ %x\n",
-                               which,
-                               snd_azf3328_codec_inl(
-                                       chip, IDX_IO_REC_DMA_CURRPOS
-                               )
-                       );
-               } else
-                       printk(KERN_WARNING "azt3328: irq handler problem!\n");
-               if (which & IRQ_REC_SOMETHING)
-                       snd_azf3328_irq_log_unknown_type(which);
-       }
        if (status & IRQ_GAMEPORT)
                snd_azf3328_gameport_interrupt(chip);
+
        /* MPU401 has less critical IRQ requirements
         * than timer and playback/recording, right? */
        if (status & IRQ_MPU401) {
                snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data);
 
                /* hmm, do we have to ack the IRQ here somehow?
-                * If so, then I don't know how... */
-               snd_azf3328_dbgplay("azt3328: MPU401 IRQ\n");
+                * If so, then I don't know how yet... */
+               snd_azf3328_dbgcodec("azt3328: MPU401 IRQ\n");
        }
        return IRQ_HANDLED;
 }
 
 /*****************************************************************/
 
-static const struct snd_pcm_hardware snd_azf3328_playback =
+/* as long as we think we have identical snd_pcm_hardware parameters
+   for playback, capture and i2s out, we can use the same physical struct
+   since the struct is simply being copied into a member.
+*/
+static const struct snd_pcm_hardware snd_azf3328_hardware =
 {
        /* FIXME!! Correct? */
        .info =                 SNDRV_PCM_INFO_MMAP |
@@ -1718,31 +1751,6 @@ static const struct snd_pcm_hardware snd_azf3328_playback =
        .fifo_size =            0,
 };
 
-static const struct snd_pcm_hardware snd_azf3328_capture =
-{
-       /* FIXME */
-       .info =                 SNDRV_PCM_INFO_MMAP |
-                               SNDRV_PCM_INFO_INTERLEAVED |
-                               SNDRV_PCM_INFO_MMAP_VALID,
-       .formats =              SNDRV_PCM_FMTBIT_S8 |
-                               SNDRV_PCM_FMTBIT_U8 |
-                               SNDRV_PCM_FMTBIT_S16_LE |
-                               SNDRV_PCM_FMTBIT_U16_LE,
-       .rates =                SNDRV_PCM_RATE_5512 |
-                               SNDRV_PCM_RATE_8000_48000 |
-                               SNDRV_PCM_RATE_KNOT,
-       .rate_min =             AZF_FREQ_4000,
-       .rate_max =             AZF_FREQ_66200,
-       .channels_min =         1,
-       .channels_max =         2,
-       .buffer_bytes_max =     65536,
-       .period_bytes_min =     64,
-       .period_bytes_max =     65536,
-       .periods_min =          1,
-       .periods_max =          1024,
-       .fifo_size =            0,
-};
-
 
 static unsigned int snd_azf3328_fixed_rates[] = {
        AZF_FREQ_4000,
@@ -1770,55 +1778,72 @@ static struct snd_pcm_hw_constraint_list snd_azf3328_hw_constraints_rates = {
 /*****************************************************************/
 
 static int
-snd_azf3328_playback_open(struct snd_pcm_substream *substream)
+snd_azf3328_pcm_open(struct snd_pcm_substream *substream,
+                    enum snd_azf3328_codec_type codec_type
+)
 {
        struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
 
        snd_azf3328_dbgcallenter();
-       chip->audio_stream[AZF_PLAYBACK].substream = substream;
-       runtime->hw = snd_azf3328_playback;
+       chip->codecs[codec_type].substream = substream;
+
+       /* same parameters for all our codecs - at least we think so... */
+       runtime->hw = snd_azf3328_hardware;
+
        snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
                                   &snd_azf3328_hw_constraints_rates);
        snd_azf3328_dbgcallleave();
        return 0;
 }
 
+static int
+snd_azf3328_playback_open(struct snd_pcm_substream *substream)
+{
+       return snd_azf3328_pcm_open(substream, AZF_CODEC_PLAYBACK);
+}
+
 static int
 snd_azf3328_capture_open(struct snd_pcm_substream *substream)
 {
-       struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
+       return snd_azf3328_pcm_open(substream, AZF_CODEC_CAPTURE);
+}
 
-       snd_azf3328_dbgcallenter();
-       chip->audio_stream[AZF_CAPTURE].substream = substream;
-       runtime->hw = snd_azf3328_capture;
-       snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
-                                  &snd_azf3328_hw_constraints_rates);
-       snd_azf3328_dbgcallleave();
-       return 0;
+static int
+snd_azf3328_i2s_out_open(struct snd_pcm_substream *substream)
+{
+       return snd_azf3328_pcm_open(substream, AZF_CODEC_I2S_OUT);
 }
 
 static int
-snd_azf3328_playback_close(struct snd_pcm_substream *substream)
+snd_azf3328_pcm_close(struct snd_pcm_substream *substream,
+                     enum snd_azf3328_codec_type codec_type
+)
 {
        struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
 
        snd_azf3328_dbgcallenter();
-       chip->audio_stream[AZF_PLAYBACK].substream = NULL;
+       chip->codecs[codec_type].substream = NULL;
        snd_azf3328_dbgcallleave();
        return 0;
 }
 
+static int
+snd_azf3328_playback_close(struct snd_pcm_substream *substream)
+{
+       return snd_azf3328_pcm_close(substream, AZF_CODEC_PLAYBACK);
+}
+
 static int
 snd_azf3328_capture_close(struct snd_pcm_substream *substream)
 {
-       struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
+       return snd_azf3328_pcm_close(substream, AZF_CODEC_CAPTURE);
+}
 
-       snd_azf3328_dbgcallenter();
-       chip->audio_stream[AZF_CAPTURE].substream = NULL;
-       snd_azf3328_dbgcallleave();
-       return 0;
+static int
+snd_azf3328_i2s_out_close(struct snd_pcm_substream *substream)
+{
+       return snd_azf3328_pcm_close(substream, AZF_CODEC_I2S_OUT);
 }
 
 /******************************************************************/
@@ -1829,9 +1854,9 @@ static struct snd_pcm_ops snd_azf3328_playback_ops = {
        .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_azf3328_hw_params,
        .hw_free =      snd_azf3328_hw_free,
-       .prepare =      snd_azf3328_playback_prepare,
-       .trigger =      snd_azf3328_playback_trigger,
-       .pointer =      snd_azf3328_playback_pointer
+       .prepare =      snd_azf3328_codec_prepare,
+       .trigger =      snd_azf3328_codec_playback_trigger,
+       .pointer =      snd_azf3328_codec_playback_pointer
 };
 
 static struct snd_pcm_ops snd_azf3328_capture_ops = {
@@ -1840,30 +1865,67 @@ static struct snd_pcm_ops snd_azf3328_capture_ops = {
        .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_azf3328_hw_params,
        .hw_free =      snd_azf3328_hw_free,
-       .prepare =      snd_azf3328_capture_prepare,
-       .trigger =      snd_azf3328_capture_trigger,
-       .pointer =      snd_azf3328_capture_pointer
+       .prepare =      snd_azf3328_codec_prepare,
+       .trigger =      snd_azf3328_codec_capture_trigger,
+       .pointer =      snd_azf3328_codec_capture_pointer
+};
+
+static struct snd_pcm_ops snd_azf3328_i2s_out_ops = {
+       .open =         snd_azf3328_i2s_out_open,
+       .close =        snd_azf3328_i2s_out_close,
+       .ioctl =        snd_pcm_lib_ioctl,
+       .hw_params =    snd_azf3328_hw_params,
+       .hw_free =      snd_azf3328_hw_free,
+       .prepare =      snd_azf3328_codec_prepare,
+       .trigger =      snd_azf3328_codec_i2s_out_trigger,
+       .pointer =      snd_azf3328_codec_i2s_out_pointer
 };
 
 static int __devinit
-snd_azf3328_pcm(struct snd_azf3328 *chip, int device)
+snd_azf3328_pcm(struct snd_azf3328 *chip)
 {
+enum { AZF_PCMDEV_STD, AZF_PCMDEV_I2S_OUT, NUM_AZF_PCMDEVS }; /* pcm devices */
+
        struct snd_pcm *pcm;
        int err;
 
        snd_azf3328_dbgcallenter();
-       if ((err = snd_pcm_new(chip->card, "AZF3328 DSP", device, 1, 1, &pcm)) < 0)
+
+       err = snd_pcm_new(chip->card, "AZF3328 DSP", AZF_PCMDEV_STD,
+                                                               1, 1, &pcm);
+       if (err < 0)
                return err;
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_azf3328_playback_ops);
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_azf3328_capture_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                                               &snd_azf3328_playback_ops);
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                                               &snd_azf3328_capture_ops);
 
        pcm->private_data = chip;
        pcm->info_flags = 0;
        strcpy(pcm->name, chip->card->shortname);
-       chip->pcm = pcm;
+       /* same pcm object for playback/capture (see snd_pcm_new() above) */
+       chip->pcm[AZF_CODEC_PLAYBACK] = pcm;
+       chip->pcm[AZF_CODEC_CAPTURE] = pcm;
 
        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             snd_dma_pci_data(chip->pci), 64*1024, 64*1024);
+                                               snd_dma_pci_data(chip->pci),
+                                                       64*1024, 64*1024);
+
+       err = snd_pcm_new(chip->card, "AZF3328 I2S OUT", AZF_PCMDEV_I2S_OUT,
+                                                               1, 0, &pcm);
+       if (err < 0)
+               return err;
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                                               &snd_azf3328_i2s_out_ops);
+
+       pcm->private_data = chip;
+       pcm->info_flags = 0;
+       strcpy(pcm->name, chip->card->shortname);
+       chip->pcm[AZF_CODEC_I2S_OUT] = pcm;
+
+       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                               snd_dma_pci_data(chip->pci),
+                                                       64*1024, 64*1024);
 
        snd_azf3328_dbgcallleave();
        return 0;
@@ -1902,7 +1964,7 @@ snd_azf3328_timer_start(struct snd_timer *timer)
        snd_azf3328_dbgtimer("setting timer countdown value %d, add COUNTDOWN|IRQ\n", delay);
        delay |= TIMER_COUNTDOWN_ENABLE | TIMER_IRQ_ENABLE;
        spin_lock_irqsave(&chip->reg_lock, flags);
-       snd_azf3328_codec_outl(chip, IDX_IO_TIMER_VALUE, delay);
+       snd_azf3328_ctrl_outl(chip, IDX_IO_TIMER_VALUE, delay);
        spin_unlock_irqrestore(&chip->reg_lock, flags);
        snd_azf3328_dbgcallleave();
        return 0;
@@ -1919,7 +1981,7 @@ snd_azf3328_timer_stop(struct snd_timer *timer)
        spin_lock_irqsave(&chip->reg_lock, flags);
        /* disable timer countdown and interrupt */
        /* FIXME: should we write TIMER_IRQ_ACK here? */
-       snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0);
+       snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0);
        spin_unlock_irqrestore(&chip->reg_lock, flags);
        snd_azf3328_dbgcallleave();
        return 0;
@@ -2035,7 +2097,7 @@ snd_azf3328_test_bit(unsigned unsigned reg, int bit)
 
        outb(val, reg);
 
-       printk(KERN_ERR "reg %04x bit %d: %02x %02x %02x\n",
+       printk(KERN_DEBUG "reg %04x bit %d: %02x %02x %02x\n",
                                reg, bit, val, valoff, valon
        );
 }
@@ -2048,9 +2110,9 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
        u16 tmp;
 
        snd_azf3328_dbgmisc(
-               "codec_io 0x%lx, game_io 0x%lx, mpu_io 0x%lx, "
+               "ctrl_io 0x%lx, game_io 0x%lx, mpu_io 0x%lx, "
                "opl3_io 0x%lx, mixer_io 0x%lx, irq %d\n",
-               chip->codec_io, chip->game_io, chip->mpu_io,
+               chip->ctrl_io, chip->game_io, chip->mpu_io,
                chip->opl3_io, chip->mixer_io, chip->irq
        );
 
@@ -2083,9 +2145,9 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
                                inb(0x38c + tmp)
                );
 
-       for (tmp = 0; tmp < AZF_IO_SIZE_CODEC; tmp += 2)
-               snd_azf3328_dbgmisc("codec 0x%02x: 0x%04x\n",
-                       tmp, snd_azf3328_codec_inw(chip, tmp)
+       for (tmp = 0; tmp < AZF_IO_SIZE_CTRL; tmp += 2)
+               snd_azf3328_dbgmisc("ctrl 0x%02x: 0x%04x\n",
+                       tmp, snd_azf3328_ctrl_inw(chip, tmp)
                );
 
        for (tmp = 0; tmp < AZF_IO_SIZE_MIXER; tmp += 2)
@@ -2106,7 +2168,8 @@ snd_azf3328_create(struct snd_card *card,
        static struct snd_device_ops ops = {
                .dev_free =     snd_azf3328_dev_free,
        };
-       u16 tmp;
+       u8 dma_init;
+       enum snd_azf3328_codec_type codec_type;
 
        *rchip = NULL;
 
@@ -2138,14 +2201,21 @@ snd_azf3328_create(struct snd_card *card,
        if (err < 0)
                goto out_err;
 
-       chip->codec_io = pci_resource_start(pci, 0);
+       chip->ctrl_io  = pci_resource_start(pci, 0);
        chip->game_io  = pci_resource_start(pci, 1);
        chip->mpu_io   = pci_resource_start(pci, 2);
-       chip->opl3_io = pci_resource_start(pci, 3);
+       chip->opl3_io  = pci_resource_start(pci, 3);
        chip->mixer_io = pci_resource_start(pci, 4);
 
-       chip->audio_stream[AZF_PLAYBACK].portbase = chip->codec_io + 0x00;
-       chip->audio_stream[AZF_CAPTURE].portbase   = chip->codec_io + 0x20;
+       chip->codecs[AZF_CODEC_PLAYBACK].io_base =
+                               chip->ctrl_io + AZF_IO_OFFS_CODEC_PLAYBACK;
+       chip->codecs[AZF_CODEC_PLAYBACK].name = "PLAYBACK";
+       chip->codecs[AZF_CODEC_CAPTURE].io_base =
+                               chip->ctrl_io + AZF_IO_OFFS_CODEC_CAPTURE;
+       chip->codecs[AZF_CODEC_CAPTURE].name = "CAPTURE";
+       chip->codecs[AZF_CODEC_I2S_OUT].io_base =
+                               chip->ctrl_io + AZF_IO_OFFS_CODEC_I2S_OUT;
+       chip->codecs[AZF_CODEC_I2S_OUT].name = "I2S_OUT";
 
        if (request_irq(pci->irq, snd_azf3328_interrupt,
                        IRQF_SHARED, card->shortname, chip)) {
@@ -2168,20 +2238,25 @@ snd_azf3328_create(struct snd_card *card,
        if (err < 0)
                goto out_err;
 
-       /* shutdown codecs to save power */
-               /* have snd_azf3328_codec_activity() act properly */
-       chip->audio_stream[AZF_PLAYBACK].running = 1;
-       snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 0);
+       /* standard codec init stuff */
+               /* default DMA init value */
+       dma_init = DMA_RUN_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE;
 
-       /* standard chip init stuff */
-               /* default IRQ init value */
-       tmp = DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE;
+       for (codec_type = AZF_CODEC_PLAYBACK;
+               codec_type <= AZF_CODEC_I2S_OUT; ++codec_type) {
+               struct snd_azf3328_codec_data *codec =
+                        &chip->codecs[codec_type];
 
-       spin_lock_irq(&chip->reg_lock);
-       snd_azf3328_codec_outb(chip, IDX_IO_PLAY_FLAGS, tmp);
-       snd_azf3328_codec_outb(chip, IDX_IO_REC_FLAGS, tmp);
-       snd_azf3328_codec_outb(chip, IDX_IO_SOMETHING_FLAGS, tmp);
-       spin_unlock_irq(&chip->reg_lock);
+               /* shutdown codecs to save power */
+                       /* have ...ctrl_codec_activity() act properly */
+               codec->running = 1;
+               snd_azf3328_ctrl_codec_activity(chip, codec_type, 0);
+
+               spin_lock_irq(&chip->reg_lock);
+               snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS,
+                                                dma_init);
+               spin_unlock_irq(&chip->reg_lock);
+       }
 
        snd_card_set_dev(card, &pci->dev);
 
@@ -2229,8 +2304,11 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 
        card->private_data = chip;
 
+       /* chose to use MPU401_HW_AZT2320 ID instead of MPU401_HW_MPU401,
+          since our hardware ought to be similar, thus use same ID. */
        err = snd_mpu401_uart_new(
-               card, 0, MPU401_HW_MPU401, chip->mpu_io, MPU401_INFO_INTEGRATED,
+               card, 0,
+               MPU401_HW_AZT2320, chip->mpu_io, MPU401_INFO_INTEGRATED,
                pci->irq, 0, &chip->rmidi
        );
        if (err < 0) {
@@ -2244,7 +2322,7 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        if (err < 0)
                goto out_err;
 
-       err = snd_azf3328_pcm(chip, 0);
+       err = snd_azf3328_pcm(chip);
        if (err < 0)
                goto out_err;
 
@@ -2266,14 +2344,14 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
        opl3->private_data = chip;
 
        sprintf(card->longname, "%s at 0x%lx, irq %i",
-               card->shortname, chip->codec_io, chip->irq);
+               card->shortname, chip->ctrl_io, chip->irq);
 
        err = snd_card_register(card);
        if (err < 0)
                goto out_err;
 
 #ifdef MODULE
-       printk(
+       printk(KERN_INFO
 "azt3328: Sound driver for Aztech AZF3328-based soundcards such as PCI168.\n"
 "azt3328: Hardware was completely undocumented, unfortunately.\n"
 "azt3328: Feel free to contact andi AT lisas.de for bug reports etc.!\n"
@@ -2308,36 +2386,52 @@ snd_azf3328_remove(struct pci_dev *pci)
 }
 
 #ifdef CONFIG_PM
+static inline void
+snd_azf3328_suspend_regs(unsigned long io_addr, unsigned count, u32 *saved_regs)
+{
+       unsigned reg;
+
+       for (reg = 0; reg < count; ++reg) {
+               *saved_regs = inl(io_addr);
+               snd_azf3328_dbgpm("suspend: io 0x%04lx: 0x%08x\n",
+                       io_addr, *saved_regs);
+               ++saved_regs;
+               io_addr += sizeof(*saved_regs);
+       }
+}
+
 static int
 snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
 {
        struct snd_card *card = pci_get_drvdata(pci);
        struct snd_azf3328 *chip = card->private_data;
-       unsigned reg;
+       u16 *saved_regs_ctrl_u16;
 
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 
-       snd_pcm_suspend_all(chip->pcm);
+       snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]);
+       snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]);
 
-       for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg)
-               chip->saved_regs_mixer[reg] = inw(chip->mixer_io + reg * 2);
+       snd_azf3328_suspend_regs(chip->mixer_io,
+               ARRAY_SIZE(chip->saved_regs_mixer), chip->saved_regs_mixer);
 
        /* make sure to disable master volume etc. to prevent looping sound */
        snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1);
        snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
 
-       for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; ++reg)
-               chip->saved_regs_codec[reg] = inw(chip->codec_io + reg * 2);
+       snd_azf3328_suspend_regs(chip->ctrl_io,
+               ARRAY_SIZE(chip->saved_regs_ctrl), chip->saved_regs_ctrl);
 
        /* manually store the one currently relevant write-only reg, too */
-       chip->saved_regs_codec[IDX_IO_6AH / 2] = chip->shadow_reg_codec_6AH;
+       saved_regs_ctrl_u16 = (u16 *)chip->saved_regs_ctrl;
+       saved_regs_ctrl_u16[IDX_IO_6AH / 2] = chip->shadow_reg_ctrl_6AH;
 
-       for (reg = 0; reg < AZF_IO_SIZE_GAME_PM / 2; ++reg)
-               chip->saved_regs_game[reg] = inw(chip->game_io + reg * 2);
-       for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; ++reg)
-               chip->saved_regs_mpu[reg] = inw(chip->mpu_io + reg * 2);
-       for (reg = 0; reg < AZF_IO_SIZE_OPL3_PM / 2; ++reg)
-               chip->saved_regs_opl3[reg] = inw(chip->opl3_io + reg * 2);
+       snd_azf3328_suspend_regs(chip->game_io,
+               ARRAY_SIZE(chip->saved_regs_game), chip->saved_regs_game);
+       snd_azf3328_suspend_regs(chip->mpu_io,
+               ARRAY_SIZE(chip->saved_regs_mpu), chip->saved_regs_mpu);
+       snd_azf3328_suspend_regs(chip->opl3_io,
+               ARRAY_SIZE(chip->saved_regs_opl3), chip->saved_regs_opl3);
 
        pci_disable_device(pci);
        pci_save_state(pci);
@@ -2345,12 +2439,28 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
        return 0;
 }
 
+static inline void
+snd_azf3328_resume_regs(const u32 *saved_regs,
+                       unsigned long io_addr,
+                       unsigned count
+)
+{
+       unsigned reg;
+
+       for (reg = 0; reg < count; ++reg) {
+               outl(*saved_regs, io_addr);
+               snd_azf3328_dbgpm("resume: io 0x%04lx: 0x%08x --> 0x%08x\n",
+                       io_addr, *saved_regs, inl(io_addr));
+               ++saved_regs;
+               io_addr += sizeof(*saved_regs);
+       }
+}
+
 static int
 snd_azf3328_resume(struct pci_dev *pci)
 {
        struct snd_card *card = pci_get_drvdata(pci);
-       struct snd_azf3328 *chip = card->private_data;
-       unsigned reg;
+       const struct snd_azf3328 *chip = card->private_data;
 
        pci_set_power_state(pci, PCI_D0);
        pci_restore_state(pci);
@@ -2362,16 +2472,24 @@ snd_azf3328_resume(struct pci_dev *pci)
        }
        pci_set_master(pci);
 
-       for (reg = 0; reg < AZF_IO_SIZE_GAME_PM / 2; ++reg)
-               outw(chip->saved_regs_game[reg], chip->game_io + reg * 2);
-       for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; ++reg)
-               outw(chip->saved_regs_mpu[reg], chip->mpu_io + reg * 2);
-       for (reg = 0; reg < AZF_IO_SIZE_OPL3_PM / 2; ++reg)
-               outw(chip->saved_regs_opl3[reg], chip->opl3_io + reg * 2);
-       for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg)
-               outw(chip->saved_regs_mixer[reg], chip->mixer_io + reg * 2);
-       for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; ++reg)
-               outw(chip->saved_regs_codec[reg], chip->codec_io + reg * 2);
+       snd_azf3328_resume_regs(chip->saved_regs_game, chip->game_io,
+                                       ARRAY_SIZE(chip->saved_regs_game));
+       snd_azf3328_resume_regs(chip->saved_regs_mpu, chip->mpu_io,
+                                       ARRAY_SIZE(chip->saved_regs_mpu));
+       snd_azf3328_resume_regs(chip->saved_regs_opl3, chip->opl3_io,
+                                       ARRAY_SIZE(chip->saved_regs_opl3));
+
+       snd_azf3328_resume_regs(chip->saved_regs_mixer, chip->mixer_io,
+                                       ARRAY_SIZE(chip->saved_regs_mixer));
+
+       /* unfortunately with 32bit transfers, IDX_MIXER_PLAY_MASTER (0x02)
+          and IDX_MIXER_RESET (offset 0x00) get touched at the same time,
+          resulting in a mixer reset condition persisting until _after_
+          master vol was restored. Thus master vol needs an extra restore. */
+       outw(((u16 *)chip->saved_regs_mixer)[1], chip->mixer_io + 2);
+
+       snd_azf3328_resume_regs(chip->saved_regs_ctrl, chip->ctrl_io,
+                                       ARRAY_SIZE(chip->saved_regs_ctrl));
 
        snd_power_change_state(card, SNDRV_CTL_POWER_D0);
        return 0;
index 974e05122f005f6d23d70fb1f593a94c017b0081..6f46b97650cca39d45beaaa40680123b40f9bfb3 100644 (file)
@@ -6,50 +6,59 @@
 
 /*** main I/O area port indices ***/
 /* (only 0x70 of 0x80 bytes saved/restored by Windows driver) */
-#define AZF_IO_SIZE_CODEC      0x80
-#define AZF_IO_SIZE_CODEC_PM   0x70
+#define AZF_IO_SIZE_CTRL       0x80
+#define AZF_IO_SIZE_CTRL_PM    0x70
 
-/* the driver initialisation suggests a layout of 4 main areas:
- * from 0x00 (playback), from 0x20 (recording) and from 0x40 (maybe MPU401??).
+/* the driver initialisation suggests a layout of 4 areas
+ * within the main card control I/O:
+ * from 0x00 (playback codec), from 0x20 (recording codec)
+ * and from 0x40 (most certainly I2S out codec).
  * And another area from 0x60 to 0x6f (DirectX timer, IRQ management,
  * power management etc.???). */
 
-/** playback area **/
-#define IDX_IO_PLAY_FLAGS       0x00 /* PU:0x0000 */
+#define AZF_IO_OFFS_CODEC_PLAYBACK     0x00
+#define AZF_IO_OFFS_CODEC_CAPTURE      0x20
+#define AZF_IO_OFFS_CODEC_I2S_OUT      0x40
+
+#define IDX_IO_CODEC_DMA_FLAGS       0x00 /* PU:0x0000 */
      /* able to reactivate output after output muting due to 8/16bit
       * output change, just like 0x0002.
       * 0x0001 is the only bit that's able to start the DMA counter */
-  #define DMA_RESUME                   0x0001 /* paused if cleared ? */
+  #define DMA_RESUME                   0x0001 /* paused if cleared? */
      /* 0x0002 *temporarily* set during DMA stopping. hmm
       * both 0x0002 and 0x0004 set in playback setup. */
      /* able to reactivate output after output muting due to 8/16bit
       * output change, just like 0x0001. */
-  #define DMA_PLAY_SOMETHING1          0x0002 /* \ alternated (toggled) */
+  #define DMA_RUN_SOMETHING1           0x0002 /* \ alternated (toggled) */
      /* 0x0004: NOT able to reactivate output */
-  #define DMA_PLAY_SOMETHING2          0x0004 /* / bits */
+  #define DMA_RUN_SOMETHING2           0x0004 /* / bits */
   #define SOMETHING_ALMOST_ALWAYS_SET  0x0008 /* ???; can be modified */
   #define DMA_EPILOGUE_SOMETHING       0x0010
   #define DMA_SOMETHING_ELSE           0x0020 /* ??? */
-  #define SOMETHING_UNMODIFIABLE       0xffc0 /* unused ? not modifiable */
-#define IDX_IO_PLAY_IRQTYPE     0x02 /* PU:0x0001 */
+  #define SOMETHING_UNMODIFIABLE       0xffc0 /* unused? not modifiable */
+#define IDX_IO_CODEC_IRQTYPE     0x02 /* PU:0x0001 */
   /* write back to flags in case flags are set, in order to ACK IRQ in handler
    * (bit 1 of port 0x64 indicates interrupt for one of these three types)
    * sometimes in this case it just writes 0xffff to globally ACK all IRQs
    * settings written are not reflected when reading back, though.
-   * seems to be IRQ, too (frequently used: port |= 0x07 !), but who knows ? */
-  #define IRQ_PLAY_SOMETHING           0x0001 /* something & ACK */
-  #define IRQ_FINISHED_PLAYBUF_1       0x0002 /* 1st dmabuf finished & ACK */
-  #define IRQ_FINISHED_PLAYBUF_2       0x0004 /* 2nd dmabuf finished & ACK */
+   * seems to be IRQ, too (frequently used: port |= 0x07 !), but who knows? */
+  #define IRQ_SOMETHING                        0x0001 /* something & ACK */
+  #define IRQ_FINISHED_DMABUF_1                0x0002 /* 1st dmabuf finished & ACK */
+  #define IRQ_FINISHED_DMABUF_2                0x0004 /* 2nd dmabuf finished & ACK */
   #define IRQMASK_SOME_STATUS_1                0x0008 /* \ related bits */
   #define IRQMASK_SOME_STATUS_2                0x0010 /* / (checked together in loop) */
-  #define IRQMASK_UNMODIFIABLE         0xffe0 /* unused ? not modifiable */
-#define IDX_IO_PLAY_DMA_START_1 0x04 /* start address of 1st DMA play area, PU:0x00000000 */
-#define IDX_IO_PLAY_DMA_START_2 0x08 /* start address of 2nd DMA play area, PU:0x00000000 */
-#define IDX_IO_PLAY_DMA_LEN_1   0x0c /* length of 1st DMA play area, PU:0x0000 */
-#define IDX_IO_PLAY_DMA_LEN_2   0x0e /* length of 2nd DMA play area, PU:0x0000 */
-#define IDX_IO_PLAY_DMA_CURRPOS 0x10 /* current DMA position, PU:0x00000000 */
-#define IDX_IO_PLAY_DMA_CURROFS        0x14 /* offset within current DMA play area, PU:0x0000 */
-#define IDX_IO_PLAY_SOUNDFORMAT 0x16 /* PU:0x0010 */
+  #define IRQMASK_UNMODIFIABLE         0xffe0 /* unused? not modifiable */
+  /* start address of 1st DMA transfer area, PU:0x00000000 */
+#define IDX_IO_CODEC_DMA_START_1 0x04
+  /* start address of 2nd DMA transfer area, PU:0x00000000 */
+#define IDX_IO_CODEC_DMA_START_2 0x08
+  /* both lengths of DMA transfer areas, PU:0x00000000
+     length1: offset 0x0c, length2: offset 0x0e */
+#define IDX_IO_CODEC_DMA_LENGTHS 0x0c
+#define IDX_IO_CODEC_DMA_CURRPOS 0x10 /* current DMA position, PU:0x00000000 */
+  /* offset within current DMA transfer area, PU:0x0000 */
+#define IDX_IO_CODEC_DMA_CURROFS 0x14
+#define IDX_IO_CODEC_SOUNDFORMAT 0x16 /* PU:0x0010 */
   /* all unspecified bits can't be modified */
   #define SOUNDFORMAT_FREQUENCY_MASK   0x000f
   #define SOUNDFORMAT_XTAL1            0x00
@@ -76,6 +85,7 @@
   #define SOUNDFORMAT_FLAG_16BIT       0x0010
   #define SOUNDFORMAT_FLAG_2CHANNELS   0x0020
 
+
 /* define frequency helpers, for maximum value safety */
 enum azf_freq_t {
 #define AZF_FREQ(rate) AZF_FREQ_##rate = rate
@@ -96,29 +106,6 @@ enum azf_freq_t {
 #undef AZF_FREQ
 };
 
-/** recording area (see also: playback bit flag definitions) **/
-#define IDX_IO_REC_FLAGS       0x20 /* ??, PU:0x0000 */
-#define IDX_IO_REC_IRQTYPE     0x22 /* ??, PU:0x0000 */
-  #define IRQ_REC_SOMETHING            0x0001 /* something & ACK */
-  #define IRQ_FINISHED_RECBUF_1                0x0002 /* 1st dmabuf finished & ACK */
-  #define IRQ_FINISHED_RECBUF_2                0x0004 /* 2nd dmabuf finished & ACK */
-  /* hmm, maybe these are just the corresponding *recording* flags ?
-   * but OTOH they are most likely at port 0x22 instead */
-  #define IRQMASK_SOME_STATUS_1                0x0008 /* \ related bits */
-  #define IRQMASK_SOME_STATUS_2                0x0010 /* / (checked together in loop) */
-#define IDX_IO_REC_DMA_START_1  0x24 /* PU:0x00000000 */
-#define IDX_IO_REC_DMA_START_2  0x28 /* PU:0x00000000 */
-#define IDX_IO_REC_DMA_LEN_1    0x2c /* PU:0x0000 */
-#define IDX_IO_REC_DMA_LEN_2    0x2e /* PU:0x0000 */
-#define IDX_IO_REC_DMA_CURRPOS  0x30 /* PU:0x00000000 */
-#define IDX_IO_REC_DMA_CURROFS  0x34 /* PU:0x00000000 */
-#define IDX_IO_REC_SOUNDFORMAT  0x36 /* PU:0x0000 */
-
-/** hmm, what is this I/O area for? MPU401?? or external DAC via I2S?? (after playback, recording, ???, timer) **/
-#define IDX_IO_SOMETHING_FLAGS 0x40 /* gets set to 0x34 just like port 0x0 and 0x20 on card init, PU:0x0000 */
-/* general */
-#define IDX_IO_42H             0x42 /* PU:0x0001 */
-
 /** DirectX timer, main interrupt area (FIXME: and something else?) **/ 
 #define IDX_IO_TIMER_VALUE     0x60 /* found this timer area by pure luck :-) */
   /* timer countdown value; triggers IRQ when timer is finished */
@@ -133,17 +120,19 @@ enum azf_freq_t {
 #define IDX_IO_IRQSTATUS        0x64
   /* some IRQ bit in here might also be used to signal a power-management timer
    * timeout, to request shutdown of the chip (e.g. AD1815JS has such a thing).
-   * Some OPL3 hardware (e.g. in LM4560) has some special timer hardware which
-   * can trigger an OPL3 timer IRQ, so maybe there's such a thing as well... */
+   * OPL3 hardware contains several timers which confusingly in most cases
+   * are NOT routed to an IRQ, but some designs (e.g. LM4560) DO support that,
+   * so I wouldn't be surprised at all to discover that AZF3328
+   * supports that thing as well... */
 
   #define IRQ_PLAYBACK 0x0001
   #define IRQ_RECORDING        0x0002
-  #define IRQ_UNKNOWN1 0x0004 /* most probably I2S port */
+  #define IRQ_I2S_OUT  0x0004 /* this IS I2S, right!? (untested) */
   #define IRQ_GAMEPORT 0x0008 /* Interrupt of Digital(ly) Enhanced Game Port */
   #define IRQ_MPU401   0x0010
   #define IRQ_TIMER    0x0020 /* DirectX timer */
-  #define IRQ_UNKNOWN2 0x0040 /* probably unused, or possibly I2S port? */
-  #define IRQ_UNKNOWN3 0x0080 /* probably unused, or possibly I2S port? */
+  #define IRQ_UNKNOWN2 0x0040 /* probably unused, or possibly OPL3 timer? */
+  #define IRQ_UNKNOWN3 0x0080 /* probably unused, or possibly OPL3 timer? */
 #define IDX_IO_66H             0x66    /* writing 0xffff returns 0x0000 */
   /* this is set to e.g. 0x3ff or 0x300, and writable;
    * maybe some buffer limit, but I couldn't find out more, PU:0x00ff: */
@@ -206,7 +195,7 @@ enum azf_freq_t {
 /*** Gameport area port indices ***/
 /* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ 
 #define AZF_IO_SIZE_GAME               0x08
-#define AZF_IO_SIZE_GAME_PM    0x06
+#define AZF_IO_SIZE_GAME_PM            0x06
 
 enum {
        AZF_GAME_LEGACY_IO_PORT = 0x200
@@ -272,6 +261,12 @@ enum {
    * 11 --> 1/200: */
   #define GAME_HWCFG_ADC_COUNTER_FREQ_MASK     0x06
 
+  /* FIXME: these values might be reversed... */
+  #define GAME_HWCFG_ADC_COUNTER_FREQ_STD      0
+  #define GAME_HWCFG_ADC_COUNTER_FREQ_1_2      1
+  #define GAME_HWCFG_ADC_COUNTER_FREQ_1_20     2
+  #define GAME_HWCFG_ADC_COUNTER_FREQ_1_200    3
+
   /* enable gameport legacy I/O address (0x200)
    * I was unable to locate any configurability for a different address: */
   #define GAME_HWCFG_LEGACY_ADDRESS_ENABLE     0x08
@@ -281,6 +276,7 @@ enum {
 #define AZF_IO_SIZE_MPU_PM     0x04
 
 /*** OPL3 synth ***/
+/* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */
 #define AZF_IO_SIZE_OPL3       0x08
 #define AZF_IO_SIZE_OPL3_PM    0x06
 /* hmm, given that a standard OPL3 has 4 registers only,
@@ -340,4 +336,7 @@ enum {
 #define SET_CHAN_LEFT  1
 #define SET_CHAN_RIGHT 2
 
+/* helper macro to align I/O port ranges to 32bit I/O width */
+#define AZF_ALIGN(x) (((x) + 3) & (~3))
+
 #endif /* __SOUND_AZT3328_H  */
index 57b992a5c05724c6b67e18668464e592d8b82660..15e4138bce17ea4b42b2904bbe29b43095252d38 100644 (file)
@@ -325,9 +325,9 @@ static struct snd_pcm_hardware snd_ca0106_capture_hw = {
        .rate_max =             192000,
        .channels_min =         2,
        .channels_max =         2,
-       .buffer_bytes_max =     ((65536 - 64) * 8),
+       .buffer_bytes_max =     65536 - 128,
        .period_bytes_min =     64,
-       .period_bytes_max =     (65536 - 64),
+       .period_bytes_max =     32768 - 64,
        .periods_min =          2,
        .periods_max =          2,
        .fifo_size =            0,
@@ -1876,7 +1876,7 @@ static int snd_ca0106_resume(struct pci_dev *pci)
 
 // PCI IDs
 static struct pci_device_id snd_ca0106_ids[] = {
-       { 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },    /* Audigy LS or Live 24bit */
+       { PCI_VDEVICE(CREATIVE, 0x0007), 0 },   /* Audigy LS or Live 24bit */
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);
index 449fe02f666e19288936295ebc8b5cc76c9d154b..ddcd4a9fd7e69f1cf63fcbc0d79adc8868c4237a 100644 (file)
@@ -2797,11 +2797,11 @@ static inline void snd_cmipci_proc_init(struct cmipci *cm) {}
 
 
 static struct pci_device_id snd_cmipci_ids[] = {
-       {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       {PCI_VENDOR_ID_CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       {PCI_VENDOR_ID_AL, PCI_DEVICE_ID_CMEDIA_CM8738, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A), 0},
+       {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B), 0},
+       {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738), 0},
+       {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738B), 0},
+       {PCI_VDEVICE(AL, PCI_DEVICE_ID_CMEDIA_CM8738), 0},
        {0,},
 };
 
index f6286f84a2213c1b08314de7b74f2bcd6a2469fb..e2e0359bb0568ca98999f2512baeb83e67a55883 100644 (file)
@@ -495,7 +495,7 @@ struct cs4281 {
 static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id);
 
 static struct pci_device_id snd_cs4281_ids[] = {
-       { 0x1013, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* CS4281 */
+       { PCI_VDEVICE(CIRRUS, 0x6005), 0, },    /* CS4281 */
        { 0, }
 };
 
index c9b3e3d48cbcbf819e16e5d0a8535e8029310596..033aec430117ac698c50cfe7514e26b6b792bdbd 100644 (file)
@@ -65,9 +65,9 @@ module_param_array(mmap_valid, bool, NULL, 0444);
 MODULE_PARM_DESC(mmap_valid, "Support OSS mmap.");
 
 static struct pci_device_id snd_cs46xx_ids[] = {
-        { 0x1013, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* CS4280 */
-        { 0x1013, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* CS4612 */
-        { 0x1013, 0x6004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* CS4615 */
+       { PCI_VDEVICE(CIRRUS, 0x6001), 0, },   /* CS4280 */
+       { PCI_VDEVICE(CIRRUS, 0x6003), 0, },   /* CS4612 */
+       { PCI_VDEVICE(CIRRUS, 0x6004), 0, },   /* CS4615 */
        { 0, }
 };
 
index 4eb55aa336125bb05ce6ccdf91ae589a5a752e6a..b5189495d58a412634d6be413e7cf77ac9876907 100644 (file)
@@ -35,7 +35,7 @@
 
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
-#define CS46XX_MIN_PERIOD_SIZE 1
+#define CS46XX_MIN_PERIOD_SIZE 64
 #define CS46XX_MAX_PERIOD_SIZE 1024*1024
 #else
 #define CS46XX_MIN_PERIOD_SIZE 2048
index 2d07986f57cc4316bfda42505aa496a25d199899..e0394e3996e851dda9b6abc6d22f52d81512a3b8 100644 (file)
 
 
 /* Timer Registers */
-#define TIMER_TIMR          0x1B7004
-#define INTERRUPT_GIP       0x1B7010
-#define INTERRUPT_GIE       0x1B7014
+#define WC             0x1b7000
+#define TIMR           0x1b7004
+# define       TIMR_IE         (1<<15)
+# define       TIMR_IP         (1<<14)
+#define GIP            0x1b7010
+#define GIE            0x1b7014
 
 /* I2C Registers */
 #define I2C_IF_ADDRESS   0x1B9000
index a1db51b3ead82f198483e5b948619ee01d082516..fee35cfc0c7f0c62895aad3b9bb3748ab0df7fa7 100644 (file)
@@ -63,7 +63,7 @@ static int amixer_set_input(struct amixer *amixer, struct rsc *rsc)
        hw = amixer->rsc.hw;
        hw->amixer_set_mode(amixer->rsc.ctrl_blk, AMIXER_Y_IMMEDIATE);
        amixer->input = rsc;
-       if (NULL == rsc)
+       if (!rsc)
                hw->amixer_set_x(amixer->rsc.ctrl_blk, BLANK_SLOT);
        else
                hw->amixer_set_x(amixer->rsc.ctrl_blk,
@@ -99,7 +99,7 @@ static int amixer_set_sum(struct amixer *amixer, struct sum *sum)
 
        hw = amixer->rsc.hw;
        amixer->sum = sum;
-       if (NULL == sum) {
+       if (!sum) {
                hw->amixer_set_se(amixer->rsc.ctrl_blk, 0);
        } else {
                hw->amixer_set_se(amixer->rsc.ctrl_blk, 1);
@@ -124,20 +124,20 @@ static int amixer_commit_write(struct amixer *amixer)
 
        /* Program master and conjugate resources */
        amixer->rsc.ops->master(&amixer->rsc);
-       if (NULL != input)
+       if (input)
                input->ops->master(input);
 
-       if (NULL != sum)
+       if (sum)
                sum->rsc.ops->master(&sum->rsc);
 
        for (i = 0; i < amixer->rsc.msr; i++) {
                hw->amixer_set_dirty_all(amixer->rsc.ctrl_blk);
-               if (NULL != input) {
+               if (input) {
                        hw->amixer_set_x(amixer->rsc.ctrl_blk,
                                                input->ops->output_slot(input));
                        input->ops->next_conj(input);
                }
-               if (NULL != sum) {
+               if (sum) {
                        hw->amixer_set_sadr(amixer->rsc.ctrl_blk,
                                                sum->rsc.ops->index(&sum->rsc));
                        sum->rsc.ops->next_conj(&sum->rsc);
@@ -147,10 +147,10 @@ static int amixer_commit_write(struct amixer *amixer)
                amixer->rsc.ops->next_conj(&amixer->rsc);
        }
        amixer->rsc.ops->master(&amixer->rsc);
-       if (NULL != input)
+       if (input)
                input->ops->master(input);
 
-       if (NULL != sum)
+       if (sum)
                sum->rsc.ops->master(&sum->rsc);
 
        return 0;
@@ -242,13 +242,12 @@ static int get_amixer_rsc(struct amixer_mgr *mgr,
 
        /* Allocate mem for amixer resource */
        amixer = kzalloc(sizeof(*amixer), GFP_KERNEL);
-       if (NULL == amixer) {
-               err = -ENOMEM;
-               return err;
-       }
+       if (!amixer)
+               return -ENOMEM;
 
        /* Check whether there are sufficient
         * amixer resources to meet request. */
+       err = 0;
        spin_lock_irqsave(&mgr->mgr_lock, flags);
        for (i = 0; i < desc->msr; i++) {
                err = mgr_get_resource(&mgr->mgr, 1, &idx);
@@ -304,7 +303,7 @@ int amixer_mgr_create(void *hw, struct amixer_mgr **ramixer_mgr)
 
        *ramixer_mgr = NULL;
        amixer_mgr = kzalloc(sizeof(*amixer_mgr), GFP_KERNEL);
-       if (NULL == amixer_mgr)
+       if (!amixer_mgr)
                return -ENOMEM;
 
        err = rsc_mgr_init(&amixer_mgr->mgr, AMIXER, AMIXER_RESOURCE_NUM, hw);
@@ -397,12 +396,11 @@ static int get_sum_rsc(struct sum_mgr *mgr,
 
        /* Allocate mem for sum resource */
        sum = kzalloc(sizeof(*sum), GFP_KERNEL);
-       if (NULL == sum) {
-               err = -ENOMEM;
-               return err;
-       }
+       if (!sum)
+               return -ENOMEM;
 
        /* Check whether there are sufficient sum resources to meet request. */
+       err = 0;
        spin_lock_irqsave(&mgr->mgr_lock, flags);
        for (i = 0; i < desc->msr; i++) {
                err = mgr_get_resource(&mgr->mgr, 1, &idx);
@@ -458,7 +456,7 @@ int sum_mgr_create(void *hw, struct sum_mgr **rsum_mgr)
 
        *rsum_mgr = NULL;
        sum_mgr = kzalloc(sizeof(*sum_mgr), GFP_KERNEL);
-       if (NULL == sum_mgr)
+       if (!sum_mgr)
                return -ENOMEM;
 
        err = rsc_mgr_init(&sum_mgr->mgr, SUM, SUM_RESOURCE_NUM, hw);
index a49c766473073e1a6d94b7ed75ed014fd0c2c293..75454648d50c6efb10d79357804c322c6f7aa80e 100644 (file)
@@ -136,7 +136,7 @@ static int ct_map_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm)
        struct snd_pcm_runtime *runtime;
        struct ct_vm *vm;
 
-       if (NULL == apcm->substream)
+       if (!apcm->substream)
                return 0;
 
        runtime = apcm->substream->runtime;
@@ -144,7 +144,7 @@ static int ct_map_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 
        apcm->vm_block = vm->map(vm, apcm->substream, runtime->dma_bytes);
 
-       if (NULL == apcm->vm_block)
+       if (!apcm->vm_block)
                return -ENOENT;
 
        return 0;
@@ -154,7 +154,7 @@ static void ct_unmap_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 {
        struct ct_vm *vm;
 
-       if (NULL == apcm->vm_block)
+       if (!apcm->vm_block)
                return;
 
        vm = atc->vm;
@@ -231,16 +231,16 @@ atc_get_pitch(unsigned int input_rate, unsigned int output_rate)
 
 static int select_rom(unsigned int pitch)
 {
-       if ((pitch > 0x00428f5c) && (pitch < 0x01b851ec)) {
+       if (pitch > 0x00428f5c && pitch < 0x01b851ec) {
                /* 0.26 <= pitch <= 1.72 */
                return 1;
-       } else if ((0x01d66666 == pitch) || (0x01d66667 == pitch)) {
+       } else if (pitch == 0x01d66666 || pitch == 0x01d66667) {
                /* pitch == 1.8375 */
                return 2;
-       } else if (0x02000000 == pitch) {
+       } else if (pitch == 0x02000000) {
                /* pitch == 2 */
                return 3;
-       } else if ((pitch >= 0x0) && (pitch <= 0x08000000)) {
+       } else if (pitch >= 0x0 && pitch <= 0x08000000) {
                /* 0 <= pitch <= 8 */
                return 0;
        } else {
@@ -283,7 +283,7 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
        /* Get AMIXER resource */
        n_amixer = (n_amixer < 2) ? 2 : n_amixer;
        apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL);
-       if (NULL == apcm->amixers) {
+       if (!apcm->amixers) {
                err = -ENOMEM;
                goto error1;
        }
@@ -311,7 +311,7 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
                                        INIT_VOL, atc->pcm[i+device*2]);
                mutex_unlock(&atc->atc_mutex);
                src = src->ops->next_interleave(src);
-               if (NULL == src)
+               if (!src)
                        src = apcm->src;
        }
 
@@ -334,7 +334,7 @@ atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
        struct srcimp *srcimp;
        int i;
 
-       if (NULL != apcm->srcimps) {
+       if (apcm->srcimps) {
                for (i = 0; i < apcm->n_srcimp; i++) {
                        srcimp = apcm->srcimps[i];
                        srcimp->ops->unmap(srcimp);
@@ -345,7 +345,7 @@ atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
                apcm->srcimps = NULL;
        }
 
-       if (NULL != apcm->srccs) {
+       if (apcm->srccs) {
                for (i = 0; i < apcm->n_srcc; i++) {
                        src_mgr->put_src(src_mgr, apcm->srccs[i]);
                        apcm->srccs[i] = NULL;
@@ -354,7 +354,7 @@ atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
                apcm->srccs = NULL;
        }
 
-       if (NULL != apcm->amixers) {
+       if (apcm->amixers) {
                for (i = 0; i < apcm->n_amixer; i++) {
                        amixer_mgr->put_amixer(amixer_mgr, apcm->amixers[i]);
                        apcm->amixers[i] = NULL;
@@ -363,17 +363,17 @@ atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
                apcm->amixers = NULL;
        }
 
-       if (NULL != apcm->mono) {
+       if (apcm->mono) {
                sum_mgr->put_sum(sum_mgr, apcm->mono);
                apcm->mono = NULL;
        }
 
-       if (NULL != apcm->src) {
+       if (apcm->src) {
                src_mgr->put_src(src_mgr, apcm->src);
                apcm->src = NULL;
        }
 
-       if (NULL != apcm->vm_block) {
+       if (apcm->vm_block) {
                /* Undo device virtual mem map */
                ct_unmap_audio_buffer(atc, apcm);
                apcm->vm_block = NULL;
@@ -419,7 +419,7 @@ static int atc_pcm_stop(struct ct_atc *atc, struct ct_atc_pcm *apcm)
        src->ops->set_state(src, SRC_STATE_OFF);
        src->ops->commit_write(src);
 
-       if (NULL != apcm->srccs) {
+       if (apcm->srccs) {
                for (i = 0; i < apcm->n_srcc; i++) {
                        src = apcm->srccs[i];
                        src->ops->set_bm(src, 0);
@@ -544,18 +544,18 @@ atc_pcm_capture_get_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 
        if (n_srcc) {
                apcm->srccs = kzalloc(sizeof(void *)*n_srcc, GFP_KERNEL);
-               if (NULL == apcm->srccs)
+               if (!apcm->srccs)
                        return -ENOMEM;
        }
        if (n_amixer) {
                apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL);
-               if (NULL == apcm->amixers) {
+               if (!apcm->amixers) {
                        err = -ENOMEM;
                        goto error1;
                }
        }
        apcm->srcimps = kzalloc(sizeof(void *)*n_srcimp, GFP_KERNEL);
-       if (NULL == apcm->srcimps) {
+       if (!apcm->srcimps) {
                err = -ENOMEM;
                goto error1;
        }
@@ -818,7 +818,7 @@ static int spdif_passthru_playback_get_resources(struct ct_atc *atc,
        /* Get AMIXER resource */
        n_amixer = (n_amixer < 2) ? 2 : n_amixer;
        apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL);
-       if (NULL == apcm->amixers) {
+       if (!apcm->amixers) {
                err = -ENOMEM;
                goto error1;
        }
@@ -919,7 +919,7 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
                amixer = apcm->amixers[i];
                amixer->ops->setup(amixer, &src->rsc, INIT_VOL, NULL);
                src = src->ops->next_interleave(src);
-               if (NULL == src)
+               if (!src)
                        src = apcm->src;
        }
        /* Connect to SPDIFOO */
@@ -1037,7 +1037,7 @@ static int atc_line_front_unmute(struct ct_atc *atc, unsigned char state)
 
 static int atc_line_surround_unmute(struct ct_atc *atc, unsigned char state)
 {
-       return atc_daio_unmute(atc, state, LINEO4);
+       return atc_daio_unmute(atc, state, LINEO2);
 }
 
 static int atc_line_clfe_unmute(struct ct_atc *atc, unsigned char state)
@@ -1047,7 +1047,7 @@ static int atc_line_clfe_unmute(struct ct_atc *atc, unsigned char state)
 
 static int atc_line_rear_unmute(struct ct_atc *atc, unsigned char state)
 {
-       return atc_daio_unmute(atc, state, LINEO2);
+       return atc_daio_unmute(atc, state, LINEO4);
 }
 
 static int atc_line_in_unmute(struct ct_atc *atc, unsigned char state)
@@ -1121,7 +1121,7 @@ static int atc_release_resources(struct ct_atc *atc)
        struct ct_mixer *mixer = NULL;
 
        /* disconnect internal mixer objects */
-       if (NULL != atc->mixer) {
+       if (atc->mixer) {
                mixer = atc->mixer;
                mixer->set_input_left(mixer, MIX_LINE_IN, NULL);
                mixer->set_input_right(mixer, MIX_LINE_IN, NULL);
@@ -1131,7 +1131,7 @@ static int atc_release_resources(struct ct_atc *atc)
                mixer->set_input_right(mixer, MIX_SPDIF_IN, NULL);
        }
 
-       if (NULL != atc->daios) {
+       if (atc->daios) {
                daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO];
                for (i = 0; i < atc->n_daio; i++) {
                        daio = atc->daios[i];
@@ -1149,7 +1149,7 @@ static int atc_release_resources(struct ct_atc *atc)
                atc->daios = NULL;
        }
 
-       if (NULL != atc->pcm) {
+       if (atc->pcm) {
                sum_mgr = atc->rsc_mgrs[SUM];
                for (i = 0; i < atc->n_pcm; i++)
                        sum_mgr->put_sum(sum_mgr, atc->pcm[i]);
@@ -1158,7 +1158,7 @@ static int atc_release_resources(struct ct_atc *atc)
                atc->pcm = NULL;
        }
 
-       if (NULL != atc->srcs) {
+       if (atc->srcs) {
                src_mgr = atc->rsc_mgrs[SRC];
                for (i = 0; i < atc->n_src; i++)
                        src_mgr->put_src(src_mgr, atc->srcs[i]);
@@ -1167,7 +1167,7 @@ static int atc_release_resources(struct ct_atc *atc)
                atc->srcs = NULL;
        }
 
-       if (NULL != atc->srcimps) {
+       if (atc->srcimps) {
                srcimp_mgr = atc->rsc_mgrs[SRCIMP];
                for (i = 0; i < atc->n_srcimp; i++) {
                        srcimp = atc->srcimps[i];
@@ -1185,7 +1185,7 @@ static int ct_atc_destroy(struct ct_atc *atc)
 {
        int i = 0;
 
-       if (NULL == atc)
+       if (!atc)
                return 0;
 
        if (atc->timer) {
@@ -1196,21 +1196,20 @@ static int ct_atc_destroy(struct ct_atc *atc)
        atc_release_resources(atc);
 
        /* Destroy internal mixer objects */
-       if (NULL != atc->mixer)
+       if (atc->mixer)
                ct_mixer_destroy(atc->mixer);
 
        for (i = 0; i < NUM_RSCTYP; i++) {
-               if ((NULL != rsc_mgr_funcs[i].destroy) &&
-                   (NULL != atc->rsc_mgrs[i]))
+               if (rsc_mgr_funcs[i].destroy && atc->rsc_mgrs[i])
                        rsc_mgr_funcs[i].destroy(atc->rsc_mgrs[i]);
 
        }
 
-       if (NULL != atc->hw)
+       if (atc->hw)
                destroy_hw_obj((struct hw *)atc->hw);
 
        /* Destroy device virtual memory manager object */
-       if (NULL != atc->vm) {
+       if (atc->vm) {
                ct_vm_destroy(atc->vm);
                atc->vm = NULL;
        }
@@ -1275,7 +1274,7 @@ int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc)
        alsa_dev_funcs[MIXER].public_name = atc->chip_name;
 
        for (i = 0; i < NUM_CTALSADEVS; i++) {
-               if (NULL == alsa_dev_funcs[i].create)
+               if (!alsa_dev_funcs[i].create)
                        continue;
 
                err = alsa_dev_funcs[i].create(atc, i,
@@ -1312,7 +1311,7 @@ static int __devinit atc_create_hw_devs(struct ct_atc *atc)
                return err;
 
        for (i = 0; i < NUM_RSCTYP; i++) {
-               if (NULL == rsc_mgr_funcs[i].create)
+               if (!rsc_mgr_funcs[i].create)
                        continue;
 
                err = rsc_mgr_funcs[i].create(atc->hw, &atc->rsc_mgrs[i]);
@@ -1339,19 +1338,19 @@ static int atc_get_resources(struct ct_atc *atc)
        int err, i;
 
        atc->daios = kzalloc(sizeof(void *)*(DAIONUM), GFP_KERNEL);
-       if (NULL == atc->daios)
+       if (!atc->daios)
                return -ENOMEM;
 
        atc->srcs = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL);
-       if (NULL == atc->srcs)
+       if (!atc->srcs)
                return -ENOMEM;
 
        atc->srcimps = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL);
-       if (NULL == atc->srcimps)
+       if (!atc->srcimps)
                return -ENOMEM;
 
        atc->pcm = kzalloc(sizeof(void *)*(2*4), GFP_KERNEL);
-       if (NULL == atc->pcm)
+       if (!atc->pcm)
                return -ENOMEM;
 
        daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO];
@@ -1648,7 +1647,7 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
        *ratc = NULL;
 
        atc = kzalloc(sizeof(*atc), GFP_KERNEL);
-       if (NULL == atc)
+       if (!atc)
                return -ENOMEM;
 
        /* Set operations */
index 082e35c08c02956371fd69120d8fbe8ad7e1eeef..af56eb949bded282affb84a59691dc49f3d3054e 100644 (file)
@@ -57,9 +57,9 @@ struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = {
 
 struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = {
        [LINEO1] = {.left = 0x40, .right = 0x41},
-       [LINEO2] = {.left = 0x70, .right = 0x71},
+       [LINEO2] = {.left = 0x60, .right = 0x61},
        [LINEO3] = {.left = 0x50, .right = 0x51},
-       [LINEO4] = {.left = 0x60, .right = 0x61},
+       [LINEO4] = {.left = 0x70, .right = 0x71},
        [LINEIM] = {.left = 0x45, .right = 0xc5},
        [SPDIFOO] = {.left = 0x00, .right = 0x01},
        [SPDIFIO] = {.left = 0x05, .right = 0x85},
@@ -173,7 +173,7 @@ static int dao_set_left_input(struct dao *dao, struct rsc *input)
        int i;
 
        entry = kzalloc((sizeof(*entry) * daio->rscl.msr), GFP_KERNEL);
-       if (NULL == entry)
+       if (!entry)
                return -ENOMEM;
 
        /* Program master and conjugate resources */
@@ -201,7 +201,7 @@ static int dao_set_right_input(struct dao *dao, struct rsc *input)
        int i;
 
        entry = kzalloc((sizeof(*entry) * daio->rscr.msr), GFP_KERNEL);
-       if (NULL == entry)
+       if (!entry)
                return -ENOMEM;
 
        /* Program master and conjugate resources */
@@ -228,7 +228,7 @@ static int dao_clear_left_input(struct dao *dao)
        struct daio *daio = &dao->daio;
        int i;
 
-       if (NULL == dao->imappers[0])
+       if (!dao->imappers[0])
                return 0;
 
        entry = dao->imappers[0];
@@ -252,7 +252,7 @@ static int dao_clear_right_input(struct dao *dao)
        struct daio *daio = &dao->daio;
        int i;
 
-       if (NULL == dao->imappers[daio->rscl.msr])
+       if (!dao->imappers[daio->rscl.msr])
                return 0;
 
        entry = dao->imappers[daio->rscl.msr];
@@ -408,7 +408,7 @@ static int dao_rsc_init(struct dao *dao,
                return err;
 
        dao->imappers = kzalloc(sizeof(void *)*desc->msr*2, GFP_KERNEL);
-       if (NULL == dao->imappers) {
+       if (!dao->imappers) {
                err = -ENOMEM;
                goto error1;
        }
@@ -442,11 +442,11 @@ error1:
 
 static int dao_rsc_uninit(struct dao *dao)
 {
-       if (NULL != dao->imappers) {
-               if (NULL != dao->imappers[0])
+       if (dao->imappers) {
+               if (dao->imappers[0])
                        dao_clear_left_input(dao);
 
-               if (NULL != dao->imappers[dao->daio.rscl.msr])
+               if (dao->imappers[dao->daio.rscl.msr])
                        dao_clear_right_input(dao);
 
                kfree(dao->imappers);
@@ -555,7 +555,7 @@ static int get_daio_rsc(struct daio_mgr *mgr,
        /* Allocate mem for daio resource */
        if (desc->type <= DAIO_OUT_MAX) {
                dao = kzalloc(sizeof(*dao), GFP_KERNEL);
-               if (NULL == dao) {
+               if (!dao) {
                        err = -ENOMEM;
                        goto error;
                }
@@ -566,7 +566,7 @@ static int get_daio_rsc(struct daio_mgr *mgr,
                *rdaio = &dao->daio;
        } else {
                dai = kzalloc(sizeof(*dai), GFP_KERNEL);
-               if (NULL == dai) {
+               if (!dai) {
                        err = -ENOMEM;
                        goto error;
                }
@@ -583,9 +583,9 @@ static int get_daio_rsc(struct daio_mgr *mgr,
        return 0;
 
 error:
-       if (NULL != dao)
+       if (dao)
                kfree(dao);
-       else if (NULL != dai)
+       else if (dai)
                kfree(dai);
 
        spin_lock_irqsave(&mgr->mgr_lock, flags);
@@ -663,7 +663,7 @@ static int daio_imap_add(struct daio_mgr *mgr, struct imapper *entry)
        int err;
 
        spin_lock_irqsave(&mgr->imap_lock, flags);
-       if ((0 == entry->addr) && (mgr->init_imap_added)) {
+       if (!entry->addr && mgr->init_imap_added) {
                input_mapper_delete(&mgr->imappers, mgr->init_imap,
                                                        daio_map_op, mgr);
                mgr->init_imap_added = 0;
@@ -707,7 +707,7 @@ int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr)
 
        *rdaio_mgr = NULL;
        daio_mgr = kzalloc(sizeof(*daio_mgr), GFP_KERNEL);
-       if (NULL == daio_mgr)
+       if (!daio_mgr)
                return -ENOMEM;
 
        err = rsc_mgr_init(&daio_mgr->mgr, DAIO, DAIO_RESOURCE_NUM, hw);
@@ -718,7 +718,7 @@ int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr)
        spin_lock_init(&daio_mgr->imap_lock);
        INIT_LIST_HEAD(&daio_mgr->imappers);
        entry = kzalloc(sizeof(*entry), GFP_KERNEL);
-       if (NULL == entry) {
+       if (!entry) {
                err = -ENOMEM;
                goto error2;
        }
index ad3e1d144464ce639ad8f01f6b5883ab495b2281..0cf400f879f9eb09388b89f5a7d323008cb6533d 100644 (file)
@@ -168,7 +168,7 @@ static int src_get_rsc_ctrl_blk(void **rblk)
 
        *rblk = NULL;
        blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        *rblk = blk;
@@ -494,7 +494,7 @@ static int src_mgr_get_ctrl_blk(void **rblk)
 
        *rblk = NULL;
        blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        *rblk = blk;
@@ -515,7 +515,7 @@ static int srcimp_mgr_get_ctrl_blk(void **rblk)
 
        *rblk = NULL;
        blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        *rblk = blk;
@@ -702,7 +702,7 @@ static int amixer_rsc_get_ctrl_blk(void **rblk)
 
        *rblk = NULL;
        blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        *rblk = blk;
@@ -723,7 +723,7 @@ static int amixer_mgr_get_ctrl_blk(void **rblk)
 
        *rblk = NULL;
        /*blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        *rblk = blk;*/
@@ -909,7 +909,7 @@ static int dai_get_ctrl_blk(void **rblk)
 
        *rblk = NULL;
        blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        *rblk = blk;
@@ -958,7 +958,7 @@ static int dao_get_ctrl_blk(void **rblk)
 
        *rblk = NULL;
        blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        *rblk = blk;
@@ -1152,7 +1152,7 @@ static int daio_mgr_get_ctrl_blk(struct hw *hw, void **rblk)
 
        *rblk = NULL;
        blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        blk->i2sctl = hw_read_20kx(hw, I2SCTL);
@@ -1808,7 +1808,7 @@ static int uaa_to_xfi(struct pci_dev *pci)
        /* By default, Hendrix card UAA Bar0 should be using memory... */
        io_base = pci_resource_start(pci, 0);
        mem_base = ioremap(io_base, pci_resource_len(pci, 0));
-       if (NULL == mem_base)
+       if (!mem_base)
                return -ENOENT;
 
        /* Read current mode from Mode Change Register */
@@ -1977,7 +1977,7 @@ static int hw_card_shutdown(struct hw *hw)
 
        hw->irq = -1;
 
-       if (NULL != ((void *)hw->mem_base))
+       if (hw->mem_base)
                iounmap((void *)hw->mem_base);
 
        hw->mem_base = (unsigned long)NULL;
@@ -2274,7 +2274,7 @@ int __devinit create_20k1_hw_obj(struct hw **rhw)
 
        *rhw = NULL;
        hw20k1 = kzalloc(sizeof(*hw20k1), GFP_KERNEL);
-       if (NULL == hw20k1)
+       if (!hw20k1)
                return -ENOMEM;
 
        spin_lock_init(&hw20k1->reg_20k1_lock);
index dec46d04b041c7e33072d484f6eedd70b0f4b974..b6b11bfe7574e2445b5811d0b2c4495a67ad50d9 100644 (file)
@@ -166,7 +166,7 @@ static int src_get_rsc_ctrl_blk(void **rblk)
 
        *rblk = NULL;
        blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        *rblk = blk;
@@ -492,7 +492,7 @@ static int src_mgr_get_ctrl_blk(void **rblk)
 
        *rblk = NULL;
        blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        *rblk = blk;
@@ -513,7 +513,7 @@ static int srcimp_mgr_get_ctrl_blk(void **rblk)
 
        *rblk = NULL;
        blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        *rblk = blk;
@@ -702,7 +702,7 @@ static int amixer_rsc_get_ctrl_blk(void **rblk)
 
        *rblk = NULL;
        blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        *rblk = blk;
@@ -891,7 +891,7 @@ static int dai_get_ctrl_blk(void **rblk)
 
        *rblk = NULL;
        blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        *rblk = blk;
@@ -941,7 +941,7 @@ static int dao_get_ctrl_blk(void **rblk)
 
        *rblk = NULL;
        blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        *rblk = blk;
@@ -1092,7 +1092,7 @@ static int daio_mgr_get_ctrl_blk(struct hw *hw, void **rblk)
 
        *rblk = NULL;
        blk = kzalloc(sizeof(*blk), GFP_KERNEL);
-       if (NULL == blk)
+       if (!blk)
                return -ENOMEM;
 
        for (i = 0; i < 8; i++) {
@@ -1112,6 +1112,26 @@ static int daio_mgr_put_ctrl_blk(void *blk)
        return 0;
 }
 
+/* Timer interrupt */
+static int set_timer_irq(struct hw *hw, int enable)
+{
+       hw_write_20kx(hw, GIE, enable ? IT_INT : 0);
+       return 0;
+}
+
+static int set_timer_tick(struct hw *hw, unsigned int ticks)
+{
+       if (ticks)
+               ticks |= TIMR_IE | TIMR_IP;
+       hw_write_20kx(hw, TIMR, ticks);
+       return 0;
+}
+
+static unsigned int get_wc(struct hw *hw)
+{
+       return hw_read_20kx(hw, WC);
+}
+
 /* Card hardware initialization block */
 struct dac_conf {
        unsigned int msr; /* master sample rate in rsrs */
@@ -1841,6 +1861,22 @@ static int hw_have_digit_io_switch(struct hw *hw)
        return 0;
 }
 
+static irqreturn_t ct_20k2_interrupt(int irq, void *dev_id)
+{
+       struct hw *hw = dev_id;
+       unsigned int status;
+
+       status = hw_read_20kx(hw, GIP);
+       if (!status)
+               return IRQ_NONE;
+
+       if (hw->irq_callback)
+               hw->irq_callback(hw->irq_callback_data, status);
+
+       hw_write_20kx(hw, GIP, status);
+       return IRQ_HANDLED;
+}
+
 static int hw_card_start(struct hw *hw)
 {
        int err = 0;
@@ -1868,7 +1904,7 @@ static int hw_card_start(struct hw *hw)
                hw->io_base = pci_resource_start(hw->pci, 2);
                hw->mem_base = (unsigned long)ioremap(hw->io_base,
                                        pci_resource_len(hw->pci, 2));
-               if (NULL == (void *)hw->mem_base) {
+               if (!hw->mem_base) {
                        err = -ENOENT;
                        goto error2;
                }
@@ -1879,12 +1915,15 @@ static int hw_card_start(struct hw *hw)
        set_field(&gctl, GCTL_UAA, 0);
        hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl);
 
-       /*if ((err = request_irq(pci->irq, ct_atc_interrupt, IRQF_SHARED,
-                               atc->chip_details->nm_card, hw))) {
-               goto error3;
+       if (hw->irq < 0) {
+               err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED,
+                                 "ctxfi", hw);
+               if (err < 0) {
+                       printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq);
+                       goto error2;
+               }
+               hw->irq = pci->irq;
        }
-       hw->irq = pci->irq;
-       */
 
        pci_set_master(pci);
 
@@ -1923,7 +1962,7 @@ static int hw_card_shutdown(struct hw *hw)
 
        hw->irq = -1;
 
-       if (NULL != ((void *)hw->mem_base))
+       if (hw->mem_base)
                iounmap((void *)hw->mem_base);
 
        hw->mem_base = (unsigned long)NULL;
@@ -1972,7 +2011,7 @@ static int hw_card_init(struct hw *hw, struct card_conf *info)
        hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl);
 
        /* Reset all global pending interrupts */
-       hw_write_20kx(hw, INTERRUPT_GIE, 0);
+       hw_write_20kx(hw, GIE, 0);
        /* Reset all SRC pending interrupts */
        hw_write_20kx(hw, SRC_IP, 0);
 
@@ -2149,6 +2188,10 @@ static struct hw ct20k2_preset __devinitdata = {
        .daio_mgr_set_imapnxt = daio_mgr_set_imapnxt,
        .daio_mgr_set_imapaddr = daio_mgr_set_imapaddr,
        .daio_mgr_commit_write = daio_mgr_commit_write,
+
+       .set_timer_irq = set_timer_irq,
+       .set_timer_tick = set_timer_tick,
+       .get_wc = get_wc,
 };
 
 int __devinit create_20k2_hw_obj(struct hw **rhw)
index f26d7cd9db9f531a94ad28a16ff8d84f31c77cea..15c1e7271ea889bbcaec9d6e45df709f0ee58845 100644 (file)
@@ -654,7 +654,7 @@ ct_mixer_kcontrol_new(struct ct_mixer *mixer, struct snd_kcontrol_new *new)
        int err;
 
        kctl = snd_ctl_new1(new, mixer->atc);
-       if (NULL == kctl)
+       if (!kctl)
                return -ENOMEM;
 
        if (SNDRV_CTL_ELEM_IFACE_PCM == kctl->id.iface)
@@ -837,17 +837,17 @@ static int ct_mixer_get_mem(struct ct_mixer **rmixer)
        *rmixer = NULL;
        /* Allocate mem for mixer obj */
        mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
-       if (NULL == mixer)
+       if (!mixer)
                return -ENOMEM;
 
        mixer->amixers = kzalloc(sizeof(void *)*(NUM_CT_AMIXERS*CHN_NUM),
                                 GFP_KERNEL);
-       if (NULL == mixer->amixers) {
+       if (!mixer->amixers) {
                err = -ENOMEM;
                goto error1;
        }
        mixer->sums = kzalloc(sizeof(void *)*(NUM_CT_SUMS*CHN_NUM), GFP_KERNEL);
-       if (NULL == mixer->sums) {
+       if (!mixer->sums) {
                err = -ENOMEM;
                goto error2;
        }
index 60ea23180acbe1f91443f5ad15b8939ec812698c..d0dc227fbdd3ceaeccc72cbcb6b7191ff037e662 100644 (file)
@@ -97,7 +97,7 @@ static void ct_atc_pcm_interrupt(struct ct_atc_pcm *atc_pcm)
 {
        struct ct_atc_pcm *apcm = atc_pcm;
 
-       if (NULL == apcm->substream)
+       if (!apcm->substream)
                return;
 
        snd_pcm_period_elapsed(apcm->substream);
@@ -123,7 +123,7 @@ static int ct_pcm_playback_open(struct snd_pcm_substream *substream)
        int err;
 
        apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
-       if (NULL == apcm)
+       if (!apcm)
                return -ENOMEM;
 
        apcm->substream = substream;
@@ -271,7 +271,7 @@ static int ct_pcm_capture_open(struct snd_pcm_substream *substream)
        int err;
 
        apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
-       if (NULL == apcm)
+       if (!apcm)
                return -ENOMEM;
 
        apcm->started = 0;
index 889c495bb7d150739786e0e9626dbcb3f520a9d8..7dfaf67344d4a0ded780ff575922250fe8df6950 100644 (file)
@@ -144,7 +144,7 @@ int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw)
        rsc->msr = msr;
        rsc->hw = hw;
        rsc->ops = &rsc_generic_ops;
-       if (NULL == hw) {
+       if (!hw) {
                rsc->ctrl_blk = NULL;
                return 0;
        }
@@ -216,7 +216,7 @@ int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
        mgr->type = NUM_RSCTYP;
 
        mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL);
-       if (NULL == mgr->rscs)
+       if (!mgr->rscs)
                return -ENOMEM;
 
        switch (type) {
index e1c145d8b702944472abe2a6bcd309a98a16bd90..c749fa72088996c75843927f7470997288a6e669 100644 (file)
@@ -441,7 +441,7 @@ get_src_rsc(struct src_mgr *mgr, const struct src_desc *desc, struct src **rsrc)
        else
                src = kzalloc(sizeof(*src), GFP_KERNEL);
 
-       if (NULL == src) {
+       if (!src) {
                err = -ENOMEM;
                goto error1;
        }
@@ -550,7 +550,7 @@ int src_mgr_create(void *hw, struct src_mgr **rsrc_mgr)
 
        *rsrc_mgr = NULL;
        src_mgr = kzalloc(sizeof(*src_mgr), GFP_KERNEL);
-       if (NULL == src_mgr)
+       if (!src_mgr)
                return -ENOMEM;
 
        err = rsc_mgr_init(&src_mgr->mgr, SRC, SRC_RESOURCE_NUM, hw);
@@ -679,7 +679,7 @@ static int srcimp_rsc_init(struct srcimp *srcimp,
        /* Reserve memory for imapper nodes */
        srcimp->imappers = kzalloc(sizeof(struct imapper)*desc->msr,
                                   GFP_KERNEL);
-       if (NULL == srcimp->imappers) {
+       if (!srcimp->imappers) {
                err = -ENOMEM;
                goto error1;
        }
@@ -724,12 +724,11 @@ static int get_srcimp_rsc(struct srcimp_mgr *mgr,
 
        /* Allocate mem for SRCIMP resource */
        srcimp = kzalloc(sizeof(*srcimp), GFP_KERNEL);
-       if (NULL == srcimp) {
-               err = -ENOMEM;
-               return err;
-       }
+       if (!srcimp)
+               return -ENOMEM;
 
        /* Check whether there are sufficient SRCIMP resources. */
+       err = 0;
        spin_lock_irqsave(&mgr->mgr_lock, flags);
        for (i = 0; i < desc->msr; i++) {
                err = mgr_get_resource(&mgr->mgr, 1, &idx);
@@ -834,7 +833,7 @@ int srcimp_mgr_create(void *hw, struct srcimp_mgr **rsrcimp_mgr)
 
        *rsrcimp_mgr = NULL;
        srcimp_mgr = kzalloc(sizeof(*srcimp_mgr), GFP_KERNEL);
-       if (NULL == srcimp_mgr)
+       if (!srcimp_mgr)
                return -ENOMEM;
 
        err = rsc_mgr_init(&srcimp_mgr->mgr, SRCIMP, SRCIMP_RESOURCE_NUM, hw);
@@ -845,7 +844,7 @@ int srcimp_mgr_create(void *hw, struct srcimp_mgr **rsrcimp_mgr)
        spin_lock_init(&srcimp_mgr->imap_lock);
        INIT_LIST_HEAD(&srcimp_mgr->imappers);
        entry = kzalloc(sizeof(*entry), GFP_KERNEL);
-       if (NULL == entry) {
+       if (!entry) {
                err = -ENOMEM;
                goto error2;
        }
index 67665a7e43c6853d08c255b5b3f1a28ea4339716..6b78752e95036b2a4010cb6a66b39f5e3b5f708c 100644 (file)
@@ -60,7 +60,7 @@ get_vm_block(struct ct_vm *vm, unsigned int size)
        }
 
        block = kzalloc(sizeof(*block), GFP_KERNEL);
-       if (NULL == block)
+       if (!block)
                goto out;
 
        block->addr = entry->addr;
@@ -181,7 +181,7 @@ int ct_vm_create(struct ct_vm **rvm)
        *rvm = NULL;
 
        vm = kzalloc(sizeof(*vm), GFP_KERNEL);
-       if (NULL == vm)
+       if (!vm)
                return -ENOMEM;
 
        mutex_init(&vm->lock);
@@ -189,7 +189,7 @@ int ct_vm_create(struct ct_vm **rvm)
        /* Allocate page table pages */
        for (i = 0; i < CT_PTP_NUM; i++) {
                vm->ptp[i] = kmalloc(PAGE_SIZE, GFP_KERNEL);
-               if (NULL == vm->ptp[i])
+               if (!vm->ptp[i])
                        break;
        }
        if (!i) {
index da2065cd2c0d5c3ffd5783b98c90ebfbc4ee244c..1305f7ca02c3c2726049dc448dec6b7fa36a63cd 100644 (file)
@@ -950,7 +950,7 @@ static int __devinit snd_echo_new_pcm(struct echoaudio *chip)
        Control interface
 ******************************************************************************/
 
-#ifndef ECHOCARD_HAS_VMIXER
+#if !defined(ECHOCARD_HAS_VMIXER) || defined(ECHOCARD_HAS_LINE_OUT_GAIN)
 
 /******************* PCM output volume *******************/
 static int snd_echo_output_gain_info(struct snd_kcontrol *kcontrol,
@@ -1003,6 +1003,19 @@ static int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol,
        return changed;
 }
 
+#ifdef ECHOCARD_HAS_LINE_OUT_GAIN
+/* On the Mia this one controls the line-out volume */
+static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = {
+       .name = "Line Playback Volume",
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+       .info = snd_echo_output_gain_info,
+       .get = snd_echo_output_gain_get,
+       .put = snd_echo_output_gain_put,
+       .tlv = {.p = db_scale_output_gain},
+};
+#else
 static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = {
        .name = "PCM Playback Volume",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1012,9 +1025,10 @@ static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = {
        .put = snd_echo_output_gain_put,
        .tlv = {.p = db_scale_output_gain},
 };
-
 #endif
 
+#endif /* !ECHOCARD_HAS_VMIXER || ECHOCARD_HAS_LINE_OUT_GAIN */
+
 
 
 #ifdef ECHOCARD_HAS_INPUT_GAIN
@@ -2030,10 +2044,18 @@ static int __devinit snd_echo_probe(struct pci_dev *pci,
        snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip);
        if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip))) < 0)
                goto ctl_error;
-#else
-       if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_pcm_output_gain, chip))) < 0)
+#ifdef ECHOCARD_HAS_LINE_OUT_GAIN
+       err = snd_ctl_add(chip->card,
+                         snd_ctl_new1(&snd_echo_line_output_gain, chip));
+       if (err < 0)
                goto ctl_error;
 #endif
+#else /* ECHOCARD_HAS_VMIXER */
+       err = snd_ctl_add(chip->card,
+                         snd_ctl_new1(&snd_echo_pcm_output_gain, chip));
+       if (err < 0)
+               goto ctl_error;
+#endif /* ECHOCARD_HAS_VMIXER */
 
 #ifdef ECHOCARD_HAS_INPUT_GAIN
        if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_input_gain, chip))) < 0)
index f3b9b45c9c1be7ad82b3c9249e66dfe84ef15833..f05c8c097aa8196de2f9fe0a62e6e45e2efbd66c 100644 (file)
@@ -29,6 +29,7 @@
 #define ECHOCARD_HAS_ADAT      FALSE
 #define ECHOCARD_HAS_STEREO_BIG_ENDIAN32
 #define ECHOCARD_HAS_MIDI
+#define ECHOCARD_HAS_LINE_OUT_GAIN
 
 /* Pipe indexes */
 #define PX_ANALOG_OUT  0       /* 8 */
index c7f3b994101cef1f335fde62e09a5d53616e4152..168af67d938e1415993b29eb166763327ec0048b 100644 (file)
@@ -77,9 +77,9 @@ MODULE_PARM_DESC(subsystem, "Force card subsystem model.");
  * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value  Model:SB0400
  */
 static struct pci_device_id snd_emu10k1_ids[] = {
-       { 0x1102, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },    /* EMU10K1 */
-       { 0x1102, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },    /* Audigy */
-       { 0x1102, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },    /* Audigy 2 Value SB0400 */
+       { PCI_VDEVICE(CREATIVE, 0x0002), 0 },   /* EMU10K1 */
+       { PCI_VDEVICE(CREATIVE, 0x0004), 1 },   /* Audigy */
+       { PCI_VDEVICE(CREATIVE, 0x0008), 1 },   /* Audigy 2 Value SB0400 */
        { 0, }
 };
 
index 4d3ad793e98fb1618048ebf84d47374695604558..36e08bd2b3cc6ff8d2a4aa74e8f51e233bb62477 100644 (file)
@@ -1607,7 +1607,7 @@ static void __devexit snd_emu10k1x_remove(struct pci_dev *pci)
 
 // PCI IDs
 static struct pci_device_id snd_emu10k1x_ids[] = {
-       { 0x1102, 0x0006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },    /* Dell OEM version (EMU10K1) */
+       { PCI_VDEVICE(CREATIVE, 0x0006), 0 },   /* Dell OEM version (EMU10K1) */
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, snd_emu10k1x_ids);
index e617acaf10e3300679b7ca0614183877bc654db9..61b8ab39800ff073cc9bf3c82bd4eb428a488350 100644 (file)
@@ -644,7 +644,7 @@ int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm *
        int err;
         int capture=1;
   
-       /* snd_printk("KERN_DEBUG snd_p16v_pcm called. device=%d\n", device); */
+       /* snd_printk(KERN_DEBUG "snd_p16v_pcm called. device=%d\n", device); */
        emu->p16v_device_offset = device;
        if (rpcm)
                *rpcm = NULL;
index 18f4d1e98c46945c63c0a2c80c64e1fcc198bde8..2b82c5c723e159a1f393724dbca259f12d755050 100644 (file)
@@ -445,12 +445,12 @@ static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id);
 
 static struct pci_device_id snd_audiopci_ids[] = {
 #ifdef CHIP1370
-       { 0x1274, 0x5000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* ES1370 */
+       { PCI_VDEVICE(ENSONIQ, 0x5000), 0, },   /* ES1370 */
 #endif
 #ifdef CHIP1371
-       { 0x1274, 0x1371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* ES1371 */
-       { 0x1274, 0x5880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* ES1373 - CT5880 */
-       { 0x1102, 0x8938, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* Ectiva EV1938 */
+       { PCI_VDEVICE(ENSONIQ, 0x1371), 0, },   /* ES1371 */
+       { PCI_VDEVICE(ENSONIQ, 0x5880), 0, },   /* ES1373 - CT5880 */
+       { PCI_VDEVICE(ECTIVA, 0x8938), 0, },    /* Ectiva EV1938 */
 #endif
        { 0, }
 };
index fbd2ac09aa34a667ef0220e9ac51bbd4a7072890..820318ee62c179872a2354e656b438e8ed74504d 100644 (file)
@@ -244,7 +244,7 @@ struct es1938 {
 static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id);
 
 static struct pci_device_id snd_es1938_ids[] = {
-        { 0x125d, 0x1969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* Solo-1 */
+       { PCI_VDEVICE(ESS, 0x1969), 0, },   /* Solo-1 */
        { 0, }
 };
 
index 0d0cdbdb44867e88d12e6c7cb088ac7b13a37a94..cecf1ffeeaaa448c50d499101fa890ce2a921db4 100644 (file)
@@ -107,7 +107,7 @@ MODULE_PARM_DESC(dxr_enable, "Enable DXR support for Terratec DMX6FIRE.");
 
 
 static const struct pci_device_id snd_ice1712_ids[] = {
-       { PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_ICE_1712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },   /* ICE1712 */
+       { PCI_VDEVICE(ICE, PCI_DEVICE_ID_ICE_1712), 0 },   /* ICE1712 */
        { 0, }
 };
 
index adc909ec125c24e51bfa6bac490cfcd05680c3b5..9da2dae64c5b6e565ffb85d7b184a62d3c07af99 100644 (file)
@@ -379,6 +379,15 @@ struct snd_ice1712 {
        unsigned char (*set_mclk)(struct snd_ice1712 *ice, unsigned int rate);
        void (*set_spdif_clock)(struct snd_ice1712 *ice);
 
+#ifdef CONFIG_PM
+       int (*pm_suspend)(struct snd_ice1712 *);
+       int (*pm_resume)(struct snd_ice1712 *);
+       int pm_suspend_enabled:1;
+       int pm_saved_is_spdif_master:1;
+       unsigned int pm_saved_spdif_ctrl;
+       unsigned char pm_saved_spdif_cfg;
+       unsigned int pm_saved_route;
+#endif
 };
 
 
index 36ade77cf37116216d6424dc3871e23377ee79cd..af6e001486219083b172b345ef94c987cd74d242 100644 (file)
@@ -93,7 +93,7 @@ MODULE_PARM_DESC(model, "Use the given board model.");
 
 /* Both VT1720 and VT1724 have the same PCI IDs */
 static const struct pci_device_id snd_vt1724_ids[] = {
-       { PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_VT1724, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { PCI_VDEVICE(ICE, PCI_DEVICE_ID_VT1724), 0 },
        { 0, }
 };
 
@@ -560,6 +560,7 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
                spin_lock(&ice->reg_lock);
                old = inb(ICEMT1724(ice, DMA_CONTROL));
                if (cmd == SNDRV_PCM_TRIGGER_START)
@@ -570,6 +571,10 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
                spin_unlock(&ice->reg_lock);
                break;
 
+       case SNDRV_PCM_TRIGGER_RESUME:
+               /* apps will have to restart stream */
+               break;
+
        default:
                return -EINVAL;
        }
@@ -2262,7 +2267,7 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
 
 
 
-static void __devinit snd_vt1724_chip_reset(struct snd_ice1712 *ice)
+static void snd_vt1724_chip_reset(struct snd_ice1712 *ice)
 {
        outb(VT1724_RESET , ICEREG1724(ice, CONTROL));
        inb(ICEREG1724(ice, CONTROL)); /* pci posting flush */
@@ -2272,7 +2277,7 @@ static void __devinit snd_vt1724_chip_reset(struct snd_ice1712 *ice)
        msleep(10);
 }
 
-static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice)
+static int snd_vt1724_chip_init(struct snd_ice1712 *ice)
 {
        outb(ice->eeprom.data[ICE_EEP2_SYSCONF], ICEREG1724(ice, SYS_CFG));
        outb(ice->eeprom.data[ICE_EEP2_ACLINK], ICEREG1724(ice, AC97_CFG));
@@ -2287,6 +2292,14 @@ static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice)
 
        outb(0, ICEREG1724(ice, POWERDOWN));
 
+       /* MPU_RX and TX irq masks are cleared later dynamically */
+       outb(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX , ICEREG1724(ice, IRQMASK));
+
+       /* don't handle FIFO overrun/underruns (just yet),
+        * since they cause machine lockups
+        */
+       outb(VT1724_MULTI_FIFO_ERR, ICEMT1724(ice, DMA_INT_MASK));
+
        return 0;
 }
 
@@ -2431,6 +2444,8 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
        snd_vt1724_proc_init(ice);
        synchronize_irq(pci->irq);
 
+       card->private_data = ice;
+
        err = pci_request_regions(pci, "ICE1724");
        if (err < 0) {
                kfree(ice);
@@ -2459,14 +2474,6 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
                return -EIO;
        }
 
-       /* MPU_RX and TX irq masks are cleared later dynamically */
-       outb(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX , ICEREG1724(ice, IRQMASK));
-
-       /* don't handle FIFO overrun/underruns (just yet),
-        * since they cause machine lockups
-        */
-       outb(VT1724_MULTI_FIFO_ERR, ICEMT1724(ice, DMA_INT_MASK));
-
        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops);
        if (err < 0) {
                snd_vt1724_free(ice);
@@ -2650,11 +2657,96 @@ static void __devexit snd_vt1724_remove(struct pci_dev *pci)
        pci_set_drvdata(pci, NULL);
 }
 
+#ifdef CONFIG_PM
+static int snd_vt1724_suspend(struct pci_dev *pci, pm_message_t state)
+{
+       struct snd_card *card = pci_get_drvdata(pci);
+       struct snd_ice1712 *ice = card->private_data;
+
+       if (!ice->pm_suspend_enabled)
+               return 0;
+
+       snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+
+       snd_pcm_suspend_all(ice->pcm);
+       snd_pcm_suspend_all(ice->pcm_pro);
+       snd_pcm_suspend_all(ice->pcm_ds);
+       snd_ac97_suspend(ice->ac97);
+
+       spin_lock_irq(&ice->reg_lock);
+       ice->pm_saved_is_spdif_master = ice->is_spdif_master(ice);
+       ice->pm_saved_spdif_ctrl = inw(ICEMT1724(ice, SPDIF_CTRL));
+       ice->pm_saved_spdif_cfg = inb(ICEREG1724(ice, SPDIF_CFG));
+       ice->pm_saved_route = inl(ICEMT1724(ice, ROUTE_PLAYBACK));
+       spin_unlock_irq(&ice->reg_lock);
+
+       if (ice->pm_suspend)
+               ice->pm_suspend(ice);
+
+       pci_disable_device(pci);
+       pci_save_state(pci);
+       pci_set_power_state(pci, pci_choose_state(pci, state));
+       return 0;
+}
+
+static int snd_vt1724_resume(struct pci_dev *pci)
+{
+       struct snd_card *card = pci_get_drvdata(pci);
+       struct snd_ice1712 *ice = card->private_data;
+
+       if (!ice->pm_suspend_enabled)
+               return 0;
+
+       pci_set_power_state(pci, PCI_D0);
+       pci_restore_state(pci);
+
+       if (pci_enable_device(pci) < 0) {
+               snd_card_disconnect(card);
+               return -EIO;
+       }
+
+       pci_set_master(pci);
+
+       snd_vt1724_chip_reset(ice);
+
+       if (snd_vt1724_chip_init(ice) < 0) {
+               snd_card_disconnect(card);
+               return -EIO;
+       }
+
+       if (ice->pm_resume)
+               ice->pm_resume(ice);
+
+       if (ice->pm_saved_is_spdif_master) {
+               /* switching to external clock via SPDIF */
+               ice->set_spdif_clock(ice);
+       } else {
+               /* internal on-card clock */
+               snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1);
+       }
+
+       update_spdif_bits(ice, ice->pm_saved_spdif_ctrl);
+
+       outb(ice->pm_saved_spdif_cfg, ICEREG1724(ice, SPDIF_CFG));
+       outl(ice->pm_saved_route, ICEMT1724(ice, ROUTE_PLAYBACK));
+
+       if (ice->ac97)
+               snd_ac97_resume(ice->ac97);
+
+       snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+       return 0;
+}
+#endif
+
 static struct pci_driver driver = {
        .name = "ICE1724",
        .id_table = snd_vt1724_ids,
        .probe = snd_vt1724_probe,
        .remove = __devexit_p(snd_vt1724_remove),
+#ifdef CONFIG_PM
+       .suspend = snd_vt1724_suspend,
+       .resume = snd_vt1724_resume,
+#endif
 };
 
 static int __init alsa_card_ice1724_init(void)
index 043a93879bd56eb3913541ea1f76f03a480f630a..c75515f5be6f0cd7ac4910cf52e930799984535c 100644 (file)
@@ -1077,7 +1077,7 @@ static int __devinit prodigy_hifi_init(struct snd_ice1712 *ice)
 /*
  * initialize the chip
  */
-static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice)
+static void ak4396_init(struct snd_ice1712 *ice)
 {
        static unsigned short ak4396_inits[] = {
                AK4396_CTRL1,      0x87,   /* I2S Normal Mode, 24 bit */
@@ -1087,9 +1087,37 @@ static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice)
                AK4396_RCH_ATT,  0x00,
        };
 
-       struct prodigy_hifi_spec *spec;
        unsigned int i;
 
+       /* initialize ak4396 codec */
+       /* reset codec */
+       ak4396_write(ice, AK4396_CTRL1, 0x86);
+       msleep(100);
+       ak4396_write(ice, AK4396_CTRL1, 0x87);
+
+       for (i = 0; i < ARRAY_SIZE(ak4396_inits); i += 2)
+               ak4396_write(ice, ak4396_inits[i], ak4396_inits[i+1]);
+}
+
+#ifdef CONFIG_PM
+static int __devinit prodigy_hd2_resume(struct snd_ice1712 *ice)
+{
+       /* initialize ak4396 codec and restore previous mixer volumes */
+       struct prodigy_hifi_spec *spec = ice->spec;
+       int i;
+       mutex_lock(&ice->gpio_mutex);
+       ak4396_init(ice);
+       for (i = 0; i < 2; i++)
+               ak4396_write(ice, AK4396_LCH_ATT + i, spec->vol[i] & 0xff);
+       mutex_unlock(&ice->gpio_mutex);
+       return 0;
+}
+#endif
+
+static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice)
+{
+       struct prodigy_hifi_spec *spec;
+
        ice->vt1720 = 0;
        ice->vt1724 = 1;
 
@@ -1112,14 +1140,12 @@ static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice)
                return -ENOMEM;
        ice->spec = spec;
 
-       /* initialize ak4396 codec */
-       /* reset codec */
-       ak4396_write(ice, AK4396_CTRL1, 0x86);
-       msleep(100);
-       ak4396_write(ice, AK4396_CTRL1, 0x87);
-                       
-       for (i = 0; i < ARRAY_SIZE(ak4396_inits); i += 2)
-               ak4396_write(ice, ak4396_inits[i], ak4396_inits[i+1]);
+#ifdef CONFIG_PM
+       ice->pm_resume = &prodigy_hd2_resume;
+       ice->pm_suspend_enabled = 1;
+#endif
+
+       ak4396_init(ice);
 
        return 0;
 }
index 8aa5687f392a10abf1310015d8ddeb57e73d070a..754867ed4785f248dc15f9d2680ba4e607932776 100644 (file)
@@ -421,29 +421,29 @@ struct intel8x0 {
 };
 
 static struct pci_device_id snd_intel8x0_ids[] = {
-       { 0x8086, 0x2415, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801AA */
-       { 0x8086, 0x2425, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82901AB */
-       { 0x8086, 0x2445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801BA */
-       { 0x8086, 0x2485, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH3 */
-       { 0x8086, 0x24c5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH4 */
-       { 0x8086, 0x24d5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH5 */
-       { 0x8086, 0x25a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ESB */
-       { 0x8086, 0x266e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH6 */
-       { 0x8086, 0x27de, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ICH7 */
-       { 0x8086, 0x2698, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL_ICH4 }, /* ESB2 */
-       { 0x8086, 0x7195, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 440MX */
-       { 0x1039, 0x7012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS },   /* SI7012 */
-       { 0x10de, 0x01b1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },        /* NFORCE */
-       { 0x10de, 0x003a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },        /* MCP04 */
-       { 0x10de, 0x006a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },        /* NFORCE2 */
-       { 0x10de, 0x0059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },        /* CK804 */
-       { 0x10de, 0x008a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },        /* CK8 */
-       { 0x10de, 0x00da, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },        /* NFORCE3 */
-       { 0x10de, 0x00ea, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },        /* CK8S */
-       { 0x10de, 0x026b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE },        /* MCP51 */
-       { 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD8111 */
-       { 0x1022, 0x7445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD768 */
-       { 0x10b9, 0x5455, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALI },   /* Ali5455 */
+       { PCI_VDEVICE(INTEL, 0x2415), DEVICE_INTEL },   /* 82801AA */
+       { PCI_VDEVICE(INTEL, 0x2425), DEVICE_INTEL },   /* 82901AB */
+       { PCI_VDEVICE(INTEL, 0x2445), DEVICE_INTEL },   /* 82801BA */
+       { PCI_VDEVICE(INTEL, 0x2485), DEVICE_INTEL },   /* ICH3 */
+       { PCI_VDEVICE(INTEL, 0x24c5), DEVICE_INTEL_ICH4 }, /* ICH4 */
+       { PCI_VDEVICE(INTEL, 0x24d5), DEVICE_INTEL_ICH4 }, /* ICH5 */
+       { PCI_VDEVICE(INTEL, 0x25a6), DEVICE_INTEL_ICH4 }, /* ESB */
+       { PCI_VDEVICE(INTEL, 0x266e), DEVICE_INTEL_ICH4 }, /* ICH6 */
+       { PCI_VDEVICE(INTEL, 0x27de), DEVICE_INTEL_ICH4 }, /* ICH7 */
+       { PCI_VDEVICE(INTEL, 0x2698), DEVICE_INTEL_ICH4 }, /* ESB2 */
+       { PCI_VDEVICE(INTEL, 0x7195), DEVICE_INTEL },   /* 440MX */
+       { PCI_VDEVICE(SI, 0x7012), DEVICE_SIS },        /* SI7012 */
+       { PCI_VDEVICE(NVIDIA, 0x01b1), DEVICE_NFORCE }, /* NFORCE */
+       { PCI_VDEVICE(NVIDIA, 0x003a), DEVICE_NFORCE }, /* MCP04 */
+       { PCI_VDEVICE(NVIDIA, 0x006a), DEVICE_NFORCE }, /* NFORCE2 */
+       { PCI_VDEVICE(NVIDIA, 0x0059), DEVICE_NFORCE }, /* CK804 */
+       { PCI_VDEVICE(NVIDIA, 0x008a), DEVICE_NFORCE }, /* CK8 */
+       { PCI_VDEVICE(NVIDIA, 0x00da), DEVICE_NFORCE }, /* NFORCE3 */
+       { PCI_VDEVICE(NVIDIA, 0x00ea), DEVICE_NFORCE }, /* CK8S */
+       { PCI_VDEVICE(NVIDIA, 0x026b), DEVICE_NFORCE }, /* MCP51 */
+       { PCI_VDEVICE(AMD, 0x746d), DEVICE_INTEL },     /* AMD8111 */
+       { PCI_VDEVICE(AMD, 0x7445), DEVICE_INTEL },     /* AMD768 */
+       { PCI_VDEVICE(AL, 0x5455), DEVICE_ALI },   /* Ali5455 */
        { 0, }
 };
 
@@ -1954,6 +1954,18 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
                .name = "Sony S1XP",
                .type = AC97_TUNE_INV_EAPD
        },
+       {
+               .subvendor = 0x104d,
+               .subdevice = 0x81c0,
+               .name = "Sony VAIO VGN-T350P", /*AD1981B*/
+               .type = AC97_TUNE_INV_EAPD
+       },
+       {
+               .subvendor = 0x104d,
+               .subdevice = 0x81c5,
+               .name = "Sony VAIO VGN-B1VP", /*AD1981B*/
+               .type = AC97_TUNE_INV_EAPD
+       },
        {
                .subvendor = 0x1043,
                .subdevice = 0x80f3,
index 6ec0fc50d6be16bf064b27ca83e61b172deb045e..9e7d12e7673f52abc3d02518da23a51c6d0ff59a 100644 (file)
@@ -220,24 +220,24 @@ struct intel8x0m {
 };
 
 static struct pci_device_id snd_intel8x0m_ids[] = {
-       { 0x8086, 0x2416, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801AA */
-       { 0x8086, 0x2426, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82901AB */
-       { 0x8086, 0x2446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 82801BA */
-       { 0x8086, 0x2486, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH3 */
-       { 0x8086, 0x24c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH4 */
-       { 0x8086, 0x24d6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH5 */
-       { 0x8086, 0x266d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH6 */
-       { 0x8086, 0x27dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH7 */
-       { 0x8086, 0x7196, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* 440MX */
-       { 0x1022, 0x7446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD768 */
-       { 0x1039, 0x7013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS },   /* SI7013 */
-       { 0x10de, 0x01c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE */
-       { 0x10de, 0x0069, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE2 */
-       { 0x10de, 0x0089, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE2s */
-       { 0x10de, 0x00d9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_NFORCE }, /* NFORCE3 */
+       { PCI_VDEVICE(INTEL, 0x2416), DEVICE_INTEL },   /* 82801AA */
+       { PCI_VDEVICE(INTEL, 0x2426), DEVICE_INTEL },   /* 82901AB */
+       { PCI_VDEVICE(INTEL, 0x2446), DEVICE_INTEL },   /* 82801BA */
+       { PCI_VDEVICE(INTEL, 0x2486), DEVICE_INTEL },   /* ICH3 */
+       { PCI_VDEVICE(INTEL, 0x24c6), DEVICE_INTEL }, /* ICH4 */
+       { PCI_VDEVICE(INTEL, 0x24d6), DEVICE_INTEL }, /* ICH5 */
+       { PCI_VDEVICE(INTEL, 0x266d), DEVICE_INTEL },   /* ICH6 */
+       { PCI_VDEVICE(INTEL, 0x27dd), DEVICE_INTEL },   /* ICH7 */
+       { PCI_VDEVICE(INTEL, 0x7196), DEVICE_INTEL },   /* 440MX */
+       { PCI_VDEVICE(AMD, 0x7446), DEVICE_INTEL },     /* AMD768 */
+       { PCI_VDEVICE(SI, 0x7013), DEVICE_SIS },        /* SI7013 */
+       { PCI_VDEVICE(NVIDIA, 0x01c1), DEVICE_NFORCE }, /* NFORCE */
+       { PCI_VDEVICE(NVIDIA, 0x0069), DEVICE_NFORCE }, /* NFORCE2 */
+       { PCI_VDEVICE(NVIDIA, 0x0089), DEVICE_NFORCE }, /* NFORCE2s */
+       { PCI_VDEVICE(NVIDIA, 0x00d9), DEVICE_NFORCE }, /* NFORCE3 */
 #if 0
-       { 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD8111 */
-       { 0x10b9, 0x5455, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALI },   /* Ali5455 */
+       { PCI_VDEVICE(AMD, 0x746d), DEVICE_INTEL },     /* AMD8111 */
+       { PCI_VDEVICE(AL, 0x5455), DEVICE_ALI },   /* Ali5455 */
 #endif
        { 0, }
 };
index 18da2ef04d097903a7ae3097e811632a1ba2774b..11b8c6514b3d8ecf5da061687d9c949e0d771d5a 100644 (file)
@@ -654,13 +654,12 @@ static int __devinit lx_init_ethersound_config(struct lx6464es *chip)
        int i;
        u32 orig_conf_es = lx_dsp_reg_read(chip, eReg_CONFES);
 
-       u32 default_conf_es = (64 << IOCR_OUTPUTS_OFFSET) |
+       /* configure 64 io channels */
+       u32 conf_es = (orig_conf_es & CONFES_READ_PART_MASK) |
                (64 << IOCR_INPUTS_OFFSET) |
+               (64 << IOCR_OUTPUTS_OFFSET) |
                (FREQ_RATIO_SINGLE_MODE << FREQ_RATIO_OFFSET);
 
-       u32 conf_es = (orig_conf_es & CONFES_READ_PART_MASK)
-               | (default_conf_es & CONFES_WRITE_PART_MASK);
-
        snd_printdd("->lx_init_ethersound\n");
 
        chip->freq_ratio = FREQ_RATIO_SINGLE_MODE;
index 012c010c8c89540e421440e7d988f2880bbd7a30..51afc048961d9855c39e321e523f9f526bd8acd3 100644 (file)
@@ -86,7 +86,6 @@ struct lx6464es {
 
        /* messaging */
        spinlock_t              msg_lock;          /* message spinlock */
-       atomic_t                send_message_locked;
        struct lx_rmh           rmh;
 
        /* configuration */
@@ -95,7 +94,6 @@ struct lx6464es {
        uint                    hardware_running[2];
        u32                     board_sample_rate; /* sample rate read from
                                                    * board */
-       u32                     sample_rate;       /* our sample rate */
        u16                     pcm_granularity;   /* board blocksize */
 
        /* dma */
index 5812780d6e89c70ab193adec0bceb51c577d5137..3086b751da4a59271b497e1a8605c3664d15a2ff 100644 (file)
@@ -314,98 +314,6 @@ static inline void lx_message_dump(struct lx_rmh *rmh)
 #define XILINX_POLL_NO_SLEEP    100
 #define XILINX_POLL_ITERATIONS  150
 
-#if 0 /* not used now */
-static int lx_message_send(struct lx6464es *chip, struct lx_rmh *rmh)
-{
-       u32 reg = ED_DSP_TIMED_OUT;
-       int dwloop;
-       int answer_received;
-
-       if (lx_dsp_reg_read(chip, eReg_CSM) & (Reg_CSM_MC | Reg_CSM_MR)) {
-               snd_printk(KERN_ERR LXP "PIOSendMessage eReg_CSM %x\n", reg);
-               return -EBUSY;
-       }
-
-       /* write command */
-       lx_dsp_reg_writebuf(chip, eReg_CRM1, rmh->cmd, rmh->cmd_len);
-
-       snd_BUG_ON(atomic_read(&chip->send_message_locked) != 0);
-       atomic_set(&chip->send_message_locked, 1);
-
-       /* MicoBlaze gogogo */
-       lx_dsp_reg_write(chip, eReg_CSM, Reg_CSM_MC);
-
-       /* wait for interrupt to answer */
-       for (dwloop = 0; dwloop != XILINX_TIMEOUT_MS; ++dwloop) {
-               answer_received = atomic_read(&chip->send_message_locked);
-               if (answer_received == 0)
-                       break;
-               msleep(1);
-       }
-
-       if (answer_received == 0) {
-               /* in Debug mode verify Reg_CSM_MR */
-               snd_BUG_ON(!(lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR));
-
-               /* command finished, read status */
-               if (rmh->dsp_stat == 0)
-                       reg = lx_dsp_reg_read(chip, eReg_CRM1);
-               else
-                       reg = 0;
-       } else {
-               int i;
-               snd_printk(KERN_WARNING LXP "TIMEOUT lx_message_send! "
-                          "Interrupts disabled?\n");
-
-               /* attente bit Reg_CSM_MR */
-               for (i = 0; i != XILINX_POLL_ITERATIONS; i++) {
-                       if ((lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR)) {
-                               if (rmh->dsp_stat == 0)
-                                       reg = lx_dsp_reg_read(chip, eReg_CRM1);
-                               else
-                                       reg = 0;
-                               goto polling_successful;
-                       }
-
-                       if (i > XILINX_POLL_NO_SLEEP)
-                               msleep(1);
-               }
-               snd_printk(KERN_WARNING LXP "TIMEOUT lx_message_send! "
-                          "polling failed\n");
-
-polling_successful:
-               atomic_set(&chip->send_message_locked, 0);
-       }
-
-       if ((reg & ERROR_VALUE) == 0) {
-               /* read response */
-               if (rmh->stat_len) {
-                       snd_BUG_ON(rmh->stat_len >= (REG_CRM_NUMBER-1));
-
-                       lx_dsp_reg_readbuf(chip, eReg_CRM2, rmh->stat,
-                                          rmh->stat_len);
-               }
-       } else
-               snd_printk(KERN_WARNING LXP "lx_message_send: error_value %x\n",
-                          reg);
-
-       /* clear Reg_CSM_MR */
-       lx_dsp_reg_write(chip, eReg_CSM, 0);
-
-       switch (reg) {
-       case ED_DSP_TIMED_OUT:
-               snd_printk(KERN_WARNING LXP "lx_message_send: dsp timeout\n");
-               return -ETIMEDOUT;
-
-       case ED_DSP_CRASHED:
-               snd_printk(KERN_WARNING LXP "lx_message_send: dsp crashed\n");
-               return -EAGAIN;
-       }
-
-       lx_message_dump(rmh);
-       return 0;
-}
-#endif /* not used now */
 
 static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh)
 {
@@ -423,7 +331,7 @@ static int lx_message_send_atomic(struct lx6464es *chip, struct lx_rmh *rmh)
        /* MicoBlaze gogogo */
        lx_dsp_reg_write(chip, eReg_CSM, Reg_CSM_MC);
 
-       /* wait for interrupt to answer */
+       /* wait for device to answer */
        for (dwloop = 0; dwloop != XILINX_TIMEOUT_MS * 1000; ++dwloop) {
                if (lx_dsp_reg_read(chip, eReg_CSM) & Reg_CSM_MR) {
                        if (rmh->dsp_stat == 0)
@@ -1175,10 +1083,6 @@ static int lx_interrupt_ack(struct lx6464es *chip, u32 *r_irqsrc,
                *r_async_escmd = 1;
        }
 
-       if (irqsrc & MASK_SYS_STATUS_CMD_DONE)
-               /* xilinx command notification */
-               atomic_set(&chip->send_message_locked, 0);
-
        if (irq_async) {
                /* snd_printd("interrupt: async event pending\n"); */
                *r_async_pending = 1;
index 82bc5b9e7629db8537e66af68624feb14e0d17e1..a83d1968a8450f49816add1bf2bbc2ffbba962c6 100644 (file)
@@ -61,7 +61,7 @@ MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard.");
  */
 
 static struct pci_device_id snd_mixart_ids[] = {
-       { 0x1057, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* MC8240 */
+       { PCI_VDEVICE(MOTOROLA, 0x0003), 0, }, /* MC8240 */
        { 0, }
 };
 
index 522a040855d41e7321414cfbd2b5c3e22b0d47a8..97a0731331a15f6ae2a4be6d16acce0f5e85915d 100644 (file)
@@ -263,9 +263,9 @@ struct nm256 {
  * PCI ids
  */
 static struct pci_device_id snd_nm256_ids[] = {
-       {PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       {PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       {PCI_VENDOR_ID_NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO), 0},
+       {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO), 0},
+       {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO), 0},
        {0,},
 };
 
index c1eb923f2ac94b63b83318e688d98fdcd0dff931..09b2b2a36df5200f35e75af487673a6ea9e215ce 100644 (file)
@@ -215,17 +215,8 @@ EXPORT_SYMBOL(oxygen_write_spi);
 
 void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data)
 {
-       unsigned long timeout;
-
        /* should not need more than about 300 us */
-       timeout = jiffies + msecs_to_jiffies(1);
-       do {
-               if (!(oxygen_read16(chip, OXYGEN_2WIRE_BUS_STATUS)
-                     & OXYGEN_2WIRE_BUSY))
-                       break;
-               udelay(1);
-               cond_resched();
-       } while (time_after_eq(timeout, jiffies));
+       msleep(1);
 
        oxygen_write8(chip, OXYGEN_2WIRE_MAP, map);
        oxygen_write8(chip, OXYGEN_2WIRE_DATA, data);
index 312251d396965404b96311bcc7cda92f409b600b..9a8936e207448e792218d1c3aee804fb09db30e6 100644 (file)
@@ -260,6 +260,9 @@ oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[])
         * chip didn't if the first EEPROM word was overwritten.
         */
        subdevice = oxygen_read_eeprom(chip, 2);
+       /* use default ID if EEPROM is missing */
+       if (subdevice == 0xffff)
+               subdevice = 0x8788;
        /*
         * We use only the subsystem device ID for searching because it is
         * unique even without the subsystem vendor ID, which may have been
index 304da169bfdcbeacb669a338a25a5f4c12271de9..5401c547c4e33f75e3e8f5186b09d2129b16fc43 100644 (file)
@@ -575,8 +575,10 @@ static int ac97_switch_put(struct snd_kcontrol *ctl,
 static int ac97_volume_info(struct snd_kcontrol *ctl,
                            struct snd_ctl_elem_info *info)
 {
+       int stereo = (ctl->private_value >> 16) & 1;
+
        info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-       info->count = 2;
+       info->count = stereo ? 2 : 1;
        info->value.integer.min = 0;
        info->value.integer.max = 0x1f;
        return 0;
@@ -587,6 +589,7 @@ static int ac97_volume_get(struct snd_kcontrol *ctl,
 {
        struct oxygen *chip = ctl->private_data;
        unsigned int codec = (ctl->private_value >> 24) & 1;
+       int stereo = (ctl->private_value >> 16) & 1;
        unsigned int index = ctl->private_value & 0xff;
        u16 reg;
 
@@ -594,7 +597,8 @@ static int ac97_volume_get(struct snd_kcontrol *ctl,
        reg = oxygen_read_ac97(chip, codec, index);
        mutex_unlock(&chip->mutex);
        value->value.integer.value[0] = 31 - (reg & 0x1f);
-       value->value.integer.value[1] = 31 - ((reg >> 8) & 0x1f);
+       if (stereo)
+               value->value.integer.value[1] = 31 - ((reg >> 8) & 0x1f);
        return 0;
 }
 
@@ -603,6 +607,7 @@ static int ac97_volume_put(struct snd_kcontrol *ctl,
 {
        struct oxygen *chip = ctl->private_data;
        unsigned int codec = (ctl->private_value >> 24) & 1;
+       int stereo = (ctl->private_value >> 16) & 1;
        unsigned int index = ctl->private_value & 0xff;
        u16 oldreg, newreg;
        int change;
@@ -612,8 +617,11 @@ static int ac97_volume_put(struct snd_kcontrol *ctl,
        newreg = oldreg;
        newreg = (newreg & ~0x1f) |
                (31 - (value->value.integer.value[0] & 0x1f));
-       newreg = (newreg & ~0x1f00) |
-               ((31 - (value->value.integer.value[0] & 0x1f)) << 8);
+       if (stereo)
+               newreg = (newreg & ~0x1f00) |
+                       ((31 - (value->value.integer.value[1] & 0x1f)) << 8);
+       else
+               newreg = (newreg & ~0x1f00) | ((newreg & 0x1f) << 8);
        change = newreg != oldreg;
        if (change)
                oxygen_write_ac97(chip, codec, index, newreg);
@@ -673,7 +681,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl,
                .private_value = ((codec) << 24) | ((invert) << 16) | \
                                 ((bitnr) << 8) | (index), \
        }
-#define AC97_VOLUME(xname, codec, index) { \
+#define AC97_VOLUME(xname, codec, index, stereo) { \
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
                .name = xname, \
                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
@@ -682,7 +690,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl,
                .get = ac97_volume_get, \
                .put = ac97_volume_put, \
                .tlv = { .p = ac97_db_scale, }, \
-               .private_value = ((codec) << 24) | (index), \
+               .private_value = ((codec) << 24) | ((stereo) << 16) | (index), \
        }
 
 static DECLARE_TLV_DB_SCALE(monitor_db_scale, -1000, 1000, 0);
@@ -882,18 +890,18 @@ static const struct {
 };
 
 static const struct snd_kcontrol_new ac97_controls[] = {
-       AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC),
+       AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC, 0),
        AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1),
        AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0),
        AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1),
-       AC97_VOLUME("CD Capture Volume", 0, AC97_CD),
+       AC97_VOLUME("CD Capture Volume", 0, AC97_CD, 1),
        AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1),
-       AC97_VOLUME("Aux Capture Volume", 0, AC97_AUX),
+       AC97_VOLUME("Aux Capture Volume", 0, AC97_AUX, 1),
        AC97_SWITCH("Aux Capture Switch", 0, AC97_AUX, 15, 1),
 };
 
 static const struct snd_kcontrol_new ac97_fp_controls[] = {
-       AC97_VOLUME("Front Panel Playback Volume", 1, AC97_HEADPHONE),
+       AC97_VOLUME("Front Panel Playback Volume", 1, AC97_HEADPHONE, 1),
        AC97_SWITCH("Front Panel Playback Switch", 1, AC97_HEADPHONE, 15, 1),
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
index 3b5ca70c9d4d2745223ac6f66102f8fd78e11161..ef2345d82b8652c55df39623fc9ca6e2f6d85f87 100644 (file)
@@ -469,9 +469,11 @@ static int oxygen_multich_hw_params(struct snd_pcm_substream *substream,
        oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT,
                              oxygen_rate(hw_params) |
                              chip->model.dac_i2s_format |
+                             oxygen_i2s_mclk(hw_params) |
                              oxygen_i2s_bits(hw_params),
                              OXYGEN_I2S_RATE_MASK |
                              OXYGEN_I2S_FORMAT_MASK |
+                             OXYGEN_I2S_MCLK_MASK |
                              OXYGEN_I2S_BITS_MASK);
        oxygen_update_dac_routing(chip);
        oxygen_update_spdif_source(chip);
index bf971f7cfdc652984d4824576306e96aaa88b4d6..6ebcb6bdd7129eb8dd04daf344aad880aabf8ce9 100644 (file)
@@ -635,6 +635,8 @@ static void xonar_d2_resume(struct oxygen *chip)
 
 static void xonar_d1_resume(struct oxygen *chip)
 {
+       oxygen_set_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC);
+       msleep(1);
        cs43xx_init(chip);
        xonar_enable_output(chip);
 }
index 235a71e5ac8de6782f9d24027a347b5dc7852046..b5ca02e2038c9bb42c35c8a194c57974e15b6686 100644 (file)
@@ -2197,9 +2197,12 @@ static int __init alsa_card_riptide_init(void)
        if (err < 0)
                return err;
 #if defined(SUPPORT_JOYSTICK)
-       pci_register_driver(&joystick_driver);
+       err = pci_register_driver(&joystick_driver);
+       /* On failure unregister formerly registered audio driver */
+       if (err < 0)
+               pci_unregister_driver(&driver);
 #endif
-       return 0;
+       return err;
 }
 
 static void __exit alsa_card_riptide_exit(void)
index d7b966e7c4cf69270358a6070979e904e072f3d4..f977dba7cbd09462ac760219711c04dbb189ea0e 100644 (file)
@@ -227,12 +227,9 @@ struct rme32 {
 };
 
 static struct pci_device_id snd_rme32_ids[] = {
-       {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
-       {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
-       {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_PRO,
-        PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
+       {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32), 0,},
+       {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8), 0,},
+       {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_PRO), 0,},
        {0,}
 };
 
index 55fb1c131f5809a1b2b62383c99c3ac6037e90c8..2ba5c0fd55dbb7adc590e568e0b78350124ffd91 100644 (file)
@@ -232,14 +232,10 @@ struct rme96 {
 };
 
 static struct pci_device_id snd_rme96_ids[] = {
-       { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-       { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-       { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-       { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST,
-         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, 
+       { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96), 0, },
+       { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8), 0, },
+       { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO), 0, },
+       { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST), 0, },
        { 0, }
 };
 
index 3da5c029f93bc763ad25322ee0cfe7e1eb356728..7bb827c7d8061bfea72e0c2579015f8668bbebc9 100644 (file)
@@ -3294,15 +3294,33 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
        char *clock_source;
        int x;
 
-       if (hdsp_check_for_iobox (hdsp)) {
-               snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n");
+       status = hdsp_read(hdsp, HDSP_statusRegister);
+       status2 = hdsp_read(hdsp, HDSP_status2Register);
+
+       snd_iprintf(buffer, "%s (Card #%d)\n", hdsp->card_name,
+                   hdsp->card->number + 1);
+       snd_iprintf(buffer, "Buffers: capture %p playback %p\n",
+                   hdsp->capture_buffer, hdsp->playback_buffer);
+       snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
+                   hdsp->irq, hdsp->port, (unsigned long)hdsp->iobase);
+       snd_iprintf(buffer, "Control register: 0x%x\n", hdsp->control_register);
+       snd_iprintf(buffer, "Control2 register: 0x%x\n",
+                   hdsp->control2_register);
+       snd_iprintf(buffer, "Status register: 0x%x\n", status);
+       snd_iprintf(buffer, "Status2 register: 0x%x\n", status2);
+
+       if (hdsp_check_for_iobox(hdsp)) {
+               snd_iprintf(buffer, "No I/O box connected.\n"
+                           "Please connect one and upload firmware.\n");
                return;
-        }
+       }
 
        if (hdsp_check_for_firmware(hdsp, 0)) {
                if (hdsp->state & HDSP_FirmwareCached) {
                        if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
-                               snd_iprintf(buffer, "Firmware loading from cache failed, please upload manually.\n");
+                               snd_iprintf(buffer, "Firmware loading from "
+                                           "cache failed, "
+                                           "please upload manually.\n");
                                return;
                        }
                } else {
@@ -3319,18 +3337,6 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
                }
        }
 
-       status = hdsp_read(hdsp, HDSP_statusRegister);
-       status2 = hdsp_read(hdsp, HDSP_status2Register);
-
-       snd_iprintf(buffer, "%s (Card #%d)\n", hdsp->card_name, hdsp->card->number + 1);
-       snd_iprintf(buffer, "Buffers: capture %p playback %p\n",
-                   hdsp->capture_buffer, hdsp->playback_buffer);
-       snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
-                   hdsp->irq, hdsp->port, (unsigned long)hdsp->iobase);
-       snd_iprintf(buffer, "Control register: 0x%x\n", hdsp->control_register);
-       snd_iprintf(buffer, "Control2 register: 0x%x\n", hdsp->control2_register);
-       snd_iprintf(buffer, "Status register: 0x%x\n", status);
-       snd_iprintf(buffer, "Status2 register: 0x%x\n", status2);
        snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff);
        snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0));
        snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0));
@@ -3351,7 +3357,6 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 
        snd_iprintf(buffer, "\n");
 
-
        switch (hdsp_clock_source(hdsp)) {
        case HDSP_CLOCK_SOURCE_AUTOSYNC:
                clock_source = "AutoSync";
index 7dc60ad4772e33b76027efe35265991ffa3ea8ef..1f6406c4534d455120efcdd0c1c6e9e3b98a9173 100644 (file)
@@ -243,7 +243,7 @@ struct sonicvibes {
 };
 
 static struct pci_device_id snd_sonic_ids[] = {
-       { 0x5333, 0xca00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+       { PCI_VDEVICE(S3, 0xca00), 0, },
         { 0, }
 };
 
index 949fcaf6b70ed9454ecd373ec052e8e7b7800fc9..acfa4760da49e3afb147b438897fbdb03b547239 100644 (file)
@@ -402,9 +402,9 @@ struct via82xx {
 
 static struct pci_device_id snd_via82xx_ids[] = {
        /* 0x1106, 0x3058 */
-       { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA686, },     /* 686A */
+       { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C686_5), TYPE_CARD_VIA686, },    /* 686A */
        /* 0x1106, 0x3059 */
-       { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA8233, },      /* VT8233 */
+       { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233_5), TYPE_CARD_VIA8233, },     /* VT8233 */
        { 0, }
 };
 
index 0d54e3503c1e6edc4ad80d23f246aa3b034aab12..47eb61561dfcad83b0bd7c22fe91f5ef9519856e 100644 (file)
@@ -261,7 +261,7 @@ struct via82xx_modem {
 };
 
 static struct pci_device_id snd_via82xx_modem_ids[] = {
-       { 0x1106, 0x3068, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TYPE_CARD_VIA82XX_MODEM, },
+       { PCI_VDEVICE(VIA, 0x3068), TYPE_CARD_VIA82XX_MODEM, },
        { 0, }
 };
 
index 6416d3f0c7be8210559f1ad8dda61f1a974fc023..a69e774d0b138f46d373cab95bb78858e04c1f11 100644 (file)
@@ -885,10 +885,10 @@ static int vx_input_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
        struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
        struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
        if (ucontrol->value.integer.value[0] < 0 ||
-           ucontrol->value.integer.value[0] < MIC_LEVEL_MAX)
+           ucontrol->value.integer.value[0] > MIC_LEVEL_MAX)
                return -EINVAL;
        if (ucontrol->value.integer.value[1] < 0 ||
-           ucontrol->value.integer.value[1] < MIC_LEVEL_MAX)
+           ucontrol->value.integer.value[1] > MIC_LEVEL_MAX)
                return -EINVAL;
        mutex_lock(&_chip->mixer_mutex);
        if (chip->input_level[0] != ucontrol->value.integer.value[0] ||
index 4af66661f9b020b83956559847848b51647fde97..e6b18b90d4510afa4393d700110cc84200c2f5ef 100644 (file)
@@ -67,12 +67,12 @@ module_param_array(rear_switch, bool, NULL, 0444);
 MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch");
 
 static struct pci_device_id snd_ymfpci_ids[] = {
-        { 0x1073, 0x0004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* YMF724 */
-        { 0x1073, 0x000d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* YMF724F */
-        { 0x1073, 0x000a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* YMF740 */
-        { 0x1073, 0x000c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* YMF740C */
-        { 0x1073, 0x0010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* YMF744 */
-        { 0x1073, 0x0012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },   /* YMF754 */
+       { PCI_VDEVICE(YAMAHA, 0x0004), 0, },   /* YMF724 */
+       { PCI_VDEVICE(YAMAHA, 0x000d), 0, },   /* YMF724F */
+       { PCI_VDEVICE(YAMAHA, 0x000a), 0, },   /* YMF740 */
+       { PCI_VDEVICE(YAMAHA, 0x000c), 0, },   /* YMF740C */
+       { PCI_VDEVICE(YAMAHA, 0x0010), 0, },   /* YMF744 */
+       { PCI_VDEVICE(YAMAHA, 0x0012), 0, },   /* YMF754 */
        { 0, }
 };
 
index 2f0925236a1b9c532acaa4c4e6a0273f44a75d0a..5518371db13f25832f566870492eff6215c8e116 100644 (file)
@@ -834,7 +834,7 @@ static irqreturn_t snd_ymfpci_interrupt(int irq, void *dev_id)
        status = snd_ymfpci_readw(chip, YDSXGR_INTFLAG);
        if (status & 1) {
                if (chip->timer)
-                       snd_timer_interrupt(chip->timer, chip->timer->sticks);
+                       snd_timer_interrupt(chip->timer, chip->timer_ticks);
        }
        snd_ymfpci_writew(chip, YDSXGR_INTFLAG, status);
 
@@ -1885,8 +1885,18 @@ static int snd_ymfpci_timer_start(struct snd_timer *timer)
        unsigned int count;
 
        chip = snd_timer_chip(timer);
-       count = (timer->sticks << 1) - 1;
        spin_lock_irqsave(&chip->reg_lock, flags);
+       if (timer->sticks > 1) {
+               chip->timer_ticks = timer->sticks;
+               count = timer->sticks - 1;
+       } else {
+               /*
+                * Divisor 1 is not allowed; fake it by using divisor 2 and
+                * counting two ticks for each interrupt.
+                */
+               chip->timer_ticks = 2;
+               count = 2 - 1;
+       }
        snd_ymfpci_writew(chip, YDSXGR_TIMERCOUNT, count);
        snd_ymfpci_writeb(chip, YDSXGR_TIMERCTRL, 0x03);
        spin_unlock_irqrestore(&chip->reg_lock, flags);
@@ -1909,14 +1919,14 @@ static int snd_ymfpci_timer_precise_resolution(struct snd_timer *timer,
                                               unsigned long *num, unsigned long *den)
 {
        *num = 1;
-       *den = 48000;
+       *den = 96000;
        return 0;
 }
 
 static struct snd_timer_hardware snd_ymfpci_timer_hw = {
        .flags = SNDRV_TIMER_HW_AUTO,
-       .resolution = 20833, /* 1/fs = 20.8333...us */
-       .ticks = 0x8000,
+       .resolution = 10417, /* 1 / 96 kHz = 10.41666...us */
+       .ticks = 0x10000,
        .start = snd_ymfpci_timer_start,
        .stop = snd_ymfpci_timer_stop,
        .precise_resolution = snd_ymfpci_timer_precise_resolution,
index 835fa19ed461864018fb152aa3c41eb57261cb4b..d06f780bd7e84ad088163eb52e134c8c57188956 100644 (file)
@@ -59,6 +59,18 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter)
        strlcpy(info.type, "keywest", I2C_NAME_SIZE);
        info.addr = keywest_ctx->addr;
        keywest_ctx->client = i2c_new_device(adapter, &info);
+       if (!keywest_ctx->client)
+               return -ENODEV;
+       /*
+        * We know the driver is already loaded, so the device should be
+        * already bound. If not it means binding failed, and then there
+        * is no point in keeping the device instantiated.
+        */
+       if (!keywest_ctx->client->driver) {
+               i2c_unregister_device(keywest_ctx->client);
+               keywest_ctx->client = NULL;
+               return -ENODEV;
+       }
        
        /*
         * Let i2c-core delete that device on driver removal.
@@ -86,7 +98,7 @@ static const struct i2c_device_id keywest_i2c_id[] = {
        { }
 };
 
-struct i2c_driver keywest_driver = {
+static struct i2c_driver keywest_driver = {
        .driver = {
                .name = "PMac Keywest Audio",
        },
index d3e786a9a0a7ec08a69564700910ef49ac4f4927..b1749bc679794ba7910ab0a55d880ee4d7db0e1a 100644 (file)
@@ -29,6 +29,7 @@ source "sound/soc/au1x/Kconfig"
 source "sound/soc/blackfin/Kconfig"
 source "sound/soc/davinci/Kconfig"
 source "sound/soc/fsl/Kconfig"
+source "sound/soc/imx/Kconfig"
 source "sound/soc/omap/Kconfig"
 source "sound/soc/pxa/Kconfig"
 source "sound/soc/s3c24xx/Kconfig"
index 6f1e28de23cf325383824299f9eb33fdfe43bec3..0c5eac01bf2e5ffbc8d4691987c7097b90dce90a 100644 (file)
@@ -1,4 +1,4 @@
-snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o
+snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o
 
 obj-$(CONFIG_SND_SOC)  += snd-soc-core.o
 obj-$(CONFIG_SND_SOC)  += codecs/
@@ -7,6 +7,7 @@ obj-$(CONFIG_SND_SOC)   += au1x/
 obj-$(CONFIG_SND_SOC)  += blackfin/
 obj-$(CONFIG_SND_SOC)  += davinci/
 obj-$(CONFIG_SND_SOC)  += fsl/
+obj-$(CONFIG_SND_SOC)   += imx/
 obj-$(CONFIG_SND_SOC)  += omap/
 obj-$(CONFIG_SND_SOC)  += pxa/
 obj-$(CONFIG_SND_SOC)  += s3c24xx/
index 173a239a541c3c1611be7a372a39d1d24901e3ce..130b12118d4f8f93c2a2b0ac83fda0495c91f763 100644 (file)
 
 #define MCLK_RATE 12000000
 
-static struct clk *mclk;
-
-static int at91sam9g20ek_startup(struct snd_pcm_substream *substream)
-{
-       struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
-       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
-       int ret;
-
-       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
-               MCLK_RATE, SND_SOC_CLOCK_IN);
-       if (ret < 0) {
-               clk_disable(mclk);
-               return ret;
-       }
-
-       return 0;
-}
-
-static void at91sam9g20ek_shutdown(struct snd_pcm_substream *substream)
-{
-       struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
+/*
+ * As shipped the board does not have inputs.  However, it is relatively
+ * straightforward to modify the board to hook them up so support is left
+ * in the driver.
+ */
+#undef ENABLE_MIC_INPUT
 
-       dev_dbg(rtd->socdev->dev, "shutdown");
-}
+static struct clk *mclk;
 
 static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params)
@@ -87,102 +71,17 @@ static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
-       struct atmel_ssc_info *ssc_p = cpu_dai->private_data;
-       struct ssc_device *ssc = ssc_p->ssc;
        int ret;
 
-       unsigned int rate;
-       int cmr_div, period;
-
-       if (ssc == NULL) {
-               printk(KERN_INFO "at91sam9g20ek_hw_params: ssc is NULL!\n");
-               return -EINVAL;
-       }
-
        /* set codec DAI configuration */
        ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
-               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
        if (ret < 0)
                return ret;
 
        /* set cpu DAI configuration */
        ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
-               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-       if (ret < 0)
-               return ret;
-
-       /*
-        * The SSC clock dividers depend on the sample rate.  The CMR.DIV
-        * field divides the system master clock MCK to drive the SSC TK
-        * signal which provides the codec BCLK.  The TCMR.PERIOD and
-        * RCMR.PERIOD fields further divide the BCLK signal to drive
-        * the SSC TF and RF signals which provide the codec DACLRC and
-        * ADCLRC clocks.
-        *
-        * The dividers were determined through trial and error, where a
-        * CMR.DIV value is chosen such that the resulting BCLK value is
-        * divisible, or almost divisible, by (2 * sample rate), and then
-        * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
-        */
-       rate = params_rate(params);
-
-       switch (rate) {
-       case 8000:
-               cmr_div = 55;   /* BCLK = 133MHz/(2*55) = 1.209MHz */
-               period = 74;    /* LRC = BCLK/(2*(74+1)) ~= 8060,6Hz */
-               break;
-       case 11025:
-               cmr_div = 67;   /* BCLK = 133MHz/(2*60) = 1.108MHz */
-               period = 45;    /* LRC = BCLK/(2*(49+1)) = 11083,3Hz */
-               break;
-       case 16000:
-               cmr_div = 63;   /* BCLK = 133MHz/(2*63) = 1.055MHz */
-               period = 32;    /* LRC = BCLK/(2*(32+1)) = 15993,2Hz */
-               break;
-       case 22050:
-               cmr_div = 52;   /* BCLK = 133MHz/(2*52) = 1.278MHz */
-               period = 28;    /* LRC = BCLK/(2*(28+1)) = 22049Hz */
-               break;
-       case 32000:
-               cmr_div = 66;   /* BCLK = 133MHz/(2*66) = 1.007MHz */
-               period = 15;    /* LRC = BCLK/(2*(15+1)) = 31486,742Hz */
-               break;
-       case 44100:
-               cmr_div = 29;   /* BCLK = 133MHz/(2*29) = 2.293MHz */
-               period = 25;    /* LRC = BCLK/(2*(25+1)) = 44098Hz */
-               break;
-       case 48000:
-               cmr_div = 33;   /* BCLK = 133MHz/(2*33) = 2.015MHz */
-               period = 20;    /* LRC = BCLK/(2*(20+1)) = 47979,79Hz */
-               break;
-       case 88200:
-               cmr_div = 29;   /* BCLK = 133MHz/(2*29) = 2.293MHz */
-               period = 12;    /* LRC = BCLK/(2*(12+1)) = 88196Hz */
-               break;
-       case 96000:
-               cmr_div = 23;   /* BCLK = 133MHz/(2*23) = 2.891MHz */
-               period = 14;    /* LRC = BCLK/(2*(14+1)) = 96376Hz */
-               break;
-       default:
-               printk(KERN_WARNING "unsupported rate %d"
-                               " on at91sam9g20ek board\n", rate);
-               return -EINVAL;
-       }
-
-       /* set the MCK divider for BCLK */
-       ret = snd_soc_dai_set_clkdiv(cpu_dai, ATMEL_SSC_CMR_DIV, cmr_div);
-       if (ret < 0)
-               return ret;
-
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               /* set the BCLK divider for DACLRC */
-               ret = snd_soc_dai_set_clkdiv(cpu_dai,
-                                               ATMEL_SSC_TCMR_PERIOD, period);
-       } else {
-               /* set the BCLK divider for ADCLRC */
-               ret = snd_soc_dai_set_clkdiv(cpu_dai,
-                                               ATMEL_SSC_RCMR_PERIOD, period);
-       }
+               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
        if (ret < 0)
                return ret;
 
@@ -190,9 +89,7 @@ static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
 }
 
 static struct snd_soc_ops at91sam9g20ek_ops = {
-       .startup = at91sam9g20ek_startup,
        .hw_params = at91sam9g20ek_hw_params,
-       .shutdown = at91sam9g20ek_shutdown,
 };
 
 static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card,
@@ -241,10 +138,20 @@ static const struct snd_soc_dapm_route intercon[] = {
  */
 static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
 {
+       struct snd_soc_dai *codec_dai = &codec->dai[0];
+       int ret;
+
        printk(KERN_DEBUG
                        "at91sam9g20ek_wm8731 "
                        ": at91sam9g20ek_wm8731_init() called\n");
 
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
+               MCLK_RATE, SND_SOC_CLOCK_IN);
+       if (ret < 0) {
+               printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret);
+               return ret;
+       }
+
        /* Add specific widgets */
        snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets,
                                  ARRAY_SIZE(at91sam9g20ek_dapm_widgets));
@@ -255,8 +162,13 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
        snd_soc_dapm_nc_pin(codec, "RLINEIN");
        snd_soc_dapm_nc_pin(codec, "LLINEIN");
 
-       /* always connected */
+#ifdef ENABLE_MIC_INPUT
        snd_soc_dapm_enable_pin(codec, "Int Mic");
+#else
+       snd_soc_dapm_nc_pin(codec, "Int Mic");
+#endif
+
+       /* always connected */
        snd_soc_dapm_enable_pin(codec, "Ext Spk");
 
        snd_soc_dapm_sync(codec);
index 479d7bdf1865cb822cdca9677d3180e2805e4d69..a521aa90ddee4ae05e7e8d3d8cfd96a7e360ffef 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Au12x0/Au1550 PSC ALSA ASoC audio support.
  *
- * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
- *     Manuel Lauss <mano@roarinelk.homelinux.net>
+ * (c) 2007-2009 MSC Vertriebsges.m.b.H.,
+ *     Manuel Lauss <manuel.lauss@gmail.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
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/delay.h>
+#include <linux/mutex.h>
 #include <linux/suspend.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -29,6 +30,9 @@
 
 #include "psc.h"
 
+/* how often to retry failed codec register reads/writes */
+#define AC97_RW_RETRIES        5
+
 #define AC97_DIR       \
        (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
 
@@ -45,6 +49,9 @@
 #define AC97PCR_CLRFIFO(stype) \
        ((stype) == PCM_TX ? PSC_AC97PCR_TC : PSC_AC97PCR_RC)
 
+#define AC97STAT_BUSY(stype)   \
+       ((stype) == PCM_TX ? PSC_AC97STAT_TB : PSC_AC97STAT_RB)
+
 /* instance data. There can be only one, MacLeod!!!! */
 static struct au1xpsc_audio_data *au1xpsc_ac97_workdata;
 
@@ -54,24 +61,33 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
 {
        /* FIXME */
        struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
-       unsigned short data, tmo;
+       unsigned short data, retry, tmo;
 
-       au_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg), AC97_CDC(pscdata));
+       au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
        au_sync();
 
-       tmo = 1000;
-       while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) && --tmo)
-               udelay(2);
+       retry = AC97_RW_RETRIES;
+       do {
+               mutex_lock(&pscdata->lock);
+
+               au_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg),
+                         AC97_CDC(pscdata));
+               au_sync();
+
+               tmo = 2000;
+               while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD))
+                       && --tmo)
+                       udelay(2);
 
-       if (!tmo)
-               data = 0xffff;
-       else
                data = au_readl(AC97_CDC(pscdata)) & 0xffff;
 
-       au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
-       au_sync();
+               au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
+               au_sync();
+
+               mutex_unlock(&pscdata->lock);
+       } while (--retry && !tmo);
 
-       return data;
+       return retry ? data : 0xffff;
 }
 
 /* AC97 controller writes to codec register */
@@ -80,16 +96,29 @@ static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
 {
        /* FIXME */
        struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
-       unsigned int tmo;
+       unsigned int tmo, retry;
 
-       au_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff), AC97_CDC(pscdata));
+       au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
        au_sync();
-       tmo = 1000;
-       while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) && --tmo)
+
+       retry = AC97_RW_RETRIES;
+       do {
+               mutex_lock(&pscdata->lock);
+
+               au_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff),
+                         AC97_CDC(pscdata));
                au_sync();
 
-       au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
-       au_sync();
+               tmo = 2000;
+               while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD))
+                      && --tmo)
+                       udelay(2);
+
+               au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
+               au_sync();
+
+               mutex_unlock(&pscdata->lock);
+       } while (--retry && !tmo);
 }
 
 /* AC97 controller asserts a warm reset */
@@ -129,9 +158,9 @@ static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
        au_sync();
 
        /* wait for PSC to indicate it's ready */
-       i = 100000;
+       i = 1000;
        while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i))
-               au_sync();
+               msleep(1);
 
        if (i == 0) {
                printk(KERN_ERR "au1xpsc-ac97: PSC not ready!\n");
@@ -143,9 +172,9 @@ static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
        au_sync();
 
        /* wait for AC97 core to become ready */
-       i = 100000;
+       i = 1000;
        while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i))
-               au_sync();
+               msleep(1);
        if (i == 0)
                printk(KERN_ERR "au1xpsc-ac97: AC97 ctrl not ready\n");
 }
@@ -165,12 +194,12 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
 {
        /* FIXME */
        struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
-       unsigned long r, stat;
+       unsigned long r, ro, stat;
        int chans, stype = SUBSTREAM_TYPE(substream);
 
        chans = params_channels(params);
 
-       r = au_readl(AC97_CFG(pscdata));
+       r = ro = au_readl(AC97_CFG(pscdata));
        stat = au_readl(AC97_STAT(pscdata));
 
        /* already active? */
@@ -180,9 +209,6 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
                    (pscdata->rate != params_rate(params)))
                        return -EINVAL;
        } else {
-               /* disable AC97 device controller first */
-               au_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
-               au_sync();
 
                /* set sample bitdepth: REG[24:21]=(BITS-2)/2 */
                r &= ~PSC_AC97CFG_LEN_MASK;
@@ -199,14 +225,40 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
                        r |= PSC_AC97CFG_RXSLOT_ENA(4);
                }
 
-               /* finally enable the AC97 controller again */
+               /* do we need to poke the hardware? */
+               if (!(r ^ ro))
+                       goto out;
+
+               /* ac97 engine is about to be disabled */
+               mutex_lock(&pscdata->lock);
+
+               /* disable AC97 device controller first... */
+               au_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
+               au_sync();
+
+               /* ...wait for it... */
+               while (au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)
+                       asm volatile ("nop");
+
+               /* ...write config... */
+               au_writel(r, AC97_CFG(pscdata));
+               au_sync();
+
+               /* ...enable the AC97 controller again... */
                au_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
                au_sync();
 
+               /* ...and wait for ready bit */
+               while (!(au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR))
+                       asm volatile ("nop");
+
+               mutex_unlock(&pscdata->lock);
+
                pscdata->cfg = r;
                pscdata->rate = params_rate(params);
        }
 
+out:
        return 0;
 }
 
@@ -222,6 +274,8 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
+               au_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
+               au_sync();
                au_writel(AC97PCR_START(stype), AC97_PCR(pscdata));
                au_sync();
                break;
@@ -229,6 +283,13 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
        case SNDRV_PCM_TRIGGER_SUSPEND:
                au_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata));
                au_sync();
+
+               while (au_readl(AC97_STAT(pscdata)) & AC97STAT_BUSY(stype))
+                       asm volatile ("nop");
+
+               au_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
+               au_sync();
+
                break;
        default:
                ret = -EINVAL;
@@ -251,6 +312,8 @@ static int au1xpsc_ac97_probe(struct platform_device *pdev,
        if (!au1xpsc_ac97_workdata)
                return -ENOMEM;
 
+       mutex_init(&au1xpsc_ac97_workdata->lock);
+
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!r) {
                ret = -ENODEV;
@@ -269,9 +332,9 @@ static int au1xpsc_ac97_probe(struct platform_device *pdev,
                goto out1;
 
        /* configuration: max dma trigger threshold, enable ac97 */
-        au1xpsc_ac97_workdata->cfg = PSC_AC97CFG_RT_FIFO8 |
-                                     PSC_AC97CFG_TT_FIFO8 |
-                                     PSC_AC97CFG_DE_ENABLE;
+       au1xpsc_ac97_workdata->cfg = PSC_AC97CFG_RT_FIFO8 |
+                                    PSC_AC97CFG_TT_FIFO8 |
+                                    PSC_AC97CFG_DE_ENABLE;
 
        /* preserve PSC clock source set up by platform (dev.platform_data
         * is already occupied by soc layer)
@@ -386,4 +449,4 @@ module_exit(au1xpsc_ac97_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver");
-MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
+MODULE_AUTHOR("Manuel Lauss <manuel.lauss@gmail.com>");
index 8fdb1a04a07b6458c93d18faf0b9983aab947baf..3f474e8ed4f6bd60a685ceed44d2ffdd4ab89eb8 100644 (file)
@@ -29,6 +29,7 @@ struct au1xpsc_audio_data {
 
        unsigned long pm[2];
        struct resource *ioarea;
+       struct mutex lock;
 };
 
 #define PCM_TX 0
index 811596f4c092a21b24f8f85f2c386348725f9385..97f1a251e446e5329c31c7f155d0c76ad29436ba 100644 (file)
@@ -32,6 +32,31 @@ config SND_BFIN_AD73311_SE
          Enter the GPIO used to control AD73311's SE pin. Acceptable
          values are 0 to 7
 
+config SND_BF5XX_TDM
+       tristate "SoC I2S(TDM mode) Audio for the ADI BF5xx chip"
+       depends on (BLACKFIN && SND_SOC)
+       help
+         Say Y or M if you want to add support for codecs attached to
+         the Blackfin SPORT (synchronous serial ports) interface in TDM
+         mode.
+         You will also need to select the audio interfaces to support below.
+
+config SND_BF5XX_SOC_AD1836
+       tristate "SoC AD1836 Audio support for BF5xx"
+       depends on SND_BF5XX_TDM
+       select SND_BF5XX_SOC_TDM
+       select SND_SOC_AD1836
+       help
+         Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
+
+config SND_BF5XX_SOC_AD1938
+       tristate "SoC AD1938 Audio support for Blackfin"
+       depends on SND_BF5XX_TDM
+       select SND_BF5XX_SOC_TDM
+       select SND_SOC_AD1938
+       help
+         Say Y if you want to add support for AD1938 codec on Blackfin.
+
 config SND_BF5XX_AC97
        tristate "SoC AC97 Audio for the ADI BF5xx chip"
        depends on BLACKFIN
@@ -62,6 +87,30 @@ config SND_BF5XX_MULTICHAN_SUPPORT
          Say y if you want AC97 driver to support up to 5.1 channel audio.
          this mode will consume much more memory for DMA.
 
+config SND_BF5XX_HAVE_COLD_RESET
+       bool "BOARD has COLD Reset GPIO"
+       depends on SND_BF5XX_AC97
+       default y if BFIN548_EZKIT
+       default n if !BFIN548_EZKIT
+
+config SND_BF5XX_RESET_GPIO_NUM
+       int "Set a GPIO for cold reset"
+       depends on SND_BF5XX_HAVE_COLD_RESET
+       range 0 159
+       default 19 if BFIN548_EZKIT
+       default 5 if BFIN537_STAMP
+       default 0
+       help
+         Set the correct GPIO for RESET the sound chip.
+
+config SND_BF5XX_SOC_AD1980
+       tristate "SoC AD1980/1 Audio support for BF5xx"
+       depends on SND_BF5XX_AC97
+       select SND_BF5XX_SOC_AC97
+       select SND_SOC_AD1980
+       help
+         Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
+
 config SND_BF5XX_SOC_SPORT
        tristate
 
@@ -69,41 +118,21 @@ config SND_BF5XX_SOC_I2S
        tristate
        select SND_BF5XX_SOC_SPORT
 
+config SND_BF5XX_SOC_TDM
+       tristate
+       select SND_BF5XX_SOC_SPORT
+
 config SND_BF5XX_SOC_AC97
        tristate
        select AC97_BUS
        select SND_SOC_AC97_BUS
        select SND_BF5XX_SOC_SPORT
 
-config SND_BF5XX_SOC_AD1980
-       tristate "SoC AD1980/1 Audio support for BF5xx"
-       depends on SND_BF5XX_AC97
-       select SND_BF5XX_SOC_AC97
-       select SND_SOC_AD1980
-       help
-         Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT.
-
 config SND_BF5XX_SPORT_NUM
        int "Set a SPORT for Sound chip"
-       depends on (SND_BF5XX_I2S || SND_BF5XX_AC97)
+       depends on (SND_BF5XX_I2S || SND_BF5XX_AC97 || SND_BF5XX_TDM)
        range 0 3 if BF54x
        range 0 1 if !BF54x
        default 0
        help
          Set the correct SPORT for sound chip.
-
-config SND_BF5XX_HAVE_COLD_RESET
-       bool "BOARD has COLD Reset GPIO"
-       depends on SND_BF5XX_AC97
-       default y if BFIN548_EZKIT
-       default n if !BFIN548_EZKIT
-
-config SND_BF5XX_RESET_GPIO_NUM
-       int "Set a GPIO for cold reset"
-       depends on SND_BF5XX_HAVE_COLD_RESET
-       range 0 159
-       default 19 if BFIN548_EZKIT
-       default 5 if BFIN537_STAMP
-       default 0
-       help
-         Set the correct GPIO for RESET the sound chip.
index 97bb37a6359c9b72816424658fdab4636c76fa36..87e30423912f165e5dff4e3655cea5e547740a15 100644 (file)
@@ -1,21 +1,29 @@
 # Blackfin Platform Support
 snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o
 snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o
+snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o
 snd-soc-bf5xx-sport-objs := bf5xx-sport.o
 snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o
 snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o
+snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o
 
 obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o
 obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o
+obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o
 obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o
 obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o
 obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o
+obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o
 
 # Blackfin Machine Support
+snd-ad1836-objs := bf5xx-ad1836.o
 snd-ad1980-objs := bf5xx-ad1980.o
 snd-ssm2602-objs := bf5xx-ssm2602.o
 snd-ad73311-objs := bf5xx-ad73311.o
+snd-ad1938-objs := bf5xx-ad1938.o
 
+obj-$(CONFIG_SND_BF5XX_SOC_AD1836) += snd-ad1836.o
 obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
 obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
 obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
+obj-$(CONFIG_SND_BF5XX_SOC_AD1938) += snd-ad1938.o
index b1ed423fabd51f56bb278e165e2d8c0369406caa..e69322978739d760e27bf47aaf61021cbf958deb 100644 (file)
@@ -277,28 +277,28 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
        if (!dai->active)
                return 0;
 
-       ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1);
+#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
+       ret = sport_set_multichannel(sport, 16, 0x3FF, 1);
+#else
+       ret = sport_set_multichannel(sport, 16, 0x1F, 1);
+#endif
        if (ret) {
                pr_err("SPORT is busy!\n");
                return -EBUSY;
        }
 
-       ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1));
+       ret = sport_config_rx(sport, IRFS, 0xF, 0, (16*16-1));
        if (ret) {
                pr_err("SPORT is busy!\n");
                return -EBUSY;
        }
 
-       ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1));
+       ret = sport_config_tx(sport, ITFS, 0xF, 0, (16*16-1));
        if (ret) {
                pr_err("SPORT is busy!\n");
                return -EBUSY;
        }
 
-       if (dai->capture.active)
-               sport_rx_start(sport);
-       if (dai->playback.active)
-               sport_tx_start(sport);
        return 0;
 }
 
@@ -338,7 +338,11 @@ static int bf5xx_ac97_probe(struct platform_device *pdev,
                goto sport_err;
        }
        /*SPORT works in TDM mode to simulate AC97 transfers*/
+#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
+       ret = sport_set_multichannel(sport_handle, 16, 0x3FF, 1);
+#else
        ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1);
+#endif
        if (ret) {
                pr_err("SPORT is busy!\n");
                ret = -EBUSY;
index 3f2a911fe0cb2adda1c45473babef9845d9280c9..a1f97dd809d63fda550f4d62cd18a5a2c1eb7bde 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/sound/arm/bf5xx-ac97.h
+ * sound/soc/blackfin/bf5xx-ac97.h
  *
  * 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
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c
new file mode 100644 (file)
index 0000000..cd361e3
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * File:         sound/soc/blackfin/bf5xx-ad1836.c
+ * Author:       Barry Song <Barry.Song@analog.com>
+ *
+ * Created:      Aug 4 2009
+ * Description:  Board driver for ad1836 sound chip
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm_params.h>
+
+#include <asm/blackfin.h>
+#include <asm/cacheflush.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#include "../codecs/ad1836.h"
+#include "bf5xx-sport.h"
+
+#include "bf5xx-tdm-pcm.h"
+#include "bf5xx-tdm.h"
+
+static struct snd_soc_card bf5xx_ad1836;
+
+static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+       cpu_dai->private_data = sport_handle;
+       return 0;
+}
+
+static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       int ret = 0;
+       /* set cpu DAI configuration */
+       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
+               SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0)
+               return ret;
+
+       /* set codec DAI configuration */
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
+               SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static struct snd_soc_ops bf5xx_ad1836_ops = {
+       .startup = bf5xx_ad1836_startup,
+       .hw_params = bf5xx_ad1836_hw_params,
+};
+
+static struct snd_soc_dai_link bf5xx_ad1836_dai = {
+       .name = "ad1836",
+       .stream_name = "AD1836",
+       .cpu_dai = &bf5xx_tdm_dai,
+       .codec_dai = &ad1836_dai,
+       .ops = &bf5xx_ad1836_ops,
+};
+
+static struct snd_soc_card bf5xx_ad1836 = {
+       .name = "bf5xx_ad1836",
+       .platform = &bf5xx_tdm_soc_platform,
+       .dai_link = &bf5xx_ad1836_dai,
+       .num_links = 1,
+};
+
+static struct snd_soc_device bf5xx_ad1836_snd_devdata = {
+       .card = &bf5xx_ad1836,
+       .codec_dev = &soc_codec_dev_ad1836,
+};
+
+static struct platform_device *bfxx_ad1836_snd_device;
+
+static int __init bf5xx_ad1836_init(void)
+{
+       int ret;
+
+       bfxx_ad1836_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!bfxx_ad1836_snd_device)
+               return -ENOMEM;
+
+       platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836_snd_devdata);
+       bf5xx_ad1836_snd_devdata.dev = &bfxx_ad1836_snd_device->dev;
+       ret = platform_device_add(bfxx_ad1836_snd_device);
+
+       if (ret)
+               platform_device_put(bfxx_ad1836_snd_device);
+
+       return ret;
+}
+
+static void __exit bf5xx_ad1836_exit(void)
+{
+       platform_device_unregister(bfxx_ad1836_snd_device);
+}
+
+module_init(bf5xx_ad1836_init);
+module_exit(bf5xx_ad1836_exit);
+
+/* Module information */
+MODULE_AUTHOR("Barry Song");
+MODULE_DESCRIPTION("ALSA SoC AD1836 board driver");
+MODULE_LICENSE("GPL");
+
diff --git a/sound/soc/blackfin/bf5xx-ad1938.c b/sound/soc/blackfin/bf5xx-ad1938.c
new file mode 100644 (file)
index 0000000..08269e9
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * File:         sound/soc/blackfin/bf5xx-ad1938.c
+ * Author:       Barry Song <Barry.Song@analog.com>
+ *
+ * Created:      Thur June 4 2009
+ * Description:  Board driver for ad1938 sound chip
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm_params.h>
+
+#include <asm/blackfin.h>
+#include <asm/cacheflush.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/portmux.h>
+
+#include "../codecs/ad1938.h"
+#include "bf5xx-sport.h"
+
+#include "bf5xx-tdm-pcm.h"
+#include "bf5xx-tdm.h"
+
+static struct snd_soc_card bf5xx_ad1938;
+
+static int bf5xx_ad1938_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+       cpu_dai->private_data = sport_handle;
+       return 0;
+}
+
+static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       int ret = 0;
+       /* set cpu DAI configuration */
+       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
+               SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0)
+               return ret;
+
+       /* set codec DAI configuration */
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
+               SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0)
+               return ret;
+
+       /* set codec DAI slots, 8 channels, all channels are enabled */
+       ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 8);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static struct snd_soc_ops bf5xx_ad1938_ops = {
+       .startup = bf5xx_ad1938_startup,
+       .hw_params = bf5xx_ad1938_hw_params,
+};
+
+static struct snd_soc_dai_link bf5xx_ad1938_dai = {
+       .name = "ad1938",
+       .stream_name = "AD1938",
+       .cpu_dai = &bf5xx_tdm_dai,
+       .codec_dai = &ad1938_dai,
+       .ops = &bf5xx_ad1938_ops,
+};
+
+static struct snd_soc_card bf5xx_ad1938 = {
+       .name = "bf5xx_ad1938",
+       .platform = &bf5xx_tdm_soc_platform,
+       .dai_link = &bf5xx_ad1938_dai,
+       .num_links = 1,
+};
+
+static struct snd_soc_device bf5xx_ad1938_snd_devdata = {
+       .card = &bf5xx_ad1938,
+       .codec_dev = &soc_codec_dev_ad1938,
+};
+
+static struct platform_device *bfxx_ad1938_snd_device;
+
+static int __init bf5xx_ad1938_init(void)
+{
+       int ret;
+
+       bfxx_ad1938_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!bfxx_ad1938_snd_device)
+               return -ENOMEM;
+
+       platform_set_drvdata(bfxx_ad1938_snd_device, &bf5xx_ad1938_snd_devdata);
+       bf5xx_ad1938_snd_devdata.dev = &bfxx_ad1938_snd_device->dev;
+       ret = platform_device_add(bfxx_ad1938_snd_device);
+
+       if (ret)
+               platform_device_put(bfxx_ad1938_snd_device);
+
+       return ret;
+}
+
+static void __exit bf5xx_ad1938_exit(void)
+{
+       platform_device_unregister(bfxx_ad1938_snd_device);
+}
+
+module_init(bf5xx_ad1938_init);
+module_exit(bf5xx_ad1938_exit);
+
+/* Module information */
+MODULE_AUTHOR("Barry Song");
+MODULE_DESCRIPTION("ALSA SoC AD1938 board driver");
+MODULE_LICENSE("GPL");
+
index edfbdc024e663d9ac6ae1048086d84334518a9cd..9825b71d0e28a3a7002ab690afcc867efaaf7123 100644 (file)
@@ -203,23 +203,23 @@ static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
        .codec_dev = &soc_codec_dev_ad73311,
 };
 
-static struct platform_device *bf52x_ad73311_snd_device;
+static struct platform_device *bf5xx_ad73311_snd_device;
 
 static int __init bf5xx_ad73311_init(void)
 {
        int ret;
 
        pr_debug("%s enter\n", __func__);
-       bf52x_ad73311_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!bf52x_ad73311_snd_device)
+       bf5xx_ad73311_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!bf5xx_ad73311_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(bf52x_ad73311_snd_device, &bf5xx_ad73311_snd_devdata);
-       bf5xx_ad73311_snd_devdata.dev = &bf52x_ad73311_snd_device->dev;
-       ret = platform_device_add(bf52x_ad73311_snd_device);
+       platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311_snd_devdata);
+       bf5xx_ad73311_snd_devdata.dev = &bf5xx_ad73311_snd_device->dev;
+       ret = platform_device_add(bf5xx_ad73311_snd_device);
 
        if (ret)
-               platform_device_put(bf52x_ad73311_snd_device);
+               platform_device_put(bf5xx_ad73311_snd_device);
 
        return ret;
 }
@@ -227,7 +227,7 @@ static int __init bf5xx_ad73311_init(void)
 static void __exit bf5xx_ad73311_exit(void)
 {
        pr_debug("%s enter\n", __func__);
-       platform_device_unregister(bf52x_ad73311_snd_device);
+       platform_device_unregister(bf5xx_ad73311_snd_device);
 }
 
 module_init(bf5xx_ad73311_init);
index af06904bab0f8411285fec191995499ffc8effde..084b68884adaa7d407e0e67ded3aa07b41edd9ee 100644 (file)
@@ -77,12 +77,12 @@ static struct sport_param sport_params[2] = {
  * TFS. When Port G is selected and EMAC then there is a conflict between
  * the PHY interrupt line and TFS.  Current settings prevent the conflict
  * by ignoring the TFS pin when Port G is selected. This allows both
- * ssm2602 using Port G and EMAC concurrently.
+ * codecs and EMAC using Port G concurrently.
  */
-#ifdef CONFIG_BF527_SPORT0_PORTF
-#define LOCAL_SPORT0_TFS (P_SPORT0_TFS)
-#else
+#ifdef CONFIG_BF527_SPORT0_PORTG
 #define LOCAL_SPORT0_TFS (0)
+#else
+#define LOCAL_SPORT0_TFS (P_SPORT0_TFS)
 #endif
 
 static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
@@ -227,7 +227,8 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,
        return 0;
 }
 
-static void bf5xx_i2s_remove(struct snd_soc_dai *dai)
+static void bf5xx_i2s_remove(struct platform_device *pdev,
+                       struct snd_soc_dai *dai)
 {
        pr_debug("%s enter\n", __func__);
        peripheral_free_list(&sport_req[sport_num][0]);
@@ -236,45 +237,36 @@ static void bf5xx_i2s_remove(struct snd_soc_dai *dai)
 #ifdef CONFIG_PM
 static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
 {
-       struct sport_device *sport =
-               (struct sport_device *)dai->private_data;
 
        pr_debug("%s : sport %d\n", __func__, dai->id);
-       if (!dai->active)
-               return 0;
+
        if (dai->capture.active)
-               sport_rx_stop(sport);
+               sport_rx_stop(sport_handle);
        if (dai->playback.active)
-               sport_tx_stop(sport);
+               sport_tx_stop(sport_handle);
        return 0;
 }
 
 static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
 {
        int ret;
-       struct sport_device *sport =
-               (struct sport_device *)dai->private_data;
 
        pr_debug("%s : sport %d\n", __func__, dai->id);
-       if (!dai->active)
-               return 0;
 
-       ret = sport_config_rx(sport_handle, RFSR | RCKFE, RSFSE|0x1f, 0, 0);
+       ret = sport_config_rx(sport_handle, bf5xx_i2s.rcr1,
+                                     bf5xx_i2s.rcr2, 0, 0);
        if (ret) {
                pr_err("SPORT is busy!\n");
                return -EBUSY;
        }
 
-       ret = sport_config_tx(sport_handle, TFSR | TCKFE, TSFSE|0x1f, 0, 0);
+       ret = sport_config_tx(sport_handle, bf5xx_i2s.tcr1,
+                                     bf5xx_i2s.tcr2, 0, 0);
        if (ret) {
                pr_err("SPORT is busy!\n");
                return -EBUSY;
        }
 
-       if (dai->capture.active)
-               sport_rx_start(sport);
-       if (dai->playback.active)
-               sport_tx_start(sport);
        return 0;
 }
 
index 7107d1a0b06b810c8ef700d9985486eec4ad6de3..264ecdcba35a6edcb9b4f44eacf28337f9b2f3f1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/sound/arm/bf5xx-i2s.h
+ * sound/soc/blackfin/bf5xx-i2s.h
  *
  * 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
index 469ce7fab20ca6aad3d6474d8c63deeacb3f5101..99051ff0954e6ffe6772d0ee4957ee53e4d3ebc4 100644 (file)
@@ -326,7 +326,7 @@ static inline int sport_hook_tx_dummy(struct sport_device *sport)
 
 int sport_tx_start(struct sport_device *sport)
 {
-       unsigned flags;
+       unsigned long flags;
        pr_debug("%s: tx_run:%d, rx_run:%d\n", __func__,
                        sport->tx_run, sport->rx_run);
        if (sport->tx_run)
index bc0cdded711664ccd0437e82fb62e41807a6a790..3a00fa4dbe6d4202d5e32647a684000335c71e29 100644 (file)
@@ -148,24 +148,24 @@ static struct snd_soc_device bf5xx_ssm2602_snd_devdata = {
        .codec_data = &bf5xx_ssm2602_setup,
 };
 
-static struct platform_device *bf52x_ssm2602_snd_device;
+static struct platform_device *bf5xx_ssm2602_snd_device;
 
 static int __init bf5xx_ssm2602_init(void)
 {
        int ret;
 
        pr_debug("%s enter\n", __func__);
-       bf52x_ssm2602_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!bf52x_ssm2602_snd_device)
+       bf5xx_ssm2602_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!bf5xx_ssm2602_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(bf52x_ssm2602_snd_device,
+       platform_set_drvdata(bf5xx_ssm2602_snd_device,
                                &bf5xx_ssm2602_snd_devdata);
-       bf5xx_ssm2602_snd_devdata.dev = &bf52x_ssm2602_snd_device->dev;
-       ret = platform_device_add(bf52x_ssm2602_snd_device);
+       bf5xx_ssm2602_snd_devdata.dev = &bf5xx_ssm2602_snd_device->dev;
+       ret = platform_device_add(bf5xx_ssm2602_snd_device);
 
        if (ret)
-               platform_device_put(bf52x_ssm2602_snd_device);
+               platform_device_put(bf5xx_ssm2602_snd_device);
 
        return ret;
 }
@@ -173,7 +173,7 @@ static int __init bf5xx_ssm2602_init(void)
 static void __exit bf5xx_ssm2602_exit(void)
 {
        pr_debug("%s enter\n", __func__);
-       platform_device_unregister(bf52x_ssm2602_snd_device);
+       platform_device_unregister(bf5xx_ssm2602_snd_device);
 }
 
 module_init(bf5xx_ssm2602_init);
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c
new file mode 100644 (file)
index 0000000..ccb5e82
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * File:         sound/soc/blackfin/bf5xx-tdm-pcm.c
+ * Author:       Barry Song <Barry.Song@analog.com>
+ *
+ * Created:      Tue June 06 2009
+ * Description:  DMA driver for tdm codec
+ *
+ * Modified:
+ *               Copyright 2009 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <asm/dma.h>
+
+#include "bf5xx-tdm-pcm.h"
+#include "bf5xx-tdm.h"
+#include "bf5xx-sport.h"
+
+#define PCM_BUFFER_MAX  0x10000
+#define FRAGMENT_SIZE_MIN  (4*1024)
+#define FRAGMENTS_MIN  2
+#define FRAGMENTS_MAX  32
+
+static void bf5xx_dma_irq(void *data)
+{
+       struct snd_pcm_substream *pcm = data;
+       snd_pcm_period_elapsed(pcm);
+}
+
+static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
+       .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_RESUME),
+       .formats =          SNDRV_PCM_FMTBIT_S32_LE,
+       .rates =            SNDRV_PCM_RATE_48000,
+       .channels_min =     2,
+       .channels_max =     8,
+       .buffer_bytes_max = PCM_BUFFER_MAX,
+       .period_bytes_min = FRAGMENT_SIZE_MIN,
+       .period_bytes_max = PCM_BUFFER_MAX/2,
+       .periods_min =      FRAGMENTS_MIN,
+       .periods_max =      FRAGMENTS_MAX,
+};
+
+static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
+       snd_pcm_lib_malloc_pages(substream, size * 4);
+
+       return 0;
+}
+
+static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       snd_pcm_lib_free_pages(substream);
+
+       return 0;
+}
+
+static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct sport_device *sport = runtime->private_data;
+       int fragsize_bytes = frames_to_bytes(runtime, runtime->period_size);
+
+       fragsize_bytes /= runtime->channels;
+       /* inflate the fragsize to match the dma width of SPORT */
+       fragsize_bytes *= 8;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
+               sport_config_tx_dma(sport, runtime->dma_area,
+                       runtime->periods, fragsize_bytes);
+       } else {
+               sport_set_rx_callback(sport, bf5xx_dma_irq, substream);
+               sport_config_rx_dma(sport, runtime->dma_area,
+                       runtime->periods, fragsize_bytes);
+       }
+
+       return 0;
+}
+
+static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct sport_device *sport = runtime->private_data;
+       int ret = 0;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+                       sport_tx_start(sport);
+               else
+                       sport_rx_start(sport);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+                       sport_tx_stop(sport);
+               else
+                       sport_rx_stop(sport);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct sport_device *sport = runtime->private_data;
+       unsigned int diff;
+       snd_pcm_uframes_t frames;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               diff = sport_curr_offset_tx(sport);
+               frames = diff / (8*4); /* 32 bytes per frame */
+       } else {
+               diff = sport_curr_offset_rx(sport);
+               frames = diff / (8*4);
+       }
+       return frames;
+}
+
+static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int ret = 0;
+
+       snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware);
+
+       ret = snd_pcm_hw_constraint_integer(runtime,
+               SNDRV_PCM_HW_PARAM_PERIODS);
+       if (ret < 0)
+               goto out;
+
+       if (sport_handle != NULL)
+               runtime->private_data = sport_handle;
+       else {
+               pr_err("sport_handle is NULL\n");
+               ret = -ENODEV;
+       }
+out:
+       return ret;
+}
+
+static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
+       snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count)
+{
+       unsigned int *src;
+       unsigned int *dst;
+       int i;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               src = buf;
+               dst = (unsigned int *)substream->runtime->dma_area;
+
+               dst += pos * 8;
+               while (count--) {
+                       for (i = 0; i < substream->runtime->channels; i++)
+                               *(dst + i) = *src++;
+                       dst += 8;
+               }
+       } else {
+               src = (unsigned int *)substream->runtime->dma_area;
+               dst = buf;
+
+               src += pos * 8;
+               while (count--) {
+                       for (i = 0; i < substream->runtime->channels; i++)
+                               *dst++ = *(src+i);
+                       src += 8;
+               }
+       }
+
+       return 0;
+}
+
+static int bf5xx_pcm_silence(struct snd_pcm_substream *substream,
+       int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
+{
+       unsigned char *buf = substream->runtime->dma_area;
+       buf += pos * 8 * 4;
+       memset(buf, '\0', count * 8 * 4);
+
+       return 0;
+}
+
+
+struct snd_pcm_ops bf5xx_pcm_tdm_ops = {
+       .open           = bf5xx_pcm_open,
+       .ioctl          = snd_pcm_lib_ioctl,
+       .hw_params      = bf5xx_pcm_hw_params,
+       .hw_free        = bf5xx_pcm_hw_free,
+       .prepare        = bf5xx_pcm_prepare,
+       .trigger        = bf5xx_pcm_trigger,
+       .pointer        = bf5xx_pcm_pointer,
+       .copy           = bf5xx_pcm_copy,
+       .silence        = bf5xx_pcm_silence,
+};
+
+static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+       struct snd_dma_buffer *buf = &substream->dma_buffer;
+       size_t size = bf5xx_pcm_hardware.buffer_bytes_max;
+
+       buf->dev.type = SNDRV_DMA_TYPE_DEV;
+       buf->dev.dev = pcm->card->dev;
+       buf->private_data = NULL;
+       buf->area = dma_alloc_coherent(pcm->card->dev, size * 4,
+               &buf->addr, GFP_KERNEL);
+       if (!buf->area) {
+               pr_err("Failed to allocate dma memory \
+                       Please increase uncached DMA memory region\n");
+               return -ENOMEM;
+       }
+       buf->bytes = size;
+
+       if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+               sport_handle->tx_buf = buf->area;
+       else
+               sport_handle->rx_buf = buf->area;
+
+       return 0;
+}
+
+static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+       struct snd_pcm_substream *substream;
+       struct snd_dma_buffer *buf;
+       int stream;
+
+       for (stream = 0; stream < 2; stream++) {
+               substream = pcm->streams[stream].substream;
+               if (!substream)
+                       continue;
+
+               buf = &substream->dma_buffer;
+               if (!buf->area)
+                       continue;
+               dma_free_coherent(NULL, buf->bytes, buf->area, 0);
+               buf->area = NULL;
+       }
+       if (sport_handle)
+               sport_done(sport_handle);
+}
+
+static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
+
+static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai,
+       struct snd_pcm *pcm)
+{
+       int ret = 0;
+
+       if (!card->dev->dma_mask)
+               card->dev->dma_mask = &bf5xx_pcm_dmamask;
+       if (!card->dev->coherent_dma_mask)
+               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+       if (dai->playback.channels_min) {
+               ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
+                       SNDRV_PCM_STREAM_PLAYBACK);
+               if (ret)
+                       goto out;
+       }
+
+       if (dai->capture.channels_min) {
+               ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
+                       SNDRV_PCM_STREAM_CAPTURE);
+               if (ret)
+                       goto out;
+       }
+out:
+       return ret;
+}
+
+struct snd_soc_platform bf5xx_tdm_soc_platform = {
+       .name           = "bf5xx-audio",
+       .pcm_ops        = &bf5xx_pcm_tdm_ops,
+       .pcm_new        = bf5xx_pcm_tdm_new,
+       .pcm_free       = bf5xx_pcm_free_dma_buffers,
+};
+EXPORT_SYMBOL_GPL(bf5xx_tdm_soc_platform);
+
+static int __init bfin_pcm_tdm_init(void)
+{
+       return snd_soc_register_platform(&bf5xx_tdm_soc_platform);
+}
+module_init(bfin_pcm_tdm_init);
+
+static void __exit bfin_pcm_tdm_exit(void)
+{
+       snd_soc_unregister_platform(&bf5xx_tdm_soc_platform);
+}
+module_exit(bfin_pcm_tdm_exit);
+
+MODULE_AUTHOR("Barry Song");
+MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.h b/sound/soc/blackfin/bf5xx-tdm-pcm.h
new file mode 100644 (file)
index 0000000..ddc5047
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * sound/soc/blackfin/bf5xx-tdm-pcm.h -- ALSA PCM interface for the Blackfin
+ *
+ * Copyright 2009 Analog Device 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 _BF5XX_TDM_PCM_H
+#define _BF5XX_TDM_PCM_H
+
+struct bf5xx_pcm_dma_params {
+       char *name;                     /* stream identifier */
+};
+
+/* platform data */
+extern struct snd_soc_platform bf5xx_tdm_soc_platform;
+
+#endif
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
new file mode 100644 (file)
index 0000000..ff546e9
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * File:         sound/soc/blackfin/bf5xx-tdm.c
+ * Author:       Barry Song <Barry.Song@analog.com>
+ *
+ * Created:      Thurs June 04 2009
+ * Description:  Blackfin I2S(TDM) CPU DAI driver
+ *              Even though TDM mode can be as part of I2S DAI, but there
+ *              are so much difference in configuration and data flow,
+ *              it's very ugly to integrate I2S and TDM into a module
+ *
+ * Modified:
+ *               Copyright 2009 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <asm/irq.h>
+#include <asm/portmux.h>
+#include <linux/mutex.h>
+#include <linux/gpio.h>
+
+#include "bf5xx-sport.h"
+#include "bf5xx-tdm.h"
+
+struct bf5xx_tdm_port {
+       u16 tcr1;
+       u16 rcr1;
+       u16 tcr2;
+       u16 rcr2;
+       int configured;
+};
+
+static struct bf5xx_tdm_port bf5xx_tdm;
+static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
+
+static struct sport_param sport_params[2] = {
+       {
+               .dma_rx_chan    = CH_SPORT0_RX,
+               .dma_tx_chan    = CH_SPORT0_TX,
+               .err_irq        = IRQ_SPORT0_ERROR,
+               .regs           = (struct sport_register *)SPORT0_TCR1,
+       },
+       {
+               .dma_rx_chan    = CH_SPORT1_RX,
+               .dma_tx_chan    = CH_SPORT1_TX,
+               .err_irq        = IRQ_SPORT1_ERROR,
+               .regs           = (struct sport_register *)SPORT1_TCR1,
+       }
+};
+
+/*
+ * Setting the TFS pin selector for SPORT 0 based on whether the selected
+ * port id F or G. If the port is F then no conflict should exist for the
+ * TFS. When Port G is selected and EMAC then there is a conflict between
+ * the PHY interrupt line and TFS.  Current settings prevent the conflict
+ * by ignoring the TFS pin when Port G is selected. This allows both
+ * codecs and EMAC using Port G concurrently.
+ */
+#ifdef CONFIG_BF527_SPORT0_PORTG
+#define LOCAL_SPORT0_TFS (0)
+#else
+#define LOCAL_SPORT0_TFS (P_SPORT0_TFS)
+#endif
+
+static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS,
+       P_SPORT0_DRPRI, P_SPORT0_RSCLK, LOCAL_SPORT0_TFS, 0},
+          {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, P_SPORT1_DRPRI,
+                  P_SPORT1_RSCLK, P_SPORT1_TFS, 0} };
+
+static int bf5xx_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+       unsigned int fmt)
+{
+       int ret = 0;
+
+       /* interface format:support TDM,slave mode */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+               break;
+       default:
+               printk(KERN_ERR "%s: Unknown DAI format type\n", __func__);
+               ret = -EINVAL;
+               break;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+       case SND_SOC_DAIFMT_CBM_CFS:
+       case SND_SOC_DAIFMT_CBS_CFM:
+               ret = -EINVAL;
+               break;
+       default:
+               printk(KERN_ERR "%s: Unknown DAI master type\n", __func__);
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params,
+       struct snd_soc_dai *dai)
+{
+       int ret = 0;
+
+       bf5xx_tdm.tcr2 &= ~0x1f;
+       bf5xx_tdm.rcr2 &= ~0x1f;
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S32_LE:
+               bf5xx_tdm.tcr2 |= 31;
+               bf5xx_tdm.rcr2 |= 31;
+               sport_handle->wdsize = 4;
+               break;
+               /* at present, we only support 32bit transfer */
+       default:
+               pr_err("not supported PCM format yet\n");
+               return -EINVAL;
+               break;
+       }
+
+       if (!bf5xx_tdm.configured) {
+               /*
+                * TX and RX are not independent,they are enabled at the
+                * same time, even if only one side is running. So, we
+                * need to configure both of them at the time when the first
+                * stream is opened.
+                *
+                * CPU DAI:slave mode.
+                */
+               ret = sport_config_rx(sport_handle, bf5xx_tdm.rcr1,
+                       bf5xx_tdm.rcr2, 0, 0);
+               if (ret) {
+                       pr_err("SPORT is busy!\n");
+                       return -EBUSY;
+               }
+
+               ret = sport_config_tx(sport_handle, bf5xx_tdm.tcr1,
+                       bf5xx_tdm.tcr2, 0, 0);
+               if (ret) {
+                       pr_err("SPORT is busy!\n");
+                       return -EBUSY;
+               }
+
+               bf5xx_tdm.configured = 1;
+       }
+
+       return 0;
+}
+
+static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream,
+       struct snd_soc_dai *dai)
+{
+       /* No active stream, SPORT is allowed to be configured again. */
+       if (!dai->active)
+               bf5xx_tdm.configured = 0;
+}
+
+#ifdef CONFIG_PM
+static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
+{
+       struct sport_device *sport =
+               (struct sport_device *)dai->private_data;
+
+       if (!dai->active)
+               return 0;
+       if (dai->capture.active)
+               sport_rx_stop(sport);
+       if (dai->playback.active)
+               sport_tx_stop(sport);
+       return 0;
+}
+
+static int bf5xx_tdm_resume(struct snd_soc_dai *dai)
+{
+       int ret;
+       struct sport_device *sport =
+               (struct sport_device *)dai->private_data;
+
+       if (!dai->active)
+               return 0;
+
+       ret = sport_set_multichannel(sport, 8, 0xFF, 1);
+       if (ret) {
+               pr_err("SPORT is busy!\n");
+               ret = -EBUSY;
+       }
+
+       ret = sport_config_rx(sport, IRFS, 0x1F, 0, 0);
+       if (ret) {
+               pr_err("SPORT is busy!\n");
+               ret = -EBUSY;
+       }
+
+       ret = sport_config_tx(sport, ITFS, 0x1F, 0, 0);
+       if (ret) {
+               pr_err("SPORT is busy!\n");
+               ret = -EBUSY;
+       }
+
+       return 0;
+}
+
+#else
+#define bf5xx_tdm_suspend      NULL
+#define bf5xx_tdm_resume       NULL
+#endif
+
+static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
+       .hw_params      = bf5xx_tdm_hw_params,
+       .set_fmt        = bf5xx_tdm_set_dai_fmt,
+       .shutdown       = bf5xx_tdm_shutdown,
+};
+
+struct snd_soc_dai bf5xx_tdm_dai = {
+       .name = "bf5xx-tdm",
+       .id = 0,
+       .suspend = bf5xx_tdm_suspend,
+       .resume = bf5xx_tdm_resume,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 8,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S32_LE,},
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 8,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S32_LE,},
+       .ops = &bf5xx_tdm_dai_ops,
+};
+EXPORT_SYMBOL_GPL(bf5xx_tdm_dai);
+
+static int __devinit bfin_tdm_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+
+       if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
+               pr_err("Requesting Peripherals failed\n");
+               return -EFAULT;
+       }
+
+       /* request DMA for SPORT */
+       sport_handle = sport_init(&sport_params[sport_num], 4, \
+               8 * sizeof(u32), NULL);
+       if (!sport_handle) {
+               peripheral_free_list(&sport_req[sport_num][0]);
+               return -ENODEV;
+       }
+
+       /* SPORT works in TDM mode */
+       ret = sport_set_multichannel(sport_handle, 8, 0xFF, 1);
+       if (ret) {
+               pr_err("SPORT is busy!\n");
+               ret = -EBUSY;
+               goto sport_config_err;
+       }
+
+       ret = sport_config_rx(sport_handle, IRFS, 0x1F, 0, 0);
+       if (ret) {
+               pr_err("SPORT is busy!\n");
+               ret = -EBUSY;
+               goto sport_config_err;
+       }
+
+       ret = sport_config_tx(sport_handle, ITFS, 0x1F, 0, 0);
+       if (ret) {
+               pr_err("SPORT is busy!\n");
+               ret = -EBUSY;
+               goto sport_config_err;
+       }
+
+       ret = snd_soc_register_dai(&bf5xx_tdm_dai);
+       if (ret) {
+               pr_err("Failed to register DAI: %d\n", ret);
+               goto sport_config_err;
+       }
+       return 0;
+
+sport_config_err:
+       peripheral_free_list(&sport_req[sport_num][0]);
+       return ret;
+}
+
+static int __devexit bfin_tdm_remove(struct platform_device *pdev)
+{
+       peripheral_free_list(&sport_req[sport_num][0]);
+       snd_soc_unregister_dai(&bf5xx_tdm_dai);
+
+       return 0;
+}
+
+static struct platform_driver bfin_tdm_driver = {
+       .probe  = bfin_tdm_probe,
+       .remove = __devexit_p(bfin_tdm_remove),
+       .driver = {
+               .name   = "bfin-tdm",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init bfin_tdm_init(void)
+{
+       return platform_driver_register(&bfin_tdm_driver);
+}
+module_init(bfin_tdm_init);
+
+static void __exit bfin_tdm_exit(void)
+{
+       platform_driver_unregister(&bfin_tdm_driver);
+}
+module_exit(bfin_tdm_exit);
+
+/* Module information */
+MODULE_AUTHOR("Barry Song");
+MODULE_DESCRIPTION("TDM driver for ADI Blackfin");
+MODULE_LICENSE("GPL");
+
diff --git a/sound/soc/blackfin/bf5xx-tdm.h b/sound/soc/blackfin/bf5xx-tdm.h
new file mode 100644 (file)
index 0000000..618ec3d
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * sound/soc/blackfin/bf5xx-tdm.h
+ *
+ * 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 _BF5XX_TDM_H
+#define _BF5XX_TDM_H
+
+extern struct snd_soc_dai bf5xx_tdm_dai;
+
+#endif
index bbc97fd7664893b58871e9d026cc20e9d9863774..0edca93af3b07f47348dbc126d805bc135606171 100644 (file)
@@ -12,11 +12,15 @@ config SND_SOC_ALL_CODECS
        tristate "Build all ASoC CODEC drivers"
        select SND_SOC_L3
        select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
+       select SND_SOC_AD1836 if SPI_MASTER
+       select SND_SOC_AD1938 if SPI_MASTER
        select SND_SOC_AD1980 if SND_SOC_AC97_BUS
        select SND_SOC_AD73311 if I2C
        select SND_SOC_AK4104 if SPI_MASTER
        select SND_SOC_AK4535 if I2C
+       select SND_SOC_AK4642 if I2C
        select SND_SOC_CS4270 if I2C
+       select SND_SOC_MAX9877 if I2C
        select SND_SOC_PCM3008
        select SND_SOC_SPDIF
        select SND_SOC_SSM2602 if I2C
@@ -30,18 +34,23 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_WM8350 if MFD_WM8350
        select SND_SOC_WM8400 if MFD_WM8400
        select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
+       select SND_SOC_WM8523 if I2C
        select SND_SOC_WM8580 if I2C
        select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI
        select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI
        select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
        select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI
+       select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI
        select SND_SOC_WM8900 if I2C
        select SND_SOC_WM8903 if I2C
        select SND_SOC_WM8940 if I2C
        select SND_SOC_WM8960 if I2C
+       select SND_SOC_WM8961 if I2C
        select SND_SOC_WM8971 if I2C
+       select SND_SOC_WM8974 if I2C
        select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
        select SND_SOC_WM8990 if I2C
+       select SND_SOC_WM8993 if I2C
        select SND_SOC_WM9081 if I2C
        select SND_SOC_WM9705 if SND_SOC_AC97_BUS
        select SND_SOC_WM9712 if SND_SOC_AC97_BUS
@@ -57,11 +66,21 @@ config SND_SOC_ALL_CODECS
 
           If unsure select "N".
 
+config SND_SOC_WM_HUBS
+       tristate
+       default y if SND_SOC_WM8993=y
+       default m if SND_SOC_WM8993=m
 
 config SND_SOC_AC97_CODEC
        tristate
        select SND_AC97_CODEC
 
+config SND_SOC_AD1836
+       tristate
+
+config SND_SOC_AD1938
+       tristate
+
 config SND_SOC_AD1980
        tristate
 
@@ -74,6 +93,9 @@ config SND_SOC_AK4104
 config SND_SOC_AK4535
        tristate
 
+config SND_SOC_AK4642
+       tristate
+
 # Cirrus Logic CS4270 Codec
 config SND_SOC_CS4270
        tristate
@@ -86,6 +108,9 @@ config SND_SOC_CS4270_VD33_ERRATA
        bool
        depends on SND_SOC_CS4270
 
+config SND_SOC_CX20442
+       tristate
+
 config SND_SOC_L3
        tristate
 
@@ -129,6 +154,9 @@ config SND_SOC_WM8400
 config SND_SOC_WM8510
        tristate
 
+config SND_SOC_WM8523
+       tristate
+
 config SND_SOC_WM8580
        tristate
 
@@ -144,6 +172,9 @@ config SND_SOC_WM8750
 config SND_SOC_WM8753
        tristate
 
+config SND_SOC_WM8776
+       tristate
+
 config SND_SOC_WM8900
        tristate
 
@@ -156,15 +187,24 @@ config SND_SOC_WM8940
 config SND_SOC_WM8960
        tristate
 
+config SND_SOC_WM8961
+       tristate
+
 config SND_SOC_WM8971
        tristate
 
+config SND_SOC_WM8974
+       tristate
+
 config SND_SOC_WM8988
        tristate
 
 config SND_SOC_WM8990
        tristate
 
+config SND_SOC_WM8993
+       tristate
+
 config SND_SOC_WM9081
        tristate
 
@@ -176,3 +216,7 @@ config SND_SOC_WM9712
 
 config SND_SOC_WM9713
        tristate
+
+# Amp
+config SND_SOC_MAX9877
+       tristate
index 8b7530546f4dece45018f54a4894eaa3875d954f..fb4af28486bae91ebbae8539b1b7f5d5c2f9fd2a 100644 (file)
@@ -1,9 +1,13 @@
 snd-soc-ac97-objs := ac97.o
+snd-soc-ad1836-objs := ad1836.o
+snd-soc-ad1938-objs := ad1938.o
 snd-soc-ad1980-objs := ad1980.o
 snd-soc-ad73311-objs := ad73311.o
 snd-soc-ak4104-objs := ak4104.o
 snd-soc-ak4535-objs := ak4535.o
+snd-soc-ak4642-objs := ak4642.o
 snd-soc-cs4270-objs := cs4270.o
+snd-soc-cx20442-objs := cx20442.o
 snd-soc-l3-objs := l3.o
 snd-soc-pcm3008-objs := pcm3008.o
 snd-soc-spdif-objs := spdif_transciever.o
@@ -18,29 +22,42 @@ snd-soc-uda1380-objs := uda1380.o
 snd-soc-wm8350-objs := wm8350.o
 snd-soc-wm8400-objs := wm8400.o
 snd-soc-wm8510-objs := wm8510.o
+snd-soc-wm8523-objs := wm8523.o
 snd-soc-wm8580-objs := wm8580.o
 snd-soc-wm8728-objs := wm8728.o
 snd-soc-wm8731-objs := wm8731.o
 snd-soc-wm8750-objs := wm8750.o
 snd-soc-wm8753-objs := wm8753.o
+snd-soc-wm8776-objs := wm8776.o
 snd-soc-wm8900-objs := wm8900.o
 snd-soc-wm8903-objs := wm8903.o
 snd-soc-wm8940-objs := wm8940.o
 snd-soc-wm8960-objs := wm8960.o
+snd-soc-wm8961-objs := wm8961.o
 snd-soc-wm8971-objs := wm8971.o
+snd-soc-wm8974-objs := wm8974.o
 snd-soc-wm8988-objs := wm8988.o
 snd-soc-wm8990-objs := wm8990.o
+snd-soc-wm8993-objs := wm8993.o
 snd-soc-wm9081-objs := wm9081.o
 snd-soc-wm9705-objs := wm9705.o
 snd-soc-wm9712-objs := wm9712.o
 snd-soc-wm9713-objs := wm9713.o
+snd-soc-wm-hubs-objs := wm_hubs.o
+
+# Amp
+snd-soc-max9877-objs := max9877.o
 
 obj-$(CONFIG_SND_SOC_AC97_CODEC)       += snd-soc-ac97.o
+obj-$(CONFIG_SND_SOC_AD1836)   += snd-soc-ad1836.o
+obj-$(CONFIG_SND_SOC_AD1938)   += snd-soc-ad1938.o
 obj-$(CONFIG_SND_SOC_AD1980)   += snd-soc-ad1980.o
 obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
 obj-$(CONFIG_SND_SOC_AK4104)   += snd-soc-ak4104.o
 obj-$(CONFIG_SND_SOC_AK4535)   += snd-soc-ak4535.o
+obj-$(CONFIG_SND_SOC_AK4642)   += snd-soc-ak4642.o
 obj-$(CONFIG_SND_SOC_CS4270)   += snd-soc-cs4270.o
+obj-$(CONFIG_SND_SOC_CX20442)  += snd-soc-cx20442.o
 obj-$(CONFIG_SND_SOC_L3)       += snd-soc-l3.o
 obj-$(CONFIG_SND_SOC_PCM3008)  += snd-soc-pcm3008.o
 obj-$(CONFIG_SND_SOC_SPDIF)    += snd-soc-spdif.o
@@ -55,19 +72,28 @@ obj-$(CONFIG_SND_SOC_UDA1380)       += snd-soc-uda1380.o
 obj-$(CONFIG_SND_SOC_WM8350)   += snd-soc-wm8350.o
 obj-$(CONFIG_SND_SOC_WM8400)   += snd-soc-wm8400.o
 obj-$(CONFIG_SND_SOC_WM8510)   += snd-soc-wm8510.o
+obj-$(CONFIG_SND_SOC_WM8523)   += snd-soc-wm8523.o
 obj-$(CONFIG_SND_SOC_WM8580)   += snd-soc-wm8580.o
 obj-$(CONFIG_SND_SOC_WM8728)   += snd-soc-wm8728.o
 obj-$(CONFIG_SND_SOC_WM8731)   += snd-soc-wm8731.o
 obj-$(CONFIG_SND_SOC_WM8750)   += snd-soc-wm8750.o
 obj-$(CONFIG_SND_SOC_WM8753)   += snd-soc-wm8753.o
+obj-$(CONFIG_SND_SOC_WM8776)   += snd-soc-wm8776.o
 obj-$(CONFIG_SND_SOC_WM8900)   += snd-soc-wm8900.o
 obj-$(CONFIG_SND_SOC_WM8903)   += snd-soc-wm8903.o
 obj-$(CONFIG_SND_SOC_WM8971)   += snd-soc-wm8971.o
+obj-$(CONFIG_SND_SOC_WM8974)   += snd-soc-wm8974.o
 obj-$(CONFIG_SND_SOC_WM8940)   += snd-soc-wm8940.o
 obj-$(CONFIG_SND_SOC_WM8960)   += snd-soc-wm8960.o
+obj-$(CONFIG_SND_SOC_WM8961)   += snd-soc-wm8961.o
 obj-$(CONFIG_SND_SOC_WM8988)   += snd-soc-wm8988.o
 obj-$(CONFIG_SND_SOC_WM8990)   += snd-soc-wm8990.o
+obj-$(CONFIG_SND_SOC_WM8993)   += snd-soc-wm8993.o
 obj-$(CONFIG_SND_SOC_WM9081)   += snd-soc-wm9081.o
 obj-$(CONFIG_SND_SOC_WM9705)   += snd-soc-wm9705.o
 obj-$(CONFIG_SND_SOC_WM9712)   += snd-soc-wm9712.o
 obj-$(CONFIG_SND_SOC_WM9713)   += snd-soc-wm9713.o
+obj-$(CONFIG_SND_SOC_WM_HUBS)  += snd-soc-wm-hubs.o
+
+# Amp
+obj-$(CONFIG_SND_SOC_MAX9877)  += snd-soc-max9877.o
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
new file mode 100644 (file)
index 0000000..c48485f
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * File:         sound/soc/codecs/ad1836.c
+ * Author:       Barry Song <Barry.Song@analog.com>
+ *
+ * Created:      Aug 04 2009
+ * Description:  Driver for AD1836 sound chip
+ *
+ * Modified:
+ *               Copyright 2009 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <sound/soc-dapm.h>
+#include <linux/spi/spi.h>
+#include "ad1836.h"
+
+/* codec private data */
+struct ad1836_priv {
+       struct snd_soc_codec codec;
+       u16 reg_cache[AD1836_NUM_REGS];
+};
+
+static struct snd_soc_codec *ad1836_codec;
+struct snd_soc_codec_device soc_codec_dev_ad1836;
+static int ad1836_register(struct ad1836_priv *ad1836);
+static void ad1836_unregister(struct ad1836_priv *ad1836);
+
+/*
+ * AD1836 volume/mute/de-emphasis etc. controls
+ */
+static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"};
+
+static const struct soc_enum ad1836_deemp_enum =
+       SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp);
+
+static const struct snd_kcontrol_new ad1836_snd_controls[] = {
+       /* DAC volume control */
+       SOC_DOUBLE_R("DAC1 Volume", AD1836_DAC_L1_VOL,
+                       AD1836_DAC_R1_VOL, 0, 0x3FF, 0),
+       SOC_DOUBLE_R("DAC2 Volume", AD1836_DAC_L2_VOL,
+                       AD1836_DAC_R2_VOL, 0, 0x3FF, 0),
+       SOC_DOUBLE_R("DAC3 Volume", AD1836_DAC_L3_VOL,
+                       AD1836_DAC_R3_VOL, 0, 0x3FF, 0),
+
+       /* ADC switch control */
+       SOC_DOUBLE("ADC1 Switch", AD1836_ADC_CTRL2, AD1836_ADCL1_MUTE,
+               AD1836_ADCR1_MUTE, 1, 1),
+       SOC_DOUBLE("ADC2 Switch", AD1836_ADC_CTRL2, AD1836_ADCL2_MUTE,
+               AD1836_ADCR2_MUTE, 1, 1),
+
+       /* DAC switch control */
+       SOC_DOUBLE("DAC1 Switch", AD1836_DAC_CTRL2, AD1836_DACL1_MUTE,
+               AD1836_DACR1_MUTE, 1, 1),
+       SOC_DOUBLE("DAC2 Switch", AD1836_DAC_CTRL2, AD1836_DACL2_MUTE,
+               AD1836_DACR2_MUTE, 1, 1),
+       SOC_DOUBLE("DAC3 Switch", AD1836_DAC_CTRL2, AD1836_DACL3_MUTE,
+               AD1836_DACR3_MUTE, 1, 1),
+
+       /* ADC high-pass filter */
+       SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1,
+                       AD1836_ADC_HIGHPASS_FILTER, 1, 0),
+
+       /* DAC de-emphasis */
+       SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum),
+};
+
+static const struct snd_soc_dapm_widget ad1836_dapm_widgets[] = {
+       SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1,
+                               AD1836_DAC_POWERDOWN, 1),
+       SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1,
+                               AD1836_ADC_POWERDOWN, 1, NULL, 0),
+       SND_SOC_DAPM_OUTPUT("DAC1OUT"),
+       SND_SOC_DAPM_OUTPUT("DAC2OUT"),
+       SND_SOC_DAPM_OUTPUT("DAC3OUT"),
+       SND_SOC_DAPM_INPUT("ADC1IN"),
+       SND_SOC_DAPM_INPUT("ADC2IN"),
+};
+
+static const struct snd_soc_dapm_route audio_paths[] = {
+       { "DAC", NULL, "ADC_PWR" },
+       { "ADC", NULL, "ADC_PWR" },
+       { "DAC1OUT", "DAC1 Switch", "DAC" },
+       { "DAC2OUT", "DAC2 Switch", "DAC" },
+       { "DAC3OUT", "DAC3 Switch", "DAC" },
+       { "ADC", "ADC1 Switch", "ADC1IN" },
+       { "ADC", "ADC2 Switch", "ADC2IN" },
+};
+
+/*
+ * DAI ops entries
+ */
+
+static int ad1836_set_dai_fmt(struct snd_soc_dai *codec_dai,
+               unsigned int fmt)
+{
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       /* at present, we support adc aux mode to interface with
+        * blackfin sport tdm mode
+        */
+       case SND_SOC_DAIFMT_DSP_A:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_IB_IF:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       /* ALCLK,ABCLK are both output, AD1836 can only be master */
+       case SND_SOC_DAIFMT_CBM_CFM:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int ad1836_hw_params(struct snd_pcm_substream *substream,
+               struct snd_pcm_hw_params *params,
+               struct snd_soc_dai *dai)
+{
+       int word_len = 0;
+
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->card->codec;
+
+       /* bit size */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               word_len = 3;
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               word_len = 1;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+       case SNDRV_PCM_FORMAT_S32_LE:
+               word_len = 0;
+               break;
+       }
+
+       snd_soc_update_bits(codec, AD1836_DAC_CTRL1,
+               AD1836_DAC_WORD_LEN_MASK, word_len);
+
+       snd_soc_update_bits(codec, AD1836_ADC_CTRL2,
+               AD1836_ADC_WORD_LEN_MASK, word_len);
+
+       return 0;
+}
+
+
+/*
+ * interface to read/write ad1836 register
+ */
+#define AD1836_SPI_REG_SHFT 12
+#define AD1836_SPI_READ     (1 << 11)
+#define AD1836_SPI_VAL_MSK  0x3FF
+
+/*
+ * write to the ad1836 register space
+ */
+
+static int ad1836_write_reg(struct snd_soc_codec *codec, unsigned int reg,
+               unsigned int value)
+{
+       u16 *reg_cache = codec->reg_cache;
+       int ret = 0;
+
+       if (value != reg_cache[reg]) {
+               unsigned short buf;
+               struct spi_transfer t = {
+                       .tx_buf = &buf,
+                       .len = 2,
+               };
+               struct spi_message m;
+
+               buf = (reg << AD1836_SPI_REG_SHFT) |
+                       (value & AD1836_SPI_VAL_MSK);
+               spi_message_init(&m);
+               spi_message_add_tail(&t, &m);
+               ret = spi_sync(codec->control_data, &m);
+               if (ret == 0)
+                       reg_cache[reg] = value;
+       }
+
+       return ret;
+}
+
+/*
+ * read from the ad1836 register space cache
+ */
+static unsigned int ad1836_read_reg_cache(struct snd_soc_codec *codec,
+                                         unsigned int reg)
+{
+       u16 *reg_cache = codec->reg_cache;
+
+       if (reg >= codec->reg_cache_size)
+               return -EINVAL;
+
+       return reg_cache[reg];
+}
+
+static int __devinit ad1836_spi_probe(struct spi_device *spi)
+{
+       struct snd_soc_codec *codec;
+       struct ad1836_priv *ad1836;
+
+       ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
+       if (ad1836 == NULL)
+               return -ENOMEM;
+
+       codec = &ad1836->codec;
+       codec->control_data = spi;
+       codec->dev = &spi->dev;
+
+       dev_set_drvdata(&spi->dev, ad1836);
+
+       return ad1836_register(ad1836);
+}
+
+static int __devexit ad1836_spi_remove(struct spi_device *spi)
+{
+       struct ad1836_priv *ad1836 = dev_get_drvdata(&spi->dev);
+
+       ad1836_unregister(ad1836);
+       return 0;
+}
+
+static struct spi_driver ad1836_spi_driver = {
+       .driver = {
+               .name   = "ad1836",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = ad1836_spi_probe,
+       .remove         = __devexit_p(ad1836_spi_remove),
+};
+
+static struct snd_soc_dai_ops ad1836_dai_ops = {
+       .hw_params = ad1836_hw_params,
+       .set_fmt = ad1836_set_dai_fmt,
+};
+
+/* codec DAI instance */
+struct snd_soc_dai ad1836_dai = {
+       .name = "AD1836",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 2,
+               .channels_max = 6,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
+       },
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 2,
+               .channels_max = 4,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
+       },
+       .ops = &ad1836_dai_ops,
+};
+EXPORT_SYMBOL_GPL(ad1836_dai);
+
+static int ad1836_register(struct ad1836_priv *ad1836)
+{
+       int ret;
+       struct snd_soc_codec *codec = &ad1836->codec;
+
+       if (ad1836_codec) {
+               dev_err(codec->dev, "Another ad1836 is registered\n");
+               return -EINVAL;
+       }
+
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+       codec->private_data = ad1836;
+       codec->reg_cache = ad1836->reg_cache;
+       codec->reg_cache_size = AD1836_NUM_REGS;
+       codec->name = "AD1836";
+       codec->owner = THIS_MODULE;
+       codec->dai = &ad1836_dai;
+       codec->num_dai = 1;
+       codec->write = ad1836_write_reg;
+       codec->read = ad1836_read_reg_cache;
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       ad1836_dai.dev = codec->dev;
+       ad1836_codec = codec;
+
+       /* default setting for ad1836 */
+       /* de-emphasis: 48kHz, power-on dac */
+       codec->write(codec, AD1836_DAC_CTRL1, 0x300);
+       /* unmute dac channels */
+       codec->write(codec, AD1836_DAC_CTRL2, 0x0);
+       /* high-pass filter enable, power-on adc */
+       codec->write(codec, AD1836_ADC_CTRL1, 0x100);
+       /* unmute adc channles, adc aux mode */
+       codec->write(codec, AD1836_ADC_CTRL2, 0x180);
+       /* left/right diff:PGA/MUX */
+       codec->write(codec, AD1836_ADC_CTRL3, 0x3A);
+       /* volume */
+       codec->write(codec, AD1836_DAC_L1_VOL, 0x3FF);
+       codec->write(codec, AD1836_DAC_R1_VOL, 0x3FF);
+       codec->write(codec, AD1836_DAC_L2_VOL, 0x3FF);
+       codec->write(codec, AD1836_DAC_R2_VOL, 0x3FF);
+       codec->write(codec, AD1836_DAC_L3_VOL, 0x3FF);
+       codec->write(codec, AD1836_DAC_R3_VOL, 0x3FF);
+
+       ret = snd_soc_register_codec(codec);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+               kfree(ad1836);
+               return ret;
+       }
+
+       ret = snd_soc_register_dai(&ad1836_dai);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
+               snd_soc_unregister_codec(codec);
+               kfree(ad1836);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void ad1836_unregister(struct ad1836_priv *ad1836)
+{
+       snd_soc_unregister_dai(&ad1836_dai);
+       snd_soc_unregister_codec(&ad1836->codec);
+       kfree(ad1836);
+       ad1836_codec = NULL;
+}
+
+static int ad1836_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec;
+       int ret = 0;
+
+       if (ad1836_codec == NULL) {
+               dev_err(&pdev->dev, "Codec device not registered\n");
+               return -ENODEV;
+       }
+
+       socdev->card->codec = ad1836_codec;
+       codec = ad1836_codec;
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to create pcms: %d\n", ret);
+               goto pcm_err;
+       }
+
+       snd_soc_add_controls(codec, ad1836_snd_controls,
+                            ARRAY_SIZE(ad1836_snd_controls));
+       snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets,
+                                 ARRAY_SIZE(ad1836_dapm_widgets));
+       snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
+       snd_soc_dapm_new_widgets(codec);
+
+       ret = snd_soc_init_card(socdev);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to register card: %d\n", ret);
+               goto card_err;
+       }
+
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+pcm_err:
+       return ret;
+}
+
+/* power down chip */
+static int ad1836_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+
+       return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_ad1836 = {
+       .probe =        ad1836_probe,
+       .remove =       ad1836_remove,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836);
+
+static int __init ad1836_init(void)
+{
+       int ret;
+
+       ret = spi_register_driver(&ad1836_spi_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register ad1836 SPI driver: %d\n",
+                               ret);
+       }
+
+       return ret;
+}
+module_init(ad1836_init);
+
+static void __exit ad1836_exit(void)
+{
+       spi_unregister_driver(&ad1836_spi_driver);
+}
+module_exit(ad1836_exit);
+
+MODULE_DESCRIPTION("ASoC ad1836 driver");
+MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h
new file mode 100644 (file)
index 0000000..7660ee6
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * File:         sound/soc/codecs/ad1836.h
+ * Based on:
+ * Author:       Barry Song <Barry.Song@analog.com>
+ *
+ * Created:      Aug 04, 2009
+ * Description:  definitions for AD1836 registers
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __AD1836_H__
+#define __AD1836_H__
+
+#define AD1836_DAC_CTRL1               0
+#define AD1836_DAC_POWERDOWN           2
+#define AD1836_DAC_SERFMT_MASK        0xE0
+#define AD1836_DAC_SERFMT_PCK256       (0x4 << 5)
+#define AD1836_DAC_SERFMT_PCK128       (0x5 << 5)
+#define AD1836_DAC_WORD_LEN_MASK       0x18
+
+#define AD1836_DAC_CTRL2               1
+#define AD1836_DACL1_MUTE              0
+#define AD1836_DACR1_MUTE              1
+#define AD1836_DACL2_MUTE              2
+#define AD1836_DACR2_MUTE              3
+#define AD1836_DACL3_MUTE              4
+#define AD1836_DACR3_MUTE              5
+
+#define AD1836_DAC_L1_VOL              2
+#define AD1836_DAC_R1_VOL              3
+#define AD1836_DAC_L2_VOL              4
+#define AD1836_DAC_R2_VOL              5
+#define AD1836_DAC_L3_VOL              6
+#define AD1836_DAC_R3_VOL              7
+
+#define AD1836_ADC_CTRL1               12
+#define AD1836_ADC_POWERDOWN           7
+#define AD1836_ADC_HIGHPASS_FILTER     8
+
+#define AD1836_ADC_CTRL2               13
+#define AD1836_ADCL1_MUTE              0
+#define AD1836_ADCR1_MUTE              1
+#define AD1836_ADCL2_MUTE              2
+#define AD1836_ADCR2_MUTE              3
+#define AD1836_ADC_WORD_LEN_MASK       0x30
+#define AD1836_ADC_SERFMT_MASK        (7 << 6)
+#define AD1836_ADC_SERFMT_PCK256       (0x4 << 6)
+#define AD1836_ADC_SERFMT_PCK128       (0x5 << 6)
+
+#define AD1836_ADC_CTRL3               14
+
+#define AD1836_NUM_REGS                16
+
+extern struct snd_soc_dai ad1836_dai;
+extern struct snd_soc_codec_device soc_codec_dev_ad1836;
+#endif
diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c
new file mode 100644 (file)
index 0000000..34b30ef
--- /dev/null
@@ -0,0 +1,681 @@
+/*
+ * File:         sound/soc/codecs/ad1938.c
+ * Author:       Barry Song <Barry.Song@analog.com>
+ *
+ * Created:      June 04 2009
+ * Description:  Driver for AD1938 sound chip
+ *
+ * Modified:
+ *               Copyright 2009 Analog Devices Inc.
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <sound/soc-dapm.h>
+#include <linux/spi/spi.h>
+#include "ad1938.h"
+
+/* codec private data */
+struct ad1938_priv {
+       struct snd_soc_codec codec;
+       u8 reg_cache[AD1938_NUM_REGS];
+};
+
+static struct snd_soc_codec *ad1938_codec;
+struct snd_soc_codec_device soc_codec_dev_ad1938;
+static int ad1938_register(struct ad1938_priv *ad1938);
+static void ad1938_unregister(struct ad1938_priv *ad1938);
+
+/*
+ * AD1938 volume/mute/de-emphasis etc. controls
+ */
+static const char *ad1938_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
+
+static const struct soc_enum ad1938_deemp_enum =
+       SOC_ENUM_SINGLE(AD1938_DAC_CTRL2, 1, 4, ad1938_deemp);
+
+static const struct snd_kcontrol_new ad1938_snd_controls[] = {
+       /* DAC volume control */
+       SOC_DOUBLE_R("DAC1  Volume", AD1938_DAC_L1_VOL,
+                       AD1938_DAC_R1_VOL, 0, 0xFF, 1),
+       SOC_DOUBLE_R("DAC2  Volume", AD1938_DAC_L2_VOL,
+                       AD1938_DAC_R2_VOL, 0, 0xFF, 1),
+       SOC_DOUBLE_R("DAC3  Volume", AD1938_DAC_L3_VOL,
+                       AD1938_DAC_R3_VOL, 0, 0xFF, 1),
+       SOC_DOUBLE_R("DAC4  Volume", AD1938_DAC_L4_VOL,
+                       AD1938_DAC_R4_VOL, 0, 0xFF, 1),
+
+       /* ADC switch control */
+       SOC_DOUBLE("ADC1 Switch", AD1938_ADC_CTRL0, AD1938_ADCL1_MUTE,
+               AD1938_ADCR1_MUTE, 1, 1),
+       SOC_DOUBLE("ADC2 Switch", AD1938_ADC_CTRL0, AD1938_ADCL2_MUTE,
+               AD1938_ADCR2_MUTE, 1, 1),
+
+       /* DAC switch control */
+       SOC_DOUBLE("DAC1 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL1_MUTE,
+               AD1938_DACR1_MUTE, 1, 1),
+       SOC_DOUBLE("DAC2 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL2_MUTE,
+               AD1938_DACR2_MUTE, 1, 1),
+       SOC_DOUBLE("DAC3 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL3_MUTE,
+               AD1938_DACR3_MUTE, 1, 1),
+       SOC_DOUBLE("DAC4 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL4_MUTE,
+               AD1938_DACR4_MUTE, 1, 1),
+
+       /* ADC high-pass filter */
+       SOC_SINGLE("ADC High Pass Filter Switch", AD1938_ADC_CTRL0,
+                       AD1938_ADC_HIGHPASS_FILTER, 1, 0),
+
+       /* DAC de-emphasis */
+       SOC_ENUM("Playback Deemphasis", ad1938_deemp_enum),
+};
+
+static const struct snd_soc_dapm_widget ad1938_dapm_widgets[] = {
+       SND_SOC_DAPM_DAC("DAC", "Playback", AD1938_DAC_CTRL0, 0, 1),
+       SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1938_ADC_CTRL0, 0, 1, NULL, 0),
+       SND_SOC_DAPM_OUTPUT("DAC1OUT"),
+       SND_SOC_DAPM_OUTPUT("DAC2OUT"),
+       SND_SOC_DAPM_OUTPUT("DAC3OUT"),
+       SND_SOC_DAPM_OUTPUT("DAC4OUT"),
+       SND_SOC_DAPM_INPUT("ADC1IN"),
+       SND_SOC_DAPM_INPUT("ADC2IN"),
+};
+
+static const struct snd_soc_dapm_route audio_paths[] = {
+       { "DAC", NULL, "ADC_PWR" },
+       { "ADC", NULL, "ADC_PWR" },
+       { "DAC1OUT", "DAC1 Switch", "DAC" },
+       { "DAC2OUT", "DAC2 Switch", "DAC" },
+       { "DAC3OUT", "DAC3 Switch", "DAC" },
+       { "DAC4OUT", "DAC4 Switch", "DAC" },
+       { "ADC", "ADC1 Switch", "ADC1IN" },
+       { "ADC", "ADC2 Switch", "ADC2IN" },
+};
+
+/*
+ * DAI ops entries
+ */
+
+static int ad1938_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       int reg;
+
+       reg = codec->read(codec, AD1938_DAC_CTRL2);
+       reg = (mute > 0) ? reg | AD1938_DAC_MASTER_MUTE : reg &
+               (~AD1938_DAC_MASTER_MUTE);
+       codec->write(codec, AD1938_DAC_CTRL2, reg);
+
+       return 0;
+}
+
+static inline int ad1938_pll_powerctrl(struct snd_soc_codec *codec, int cmd)
+{
+       int reg = codec->read(codec, AD1938_PLL_CLK_CTRL0);
+       reg = (cmd > 0) ? reg & (~AD1938_PLL_POWERDOWN) : reg |
+               AD1938_PLL_POWERDOWN;
+       codec->write(codec, AD1938_PLL_CLK_CTRL0, reg);
+
+       return 0;
+}
+
+static int ad1938_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+                              unsigned int mask, int slots, int width)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       int dac_reg = codec->read(codec, AD1938_DAC_CTRL1);
+       int adc_reg = codec->read(codec, AD1938_ADC_CTRL2);
+
+       dac_reg &= ~AD1938_DAC_CHAN_MASK;
+       adc_reg &= ~AD1938_ADC_CHAN_MASK;
+
+       switch (slots) {
+       case 2:
+               dac_reg |= AD1938_DAC_2_CHANNELS << AD1938_DAC_CHAN_SHFT;
+               adc_reg |= AD1938_ADC_2_CHANNELS << AD1938_ADC_CHAN_SHFT;
+               break;
+       case 4:
+               dac_reg |= AD1938_DAC_4_CHANNELS << AD1938_DAC_CHAN_SHFT;
+               adc_reg |= AD1938_ADC_4_CHANNELS << AD1938_ADC_CHAN_SHFT;
+               break;
+       case 8:
+               dac_reg |= AD1938_DAC_8_CHANNELS << AD1938_DAC_CHAN_SHFT;
+               adc_reg |= AD1938_ADC_8_CHANNELS << AD1938_ADC_CHAN_SHFT;
+               break;
+       case 16:
+               dac_reg |= AD1938_DAC_16_CHANNELS << AD1938_DAC_CHAN_SHFT;
+               adc_reg |= AD1938_ADC_16_CHANNELS << AD1938_ADC_CHAN_SHFT;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       codec->write(codec, AD1938_DAC_CTRL1, dac_reg);
+       codec->write(codec, AD1938_ADC_CTRL2, adc_reg);
+
+       return 0;
+}
+
+static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai,
+               unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       int adc_reg, dac_reg;
+
+       adc_reg = codec->read(codec, AD1938_ADC_CTRL2);
+       dac_reg = codec->read(codec, AD1938_DAC_CTRL1);
+
+       /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
+        * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
+        */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               adc_reg &= ~AD1938_ADC_SERFMT_MASK;
+               adc_reg |= AD1938_ADC_SERFMT_TDM;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               adc_reg &= ~AD1938_ADC_SERFMT_MASK;
+               adc_reg |= AD1938_ADC_SERFMT_AUX;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
+               adc_reg &= ~AD1938_ADC_LEFT_HIGH;
+               adc_reg &= ~AD1938_ADC_BCLK_INV;
+               dac_reg &= ~AD1938_DAC_LEFT_HIGH;
+               dac_reg &= ~AD1938_DAC_BCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */
+               adc_reg |= AD1938_ADC_LEFT_HIGH;
+               adc_reg &= ~AD1938_ADC_BCLK_INV;
+               dac_reg |= AD1938_DAC_LEFT_HIGH;
+               dac_reg &= ~AD1938_DAC_BCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */
+               adc_reg &= ~AD1938_ADC_LEFT_HIGH;
+               adc_reg |= AD1938_ADC_BCLK_INV;
+               dac_reg &= ~AD1938_DAC_LEFT_HIGH;
+               dac_reg |= AD1938_DAC_BCLK_INV;
+               break;
+
+       case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */
+               adc_reg |= AD1938_ADC_LEFT_HIGH;
+               adc_reg |= AD1938_ADC_BCLK_INV;
+               dac_reg |= AD1938_DAC_LEFT_HIGH;
+               dac_reg |= AD1938_DAC_BCLK_INV;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
+               adc_reg |= AD1938_ADC_LCR_MASTER;
+               adc_reg |= AD1938_ADC_BCLK_MASTER;
+               dac_reg |= AD1938_DAC_LCR_MASTER;
+               dac_reg |= AD1938_DAC_BCLK_MASTER;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */
+               adc_reg |= AD1938_ADC_LCR_MASTER;
+               adc_reg &= ~AD1938_ADC_BCLK_MASTER;
+               dac_reg |= AD1938_DAC_LCR_MASTER;
+               dac_reg &= ~AD1938_DAC_BCLK_MASTER;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
+               adc_reg &= ~AD1938_ADC_LCR_MASTER;
+               adc_reg |= AD1938_ADC_BCLK_MASTER;
+               dac_reg &= ~AD1938_DAC_LCR_MASTER;
+               dac_reg |= AD1938_DAC_BCLK_MASTER;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */
+               adc_reg &= ~AD1938_ADC_LCR_MASTER;
+               adc_reg &= ~AD1938_ADC_BCLK_MASTER;
+               dac_reg &= ~AD1938_DAC_LCR_MASTER;
+               dac_reg &= ~AD1938_DAC_BCLK_MASTER;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       codec->write(codec, AD1938_ADC_CTRL2, adc_reg);
+       codec->write(codec, AD1938_DAC_CTRL1, dac_reg);
+
+       return 0;
+}
+
+static int ad1938_hw_params(struct snd_pcm_substream *substream,
+               struct snd_pcm_hw_params *params,
+               struct snd_soc_dai *dai)
+{
+       int word_len = 0, reg = 0;
+
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->card->codec;
+
+       /* bit size */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               word_len = 3;
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               word_len = 1;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+       case SNDRV_PCM_FORMAT_S32_LE:
+               word_len = 0;
+               break;
+       }
+
+       reg = codec->read(codec, AD1938_DAC_CTRL2);
+       reg = (reg & (~AD1938_DAC_WORD_LEN_MASK)) | word_len;
+       codec->write(codec, AD1938_DAC_CTRL2, reg);
+
+       reg = codec->read(codec, AD1938_ADC_CTRL1);
+       reg = (reg & (~AD1938_ADC_WORD_LEN_MASK)) | word_len;
+       codec->write(codec, AD1938_ADC_CTRL1, reg);
+
+       return 0;
+}
+
+static int ad1938_set_bias_level(struct snd_soc_codec *codec,
+               enum snd_soc_bias_level level)
+{
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               ad1938_pll_powerctrl(codec, 1);
+               break;
+       case SND_SOC_BIAS_PREPARE:
+               break;
+       case SND_SOC_BIAS_STANDBY:
+       case SND_SOC_BIAS_OFF:
+               ad1938_pll_powerctrl(codec, 0);
+               break;
+       }
+       codec->bias_level = level;
+       return 0;
+}
+
+/*
+ * interface to read/write ad1938 register
+ */
+
+#define AD1938_SPI_ADDR    0x4
+#define AD1938_SPI_READ    0x1
+#define AD1938_SPI_BUFLEN  3
+
+/*
+ * write to the ad1938 register space
+ */
+
+static int ad1938_write_reg(struct snd_soc_codec *codec, unsigned int reg,
+               unsigned int value)
+{
+       u8 *reg_cache = codec->reg_cache;
+       int ret = 0;
+
+       if (value != reg_cache[reg]) {
+               uint8_t buf[AD1938_SPI_BUFLEN];
+               struct spi_transfer t = {
+                       .tx_buf = buf,
+                       .len = AD1938_SPI_BUFLEN,
+               };
+               struct spi_message m;
+
+               buf[0] = AD1938_SPI_ADDR << 1;
+               buf[1] = reg;
+               buf[2] = value;
+               spi_message_init(&m);
+               spi_message_add_tail(&t, &m);
+               ret = spi_sync(codec->control_data, &m);
+               if (ret == 0)
+                       reg_cache[reg] = value;
+       }
+
+       return ret;
+}
+
+/*
+ * read from the ad1938 register space cache
+ */
+
+static unsigned int ad1938_read_reg_cache(struct snd_soc_codec *codec,
+                                         unsigned int reg)
+{
+       u8 *reg_cache = codec->reg_cache;
+
+       if (reg >= codec->reg_cache_size)
+               return -EINVAL;
+
+       return reg_cache[reg];
+}
+
+/*
+ * read from the ad1938 register space
+ */
+
+static unsigned int ad1938_read_reg(struct snd_soc_codec *codec,
+                                               unsigned int reg)
+{
+       char w_buf[AD1938_SPI_BUFLEN];
+       char r_buf[AD1938_SPI_BUFLEN];
+       int ret;
+
+       struct spi_transfer t = {
+               .tx_buf = w_buf,
+               .rx_buf = r_buf,
+               .len = AD1938_SPI_BUFLEN,
+       };
+       struct spi_message m;
+
+       w_buf[0] = (AD1938_SPI_ADDR << 1) | AD1938_SPI_READ;
+       w_buf[1] = reg;
+       w_buf[2] = 0;
+
+       spi_message_init(&m);
+       spi_message_add_tail(&t, &m);
+       ret = spi_sync(codec->control_data, &m);
+       if (ret == 0)
+               return  r_buf[2];
+       else
+               return -EIO;
+}
+
+static int ad1938_fill_cache(struct snd_soc_codec *codec)
+{
+       int i;
+       u8 *reg_cache = codec->reg_cache;
+       struct spi_device *spi = codec->control_data;
+
+       for (i = 0; i < codec->reg_cache_size; i++) {
+               int ret = ad1938_read_reg(codec, i);
+               if (ret == -EIO) {
+                       dev_err(&spi->dev, "AD1938 SPI read failure\n");
+                       return ret;
+               }
+               reg_cache[i] = ret;
+       }
+
+       return 0;
+}
+
+static int __devinit ad1938_spi_probe(struct spi_device *spi)
+{
+       struct snd_soc_codec *codec;
+       struct ad1938_priv *ad1938;
+
+       ad1938 = kzalloc(sizeof(struct ad1938_priv), GFP_KERNEL);
+       if (ad1938 == NULL)
+               return -ENOMEM;
+
+       codec = &ad1938->codec;
+       codec->control_data = spi;
+       codec->dev = &spi->dev;
+
+       dev_set_drvdata(&spi->dev, ad1938);
+
+       return ad1938_register(ad1938);
+}
+
+static int __devexit ad1938_spi_remove(struct spi_device *spi)
+{
+       struct ad1938_priv *ad1938 = dev_get_drvdata(&spi->dev);
+
+       ad1938_unregister(ad1938);
+       return 0;
+}
+
+static struct spi_driver ad1938_spi_driver = {
+       .driver = {
+               .name   = "ad1938",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = ad1938_spi_probe,
+       .remove         = __devexit_p(ad1938_spi_remove),
+};
+
+static struct snd_soc_dai_ops ad1938_dai_ops = {
+       .hw_params = ad1938_hw_params,
+       .digital_mute = ad1938_mute,
+       .set_tdm_slot = ad1938_set_tdm_slot,
+       .set_fmt = ad1938_set_dai_fmt,
+};
+
+/* codec DAI instance */
+struct snd_soc_dai ad1938_dai = {
+       .name = "AD1938",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 2,
+               .channels_max = 8,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
+       },
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 2,
+               .channels_max = 4,
+               .rates = SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE |
+                       SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE,
+       },
+       .ops = &ad1938_dai_ops,
+};
+EXPORT_SYMBOL_GPL(ad1938_dai);
+
+static int ad1938_register(struct ad1938_priv *ad1938)
+{
+       int ret;
+       struct snd_soc_codec *codec = &ad1938->codec;
+
+       if (ad1938_codec) {
+               dev_err(codec->dev, "Another ad1938 is registered\n");
+               return -EINVAL;
+       }
+
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+       codec->private_data = ad1938;
+       codec->reg_cache = ad1938->reg_cache;
+       codec->reg_cache_size = AD1938_NUM_REGS;
+       codec->name = "AD1938";
+       codec->owner = THIS_MODULE;
+       codec->dai = &ad1938_dai;
+       codec->num_dai = 1;
+       codec->write = ad1938_write_reg;
+       codec->read = ad1938_read_reg_cache;
+       codec->set_bias_level = ad1938_set_bias_level;
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       ad1938_dai.dev = codec->dev;
+       ad1938_codec = codec;
+
+       /* default setting for ad1938 */
+
+       /* unmute dac channels */
+       codec->write(codec, AD1938_DAC_CHNL_MUTE, 0x0);
+       /* de-emphasis: 48kHz, powedown dac */
+       codec->write(codec, AD1938_DAC_CTRL2, 0x1A);
+       /* powerdown dac, dac in tdm mode */
+       codec->write(codec, AD1938_DAC_CTRL0, 0x41);
+       /* high-pass filter enable */
+       codec->write(codec, AD1938_ADC_CTRL0, 0x3);
+       /* sata delay=1, adc aux mode */
+       codec->write(codec, AD1938_ADC_CTRL1, 0x43);
+       /* pll input: mclki/xi */
+       codec->write(codec, AD1938_PLL_CLK_CTRL0, 0x9D);
+       codec->write(codec, AD1938_PLL_CLK_CTRL1, 0x04);
+
+       ad1938_fill_cache(codec);
+
+       ret = snd_soc_register_codec(codec);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+               kfree(ad1938);
+               return ret;
+       }
+
+       ret = snd_soc_register_dai(&ad1938_dai);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
+               snd_soc_unregister_codec(codec);
+               kfree(ad1938);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void ad1938_unregister(struct ad1938_priv *ad1938)
+{
+       ad1938_set_bias_level(&ad1938->codec, SND_SOC_BIAS_OFF);
+       snd_soc_unregister_dai(&ad1938_dai);
+       snd_soc_unregister_codec(&ad1938->codec);
+       kfree(ad1938);
+       ad1938_codec = NULL;
+}
+
+static int ad1938_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec;
+       int ret = 0;
+
+       if (ad1938_codec == NULL) {
+               dev_err(&pdev->dev, "Codec device not registered\n");
+               return -ENODEV;
+       }
+
+       socdev->card->codec = ad1938_codec;
+       codec = ad1938_codec;
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to create pcms: %d\n", ret);
+               goto pcm_err;
+       }
+
+       snd_soc_add_controls(codec, ad1938_snd_controls,
+                            ARRAY_SIZE(ad1938_snd_controls));
+       snd_soc_dapm_new_controls(codec, ad1938_dapm_widgets,
+                                 ARRAY_SIZE(ad1938_dapm_widgets));
+       snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
+       snd_soc_dapm_new_widgets(codec);
+
+       ad1938_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       ret = snd_soc_init_card(socdev);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to register card: %d\n", ret);
+               goto card_err;
+       }
+
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+pcm_err:
+       return ret;
+}
+
+/* power down chip */
+static int ad1938_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int ad1938_suspend(struct platform_device *pdev,
+               pm_message_t state)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+
+       ad1938_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int ad1938_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+
+       if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
+               ad1938_set_bias_level(codec, SND_SOC_BIAS_ON);
+
+       return 0;
+}
+#else
+#define ad1938_suspend NULL
+#define ad1938_resume NULL
+#endif
+
+struct snd_soc_codec_device soc_codec_dev_ad1938 = {
+       .probe =        ad1938_probe,
+       .remove =       ad1938_remove,
+       .suspend =      ad1938_suspend,
+       .resume =       ad1938_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_ad1938);
+
+static int __init ad1938_init(void)
+{
+       int ret;
+
+       ret = spi_register_driver(&ad1938_spi_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register ad1938 SPI driver: %d\n",
+                               ret);
+       }
+
+       return ret;
+}
+module_init(ad1938_init);
+
+static void __exit ad1938_exit(void)
+{
+       spi_unregister_driver(&ad1938_spi_driver);
+}
+module_exit(ad1938_exit);
+
+MODULE_DESCRIPTION("ASoC ad1938 driver");
+MODULE_AUTHOR("Barry Song ");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ad1938.h b/sound/soc/codecs/ad1938.h
new file mode 100644 (file)
index 0000000..fe3c48c
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * File:         sound/soc/codecs/ad1836.h
+ * Based on:
+ * Author:       Barry Song <Barry.Song@analog.com>
+ *
+ * Created:      May 25, 2009
+ * Description:  definitions for AD1938 registers
+ *
+ * Modified:
+ *
+ * Bugs:         Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This 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, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __AD1938_H__
+#define __AD1938_H__
+
+#define AD1938_PLL_CLK_CTRL0    0
+#define AD1938_PLL_POWERDOWN           0x01
+#define AD1938_PLL_CLK_CTRL1    1
+#define AD1938_DAC_CTRL0        2
+#define AD1938_DAC_POWERDOWN           0x01
+#define AD1938_DAC_SERFMT_MASK         0xC0
+#define AD1938_DAC_SERFMT_STEREO       (0 << 6)
+#define AD1938_DAC_SERFMT_TDM          (1 << 6)
+#define AD1938_DAC_CTRL1        3
+#define AD1938_DAC_2_CHANNELS   0
+#define AD1938_DAC_4_CHANNELS   1
+#define AD1938_DAC_8_CHANNELS   2
+#define AD1938_DAC_16_CHANNELS  3
+#define AD1938_DAC_CHAN_SHFT    1
+#define AD1938_DAC_CHAN_MASK    (3 << AD1938_DAC_CHAN_SHFT)
+#define AD1938_DAC_LCR_MASTER   (1 << 4)
+#define AD1938_DAC_BCLK_MASTER  (1 << 5)
+#define AD1938_DAC_LEFT_HIGH    (1 << 3)
+#define AD1938_DAC_BCLK_INV     (1 << 7)
+#define AD1938_DAC_CTRL2        4
+#define AD1938_DAC_WORD_LEN_MASK       0xC
+#define AD1938_DAC_MASTER_MUTE  1
+#define AD1938_DAC_CHNL_MUTE    5
+#define AD1938_DACL1_MUTE       0
+#define AD1938_DACR1_MUTE       1
+#define AD1938_DACL2_MUTE       2
+#define AD1938_DACR2_MUTE       3
+#define AD1938_DACL3_MUTE       4
+#define AD1938_DACR3_MUTE       5
+#define AD1938_DACL4_MUTE       6
+#define AD1938_DACR4_MUTE       7
+#define AD1938_DAC_L1_VOL       6
+#define AD1938_DAC_R1_VOL       7
+#define AD1938_DAC_L2_VOL       8
+#define AD1938_DAC_R2_VOL       9
+#define AD1938_DAC_L3_VOL       10
+#define AD1938_DAC_R3_VOL       11
+#define AD1938_DAC_L4_VOL       12
+#define AD1938_DAC_R4_VOL       13
+#define AD1938_ADC_CTRL0        14
+#define AD1938_ADC_POWERDOWN           0x01
+#define AD1938_ADC_HIGHPASS_FILTER     1
+#define AD1938_ADCL1_MUTE              2
+#define AD1938_ADCR1_MUTE              3
+#define AD1938_ADCL2_MUTE              4
+#define AD1938_ADCR2_MUTE              5
+#define AD1938_ADC_CTRL1        15
+#define AD1938_ADC_SERFMT_MASK         0x60
+#define AD1938_ADC_SERFMT_STEREO       (0 << 5)
+#define AD1938_ADC_SERFMT_TDM          (1 << 2)
+#define AD1938_ADC_SERFMT_AUX          (2 << 5)
+#define AD1938_ADC_WORD_LEN_MASK       0x3
+#define AD1938_ADC_CTRL2        16
+#define AD1938_ADC_2_CHANNELS   0
+#define AD1938_ADC_4_CHANNELS   1
+#define AD1938_ADC_8_CHANNELS   2
+#define AD1938_ADC_16_CHANNELS  3
+#define AD1938_ADC_CHAN_SHFT    4
+#define AD1938_ADC_CHAN_MASK    (3 << AD1938_ADC_CHAN_SHFT)
+#define AD1938_ADC_LCR_MASTER   (1 << 3)
+#define AD1938_ADC_BCLK_MASTER  (1 << 6)
+#define AD1938_ADC_LEFT_HIGH    (1 << 2)
+#define AD1938_ADC_BCLK_INV     (1 << 1)
+
+#define AD1938_NUM_REGS          17
+
+extern struct snd_soc_dai ad1938_dai;
+extern struct snd_soc_codec_device soc_codec_dev_ad1938;
+#endif
index dd3380202766cf0ff8d1aec6ea9193317f458fa1..0abec0d29a964ec457e65e7f618feb4dd6bacd72 100644 (file)
@@ -59,21 +59,6 @@ static inline unsigned int ak4535_read_reg_cache(struct snd_soc_codec *codec,
        return cache[reg];
 }
 
-static inline unsigned int ak4535_read(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u8 data;
-       data = reg;
-
-       if (codec->hw_write(codec->control_data, &data, 1) != 1)
-               return -EIO;
-
-       if (codec->hw_read(codec->control_data, &data, 1) != 1)
-               return -EIO;
-
-       return data;
-};
-
 /*
  * write ak4535 register cache
  */
@@ -635,7 +620,6 @@ static int ak4535_probe(struct platform_device *pdev)
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        if (setup->i2c_address) {
                codec->hw_write = (hw_write_t)i2c_master_send;
-               codec->hw_read = (hw_read_t)i2c_master_recv;
                ret = ak4535_add_i2c_device(pdev, setup);
        }
 #endif
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
new file mode 100644 (file)
index 0000000..e057c7b
--- /dev/null
@@ -0,0 +1,502 @@
+/*
+ * ak4642.c  --  AK4642/AK4643 ALSA Soc Audio driver
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on wm8731.c by Richard Purdie
+ * Based on ak4535.c by Richard Purdie
+ * Based on wm8753.c by Liam Girdwood
+ *
+ * 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.
+ */
+
+/* ** CAUTION **
+ *
+ * This is very simple driver.
+ * It can use headphone output / stereo input only
+ *
+ * AK4642 is not tested.
+ * AK4643 is tested.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+#include "ak4642.h"
+
+#define AK4642_VERSION "0.0.1"
+
+#define PW_MGMT1       0x00
+#define PW_MGMT2       0x01
+#define SG_SL1         0x02
+#define SG_SL2         0x03
+#define MD_CTL1                0x04
+#define MD_CTL2                0x05
+#define TIMER          0x06
+#define ALC_CTL1       0x07
+#define ALC_CTL2       0x08
+#define L_IVC          0x09
+#define L_DVC          0x0a
+#define ALC_CTL3       0x0b
+#define R_IVC          0x0c
+#define R_DVC          0x0d
+#define MD_CTL3                0x0e
+#define MD_CTL4                0x0f
+#define PW_MGMT3       0x10
+#define DF_S           0x11
+#define FIL3_0         0x12
+#define FIL3_1         0x13
+#define FIL3_2         0x14
+#define FIL3_3         0x15
+#define EQ_0           0x16
+#define EQ_1           0x17
+#define EQ_2           0x18
+#define EQ_3           0x19
+#define EQ_4           0x1a
+#define EQ_5           0x1b
+#define FIL1_0         0x1c
+#define FIL1_1         0x1d
+#define FIL1_2         0x1e
+#define FIL1_3         0x1f
+#define PW_MGMT4       0x20
+#define MD_CTL5                0x21
+#define LO_MS          0x22
+#define HP_MS          0x23
+#define SPK_MS         0x24
+
+#define AK4642_CACHEREGNUM     0x25
+
+struct snd_soc_codec_device soc_codec_dev_ak4642;
+
+/* codec private data */
+struct ak4642_priv {
+       struct snd_soc_codec codec;
+       unsigned int sysclk;
+};
+
+static struct snd_soc_codec *ak4642_codec;
+
+/*
+ * ak4642 register cache
+ */
+static const u16 ak4642_reg[AK4642_CACHEREGNUM] = {
+       0x0000, 0x0000, 0x0001, 0x0000,
+       0x0002, 0x0000, 0x0000, 0x0000,
+       0x00e1, 0x00e1, 0x0018, 0x0000,
+       0x00e1, 0x0018, 0x0011, 0x0008,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0000,
+};
+
+/*
+ * read ak4642 register cache
+ */
+static inline unsigned int ak4642_read_reg_cache(struct snd_soc_codec *codec,
+       unsigned int reg)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg >= AK4642_CACHEREGNUM)
+               return -1;
+       return cache[reg];
+}
+
+/*
+ * write ak4642 register cache
+ */
+static inline void ak4642_write_reg_cache(struct snd_soc_codec *codec,
+       u16 reg, unsigned int value)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg >= AK4642_CACHEREGNUM)
+               return;
+
+       cache[reg] = value;
+}
+
+/*
+ * write to the AK4642 register space
+ */
+static int ak4642_write(struct snd_soc_codec *codec, unsigned int reg,
+       unsigned int value)
+{
+       u8 data[2];
+
+       /* data is
+        *   D15..D8 AK4642 register offset
+        *   D7...D0 register data
+        */
+       data[0] = reg & 0xff;
+       data[1] = value & 0xff;
+
+       if (codec->hw_write(codec->control_data, data, 2) == 2) {
+               ak4642_write_reg_cache(codec, reg, value);
+               return 0;
+       } else
+               return -EIO;
+}
+
+static int ak4642_sync(struct snd_soc_codec *codec)
+{
+       u16 *cache = codec->reg_cache;
+       int i, r = 0;
+
+       for (i = 0; i < AK4642_CACHEREGNUM; i++)
+               r |= ak4642_write(codec, i, cache[i]);
+
+       return r;
+};
+
+static int ak4642_dai_startup(struct snd_pcm_substream *substream,
+                             struct snd_soc_dai *dai)
+{
+       int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+       struct snd_soc_codec *codec = dai->codec;
+
+       if (is_play) {
+               /*
+                * start headphone output
+                *
+                * PLL, Master Mode
+                * Audio I/F Format :MSB justified (ADC & DAC)
+                * Sampling Frequency: 44.1kHz
+                * Digital Volume: −8dB
+                * Bass Boost Level : Middle
+                *
+                * This operation came from example code of
+                * "ASAHI KASEI AK4642" (japanese) manual p97.
+                *
+                * Example code use 0x39, 0x79 value for 0x01 address,
+                * But we need MCKO (0x02) bit now
+                */
+               ak4642_write(codec, 0x05, 0x27);
+               ak4642_write(codec, 0x0f, 0x09);
+               ak4642_write(codec, 0x0e, 0x19);
+               ak4642_write(codec, 0x09, 0x91);
+               ak4642_write(codec, 0x0c, 0x91);
+               ak4642_write(codec, 0x0a, 0x28);
+               ak4642_write(codec, 0x0d, 0x28);
+               ak4642_write(codec, 0x00, 0x64);
+               ak4642_write(codec, 0x01, 0x3b); /* + MCKO bit */
+               ak4642_write(codec, 0x01, 0x7b); /* + MCKO bit */
+       } else {
+               /*
+                * start stereo input
+                *
+                * PLL Master Mode
+                * Audio I/F Format:MSB justified (ADC & DAC)
+                * Sampling Frequency:44.1kHz
+                * Pre MIC AMP:+20dB
+                * MIC Power On
+                * ALC setting:Refer to Table 35
+                * ALC bit=“1”
+                *
+                * This operation came from example code of
+                * "ASAHI KASEI AK4642" (japanese) manual p94.
+                */
+               ak4642_write(codec, 0x05, 0x27);
+               ak4642_write(codec, 0x02, 0x05);
+               ak4642_write(codec, 0x06, 0x3c);
+               ak4642_write(codec, 0x08, 0xe1);
+               ak4642_write(codec, 0x0b, 0x00);
+               ak4642_write(codec, 0x07, 0x21);
+               ak4642_write(codec, 0x00, 0x41);
+               ak4642_write(codec, 0x10, 0x01);
+       }
+
+       return 0;
+}
+
+static void ak4642_dai_shutdown(struct snd_pcm_substream *substream,
+                              struct snd_soc_dai *dai)
+{
+       int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+       struct snd_soc_codec *codec = dai->codec;
+
+       if (is_play) {
+               /* stop headphone output */
+               ak4642_write(codec, 0x01, 0x3b);
+               ak4642_write(codec, 0x01, 0x0b);
+               ak4642_write(codec, 0x00, 0x40);
+               ak4642_write(codec, 0x0e, 0x11);
+               ak4642_write(codec, 0x0f, 0x08);
+       } else {
+               /* stop stereo input */
+               ak4642_write(codec, 0x00, 0x40);
+               ak4642_write(codec, 0x10, 0x00);
+               ak4642_write(codec, 0x07, 0x01);
+       }
+}
+
+static int ak4642_dai_set_sysclk(struct snd_soc_dai *codec_dai,
+       int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct ak4642_priv *ak4642 = codec->private_data;
+
+       ak4642->sysclk = freq;
+       return 0;
+}
+
+static struct snd_soc_dai_ops ak4642_dai_ops = {
+       .startup        = ak4642_dai_startup,
+       .shutdown       = ak4642_dai_shutdown,
+       .set_sysclk     = ak4642_dai_set_sysclk,
+};
+
+struct snd_soc_dai ak4642_dai = {
+       .name = "AK4642",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE },
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = SNDRV_PCM_RATE_8000_48000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE },
+       .ops = &ak4642_dai_ops,
+};
+EXPORT_SYMBOL_GPL(ak4642_dai);
+
+static int ak4642_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+
+       ak4642_sync(codec);
+       return 0;
+}
+
+/*
+ * initialise the AK4642 driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int ak4642_init(struct ak4642_priv *ak4642)
+{
+       struct snd_soc_codec *codec = &ak4642->codec;
+       int ret = 0;
+
+       if (ak4642_codec) {
+               dev_err(codec->dev, "Another ak4642 is registered\n");
+               return -EINVAL;
+       }
+
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       codec->private_data     = ak4642;
+       codec->name             = "AK4642";
+       codec->owner            = THIS_MODULE;
+       codec->read             = ak4642_read_reg_cache;
+       codec->write            = ak4642_write;
+       codec->dai              = &ak4642_dai;
+       codec->num_dai          = 1;
+       codec->hw_write         = (hw_write_t)i2c_master_send;
+       codec->reg_cache_size   = ARRAY_SIZE(ak4642_reg);
+       codec->reg_cache        = kmemdup(ak4642_reg,
+                                         sizeof(ak4642_reg), GFP_KERNEL);
+
+       if (!codec->reg_cache)
+               return -ENOMEM;
+
+       ak4642_dai.dev = codec->dev;
+       ak4642_codec = codec;
+
+       ret = snd_soc_register_codec(codec);
+       if (ret) {
+               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+               goto reg_cache_err;
+       }
+
+       ret = snd_soc_register_dai(&ak4642_dai);
+       if (ret) {
+               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
+               snd_soc_unregister_codec(codec);
+               goto reg_cache_err;
+       }
+
+       /*
+        * clock setting
+        *
+        * Audio I/F Format: MSB justified (ADC & DAC)
+        * BICK frequency at Master Mode: 64fs
+        * Input Master Clock Select at PLL Mode: 11.2896MHz
+        * MCKO: Enable
+        * Sampling Frequency: 44.1kHz
+        *
+        * This operation came from example code of
+        * "ASAHI KASEI AK4642" (japanese) manual p89.
+        *
+        * please fix-me
+        */
+       ak4642_write(codec, 0x01, 0x08);
+       ak4642_write(codec, 0x04, 0x4a);
+       ak4642_write(codec, 0x05, 0x27);
+       ak4642_write(codec, 0x00, 0x40);
+       ak4642_write(codec, 0x01, 0x0b);
+
+       return ret;
+
+reg_cache_err:
+       kfree(codec->reg_cache);
+       codec->reg_cache = NULL;
+
+       return ret;
+}
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static int ak4642_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
+{
+       struct ak4642_priv *ak4642;
+       struct snd_soc_codec *codec;
+       int ret;
+
+       ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL);
+       if (!ak4642)
+               return -ENOMEM;
+
+       codec = &ak4642->codec;
+       codec->dev = &i2c->dev;
+
+       i2c_set_clientdata(i2c, ak4642);
+       codec->control_data = i2c;
+
+       ret = ak4642_init(ak4642);
+       if (ret < 0)
+               printk(KERN_ERR "failed to initialise AK4642\n");
+
+       return ret;
+}
+
+static int ak4642_i2c_remove(struct i2c_client *client)
+{
+       struct ak4642_priv *ak4642 = i2c_get_clientdata(client);
+
+       snd_soc_unregister_dai(&ak4642_dai);
+       snd_soc_unregister_codec(&ak4642->codec);
+       kfree(ak4642->codec.reg_cache);
+       kfree(ak4642);
+       ak4642_codec = NULL;
+
+       return 0;
+}
+
+static const struct i2c_device_id ak4642_i2c_id[] = {
+       { "ak4642", 0 },
+       { "ak4643", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
+
+static struct i2c_driver ak4642_i2c_driver = {
+       .driver = {
+               .name = "AK4642 I2C Codec",
+               .owner = THIS_MODULE,
+       },
+       .probe          = ak4642_i2c_probe,
+       .remove         = ak4642_i2c_remove,
+       .id_table       = ak4642_i2c_id,
+};
+
+#endif
+
+static int ak4642_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       int ret;
+
+       if (!ak4642_codec) {
+               dev_err(&pdev->dev, "Codec device not registered\n");
+               return -ENODEV;
+       }
+
+       socdev->card->codec = ak4642_codec;
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               printk(KERN_ERR "ak4642: failed to create pcms\n");
+               goto pcm_err;
+       }
+
+       ret = snd_soc_init_card(socdev);
+       if (ret < 0) {
+               printk(KERN_ERR "ak4642: failed to register card\n");
+               goto card_err;
+       }
+
+       dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+pcm_err:
+       return ret;
+
+}
+
+/* power down chip */
+static int ak4642_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+
+       return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_ak4642 = {
+       .probe =        ak4642_probe,
+       .remove =       ak4642_remove,
+       .resume =       ak4642_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642);
+
+static int __init ak4642_modinit(void)
+{
+       int ret;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       ret = i2c_add_driver(&ak4642_i2c_driver);
+#endif
+       return ret;
+
+}
+module_init(ak4642_modinit);
+
+static void __exit ak4642_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&ak4642_i2c_driver);
+#endif
+
+}
+module_exit(ak4642_exit);
+
+MODULE_DESCRIPTION("Soc AK4642 driver");
+MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ak4642.h b/sound/soc/codecs/ak4642.h
new file mode 100644 (file)
index 0000000..e476833
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * ak4642.h  --  AK4642 Soc Audio driver
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on ak4535.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.
+ */
+
+#ifndef _AK4642_H
+#define _AK4642_H
+
+extern struct snd_soc_dai ak4642_dai;
+extern struct snd_soc_codec_device soc_codec_dev_ak4642;
+
+#endif
index a32b8226c8a43bc19a2f3852ef24b3e802238c05..ca1e24a8f12aaf4e54dc92a50ddbc2141ebd5161 100644 (file)
@@ -806,15 +806,30 @@ static int cs4270_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
 {
        struct cs4270_private *cs4270 = i2c_get_clientdata(client);
        struct snd_soc_codec *codec = &cs4270->codec;
-       int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL;
 
-       return snd_soc_write(codec, CS4270_PWRCTL, reg);
+       return snd_soc_suspend_device(codec->dev);
 }
 
 static int cs4270_i2c_resume(struct i2c_client *client)
 {
        struct cs4270_private *cs4270 = i2c_get_clientdata(client);
        struct snd_soc_codec *codec = &cs4270->codec;
+
+       return snd_soc_resume_device(codec->dev);
+}
+
+static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+       struct snd_soc_codec *codec = cs4270_codec;
+       int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL;
+
+       return snd_soc_write(codec, CS4270_PWRCTL, reg);
+}
+
+static int cs4270_soc_resume(struct platform_device *pdev)
+{
+       struct snd_soc_codec *codec = cs4270_codec;
+       struct i2c_client *i2c_client = codec->control_data;
        int reg;
 
        /* In case the device was put to hard reset during sleep, we need to
@@ -825,7 +840,7 @@ static int cs4270_i2c_resume(struct i2c_client *client)
        for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) {
                u8 val = snd_soc_read(codec, reg);
 
-               if (i2c_smbus_write_byte_data(client, reg, val)) {
+               if (i2c_smbus_write_byte_data(i2c_client, reg, val)) {
                        dev_err(codec->dev, "i2c write failed\n");
                        return -EIO;
                }
@@ -840,6 +855,8 @@ static int cs4270_i2c_resume(struct i2c_client *client)
 #else
 #define cs4270_i2c_suspend     NULL
 #define cs4270_i2c_resume      NULL
+#define cs4270_soc_suspend     NULL
+#define cs4270_soc_resume      NULL
 #endif /* CONFIG_PM */
 
 /*
@@ -868,7 +885,9 @@ static struct i2c_driver cs4270_i2c_driver = {
  */
 struct snd_soc_codec_device soc_codec_device_cs4270 = {
        .probe =        cs4270_probe,
-       .remove =       cs4270_remove
+       .remove =       cs4270_remove,
+       .suspend =      cs4270_soc_suspend,
+       .resume =       cs4270_soc_resume,
 };
 EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
 
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
new file mode 100644 (file)
index 0000000..38eac9c
--- /dev/null
@@ -0,0 +1,501 @@
+/*
+ * cx20442.c  --  CX20442 ALSA Soc Audio driver
+ *
+ * Copyright 2009 Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
+ *
+ * Initially based on sound/soc/codecs/wm8400.c
+ * Copyright 2008, 2009 Wolfson Microelectronics PLC.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/tty.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/soc-dapm.h>
+
+#include "cx20442.h"
+
+
+struct cx20442_priv {
+       struct snd_soc_codec codec;
+       u8 reg_cache[1];
+};
+
+#define CX20442_PM             0x0
+
+#define CX20442_TELIN          0
+#define CX20442_TELOUT         1
+#define CX20442_MIC            2
+#define CX20442_SPKOUT         3
+#define CX20442_AGC            4
+
+static const struct snd_soc_dapm_widget cx20442_dapm_widgets[] = {
+       SND_SOC_DAPM_OUTPUT("TELOUT"),
+       SND_SOC_DAPM_OUTPUT("SPKOUT"),
+       SND_SOC_DAPM_OUTPUT("AGCOUT"),
+
+       SND_SOC_DAPM_MIXER("SPKOUT Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       SND_SOC_DAPM_PGA("TELOUT Amp", CX20442_PM, CX20442_TELOUT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("SPKOUT Amp", CX20442_PM, CX20442_SPKOUT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("SPKOUT AGC", CX20442_PM, CX20442_AGC, 0, NULL, 0),
+
+       SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
+
+       SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+       SND_SOC_DAPM_MICBIAS("TELIN Bias", CX20442_PM, CX20442_TELIN, 0),
+       SND_SOC_DAPM_MICBIAS("MIC Bias", CX20442_PM, CX20442_MIC, 0),
+
+       SND_SOC_DAPM_PGA("MIC AGC", CX20442_PM, CX20442_AGC, 0, NULL, 0),
+
+       SND_SOC_DAPM_INPUT("TELIN"),
+       SND_SOC_DAPM_INPUT("MIC"),
+       SND_SOC_DAPM_INPUT("AGCIN"),
+};
+
+static const struct snd_soc_dapm_route cx20442_audio_map[] = {
+       {"TELOUT", NULL, "TELOUT Amp"},
+
+       {"SPKOUT", NULL, "SPKOUT Mixer"},
+       {"SPKOUT Mixer", NULL, "SPKOUT Amp"},
+
+       {"TELOUT Amp", NULL, "DAC"},
+       {"SPKOUT Amp", NULL, "DAC"},
+
+       {"SPKOUT Mixer", NULL, "SPKOUT AGC"},
+       {"SPKOUT AGC", NULL, "AGCIN"},
+
+       {"AGCOUT", NULL, "MIC AGC"},
+       {"MIC AGC", NULL, "MIC"},
+
+       {"MIC Bias", NULL, "MIC"},
+       {"Input Mixer", NULL, "MIC Bias"},
+
+       {"TELIN Bias", NULL, "TELIN"},
+       {"Input Mixer", NULL, "TELIN Bias"},
+
+       {"ADC", NULL, "Input Mixer"},
+};
+
+static int cx20442_add_widgets(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_new_controls(codec, cx20442_dapm_widgets,
+                                 ARRAY_SIZE(cx20442_dapm_widgets));
+
+       snd_soc_dapm_add_routes(codec, cx20442_audio_map,
+                               ARRAY_SIZE(cx20442_audio_map));
+
+       snd_soc_dapm_new_widgets(codec);
+       return 0;
+}
+
+static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec,
+                                                       unsigned int reg)
+{
+       u8 *reg_cache = codec->reg_cache;
+
+       if (reg >= codec->reg_cache_size)
+               return -EINVAL;
+
+       return reg_cache[reg];
+}
+
+enum v253_vls {
+       V253_VLS_NONE = 0,
+       V253_VLS_T,
+       V253_VLS_L,
+       V253_VLS_LT,
+       V253_VLS_S,
+       V253_VLS_ST,
+       V253_VLS_M,
+       V253_VLS_MST,
+       V253_VLS_S1,
+       V253_VLS_S1T,
+       V253_VLS_MS1T,
+       V253_VLS_M1,
+       V253_VLS_M1ST,
+       V253_VLS_M1S1T,
+       V253_VLS_H,
+       V253_VLS_HT,
+       V253_VLS_MS,
+       V253_VLS_MS1,
+       V253_VLS_M1S,
+       V253_VLS_M1S1,
+       V253_VLS_TEST,
+};
+
+static int cx20442_pm_to_v253_vls(u8 value)
+{
+       switch (value & ~(1 << CX20442_AGC)) {
+       case 0:
+               return V253_VLS_T;
+       case (1 << CX20442_SPKOUT):
+       case (1 << CX20442_MIC):
+       case (1 << CX20442_SPKOUT) | (1 << CX20442_MIC):
+               return V253_VLS_M1S1;
+       case (1 << CX20442_TELOUT):
+       case (1 << CX20442_TELIN):
+       case (1 << CX20442_TELOUT) | (1 << CX20442_TELIN):
+               return V253_VLS_L;
+       case (1 << CX20442_TELOUT) | (1 << CX20442_MIC):
+               return V253_VLS_NONE;
+       }
+       return -EINVAL;
+}
+static int cx20442_pm_to_v253_vsp(u8 value)
+{
+       switch (value & ~(1 << CX20442_AGC)) {
+       case (1 << CX20442_SPKOUT):
+       case (1 << CX20442_MIC):
+       case (1 << CX20442_SPKOUT) | (1 << CX20442_MIC):
+               return (bool)(value & (1 << CX20442_AGC));
+       }
+       return (value & (1 << CX20442_AGC)) ? -EINVAL : 0;
+}
+
+static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
+                                                       unsigned int value)
+{
+       u8 *reg_cache = codec->reg_cache;
+       int vls, vsp, old, len;
+       char buf[18];
+
+       if (reg >= codec->reg_cache_size)
+               return -EINVAL;
+
+       /* hw_write and control_data pointers required for talking to the modem
+        * are expected to be set by the line discipline initialization code */
+       if (!codec->hw_write || !codec->control_data)
+               return -EIO;
+
+       old = reg_cache[reg];
+       reg_cache[reg] = value;
+
+       vls = cx20442_pm_to_v253_vls(value);
+       if (vls < 0)
+               return vls;
+
+       vsp = cx20442_pm_to_v253_vsp(value);
+       if (vsp < 0)
+               return vsp;
+
+       if ((vls == V253_VLS_T) ||
+                       (vls == cx20442_pm_to_v253_vls(old))) {
+               if (vsp == cx20442_pm_to_v253_vsp(old))
+                       return 0;
+               len = snprintf(buf, ARRAY_SIZE(buf), "at+vsp=%d\r", vsp);
+       } else if (vsp == cx20442_pm_to_v253_vsp(old))
+               len = snprintf(buf, ARRAY_SIZE(buf), "at+vls=%d\r", vls);
+       else
+               len = snprintf(buf, ARRAY_SIZE(buf),
+                                       "at+vls=%d;+vsp=%d\r", vls, vsp);
+
+       if (unlikely(len > (ARRAY_SIZE(buf) - 1)))
+               return -ENOMEM;
+
+       dev_dbg(codec->dev, "%s: %s\n", __func__, buf);
+       if (codec->hw_write(codec->control_data, buf, len) != len)
+               return -EIO;
+
+       return 0;
+}
+
+
+/* Moved up here as line discipline referres it during initialization */
+static struct snd_soc_codec *cx20442_codec;
+
+
+/*
+ * Line discpline related code
+ *
+ * Any of the callback functions below can be used in two ways:
+ * 1) registerd by a machine driver as one of line discipline operations,
+ * 2) called from a machine's provided line discipline callback function
+ *    in case when extra machine specific code must be run as well.
+ */
+
+/* Modem init: echo off, digital speaker off, quiet off, voice mode */
+static const char *v253_init = "ate0m0q0+fclass=8\r";
+
+/* Line discipline .open() */
+static int v253_open(struct tty_struct *tty)
+{
+       struct snd_soc_codec *codec = cx20442_codec;
+       int ret, len = strlen(v253_init);
+
+       /* Doesn't make sense without write callback */
+       if (!tty->ops->write)
+               return -EINVAL;
+
+       /* Pass the codec structure address for use by other ldisc callbacks */
+       tty->disc_data = codec;
+
+       if (tty->ops->write(tty, v253_init, len) != len) {
+               ret = -EIO;
+               goto err;
+       }
+       /* Actual setup will be performed after the modem responds. */
+       return 0;
+err:
+       tty->disc_data = NULL;
+       return ret;
+}
+
+/* Line discipline .close() */
+static void v253_close(struct tty_struct *tty)
+{
+       struct snd_soc_codec *codec = tty->disc_data;
+
+       tty->disc_data = NULL;
+
+       if (!codec)
+               return;
+
+       /* Prevent the codec driver from further accessing the modem */
+       codec->hw_write = NULL;
+       codec->control_data = NULL;
+       codec->pop_time = 0;
+}
+
+/* Line discipline .hangup() */
+static int v253_hangup(struct tty_struct *tty)
+{
+       v253_close(tty);
+       return 0;
+}
+
+/* Line discipline .receive_buf() */
+static void v253_receive(struct tty_struct *tty,
+                               const unsigned char *cp, char *fp, int count)
+{
+       struct snd_soc_codec *codec = tty->disc_data;
+
+       if (!codec)
+               return;
+
+       if (!codec->control_data) {
+               /* First modem response, complete setup procedure */
+
+               /* Set up codec driver access to modem controls */
+               codec->control_data = tty;
+               codec->hw_write = (hw_write_t)tty->ops->write;
+               codec->pop_time = 1;
+       }
+}
+
+/* Line discipline .write_wakeup() */
+static void v253_wakeup(struct tty_struct *tty)
+{
+}
+
+struct tty_ldisc_ops v253_ops = {
+       .magic = TTY_LDISC_MAGIC,
+       .name = "cx20442",
+       .owner = THIS_MODULE,
+       .open = v253_open,
+       .close = v253_close,
+       .hangup = v253_hangup,
+       .receive_buf = v253_receive,
+       .write_wakeup = v253_wakeup,
+};
+EXPORT_SYMBOL_GPL(v253_ops);
+
+
+/*
+ * Codec DAI
+ */
+
+struct snd_soc_dai cx20442_dai = {
+       .name = "CX20442",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 1,
+               .channels_max = 1,
+               .rates = SNDRV_PCM_RATE_8000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 1,
+               .channels_max = 1,
+               .rates = SNDRV_PCM_RATE_8000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,
+       },
+};
+EXPORT_SYMBOL_GPL(cx20442_dai);
+
+static int cx20442_codec_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec;
+       int ret;
+
+       if (!cx20442_codec) {
+               dev_err(&pdev->dev, "cx20442 not yet discovered\n");
+               return -ENODEV;
+       }
+       codec = cx20442_codec;
+
+       socdev->card->codec = codec;
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to create pcms\n");
+               goto pcm_err;
+       }
+
+       cx20442_add_widgets(codec);
+
+       ret = snd_soc_init_card(socdev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to register card\n");
+               goto card_err;
+       }
+
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+pcm_err:
+       return ret;
+}
+
+/* power down chip */
+static int cx20442_codec_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+
+       return 0;
+}
+
+struct snd_soc_codec_device cx20442_codec_dev = {
+       .probe =        cx20442_codec_probe,
+       .remove =       cx20442_codec_remove,
+};
+EXPORT_SYMBOL_GPL(cx20442_codec_dev);
+
+static int cx20442_register(struct cx20442_priv *cx20442)
+{
+       struct snd_soc_codec *codec = &cx20442->codec;
+       int ret;
+
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       codec->name = "CX20442";
+       codec->owner = THIS_MODULE;
+       codec->private_data = cx20442;
+
+       codec->dai = &cx20442_dai;
+       codec->num_dai = 1;
+
+       codec->reg_cache = &cx20442->reg_cache;
+       codec->reg_cache_size = ARRAY_SIZE(cx20442->reg_cache);
+       codec->read = cx20442_read_reg_cache;
+       codec->write = cx20442_write;
+
+       codec->bias_level = SND_SOC_BIAS_OFF;
+
+       cx20442_dai.dev = codec->dev;
+
+       cx20442_codec = codec;
+
+       ret = snd_soc_register_codec(codec);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+               goto err;
+       }
+
+       ret = snd_soc_register_dai(&cx20442_dai);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
+               goto err_codec;
+       }
+
+       return 0;
+
+err_codec:
+       snd_soc_unregister_codec(codec);
+err:
+       cx20442_codec = NULL;
+       kfree(cx20442);
+       return ret;
+}
+
+static void cx20442_unregister(struct cx20442_priv *cx20442)
+{
+       snd_soc_unregister_dai(&cx20442_dai);
+       snd_soc_unregister_codec(&cx20442->codec);
+
+       cx20442_codec = NULL;
+       kfree(cx20442);
+}
+
+static int cx20442_platform_probe(struct platform_device *pdev)
+{
+       struct cx20442_priv *cx20442;
+       struct snd_soc_codec *codec;
+
+       cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL);
+       if (cx20442 == NULL)
+               return -ENOMEM;
+
+       codec = &cx20442->codec;
+
+       codec->control_data = NULL;
+       codec->hw_write = NULL;
+       codec->pop_time = 0;
+
+       codec->dev = &pdev->dev;
+       platform_set_drvdata(pdev, cx20442);
+
+       return cx20442_register(cx20442);
+}
+
+static int __exit cx20442_platform_remove(struct platform_device *pdev)
+{
+       struct cx20442_priv *cx20442 = platform_get_drvdata(pdev);
+
+       cx20442_unregister(cx20442);
+       return 0;
+}
+
+static struct platform_driver cx20442_platform_driver = {
+       .driver = {
+               .name = "cx20442",
+               .owner = THIS_MODULE,
+               },
+       .probe = cx20442_platform_probe,
+       .remove = __exit_p(cx20442_platform_remove),
+};
+
+static int __init cx20442_init(void)
+{
+       return platform_driver_register(&cx20442_platform_driver);
+}
+module_init(cx20442_init);
+
+static void __exit cx20442_exit(void)
+{
+       platform_driver_unregister(&cx20442_platform_driver);
+}
+module_exit(cx20442_exit);
+
+MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver");
+MODULE_AUTHOR("Janusz Krzysztofik");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:cx20442");
diff --git a/sound/soc/codecs/cx20442.h b/sound/soc/codecs/cx20442.h
new file mode 100644 (file)
index 0000000..688a5eb
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * cx20442.h  --  audio driver for CX20442
+ *
+ * Copyright 2009 Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
+ *
+ *  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 _CX20442_CODEC_H
+#define _CX20442_CODEC_H
+
+extern struct snd_soc_dai cx20442_dai;
+extern struct snd_soc_codec_device cx20442_codec_dev;
+extern struct tty_ldisc_ops v253_ops;
+
+#endif
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c
new file mode 100644 (file)
index 0000000..9e7e964
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * max9877.c  --  amp driver for max9877
+ *
+ * Copyright (C) 2009 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.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/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+#include "max9877.h"
+
+static struct i2c_client *i2c;
+
+static u8 max9877_regs[5] = { 0x40, 0x00, 0x00, 0x00, 0x49 };
+
+static void max9877_write_regs(void)
+{
+       unsigned int i;
+       u8 data[6];
+
+       data[0] = MAX9877_INPUT_MODE;
+       for (i = 0; i < ARRAY_SIZE(max9877_regs); i++)
+               data[i + 1] = max9877_regs[i];
+
+       if (i2c_master_send(i2c, data, 6) != 6)
+               dev_err(&i2c->dev, "i2c write failed\n");
+}
+
+static int max9877_get_reg(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_mixer_control *mc =
+               (struct soc_mixer_control *)kcontrol->private_value;
+       unsigned int reg = mc->reg;
+       unsigned int shift = mc->shift;
+       unsigned int mask = mc->max;
+       unsigned int invert = mc->invert;
+
+       ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask;
+
+       if (invert)
+               ucontrol->value.integer.value[0] =
+                       mask - ucontrol->value.integer.value[0];
+
+       return 0;
+}
+
+static int max9877_set_reg(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_mixer_control *mc =
+               (struct soc_mixer_control *)kcontrol->private_value;
+       unsigned int reg = mc->reg;
+       unsigned int shift = mc->shift;
+       unsigned int mask = mc->max;
+       unsigned int invert = mc->invert;
+       unsigned int val = (ucontrol->value.integer.value[0] & mask);
+
+       if (invert)
+               val = mask - val;
+
+       if (((max9877_regs[reg] >> shift) & mask) == val)
+               return 0;
+
+       max9877_regs[reg] &= ~(mask << shift);
+       max9877_regs[reg] |= val << shift;
+       max9877_write_regs();
+
+       return 1;
+}
+
+static int max9877_get_2reg(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_mixer_control *mc =
+               (struct soc_mixer_control *)kcontrol->private_value;
+       unsigned int reg = mc->reg;
+       unsigned int reg2 = mc->rreg;
+       unsigned int shift = mc->shift;
+       unsigned int mask = mc->max;
+
+       ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask;
+       ucontrol->value.integer.value[1] = (max9877_regs[reg2] >> shift) & mask;
+
+       return 0;
+}
+
+static int max9877_set_2reg(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_mixer_control *mc =
+               (struct soc_mixer_control *)kcontrol->private_value;
+       unsigned int reg = mc->reg;
+       unsigned int reg2 = mc->rreg;
+       unsigned int shift = mc->shift;
+       unsigned int mask = mc->max;
+       unsigned int val = (ucontrol->value.integer.value[0] & mask);
+       unsigned int val2 = (ucontrol->value.integer.value[1] & mask);
+       unsigned int change = 1;
+
+       if (((max9877_regs[reg] >> shift) & mask) == val)
+               change = 0;
+
+       if (((max9877_regs[reg2] >> shift) & mask) == val2)
+               change = 0;
+
+       if (change) {
+               max9877_regs[reg] &= ~(mask << shift);
+               max9877_regs[reg] |= val << shift;
+               max9877_regs[reg2] &= ~(mask << shift);
+               max9877_regs[reg2] |= val2 << shift;
+               max9877_write_regs();
+       }
+
+       return change;
+}
+
+static int max9877_get_out_mode(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       u8 value = max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK;
+
+       if (value)
+               value -= 1;
+
+       ucontrol->value.integer.value[0] = value;
+       return 0;
+}
+
+static int max9877_set_out_mode(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       u8 value = ucontrol->value.integer.value[0];
+
+       value += 1;
+
+       if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK) == value)
+               return 0;
+
+       max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OUTMODE_MASK;
+       max9877_regs[MAX9877_OUTPUT_MODE] |= value;
+       max9877_write_regs();
+       return 1;
+}
+
+static int max9877_get_osc_mode(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       u8 value = (max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK);
+
+       value = value >> MAX9877_OSC_OFFSET;
+
+       ucontrol->value.integer.value[0] = value;
+       return 0;
+}
+
+static int max9877_set_osc_mode(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       u8 value = ucontrol->value.integer.value[0];
+
+       value = value << MAX9877_OSC_OFFSET;
+       if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK) == value)
+               return 0;
+
+       max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OSC_MASK;
+       max9877_regs[MAX9877_OUTPUT_MODE] |= value;
+       max9877_write_regs();
+       return 1;
+}
+
+static const unsigned int max9877_pgain_tlv[] = {
+       TLV_DB_RANGE_HEAD(2),
+       0, 1, TLV_DB_SCALE_ITEM(0, 900, 0),
+       2, 2, TLV_DB_SCALE_ITEM(2000, 0, 0),
+};
+
+static const unsigned int max9877_output_tlv[] = {
+       TLV_DB_RANGE_HEAD(4),
+       0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1),
+       8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0),
+       16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0),
+       24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0),
+};
+
+static const char *max9877_out_mode[] = {
+       "INA -> SPK",
+       "INA -> HP",
+       "INA -> SPK and HP",
+       "INB -> SPK",
+       "INB -> HP",
+       "INB -> SPK and HP",
+       "INA + INB -> SPK",
+       "INA + INB -> HP",
+       "INA + INB -> SPK and HP",
+};
+
+static const char *max9877_osc_mode[] = {
+       "1176KHz",
+       "1100KHz",
+       "700KHz",
+};
+
+static const struct soc_enum max9877_enum[] = {
+       SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_out_mode), max9877_out_mode),
+       SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode),
+};
+
+static const struct snd_kcontrol_new max9877_controls[] = {
+       SOC_SINGLE_EXT_TLV("MAX9877 PGAINA Playback Volume",
+                       MAX9877_INPUT_MODE, 0, 2, 0,
+                       max9877_get_reg, max9877_set_reg, max9877_pgain_tlv),
+       SOC_SINGLE_EXT_TLV("MAX9877 PGAINB Playback Volume",
+                       MAX9877_INPUT_MODE, 2, 2, 0,
+                       max9877_get_reg, max9877_set_reg, max9877_pgain_tlv),
+       SOC_SINGLE_EXT_TLV("MAX9877 Amp Speaker Playback Volume",
+                       MAX9877_SPK_VOLUME, 0, 31, 0,
+                       max9877_get_reg, max9877_set_reg, max9877_output_tlv),
+       SOC_DOUBLE_R_EXT_TLV("MAX9877 Amp HP Playback Volume",
+                       MAX9877_HPL_VOLUME, MAX9877_HPR_VOLUME, 0, 31, 0,
+                       max9877_get_2reg, max9877_set_2reg, max9877_output_tlv),
+       SOC_SINGLE_EXT("MAX9877 INB Stereo Switch",
+                       MAX9877_INPUT_MODE, 4, 1, 1,
+                       max9877_get_reg, max9877_set_reg),
+       SOC_SINGLE_EXT("MAX9877 INA Stereo Switch",
+                       MAX9877_INPUT_MODE, 5, 1, 1,
+                       max9877_get_reg, max9877_set_reg),
+       SOC_SINGLE_EXT("MAX9877 Zero-crossing detection Switch",
+                       MAX9877_INPUT_MODE, 6, 1, 0,
+                       max9877_get_reg, max9877_set_reg),
+       SOC_SINGLE_EXT("MAX9877 Bypass Mode Switch",
+                       MAX9877_OUTPUT_MODE, 6, 1, 0,
+                       max9877_get_reg, max9877_set_reg),
+       SOC_SINGLE_EXT("MAX9877 Shutdown Mode Switch",
+                       MAX9877_OUTPUT_MODE, 7, 1, 1,
+                       max9877_get_reg, max9877_set_reg),
+       SOC_ENUM_EXT("MAX9877 Output Mode", max9877_enum[0],
+                       max9877_get_out_mode, max9877_set_out_mode),
+       SOC_ENUM_EXT("MAX9877 Oscillator Mode", max9877_enum[1],
+                       max9877_get_osc_mode, max9877_set_osc_mode),
+};
+
+/* This function is called from ASoC machine driver */
+int max9877_add_controls(struct snd_soc_codec *codec)
+{
+       return snd_soc_add_controls(codec, max9877_controls,
+                       ARRAY_SIZE(max9877_controls));
+}
+EXPORT_SYMBOL_GPL(max9877_add_controls);
+
+static int __devinit max9877_i2c_probe(struct i2c_client *client,
+               const struct i2c_device_id *id)
+{
+       i2c = client;
+
+       max9877_write_regs();
+
+       return 0;
+}
+
+static __devexit int max9877_i2c_remove(struct i2c_client *client)
+{
+       i2c = NULL;
+
+       return 0;
+}
+
+static const struct i2c_device_id max9877_i2c_id[] = {
+       { "max9877", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, max9877_i2c_id);
+
+static struct i2c_driver max9877_i2c_driver = {
+       .driver = {
+               .name = "max9877",
+               .owner = THIS_MODULE,
+       },
+       .probe = max9877_i2c_probe,
+       .remove = __devexit_p(max9877_i2c_remove),
+       .id_table = max9877_i2c_id,
+};
+
+static int __init max9877_init(void)
+{
+       return i2c_add_driver(&max9877_i2c_driver);
+}
+module_init(max9877_init);
+
+static void __exit max9877_exit(void)
+{
+       i2c_del_driver(&max9877_i2c_driver);
+}
+module_exit(max9877_exit);
+
+MODULE_DESCRIPTION("ASoC MAX9877 amp driver");
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max9877.h b/sound/soc/codecs/max9877.h
new file mode 100644 (file)
index 0000000..6da7229
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * max9877.h  --  amp driver for max9877
+ *
+ * Copyright (C) 2009 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.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.
+ *
+ */
+
+#ifndef _MAX9877_H
+#define _MAX9877_H
+
+#define MAX9877_INPUT_MODE             0x00
+#define MAX9877_SPK_VOLUME             0x01
+#define MAX9877_HPL_VOLUME             0x02
+#define MAX9877_HPR_VOLUME             0x03
+#define MAX9877_OUTPUT_MODE            0x04
+
+/* MAX9877_INPUT_MODE */
+#define MAX9877_INB                    (1 << 4)
+#define MAX9877_INA                    (1 << 5)
+#define MAX9877_ZCD                    (1 << 6)
+
+/* MAX9877_OUTPUT_MODE */
+#define MAX9877_OUTMODE_MASK           (15 << 0)
+#define MAX9877_OSC_MASK               (3 << 4)
+#define MAX9877_OSC_OFFSET             4
+#define MAX9877_BYPASS                 (1 << 6)
+#define MAX9877_SHDN                   (1 << 7)
+
+extern int max9877_add_controls(struct snd_soc_codec *codec);
+
+#endif
index 218b33adad907679d04c4fa7ad71a864a5abc480..a63191141052ffa284537fe14d2bc90fd093679a 100644 (file)
@@ -21,6 +21,8 @@
 
 #include "spdif_transciever.h"
 
+MODULE_LICENSE("GPL");
+
 #define STUB_RATES     SNDRV_PCM_RATE_8000_96000
 #define STUB_FORMATS   SNDRV_PCM_FMTBIT_S16_LE
 
@@ -34,6 +36,7 @@ struct snd_soc_dai dit_stub_dai = {
                .formats        = STUB_FORMATS,
        },
 };
+EXPORT_SYMBOL_GPL(dit_stub_dai);
 
 static int spdif_dit_probe(struct platform_device *pdev)
 {
index 8ad4b7b3e3ba3a81fe86142dc2ff2281519f9756..befc6488c39a54f27cb9d9b27e7a4ca1b7451bd7 100644 (file)
@@ -149,7 +149,7 @@ static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg,
                stac9766_ac97_write(codec, AC97_INT_PAGING, 1);
                return 0;
        }
-       if (reg / 2 > ARRAY_SIZE(stac9766_reg))
+       if (reg / 2 >= ARRAY_SIZE(stac9766_reg))
                return -EIO;
 
        soc_ac97_ops.write(codec->ac97, reg, val);
@@ -168,7 +168,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec,
                stac9766_ac97_write(codec, AC97_INT_PAGING, 1);
                return val;
        }
-       if (reg / 2 > ARRAY_SIZE(stac9766_reg))
+       if (reg / 2 >= ARRAY_SIZE(stac9766_reg))
                return -EIO;
 
        if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
index ab099f482487b7e642d0f3d1372e6001673b3d27..3395cf945d565b694dc1849a32027b48802c1e99 100644 (file)
@@ -53,6 +53,7 @@
 
 /* codec private data */
 struct aic3x_priv {
+       struct snd_soc_codec codec;
        unsigned int sysclk;
        int master;
 };
@@ -145,8 +146,8 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
                      u8 *value)
 {
        *value = reg & 0xff;
-       if (codec->hw_read(codec->control_data, value, 1) != 1)
-               return -EIO;
+
+       value[0] = i2c_smbus_read_byte_data(codec->control_data, value[0]);
 
        aic3x_write_reg_cache(codec, reg, *value);
        return 0;
@@ -767,6 +768,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
        int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
        u8 data, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
        u16 pll_d = 1;
+       u8 reg;
 
        /* select data word length */
        data =
@@ -801,8 +803,16 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
                pll_q &= 0xf;
                aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
                aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
-       } else
+               /* disable PLL if it is bypassed */
+               reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
+               aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE);
+
+       } else {
                aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
+               /* enable PLL when it is used */
+               reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG);
+               aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE);
+       }
 
        /* Route Left DAC to left channel input and
         * right DAC to right channel input */
@@ -1147,11 +1157,13 @@ static int aic3x_resume(struct platform_device *pdev)
  * initialise the AIC3X driver
  * register the mixer and dsp interfaces with the kernel
  */
-static int aic3x_init(struct snd_soc_device *socdev)
+static int aic3x_init(struct snd_soc_codec *codec)
 {
-       struct snd_soc_codec *codec = socdev->card->codec;
-       struct aic3x_setup_data *setup = socdev->codec_data;
-       int reg, ret = 0;
+       int reg;
+
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
 
        codec->name = "tlv320aic3x";
        codec->owner = THIS_MODULE;
@@ -1168,13 +1180,6 @@ static int aic3x_init(struct snd_soc_device *socdev)
        aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT);
        aic3x_write(codec, AIC3X_RESET, SOFT_RESET);
 
-       /* register pcms */
-       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
-       if (ret < 0) {
-               printk(KERN_ERR "aic3x: failed to create pcms\n");
-               goto pcm_err;
-       }
-
        /* DAC default volume and mute */
        aic3x_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON);
        aic3x_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON);
@@ -1241,30 +1246,51 @@ static int aic3x_init(struct snd_soc_device *socdev)
        /* off, with power on */
        aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       /* setup GPIO functions */
-       aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4);
-       aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4);
+       return 0;
+}
+
+static struct snd_soc_codec *aic3x_codec;
 
-       snd_soc_add_controls(codec, aic3x_snd_controls,
-                               ARRAY_SIZE(aic3x_snd_controls));
-       aic3x_add_widgets(codec);
-       ret = snd_soc_init_card(socdev);
+static int aic3x_register(struct snd_soc_codec *codec)
+{
+       int ret;
+
+       ret = aic3x_init(codec);
        if (ret < 0) {
-               printk(KERN_ERR "aic3x: failed to register card\n");
-               goto card_err;
+               dev_err(codec->dev, "Failed to initialise device\n");
+               return ret;
        }
 
-       return ret;
+       aic3x_codec = codec;
 
-card_err:
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
-pcm_err:
-       kfree(codec->reg_cache);
-       return ret;
+       ret = snd_soc_register_codec(codec);
+       if (ret) {
+               dev_err(codec->dev, "Failed to register codec\n");
+               return ret;
+       }
+
+       ret = snd_soc_register_dai(&aic3x_dai);
+       if (ret) {
+               dev_err(codec->dev, "Failed to register dai\n");
+               snd_soc_unregister_codec(codec);
+               return ret;
+       }
+
+       return 0;
 }
 
-static struct snd_soc_device *aic3x_socdev;
+static int aic3x_unregister(struct aic3x_priv *aic3x)
+{
+       aic3x_set_bias_level(&aic3x->codec, SND_SOC_BIAS_OFF);
+
+       snd_soc_unregister_dai(&aic3x_dai);
+       snd_soc_unregister_codec(&aic3x->codec);
+
+       kfree(aic3x);
+       aic3x_codec = NULL;
+
+       return 0;
+}
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 /*
@@ -1279,28 +1305,36 @@ static struct snd_soc_device *aic3x_socdev;
 static int aic3x_i2c_probe(struct i2c_client *i2c,
                           const struct i2c_device_id *id)
 {
-       struct snd_soc_device *socdev = aic3x_socdev;
-       struct snd_soc_codec *codec = socdev->card->codec;
-       int ret;
+       struct snd_soc_codec *codec;
+       struct aic3x_priv *aic3x;
+
+       aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
+       if (aic3x == NULL) {
+               dev_err(&i2c->dev, "failed to create private data\n");
+               return -ENOMEM;
+       }
 
-       i2c_set_clientdata(i2c, codec);
+       codec = &aic3x->codec;
+       codec->dev = &i2c->dev;
+       codec->private_data = aic3x;
        codec->control_data = i2c;
+       codec->hw_write = (hw_write_t) i2c_master_send;
 
-       ret = aic3x_init(socdev);
-       if (ret < 0)
-               printk(KERN_ERR "aic3x: failed to initialise AIC3X\n");
-       return ret;
+       i2c_set_clientdata(i2c, aic3x);
+
+       return aic3x_register(codec);
 }
 
 static int aic3x_i2c_remove(struct i2c_client *client)
 {
-       struct snd_soc_codec *codec = i2c_get_clientdata(client);
-       kfree(codec->reg_cache);
-       return 0;
+       struct aic3x_priv *aic3x = i2c_get_clientdata(client);
+
+       return aic3x_unregister(aic3x);
 }
 
 static const struct i2c_device_id aic3x_i2c_id[] = {
        { "tlv320aic3x", 0 },
+       { "tlv320aic33", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
@@ -1311,56 +1345,28 @@ static struct i2c_driver aic3x_i2c_driver = {
                .name = "aic3x I2C Codec",
                .owner = THIS_MODULE,
        },
-       .probe = aic3x_i2c_probe,
+       .probe  = aic3x_i2c_probe,
        .remove = aic3x_i2c_remove,
        .id_table = aic3x_i2c_id,
 };
 
-static int aic3x_i2c_read(struct i2c_client *client, u8 *value, int len)
-{
-       value[0] = i2c_smbus_read_byte_data(client, value[0]);
-       return (len == 1);
-}
-
-static int aic3x_add_i2c_device(struct platform_device *pdev,
-                                const struct aic3x_setup_data *setup)
+static inline void aic3x_i2c_init(void)
 {
-       struct i2c_board_info info;
-       struct i2c_adapter *adapter;
-       struct i2c_client *client;
        int ret;
 
        ret = i2c_add_driver(&aic3x_i2c_driver);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "can't add i2c driver\n");
-               return ret;
-       }
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       info.addr = setup->i2c_address;
-       strlcpy(info.type, "tlv320aic3x", I2C_NAME_SIZE);
-
-       adapter = i2c_get_adapter(setup->i2c_bus);
-       if (!adapter) {
-               dev_err(&pdev->dev, "can't get i2c adapter %d\n",
-                       setup->i2c_bus);
-               goto err_driver;
-       }
-
-       client = i2c_new_device(adapter, &info);
-       i2c_put_adapter(adapter);
-       if (!client) {
-               dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
-                       (unsigned int)info.addr);
-               goto err_driver;
-       }
-
-       return 0;
+       if (ret)
+               printk(KERN_ERR "%s: error regsitering i2c driver, %d\n",
+                      __func__, ret);
+}
 
-err_driver:
+static inline void aic3x_i2c_exit(void)
+{
        i2c_del_driver(&aic3x_i2c_driver);
-       return -ENODEV;
 }
+#else
+static inline void aic3x_i2c_init(void) { }
+static inline void aic3x_i2c_exit(void) { }
 #endif
 
 static int aic3x_probe(struct platform_device *pdev)
@@ -1368,43 +1374,51 @@ static int aic3x_probe(struct platform_device *pdev)
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct aic3x_setup_data *setup;
        struct snd_soc_codec *codec;
-       struct aic3x_priv *aic3x;
        int ret = 0;
 
-       printk(KERN_INFO "AIC3X Audio Codec %s\n", AIC3X_VERSION);
+       codec = aic3x_codec;
+       if (!codec) {
+               dev_err(&pdev->dev, "Codec not registered\n");
+               return -ENODEV;
+       }
 
+       socdev->card->codec = codec;
        setup = socdev->codec_data;
-       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (codec == NULL)
-               return -ENOMEM;
 
-       aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
-       if (aic3x == NULL) {
-               kfree(codec);
-               return -ENOMEM;
+       if (setup) {
+               /* setup GPIO functions */
+               aic3x_write(codec, AIC3X_GPIO1_REG,
+                           (setup->gpio_func[0] & 0xf) << 4);
+               aic3x_write(codec, AIC3X_GPIO2_REG,
+                           (setup->gpio_func[1] & 0xf) << 4);
        }
 
-       codec->private_data = aic3x;
-       socdev->card->codec = codec;
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
-
-       aic3x_socdev = socdev;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       if (setup->i2c_address) {
-               codec->hw_write = (hw_write_t) i2c_master_send;
-               codec->hw_read = (hw_read_t) aic3x_i2c_read;
-               ret = aic3x_add_i2c_device(pdev, setup);
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               printk(KERN_ERR "aic3x: failed to create pcms\n");
+               goto pcm_err;
        }
-#else
-       /* Add other interfaces here */
-#endif
 
-       if (ret != 0) {
-               kfree(codec->private_data);
-               kfree(codec);
+       snd_soc_add_controls(codec, aic3x_snd_controls,
+                            ARRAY_SIZE(aic3x_snd_controls));
+
+       aic3x_add_widgets(codec);
+
+       ret = snd_soc_init_card(socdev);
+       if (ret < 0) {
+               printk(KERN_ERR "aic3x: failed to register card\n");
+               goto card_err;
        }
+
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+
+pcm_err:
+       kfree(codec->reg_cache);
        return ret;
 }
 
@@ -1419,12 +1433,8 @@ static int aic3x_remove(struct platform_device *pdev)
 
        snd_soc_free_pcms(socdev);
        snd_soc_dapm_free(socdev);
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       i2c_unregister_device(codec->control_data);
-       i2c_del_driver(&aic3x_i2c_driver);
-#endif
-       kfree(codec->private_data);
-       kfree(codec);
+
+       kfree(codec->reg_cache);
 
        return 0;
 }
@@ -1439,13 +1449,15 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x);
 
 static int __init aic3x_modinit(void)
 {
-       return snd_soc_register_dai(&aic3x_dai);
+       aic3x_i2c_init();
+
+       return 0;
 }
 module_init(aic3x_modinit);
 
 static void __exit aic3x_exit(void)
 {
-       snd_soc_unregister_dai(&aic3x_dai);
+       aic3x_i2c_exit();
 }
 module_exit(aic3x_exit);
 
index ac827e578c4d0548a7d64b7da037ecc7313d55d6..9af1c886213c0f1d432014ea65a259dfea4ecfd8 100644 (file)
@@ -282,8 +282,6 @@ int aic3x_headset_detected(struct snd_soc_codec *codec);
 int aic3x_button_pressed(struct snd_soc_codec *codec);
 
 struct aic3x_setup_data {
-       int i2c_bus;
-       unsigned short i2c_address;
        unsigned int gpio_func[2];
 };
 
index 4dbb853eef5ad056fec1e6cca89f0becbe579251..4df7c6c61c76da631cd213a25a927e35e7710bc2 100644 (file)
@@ -225,55 +225,11 @@ static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute)
                return;
 
        if (mute) {
-               /* Bypass the reg_cache and mute the volumes
-                * Headset mute is done in it's own event handler
-                * Things to mute:  Earpiece, PreDrivL/R, CarkitL/R
-                */
-               reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL);
-               twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-                                       reg_val & (~TWL4030_EAR_GAIN),
-                                       TWL4030_REG_EAR_CTL);
-
-               reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL);
-               twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-                                       reg_val & (~TWL4030_PREDL_GAIN),
-                                       TWL4030_REG_PREDL_CTL);
-               reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL);
-               twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-                                       reg_val & (~TWL4030_PREDR_GAIN),
-                                       TWL4030_REG_PREDL_CTL);
-
-               reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL);
-               twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-                                       reg_val & (~TWL4030_PRECKL_GAIN),
-                                       TWL4030_REG_PRECKL_CTL);
-               reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL);
-               twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,
-                                       reg_val & (~TWL4030_PRECKR_GAIN),
-                                       TWL4030_REG_PRECKR_CTL);
-
                /* Disable PLL */
                reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL);
                reg_val &= ~TWL4030_APLL_EN;
                twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val);
        } else {
-               /* Restore the volumes
-                * Headset mute is done in it's own event handler
-                * Things to restore:  Earpiece, PreDrivL/R, CarkitL/R
-                */
-               twl4030_write(codec, TWL4030_REG_EAR_CTL,
-                       twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL));
-
-               twl4030_write(codec, TWL4030_REG_PREDL_CTL,
-                       twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL));
-               twl4030_write(codec, TWL4030_REG_PREDR_CTL,
-                       twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL));
-
-               twl4030_write(codec, TWL4030_REG_PRECKL_CTL,
-                       twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL));
-               twl4030_write(codec, TWL4030_REG_PRECKR_CTL,
-                       twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL));
-
                /* Enable PLL */
                reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL);
                reg_val |= TWL4030_APLL_EN;
@@ -443,16 +399,20 @@ SOC_DAPM_ENUM("Route", twl4030_vibrapath_enum);
 
 /* Left analog microphone selection */
 static const struct snd_kcontrol_new twl4030_dapm_analoglmic_controls[] = {
-       SOC_DAPM_SINGLE("Main mic", TWL4030_REG_ANAMICL, 0, 1, 0),
-       SOC_DAPM_SINGLE("Headset mic", TWL4030_REG_ANAMICL, 1, 1, 0),
-       SOC_DAPM_SINGLE("AUXL", TWL4030_REG_ANAMICL, 2, 1, 0),
-       SOC_DAPM_SINGLE("Carkit mic", TWL4030_REG_ANAMICL, 3, 1, 0),
+       SOC_DAPM_SINGLE("Main Mic Capture Switch",
+                       TWL4030_REG_ANAMICL, 0, 1, 0),
+       SOC_DAPM_SINGLE("Headset Mic Capture Switch",
+                       TWL4030_REG_ANAMICL, 1, 1, 0),
+       SOC_DAPM_SINGLE("AUXL Capture Switch",
+                       TWL4030_REG_ANAMICL, 2, 1, 0),
+       SOC_DAPM_SINGLE("Carkit Mic Capture Switch",
+                       TWL4030_REG_ANAMICL, 3, 1, 0),
 };
 
 /* Right analog microphone selection */
 static const struct snd_kcontrol_new twl4030_dapm_analogrmic_controls[] = {
-       SOC_DAPM_SINGLE("Sub mic", TWL4030_REG_ANAMICR, 0, 1, 0),
-       SOC_DAPM_SINGLE("AUXR", TWL4030_REG_ANAMICR, 2, 1, 0),
+       SOC_DAPM_SINGLE("Sub Mic Capture Switch", TWL4030_REG_ANAMICR, 0, 1, 0),
+       SOC_DAPM_SINGLE("AUXR Capture Switch", TWL4030_REG_ANAMICR, 2, 1, 0),
 };
 
 /* TX1 L/R Analog/Digital microphone selection */
@@ -560,6 +520,41 @@ static int micpath_event(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
+/*
+ * Output PGA builder:
+ * Handle the muting and unmuting of the given output (turning off the
+ * amplifier associated with the output pin)
+ * On mute bypass the reg_cache and mute the volume
+ * On unmute: restore the register content
+ * Outputs handled in this way:  Earpiece, PreDrivL/R, CarkitL/R
+ */
+#define TWL4030_OUTPUT_PGA(pin_name, reg, mask)                                \
+static int pin_name##pga_event(struct snd_soc_dapm_widget *w,          \
+               struct snd_kcontrol *kcontrol, int event)               \
+{                                                                      \
+       u8 reg_val;                                                     \
+                                                                       \
+       switch (event) {                                                \
+       case SND_SOC_DAPM_POST_PMU:                                     \
+               twl4030_write(w->codec, reg,                            \
+                       twl4030_read_reg_cache(w->codec, reg));         \
+               break;                                                  \
+       case SND_SOC_DAPM_POST_PMD:                                     \
+               reg_val = twl4030_read_reg_cache(w->codec, reg);        \
+               twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE,        \
+                                       reg_val & (~mask),              \
+                                       reg);                           \
+               break;                                                  \
+       }                                                               \
+       return 0;                                                       \
+}
+
+TWL4030_OUTPUT_PGA(earpiece, TWL4030_REG_EAR_CTL, TWL4030_EAR_GAIN);
+TWL4030_OUTPUT_PGA(predrivel, TWL4030_REG_PREDL_CTL, TWL4030_PREDL_GAIN);
+TWL4030_OUTPUT_PGA(predriver, TWL4030_REG_PREDR_CTL, TWL4030_PREDR_GAIN);
+TWL4030_OUTPUT_PGA(carkitl, TWL4030_REG_PRECKL_CTL, TWL4030_PRECKL_GAIN);
+TWL4030_OUTPUT_PGA(carkitr, TWL4030_REG_PRECKR_CTL, TWL4030_PRECKR_GAIN);
+
 static void handsfree_ramp(struct snd_soc_codec *codec, int reg, int ramp)
 {
        unsigned char hs_ctl;
@@ -620,6 +615,9 @@ static int handsfreerpga_event(struct snd_soc_dapm_widget *w,
 
 static void headset_ramp(struct snd_soc_codec *codec, int ramp)
 {
+       struct snd_soc_device *socdev = codec->socdev;
+       struct twl4030_setup_data *setup = socdev->codec_data;
+
        unsigned char hs_gain, hs_pop;
        struct twl4030_priv *twl4030 = codec->private_data;
        /* Base values for ramp delay calculation: 2^19 - 2^26 */
@@ -629,6 +627,17 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
        hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET);
        hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
 
+       /* Enable external mute control, this dramatically reduces
+        * the pop-noise */
+       if (setup && setup->hs_extmute) {
+               if (setup->set_hs_extmute) {
+                       setup->set_hs_extmute(1);
+               } else {
+                       hs_pop |= TWL4030_EXTMUTE;
+                       twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
+               }
+       }
+
        if (ramp) {
                /* Headset ramp-up according to the TRM */
                hs_pop |= TWL4030_VMID_EN;
@@ -636,6 +645,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
                twl4030_write(codec, TWL4030_REG_HS_GAIN_SET, hs_gain);
                hs_pop |= TWL4030_RAMP_EN;
                twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
+               /* Wait ramp delay time + 1, so the VMID can settle */
+               mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] /
+                       twl4030->sysclk) + 1);
        } else {
                /* Headset ramp-down _not_ according to
                 * the TRM, but in a way that it is working */
@@ -652,6 +664,16 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
                hs_pop &= ~TWL4030_VMID_EN;
                twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
        }
+
+       /* Disable external mute */
+       if (setup && setup->hs_extmute) {
+               if (setup->set_hs_extmute) {
+                       setup->set_hs_extmute(0);
+               } else {
+                       hs_pop &= ~TWL4030_EXTMUTE;
+                       twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
+               }
+       }
 }
 
 static int headsetlpga_event(struct snd_soc_dapm_widget *w,
@@ -712,7 +734,19 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
 
        reg = twl4030_read_reg_cache(w->codec, m->reg);
 
-       if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) {
+       /*
+        * bypass_state[0:3] - analog HiFi bypass
+        * bypass_state[4]   - analog voice bypass
+        * bypass_state[5]   - digital voice bypass
+        * bypass_state[6:7] - digital HiFi bypass
+        */
+       if (m->reg == TWL4030_REG_VSTPGA) {
+               /* Voice digital bypass */
+               if (reg)
+                       twl4030->bypass_state |= (1 << 5);
+               else
+                       twl4030->bypass_state &= ~(1 << 5);
+       } else if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) {
                /* Analog bypass */
                if (reg & (1 << m->shift))
                        twl4030->bypass_state |=
@@ -726,12 +760,6 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
                        twl4030->bypass_state |= (1 << 4);
                else
                        twl4030->bypass_state &= ~(1 << 4);
-       } else if (m->reg == TWL4030_REG_VSTPGA) {
-               /* Voice digital bypass */
-               if (reg)
-                       twl4030->bypass_state |= (1 << 5);
-               else
-                       twl4030->bypass_state &= ~(1 << 5);
        } else {
                /* Digital bypass */
                if (reg & (0x7 << m->shift))
@@ -924,7 +952,7 @@ static const struct soc_enum twl4030_op_modes_enum =
                        ARRAY_SIZE(twl4030_op_modes_texts),
                        twl4030_op_modes_texts);
 
-int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
+static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
@@ -1005,6 +1033,16 @@ static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0);
  */
 static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0);
 
+/* AVADC clock priority */
+static const char *twl4030_avadc_clk_priority_texts[] = {
+       "Voice high priority", "HiFi high priority"
+};
+
+static const struct soc_enum twl4030_avadc_clk_priority_enum =
+       SOC_ENUM_SINGLE(TWL4030_REG_AVADC_CTL, 2,
+                       ARRAY_SIZE(twl4030_avadc_clk_priority_texts),
+                       twl4030_avadc_clk_priority_texts);
+
 static const char *twl4030_rampdelay_texts[] = {
        "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms",
        "437/323/218 ms", "874/645/437 ms", "1748/1291/874 ms",
@@ -1106,6 +1144,8 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
        SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN,
                0, 3, 5, 0, input_gain_tlv),
 
+       SOC_ENUM("AVADC Clock Priority", twl4030_avadc_clk_priority_enum),
+
        SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum),
 
        SOC_ENUM("Vibra H-bridge mode", twl4030_vibradirmode_enum),
@@ -1208,13 +1248,22 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
        SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
                        &twl4030_dapm_earpiece_controls[0],
                        ARRAY_SIZE(twl4030_dapm_earpiece_controls)),
+       SND_SOC_DAPM_PGA_E("Earpiece PGA", SND_SOC_NOPM,
+                       0, 0, NULL, 0, earpiecepga_event,
+                       SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
        /* PreDrivL/R */
        SND_SOC_DAPM_MIXER("PredriveL Mixer", SND_SOC_NOPM, 0, 0,
                        &twl4030_dapm_predrivel_controls[0],
                        ARRAY_SIZE(twl4030_dapm_predrivel_controls)),
+       SND_SOC_DAPM_PGA_E("PredriveL PGA", SND_SOC_NOPM,
+                       0, 0, NULL, 0, predrivelpga_event,
+                       SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
        SND_SOC_DAPM_MIXER("PredriveR Mixer", SND_SOC_NOPM, 0, 0,
                        &twl4030_dapm_predriver_controls[0],
                        ARRAY_SIZE(twl4030_dapm_predriver_controls)),
+       SND_SOC_DAPM_PGA_E("PredriveR PGA", SND_SOC_NOPM,
+                       0, 0, NULL, 0, predriverpga_event,
+                       SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
        /* HeadsetL/R */
        SND_SOC_DAPM_MIXER("HeadsetL Mixer", SND_SOC_NOPM, 0, 0,
                        &twl4030_dapm_hsol_controls[0],
@@ -1232,22 +1281,28 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
        SND_SOC_DAPM_MIXER("CarkitL Mixer", SND_SOC_NOPM, 0, 0,
                        &twl4030_dapm_carkitl_controls[0],
                        ARRAY_SIZE(twl4030_dapm_carkitl_controls)),
+       SND_SOC_DAPM_PGA_E("CarkitL PGA", SND_SOC_NOPM,
+                       0, 0, NULL, 0, carkitlpga_event,
+                       SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
        SND_SOC_DAPM_MIXER("CarkitR Mixer", SND_SOC_NOPM, 0, 0,
                        &twl4030_dapm_carkitr_controls[0],
                        ARRAY_SIZE(twl4030_dapm_carkitr_controls)),
+       SND_SOC_DAPM_PGA_E("CarkitR PGA", SND_SOC_NOPM,
+                       0, 0, NULL, 0, carkitrpga_event,
+                       SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
 
        /* Output MUX controls */
        /* HandsfreeL/R */
        SND_SOC_DAPM_MUX("HandsfreeL Mux", SND_SOC_NOPM, 0, 0,
                &twl4030_dapm_handsfreel_control),
-       SND_SOC_DAPM_SWITCH("HandsfreeL Switch", SND_SOC_NOPM, 0, 0,
+       SND_SOC_DAPM_SWITCH("HandsfreeL", SND_SOC_NOPM, 0, 0,
                        &twl4030_dapm_handsfreelmute_control),
        SND_SOC_DAPM_PGA_E("HandsfreeL PGA", SND_SOC_NOPM,
                        0, 0, NULL, 0, handsfreelpga_event,
                        SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
        SND_SOC_DAPM_MUX("HandsfreeR Mux", SND_SOC_NOPM, 5, 0,
                &twl4030_dapm_handsfreer_control),
-       SND_SOC_DAPM_SWITCH("HandsfreeR Switch", SND_SOC_NOPM, 0, 0,
+       SND_SOC_DAPM_SWITCH("HandsfreeR", SND_SOC_NOPM, 0, 0,
                        &twl4030_dapm_handsfreermute_control),
        SND_SOC_DAPM_PGA_E("HandsfreeR PGA", SND_SOC_NOPM,
                        0, 0, NULL, 0, handsfreerpga_event,
@@ -1282,11 +1337,11 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
                SND_SOC_DAPM_POST_REG),
 
        /* Analog input mixers for the capture amplifiers */
-       SND_SOC_DAPM_MIXER("Analog Left Capture Route",
+       SND_SOC_DAPM_MIXER("Analog Left",
                TWL4030_REG_ANAMICL, 4, 0,
                &twl4030_dapm_analoglmic_controls[0],
                ARRAY_SIZE(twl4030_dapm_analoglmic_controls)),
-       SND_SOC_DAPM_MIXER("Analog Right Capture Route",
+       SND_SOC_DAPM_MIXER("Analog Right",
                TWL4030_REG_ANAMICR, 4, 0,
                &twl4030_dapm_analogrmic_controls[0],
                ARRAY_SIZE(twl4030_dapm_analogrmic_controls)),
@@ -1326,16 +1381,19 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"Earpiece Mixer", "AudioL1", "Analog L1 Playback Mixer"},
        {"Earpiece Mixer", "AudioL2", "Analog L2 Playback Mixer"},
        {"Earpiece Mixer", "AudioR1", "Analog R1 Playback Mixer"},
+       {"Earpiece PGA", NULL, "Earpiece Mixer"},
        /* PreDrivL */
        {"PredriveL Mixer", "Voice", "Analog Voice Playback Mixer"},
        {"PredriveL Mixer", "AudioL1", "Analog L1 Playback Mixer"},
        {"PredriveL Mixer", "AudioL2", "Analog L2 Playback Mixer"},
        {"PredriveL Mixer", "AudioR2", "Analog R2 Playback Mixer"},
+       {"PredriveL PGA", NULL, "PredriveL Mixer"},
        /* PreDrivR */
        {"PredriveR Mixer", "Voice", "Analog Voice Playback Mixer"},
        {"PredriveR Mixer", "AudioR1", "Analog R1 Playback Mixer"},
        {"PredriveR Mixer", "AudioR2", "Analog R2 Playback Mixer"},
        {"PredriveR Mixer", "AudioL2", "Analog L2 Playback Mixer"},
+       {"PredriveR PGA", NULL, "PredriveR Mixer"},
        /* HeadsetL */
        {"HeadsetL Mixer", "Voice", "Analog Voice Playback Mixer"},
        {"HeadsetL Mixer", "AudioL1", "Analog L1 Playback Mixer"},
@@ -1350,24 +1408,26 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"CarkitL Mixer", "Voice", "Analog Voice Playback Mixer"},
        {"CarkitL Mixer", "AudioL1", "Analog L1 Playback Mixer"},
        {"CarkitL Mixer", "AudioL2", "Analog L2 Playback Mixer"},
+       {"CarkitL PGA", NULL, "CarkitL Mixer"},
        /* CarkitR */
        {"CarkitR Mixer", "Voice", "Analog Voice Playback Mixer"},
        {"CarkitR Mixer", "AudioR1", "Analog R1 Playback Mixer"},
        {"CarkitR Mixer", "AudioR2", "Analog R2 Playback Mixer"},
+       {"CarkitR PGA", NULL, "CarkitR Mixer"},
        /* HandsfreeL */
        {"HandsfreeL Mux", "Voice", "Analog Voice Playback Mixer"},
        {"HandsfreeL Mux", "AudioL1", "Analog L1 Playback Mixer"},
        {"HandsfreeL Mux", "AudioL2", "Analog L2 Playback Mixer"},
        {"HandsfreeL Mux", "AudioR2", "Analog R2 Playback Mixer"},
-       {"HandsfreeL Switch", "Switch", "HandsfreeL Mux"},
-       {"HandsfreeL PGA", NULL, "HandsfreeL Switch"},
+       {"HandsfreeL", "Switch", "HandsfreeL Mux"},
+       {"HandsfreeL PGA", NULL, "HandsfreeL"},
        /* HandsfreeR */
        {"HandsfreeR Mux", "Voice", "Analog Voice Playback Mixer"},
        {"HandsfreeR Mux", "AudioR1", "Analog R1 Playback Mixer"},
        {"HandsfreeR Mux", "AudioR2", "Analog R2 Playback Mixer"},
        {"HandsfreeR Mux", "AudioL2", "Analog L2 Playback Mixer"},
-       {"HandsfreeR Switch", "Switch", "HandsfreeR Mux"},
-       {"HandsfreeR PGA", NULL, "HandsfreeR Switch"},
+       {"HandsfreeR", "Switch", "HandsfreeR Mux"},
+       {"HandsfreeR PGA", NULL, "HandsfreeR"},
        /* Vibra */
        {"Vibra Mux", "AudioL1", "DAC Left1"},
        {"Vibra Mux", "AudioR1", "DAC Right1"},
@@ -1377,29 +1437,29 @@ static const struct snd_soc_dapm_route intercon[] = {
        /* outputs */
        {"OUTL", NULL, "Analog L2 Playback Mixer"},
        {"OUTR", NULL, "Analog R2 Playback Mixer"},
-       {"EARPIECE", NULL, "Earpiece Mixer"},
-       {"PREDRIVEL", NULL, "PredriveL Mixer"},
-       {"PREDRIVER", NULL, "PredriveR Mixer"},
+       {"EARPIECE", NULL, "Earpiece PGA"},
+       {"PREDRIVEL", NULL, "PredriveL PGA"},
+       {"PREDRIVER", NULL, "PredriveR PGA"},
        {"HSOL", NULL, "HeadsetL PGA"},
        {"HSOR", NULL, "HeadsetR PGA"},
-       {"CARKITL", NULL, "CarkitL Mixer"},
-       {"CARKITR", NULL, "CarkitR Mixer"},
+       {"CARKITL", NULL, "CarkitL PGA"},
+       {"CARKITR", NULL, "CarkitR PGA"},
        {"HFL", NULL, "HandsfreeL PGA"},
        {"HFR", NULL, "HandsfreeR PGA"},
        {"Vibra Route", "Audio", "Vibra Mux"},
        {"VIBRA", NULL, "Vibra Route"},
 
        /* Capture path */
-       {"Analog Left Capture Route", "Main mic", "MAINMIC"},
-       {"Analog Left Capture Route", "Headset mic", "HSMIC"},
-       {"Analog Left Capture Route", "AUXL", "AUXL"},
-       {"Analog Left Capture Route", "Carkit mic", "CARKITMIC"},
+       {"Analog Left", "Main Mic Capture Switch", "MAINMIC"},
+       {"Analog Left", "Headset Mic Capture Switch", "HSMIC"},
+       {"Analog Left", "AUXL Capture Switch", "AUXL"},
+       {"Analog Left", "Carkit Mic Capture Switch", "CARKITMIC"},
 
-       {"Analog Right Capture Route", "Sub mic", "SUBMIC"},
-       {"Analog Right Capture Route", "AUXR", "AUXR"},
+       {"Analog Right", "Sub Mic Capture Switch", "SUBMIC"},
+       {"Analog Right", "AUXR Capture Switch", "AUXR"},
 
-       {"ADC Physical Left", NULL, "Analog Left Capture Route"},
-       {"ADC Physical Right", NULL, "Analog Right Capture Route"},
+       {"ADC Physical Left", NULL, "Analog Left"},
+       {"ADC Physical Right", NULL, "Analog Right"},
 
        {"Digimic0 Enable", NULL, "DIGIMIC0"},
        {"Digimic1 Enable", NULL, "DIGIMIC1"},
@@ -1423,11 +1483,11 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"ADC Virtual Right2", NULL, "TX2 Capture Route"},
 
        /* Analog bypass routes */
-       {"Right1 Analog Loopback", "Switch", "Analog Right Capture Route"},
-       {"Left1 Analog Loopback", "Switch", "Analog Left Capture Route"},
-       {"Right2 Analog Loopback", "Switch", "Analog Right Capture Route"},
-       {"Left2 Analog Loopback", "Switch", "Analog Left Capture Route"},
-       {"Voice Analog Loopback", "Switch", "Analog Left Capture Route"},
+       {"Right1 Analog Loopback", "Switch", "Analog Right"},
+       {"Left1 Analog Loopback", "Switch", "Analog Left"},
+       {"Right2 Analog Loopback", "Switch", "Analog Right"},
+       {"Left2 Analog Loopback", "Switch", "Analog Left"},
+       {"Voice Analog Loopback", "Switch", "Analog Left"},
 
        {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"},
        {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"},
@@ -1609,8 +1669,6 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
 
         /* If the substream has 4 channel, do the necessary setup */
        if (params_channels(params) == 4) {
-               u8 format, mode;
-
                format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
                mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
 
@@ -1806,6 +1864,19 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
        return 0;
 }
 
+static int twl4030_set_tristate(struct snd_soc_dai *dai, int tristate)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
+
+       if (tristate)
+               reg |= TWL4030_AIF_TRI_EN;
+       else
+               reg &= ~TWL4030_AIF_TRI_EN;
+
+       return twl4030_write(codec, TWL4030_REG_AUDIO_IF, reg);
+}
+
 /* In case of voice mode, the RX1 L(VRX) for downlink and the TX2 L/R
  * (VTXL, VTXR) for uplink has to be enabled/disabled. */
 static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction,
@@ -1948,7 +2019,7 @@ static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
 
        /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-       case SND_SOC_DAIFMT_CBS_CFM:
+       case SND_SOC_DAIFMT_CBM_CFM:
                format &= ~(TWL4030_VIF_SLAVE_EN);
                break;
        case SND_SOC_DAIFMT_CBS_CFS:
@@ -1980,6 +2051,19 @@ static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
        return 0;
 }
 
+static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF);
+
+       if (tristate)
+               reg |= TWL4030_VIF_TRI_EN;
+       else
+               reg &= ~TWL4030_VIF_TRI_EN;
+
+       return twl4030_write(codec, TWL4030_REG_VOICE_IF, reg);
+}
+
 #define TWL4030_RATES   (SNDRV_PCM_RATE_8000_48000)
 #define TWL4030_FORMATS         (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
 
@@ -1989,6 +2073,7 @@ static struct snd_soc_dai_ops twl4030_dai_ops = {
        .hw_params      = twl4030_hw_params,
        .set_sysclk     = twl4030_set_dai_sysclk,
        .set_fmt        = twl4030_set_dai_fmt,
+       .set_tristate   = twl4030_set_tristate,
 };
 
 static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
@@ -1997,6 +2082,7 @@ static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
        .hw_params      = twl4030_voice_hw_params,
        .set_sysclk     = twl4030_voice_set_dai_sysclk,
        .set_fmt        = twl4030_voice_set_dai_fmt,
+       .set_tristate   = twl4030_voice_set_tristate,
 };
 
 struct snd_soc_dai twl4030_dai[] = {
index fe5f395d9e4fe8bdcce9b4ca29c82aceecb57a7c..2b4bfa23f985d5c2a1f74e8cad4f607410a8f23b 100644 (file)
@@ -274,6 +274,8 @@ extern struct snd_soc_codec_device soc_codec_dev_twl4030;
 struct twl4030_setup_data {
        unsigned int ramp_delay_value;
        unsigned int sysclk;
+       unsigned int hs_extmute:1;
+       void (*set_hs_extmute)(int mute);
 };
 
 #endif /* End of __TWL4030_AUDIO_H__ */
index 269b108e1de612f6aaff359b09b59be3f904abaa..c33b92edbded03774fc1cc16bfb7f1bda82414dd 100644 (file)
@@ -163,7 +163,7 @@ static int uda134x_mute(struct snd_soc_dai *dai, int mute)
        else
                mute_reg &= ~(1<<2);
 
-       uda134x_write(codec, UDA134X_DATA010, mute_reg & ~(1<<2));
+       uda134x_write(codec, UDA134X_DATA010, mute_reg);
 
        return 0;
 }
index 5b21594e0e58283ee30d3ee6ea209d8636929aef..92ec034421543e06f494b7c5075cc3a8767f2a95 100644 (file)
@@ -5,9 +5,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * Copyright (c) 2007 Philipp Zabel <philipp.zabel@gmail.com>
- * Improved support for DAPM and audio routing/mixing capabilities,
- * added TLV support.
+ * Copyright (c) 2007-2009 Philipp Zabel <philipp.zabel@gmail.com>
  *
  * Modified by Richard Purdie <richard@openedhand.com> to fit into SoC
  * codec model.
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
-#include <linux/ioctl.h>
+#include <linux/gpio.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/workqueue.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/initval.h>
-#include <sound/info.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/tlv.h>
+#include <sound/uda1380.h>
 
 #include "uda1380.h"
 
-static struct work_struct uda1380_work;
 static struct snd_soc_codec *uda1380_codec;
 
+/* codec private data */
+struct uda1380_priv {
+       struct snd_soc_codec codec;
+       u16 reg_cache[UDA1380_CACHEREGNUM];
+       unsigned int dac_clk;
+       struct work_struct work;
+};
+
 /*
  * uda1380 register cache
  */
@@ -473,6 +477,7 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->card->codec;
+       struct uda1380_priv *uda1380 = codec->private_data;
        int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER);
 
        switch (cmd) {
@@ -480,13 +485,13 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                uda1380_write_reg_cache(codec, UDA1380_MIXER,
                                        mixer & ~R14_SILENCE);
-               schedule_work(&uda1380_work);
+               schedule_work(&uda1380->work);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                uda1380_write_reg_cache(codec, UDA1380_MIXER,
                                        mixer | R14_SILENCE);
-               schedule_work(&uda1380_work);
+               schedule_work(&uda1380->work);
                break;
        }
        return 0;
@@ -670,44 +675,33 @@ static int uda1380_resume(struct platform_device *pdev)
        return 0;
 }
 
-/*
- * initialise the UDA1380 driver
- * register mixer and dsp interfaces with the kernel
- */
-static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
+static int uda1380_probe(struct platform_device *pdev)
 {
-       struct snd_soc_codec *codec = socdev->card->codec;
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec;
+       struct uda1380_platform_data *pdata;
        int ret = 0;
 
-       codec->name = "UDA1380";
-       codec->owner = THIS_MODULE;
-       codec->read = uda1380_read_reg_cache;
-       codec->write = uda1380_write;
-       codec->set_bias_level = uda1380_set_bias_level;
-       codec->dai = uda1380_dai;
-       codec->num_dai = ARRAY_SIZE(uda1380_dai);
-       codec->reg_cache = kmemdup(uda1380_reg, sizeof(uda1380_reg),
-                                  GFP_KERNEL);
-       if (codec->reg_cache == NULL)
-               return -ENOMEM;
-       codec->reg_cache_size = ARRAY_SIZE(uda1380_reg);
-       codec->reg_cache_step = 1;
-       uda1380_reset(codec);
+       if (uda1380_codec == NULL) {
+               dev_err(&pdev->dev, "Codec device not registered\n");
+               return -ENODEV;
+       }
 
-       uda1380_codec = codec;
-       INIT_WORK(&uda1380_work, uda1380_flush_work);
+       socdev->card->codec = uda1380_codec;
+       codec = uda1380_codec;
+       pdata = codec->dev->platform_data;
 
        /* register pcms */
        ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
        if (ret < 0) {
-               pr_err("uda1380: failed to create pcms\n");
+               dev_err(codec->dev, "failed to create pcms: %d\n", ret);
                goto pcm_err;
        }
 
        /* power on device */
        uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
        /* set clock input */
-       switch (dac_clk) {
+       switch (pdata->dac_clk) {
        case UDA1380_DAC_CLK_SYSCLK:
                uda1380_write(codec, UDA1380_CLK, 0);
                break;
@@ -716,13 +710,12 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
                break;
        }
 
-       /* uda1380 init */
        snd_soc_add_controls(codec, uda1380_snd_controls,
                                ARRAY_SIZE(uda1380_snd_controls));
        uda1380_add_widgets(codec);
        ret = snd_soc_init_card(socdev);
        if (ret < 0) {
-               pr_err("uda1380: failed to register card\n");
+               dev_err(codec->dev, "failed to register card: %d\n", ret);
                goto card_err;
        }
 
@@ -732,165 +725,201 @@ card_err:
        snd_soc_free_pcms(socdev);
        snd_soc_dapm_free(socdev);
 pcm_err:
-       kfree(codec->reg_cache);
        return ret;
 }
 
-static struct snd_soc_device *uda1380_socdev;
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-static int uda1380_i2c_probe(struct i2c_client *i2c,
-                            const struct i2c_device_id *id)
+/* power down chip */
+static int uda1380_remove(struct platform_device *pdev)
 {
-       struct snd_soc_device *socdev = uda1380_socdev;
-       struct uda1380_setup_data *setup = socdev->codec_data;
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_codec *codec = socdev->card->codec;
-       int ret;
-
-       i2c_set_clientdata(i2c, codec);
-       codec->control_data = i2c;
 
-       ret = uda1380_init(socdev, setup->dac_clk);
-       if (ret < 0)
-               pr_err("uda1380: failed to initialise UDA1380\n");
+       if (codec->control_data)
+               uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
 
-       return ret;
-}
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
 
-static int uda1380_i2c_remove(struct i2c_client *client)
-{
-       struct snd_soc_codec *codec = i2c_get_clientdata(client);
-       kfree(codec->reg_cache);
        return 0;
 }
 
-static const struct i2c_device_id uda1380_i2c_id[] = {
-       { "uda1380", 0 },
-       { }
-};
-MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id);
-
-static struct i2c_driver uda1380_i2c_driver = {
-       .driver = {
-               .name =  "UDA1380 I2C Codec",
-               .owner = THIS_MODULE,
-       },
-       .probe =    uda1380_i2c_probe,
-       .remove =   uda1380_i2c_remove,
-       .id_table = uda1380_i2c_id,
+struct snd_soc_codec_device soc_codec_dev_uda1380 = {
+       .probe =        uda1380_probe,
+       .remove =       uda1380_remove,
+       .suspend =      uda1380_suspend,
+       .resume =       uda1380_resume,
 };
+EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
 
-static int uda1380_add_i2c_device(struct platform_device *pdev,
-                                 const struct uda1380_setup_data *setup)
+static int uda1380_register(struct uda1380_priv *uda1380)
 {
-       struct i2c_board_info info;
-       struct i2c_adapter *adapter;
-       struct i2c_client *client;
-       int ret;
+       int ret, i;
+       struct snd_soc_codec *codec = &uda1380->codec;
+       struct uda1380_platform_data *pdata = codec->dev->platform_data;
 
-       ret = i2c_add_driver(&uda1380_i2c_driver);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "can't add i2c driver\n");
-               return ret;
+       if (uda1380_codec) {
+               dev_err(codec->dev, "Another UDA1380 is registered\n");
+               return -EINVAL;
+       }
+
+       if (!pdata || !pdata->gpio_power || !pdata->gpio_reset)
+               return -EINVAL;
+
+       ret = gpio_request(pdata->gpio_power, "uda1380 power");
+       if (ret)
+               goto err_out;
+       ret = gpio_request(pdata->gpio_reset, "uda1380 reset");
+       if (ret)
+               goto err_gpio;
+
+       gpio_direction_output(pdata->gpio_power, 1);
+
+       /* we may need to have the clock running here - pH5 */
+       gpio_direction_output(pdata->gpio_reset, 1);
+       udelay(5);
+       gpio_set_value(pdata->gpio_reset, 0);
+
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       codec->private_data = uda1380;
+       codec->name = "UDA1380";
+       codec->owner = THIS_MODULE;
+       codec->read = uda1380_read_reg_cache;
+       codec->write = uda1380_write;
+       codec->bias_level = SND_SOC_BIAS_OFF;
+       codec->set_bias_level = uda1380_set_bias_level;
+       codec->dai = uda1380_dai;
+       codec->num_dai = ARRAY_SIZE(uda1380_dai);
+       codec->reg_cache_size = ARRAY_SIZE(uda1380_reg);
+       codec->reg_cache = &uda1380->reg_cache;
+       codec->reg_cache_step = 1;
+
+       memcpy(codec->reg_cache, uda1380_reg, sizeof(uda1380_reg));
+
+       ret = uda1380_reset(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to issue reset\n");
+               goto err_reset;
        }
 
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       info.addr = setup->i2c_address;
-       strlcpy(info.type, "uda1380", I2C_NAME_SIZE);
+       INIT_WORK(&uda1380->work, uda1380_flush_work);
+
+       for (i = 0; i < ARRAY_SIZE(uda1380_dai); i++)
+               uda1380_dai[i].dev = codec->dev;
 
-       adapter = i2c_get_adapter(setup->i2c_bus);
-       if (!adapter) {
-               dev_err(&pdev->dev, "can't get i2c adapter %d\n",
-                       setup->i2c_bus);
-               goto err_driver;
+       uda1380_codec = codec;
+
+       ret = snd_soc_register_codec(codec);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+               goto err_reset;
        }
 
-       client = i2c_new_device(adapter, &info);
-       i2c_put_adapter(adapter);
-       if (!client) {
-               dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
-                       (unsigned int)info.addr);
-               goto err_driver;
+       ret = snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
+               goto err_dai;
        }
 
        return 0;
 
-err_driver:
-       i2c_del_driver(&uda1380_i2c_driver);
-       return -ENODEV;
+err_dai:
+       snd_soc_unregister_codec(codec);
+err_reset:
+       gpio_set_value(pdata->gpio_power, 0);
+       gpio_free(pdata->gpio_reset);
+err_gpio:
+       gpio_free(pdata->gpio_power);
+err_out:
+       return ret;
 }
-#endif
 
-static int uda1380_probe(struct platform_device *pdev)
+static void uda1380_unregister(struct uda1380_priv *uda1380)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct uda1380_setup_data *setup;
+       struct snd_soc_codec *codec = &uda1380->codec;
+       struct uda1380_platform_data *pdata = codec->dev->platform_data;
+
+       snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
+       snd_soc_unregister_codec(&uda1380->codec);
+
+       gpio_set_value(pdata->gpio_power, 0);
+       gpio_free(pdata->gpio_reset);
+       gpio_free(pdata->gpio_power);
+
+       kfree(uda1380);
+       uda1380_codec = NULL;
+}
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct uda1380_priv *uda1380;
        struct snd_soc_codec *codec;
        int ret;
 
-       setup = socdev->codec_data;
-       codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
-       if (codec == NULL)
+       uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL);
+       if (uda1380 == NULL)
                return -ENOMEM;
 
-       socdev->card->codec = codec;
-       mutex_init(&codec->mutex);
-       INIT_LIST_HEAD(&codec->dapm_widgets);
-       INIT_LIST_HEAD(&codec->dapm_paths);
+       codec = &uda1380->codec;
+       codec->hw_write = (hw_write_t)i2c_master_send;
 
-       uda1380_socdev = socdev;
-       ret = -ENODEV;
+       i2c_set_clientdata(i2c, uda1380);
+       codec->control_data = i2c;
 
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       if (setup->i2c_address) {
-               codec->hw_write = (hw_write_t)i2c_master_send;
-               ret = uda1380_add_i2c_device(pdev, setup);
-       }
-#endif
+       codec->dev = &i2c->dev;
 
+       ret = uda1380_register(uda1380);
        if (ret != 0)
-               kfree(codec);
+               kfree(uda1380);
+
        return ret;
 }
 
-/* power down chip */
-static int uda1380_remove(struct platform_device *pdev)
+static int __devexit uda1380_i2c_remove(struct i2c_client *i2c)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_codec *codec = socdev->card->codec;
-
-       if (codec->control_data)
-               uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-       snd_soc_free_pcms(socdev);
-       snd_soc_dapm_free(socdev);
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       i2c_unregister_device(codec->control_data);
-       i2c_del_driver(&uda1380_i2c_driver);
-#endif
-       kfree(codec);
-
+       struct uda1380_priv *uda1380 = i2c_get_clientdata(i2c);
+       uda1380_unregister(uda1380);
        return 0;
 }
 
-struct snd_soc_codec_device soc_codec_dev_uda1380 = {
-       .probe =        uda1380_probe,
-       .remove =       uda1380_remove,
-       .suspend =      uda1380_suspend,
-       .resume =       uda1380_resume,
+static const struct i2c_device_id uda1380_i2c_id[] = {
+       { "uda1380", 0 },
+       { }
 };
-EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
+MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id);
+
+static struct i2c_driver uda1380_i2c_driver = {
+       .driver = {
+               .name =  "UDA1380 I2C Codec",
+               .owner = THIS_MODULE,
+       },
+       .probe =    uda1380_i2c_probe,
+       .remove =   __devexit_p(uda1380_i2c_remove),
+       .id_table = uda1380_i2c_id,
+};
+#endif
 
 static int __init uda1380_modinit(void)
 {
-       return snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
+       int ret;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       ret = i2c_add_driver(&uda1380_i2c_driver);
+       if (ret != 0)
+               pr_err("Failed to register UDA1380 I2C driver: %d\n", ret);
+#endif
+       return 0;
 }
 module_init(uda1380_modinit);
 
 static void __exit uda1380_exit(void)
 {
-       snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&uda1380_i2c_driver);
+#endif
 }
 module_exit(uda1380_exit);
 
index c55c17a52a1205a17454e0c0b575b881ea44b71d..9cefa8a54770da1c003db0e0cfb029b1a65a8baa 100644 (file)
 #define R22_SKIP_DCFIL 0x0002
 #define R23_AGC_EN     0x0001
 
-struct uda1380_setup_data {
-       int            i2c_bus;
-       unsigned short i2c_address;
-       int            dac_clk;
-#define UDA1380_DAC_CLK_SYSCLK 0
-#define UDA1380_DAC_CLK_WSPLL  1
-};
-
 #define UDA1380_DAI_DUPLEX     0 /* playback and capture on single DAI */
 #define UDA1380_DAI_PLAYBACK   1 /* playback DAI */
 #define UDA1380_DAI_CAPTURE    2 /* capture DAI */
index e7348d341b761d5870889a97f814f8f5a927b0cd..3ff0373dff8904faeb2f1c522495e2c1ff32e63e 100644 (file)
@@ -63,6 +63,8 @@ struct wm8350_data {
        struct wm8350_jack_data hpl;
        struct wm8350_jack_data hpr;
        struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
+       int fll_freq_out;
+       int fll_freq_in;
 };
 
 static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec,
@@ -406,7 +408,6 @@ static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
 static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" };
 static const char *wm8350_dacmutem[] = { "Normal", "Soft" };
 static const char *wm8350_dacmutes[] = { "Fast", "Slow" };
-static const char *wm8350_dacfilter[] = { "Normal", "Sloping" };
 static const char *wm8350_adcfilter[] = { "None", "High Pass" };
 static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" };
 static const char *wm8350_lr[] = { "Left", "Right" };
@@ -416,7 +417,6 @@ static const struct soc_enum wm8350_enum[] = {
        SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol),
        SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem),
        SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes),
-       SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 12, 2, wm8350_dacfilter),
        SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter),
        SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp),
        SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol),
@@ -444,10 +444,9 @@ static const struct snd_kcontrol_new wm8350_snd_controls[] = {
                                0, 255, 0, dac_pcm_tlv),
        SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]),
        SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]),
-       SOC_ENUM("Playback PCM Filter", wm8350_enum[4]),
-       SOC_ENUM("Capture PCM Filter", wm8350_enum[5]),
-       SOC_ENUM("Capture PCM HP Filter", wm8350_enum[6]),
-       SOC_ENUM("Capture ADC Inversion", wm8350_enum[7]),
+       SOC_ENUM("Capture PCM Filter", wm8350_enum[4]),
+       SOC_ENUM("Capture PCM HP Filter", wm8350_enum[5]),
+       SOC_ENUM("Capture ADC Inversion", wm8350_enum[6]),
        SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume",
                                WM8350_ADC_DIGITAL_VOLUME_L,
                                WM8350_ADC_DIGITAL_VOLUME_R,
@@ -613,7 +612,7 @@ SOC_DAPM_SINGLE("Switch", WM8350_BEEP_VOLUME, 15, 1, 1);
 
 /* Out4 Capture Mux */
 static const struct snd_kcontrol_new wm8350_out4_capture_controls =
-SOC_DAPM_ENUM("Route", wm8350_enum[8]);
+SOC_DAPM_ENUM("Route", wm8350_enum[7]);
 
 static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = {
 
@@ -993,6 +992,7 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
                                struct snd_soc_dai *codec_dai)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
+       struct wm8350 *wm8350 = codec->control_data;
        u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) &
            ~WM8350_AIF_WL_MASK;
 
@@ -1012,6 +1012,19 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
        }
 
        wm8350_codec_write(codec, WM8350_AI_FORMATING, iface);
+
+       /* The sloping stopband filter is recommended for use with
+        * lower sample rates to improve performance.
+        */
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               if (params_rate(params) < 24000)
+                       wm8350_set_bits(wm8350, WM8350_DAC_MUTE_VOLUME,
+                                       WM8350_DAC_SB_FILT);
+               else
+                       wm8350_clear_bits(wm8350, WM8350_DAC_MUTE_VOLUME,
+                                         WM8350_DAC_SB_FILT);
+       }
+
        return 0;
 }
 
@@ -1093,10 +1106,14 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct wm8350 *wm8350 = codec->control_data;
+       struct wm8350_data *priv = codec->private_data;
        struct _fll_div fll_div;
        int ret = 0;
        u16 fll_1, fll_4;
 
+       if (freq_in == priv->fll_freq_in && freq_out == priv->fll_freq_out)
+               return 0;
+
        /* power down FLL - we need to do this for reconfiguration */
        wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4,
                          WM8350_FLL_ENA | WM8350_FLL_OSC_ENA);
@@ -1131,6 +1148,9 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
        wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA);
        wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA);
 
+       priv->fll_freq_out = freq_out;
+       priv->fll_freq_in = freq_in;
+
        return 0;
 }
 
@@ -1660,6 +1680,21 @@ static int __devexit wm8350_codec_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm8350_codec_suspend(struct platform_device *pdev, pm_message_t m)
+{
+       return snd_soc_suspend_device(&pdev->dev);
+}
+
+static int wm8350_codec_resume(struct platform_device *pdev)
+{
+       return snd_soc_resume_device(&pdev->dev);
+}
+#else
+#define wm8350_codec_suspend NULL
+#define wm8350_codec_resume NULL
+#endif
+
 static struct platform_driver wm8350_codec_driver = {
        .driver = {
                   .name = "wm8350-codec",
@@ -1667,6 +1702,8 @@ static struct platform_driver wm8350_codec_driver = {
                   },
        .probe = wm8350_codec_probe,
        .remove = __devexit_p(wm8350_codec_remove),
+       .suspend = wm8350_codec_suspend,
+       .resume = wm8350_codec_resume,
 };
 
 static __init int wm8350_init(void)
index 502eefac1ecd797dd02ff8382e31e19f8d8b972b..b9ef4d9152211a7649249e0f6a96c50f484147b0 100644 (file)
@@ -1022,10 +1022,15 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
        if (freq_in == wm8400->fll_in && freq_out == wm8400->fll_out)
                return 0;
 
-       if (freq_out != 0) {
+       if (freq_out) {
                ret = fll_factors(wm8400, &factors, freq_in, freq_out);
                if (ret != 0)
                        return ret;
+       } else {
+               /* Bodge GCC 4.4.0 uninitialised variable warning - it
+                * doesn't seem capable of working out that we exit if
+                * freq_out is 0 before any of the uses. */
+               memset(&factors, 0, sizeof(factors));
        }
 
        wm8400->fll_out = freq_out;
@@ -1040,7 +1045,7 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
        reg &= ~WM8400_FLL_OSC_ENA;
        wm8400_write(codec, WM8400_FLL_CONTROL_1, reg);
 
-       if (freq_out == 0)
+       if (!freq_out)
                return 0;
 
        reg &= ~(WM8400_FLL_REF_FREQ | WM8400_FLL_FRATIO_MASK);
@@ -1553,6 +1558,21 @@ static int __exit wm8400_codec_remove(struct platform_device *dev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm8400_pdev_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&pdev->dev);
+}
+
+static int wm8400_pdev_resume(struct platform_device *pdev)
+{
+       return snd_soc_resume_device(&pdev->dev);
+}
+#else
+#define wm8400_pdev_suspend NULL
+#define wm8400_pdev_resume NULL
+#endif
+
 static struct platform_driver wm8400_codec_driver = {
        .driver = {
                .name = "wm8400-codec",
@@ -1560,6 +1580,8 @@ static struct platform_driver wm8400_codec_driver = {
        },
        .probe = wm8400_codec_probe,
        .remove = __exit_p(wm8400_codec_remove),
+       .suspend = wm8400_pdev_suspend,
+       .resume = wm8400_pdev_resume,
 };
 
 static int __init wm8400_codec_init(void)
index c8b8dba858907d0ec7d9bc3f64b2a19cc6b876fc..060d5d06ba955019baf1209595a72734d6866657 100644 (file)
@@ -58,55 +58,7 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
 #define WM8510_POWER1_BIASEN  0x08
 #define WM8510_POWER1_BUFIOEN 0x10
 
-/*
- * read wm8510 register cache
- */
-static inline unsigned int wm8510_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg == WM8510_RESET)
-               return 0;
-       if (reg >= WM8510_CACHEREGNUM)
-               return -1;
-       return cache[reg];
-}
-
-/*
- * write wm8510 register cache
- */
-static inline void wm8510_write_reg_cache(struct snd_soc_codec *codec,
-       u16 reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg >= WM8510_CACHEREGNUM)
-               return;
-       cache[reg] = value;
-}
-
-/*
- * write to the WM8510 register space
- */
-static int wm8510_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
-{
-       u8 data[2];
-
-       /* data is
-        *   D15..D9 WM8510 register offset
-        *   D8...D0 register data
-        */
-       data[0] = (reg << 1) | ((value >> 8) & 0x0001);
-       data[1] = value & 0x00ff;
-
-       wm8510_write_reg_cache(codec, reg, value);
-       if (codec->hw_write(codec->control_data, data, 2) == 2)
-               return 0;
-       else
-               return -EIO;
-}
-
-#define wm8510_reset(c)        wm8510_write(c, WM8510_RESET, 0)
+#define wm8510_reset(c)        snd_soc_write(c, WM8510_RESET, 0)
 
 static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" };
 static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
@@ -327,27 +279,27 @@ static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai,
 
        if (freq_in == 0 || freq_out == 0) {
                /* Clock CODEC directly from MCLK */
-               reg = wm8510_read_reg_cache(codec, WM8510_CLOCK);
-               wm8510_write(codec, WM8510_CLOCK, reg & 0x0ff);
+               reg = snd_soc_read(codec, WM8510_CLOCK);
+               snd_soc_write(codec, WM8510_CLOCK, reg & 0x0ff);
 
                /* Turn off PLL */
-               reg = wm8510_read_reg_cache(codec, WM8510_POWER1);
-               wm8510_write(codec, WM8510_POWER1, reg & 0x1df);
+               reg = snd_soc_read(codec, WM8510_POWER1);
+               snd_soc_write(codec, WM8510_POWER1, reg & 0x1df);
                return 0;
        }
 
        pll_factors(freq_out*4, freq_in);
 
-       wm8510_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n);
-       wm8510_write(codec, WM8510_PLLK1, pll_div.k >> 18);
-       wm8510_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff);
-       wm8510_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff);
-       reg = wm8510_read_reg_cache(codec, WM8510_POWER1);
-       wm8510_write(codec, WM8510_POWER1, reg | 0x020);
+       snd_soc_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n);
+       snd_soc_write(codec, WM8510_PLLK1, pll_div.k >> 18);
+       snd_soc_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff);
+       snd_soc_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff);
+       reg = snd_soc_read(codec, WM8510_POWER1);
+       snd_soc_write(codec, WM8510_POWER1, reg | 0x020);
 
        /* Run CODEC from PLL instead of MCLK */
-       reg = wm8510_read_reg_cache(codec, WM8510_CLOCK);
-       wm8510_write(codec, WM8510_CLOCK, reg | 0x100);
+       reg = snd_soc_read(codec, WM8510_CLOCK);
+       snd_soc_write(codec, WM8510_CLOCK, reg | 0x100);
 
        return 0;
 }
@@ -363,24 +315,24 @@ static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
 
        switch (div_id) {
        case WM8510_OPCLKDIV:
-               reg = wm8510_read_reg_cache(codec, WM8510_GPIO) & 0x1cf;
-               wm8510_write(codec, WM8510_GPIO, reg | div);
+               reg = snd_soc_read(codec, WM8510_GPIO) & 0x1cf;
+               snd_soc_write(codec, WM8510_GPIO, reg | div);
                break;
        case WM8510_MCLKDIV:
-               reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x11f;
-               wm8510_write(codec, WM8510_CLOCK, reg | div);
+               reg = snd_soc_read(codec, WM8510_CLOCK) & 0x11f;
+               snd_soc_write(codec, WM8510_CLOCK, reg | div);
                break;
        case WM8510_ADCCLK:
-               reg = wm8510_read_reg_cache(codec, WM8510_ADC) & 0x1f7;
-               wm8510_write(codec, WM8510_ADC, reg | div);
+               reg = snd_soc_read(codec, WM8510_ADC) & 0x1f7;
+               snd_soc_write(codec, WM8510_ADC, reg | div);
                break;
        case WM8510_DACCLK:
-               reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0x1f7;
-               wm8510_write(codec, WM8510_DAC, reg | div);
+               reg = snd_soc_read(codec, WM8510_DAC) & 0x1f7;
+               snd_soc_write(codec, WM8510_DAC, reg | div);
                break;
        case WM8510_BCLKDIV:
-               reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1e3;
-               wm8510_write(codec, WM8510_CLOCK, reg | div);
+               reg = snd_soc_read(codec, WM8510_CLOCK) & 0x1e3;
+               snd_soc_write(codec, WM8510_CLOCK, reg | div);
                break;
        default:
                return -EINVAL;
@@ -394,7 +346,7 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        u16 iface = 0;
-       u16 clk = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1fe;
+       u16 clk = snd_soc_read(codec, WM8510_CLOCK) & 0x1fe;
 
        /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -441,8 +393,8 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8510_write(codec, WM8510_IFACE, iface);
-       wm8510_write(codec, WM8510_CLOCK, clk);
+       snd_soc_write(codec, WM8510_IFACE, iface);
+       snd_soc_write(codec, WM8510_CLOCK, clk);
        return 0;
 }
 
@@ -453,8 +405,8 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->card->codec;
-       u16 iface = wm8510_read_reg_cache(codec, WM8510_IFACE) & 0x19f;
-       u16 adn = wm8510_read_reg_cache(codec, WM8510_ADD) & 0x1f1;
+       u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f;
+       u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1;
 
        /* bit size */
        switch (params_format(params)) {
@@ -493,20 +445,20 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
                break;
        }
 
-       wm8510_write(codec, WM8510_IFACE, iface);
-       wm8510_write(codec, WM8510_ADD, adn);
+       snd_soc_write(codec, WM8510_IFACE, iface);
+       snd_soc_write(codec, WM8510_ADD, adn);
        return 0;
 }
 
 static int wm8510_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u16 mute_reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0xffbf;
+       u16 mute_reg = snd_soc_read(codec, WM8510_DAC) & 0xffbf;
 
        if (mute)
-               wm8510_write(codec, WM8510_DAC, mute_reg | 0x40);
+               snd_soc_write(codec, WM8510_DAC, mute_reg | 0x40);
        else
-               wm8510_write(codec, WM8510_DAC, mute_reg);
+               snd_soc_write(codec, WM8510_DAC, mute_reg);
        return 0;
 }
 
@@ -514,13 +466,13 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute)
 static int wm8510_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
-       u16 power1 = wm8510_read_reg_cache(codec, WM8510_POWER1) & ~0x3;
+       u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
        case SND_SOC_BIAS_PREPARE:
                power1 |= 0x1;  /* VMID 50k */
-               wm8510_write(codec, WM8510_POWER1, power1);
+               snd_soc_write(codec, WM8510_POWER1, power1);
                break;
 
        case SND_SOC_BIAS_STANDBY:
@@ -528,18 +480,18 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec,
 
                if (codec->bias_level == SND_SOC_BIAS_OFF) {
                        /* Initial cap charge at VMID 5k */
-                       wm8510_write(codec, WM8510_POWER1, power1 | 0x3);
+                       snd_soc_write(codec, WM8510_POWER1, power1 | 0x3);
                        mdelay(100);
                }
 
                power1 |= 0x2;  /* VMID 500k */
-               wm8510_write(codec, WM8510_POWER1, power1);
+               snd_soc_write(codec, WM8510_POWER1, power1);
                break;
 
        case SND_SOC_BIAS_OFF:
-               wm8510_write(codec, WM8510_POWER1, 0);
-               wm8510_write(codec, WM8510_POWER2, 0);
-               wm8510_write(codec, WM8510_POWER3, 0);
+               snd_soc_write(codec, WM8510_POWER1, 0);
+               snd_soc_write(codec, WM8510_POWER2, 0);
+               snd_soc_write(codec, WM8510_POWER3, 0);
                break;
        }
 
@@ -577,6 +529,7 @@ struct snd_soc_dai wm8510_dai = {
                .rates = WM8510_RATES,
                .formats = WM8510_FORMATS,},
        .ops = &wm8510_dai_ops,
+       .symmetric_rates = 1,
 };
 EXPORT_SYMBOL_GPL(wm8510_dai);
 
@@ -612,15 +565,14 @@ static int wm8510_resume(struct platform_device *pdev)
  * initialise the WM8510 driver
  * register the mixer and dsp interfaces with the kernel
  */
-static int wm8510_init(struct snd_soc_device *socdev)
+static int wm8510_init(struct snd_soc_device *socdev,
+                      enum snd_soc_control_type control)
 {
        struct snd_soc_codec *codec = socdev->card->codec;
        int ret = 0;
 
        codec->name = "WM8510";
        codec->owner = THIS_MODULE;
-       codec->read = wm8510_read_reg_cache;
-       codec->write = wm8510_write;
        codec->set_bias_level = wm8510_set_bias_level;
        codec->dai = &wm8510_dai;
        codec->num_dai = 1;
@@ -630,13 +582,20 @@ static int wm8510_init(struct snd_soc_device *socdev)
        if (codec->reg_cache == NULL)
                return -ENOMEM;
 
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       if (ret < 0) {
+               printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n",
+                      ret);
+               goto err;
+       }
+
        wm8510_reset(codec);
 
        /* register pcms */
        ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
        if (ret < 0) {
                printk(KERN_ERR "wm8510: failed to create pcms\n");
-               goto pcm_err;
+               goto err;
        }
 
        /* power on device */
@@ -655,7 +614,7 @@ static int wm8510_init(struct snd_soc_device *socdev)
 card_err:
        snd_soc_free_pcms(socdev);
        snd_soc_dapm_free(socdev);
-pcm_err:
+err:
        kfree(codec->reg_cache);
        return ret;
 }
@@ -678,7 +637,7 @@ static int wm8510_i2c_probe(struct i2c_client *i2c,
        i2c_set_clientdata(i2c, codec);
        codec->control_data = i2c;
 
-       ret = wm8510_init(socdev);
+       ret = wm8510_init(socdev, SND_SOC_I2C);
        if (ret < 0)
                pr_err("failed to initialise WM8510\n");
 
@@ -758,7 +717,7 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi)
 
        codec->control_data = spi;
 
-       ret = wm8510_init(socdev);
+       ret = wm8510_init(socdev, SND_SOC_SPI);
        if (ret < 0)
                dev_err(&spi->dev, "failed to initialise WM8510\n");
 
@@ -779,30 +738,6 @@ static struct spi_driver wm8510_spi_driver = {
        .probe          = wm8510_spi_probe,
        .remove         = __devexit_p(wm8510_spi_remove),
 };
-
-static int wm8510_spi_write(struct spi_device *spi, const char *data, int len)
-{
-       struct spi_transfer t;
-       struct spi_message m;
-       u8 msg[2];
-
-       if (len <= 0)
-               return 0;
-
-       msg[0] = data[0];
-       msg[1] = data[1];
-
-       spi_message_init(&m);
-       memset(&t, 0, (sizeof t));
-
-       t.tx_buf = &msg[0];
-       t.len = len;
-
-       spi_message_add_tail(&t, &m);
-       spi_sync(spi, &m);
-
-       return len;
-}
 #endif /* CONFIG_SPI_MASTER */
 
 static int wm8510_probe(struct platform_device *pdev)
@@ -827,13 +762,11 @@ static int wm8510_probe(struct platform_device *pdev)
        wm8510_socdev = socdev;
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        if (setup->i2c_address) {
-               codec->hw_write = (hw_write_t)i2c_master_send;
                ret = wm8510_add_i2c_device(pdev, setup);
        }
 #endif
 #if defined(CONFIG_SPI_MASTER)
        if (setup->spi) {
-               codec->hw_write = (hw_write_t)wm8510_spi_write;
                ret = spi_register_driver(&wm8510_spi_driver);
                if (ret != 0)
                        printk(KERN_ERR "can't add spi driver");
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
new file mode 100644 (file)
index 0000000..25870a4
--- /dev/null
@@ -0,0 +1,699 @@
+/*
+ * wm8523.c  --  WM8523 ALSA SoC Audio driver
+ *
+ * Copyright 2009 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8523.h"
+
+static struct snd_soc_codec *wm8523_codec;
+struct snd_soc_codec_device soc_codec_dev_wm8523;
+
+#define WM8523_NUM_SUPPLIES 2
+static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
+       "AVDD",
+       "LINEVDD",
+};
+
+#define WM8523_NUM_RATES 7
+
+/* codec private data */
+struct wm8523_priv {
+       struct snd_soc_codec codec;
+       u16 reg_cache[WM8523_REGISTER_COUNT];
+       struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];
+       unsigned int sysclk;
+       unsigned int rate_constraint_list[WM8523_NUM_RATES];
+       struct snd_pcm_hw_constraint_list rate_constraint;
+};
+
+static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = {
+       0x8523,     /* R0 - DEVICE_ID */
+       0x0001,     /* R1 - REVISION */
+       0x0000,     /* R2 - PSCTRL1 */
+       0x1812,     /* R3 - AIF_CTRL1 */
+       0x0000,     /* R4 - AIF_CTRL2 */
+       0x0001,     /* R5 - DAC_CTRL3 */
+       0x0190,     /* R6 - DAC_GAINL */
+       0x0190,     /* R7 - DAC_GAINR */
+       0x0000,     /* R8 - ZERO_DETECT */
+};
+
+static int wm8523_volatile_register(unsigned int reg)
+{
+       switch (reg) {
+       case WM8523_DEVICE_ID:
+       case WM8523_REVISION:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static int wm8523_reset(struct snd_soc_codec *codec)
+{
+       return snd_soc_write(codec, WM8523_DEVICE_ID, 0);
+}
+
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0);
+
+static const char *wm8523_zd_count_text[] = {
+       "1024",
+       "2048",
+};
+
+static const struct soc_enum wm8523_zc_count =
+       SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text);
+
+static const struct snd_kcontrol_new wm8523_snd_controls[] = {
+SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR,
+                0, 448, 0, dac_tlv),
+SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0),
+SOC_SINGLE("Playback Deemphasis Switch", WM8523_AIF_CTRL1, 8, 1, 0),
+SOC_DOUBLE("Playback Switch", WM8523_DAC_CTRL3, 2, 3, 1, 1),
+SOC_SINGLE("Volume Ramp Up Switch", WM8523_DAC_CTRL3, 1, 1, 0),
+SOC_SINGLE("Volume Ramp Down Switch", WM8523_DAC_CTRL3, 0, 1, 0),
+SOC_ENUM("Zero Detect Count", wm8523_zc_count),
+};
+
+static const struct snd_soc_dapm_widget wm8523_dapm_widgets[] = {
+SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_OUTPUT("LINEVOUTL"),
+SND_SOC_DAPM_OUTPUT("LINEVOUTR"),
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+       { "LINEVOUTL", NULL, "DAC" },
+       { "LINEVOUTR", NULL, "DAC" },
+};
+
+static int wm8523_add_widgets(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_new_controls(codec, wm8523_dapm_widgets,
+                                 ARRAY_SIZE(wm8523_dapm_widgets));
+
+       snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
+
+       snd_soc_dapm_new_widgets(codec);
+       return 0;
+}
+
+static struct {
+       int value;
+       int ratio;
+} lrclk_ratios[WM8523_NUM_RATES] = {
+       { 1, 128 },
+       { 2, 192 },
+       { 3, 256 },
+       { 4, 384 },
+       { 5, 512 },
+       { 6, 768 },
+       { 7, 1152 },
+};
+
+static int wm8523_startup(struct snd_pcm_substream *substream,
+                         struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8523_priv *wm8523 = codec->private_data;
+
+       /* The set of sample rates that can be supported depends on the
+        * MCLK supplied to the CODEC - enforce this.
+        */
+       if (!wm8523->sysclk) {
+               dev_err(codec->dev,
+                       "No MCLK configured, call set_sysclk() on init\n");
+               return -EINVAL;
+       }
+
+       return 0;
+       snd_pcm_hw_constraint_list(substream->runtime, 0,
+                                  SNDRV_PCM_HW_PARAM_RATE,
+                                  &wm8523->rate_constraint);
+
+       return 0;
+}
+
+static int wm8523_hw_params(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params,
+                           struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->card->codec;
+       struct wm8523_priv *wm8523 = codec->private_data;
+       int i;
+       u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1);
+       u16 aifctrl2 = snd_soc_read(codec, WM8523_AIF_CTRL2);
+
+       /* Find a supported LRCLK ratio */
+       for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
+               if (wm8523->sysclk / params_rate(params) ==
+                   lrclk_ratios[i].ratio)
+                       break;
+       }
+
+       /* Should never happen, should be handled by constraints */
+       if (i == ARRAY_SIZE(lrclk_ratios)) {
+               dev_err(codec->dev, "MCLK/fs ratio %d unsupported\n",
+                       wm8523->sysclk / params_rate(params));
+               return -EINVAL;
+       }
+
+       aifctrl2 &= ~WM8523_SR_MASK;
+       aifctrl2 |= lrclk_ratios[i].value;
+
+       aifctrl1 &= ~WM8523_WL_MASK;
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               aifctrl1 |= 0x8;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               aifctrl1 |= 0x10;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               aifctrl1 |= 0x18;
+               break;
+       }
+
+       snd_soc_write(codec, WM8523_AIF_CTRL1, aifctrl1);
+       snd_soc_write(codec, WM8523_AIF_CTRL2, aifctrl2);
+
+       return 0;
+}
+
+static int wm8523_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+               int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct wm8523_priv *wm8523 = codec->private_data;
+       unsigned int val;
+       int i;
+
+       wm8523->sysclk = freq;
+
+       wm8523->rate_constraint.count = 0;
+       for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) {
+               val = freq / lrclk_ratios[i].ratio;
+               /* Check that it's a standard rate since core can't
+                * cope with others and having the odd rates confuses
+                * constraint matching.
+                */
+               switch (val) {
+               case 8000:
+               case 11025:
+               case 16000:
+               case 22050:
+               case 32000:
+               case 44100:
+               case 48000:
+               case 64000:
+               case 88200:
+               case 96000:
+               case 176400:
+               case 192000:
+                       dev_dbg(codec->dev, "Supported sample rate: %dHz\n",
+                               val);
+                       wm8523->rate_constraint_list[i] = val;
+                       wm8523->rate_constraint.count++;
+                       break;
+               default:
+                       dev_dbg(codec->dev, "Skipping sample rate: %dHz\n",
+                               val);
+               }
+       }
+
+       /* Need at least one supported rate... */
+       if (wm8523->rate_constraint.count == 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+
+static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai,
+               unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1);
+
+       aifctrl1 &= ~(WM8523_BCLK_INV_MASK | WM8523_LRCLK_INV_MASK |
+                     WM8523_FMT_MASK | WM8523_AIF_MSTR_MASK);
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               aifctrl1 |= WM8523_AIF_MSTR;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               aifctrl1 |= 0x0002;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               aifctrl1 |= 0x0001;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               aifctrl1 |= 0x0003;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               aifctrl1 |= 0x0023;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               aifctrl1 |= WM8523_BCLK_INV | WM8523_LRCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               aifctrl1 |= WM8523_BCLK_INV;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               aifctrl1 |= WM8523_LRCLK_INV;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_write(codec, WM8523_AIF_CTRL1, aifctrl1);
+
+       return 0;
+}
+
+static int wm8523_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
+{
+       struct wm8523_priv *wm8523 = codec->private_data;
+       int ret, i;
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+
+       case SND_SOC_BIAS_PREPARE:
+               /* Full power on */
+               snd_soc_update_bits(codec, WM8523_PSCTRL1,
+                                   WM8523_SYS_ENA_MASK, 3);
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->bias_level == SND_SOC_BIAS_OFF) {
+                       ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
+                                                   wm8523->supplies);
+                       if (ret != 0) {
+                               dev_err(codec->dev,
+                                       "Failed to enable supplies: %d\n",
+                                       ret);
+                               return ret;
+                       }
+
+                       /* Initial power up */
+                       snd_soc_update_bits(codec, WM8523_PSCTRL1,
+                                           WM8523_SYS_ENA_MASK, 1);
+
+                       /* Sync back default/cached values */
+                       for (i = WM8523_AIF_CTRL1;
+                            i < WM8523_MAX_REGISTER; i++)
+                               snd_soc_write(codec, i, wm8523->reg_cache[i]);
+
+
+                       msleep(100);
+               }
+
+               /* Power up to mute */
+               snd_soc_update_bits(codec, WM8523_PSCTRL1,
+                                   WM8523_SYS_ENA_MASK, 2);
+
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               /* The chip runs through the power down sequence for us. */
+               snd_soc_update_bits(codec, WM8523_PSCTRL1,
+                                   WM8523_SYS_ENA_MASK, 0);
+               msleep(100);
+
+               regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies),
+                                      wm8523->supplies);
+               break;
+       }
+       codec->bias_level = level;
+       return 0;
+}
+
+#define WM8523_RATES SNDRV_PCM_RATE_8000_192000
+
+#define WM8523_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+                       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops wm8523_dai_ops = {
+       .startup        = wm8523_startup,
+       .hw_params      = wm8523_hw_params,
+       .set_sysclk     = wm8523_set_dai_sysclk,
+       .set_fmt        = wm8523_set_dai_fmt,
+};
+
+struct snd_soc_dai wm8523_dai = {
+       .name = "WM8523",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 2,  /* Mono modes not yet supported */
+               .channels_max = 2,
+               .rates = WM8523_RATES,
+               .formats = WM8523_FORMATS,
+       },
+       .ops = &wm8523_dai_ops,
+};
+EXPORT_SYMBOL_GPL(wm8523_dai);
+
+#ifdef CONFIG_PM
+static int wm8523_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+
+       wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int wm8523_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+
+       wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       return 0;
+}
+#else
+#define wm8523_suspend NULL
+#define wm8523_resume NULL
+#endif
+
+static int wm8523_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec;
+       int ret = 0;
+
+       if (wm8523_codec == NULL) {
+               dev_err(&pdev->dev, "Codec device not registered\n");
+               return -ENODEV;
+       }
+
+       socdev->card->codec = wm8523_codec;
+       codec = wm8523_codec;
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to create pcms: %d\n", ret);
+               goto pcm_err;
+       }
+
+       snd_soc_add_controls(codec, wm8523_snd_controls,
+                            ARRAY_SIZE(wm8523_snd_controls));
+       wm8523_add_widgets(codec);
+       ret = snd_soc_init_card(socdev);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to register card: %d\n", ret);
+               goto card_err;
+       }
+
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+pcm_err:
+       return ret;
+}
+
+static int wm8523_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+
+       return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8523 = {
+       .probe =        wm8523_probe,
+       .remove =       wm8523_remove,
+       .suspend =      wm8523_suspend,
+       .resume =       wm8523_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523);
+
+static int wm8523_register(struct wm8523_priv *wm8523,
+                          enum snd_soc_control_type control)
+{
+       int ret;
+       struct snd_soc_codec *codec = &wm8523->codec;
+       int i;
+
+       if (wm8523_codec) {
+               dev_err(codec->dev, "Another WM8523 is registered\n");
+               return -EINVAL;
+       }
+
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       codec->private_data = wm8523;
+       codec->name = "WM8523";
+       codec->owner = THIS_MODULE;
+       codec->bias_level = SND_SOC_BIAS_OFF;
+       codec->set_bias_level = wm8523_set_bias_level;
+       codec->dai = &wm8523_dai;
+       codec->num_dai = 1;
+       codec->reg_cache_size = WM8523_REGISTER_COUNT;
+       codec->reg_cache = &wm8523->reg_cache;
+       codec->volatile_register = wm8523_volatile_register;
+
+       wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
+       wm8523->rate_constraint.count =
+               ARRAY_SIZE(wm8523->rate_constraint_list);
+
+       memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg));
+
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++)
+               wm8523->supplies[i].supply = wm8523_supply_names[i];
+
+       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8523->supplies),
+                                wm8523->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               goto err;
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
+                                   wm8523->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+               goto err_get;
+       }
+
+       ret = snd_soc_read(codec, WM8523_DEVICE_ID);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read ID register\n");
+               goto err_enable;
+       }
+       if (ret != wm8523_reg[WM8523_DEVICE_ID]) {
+               dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret);
+               ret = -EINVAL;
+               goto err_enable;
+       }
+
+       ret = snd_soc_read(codec, WM8523_REVISION);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to read revision register\n");
+               goto err_enable;
+       }
+       dev_info(codec->dev, "revision %c\n",
+                (ret & WM8523_CHIP_REV_MASK) + 'A');
+
+       ret = wm8523_reset(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to issue reset\n");
+               goto err_enable;
+       }
+
+       wm8523_dai.dev = codec->dev;
+
+       /* Change some default settings - latch VU and enable ZC */
+       wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
+       wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
+
+       wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       /* Bias level configuration will have done an extra enable */
+       regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
+
+       wm8523_codec = codec;
+
+       ret = snd_soc_register_codec(codec);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+               return ret;
+       }
+
+       ret = snd_soc_register_dai(&wm8523_dai);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
+               snd_soc_unregister_codec(codec);
+               return ret;
+       }
+
+       return 0;
+
+err_enable:
+       regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
+err_get:
+       regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
+err:
+       kfree(wm8523);
+       return ret;
+}
+
+static void wm8523_unregister(struct wm8523_priv *wm8523)
+{
+       wm8523_set_bias_level(&wm8523->codec, SND_SOC_BIAS_OFF);
+       regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
+       snd_soc_unregister_dai(&wm8523_dai);
+       snd_soc_unregister_codec(&wm8523->codec);
+       kfree(wm8523);
+       wm8523_codec = NULL;
+}
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct wm8523_priv *wm8523;
+       struct snd_soc_codec *codec;
+
+       wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL);
+       if (wm8523 == NULL)
+               return -ENOMEM;
+
+       codec = &wm8523->codec;
+       codec->hw_write = (hw_write_t)i2c_master_send;
+
+       i2c_set_clientdata(i2c, wm8523);
+       codec->control_data = i2c;
+
+       codec->dev = &i2c->dev;
+
+       return wm8523_register(wm8523, SND_SOC_I2C);
+}
+
+static __devexit int wm8523_i2c_remove(struct i2c_client *client)
+{
+       struct wm8523_priv *wm8523 = i2c_get_clientdata(client);
+       wm8523_unregister(wm8523);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int wm8523_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&i2c->dev);
+}
+
+static int wm8523_i2c_resume(struct i2c_client *i2c)
+{
+       return snd_soc_resume_device(&i2c->dev);
+}
+#else
+#define wm8523_i2c_suspend NULL
+#define wm8523_i2c_resume NULL
+#endif
+
+static const struct i2c_device_id wm8523_i2c_id[] = {
+       { "wm8523", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);
+
+static struct i2c_driver wm8523_i2c_driver = {
+       .driver = {
+               .name = "WM8523",
+               .owner = THIS_MODULE,
+       },
+       .probe =    wm8523_i2c_probe,
+       .remove =   __devexit_p(wm8523_i2c_remove),
+       .suspend =  wm8523_i2c_suspend,
+       .resume =   wm8523_i2c_resume,
+       .id_table = wm8523_i2c_id,
+};
+#endif
+
+static int __init wm8523_modinit(void)
+{
+       int ret;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       ret = i2c_add_driver(&wm8523_i2c_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register WM8523 I2C driver: %d\n",
+                      ret);
+       }
+#endif
+       return 0;
+}
+module_init(wm8523_modinit);
+
+static void __exit wm8523_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&wm8523_i2c_driver);
+#endif
+}
+module_exit(wm8523_exit);
+
+MODULE_DESCRIPTION("ASoC WM8523 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8523.h b/sound/soc/codecs/wm8523.h
new file mode 100644 (file)
index 0000000..1aa9ce3
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * wm8523.h  --  WM8423 ASoC driver
+ *
+ * Copyright 2009 Wolfson Microelectronics, plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * Based on wm8753.h
+ *
+ * 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 _WM8523_H
+#define _WM8523_H
+
+/*
+ * Register values.
+ */
+#define WM8523_DEVICE_ID                        0x00
+#define WM8523_REVISION                         0x01
+#define WM8523_PSCTRL1                          0x02
+#define WM8523_AIF_CTRL1                        0x03
+#define WM8523_AIF_CTRL2                        0x04
+#define WM8523_DAC_CTRL3                        0x05
+#define WM8523_DAC_GAINL                        0x06
+#define WM8523_DAC_GAINR                        0x07
+#define WM8523_ZERO_DETECT                      0x08
+
+#define WM8523_REGISTER_COUNT                   9
+#define WM8523_MAX_REGISTER                     0x08
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - DEVICE_ID
+ */
+#define WM8523_CHIP_ID_MASK                     0xFFFF  /* CHIP_ID - [15:0] */
+#define WM8523_CHIP_ID_SHIFT                         0  /* CHIP_ID - [15:0] */
+#define WM8523_CHIP_ID_WIDTH                        16  /* CHIP_ID - [15:0] */
+
+/*
+ * R1 (0x01) - REVISION
+ */
+#define WM8523_CHIP_REV_MASK                    0x0007  /* CHIP_REV - [2:0] */
+#define WM8523_CHIP_REV_SHIFT                        0  /* CHIP_REV - [2:0] */
+#define WM8523_CHIP_REV_WIDTH                        3  /* CHIP_REV - [2:0] */
+
+/*
+ * R2 (0x02) - PSCTRL1
+ */
+#define WM8523_SYS_ENA_MASK                     0x0003  /* SYS_ENA - [1:0] */
+#define WM8523_SYS_ENA_SHIFT                         0  /* SYS_ENA - [1:0] */
+#define WM8523_SYS_ENA_WIDTH                         2  /* SYS_ENA - [1:0] */
+
+/*
+ * R3 (0x03) - AIF_CTRL1
+ */
+#define WM8523_TDM_MODE_MASK                    0x1800  /* TDM_MODE - [12:11] */
+#define WM8523_TDM_MODE_SHIFT                       11  /* TDM_MODE - [12:11] */
+#define WM8523_TDM_MODE_WIDTH                        2  /* TDM_MODE - [12:11] */
+#define WM8523_TDM_SLOT_MASK                    0x0600  /* TDM_SLOT - [10:9] */
+#define WM8523_TDM_SLOT_SHIFT                        9  /* TDM_SLOT - [10:9] */
+#define WM8523_TDM_SLOT_WIDTH                        2  /* TDM_SLOT - [10:9] */
+#define WM8523_DEEMPH                           0x0100  /* DEEMPH  */
+#define WM8523_DEEMPH_MASK                      0x0100  /* DEEMPH  */
+#define WM8523_DEEMPH_SHIFT                          8  /* DEEMPH  */
+#define WM8523_DEEMPH_WIDTH                          1  /* DEEMPH  */
+#define WM8523_AIF_MSTR                         0x0080  /* AIF_MSTR  */
+#define WM8523_AIF_MSTR_MASK                    0x0080  /* AIF_MSTR  */
+#define WM8523_AIF_MSTR_SHIFT                        7  /* AIF_MSTR  */
+#define WM8523_AIF_MSTR_WIDTH                        1  /* AIF_MSTR  */
+#define WM8523_LRCLK_INV                        0x0040  /* LRCLK_INV  */
+#define WM8523_LRCLK_INV_MASK                   0x0040  /* LRCLK_INV  */
+#define WM8523_LRCLK_INV_SHIFT                       6  /* LRCLK_INV  */
+#define WM8523_LRCLK_INV_WIDTH                       1  /* LRCLK_INV  */
+#define WM8523_BCLK_INV                         0x0020  /* BCLK_INV  */
+#define WM8523_BCLK_INV_MASK                    0x0020  /* BCLK_INV  */
+#define WM8523_BCLK_INV_SHIFT                        5  /* BCLK_INV  */
+#define WM8523_BCLK_INV_WIDTH                        1  /* BCLK_INV  */
+#define WM8523_WL_MASK                          0x0018  /* WL - [4:3] */
+#define WM8523_WL_SHIFT                              3  /* WL - [4:3] */
+#define WM8523_WL_WIDTH                              2  /* WL - [4:3] */
+#define WM8523_FMT_MASK                         0x0007  /* FMT - [2:0] */
+#define WM8523_FMT_SHIFT                             0  /* FMT - [2:0] */
+#define WM8523_FMT_WIDTH                             3  /* FMT - [2:0] */
+
+/*
+ * R4 (0x04) - AIF_CTRL2
+ */
+#define WM8523_DAC_OP_MUX_MASK                  0x00C0  /* DAC_OP_MUX - [7:6] */
+#define WM8523_DAC_OP_MUX_SHIFT                      6  /* DAC_OP_MUX - [7:6] */
+#define WM8523_DAC_OP_MUX_WIDTH                      2  /* DAC_OP_MUX - [7:6] */
+#define WM8523_BCLKDIV_MASK                     0x0038  /* BCLKDIV - [5:3] */
+#define WM8523_BCLKDIV_SHIFT                         3  /* BCLKDIV - [5:3] */
+#define WM8523_BCLKDIV_WIDTH                         3  /* BCLKDIV - [5:3] */
+#define WM8523_SR_MASK                          0x0007  /* SR - [2:0] */
+#define WM8523_SR_SHIFT                              0  /* SR - [2:0] */
+#define WM8523_SR_WIDTH                              3  /* SR - [2:0] */
+
+/*
+ * R5 (0x05) - DAC_CTRL3
+ */
+#define WM8523_ZC                               0x0010  /* ZC  */
+#define WM8523_ZC_MASK                          0x0010  /* ZC  */
+#define WM8523_ZC_SHIFT                              4  /* ZC  */
+#define WM8523_ZC_WIDTH                              1  /* ZC  */
+#define WM8523_DACR                             0x0008  /* DACR  */
+#define WM8523_DACR_MASK                        0x0008  /* DACR  */
+#define WM8523_DACR_SHIFT                            3  /* DACR  */
+#define WM8523_DACR_WIDTH                            1  /* DACR  */
+#define WM8523_DACL                             0x0004  /* DACL  */
+#define WM8523_DACL_MASK                        0x0004  /* DACL  */
+#define WM8523_DACL_SHIFT                            2  /* DACL  */
+#define WM8523_DACL_WIDTH                            1  /* DACL  */
+#define WM8523_VOL_UP_RAMP                      0x0002  /* VOL_UP_RAMP  */
+#define WM8523_VOL_UP_RAMP_MASK                 0x0002  /* VOL_UP_RAMP  */
+#define WM8523_VOL_UP_RAMP_SHIFT                     1  /* VOL_UP_RAMP  */
+#define WM8523_VOL_UP_RAMP_WIDTH                     1  /* VOL_UP_RAMP  */
+#define WM8523_VOL_DOWN_RAMP                    0x0001  /* VOL_DOWN_RAMP  */
+#define WM8523_VOL_DOWN_RAMP_MASK               0x0001  /* VOL_DOWN_RAMP  */
+#define WM8523_VOL_DOWN_RAMP_SHIFT                   0  /* VOL_DOWN_RAMP  */
+#define WM8523_VOL_DOWN_RAMP_WIDTH                   1  /* VOL_DOWN_RAMP  */
+
+/*
+ * R6 (0x06) - DAC_GAINL
+ */
+#define WM8523_DACL_VU                          0x0200  /* DACL_VU  */
+#define WM8523_DACL_VU_MASK                     0x0200  /* DACL_VU  */
+#define WM8523_DACL_VU_SHIFT                         9  /* DACL_VU  */
+#define WM8523_DACL_VU_WIDTH                         1  /* DACL_VU  */
+#define WM8523_DACL_VOL_MASK                    0x01FF  /* DACL_VOL - [8:0] */
+#define WM8523_DACL_VOL_SHIFT                        0  /* DACL_VOL - [8:0] */
+#define WM8523_DACL_VOL_WIDTH                        9  /* DACL_VOL - [8:0] */
+
+/*
+ * R7 (0x07) - DAC_GAINR
+ */
+#define WM8523_DACR_VU                          0x0200  /* DACR_VU  */
+#define WM8523_DACR_VU_MASK                     0x0200  /* DACR_VU  */
+#define WM8523_DACR_VU_SHIFT                         9  /* DACR_VU  */
+#define WM8523_DACR_VU_WIDTH                         1  /* DACR_VU  */
+#define WM8523_DACR_VOL_MASK                    0x01FF  /* DACR_VOL - [8:0] */
+#define WM8523_DACR_VOL_SHIFT                        0  /* DACR_VOL - [8:0] */
+#define WM8523_DACR_VOL_WIDTH                        9  /* DACR_VOL - [8:0] */
+
+/*
+ * R8 (0x08) - ZERO_DETECT
+ */
+#define WM8523_ZD_COUNT_MASK                    0x0003  /* ZD_COUNT - [1:0] */
+#define WM8523_ZD_COUNT_SHIFT                        0  /* ZD_COUNT - [1:0] */
+#define WM8523_ZD_COUNT_WIDTH                        2  /* ZD_COUNT - [1:0] */
+
+extern struct snd_soc_dai wm8523_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8523;
+
+#endif
index 86c4b24db8172aa610d283120476440587035c3d..6bded8c78150d7f64c52cf7cc4eca8fd89df0866 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -187,82 +189,22 @@ struct pll_state {
        unsigned int out;
 };
 
+#define WM8580_NUM_SUPPLIES 3
+static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = {
+       "AVDD",
+       "DVDD",
+       "PVDD",
+};
+
 /* codec private data */
 struct wm8580_priv {
        struct snd_soc_codec codec;
+       struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES];
        u16 reg_cache[WM8580_MAX_REGISTER + 1];
        struct pll_state a;
        struct pll_state b;
 };
 
-
-/*
- * read wm8580 register cache
- */
-static inline unsigned int wm8580_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       BUG_ON(reg >= ARRAY_SIZE(wm8580_reg));
-       return cache[reg];
-}
-
-/*
- * write wm8580 register cache
- */
-static inline void wm8580_write_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-
-       cache[reg] = value;
-}
-
-/*
- * write to the WM8580 register space
- */
-static int wm8580_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
-{
-       u8 data[2];
-
-       BUG_ON(reg >= ARRAY_SIZE(wm8580_reg));
-
-       /* Registers are 9 bits wide */
-       value &= 0x1ff;
-
-       switch (reg) {
-       case WM8580_RESET:
-               /* Uncached */
-               break;
-       default:
-               if (value == wm8580_read_reg_cache(codec, reg))
-                       return 0;
-       }
-
-       /* data is
-        *   D15..D9 WM8580 register offset
-        *   D8...D0 register data
-        */
-       data[0] = (reg << 1) | ((value >> 8) & 0x0001);
-       data[1] = value & 0x00ff;
-
-       wm8580_write_reg_cache(codec, reg, value);
-       if (codec->hw_write(codec->control_data, data, 2) == 2)
-               return 0;
-       else
-               return -EIO;
-}
-
-static inline unsigned int wm8580_read(struct snd_soc_codec *codec,
-                                      unsigned int reg)
-{
-       switch (reg) {
-       default:
-               return wm8580_read_reg_cache(codec, reg);
-       }
-}
-
 static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
 
 static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
@@ -271,25 +213,22 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       u16 *reg_cache = codec->reg_cache;
        unsigned int reg = mc->reg;
        unsigned int reg2 = mc->rreg;
        int ret;
-       u16 val;
 
        /* Clear the register cache so we write without VU set */
-       wm8580_write_reg_cache(codec, reg, 0);
-       wm8580_write_reg_cache(codec, reg2, 0);
+       reg_cache[reg] = 0;
+       reg_cache[reg2] = 0;
 
        ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
        if (ret < 0)
                return ret;
 
        /* Now write again with the volume update bit set */
-       val = wm8580_read_reg_cache(codec, reg);
-       wm8580_write(codec, reg, val | 0x0100);
-
-       val = wm8580_read_reg_cache(codec, reg2);
-       wm8580_write(codec, reg2, val | 0x0100);
+       snd_soc_update_bits(codec, reg, 0x100, 0x100);
+       snd_soc_update_bits(codec, reg2, 0x100, 0x100);
 
        return 0;
 }
@@ -512,27 +451,27 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai,
        /* Always disable the PLL - it is not safe to leave it running
         * while reprogramming it.
         */
-       reg = wm8580_read(codec, WM8580_PWRDN2);
-       wm8580_write(codec, WM8580_PWRDN2, reg | pwr_mask);
+       reg = snd_soc_read(codec, WM8580_PWRDN2);
+       snd_soc_write(codec, WM8580_PWRDN2, reg | pwr_mask);
 
        if (!freq_in || !freq_out)
                return 0;
 
-       wm8580_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff);
-       wm8580_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0xff);
-       wm8580_write(codec, WM8580_PLLA3 + offset,
+       snd_soc_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff);
+       snd_soc_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0x1ff);
+       snd_soc_write(codec, WM8580_PLLA3 + offset,
                     (pll_div.k >> 18 & 0xf) | (pll_div.n << 4));
 
-       reg = wm8580_read(codec, WM8580_PLLA4 + offset);
-       reg &= ~0x3f;
+       reg = snd_soc_read(codec, WM8580_PLLA4 + offset);
+       reg &= ~0x1b;
        reg |= pll_div.prescale | pll_div.postscale << 1 |
                pll_div.freqmode << 3;
 
-       wm8580_write(codec, WM8580_PLLA4 + offset, reg);
+       snd_soc_write(codec, WM8580_PLLA4 + offset, reg);
 
        /* All done, turn it on */
-       reg = wm8580_read(codec, WM8580_PWRDN2);
-       wm8580_write(codec, WM8580_PWRDN2, reg & ~pwr_mask);
+       reg = snd_soc_read(codec, WM8580_PWRDN2);
+       snd_soc_write(codec, WM8580_PWRDN2, reg & ~pwr_mask);
 
        return 0;
 }
@@ -547,7 +486,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->card->codec;
-       u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id);
+       u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id);
 
        paifb &= ~WM8580_AIF_LENGTH_MASK;
        /* bit size */
@@ -567,7 +506,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       wm8580_write(codec, WM8580_PAIF3 + dai->id, paifb);
+       snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb);
        return 0;
 }
 
@@ -579,8 +518,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
        unsigned int aifb;
        int can_invert_lrclk;
 
-       aifa = wm8580_read(codec, WM8580_PAIF1 + codec_dai->id);
-       aifb = wm8580_read(codec, WM8580_PAIF3 + codec_dai->id);
+       aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id);
+       aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id);
 
        aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP);
 
@@ -646,8 +585,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8580_write(codec, WM8580_PAIF1 + codec_dai->id, aifa);
-       wm8580_write(codec, WM8580_PAIF3 + codec_dai->id, aifb);
+       snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa);
+       snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb);
 
        return 0;
 }
@@ -660,7 +599,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
 
        switch (div_id) {
        case WM8580_MCLK:
-               reg = wm8580_read(codec, WM8580_PLLB4);
+               reg = snd_soc_read(codec, WM8580_PLLB4);
                reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK;
 
                switch (div) {
@@ -682,11 +621,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
                default:
                        return -EINVAL;
                }
-               wm8580_write(codec, WM8580_PLLB4, reg);
+               snd_soc_write(codec, WM8580_PLLB4, reg);
                break;
 
        case WM8580_DAC_CLKSEL:
-               reg = wm8580_read(codec, WM8580_CLKSEL);
+               reg = snd_soc_read(codec, WM8580_CLKSEL);
                reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK;
 
                switch (div) {
@@ -704,11 +643,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
                default:
                        return -EINVAL;
                }
-               wm8580_write(codec, WM8580_CLKSEL, reg);
+               snd_soc_write(codec, WM8580_CLKSEL, reg);
                break;
 
        case WM8580_CLKOUTSRC:
-               reg = wm8580_read(codec, WM8580_PLLB4);
+               reg = snd_soc_read(codec, WM8580_PLLB4);
                reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK;
 
                switch (div) {
@@ -730,7 +669,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
                default:
                        return -EINVAL;
                }
-               wm8580_write(codec, WM8580_PLLB4, reg);
+               snd_soc_write(codec, WM8580_PLLB4, reg);
                break;
 
        default:
@@ -745,14 +684,14 @@ static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
        struct snd_soc_codec *codec = codec_dai->codec;
        unsigned int reg;
 
-       reg = wm8580_read(codec, WM8580_DAC_CONTROL5);
+       reg = snd_soc_read(codec, WM8580_DAC_CONTROL5);
 
        if (mute)
                reg |= WM8580_DAC_CONTROL5_MUTEALL;
        else
                reg &= ~WM8580_DAC_CONTROL5_MUTEALL;
 
-       wm8580_write(codec, WM8580_DAC_CONTROL5, reg);
+       snd_soc_write(codec, WM8580_DAC_CONTROL5, reg);
 
        return 0;
 }
@@ -769,20 +708,20 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_STANDBY:
                if (codec->bias_level == SND_SOC_BIAS_OFF) {
                        /* Power up and get individual control of the DACs */
-                       reg = wm8580_read(codec, WM8580_PWRDN1);
+                       reg = snd_soc_read(codec, WM8580_PWRDN1);
                        reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD);
-                       wm8580_write(codec, WM8580_PWRDN1, reg);
+                       snd_soc_write(codec, WM8580_PWRDN1, reg);
 
                        /* Make VMID high impedence */
-                       reg = wm8580_read(codec,  WM8580_ADC_CONTROL1);
+                       reg = snd_soc_read(codec,  WM8580_ADC_CONTROL1);
                        reg &= ~0x100;
-                       wm8580_write(codec, WM8580_ADC_CONTROL1, reg);
+                       snd_soc_write(codec, WM8580_ADC_CONTROL1, reg);
                }
                break;
 
        case SND_SOC_BIAS_OFF:
-               reg = wm8580_read(codec, WM8580_PWRDN1);
-               wm8580_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
+               reg = snd_soc_read(codec, WM8580_PWRDN1);
+               snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
                break;
        }
        codec->bias_level = level;
@@ -893,7 +832,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8580 = {
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
 
-static int wm8580_register(struct wm8580_priv *wm8580)
+static int wm8580_register(struct wm8580_priv *wm8580,
+                          enum snd_soc_control_type control)
 {
        int ret, i;
        struct snd_soc_codec *codec = &wm8580->codec;
@@ -911,8 +851,6 @@ static int wm8580_register(struct wm8580_priv *wm8580)
        codec->private_data = wm8580;
        codec->name = "WM8580";
        codec->owner = THIS_MODULE;
-       codec->read = wm8580_read_reg_cache;
-       codec->write = wm8580_write;
        codec->bias_level = SND_SOC_BIAS_OFF;
        codec->set_bias_level = wm8580_set_bias_level;
        codec->dai = wm8580_dai;
@@ -922,11 +860,34 @@ static int wm8580_register(struct wm8580_priv *wm8580)
 
        memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg));
 
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++)
+               wm8580->supplies[i].supply = wm8580_supply_names[i];
+
+       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies),
+                                wm8580->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+               goto err;
+       }
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies),
+                                   wm8580->supplies);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+               goto err_regulator_get;
+       }
+
        /* Get the codec into a known state */
-       ret = wm8580_write(codec, WM8580_RESET, 0);
+       ret = snd_soc_write(codec, WM8580_RESET, 0);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to reset codec: %d\n", ret);
-               goto err;
+               goto err_regulator_enable;
        }
 
        for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++)
@@ -939,7 +900,7 @@ static int wm8580_register(struct wm8580_priv *wm8580)
        ret = snd_soc_register_codec(codec);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               goto err;
+               goto err_regulator_enable;
        }
 
        ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
@@ -952,6 +913,10 @@ static int wm8580_register(struct wm8580_priv *wm8580)
 
 err_codec:
        snd_soc_unregister_codec(codec);
+err_regulator_enable:
+       regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
+err_regulator_get:
+       regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
 err:
        kfree(wm8580);
        return ret;
@@ -962,6 +927,8 @@ static void wm8580_unregister(struct wm8580_priv *wm8580)
        wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF);
        snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
        snd_soc_unregister_codec(&wm8580->codec);
+       regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
+       regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
        kfree(wm8580);
        wm8580_codec = NULL;
 }
@@ -978,14 +945,13 @@ static int wm8580_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        codec = &wm8580->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
 
        i2c_set_clientdata(i2c, wm8580);
        codec->control_data = i2c;
 
        codec->dev = &i2c->dev;
 
-       return wm8580_register(wm8580);
+       return wm8580_register(wm8580, SND_SOC_I2C);
 }
 
 static int wm8580_i2c_remove(struct i2c_client *client)
@@ -995,6 +961,21 @@ static int wm8580_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm8580_i2c_suspend(struct i2c_client *client, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&client->dev);
+}
+
+static int wm8580_i2c_resume(struct i2c_client *client)
+{
+       return snd_soc_resume_device(&client->dev);
+}
+#else
+#define wm8580_i2c_suspend NULL
+#define wm8580_i2c_resume NULL
+#endif
+
 static const struct i2c_device_id wm8580_i2c_id[] = {
        { "wm8580", 0 },
        { }
@@ -1008,6 +989,8 @@ static struct i2c_driver wm8580_i2c_driver = {
        },
        .probe =    wm8580_i2c_probe,
        .remove =   wm8580_i2c_remove,
+       .suspend =  wm8580_i2c_suspend,
+       .resume =   wm8580_i2c_resume,
        .id_table = wm8580_i2c_id,
 };
 #endif
index e7ff2121ede9b7b4781eecf9ead866db3afbd289..16e969a762c3934bd9af11b5e240a0f5aa1f0b75 100644 (file)
@@ -43,45 +43,6 @@ static const u16 wm8728_reg_defaults[] = {
        0x100,
 };
 
-static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults));
-       return cache[reg];
-}
-
-static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec,
-       u16 reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-       BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults));
-       cache[reg] = value;
-}
-
-/*
- * write to the WM8728 register space
- */
-static int wm8728_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
-{
-       u8 data[2];
-
-       /* data is
-        *   D15..D9 WM8728 register offset
-        *   D8...D0 register data
-        */
-       data[0] = (reg << 1) | ((value >> 8) & 0x0001);
-       data[1] = value & 0x00ff;
-
-       wm8728_write_reg_cache(codec, reg, value);
-
-       if (codec->hw_write(codec->control_data, data, 2) == 2)
-               return 0;
-       else
-               return -EIO;
-}
-
 static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1);
 
 static const struct snd_kcontrol_new wm8728_snd_controls[] = {
@@ -121,12 +82,12 @@ static int wm8728_add_widgets(struct snd_soc_codec *codec)
 static int wm8728_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u16 mute_reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
+       u16 mute_reg = snd_soc_read(codec, WM8728_DACCTL);
 
        if (mute)
-               wm8728_write(codec, WM8728_DACCTL, mute_reg | 1);
+               snd_soc_write(codec, WM8728_DACCTL, mute_reg | 1);
        else
-               wm8728_write(codec, WM8728_DACCTL, mute_reg & ~1);
+               snd_soc_write(codec, WM8728_DACCTL, mute_reg & ~1);
 
        return 0;
 }
@@ -138,7 +99,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->card->codec;
-       u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL);
+       u16 dac = snd_soc_read(codec, WM8728_DACCTL);
 
        dac &= ~0x18;
 
@@ -155,7 +116,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       wm8728_write(codec, WM8728_DACCTL, dac);
+       snd_soc_write(codec, WM8728_DACCTL, dac);
 
        return 0;
 }
@@ -164,7 +125,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
-       u16 iface = wm8728_read_reg_cache(codec, WM8728_IFCTL);
+       u16 iface = snd_soc_read(codec, WM8728_IFCTL);
 
        /* Currently only I2S is supported by the driver, though the
         * hardware is more flexible.
@@ -204,7 +165,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8728_write(codec, WM8728_IFCTL, iface);
+       snd_soc_write(codec, WM8728_IFCTL, iface);
        return 0;
 }
 
@@ -220,19 +181,19 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec,
        case SND_SOC_BIAS_STANDBY:
                if (codec->bias_level == SND_SOC_BIAS_OFF) {
                        /* Power everything up... */
-                       reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
-                       wm8728_write(codec, WM8728_DACCTL, reg & ~0x4);
+                       reg = snd_soc_read(codec, WM8728_DACCTL);
+                       snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4);
 
                        /* ..then sync in the register cache. */
                        for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++)
-                               wm8728_write(codec, i,
-                                            wm8728_read_reg_cache(codec, i));
+                               snd_soc_write(codec, i,
+                                            snd_soc_read(codec, i));
                }
                break;
 
        case SND_SOC_BIAS_OFF:
-               reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
-               wm8728_write(codec, WM8728_DACCTL, reg | 0x4);
+               reg = snd_soc_read(codec, WM8728_DACCTL);
+               snd_soc_write(codec, WM8728_DACCTL, reg | 0x4);
                break;
        }
        codec->bias_level = level;
@@ -287,15 +248,14 @@ static int wm8728_resume(struct platform_device *pdev)
  * initialise the WM8728 driver
  * register the mixer and dsp interfaces with the kernel
  */
-static int wm8728_init(struct snd_soc_device *socdev)
+static int wm8728_init(struct snd_soc_device *socdev,
+                      enum snd_soc_control_type control)
 {
        struct snd_soc_codec *codec = socdev->card->codec;
        int ret = 0;
 
        codec->name = "WM8728";
        codec->owner = THIS_MODULE;
-       codec->read = wm8728_read_reg_cache;
-       codec->write = wm8728_write;
        codec->set_bias_level = wm8728_set_bias_level;
        codec->dai = &wm8728_dai;
        codec->num_dai = 1;
@@ -307,11 +267,18 @@ static int wm8728_init(struct snd_soc_device *socdev)
        if (codec->reg_cache == NULL)
                return -ENOMEM;
 
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       if (ret < 0) {
+               printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n",
+                      ret);
+               goto err;
+       }
+
        /* register pcms */
        ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
        if (ret < 0) {
                printk(KERN_ERR "wm8728: failed to create pcms\n");
-               goto pcm_err;
+               goto err;
        }
 
        /* power on device */
@@ -331,7 +298,7 @@ static int wm8728_init(struct snd_soc_device *socdev)
 card_err:
        snd_soc_free_pcms(socdev);
        snd_soc_dapm_free(socdev);
-pcm_err:
+err:
        kfree(codec->reg_cache);
        return ret;
 }
@@ -357,7 +324,7 @@ static int wm8728_i2c_probe(struct i2c_client *i2c,
        i2c_set_clientdata(i2c, codec);
        codec->control_data = i2c;
 
-       ret = wm8728_init(socdev);
+       ret = wm8728_init(socdev, SND_SOC_I2C);
        if (ret < 0)
                pr_err("failed to initialise WM8728\n");
 
@@ -437,7 +404,7 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi)
 
        codec->control_data = spi;
 
-       ret = wm8728_init(socdev);
+       ret = wm8728_init(socdev, SND_SOC_SPI);
        if (ret < 0)
                dev_err(&spi->dev, "failed to initialise WM8728\n");
 
@@ -458,30 +425,6 @@ static struct spi_driver wm8728_spi_driver = {
        .probe          = wm8728_spi_probe,
        .remove         = __devexit_p(wm8728_spi_remove),
 };
-
-static int wm8728_spi_write(struct spi_device *spi, const char *data, int len)
-{
-       struct spi_transfer t;
-       struct spi_message m;
-       u8 msg[2];
-
-       if (len <= 0)
-               return 0;
-
-       msg[0] = data[0];
-       msg[1] = data[1];
-
-       spi_message_init(&m);
-       memset(&t, 0, (sizeof t));
-
-       t.tx_buf = &msg[0];
-       t.len = len;
-
-       spi_message_add_tail(&t, &m);
-       spi_sync(spi, &m);
-
-       return len;
-}
 #endif /* CONFIG_SPI_MASTER */
 
 static int wm8728_probe(struct platform_device *pdev)
@@ -506,13 +449,11 @@ static int wm8728_probe(struct platform_device *pdev)
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        if (setup->i2c_address) {
-               codec->hw_write = (hw_write_t)i2c_master_send;
                ret = wm8728_add_i2c_device(pdev, setup);
        }
 #endif
 #if defined(CONFIG_SPI_MASTER)
        if (setup->spi) {
-               codec->hw_write = (hw_write_t)wm8728_spi_write;
                ret = spi_register_driver(&wm8728_spi_driver);
                if (ret != 0)
                        printk(KERN_ERR "can't add spi driver");
index 7a205876ef4f0dc4e0982855694c62f2ea5e4def..d3fd4f28d96eebd48edee92abdca17fe7f406ac6 100644 (file)
@@ -26,6 +26,7 @@
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
 #include <sound/initval.h>
+#include <sound/tlv.h>
 
 #include "wm8731.h"
 
@@ -39,9 +40,6 @@ struct wm8731_priv {
        unsigned int sysclk;
 };
 
-#ifdef CONFIG_SPI_MASTER
-static int wm8731_spi_write(struct spi_device *spi, const char *data, int len);
-#endif
 
 /*
  * wm8731 register cache
@@ -50,60 +48,12 @@ static int wm8731_spi_write(struct spi_device *spi, const char *data, int len);
  * There is no point in caching the reset register
  */
 static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
-    0x0097, 0x0097, 0x0079, 0x0079,
-    0x000a, 0x0008, 0x009f, 0x000a,
-    0x0000, 0x0000
+       0x0097, 0x0097, 0x0079, 0x0079,
+       0x000a, 0x0008, 0x009f, 0x000a,
+       0x0000, 0x0000
 };
 
-/*
- * read wm8731 register cache
- */
-static inline unsigned int wm8731_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg == WM8731_RESET)
-               return 0;
-       if (reg >= WM8731_CACHEREGNUM)
-               return -1;
-       return cache[reg];
-}
-
-/*
- * write wm8731 register cache
- */
-static inline void wm8731_write_reg_cache(struct snd_soc_codec *codec,
-       u16 reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg >= WM8731_CACHEREGNUM)
-               return;
-       cache[reg] = value;
-}
-
-/*
- * write to the WM8731 register space
- */
-static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
-{
-       u8 data[2];
-
-       /* data is
-        *   D15..D9 WM8731 register offset
-        *   D8...D0 register data
-        */
-       data[0] = (reg << 1) | ((value >> 8) & 0x0001);
-       data[1] = value & 0x00ff;
-
-       wm8731_write_reg_cache(codec, reg, value);
-       if (codec->hw_write(codec->control_data, data, 2) == 2)
-               return 0;
-       else
-               return -EIO;
-}
-
-#define wm8731_reset(c)        wm8731_write(c, WM8731_RESET, 0)
+#define wm8731_reset(c)        snd_soc_write(c, WM8731_RESET, 0)
 
 static const char *wm8731_input_select[] = {"Line In", "Mic"};
 static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
@@ -113,20 +63,26 @@ static const struct soc_enum wm8731_enum[] = {
        SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph),
 };
 
+static const DECLARE_TLV_DB_SCALE(in_tlv, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -1500, 300, 0);
+static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
+
 static const struct snd_kcontrol_new wm8731_snd_controls[] = {
 
-SOC_DOUBLE_R("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V,
-       0, 127, 0),
+SOC_DOUBLE_R_TLV("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V,
+                0, 127, 0, out_tlv),
 SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V,
        7, 1, 0),
 
-SOC_DOUBLE_R("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0),
+SOC_DOUBLE_R_TLV("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0,
+                in_tlv),
 SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1),
 
 SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0),
-SOC_SINGLE("Capture Mic Switch", WM8731_APANA, 1, 1, 1),
+SOC_SINGLE("Mic Capture Switch", WM8731_APANA, 1, 1, 1),
 
-SOC_SINGLE("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1),
+SOC_SINGLE_TLV("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1,
+              sidetone_tlv),
 
 SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1),
 SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0),
@@ -260,12 +216,12 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->card->codec;
        struct wm8731_priv *wm8731 = codec->private_data;
-       u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3;
+       u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3;
        int i = get_coeff(wm8731->sysclk, params_rate(params));
        u16 srate = (coeff_div[i].sr << 2) |
                (coeff_div[i].bosr << 1) | coeff_div[i].usb;
 
-       wm8731_write(codec, WM8731_SRATE, srate);
+       snd_soc_write(codec, WM8731_SRATE, srate);
 
        /* bit size */
        switch (params_format(params)) {
@@ -279,7 +235,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
                break;
        }
 
-       wm8731_write(codec, WM8731_IFACE, iface);
+       snd_soc_write(codec, WM8731_IFACE, iface);
        return 0;
 }
 
@@ -291,7 +247,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
        struct snd_soc_codec *codec = socdev->card->codec;
 
        /* set active */
-       wm8731_write(codec, WM8731_ACTIVE, 0x0001);
+       snd_soc_write(codec, WM8731_ACTIVE, 0x0001);
 
        return 0;
 }
@@ -306,19 +262,19 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream,
        /* deactivate */
        if (!codec->active) {
                udelay(50);
-               wm8731_write(codec, WM8731_ACTIVE, 0x0);
+               snd_soc_write(codec, WM8731_ACTIVE, 0x0);
        }
 }
 
 static int wm8731_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7;
+       u16 mute_reg = snd_soc_read(codec, WM8731_APDIGI) & 0xfff7;
 
        if (mute)
-               wm8731_write(codec, WM8731_APDIGI, mute_reg | 0x8);
+               snd_soc_write(codec, WM8731_APDIGI, mute_reg | 0x8);
        else
-               wm8731_write(codec, WM8731_APDIGI, mute_reg);
+               snd_soc_write(codec, WM8731_APDIGI, mute_reg);
        return 0;
 }
 
@@ -396,7 +352,7 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai,
        }
 
        /* set iface */
-       wm8731_write(codec, WM8731_IFACE, iface);
+       snd_soc_write(codec, WM8731_IFACE, iface);
        return 0;
 }
 
@@ -412,12 +368,12 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
                break;
        case SND_SOC_BIAS_STANDBY:
                /* Clear PWROFF, gate CLKOUT, everything else as-is */
-               reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f;
-               wm8731_write(codec, WM8731_PWR, reg | 0x0040);
+               reg = snd_soc_read(codec, WM8731_PWR) & 0xff7f;
+               snd_soc_write(codec, WM8731_PWR, reg | 0x0040);
                break;
        case SND_SOC_BIAS_OFF:
-               wm8731_write(codec, WM8731_ACTIVE, 0x0);
-               wm8731_write(codec, WM8731_PWR, 0xffff);
+               snd_soc_write(codec, WM8731_ACTIVE, 0x0);
+               snd_soc_write(codec, WM8731_PWR, 0xffff);
                break;
        }
        codec->bias_level = level;
@@ -457,15 +413,17 @@ struct snd_soc_dai wm8731_dai = {
                .rates = WM8731_RATES,
                .formats = WM8731_FORMATS,},
        .ops = &wm8731_dai_ops,
+       .symmetric_rates = 1,
 };
 EXPORT_SYMBOL_GPL(wm8731_dai);
 
+#ifdef CONFIG_PM
 static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
 {
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_codec *codec = socdev->card->codec;
 
-       wm8731_write(codec, WM8731_ACTIVE, 0x0);
+       snd_soc_write(codec, WM8731_ACTIVE, 0x0);
        wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
        return 0;
 }
@@ -488,6 +446,10 @@ static int wm8731_resume(struct platform_device *pdev)
        wm8731_set_bias_level(codec, codec->suspend_bias_level);
        return 0;
 }
+#else
+#define wm8731_suspend NULL
+#define wm8731_resume NULL
+#endif
 
 static int wm8731_probe(struct platform_device *pdev)
 {
@@ -547,15 +509,16 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = {
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
 
-static int wm8731_register(struct wm8731_priv *wm8731)
+static int wm8731_register(struct wm8731_priv *wm8731,
+                          enum snd_soc_control_type control)
 {
        int ret;
        struct snd_soc_codec *codec = &wm8731->codec;
-       u16 reg;
 
        if (wm8731_codec) {
                dev_err(codec->dev, "Another WM8731 is registered\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err;
        }
 
        mutex_init(&codec->mutex);
@@ -565,8 +528,6 @@ static int wm8731_register(struct wm8731_priv *wm8731)
        codec->private_data = wm8731;
        codec->name = "WM8731";
        codec->owner = THIS_MODULE;
-       codec->read = wm8731_read_reg_cache;
-       codec->write = wm8731_write;
        codec->bias_level = SND_SOC_BIAS_OFF;
        codec->set_bias_level = wm8731_set_bias_level;
        codec->dai = &wm8731_dai;
@@ -576,10 +537,16 @@ static int wm8731_register(struct wm8731_priv *wm8731)
 
        memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg));
 
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
        ret = wm8731_reset(codec);
        if (ret < 0) {
-               dev_err(codec->dev, "Failed to issue reset\n");
-               return ret;
+               dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
+               goto err;
        }
 
        wm8731_dai.dev = codec->dev;
@@ -587,35 +554,36 @@ static int wm8731_register(struct wm8731_priv *wm8731)
        wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Latch the update bits */
-       reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V);
-       wm8731_write(codec, WM8731_LOUT1V, reg & ~0x0100);
-       reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V);
-       wm8731_write(codec, WM8731_ROUT1V, reg & ~0x0100);
-       reg = wm8731_read_reg_cache(codec, WM8731_LINVOL);
-       wm8731_write(codec, WM8731_LINVOL, reg & ~0x0100);
-       reg = wm8731_read_reg_cache(codec, WM8731_RINVOL);
-       wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100);
+       snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0);
+       snd_soc_update_bits(codec, WM8731_ROUT1V, 0x100, 0);
+       snd_soc_update_bits(codec, WM8731_LINVOL, 0x100, 0);
+       snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0);
 
        /* Disable bypass path by default */
-       reg = wm8731_read_reg_cache(codec, WM8731_APANA);
-       wm8731_write(codec, WM8731_APANA, reg & ~0x4);
+       snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0);
 
        wm8731_codec = codec;
 
        ret = snd_soc_register_codec(codec);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               return ret;
+               goto err;
        }
 
        ret = snd_soc_register_dai(&wm8731_dai);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
                snd_soc_unregister_codec(codec);
-               return ret;
+               goto err_codec;
        }
 
        return 0;
+
+err_codec:
+       snd_soc_unregister_codec(codec);
+err:
+       kfree(wm8731);
+       return ret;
 }
 
 static void wm8731_unregister(struct wm8731_priv *wm8731)
@@ -628,30 +596,6 @@ static void wm8731_unregister(struct wm8731_priv *wm8731)
 }
 
 #if defined(CONFIG_SPI_MASTER)
-static int wm8731_spi_write(struct spi_device *spi, const char *data, int len)
-{
-       struct spi_transfer t;
-       struct spi_message m;
-       u8 msg[2];
-
-       if (len <= 0)
-               return 0;
-
-       msg[0] = data[0];
-       msg[1] = data[1];
-
-       spi_message_init(&m);
-       memset(&t, 0, (sizeof t));
-
-       t.tx_buf = &msg[0];
-       t.len = len;
-
-       spi_message_add_tail(&t, &m);
-       spi_sync(spi, &m);
-
-       return len;
-}
-
 static int __devinit wm8731_spi_probe(struct spi_device *spi)
 {
        struct snd_soc_codec *codec;
@@ -663,12 +607,11 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
 
        codec = &wm8731->codec;
        codec->control_data = spi;
-       codec->hw_write = (hw_write_t)wm8731_spi_write;
        codec->dev = &spi->dev;
 
        dev_set_drvdata(&spi->dev, wm8731);
 
-       return wm8731_register(wm8731);
+       return wm8731_register(wm8731, SND_SOC_SPI);
 }
 
 static int __devexit wm8731_spi_remove(struct spi_device *spi)
@@ -680,6 +623,21 @@ static int __devexit wm8731_spi_remove(struct spi_device *spi)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm8731_spi_suspend(struct spi_device *spi, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&spi->dev);
+}
+
+static int wm8731_spi_resume(struct spi_device *spi)
+{
+       return snd_soc_resume_device(&spi->dev);
+}
+#else
+#define wm8731_spi_suspend NULL
+#define wm8731_spi_resume NULL
+#endif
+
 static struct spi_driver wm8731_spi_driver = {
        .driver = {
                .name   = "wm8731",
@@ -687,6 +645,8 @@ static struct spi_driver wm8731_spi_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = wm8731_spi_probe,
+       .suspend        = wm8731_spi_suspend,
+       .resume         = wm8731_spi_resume,
        .remove         = __devexit_p(wm8731_spi_remove),
 };
 #endif /* CONFIG_SPI_MASTER */
@@ -703,14 +663,13 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        codec = &wm8731->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
 
        i2c_set_clientdata(i2c, wm8731);
        codec->control_data = i2c;
 
        codec->dev = &i2c->dev;
 
-       return wm8731_register(wm8731);
+       return wm8731_register(wm8731, SND_SOC_I2C);
 }
 
 static __devexit int wm8731_i2c_remove(struct i2c_client *client)
@@ -720,6 +679,21 @@ static __devexit int wm8731_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm8731_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&i2c->dev);
+}
+
+static int wm8731_i2c_resume(struct i2c_client *i2c)
+{
+       return snd_soc_resume_device(&i2c->dev);
+}
+#else
+#define wm8731_i2c_suspend NULL
+#define wm8731_i2c_resume NULL
+#endif
+
 static const struct i2c_device_id wm8731_i2c_id[] = {
        { "wm8731", 0 },
        { }
@@ -733,6 +707,8 @@ static struct i2c_driver wm8731_i2c_driver = {
        },
        .probe =    wm8731_i2c_probe,
        .remove =   __devexit_p(wm8731_i2c_remove),
+       .suspend =  wm8731_i2c_suspend,
+       .resume =   wm8731_i2c_resume,
        .id_table = wm8731_i2c_id,
 };
 #endif
index b64509b01a49645f847d91fbcf1f051e1248f53b..4ba1e7e93fb4dbfc99cb28e04e7baa82318102f3 100644 (file)
@@ -55,50 +55,7 @@ static const u16 wm8750_reg[] = {
        0x0079, 0x0079, 0x0079,          /* 40 */
 };
 
-/*
- * read wm8750 register cache
- */
-static inline unsigned int wm8750_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg > WM8750_CACHE_REGNUM)
-               return -1;
-       return cache[reg];
-}
-
-/*
- * write wm8750 register cache
- */
-static inline void wm8750_write_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg > WM8750_CACHE_REGNUM)
-               return;
-       cache[reg] = value;
-}
-
-static int wm8750_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
-{
-       u8 data[2];
-
-       /* data is
-        *   D15..D9 WM8753 register offset
-        *   D8...D0 register data
-        */
-       data[0] = (reg << 1) | ((value >> 8) & 0x0001);
-       data[1] = value & 0x00ff;
-
-       wm8750_write_reg_cache(codec, reg, value);
-       if (codec->hw_write(codec->control_data, data, 2) == 2)
-               return 0;
-       else
-               return -EIO;
-}
-
-#define wm8750_reset(c)        wm8750_write(c, WM8750_RESET, 0)
+#define wm8750_reset(c)        snd_soc_write(c, WM8750_RESET, 0)
 
 /*
  * WM8750 Controls
@@ -594,7 +551,7 @@ static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8750_write(codec, WM8750_IFACE, iface);
+       snd_soc_write(codec, WM8750_IFACE, iface);
        return 0;
 }
 
@@ -606,8 +563,8 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->card->codec;
        struct wm8750_priv *wm8750 = codec->private_data;
-       u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3;
-       u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0;
+       u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3;
+       u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0;
        int coeff = get_coeff(wm8750->sysclk, params_rate(params));
 
        /* bit size */
@@ -626,9 +583,9 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
        }
 
        /* set iface & srate */
-       wm8750_write(codec, WM8750_IFACE, iface);
+       snd_soc_write(codec, WM8750_IFACE, iface);
        if (coeff >= 0)
-               wm8750_write(codec, WM8750_SRATE, srate |
+               snd_soc_write(codec, WM8750_SRATE, srate |
                        (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
 
        return 0;
@@ -637,35 +594,35 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
 static int wm8750_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u16 mute_reg = wm8750_read_reg_cache(codec, WM8750_ADCDAC) & 0xfff7;
+       u16 mute_reg = snd_soc_read(codec, WM8750_ADCDAC) & 0xfff7;
 
        if (mute)
-               wm8750_write(codec, WM8750_ADCDAC, mute_reg | 0x8);
+               snd_soc_write(codec, WM8750_ADCDAC, mute_reg | 0x8);
        else
-               wm8750_write(codec, WM8750_ADCDAC, mute_reg);
+               snd_soc_write(codec, WM8750_ADCDAC, mute_reg);
        return 0;
 }
 
 static int wm8750_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
-       u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3e;
+       u16 pwr_reg = snd_soc_read(codec, WM8750_PWR1) & 0xfe3e;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
                /* set vmid to 50k and unmute dac */
-               wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
+               snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
                break;
        case SND_SOC_BIAS_PREPARE:
                /* set vmid to 5k for quick power up */
-               wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
+               snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
                break;
        case SND_SOC_BIAS_STANDBY:
                /* mute dac and set vmid to 500k, enable VREF */
-               wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0141);
+               snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141);
                break;
        case SND_SOC_BIAS_OFF:
-               wm8750_write(codec, WM8750_PWR1, 0x0001);
+               snd_soc_write(codec, WM8750_PWR1, 0x0001);
                break;
        }
        codec->bias_level = level;
@@ -754,15 +711,14 @@ static int wm8750_resume(struct platform_device *pdev)
  * initialise the WM8750 driver
  * register the mixer and dsp interfaces with the kernel
  */
-static int wm8750_init(struct snd_soc_device *socdev)
+static int wm8750_init(struct snd_soc_device *socdev,
+                      enum snd_soc_control_type control)
 {
        struct snd_soc_codec *codec = socdev->card->codec;
        int reg, ret = 0;
 
        codec->name = "WM8750";
        codec->owner = THIS_MODULE;
-       codec->read = wm8750_read_reg_cache;
-       codec->write = wm8750_write;
        codec->set_bias_level = wm8750_set_bias_level;
        codec->dai = &wm8750_dai;
        codec->num_dai = 1;
@@ -771,13 +727,23 @@ static int wm8750_init(struct snd_soc_device *socdev)
        if (codec->reg_cache == NULL)
                return -ENOMEM;
 
-       wm8750_reset(codec);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       if (ret < 0) {
+               printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
+       ret = wm8750_reset(codec);
+       if (ret < 0) {
+               printk(KERN_ERR "wm8750: failed to reset: %d\n", ret);
+               goto err;
+       }
 
        /* register pcms */
        ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
        if (ret < 0) {
                printk(KERN_ERR "wm8750: failed to create pcms\n");
-               goto pcm_err;
+               goto err;
        }
 
        /* charge output caps */
@@ -786,22 +752,22 @@ static int wm8750_init(struct snd_soc_device *socdev)
        schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
 
        /* set the update bits */
-       reg = wm8750_read_reg_cache(codec, WM8750_LDAC);
-       wm8750_write(codec, WM8750_LDAC, reg | 0x0100);
-       reg = wm8750_read_reg_cache(codec, WM8750_RDAC);
-       wm8750_write(codec, WM8750_RDAC, reg | 0x0100);
-       reg = wm8750_read_reg_cache(codec, WM8750_LOUT1V);
-       wm8750_write(codec, WM8750_LOUT1V, reg | 0x0100);
-       reg = wm8750_read_reg_cache(codec, WM8750_ROUT1V);
-       wm8750_write(codec, WM8750_ROUT1V, reg | 0x0100);
-       reg = wm8750_read_reg_cache(codec, WM8750_LOUT2V);
-       wm8750_write(codec, WM8750_LOUT2V, reg | 0x0100);
-       reg = wm8750_read_reg_cache(codec, WM8750_ROUT2V);
-       wm8750_write(codec, WM8750_ROUT2V, reg | 0x0100);
-       reg = wm8750_read_reg_cache(codec, WM8750_LINVOL);
-       wm8750_write(codec, WM8750_LINVOL, reg | 0x0100);
-       reg = wm8750_read_reg_cache(codec, WM8750_RINVOL);
-       wm8750_write(codec, WM8750_RINVOL, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8750_LDAC);
+       snd_soc_write(codec, WM8750_LDAC, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8750_RDAC);
+       snd_soc_write(codec, WM8750_RDAC, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8750_LOUT1V);
+       snd_soc_write(codec, WM8750_LOUT1V, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8750_ROUT1V);
+       snd_soc_write(codec, WM8750_ROUT1V, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8750_LOUT2V);
+       snd_soc_write(codec, WM8750_LOUT2V, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8750_ROUT2V);
+       snd_soc_write(codec, WM8750_ROUT2V, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8750_LINVOL);
+       snd_soc_write(codec, WM8750_LINVOL, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8750_RINVOL);
+       snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100);
 
        snd_soc_add_controls(codec, wm8750_snd_controls,
                                ARRAY_SIZE(wm8750_snd_controls));
@@ -816,7 +782,7 @@ static int wm8750_init(struct snd_soc_device *socdev)
 card_err:
        snd_soc_free_pcms(socdev);
        snd_soc_dapm_free(socdev);
-pcm_err:
+err:
        kfree(codec->reg_cache);
        return ret;
 }
@@ -844,7 +810,7 @@ static int wm8750_i2c_probe(struct i2c_client *i2c,
        i2c_set_clientdata(i2c, codec);
        codec->control_data = i2c;
 
-       ret = wm8750_init(socdev);
+       ret = wm8750_init(socdev, SND_SOC_I2C);
        if (ret < 0)
                pr_err("failed to initialise WM8750\n");
 
@@ -924,7 +890,7 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
 
        codec->control_data = spi;
 
-       ret = wm8750_init(socdev);
+       ret = wm8750_init(socdev, SND_SOC_SPI);
        if (ret < 0)
                dev_err(&spi->dev, "failed to initialise WM8750\n");
 
@@ -945,30 +911,6 @@ static struct spi_driver wm8750_spi_driver = {
        .probe          = wm8750_spi_probe,
        .remove         = __devexit_p(wm8750_spi_remove),
 };
-
-static int wm8750_spi_write(struct spi_device *spi, const char *data, int len)
-{
-       struct spi_transfer t;
-       struct spi_message m;
-       u8 msg[2];
-
-       if (len <= 0)
-               return 0;
-
-       msg[0] = data[0];
-       msg[1] = data[1];
-
-       spi_message_init(&m);
-       memset(&t, 0, (sizeof t));
-
-       t.tx_buf = &msg[0];
-       t.len = len;
-
-       spi_message_add_tail(&t, &m);
-       spi_sync(spi, &m);
-
-       return len;
-}
 #endif
 
 static int wm8750_probe(struct platform_device *pdev)
@@ -1002,13 +944,11 @@ static int wm8750_probe(struct platform_device *pdev)
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        if (setup->i2c_address) {
-               codec->hw_write = (hw_write_t)i2c_master_send;
                ret = wm8750_add_i2c_device(pdev, setup);
        }
 #endif
 #if defined(CONFIG_SPI_MASTER)
        if (setup->spi) {
-               codec->hw_write = (hw_write_t)wm8750_spi_write;
                ret = spi_register_driver(&wm8750_spi_driver);
                if (ret != 0)
                        printk(KERN_ERR "can't add spi driver");
index d28eeaceb8573a504f3c7c5471f9f2f296c5618c..5ad677ce80da46baa8789c2d3072c3205474bb2b 100644 (file)
@@ -79,7 +79,7 @@ static const u16 wm8753_reg[] = {
        0x0097, 0x0097, 0x0000, 0x0004,
        0x0000, 0x0083, 0x0024, 0x01ba,
        0x0000, 0x0083, 0x0024, 0x01ba,
-       0x0000, 0x0000
+       0x0000, 0x0000, 0x0000
 };
 
 /* codec private data */
@@ -595,6 +595,7 @@ static const struct snd_soc_dapm_route audio_map[] = {
 
        /* Mono Capture mixer-mux */
        {"Capture Right Mixer", "Stereo", "Capture Right Mux"},
+       {"Capture Left Mixer", "Stereo", "Capture Left Mux"},
        {"Capture Left Mixer", "Analogue Mix Left", "Capture Left Mux"},
        {"Capture Left Mixer", "Analogue Mix Left", "Capture Right Mux"},
        {"Capture Right Mixer", "Analogue Mix Right", "Capture Left Mux"},
@@ -1660,11 +1661,11 @@ static int wm8753_register(struct wm8753_priv *wm8753)
        codec->set_bias_level = wm8753_set_bias_level;
        codec->dai = wm8753_dai;
        codec->num_dai = 2;
-       codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache);
+       codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache) + 1;
        codec->reg_cache = &wm8753->reg_cache;
        codec->private_data = wm8753;
 
-       memcpy(codec->reg_cache, wm8753_reg, sizeof(codec->reg_cache));
+       memcpy(codec->reg_cache, wm8753_reg, sizeof(wm8753->reg_cache));
        INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
 
        ret = wm8753_reset(codec);
@@ -1766,6 +1767,21 @@ static int wm8753_i2c_remove(struct i2c_client *client)
         return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm8753_i2c_suspend(struct i2c_client *client, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&client->dev);
+}
+
+static int wm8753_i2c_resume(struct i2c_client *client)
+{
+       return snd_soc_resume_device(&client->dev);
+}
+#else
+#define wm8753_i2c_suspend NULL
+#define wm8753_i2c_resume NULL
+#endif
+
 static const struct i2c_device_id wm8753_i2c_id[] = {
        { "wm8753", 0 },
        { }
@@ -1779,6 +1795,8 @@ static struct i2c_driver wm8753_i2c_driver = {
        },
        .probe =    wm8753_i2c_probe,
        .remove =   wm8753_i2c_remove,
+       .suspend =  wm8753_i2c_suspend,
+       .resume =   wm8753_i2c_resume,
        .id_table = wm8753_i2c_id,
 };
 #endif
@@ -1834,6 +1852,22 @@ static int __devexit wm8753_spi_remove(struct spi_device *spi)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm8753_spi_suspend(struct spi_device *spi, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&spi->dev);
+}
+
+static int wm8753_spi_resume(struct spi_device *spi)
+{
+       return snd_soc_resume_device(&spi->dev);
+}
+
+#else
+#define wm8753_spi_suspend NULL
+#define wm8753_spi_resume NULL
+#endif
+
 static struct spi_driver wm8753_spi_driver = {
        .driver = {
                .name   = "wm8753",
@@ -1842,6 +1876,8 @@ static struct spi_driver wm8753_spi_driver = {
        },
        .probe          = wm8753_spi_probe,
        .remove         = __devexit_p(wm8753_spi_remove),
+       .suspend        = wm8753_spi_suspend,
+       .resume         = wm8753_spi_resume,
 };
 #endif
 
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
new file mode 100644 (file)
index 0000000..a9829aa
--- /dev/null
@@ -0,0 +1,744 @@
+/*
+ * wm8776.c  --  WM8776 ALSA SoC Audio driver
+ *
+ * Copyright 2009 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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.
+ *
+ * TODO: Input ALC/limiter support
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8776.h"
+
+static struct snd_soc_codec *wm8776_codec;
+struct snd_soc_codec_device soc_codec_dev_wm8776;
+
+/* codec private data */
+struct wm8776_priv {
+       struct snd_soc_codec codec;
+       u16 reg_cache[WM8776_CACHEREGNUM];
+       int sysclk[2];
+};
+
+#ifdef CONFIG_SPI_MASTER
+static int wm8776_spi_write(struct spi_device *spi, const char *data, int len);
+#endif
+
+static const u16 wm8776_reg[WM8776_CACHEREGNUM] = {
+       0x79, 0x79, 0x79, 0xff, 0xff,  /* 4 */
+       0xff, 0x00, 0x90, 0x00, 0x00,  /* 9 */
+       0x22, 0x22, 0x22, 0x08, 0xcf,  /* 14 */
+       0xcf, 0x7b, 0x00, 0x32, 0x00,  /* 19 */
+       0xa6, 0x01, 0x01
+};
+
+static int wm8776_reset(struct snd_soc_codec *codec)
+{
+       return snd_soc_write(codec, WM8776_RESET, 0);
+}
+
+static const DECLARE_TLV_DB_SCALE(hp_tlv, -12100, 100, 1);
+static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -10350, 50, 1);
+
+static const struct snd_kcontrol_new wm8776_snd_controls[] = {
+SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8776_HPLVOL, WM8776_HPRVOL,
+                0, 127, 0, hp_tlv),
+SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8776_DACLVOL, WM8776_DACRVOL,
+                0, 255, 0, dac_tlv),
+SOC_SINGLE("Digital Playback ZC Switch", WM8776_DACCTRL1, 0, 1, 0),
+
+SOC_SINGLE("Deemphasis Switch", WM8776_DACCTRL2, 0, 1, 0),
+
+SOC_DOUBLE_R_TLV("Capture Volume", WM8776_ADCLVOL, WM8776_ADCRVOL,
+                0, 255, 0, adc_tlv),
+SOC_DOUBLE("Capture Switch", WM8776_ADCMUX, 7, 6, 1, 1),
+SOC_DOUBLE_R("Capture ZC Switch", WM8776_ADCLVOL, WM8776_ADCRVOL, 8, 1, 0),
+SOC_SINGLE("Capture HPF Switch", WM8776_ADCIFCTRL, 8, 1, 1),
+};
+
+static const struct snd_kcontrol_new inmix_controls[] = {
+SOC_DAPM_SINGLE("AIN1 Switch", WM8776_ADCMUX, 0, 1, 0),
+SOC_DAPM_SINGLE("AIN2 Switch", WM8776_ADCMUX, 1, 1, 0),
+SOC_DAPM_SINGLE("AIN3 Switch", WM8776_ADCMUX, 2, 1, 0),
+SOC_DAPM_SINGLE("AIN4 Switch", WM8776_ADCMUX, 3, 1, 0),
+SOC_DAPM_SINGLE("AIN5 Switch", WM8776_ADCMUX, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new outmix_controls[] = {
+SOC_DAPM_SINGLE("DAC Switch", WM8776_OUTMUX, 0, 1, 0),
+SOC_DAPM_SINGLE("AUX Switch", WM8776_OUTMUX, 1, 1, 0),
+SOC_DAPM_SINGLE("Bypass Switch", WM8776_OUTMUX, 2, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget wm8776_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("AUX"),
+SND_SOC_DAPM_INPUT("AUX"),
+
+SND_SOC_DAPM_INPUT("AIN1"),
+SND_SOC_DAPM_INPUT("AIN2"),
+SND_SOC_DAPM_INPUT("AIN3"),
+SND_SOC_DAPM_INPUT("AIN4"),
+SND_SOC_DAPM_INPUT("AIN5"),
+
+SND_SOC_DAPM_MIXER("Input Mixer", WM8776_PWRDOWN, 6, 1,
+                  inmix_controls, ARRAY_SIZE(inmix_controls)),
+
+SND_SOC_DAPM_ADC("ADC", "Capture", WM8776_PWRDOWN, 1, 1),
+SND_SOC_DAPM_DAC("DAC", "Playback", WM8776_PWRDOWN, 2, 1),
+
+SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0,
+                  outmix_controls, ARRAY_SIZE(outmix_controls)),
+
+SND_SOC_DAPM_PGA("Headphone PGA", WM8776_PWRDOWN, 3, 1, NULL, 0),
+
+SND_SOC_DAPM_OUTPUT("VOUT"),
+
+SND_SOC_DAPM_OUTPUT("HPOUTL"),
+SND_SOC_DAPM_OUTPUT("HPOUTR"),
+};
+
+static const struct snd_soc_dapm_route routes[] = {
+       { "Input Mixer", "AIN1 Switch", "AIN1" },
+       { "Input Mixer", "AIN2 Switch", "AIN2" },
+       { "Input Mixer", "AIN3 Switch", "AIN3" },
+       { "Input Mixer", "AIN4 Switch", "AIN4" },
+       { "Input Mixer", "AIN5 Switch", "AIN5" },
+
+       { "ADC", NULL, "Input Mixer" },
+
+       { "Output Mixer", "DAC Switch", "DAC" },
+       { "Output Mixer", "AUX Switch", "AUX" },
+       { "Output Mixer", "Bypass Switch", "Input Mixer" },
+
+       { "VOUT", NULL, "Output Mixer" },
+
+       { "Headphone PGA", NULL, "Output Mixer" },
+
+       { "HPOUTL", NULL, "Headphone PGA" },
+       { "HPOUTR", NULL, "Headphone PGA" },
+};
+
+static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       int reg, iface, master;
+
+       switch (dai->id) {
+       case WM8776_DAI_DAC:
+               reg = WM8776_DACIFCTRL;
+               master = 0x80;
+               break;
+       case WM8776_DAI_ADC:
+               reg = WM8776_ADCIFCTRL;
+               master = 0x100;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       iface = 0;
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               master = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               iface |= 0x0002;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               iface |= 0x0001;
+               break;
+               /* FIXME: CHECK A/B */
+       case SND_SOC_DAIFMT_DSP_A:
+               iface |= 0x0003;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               iface |= 0x0007;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               iface |= 0x00c;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               iface |= 0x008;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               iface |= 0x004;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Finally, write out the values */
+       snd_soc_update_bits(codec, reg, 0xf, iface);
+       snd_soc_update_bits(codec, WM8776_MSTRCTRL, 0x180, master);
+
+       return 0;
+}
+
+static int mclk_ratios[] = {
+       128,
+       192,
+       256,
+       384,
+       512,
+       768,
+};
+
+static int wm8776_hw_params(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params,
+                           struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8776_priv *wm8776 = codec->private_data;
+       int iface_reg, iface;
+       int ratio_shift, master;
+       int i;
+
+       iface = 0;
+
+       switch (dai->id) {
+       case WM8776_DAI_DAC:
+               iface_reg = WM8776_DACIFCTRL;
+               master = 0x80;
+               ratio_shift = 4;
+               break;
+       case WM8776_DAI_ADC:
+               iface_reg = WM8776_ADCIFCTRL;
+               master = 0x100;
+               ratio_shift = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+
+       /* Set word length */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               iface |= 0x10;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               iface |= 0x20;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               iface |= 0x30;
+               break;
+       }
+
+       /* Only need to set MCLK/LRCLK ratio if we're master */
+       if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) {
+               for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) {
+                       if (wm8776->sysclk[dai->id] / params_rate(params)
+                           == mclk_ratios[i])
+                               break;
+               }
+
+               if (i == ARRAY_SIZE(mclk_ratios)) {
+                       dev_err(codec->dev,
+                               "Unable to configure MCLK ratio %d/%d\n",
+                               wm8776->sysclk[dai->id], params_rate(params));
+                       return -EINVAL;
+               }
+
+               dev_dbg(codec->dev, "MCLK is %dfs\n", mclk_ratios[i]);
+
+               snd_soc_update_bits(codec, WM8776_MSTRCTRL,
+                                   0x7 << ratio_shift, i << ratio_shift);
+       } else {
+               dev_dbg(codec->dev, "DAI in slave mode\n");
+       }
+
+       snd_soc_update_bits(codec, iface_reg, 0x30, iface);
+
+       return 0;
+}
+
+static int wm8776_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+
+       return snd_soc_write(codec, WM8776_DACMUTE, !!mute);
+}
+
+static int wm8776_set_sysclk(struct snd_soc_dai *dai,
+                            int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8776_priv *wm8776 = codec->private_data;
+
+       BUG_ON(dai->id >= ARRAY_SIZE(wm8776->sysclk));
+
+       wm8776->sysclk[dai->id] = freq;
+
+       return 0;
+}
+
+static int wm8776_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
+{
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+       case SND_SOC_BIAS_PREPARE:
+               break;
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->bias_level == SND_SOC_BIAS_OFF) {
+                       /* Disable the global powerdown; DAPM does the rest */
+                       snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0);
+               }
+
+               break;
+       case SND_SOC_BIAS_OFF:
+               snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 1);
+               break;
+       }
+
+       codec->bias_level = level;
+       return 0;
+}
+
+#define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
+                     SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
+                     SNDRV_PCM_RATE_96000)
+
+
+#define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+                       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops wm8776_dac_ops = {
+       .digital_mute   = wm8776_mute,
+       .hw_params      = wm8776_hw_params,
+       .set_fmt        = wm8776_set_fmt,
+       .set_sysclk     = wm8776_set_sysclk,
+};
+
+static struct snd_soc_dai_ops wm8776_adc_ops = {
+       .hw_params      = wm8776_hw_params,
+       .set_fmt        = wm8776_set_fmt,
+       .set_sysclk     = wm8776_set_sysclk,
+};
+
+struct snd_soc_dai wm8776_dai[] = {
+       {
+               .name = "WM8776 Playback",
+               .id = WM8776_DAI_DAC,
+               .playback = {
+                       .stream_name = "Playback",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = WM8776_RATES,
+                       .formats = WM8776_FORMATS,
+               },
+               .ops = &wm8776_dac_ops,
+       },
+       {
+               .name = "WM8776 Capture",
+               .id = WM8776_DAI_ADC,
+               .capture = {
+                       .stream_name = "Capture",
+                       .channels_min = 2,
+                       .channels_max = 2,
+                       .rates = WM8776_RATES,
+                       .formats = WM8776_FORMATS,
+               },
+               .ops = &wm8776_adc_ops,
+       },
+};
+EXPORT_SYMBOL_GPL(wm8776_dai);
+
+#ifdef CONFIG_PM
+static int wm8776_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+
+       wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       return 0;
+}
+
+static int wm8776_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+       int i;
+       u8 data[2];
+       u16 *cache = codec->reg_cache;
+
+       /* Sync reg_cache with the hardware */
+       for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) {
+               data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
+               data[1] = cache[i] & 0x00ff;
+               codec->hw_write(codec->control_data, data, 2);
+       }
+
+       wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       return 0;
+}
+#else
+#define wm8776_suspend NULL
+#define wm8776_resume NULL
+#endif
+
+static int wm8776_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec;
+       int ret = 0;
+
+       if (wm8776_codec == NULL) {
+               dev_err(&pdev->dev, "Codec device not registered\n");
+               return -ENODEV;
+       }
+
+       socdev->card->codec = wm8776_codec;
+       codec = wm8776_codec;
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to create pcms: %d\n", ret);
+               goto pcm_err;
+       }
+
+       snd_soc_add_controls(codec, wm8776_snd_controls,
+                            ARRAY_SIZE(wm8776_snd_controls));
+       snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets,
+                                 ARRAY_SIZE(wm8776_dapm_widgets));
+       snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes));
+
+       ret = snd_soc_init_card(socdev);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to register card: %d\n", ret);
+               goto card_err;
+       }
+
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+pcm_err:
+       return ret;
+}
+
+/* power down chip */
+static int wm8776_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+
+       return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8776 = {
+       .probe =        wm8776_probe,
+       .remove =       wm8776_remove,
+       .suspend =      wm8776_suspend,
+       .resume =       wm8776_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8776);
+
+static int wm8776_register(struct wm8776_priv *wm8776,
+                          enum snd_soc_control_type control)
+{
+       int ret, i;
+       struct snd_soc_codec *codec = &wm8776->codec;
+
+       if (wm8776_codec) {
+               dev_err(codec->dev, "Another WM8776 is registered\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       codec->private_data = wm8776;
+       codec->name = "WM8776";
+       codec->owner = THIS_MODULE;
+       codec->bias_level = SND_SOC_BIAS_OFF;
+       codec->set_bias_level = wm8776_set_bias_level;
+       codec->dai = wm8776_dai;
+       codec->num_dai = ARRAY_SIZE(wm8776_dai);
+       codec->reg_cache_size = WM8776_CACHEREGNUM;
+       codec->reg_cache = &wm8776->reg_cache;
+
+       memcpy(codec->reg_cache, wm8776_reg, sizeof(wm8776_reg));
+
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm8776_dai); i++)
+               wm8776_dai[i].dev = codec->dev;
+
+       ret = wm8776_reset(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
+               goto err;
+       }
+
+       wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       /* Latch the update bits; right channel only since we always
+        * update both. */
+       snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100);
+       snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100);
+
+       wm8776_codec = codec;
+
+       ret = snd_soc_register_codec(codec);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+               goto err;
+       }
+
+       ret = snd_soc_register_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai));
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
+               goto err_codec;
+       }
+
+       return 0;
+
+err_codec:
+       snd_soc_unregister_codec(codec);
+err:
+       kfree(wm8776);
+       return ret;
+}
+
+static void wm8776_unregister(struct wm8776_priv *wm8776)
+{
+       wm8776_set_bias_level(&wm8776->codec, SND_SOC_BIAS_OFF);
+       snd_soc_unregister_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai));
+       snd_soc_unregister_codec(&wm8776->codec);
+       kfree(wm8776);
+       wm8776_codec = NULL;
+}
+
+#if defined(CONFIG_SPI_MASTER)
+static int wm8776_spi_write(struct spi_device *spi, const char *data, int len)
+{
+       struct spi_transfer t;
+       struct spi_message m;
+       u8 msg[2];
+
+       if (len <= 0)
+               return 0;
+
+       msg[0] = data[0];
+       msg[1] = data[1];
+
+       spi_message_init(&m);
+       memset(&t, 0, (sizeof t));
+
+       t.tx_buf = &msg[0];
+       t.len = len;
+
+       spi_message_add_tail(&t, &m);
+       spi_sync(spi, &m);
+
+       return len;
+}
+
+static int __devinit wm8776_spi_probe(struct spi_device *spi)
+{
+       struct snd_soc_codec *codec;
+       struct wm8776_priv *wm8776;
+
+       wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
+       if (wm8776 == NULL)
+               return -ENOMEM;
+
+       codec = &wm8776->codec;
+       codec->control_data = spi;
+       codec->hw_write = (hw_write_t)wm8776_spi_write;
+       codec->dev = &spi->dev;
+
+       dev_set_drvdata(&spi->dev, wm8776);
+
+       return wm8776_register(wm8776, SND_SOC_SPI);
+}
+
+static int __devexit wm8776_spi_remove(struct spi_device *spi)
+{
+       struct wm8776_priv *wm8776 = dev_get_drvdata(&spi->dev);
+
+       wm8776_unregister(wm8776);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int wm8776_spi_suspend(struct spi_device *spi, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&spi->dev);
+}
+
+static int wm8776_spi_resume(struct spi_device *spi)
+{
+       return snd_soc_resume_device(&spi->dev);
+}
+#else
+#define wm8776_spi_suspend NULL
+#define wm8776_spi_resume NULL
+#endif
+
+static struct spi_driver wm8776_spi_driver = {
+       .driver = {
+               .name   = "wm8776",
+               .bus    = &spi_bus_type,
+               .owner  = THIS_MODULE,
+       },
+       .probe          = wm8776_spi_probe,
+       .suspend        = wm8776_spi_suspend,
+       .resume         = wm8776_spi_resume,
+       .remove         = __devexit_p(wm8776_spi_remove),
+};
+#endif /* CONFIG_SPI_MASTER */
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct wm8776_priv *wm8776;
+       struct snd_soc_codec *codec;
+
+       wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
+       if (wm8776 == NULL)
+               return -ENOMEM;
+
+       codec = &wm8776->codec;
+       codec->hw_write = (hw_write_t)i2c_master_send;
+
+       i2c_set_clientdata(i2c, wm8776);
+       codec->control_data = i2c;
+
+       codec->dev = &i2c->dev;
+
+       return wm8776_register(wm8776, SND_SOC_I2C);
+}
+
+static __devexit int wm8776_i2c_remove(struct i2c_client *client)
+{
+       struct wm8776_priv *wm8776 = i2c_get_clientdata(client);
+       wm8776_unregister(wm8776);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int wm8776_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&i2c->dev);
+}
+
+static int wm8776_i2c_resume(struct i2c_client *i2c)
+{
+       return snd_soc_resume_device(&i2c->dev);
+}
+#else
+#define wm8776_i2c_suspend NULL
+#define wm8776_i2c_resume NULL
+#endif
+
+static const struct i2c_device_id wm8776_i2c_id[] = {
+       { "wm8776", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
+
+static struct i2c_driver wm8776_i2c_driver = {
+       .driver = {
+               .name = "wm8776",
+               .owner = THIS_MODULE,
+       },
+       .probe =    wm8776_i2c_probe,
+       .remove =   __devexit_p(wm8776_i2c_remove),
+       .suspend =  wm8776_i2c_suspend,
+       .resume =   wm8776_i2c_resume,
+       .id_table = wm8776_i2c_id,
+};
+#endif
+
+static int __init wm8776_modinit(void)
+{
+       int ret;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       ret = i2c_add_driver(&wm8776_i2c_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register WM8776 I2C driver: %d\n",
+                      ret);
+       }
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       ret = spi_register_driver(&wm8776_spi_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register WM8776 SPI driver: %d\n",
+                      ret);
+       }
+#endif
+       return 0;
+}
+module_init(wm8776_modinit);
+
+static void __exit wm8776_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_driver(&wm8776_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+       spi_unregister_driver(&wm8776_spi_driver);
+#endif
+}
+module_exit(wm8776_exit);
+
+MODULE_DESCRIPTION("ASoC WM8776 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8776.h b/sound/soc/codecs/wm8776.h
new file mode 100644 (file)
index 0000000..6606d25
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * wm8776.h  --  WM8776 ASoC driver
+ *
+ * Copyright 2009 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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.
+ */
+
+#ifndef _WM8776_H
+#define _WM8776_H
+
+/* Registers */
+
+#define WM8776_HPLVOL    0x00
+#define WM8776_HPRVOL    0x01
+#define WM8776_HPMASTER  0x02
+#define WM8776_DACLVOL   0x03
+#define WM8776_DACRVOL   0x04
+#define WM8776_DACMASTER 0x05
+#define WM8776_PHASESWAP 0x06
+#define WM8776_DACCTRL1  0x07
+#define WM8776_DACMUTE   0x08
+#define WM8776_DACCTRL2  0x09
+#define WM8776_DACIFCTRL 0x0a
+#define WM8776_ADCIFCTRL 0x0b
+#define WM8776_MSTRCTRL  0x0c
+#define WM8776_PWRDOWN   0x0d
+#define WM8776_ADCLVOL   0x0e
+#define WM8776_ADCRVOL   0x0f
+#define WM8776_ALCCTRL1  0x10
+#define WM8776_ALCCTRL2  0x11
+#define WM8776_ALCCTRL3  0x12
+#define WM8776_NOISEGATE 0x13
+#define WM8776_LIMITER   0x14
+#define WM8776_ADCMUX    0x15
+#define WM8776_OUTMUX    0x16
+#define WM8776_RESET     0x17
+
+#define WM8776_CACHEREGNUM 0x17
+
+#define WM8776_DAI_DAC 0
+#define WM8776_DAI_ADC 1
+
+extern struct snd_soc_dai wm8776_dai[];
+extern struct snd_soc_codec_device soc_codec_dev_wm8776;
+
+#endif
index 3c78945244b8df516f12f0181f0194a4b1a1b949..5e9c855c0036eb72e79741ff4b90d13b3b7ae3c3 100644 (file)
 #define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c
 
 #define WM8900_REG_DACCTRL_MUTE          0x004
+#define WM8900_REG_DACCTRL_DAC_SB_FILT   0x100
 #define WM8900_REG_DACCTRL_AIF_LRCLKRATE 0x400
 
 #define WM8900_REG_AUDIO3_ADCLRC_DIR    0x0800
@@ -182,111 +183,20 @@ static const u16 wm8900_reg_defaults[WM8900_MAXREG] = {
        /* Remaining registers all zero */
 };
 
-/*
- * read wm8900 register cache
- */
-static inline unsigned int wm8900_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-
-       BUG_ON(reg >= WM8900_MAXREG);
-
-       if (reg == WM8900_REG_ID)
-               return 0;
-
-       return cache[reg];
-}
-
-/*
- * write wm8900 register cache
- */
-static inline void wm8900_write_reg_cache(struct snd_soc_codec *codec,
-       u16 reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-
-       BUG_ON(reg >= WM8900_MAXREG);
-
-       cache[reg] = value;
-}
-
-/*
- * write to the WM8900 register space
- */
-static int wm8900_write(struct snd_soc_codec *codec, unsigned int reg,
-                       unsigned int value)
-{
-       u8 data[3];
-
-       if (value == wm8900_read_reg_cache(codec, reg))
-               return 0;
-
-       /* data is
-        *   D15..D9 WM8900 register offset
-        *   D8...D0 register data
-        */
-       data[0] = reg;
-       data[1] = value >> 8;
-       data[2] = value & 0x00ff;
-
-       wm8900_write_reg_cache(codec, reg, value);
-       if (codec->hw_write(codec->control_data, data, 3) == 3)
-               return 0;
-       else
-               return -EIO;
-}
-
-/*
- * Read from the wm8900.
- */
-static unsigned int wm8900_chip_read(struct snd_soc_codec *codec, u8 reg)
-{
-       struct i2c_msg xfer[2];
-       u16 data;
-       int ret;
-       struct i2c_client *client = codec->control_data;
-
-       BUG_ON(reg != WM8900_REG_ID && reg != WM8900_REG_POWER1);
-
-       /* Write register */
-       xfer[0].addr = client->addr;
-       xfer[0].flags = 0;
-       xfer[0].len = 1;
-       xfer[0].buf = &reg;
-
-       /* Read data */
-       xfer[1].addr = client->addr;
-       xfer[1].flags = I2C_M_RD;
-       xfer[1].len = 2;
-       xfer[1].buf = (u8 *)&data;
-
-       ret = i2c_transfer(client->adapter, xfer, 2);
-       if (ret != 2) {
-               printk(KERN_CRIT "i2c_transfer returned %d\n", ret);
-               return 0;
-       }
-
-       return (data >> 8) | ((data & 0xff) << 8);
-}
-
-/*
- * Read from the WM8900 register space.  Most registers can't be read
- * and are therefore supplied from cache.
- */
-static unsigned int wm8900_read(struct snd_soc_codec *codec, unsigned int reg)
+static int wm8900_volatile_register(unsigned int reg)
 {
        switch (reg) {
        case WM8900_REG_ID:
-               return wm8900_chip_read(codec, reg);
+       case WM8900_REG_POWER1:
+               return 1;
        default:
-               return wm8900_read_reg_cache(codec, reg);
+               return 0;
        }
 }
 
 static void wm8900_reset(struct snd_soc_codec *codec)
 {
-       wm8900_write(codec, WM8900_REG_RESET, 0);
+       snd_soc_write(codec, WM8900_REG_RESET, 0);
 
        memcpy(codec->reg_cache, wm8900_reg_defaults,
               sizeof(codec->reg_cache));
@@ -296,14 +206,14 @@ static int wm8900_hp_event(struct snd_soc_dapm_widget *w,
                           struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_codec *codec = w->codec;
-       u16 hpctl1 = wm8900_read(codec, WM8900_REG_HPCTL1);
+       u16 hpctl1 = snd_soc_read(codec, WM8900_REG_HPCTL1);
 
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
                /* Clamp headphone outputs */
                hpctl1 = WM8900_REG_HPCTL1_HP_CLAMP_IP |
                        WM8900_REG_HPCTL1_HP_CLAMP_OP;
-               wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
+               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
                break;
 
        case SND_SOC_DAPM_POST_PMU:
@@ -312,41 +222,41 @@ static int wm8900_hp_event(struct snd_soc_dapm_widget *w,
                hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT |
                        WM8900_REG_HPCTL1_HP_SHORT2 |
                        WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
-               wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
+               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
 
                msleep(400);
 
                /* Enable the output stage */
                hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_OP;
                hpctl1 |= WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
-               wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
+               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
 
                /* Remove the shorts */
                hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT2;
-               wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
+               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
                hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT;
-               wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
+               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
                break;
 
        case SND_SOC_DAPM_PRE_PMD:
                /* Short the output */
                hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT;
-               wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
+               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
 
                /* Disable the output stage */
                hpctl1 &= ~WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
-               wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
+               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
 
                /* Clamp the outputs and power down input */
                hpctl1 |= WM8900_REG_HPCTL1_HP_CLAMP_IP |
                        WM8900_REG_HPCTL1_HP_CLAMP_OP;
                hpctl1 &= ~WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
-               wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1);
+               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
                break;
 
        case SND_SOC_DAPM_POST_PMD:
                /* Disable everything */
-               wm8900_write(codec, WM8900_REG_HPCTL1, 0);
+               snd_soc_write(codec, WM8900_REG_HPCTL1, 0);
                break;
 
        default:
@@ -439,7 +349,6 @@ SOC_SINGLE("DAC Soft Mute Switch", WM8900_REG_DACCTRL, 6, 1, 1),
 SOC_ENUM("DAC Mute Rate", dac_mute_rate),
 SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0),
 SOC_ENUM("DAC Deemphasis", dac_deemphasis),
-SOC_SINGLE("DAC Sloping Stopband Filter Switch", WM8900_REG_DACCTRL, 8, 1, 0),
 SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL,
           12, 1, 0),
 
@@ -723,7 +632,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_codec *codec = socdev->card->codec;
        u16 reg;
 
-       reg = wm8900_read(codec, WM8900_REG_AUDIO1) & ~0x60;
+       reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60;
 
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
@@ -741,7 +650,18 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       wm8900_write(codec, WM8900_REG_AUDIO1, reg);
+       snd_soc_write(codec, WM8900_REG_AUDIO1, reg);
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
+
+               if (params_rate(params) <= 24000)
+                       reg |= WM8900_REG_DACCTRL_DAC_SB_FILT;
+               else
+                       reg &= ~WM8900_REG_DACCTRL_DAC_SB_FILT;
+
+               snd_soc_write(codec, WM8900_REG_DACCTRL, reg);
+       }
 
        return 0;
 }
@@ -834,18 +754,18 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
                return 0;
 
        /* The digital side should be disabled during any change. */
-       reg = wm8900_read(codec, WM8900_REG_POWER1);
-       wm8900_write(codec, WM8900_REG_POWER1,
+       reg = snd_soc_read(codec, WM8900_REG_POWER1);
+       snd_soc_write(codec, WM8900_REG_POWER1,
                     reg & (~WM8900_REG_POWER1_FLL_ENA));
 
        /* Disable the FLL? */
        if (!freq_in || !freq_out) {
-               reg = wm8900_read(codec, WM8900_REG_CLOCKING1);
-               wm8900_write(codec, WM8900_REG_CLOCKING1,
+               reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
+               snd_soc_write(codec, WM8900_REG_CLOCKING1,
                             reg & (~WM8900_REG_CLOCKING1_MCLK_SRC));
 
-               reg = wm8900_read(codec, WM8900_REG_FLLCTL1);
-               wm8900_write(codec, WM8900_REG_FLLCTL1,
+               reg = snd_soc_read(codec, WM8900_REG_FLLCTL1);
+               snd_soc_write(codec, WM8900_REG_FLLCTL1,
                             reg & (~WM8900_REG_FLLCTL1_OSC_ENA));
 
                wm8900->fll_in = freq_in;
@@ -862,33 +782,33 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
 
        /* The osclilator *MUST* be enabled before we enable the
         * digital circuit. */
-       wm8900_write(codec, WM8900_REG_FLLCTL1,
+       snd_soc_write(codec, WM8900_REG_FLLCTL1,
                     fll_div.fll_ratio | WM8900_REG_FLLCTL1_OSC_ENA);
 
-       wm8900_write(codec, WM8900_REG_FLLCTL4, fll_div.n >> 5);
-       wm8900_write(codec, WM8900_REG_FLLCTL5,
+       snd_soc_write(codec, WM8900_REG_FLLCTL4, fll_div.n >> 5);
+       snd_soc_write(codec, WM8900_REG_FLLCTL5,
                     (fll_div.fllclk_div << 6) | (fll_div.n & 0x1f));
 
        if (fll_div.k) {
-               wm8900_write(codec, WM8900_REG_FLLCTL2,
+               snd_soc_write(codec, WM8900_REG_FLLCTL2,
                             (fll_div.k >> 8) | 0x100);
-               wm8900_write(codec, WM8900_REG_FLLCTL3, fll_div.k & 0xff);
+               snd_soc_write(codec, WM8900_REG_FLLCTL3, fll_div.k & 0xff);
        } else
-               wm8900_write(codec, WM8900_REG_FLLCTL2, 0);
+               snd_soc_write(codec, WM8900_REG_FLLCTL2, 0);
 
        if (fll_div.fll_slow_lock_ref)
-               wm8900_write(codec, WM8900_REG_FLLCTL6,
+               snd_soc_write(codec, WM8900_REG_FLLCTL6,
                             WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF);
        else
-               wm8900_write(codec, WM8900_REG_FLLCTL6, 0);
+               snd_soc_write(codec, WM8900_REG_FLLCTL6, 0);
 
-       reg = wm8900_read(codec, WM8900_REG_POWER1);
-       wm8900_write(codec, WM8900_REG_POWER1,
+       reg = snd_soc_read(codec, WM8900_REG_POWER1);
+       snd_soc_write(codec, WM8900_REG_POWER1,
                     reg | WM8900_REG_POWER1_FLL_ENA);
 
 reenable:
-       reg = wm8900_read(codec, WM8900_REG_CLOCKING1);
-       wm8900_write(codec, WM8900_REG_CLOCKING1,
+       reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
+       snd_soc_write(codec, WM8900_REG_CLOCKING1,
                     reg | WM8900_REG_CLOCKING1_MCLK_SRC);
 
        return 0;
@@ -908,38 +828,38 @@ static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
 
        switch (div_id) {
        case WM8900_BCLK_DIV:
-               reg = wm8900_read(codec, WM8900_REG_CLOCKING1);
-               wm8900_write(codec, WM8900_REG_CLOCKING1,
+               reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
+               snd_soc_write(codec, WM8900_REG_CLOCKING1,
                             div | (reg & WM8900_REG_CLOCKING1_BCLK_MASK));
                break;
        case WM8900_OPCLK_DIV:
-               reg = wm8900_read(codec, WM8900_REG_CLOCKING1);
-               wm8900_write(codec, WM8900_REG_CLOCKING1,
+               reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
+               snd_soc_write(codec, WM8900_REG_CLOCKING1,
                             div | (reg & WM8900_REG_CLOCKING1_OPCLK_MASK));
                break;
        case WM8900_DAC_LRCLK:
-               reg = wm8900_read(codec, WM8900_REG_AUDIO4);
-               wm8900_write(codec, WM8900_REG_AUDIO4,
+               reg = snd_soc_read(codec, WM8900_REG_AUDIO4);
+               snd_soc_write(codec, WM8900_REG_AUDIO4,
                             div | (reg & WM8900_LRC_MASK));
                break;
        case WM8900_ADC_LRCLK:
-               reg = wm8900_read(codec, WM8900_REG_AUDIO3);
-               wm8900_write(codec, WM8900_REG_AUDIO3,
+               reg = snd_soc_read(codec, WM8900_REG_AUDIO3);
+               snd_soc_write(codec, WM8900_REG_AUDIO3,
                             div | (reg & WM8900_LRC_MASK));
                break;
        case WM8900_DAC_CLKDIV:
-               reg = wm8900_read(codec, WM8900_REG_CLOCKING2);
-               wm8900_write(codec, WM8900_REG_CLOCKING2,
+               reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
+               snd_soc_write(codec, WM8900_REG_CLOCKING2,
                             div | (reg & WM8900_REG_CLOCKING2_DAC_CLKDIV));
                break;
        case WM8900_ADC_CLKDIV:
-               reg = wm8900_read(codec, WM8900_REG_CLOCKING2);
-               wm8900_write(codec, WM8900_REG_CLOCKING2,
+               reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
+               snd_soc_write(codec, WM8900_REG_CLOCKING2,
                             div | (reg & WM8900_REG_CLOCKING2_ADC_CLKDIV));
                break;
        case WM8900_LRCLK_MODE:
-               reg = wm8900_read(codec, WM8900_REG_DACCTRL);
-               wm8900_write(codec, WM8900_REG_DACCTRL,
+               reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
+               snd_soc_write(codec, WM8900_REG_DACCTRL,
                             div | (reg & WM8900_REG_DACCTRL_AIF_LRCLKRATE));
                break;
        default:
@@ -956,10 +876,10 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai,
        struct snd_soc_codec *codec = codec_dai->codec;
        unsigned int clocking1, aif1, aif3, aif4;
 
-       clocking1 = wm8900_read(codec, WM8900_REG_CLOCKING1);
-       aif1 = wm8900_read(codec, WM8900_REG_AUDIO1);
-       aif3 = wm8900_read(codec, WM8900_REG_AUDIO3);
-       aif4 = wm8900_read(codec, WM8900_REG_AUDIO4);
+       clocking1 = snd_soc_read(codec, WM8900_REG_CLOCKING1);
+       aif1 = snd_soc_read(codec, WM8900_REG_AUDIO1);
+       aif3 = snd_soc_read(codec, WM8900_REG_AUDIO3);
+       aif4 = snd_soc_read(codec, WM8900_REG_AUDIO4);
 
        /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1055,10 +975,10 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8900_write(codec, WM8900_REG_CLOCKING1, clocking1);
-       wm8900_write(codec, WM8900_REG_AUDIO1, aif1);
-       wm8900_write(codec, WM8900_REG_AUDIO3, aif3);
-       wm8900_write(codec, WM8900_REG_AUDIO4, aif4);
+       snd_soc_write(codec, WM8900_REG_CLOCKING1, clocking1);
+       snd_soc_write(codec, WM8900_REG_AUDIO1, aif1);
+       snd_soc_write(codec, WM8900_REG_AUDIO3, aif3);
+       snd_soc_write(codec, WM8900_REG_AUDIO4, aif4);
 
        return 0;
 }
@@ -1068,14 +988,14 @@ static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute)
        struct snd_soc_codec *codec = codec_dai->codec;
        u16 reg;
 
-       reg = wm8900_read(codec, WM8900_REG_DACCTRL);
+       reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
 
        if (mute)
                reg |= WM8900_REG_DACCTRL_MUTE;
        else
                reg &= ~WM8900_REG_DACCTRL_MUTE;
 
-       wm8900_write(codec, WM8900_REG_DACCTRL, reg);
+       snd_soc_write(codec, WM8900_REG_DACCTRL, reg);
 
        return 0;
 }
@@ -1124,11 +1044,11 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
        switch (level) {
        case SND_SOC_BIAS_ON:
                /* Enable thermal shutdown */
-               reg = wm8900_read(codec, WM8900_REG_GPIO);
-               wm8900_write(codec, WM8900_REG_GPIO,
+               reg = snd_soc_read(codec, WM8900_REG_GPIO);
+               snd_soc_write(codec, WM8900_REG_GPIO,
                             reg | WM8900_REG_GPIO_TEMP_ENA);
-               reg = wm8900_read(codec, WM8900_REG_ADDCTL);
-               wm8900_write(codec, WM8900_REG_ADDCTL,
+               reg = snd_soc_read(codec, WM8900_REG_ADDCTL);
+               snd_soc_write(codec, WM8900_REG_ADDCTL,
                             reg | WM8900_REG_ADDCTL_TEMP_SD);
                break;
 
@@ -1139,69 +1059,69 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
                /* Charge capacitors if initial power up */
                if (codec->bias_level == SND_SOC_BIAS_OFF) {
                        /* STARTUP_BIAS_ENA on */
-                       wm8900_write(codec, WM8900_REG_POWER1,
+                       snd_soc_write(codec, WM8900_REG_POWER1,
                                     WM8900_REG_POWER1_STARTUP_BIAS_ENA);
 
                        /* Startup bias mode */
-                       wm8900_write(codec, WM8900_REG_ADDCTL,
+                       snd_soc_write(codec, WM8900_REG_ADDCTL,
                                     WM8900_REG_ADDCTL_BIAS_SRC |
                                     WM8900_REG_ADDCTL_VMID_SOFTST);
 
                        /* VMID 2x50k */
-                       wm8900_write(codec, WM8900_REG_POWER1,
+                       snd_soc_write(codec, WM8900_REG_POWER1,
                                     WM8900_REG_POWER1_STARTUP_BIAS_ENA | 0x1);
 
                        /* Allow capacitors to charge */
                        schedule_timeout_interruptible(msecs_to_jiffies(400));
 
                        /* Enable bias */
-                       wm8900_write(codec, WM8900_REG_POWER1,
+                       snd_soc_write(codec, WM8900_REG_POWER1,
                                     WM8900_REG_POWER1_STARTUP_BIAS_ENA |
                                     WM8900_REG_POWER1_BIAS_ENA | 0x1);
 
-                       wm8900_write(codec, WM8900_REG_ADDCTL, 0);
+                       snd_soc_write(codec, WM8900_REG_ADDCTL, 0);
 
-                       wm8900_write(codec, WM8900_REG_POWER1,
+                       snd_soc_write(codec, WM8900_REG_POWER1,
                                     WM8900_REG_POWER1_BIAS_ENA | 0x1);
                }
 
-               reg = wm8900_read(codec, WM8900_REG_POWER1);
-               wm8900_write(codec, WM8900_REG_POWER1,
+               reg = snd_soc_read(codec, WM8900_REG_POWER1);
+               snd_soc_write(codec, WM8900_REG_POWER1,
                             (reg & WM8900_REG_POWER1_FLL_ENA) |
                             WM8900_REG_POWER1_BIAS_ENA | 0x1);
-               wm8900_write(codec, WM8900_REG_POWER2,
+               snd_soc_write(codec, WM8900_REG_POWER2,
                             WM8900_REG_POWER2_SYSCLK_ENA);
-               wm8900_write(codec, WM8900_REG_POWER3, 0);
+               snd_soc_write(codec, WM8900_REG_POWER3, 0);
                break;
 
        case SND_SOC_BIAS_OFF:
                /* Startup bias enable */
-               reg = wm8900_read(codec, WM8900_REG_POWER1);
-               wm8900_write(codec, WM8900_REG_POWER1,
+               reg = snd_soc_read(codec, WM8900_REG_POWER1);
+               snd_soc_write(codec, WM8900_REG_POWER1,
                             reg & WM8900_REG_POWER1_STARTUP_BIAS_ENA);
-               wm8900_write(codec, WM8900_REG_ADDCTL,
+               snd_soc_write(codec, WM8900_REG_ADDCTL,
                             WM8900_REG_ADDCTL_BIAS_SRC |
                             WM8900_REG_ADDCTL_VMID_SOFTST);
 
                /* Discharge caps */
-               wm8900_write(codec, WM8900_REG_POWER1,
+               snd_soc_write(codec, WM8900_REG_POWER1,
                             WM8900_REG_POWER1_STARTUP_BIAS_ENA);
                schedule_timeout_interruptible(msecs_to_jiffies(500));
 
                /* Remove clamp */
-               wm8900_write(codec, WM8900_REG_HPCTL1, 0);
+               snd_soc_write(codec, WM8900_REG_HPCTL1, 0);
 
                /* Power down */
-               wm8900_write(codec, WM8900_REG_ADDCTL, 0);
-               wm8900_write(codec, WM8900_REG_POWER1, 0);
-               wm8900_write(codec, WM8900_REG_POWER2, 0);
-               wm8900_write(codec, WM8900_REG_POWER3, 0);
+               snd_soc_write(codec, WM8900_REG_ADDCTL, 0);
+               snd_soc_write(codec, WM8900_REG_POWER1, 0);
+               snd_soc_write(codec, WM8900_REG_POWER2, 0);
+               snd_soc_write(codec, WM8900_REG_POWER3, 0);
 
                /* Need to let things settle before stopping the clock
                 * to ensure that restart works, see "Stopping the
                 * master clock" in the datasheet. */
                schedule_timeout_interruptible(msecs_to_jiffies(1));
-               wm8900_write(codec, WM8900_REG_POWER2,
+               snd_soc_write(codec, WM8900_REG_POWER2,
                             WM8900_REG_POWER2_SYSCLK_ENA);
                break;
        }
@@ -1264,7 +1184,7 @@ static int wm8900_resume(struct platform_device *pdev)
 
        if (cache) {
                for (i = 0; i < WM8900_MAXREG; i++)
-                       wm8900_write(codec, i, cache[i]);
+                       snd_soc_write(codec, i, cache[i]);
                kfree(cache);
        } else
                dev_err(&pdev->dev, "Unable to allocate register cache\n");
@@ -1297,16 +1217,20 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
 
        codec->name = "WM8900";
        codec->owner = THIS_MODULE;
-       codec->read = wm8900_read;
-       codec->write = wm8900_write;
        codec->dai = &wm8900_dai;
        codec->num_dai = 1;
-       codec->hw_write = (hw_write_t)i2c_master_send;
        codec->control_data = i2c;
        codec->set_bias_level = wm8900_set_bias_level;
+       codec->volatile_register = wm8900_volatile_register;
        codec->dev = &i2c->dev;
 
-       reg = wm8900_read(codec, WM8900_REG_ID);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
+       reg = snd_soc_read(codec, WM8900_REG_ID);
        if (reg != 0x8900) {
                dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg);
                ret = -ENODEV;
@@ -1314,7 +1238,7 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
        }
 
        /* Read back from the chip */
-       reg = wm8900_chip_read(codec, WM8900_REG_POWER1);
+       reg = snd_soc_read(codec, WM8900_REG_POWER1);
        reg = (reg >> 12) & 0xf;
        dev_info(&i2c->dev, "WM8900 revision %d\n", reg);
 
@@ -1324,29 +1248,29 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
        wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Latch the volume update bits */
-       wm8900_write(codec, WM8900_REG_LINVOL,
-                    wm8900_read(codec, WM8900_REG_LINVOL) | 0x100);
-       wm8900_write(codec, WM8900_REG_RINVOL,
-                    wm8900_read(codec, WM8900_REG_RINVOL) | 0x100);
-       wm8900_write(codec, WM8900_REG_LOUT1CTL,
-                    wm8900_read(codec, WM8900_REG_LOUT1CTL) | 0x100);
-       wm8900_write(codec, WM8900_REG_ROUT1CTL,
-                    wm8900_read(codec, WM8900_REG_ROUT1CTL) | 0x100);
-       wm8900_write(codec, WM8900_REG_LOUT2CTL,
-                    wm8900_read(codec, WM8900_REG_LOUT2CTL) | 0x100);
-       wm8900_write(codec, WM8900_REG_ROUT2CTL,
-                    wm8900_read(codec, WM8900_REG_ROUT2CTL) | 0x100);
-       wm8900_write(codec, WM8900_REG_LDAC_DV,
-                    wm8900_read(codec, WM8900_REG_LDAC_DV) | 0x100);
-       wm8900_write(codec, WM8900_REG_RDAC_DV,
-                    wm8900_read(codec, WM8900_REG_RDAC_DV) | 0x100);
-       wm8900_write(codec, WM8900_REG_LADC_DV,
-                    wm8900_read(codec, WM8900_REG_LADC_DV) | 0x100);
-       wm8900_write(codec, WM8900_REG_RADC_DV,
-                    wm8900_read(codec, WM8900_REG_RADC_DV) | 0x100);
+       snd_soc_write(codec, WM8900_REG_LINVOL,
+                     snd_soc_read(codec, WM8900_REG_LINVOL) | 0x100);
+       snd_soc_write(codec, WM8900_REG_RINVOL,
+                     snd_soc_read(codec, WM8900_REG_RINVOL) | 0x100);
+       snd_soc_write(codec, WM8900_REG_LOUT1CTL,
+                     snd_soc_read(codec, WM8900_REG_LOUT1CTL) | 0x100);
+       snd_soc_write(codec, WM8900_REG_ROUT1CTL,
+                     snd_soc_read(codec, WM8900_REG_ROUT1CTL) | 0x100);
+       snd_soc_write(codec, WM8900_REG_LOUT2CTL,
+                     snd_soc_read(codec, WM8900_REG_LOUT2CTL) | 0x100);
+       snd_soc_write(codec, WM8900_REG_ROUT2CTL,
+                     snd_soc_read(codec, WM8900_REG_ROUT2CTL) | 0x100);
+       snd_soc_write(codec, WM8900_REG_LDAC_DV,
+                     snd_soc_read(codec, WM8900_REG_LDAC_DV) | 0x100);
+       snd_soc_write(codec, WM8900_REG_RDAC_DV,
+                     snd_soc_read(codec, WM8900_REG_RDAC_DV) | 0x100);
+       snd_soc_write(codec, WM8900_REG_LADC_DV,
+                     snd_soc_read(codec, WM8900_REG_LADC_DV) | 0x100);
+       snd_soc_write(codec, WM8900_REG_RADC_DV,
+                     snd_soc_read(codec, WM8900_REG_RADC_DV) | 0x100);
 
        /* Set the DAC and mixer output bias */
-       wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
+       snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
 
        wm8900_dai.dev = &i2c->dev;
 
@@ -1388,6 +1312,21 @@ static __devexit int wm8900_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm8900_i2c_suspend(struct i2c_client *client, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&client->dev);
+}
+
+static int wm8900_i2c_resume(struct i2c_client *client)
+{
+       return snd_soc_resume_device(&client->dev);
+}
+#else
+#define wm8900_i2c_suspend NULL
+#define wm8900_i2c_resume NULL
+#endif
+
 static const struct i2c_device_id wm8900_i2c_id[] = {
        { "wm8900", 0 },
        { }
@@ -1401,6 +1340,8 @@ static struct i2c_driver wm8900_i2c_driver = {
        },
        .probe = wm8900_i2c_probe,
        .remove = __devexit_p(wm8900_i2c_remove),
+       .suspend = wm8900_i2c_suspend,
+       .resume = wm8900_i2c_resume,
        .id_table = wm8900_i2c_id,
 };
 
index e8d2e3e14c45528d6dd23ba73e71bead6c8fb53b..fe1307b500cf5cf30af59b9f83c0310447c08f33 100644 (file)
@@ -225,94 +225,18 @@ struct wm8903_priv {
        struct snd_pcm_substream *slave_substream;
 };
 
-
-static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec,
-                                                unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-
-       BUG_ON(reg >= ARRAY_SIZE(wm8903_reg_defaults));
-
-       return cache[reg];
-}
-
-static unsigned int wm8903_hw_read(struct snd_soc_codec *codec, u8 reg)
-{
-       struct i2c_msg xfer[2];
-       u16 data;
-       int ret;
-       struct i2c_client *client = codec->control_data;
-
-       /* Write register */
-       xfer[0].addr = client->addr;
-       xfer[0].flags = 0;
-       xfer[0].len = 1;
-       xfer[0].buf = &reg;
-
-       /* Read data */
-       xfer[1].addr = client->addr;
-       xfer[1].flags = I2C_M_RD;
-       xfer[1].len = 2;
-       xfer[1].buf = (u8 *)&data;
-
-       ret = i2c_transfer(client->adapter, xfer, 2);
-       if (ret != 2) {
-               pr_err("i2c_transfer returned %d\n", ret);
-               return 0;
-       }
-
-       return (data >> 8) | ((data & 0xff) << 8);
-}
-
-static unsigned int wm8903_read(struct snd_soc_codec *codec,
-                               unsigned int reg)
+static int wm8903_volatile_register(unsigned int reg)
 {
        switch (reg) {
        case WM8903_SW_RESET_AND_ID:
        case WM8903_REVISION_NUMBER:
        case WM8903_INTERRUPT_STATUS_1:
        case WM8903_WRITE_SEQUENCER_4:
-               return wm8903_hw_read(codec, reg);
+               return 1;
 
        default:
-               return wm8903_read_reg_cache(codec, reg);
-       }
-}
-
-static void wm8903_write_reg_cache(struct snd_soc_codec *codec,
-                                  u16 reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-
-       BUG_ON(reg >= ARRAY_SIZE(wm8903_reg_defaults));
-
-       switch (reg) {
-       case WM8903_SW_RESET_AND_ID:
-       case WM8903_REVISION_NUMBER:
-               break;
-
-       default:
-               cache[reg] = value;
-               break;
-       }
-}
-
-static int wm8903_write(struct snd_soc_codec *codec, unsigned int reg,
-                       unsigned int value)
-{
-       u8 data[3];
-
-       wm8903_write_reg_cache(codec, reg, value);
-
-       /* Data format is 1 byte of address followed by 2 bytes of data */
-       data[0] = reg;
-       data[1] = (value >> 8) & 0xff;
-       data[2] = value & 0xff;
-
-       if (codec->hw_write(codec->control_data, data, 3) == 2)
                return 0;
-       else
-               return -EIO;
+       }
 }
 
 static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
@@ -323,13 +247,13 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
        BUG_ON(start > 48);
 
        /* Enable the sequencer */
-       reg[0] = wm8903_read(codec, WM8903_WRITE_SEQUENCER_0);
+       reg[0] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_0);
        reg[0] |= WM8903_WSEQ_ENA;
-       wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]);
+       snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]);
 
        dev_dbg(&i2c->dev, "Starting sequence at %d\n", start);
 
-       wm8903_write(codec, WM8903_WRITE_SEQUENCER_3,
+       snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3,
                     start | WM8903_WSEQ_START);
 
        /* Wait for it to complete.  If we have the interrupt wired up then
@@ -339,13 +263,13 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
        do {
                msleep(10);
 
-               reg[4] = wm8903_read(codec, WM8903_WRITE_SEQUENCER_4);
+               reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4);
        } while (reg[4] & WM8903_WSEQ_BUSY);
 
        dev_dbg(&i2c->dev, "Sequence complete\n");
 
        /* Disable the sequencer again */
-       wm8903_write(codec, WM8903_WRITE_SEQUENCER_0,
+       snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0,
                     reg[0] & ~WM8903_WSEQ_ENA);
 
        return 0;
@@ -357,12 +281,12 @@ static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache)
 
        /* There really ought to be something better we can do here :/ */
        for (i = 0; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
-               cache[i] = wm8903_hw_read(codec, i);
+               cache[i] = codec->hw_read(codec, i);
 }
 
 static void wm8903_reset(struct snd_soc_codec *codec)
 {
-       wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0);
+       snd_soc_write(codec, WM8903_SW_RESET_AND_ID, 0);
        memcpy(codec->reg_cache, wm8903_reg_defaults,
               sizeof(wm8903_reg_defaults));
 }
@@ -423,52 +347,52 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
        }
 
        if (event & SND_SOC_DAPM_PRE_PMU) {
-               val = wm8903_read(codec, reg);
+               val = snd_soc_read(codec, reg);
 
                /* Short the output */
                val &= ~(WM8903_OUTPUT_SHORT << shift);
-               wm8903_write(codec, reg, val);
+               snd_soc_write(codec, reg, val);
        }
 
        if (event & SND_SOC_DAPM_POST_PMU) {
-               val = wm8903_read(codec, reg);
+               val = snd_soc_read(codec, reg);
 
                val |= (WM8903_OUTPUT_IN << shift);
-               wm8903_write(codec, reg, val);
+               snd_soc_write(codec, reg, val);
 
                val |= (WM8903_OUTPUT_INT << shift);
-               wm8903_write(codec, reg, val);
+               snd_soc_write(codec, reg, val);
 
                /* Turn on the output ENA_OUTP */
                val |= (WM8903_OUTPUT_OUT << shift);
-               wm8903_write(codec, reg, val);
+               snd_soc_write(codec, reg, val);
 
                /* Enable the DC servo */
-               dcs_reg = wm8903_read(codec, WM8903_DC_SERVO_0);
+               dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0);
                dcs_reg |= dcs_bit;
-               wm8903_write(codec, WM8903_DC_SERVO_0, dcs_reg);
+               snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg);
 
                /* Remove the short */
                val |= (WM8903_OUTPUT_SHORT << shift);
-               wm8903_write(codec, reg, val);
+               snd_soc_write(codec, reg, val);
        }
 
        if (event & SND_SOC_DAPM_PRE_PMD) {
-               val = wm8903_read(codec, reg);
+               val = snd_soc_read(codec, reg);
 
                /* Short the output */
                val &= ~(WM8903_OUTPUT_SHORT << shift);
-               wm8903_write(codec, reg, val);
+               snd_soc_write(codec, reg, val);
 
                /* Disable the DC servo */
-               dcs_reg = wm8903_read(codec, WM8903_DC_SERVO_0);
+               dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0);
                dcs_reg &= ~dcs_bit;
-               wm8903_write(codec, WM8903_DC_SERVO_0, dcs_reg);
+               snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg);
 
                /* Then disable the intermediate and output stages */
                val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT |
                          WM8903_OUTPUT_IN) << shift);
-               wm8903_write(codec, reg, val);
+               snd_soc_write(codec, reg, val);
        }
 
        return 0;
@@ -492,13 +416,13 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
        u16 reg;
        int ret;
 
-       reg = wm8903_read(codec, WM8903_CLASS_W_0);
+       reg = snd_soc_read(codec, WM8903_CLASS_W_0);
 
        /* Turn it off if we're about to enable bypass */
        if (ucontrol->value.integer.value[0]) {
                if (wm8903->class_w_users == 0) {
                        dev_dbg(&i2c->dev, "Disabling Class W\n");
-                       wm8903_write(codec, WM8903_CLASS_W_0, reg &
+                       snd_soc_write(codec, WM8903_CLASS_W_0, reg &
                                     ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V));
                }
                wm8903->class_w_users++;
@@ -511,7 +435,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
        if (!ucontrol->value.integer.value[0]) {
                if (wm8903->class_w_users == 1) {
                        dev_dbg(&i2c->dev, "Enabling Class W\n");
-                       wm8903_write(codec, WM8903_CLASS_W_0, reg |
+                       snd_soc_write(codec, WM8903_CLASS_W_0, reg |
                                     WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
                }
                wm8903->class_w_users--;
@@ -715,8 +639,6 @@ SOC_ENUM("DAC Soft Mute Rate", soft_mute),
 SOC_ENUM("DAC Mute Mode", mute_mode),
 SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0),
 SOC_ENUM("DAC De-emphasis", dac_deemphasis),
-SOC_SINGLE("DAC Sloping Stopband Filter Switch",
-          WM8903_DAC_DIGITAL_1, 11, 1, 0),
 SOC_ENUM("DAC Companding Mode", dac_companding),
 SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0),
 
@@ -1011,55 +933,55 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
        switch (level) {
        case SND_SOC_BIAS_ON:
        case SND_SOC_BIAS_PREPARE:
-               reg = wm8903_read(codec, WM8903_VMID_CONTROL_0);
+               reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0);
                reg &= ~(WM8903_VMID_RES_MASK);
                reg |= WM8903_VMID_RES_50K;
-               wm8903_write(codec, WM8903_VMID_CONTROL_0, reg);
+               snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg);
                break;
 
        case SND_SOC_BIAS_STANDBY:
                if (codec->bias_level == SND_SOC_BIAS_OFF) {
-                       wm8903_write(codec, WM8903_CLOCK_RATES_2,
+                       snd_soc_write(codec, WM8903_CLOCK_RATES_2,
                                     WM8903_CLK_SYS_ENA);
 
                        /* Change DC servo dither level in startup sequence */
-                       wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, 0x11);
-                       wm8903_write(codec, WM8903_WRITE_SEQUENCER_1, 0x1257);
-                       wm8903_write(codec, WM8903_WRITE_SEQUENCER_2, 0x2);
+                       snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, 0x11);
+                       snd_soc_write(codec, WM8903_WRITE_SEQUENCER_1, 0x1257);
+                       snd_soc_write(codec, WM8903_WRITE_SEQUENCER_2, 0x2);
 
                        wm8903_run_sequence(codec, 0);
                        wm8903_sync_reg_cache(codec, codec->reg_cache);
 
                        /* Enable low impedence charge pump output */
-                       reg = wm8903_read(codec,
+                       reg = snd_soc_read(codec,
                                          WM8903_CONTROL_INTERFACE_TEST_1);
-                       wm8903_write(codec, WM8903_CONTROL_INTERFACE_TEST_1,
+                       snd_soc_write(codec, WM8903_CONTROL_INTERFACE_TEST_1,
                                     reg | WM8903_TEST_KEY);
-                       reg2 = wm8903_read(codec, WM8903_CHARGE_PUMP_TEST_1);
-                       wm8903_write(codec, WM8903_CHARGE_PUMP_TEST_1,
+                       reg2 = snd_soc_read(codec, WM8903_CHARGE_PUMP_TEST_1);
+                       snd_soc_write(codec, WM8903_CHARGE_PUMP_TEST_1,
                                     reg2 | WM8903_CP_SW_KELVIN_MODE_MASK);
-                       wm8903_write(codec, WM8903_CONTROL_INTERFACE_TEST_1,
+                       snd_soc_write(codec, WM8903_CONTROL_INTERFACE_TEST_1,
                                     reg);
 
                        /* By default no bypass paths are enabled so
                         * enable Class W support.
                         */
                        dev_dbg(&i2c->dev, "Enabling Class W\n");
-                       wm8903_write(codec, WM8903_CLASS_W_0, reg |
+                       snd_soc_write(codec, WM8903_CLASS_W_0, reg |
                                     WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
                }
 
-               reg = wm8903_read(codec, WM8903_VMID_CONTROL_0);
+               reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0);
                reg &= ~(WM8903_VMID_RES_MASK);
                reg |= WM8903_VMID_RES_250K;
-               wm8903_write(codec, WM8903_VMID_CONTROL_0, reg);
+               snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg);
                break;
 
        case SND_SOC_BIAS_OFF:
                wm8903_run_sequence(codec, 32);
-               reg = wm8903_read(codec, WM8903_CLOCK_RATES_2);
+               reg = snd_soc_read(codec, WM8903_CLOCK_RATES_2);
                reg &= ~WM8903_CLK_SYS_ENA;
-               wm8903_write(codec, WM8903_CLOCK_RATES_2, reg);
+               snd_soc_write(codec, WM8903_CLOCK_RATES_2, reg);
                break;
        }
 
@@ -1083,7 +1005,7 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai,
                              unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
-       u16 aif1 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_1);
+       u16 aif1 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_1);
 
        aif1 &= ~(WM8903_LRCLK_DIR | WM8903_BCLK_DIR | WM8903_AIF_FMT_MASK |
                  WM8903_AIF_LRCLK_INV | WM8903_AIF_BCLK_INV);
@@ -1161,7 +1083,7 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
+       snd_soc_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
 
        return 0;
 }
@@ -1171,14 +1093,14 @@ static int wm8903_digital_mute(struct snd_soc_dai *codec_dai, int mute)
        struct snd_soc_codec *codec = codec_dai->codec;
        u16 reg;
 
-       reg = wm8903_read(codec, WM8903_DAC_DIGITAL_1);
+       reg = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
 
        if (mute)
                reg |= WM8903_DAC_MUTE;
        else
                reg &= ~WM8903_DAC_MUTE;
 
-       wm8903_write(codec, WM8903_DAC_DIGITAL_1, reg);
+       snd_soc_write(codec, WM8903_DAC_DIGITAL_1, reg);
 
        return 0;
 }
@@ -1368,17 +1290,24 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
        int cur_val;
        int clk_sys;
 
-       u16 aif1 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_1);
-       u16 aif2 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_2);
-       u16 aif3 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_3);
-       u16 clock0 = wm8903_read(codec, WM8903_CLOCK_RATES_0);
-       u16 clock1 = wm8903_read(codec, WM8903_CLOCK_RATES_1);
+       u16 aif1 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_1);
+       u16 aif2 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_2);
+       u16 aif3 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_3);
+       u16 clock0 = snd_soc_read(codec, WM8903_CLOCK_RATES_0);
+       u16 clock1 = snd_soc_read(codec, WM8903_CLOCK_RATES_1);
+       u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
 
        if (substream == wm8903->slave_substream) {
                dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n");
                return 0;
        }
 
+       /* Enable sloping stopband filter for low sample rates */
+       if (fs <= 24000)
+               dac_digital1 |= WM8903_DAC_SB_FILT;
+       else
+               dac_digital1 &= ~WM8903_DAC_SB_FILT;
+
        /* Configure sample rate logic for DSP - choose nearest rate */
        dsp_config = 0;
        best_val = abs(sample_rates[dsp_config].rate - fs);
@@ -1498,11 +1427,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
        aif2 |= bclk_divs[bclk_div].div;
        aif3 |= bclk / fs;
 
-       wm8903_write(codec, WM8903_CLOCK_RATES_0, clock0);
-       wm8903_write(codec, WM8903_CLOCK_RATES_1, clock1);
-       wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
-       wm8903_write(codec, WM8903_AUDIO_INTERFACE_2, aif2);
-       wm8903_write(codec, WM8903_AUDIO_INTERFACE_3, aif3);
+       snd_soc_write(codec, WM8903_CLOCK_RATES_0, clock0);
+       snd_soc_write(codec, WM8903_CLOCK_RATES_1, clock1);
+       snd_soc_write(codec, WM8903_AUDIO_INTERFACE_1, aif1);
+       snd_soc_write(codec, WM8903_AUDIO_INTERFACE_2, aif2);
+       snd_soc_write(codec, WM8903_AUDIO_INTERFACE_3, aif3);
+       snd_soc_write(codec, WM8903_DAC_DIGITAL_1, dac_digital1);
 
        return 0;
 }
@@ -1587,7 +1517,7 @@ static int wm8903_resume(struct platform_device *pdev)
        if (tmp_cache) {
                for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
                        if (tmp_cache[i] != reg_cache[i])
-                               wm8903_write(codec, i, tmp_cache[i]);
+                               snd_soc_write(codec, i, tmp_cache[i]);
        } else {
                dev_err(&i2c->dev, "Failed to allocate temporary cache\n");
        }
@@ -1618,9 +1548,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
        codec->dev = &i2c->dev;
        codec->name = "WM8903";
        codec->owner = THIS_MODULE;
-       codec->read = wm8903_read;
-       codec->write = wm8903_write;
-       codec->hw_write = (hw_write_t)i2c_master_send;
        codec->bias_level = SND_SOC_BIAS_OFF;
        codec->set_bias_level = wm8903_set_bias_level;
        codec->dai = &wm8903_dai;
@@ -1628,18 +1555,25 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
        codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache);
        codec->reg_cache = &wm8903->reg_cache[0];
        codec->private_data = wm8903;
+       codec->volatile_register = wm8903_volatile_register;
 
        i2c_set_clientdata(i2c, codec);
        codec->control_data = i2c;
 
-       val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       if (ret != 0) {
+               dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
+       val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID);
        if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
                dev_err(&i2c->dev,
                        "Device with ID register %x is not a WM8903\n", val);
                return -ENODEV;
        }
 
-       val = wm8903_read(codec, WM8903_REVISION_NUMBER);
+       val = snd_soc_read(codec, WM8903_REVISION_NUMBER);
        dev_info(&i2c->dev, "WM8903 revision %d\n",
                 val & WM8903_CHIP_REV_MASK);
 
@@ -1649,35 +1583,35 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
        wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Latch volume update bits */
-       val = wm8903_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT);
+       val = snd_soc_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT);
        val |= WM8903_ADCVU;
-       wm8903_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val);
-       wm8903_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val);
+       snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val);
+       snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val);
 
-       val = wm8903_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT);
+       val = snd_soc_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT);
        val |= WM8903_DACVU;
-       wm8903_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val);
-       wm8903_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val);
+       snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val);
+       snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val);
 
-       val = wm8903_read(codec, WM8903_ANALOGUE_OUT1_LEFT);
+       val = snd_soc_read(codec, WM8903_ANALOGUE_OUT1_LEFT);
        val |= WM8903_HPOUTVU;
-       wm8903_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val);
-       wm8903_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val);
+       snd_soc_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val);
+       snd_soc_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val);
 
-       val = wm8903_read(codec, WM8903_ANALOGUE_OUT2_LEFT);
+       val = snd_soc_read(codec, WM8903_ANALOGUE_OUT2_LEFT);
        val |= WM8903_LINEOUTVU;
-       wm8903_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val);
-       wm8903_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val);
+       snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val);
+       snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val);
 
-       val = wm8903_read(codec, WM8903_ANALOGUE_OUT3_LEFT);
+       val = snd_soc_read(codec, WM8903_ANALOGUE_OUT3_LEFT);
        val |= WM8903_SPKVU;
-       wm8903_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val);
-       wm8903_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val);
+       snd_soc_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val);
+       snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val);
 
        /* Enable DAC soft mute by default */
-       val = wm8903_read(codec, WM8903_DAC_DIGITAL_1);
+       val = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
        val |= WM8903_DAC_MUTEMODE;
-       wm8903_write(codec, WM8903_DAC_DIGITAL_1, val);
+       snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val);
 
        wm8903_dai.dev = &i2c->dev;
        wm8903_codec = codec;
@@ -1721,6 +1655,21 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm8903_i2c_suspend(struct i2c_client *client, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&client->dev);
+}
+
+static int wm8903_i2c_resume(struct i2c_client *client)
+{
+       return snd_soc_resume_device(&client->dev);
+}
+#else
+#define wm8903_i2c_suspend NULL
+#define wm8903_i2c_resume NULL
+#endif
+
 /* i2c codec control layer */
 static const struct i2c_device_id wm8903_i2c_id[] = {
        { "wm8903", 0 },
@@ -1735,6 +1684,8 @@ static struct i2c_driver wm8903_i2c_driver = {
        },
        .probe    = wm8903_i2c_probe,
        .remove   = __devexit_p(wm8903_i2c_remove),
+       .suspend  = wm8903_i2c_suspend,
+       .resume   = wm8903_i2c_resume,
        .id_table = wm8903_i2c_id,
 };
 
index b8e17d6bc1f7d2f0078c62887df249ce8e7479fb..da97aae475a2ed1eb89582401558165074f96ef7 100644 (file)
@@ -106,50 +106,6 @@ static u16 wm8940_reg_defaults[] = {
        0x0000, /* Mono Mixer Control */
 };
 
-static inline unsigned int wm8940_read_reg_cache(struct snd_soc_codec *codec,
-                                                unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-
-       if (reg >= ARRAY_SIZE(wm8940_reg_defaults))
-               return -1;
-
-       return cache[reg];
-}
-
-static inline int wm8940_write_reg_cache(struct snd_soc_codec *codec,
-                                         u16 reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-
-       if (reg >= ARRAY_SIZE(wm8940_reg_defaults))
-               return -1;
-
-       cache[reg] = value;
-
-       return 0;
-}
-
-static int wm8940_write(struct snd_soc_codec *codec, unsigned int reg,
-                       unsigned int value)
-{
-       int ret;
-       u8 data[3] = { reg,
-                      (value & 0xff00) >> 8,
-                      (value & 0x00ff)
-       };
-
-       wm8940_write_reg_cache(codec, reg, value);
-
-       ret = codec->hw_write(codec->control_data, data, 3);
-
-       if (ret < 0)
-               return ret;
-       else if (ret != 3)
-               return -EIO;
-       return 0;
-}
-
 static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" };
 static const struct soc_enum wm8940_adc_companding_enum
 = SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 1, 4, wm8940_companding);
@@ -348,14 +304,14 @@ error_ret:
        return ret;
 }
 
-#define wm8940_reset(c) wm8940_write(c, WM8940_SOFTRESET, 0);
+#define wm8940_reset(c) snd_soc_write(c, WM8940_SOFTRESET, 0);
 
 static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai,
                              unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
-       u16 iface = wm8940_read_reg_cache(codec, WM8940_IFACE) & 0xFE67;
-       u16 clk = wm8940_read_reg_cache(codec, WM8940_CLOCK) & 0x1fe;
+       u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFE67;
+       u16 clk = snd_soc_read(codec, WM8940_CLOCK) & 0x1fe;
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBM_CFM:
@@ -366,7 +322,7 @@ static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai,
        default:
                return -EINVAL;
        }
-       wm8940_write(codec, WM8940_CLOCK, clk);
+       snd_soc_write(codec, WM8940_CLOCK, clk);
 
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
@@ -399,7 +355,7 @@ static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai,
                break;
        }
 
-       wm8940_write(codec, WM8940_IFACE, iface);
+       snd_soc_write(codec, WM8940_IFACE, iface);
 
        return 0;
 }
@@ -411,9 +367,9 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->card->codec;
-       u16 iface = wm8940_read_reg_cache(codec, WM8940_IFACE) & 0xFD9F;
-       u16 addcntrl = wm8940_read_reg_cache(codec, WM8940_ADDCNTRL) & 0xFFF1;
-       u16 companding =  wm8940_read_reg_cache(codec,
+       u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F;
+       u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1;
+       u16 companding =  snd_soc_read(codec,
                                                WM8940_COMPANDINGCTL) & 0xFFDF;
        int ret;
 
@@ -442,7 +398,7 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
        case SNDRV_PCM_RATE_48000:
                break;
        }
-       ret = wm8940_write(codec, WM8940_ADDCNTRL, addcntrl);
+       ret = snd_soc_write(codec, WM8940_ADDCNTRL, addcntrl);
        if (ret)
                goto error_ret;
 
@@ -462,10 +418,10 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
                iface |= (3 << 5);
                break;
        }
-       ret = wm8940_write(codec, WM8940_COMPANDINGCTL, companding);
+       ret = snd_soc_write(codec, WM8940_COMPANDINGCTL, companding);
        if (ret)
                goto error_ret;
-       ret = wm8940_write(codec, WM8940_IFACE, iface);
+       ret = snd_soc_write(codec, WM8940_IFACE, iface);
 
 error_ret:
        return ret;
@@ -474,19 +430,19 @@ error_ret:
 static int wm8940_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u16 mute_reg = wm8940_read_reg_cache(codec, WM8940_DAC) & 0xffbf;
+       u16 mute_reg = snd_soc_read(codec, WM8940_DAC) & 0xffbf;
 
        if (mute)
                mute_reg |= 0x40;
 
-       return wm8940_write(codec, WM8940_DAC, mute_reg);
+       return snd_soc_write(codec, WM8940_DAC, mute_reg);
 }
 
 static int wm8940_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
        u16 val;
-       u16 pwr_reg = wm8940_read_reg_cache(codec, WM8940_POWER1) & 0x1F0;
+       u16 pwr_reg = snd_soc_read(codec, WM8940_POWER1) & 0x1F0;
        int ret = 0;
 
        switch (level) {
@@ -494,26 +450,26 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec,
                /* ensure bufioen and biasen */
                pwr_reg |= (1 << 2) | (1 << 3);
                /* Enable thermal shutdown */
-               val = wm8940_read_reg_cache(codec, WM8940_OUTPUTCTL);
-               ret = wm8940_write(codec, WM8940_OUTPUTCTL, val | 0x2);
+               val = snd_soc_read(codec, WM8940_OUTPUTCTL);
+               ret = snd_soc_write(codec, WM8940_OUTPUTCTL, val | 0x2);
                if (ret)
                        break;
                /* set vmid to 75k */
-               ret = wm8940_write(codec, WM8940_POWER1, pwr_reg | 0x1);
+               ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1);
                break;
        case SND_SOC_BIAS_PREPARE:
                /* ensure bufioen and biasen */
                pwr_reg |= (1 << 2) | (1 << 3);
-               ret = wm8940_write(codec, WM8940_POWER1, pwr_reg | 0x1);
+               ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1);
                break;
        case SND_SOC_BIAS_STANDBY:
                /* ensure bufioen and biasen */
                pwr_reg |= (1 << 2) | (1 << 3);
                /* set vmid to 300k for standby */
-               ret = wm8940_write(codec, WM8940_POWER1, pwr_reg | 0x2);
+               ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x2);
                break;
        case SND_SOC_BIAS_OFF:
-               ret = wm8940_write(codec, WM8940_POWER1, pwr_reg);
+               ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg);
                break;
        }
 
@@ -587,36 +543,36 @@ static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai,
        u16 reg;
 
        /* Turn off PLL */
-       reg = wm8940_read_reg_cache(codec, WM8940_POWER1);
-       wm8940_write(codec, WM8940_POWER1, reg & 0x1df);
+       reg = snd_soc_read(codec, WM8940_POWER1);
+       snd_soc_write(codec, WM8940_POWER1, reg & 0x1df);
 
        if (freq_in == 0 || freq_out == 0) {
                /* Clock CODEC directly from MCLK */
-               reg = wm8940_read_reg_cache(codec, WM8940_CLOCK);
-               wm8940_write(codec, WM8940_CLOCK, reg & 0x0ff);
+               reg = snd_soc_read(codec, WM8940_CLOCK);
+               snd_soc_write(codec, WM8940_CLOCK, reg & 0x0ff);
                /* Pll power down */
-               wm8940_write(codec, WM8940_PLLN, (1 << 7));
+               snd_soc_write(codec, WM8940_PLLN, (1 << 7));
                return 0;
        }
 
        /* Pll is followed by a frequency divide by 4 */
        pll_factors(freq_out*4, freq_in);
        if (pll_div.k)
-               wm8940_write(codec, WM8940_PLLN,
+               snd_soc_write(codec, WM8940_PLLN,
                             (pll_div.pre_scale << 4) | pll_div.n | (1 << 6));
        else /* No factional component */
-               wm8940_write(codec, WM8940_PLLN,
+               snd_soc_write(codec, WM8940_PLLN,
                             (pll_div.pre_scale << 4) | pll_div.n);
-       wm8940_write(codec, WM8940_PLLK1, pll_div.k >> 18);
-       wm8940_write(codec, WM8940_PLLK2, (pll_div.k >> 9) & 0x1ff);
-       wm8940_write(codec, WM8940_PLLK3, pll_div.k & 0x1ff);
+       snd_soc_write(codec, WM8940_PLLK1, pll_div.k >> 18);
+       snd_soc_write(codec, WM8940_PLLK2, (pll_div.k >> 9) & 0x1ff);
+       snd_soc_write(codec, WM8940_PLLK3, pll_div.k & 0x1ff);
        /* Enable the PLL */
-       reg = wm8940_read_reg_cache(codec, WM8940_POWER1);
-       wm8940_write(codec, WM8940_POWER1, reg | 0x020);
+       reg = snd_soc_read(codec, WM8940_POWER1);
+       snd_soc_write(codec, WM8940_POWER1, reg | 0x020);
 
        /* Run CODEC from PLL instead of MCLK */
-       reg = wm8940_read_reg_cache(codec, WM8940_CLOCK);
-       wm8940_write(codec, WM8940_CLOCK, reg | 0x100);
+       reg = snd_soc_read(codec, WM8940_CLOCK);
+       snd_soc_write(codec, WM8940_CLOCK, reg | 0x100);
 
        return 0;
 }
@@ -648,16 +604,16 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
 
        switch (div_id) {
        case WM8940_BCLKDIV:
-               reg = wm8940_read_reg_cache(codec, WM8940_CLOCK) & 0xFFEF3;
-               ret = wm8940_write(codec, WM8940_CLOCK, reg | (div << 2));
+               reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFEF3;
+               ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 2));
                break;
        case WM8940_MCLKDIV:
-               reg = wm8940_read_reg_cache(codec, WM8940_CLOCK) & 0xFF1F;
-               ret = wm8940_write(codec, WM8940_CLOCK, reg | (div << 5));
+               reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFF1F;
+               ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 5));
                break;
        case WM8940_OPCLKDIV:
-               reg = wm8940_read_reg_cache(codec, WM8940_ADDCNTRL) & 0xFFCF;
-               ret = wm8940_write(codec, WM8940_ADDCNTRL, reg | (div << 4));
+               reg = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFCF;
+               ret = snd_soc_write(codec, WM8940_ADDCNTRL, reg | (div << 4));
                break;
        }
        return ret;
@@ -808,7 +764,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8940 = {
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8940);
 
-static int wm8940_register(struct wm8940_priv *wm8940)
+static int wm8940_register(struct wm8940_priv *wm8940,
+                          enum snd_soc_control_type control)
 {
        struct wm8940_setup_data *pdata = wm8940->codec.dev->platform_data;
        struct snd_soc_codec *codec = &wm8940->codec;
@@ -825,8 +782,6 @@ static int wm8940_register(struct wm8940_priv *wm8940)
        codec->private_data = wm8940;
        codec->name = "WM8940";
        codec->owner = THIS_MODULE;
-       codec->read = wm8940_read_reg_cache;
-       codec->write = wm8940_write;
        codec->bias_level = SND_SOC_BIAS_OFF;
        codec->set_bias_level = wm8940_set_bias_level;
        codec->dai = &wm8940_dai;
@@ -834,6 +789,12 @@ static int wm8940_register(struct wm8940_priv *wm8940)
        codec->reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults);
        codec->reg_cache = &wm8940->reg_cache;
 
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
+       if (ret == 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
+
        memcpy(codec->reg_cache, wm8940_reg_defaults,
               sizeof(wm8940_reg_defaults));
 
@@ -847,15 +808,15 @@ static int wm8940_register(struct wm8940_priv *wm8940)
 
        wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       ret = wm8940_write(codec, WM8940_POWER1, 0x180);
+       ret = snd_soc_write(codec, WM8940_POWER1, 0x180);
        if (ret < 0)
                return ret;
 
        if (!pdata)
                dev_warn(codec->dev, "No platform data supplied\n");
        else {
-               reg = wm8940_read_reg_cache(codec, WM8940_OUTPUTCTL);
-               ret = wm8940_write(codec, WM8940_OUTPUTCTL, reg | pdata->vroi);
+               reg = snd_soc_read(codec, WM8940_OUTPUTCTL);
+               ret = snd_soc_write(codec, WM8940_OUTPUTCTL, reg | pdata->vroi);
                if (ret < 0)
                        return ret;
        }
@@ -904,7 +865,7 @@ static int wm8940_i2c_probe(struct i2c_client *i2c,
        codec->control_data = i2c;
        codec->dev = &i2c->dev;
 
-       return wm8940_register(wm8940);
+       return wm8940_register(wm8940, SND_SOC_I2C);
 }
 
 static int __devexit wm8940_i2c_remove(struct i2c_client *client)
@@ -916,6 +877,21 @@ static int __devexit wm8940_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm8940_i2c_suspend(struct i2c_client *client, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&client->dev);
+}
+
+static int wm8940_i2c_resume(struct i2c_client *client)
+{
+       return snd_soc_resume_device(&client->dev);
+}
+#else
+#define wm8940_i2c_suspend NULL
+#define wm8940_i2c_resume NULL
+#endif
+
 static const struct i2c_device_id wm8940_i2c_id[] = {
        { "wm8940", 0 },
        { }
@@ -929,6 +905,8 @@ static struct i2c_driver wm8940_i2c_driver = {
        },
        .probe = wm8940_i2c_probe,
        .remove = __devexit_p(wm8940_i2c_remove),
+       .suspend = wm8940_i2c_suspend,
+       .resume = wm8940_i2c_resume,
        .id_table = wm8940_i2c_id,
 };
 
index e224d8add170148b3f54608904cb3e75aa669804..f59703be61c84b6213600edab224c0f71ab63bf6 100644 (file)
@@ -69,61 +69,7 @@ struct wm8960_priv {
        struct snd_soc_codec codec;
 };
 
-/*
- * read wm8960 register cache
- */
-static inline unsigned int wm8960_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg == WM8960_RESET)
-               return 0;
-       if (reg >= WM8960_CACHEREGNUM)
-               return -1;
-       return cache[reg];
-}
-
-/*
- * write wm8960 register cache
- */
-static inline void wm8960_write_reg_cache(struct snd_soc_codec *codec,
-       u16 reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg >= WM8960_CACHEREGNUM)
-               return;
-       cache[reg] = value;
-}
-
-static inline unsigned int wm8960_read(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       return wm8960_read_reg_cache(codec, reg);
-}
-
-/*
- * write to the WM8960 register space
- */
-static int wm8960_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
-{
-       u8 data[2];
-
-       /* data is
-        *   D15..D9 WM8960 register offset
-        *   D8...D0 register data
-        */
-       data[0] = (reg << 1) | ((value >> 8) & 0x0001);
-       data[1] = value & 0x00ff;
-
-       wm8960_write_reg_cache(codec, reg, value);
-       if (codec->hw_write(codec->control_data, data, 2) == 2)
-               return 0;
-       else
-               return -EIO;
-}
-
-#define wm8960_reset(c)        wm8960_write(c, WM8960_RESET, 0)
+#define wm8960_reset(c)        snd_soc_write(c, WM8960_RESET, 0)
 
 /* enumerated controls */
 static const char *wm8960_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
@@ -420,7 +366,7 @@ static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai,
        }
 
        /* set iface */
-       wm8960_write(codec, WM8960_IFACE1, iface);
+       snd_soc_write(codec, WM8960_IFACE1, iface);
        return 0;
 }
 
@@ -431,7 +377,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->card->codec;
-       u16 iface = wm8960_read(codec, WM8960_IFACE1) & 0xfff3;
+       u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3;
 
        /* bit size */
        switch (params_format(params)) {
@@ -446,19 +392,19 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
        }
 
        /* set iface */
-       wm8960_write(codec, WM8960_IFACE1, iface);
+       snd_soc_write(codec, WM8960_IFACE1, iface);
        return 0;
 }
 
 static int wm8960_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u16 mute_reg = wm8960_read(codec, WM8960_DACCTL1) & 0xfff7;
+       u16 mute_reg = snd_soc_read(codec, WM8960_DACCTL1) & 0xfff7;
 
        if (mute)
-               wm8960_write(codec, WM8960_DACCTL1, mute_reg | 0x8);
+               snd_soc_write(codec, WM8960_DACCTL1, mute_reg | 0x8);
        else
-               wm8960_write(codec, WM8960_DACCTL1, mute_reg);
+               snd_soc_write(codec, WM8960_DACCTL1, mute_reg);
        return 0;
 }
 
@@ -474,16 +420,16 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec,
 
        case SND_SOC_BIAS_PREPARE:
                /* Set VMID to 2x50k */
-               reg = wm8960_read(codec, WM8960_POWER1);
+               reg = snd_soc_read(codec, WM8960_POWER1);
                reg &= ~0x180;
                reg |= 0x80;
-               wm8960_write(codec, WM8960_POWER1, reg);
+               snd_soc_write(codec, WM8960_POWER1, reg);
                break;
 
        case SND_SOC_BIAS_STANDBY:
                if (codec->bias_level == SND_SOC_BIAS_OFF) {
                        /* Enable anti-pop features */
-                       wm8960_write(codec, WM8960_APOP1,
+                       snd_soc_write(codec, WM8960_APOP1,
                                     WM8960_POBCTRL | WM8960_SOFT_ST |
                                     WM8960_BUFDCOPEN | WM8960_BUFIOEN);
 
@@ -491,43 +437,43 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec,
                        reg = WM8960_DISOP;
                        if (pdata)
                                reg |= pdata->dres << 4;
-                       wm8960_write(codec, WM8960_APOP2, reg);
+                       snd_soc_write(codec, WM8960_APOP2, reg);
 
                        msleep(400);
 
-                       wm8960_write(codec, WM8960_APOP2, 0);
+                       snd_soc_write(codec, WM8960_APOP2, 0);
 
                        /* Enable & ramp VMID at 2x50k */
-                       reg = wm8960_read(codec, WM8960_POWER1);
+                       reg = snd_soc_read(codec, WM8960_POWER1);
                        reg |= 0x80;
-                       wm8960_write(codec, WM8960_POWER1, reg);
+                       snd_soc_write(codec, WM8960_POWER1, reg);
                        msleep(100);
 
                        /* Enable VREF */
-                       wm8960_write(codec, WM8960_POWER1, reg | WM8960_VREF);
+                       snd_soc_write(codec, WM8960_POWER1, reg | WM8960_VREF);
 
                        /* Disable anti-pop features */
-                       wm8960_write(codec, WM8960_APOP1, WM8960_BUFIOEN);
+                       snd_soc_write(codec, WM8960_APOP1, WM8960_BUFIOEN);
                }
 
                /* Set VMID to 2x250k */
-               reg = wm8960_read(codec, WM8960_POWER1);
+               reg = snd_soc_read(codec, WM8960_POWER1);
                reg &= ~0x180;
                reg |= 0x100;
-               wm8960_write(codec, WM8960_POWER1, reg);
+               snd_soc_write(codec, WM8960_POWER1, reg);
                break;
 
        case SND_SOC_BIAS_OFF:
                /* Enable anti-pop features */
-               wm8960_write(codec, WM8960_APOP1,
+               snd_soc_write(codec, WM8960_APOP1,
                             WM8960_POBCTRL | WM8960_SOFT_ST |
                             WM8960_BUFDCOPEN | WM8960_BUFIOEN);
 
                /* Disable VMID and VREF, let them discharge */
-               wm8960_write(codec, WM8960_POWER1, 0);
+               snd_soc_write(codec, WM8960_POWER1, 0);
                msleep(600);
 
-               wm8960_write(codec, WM8960_APOP1, 0);
+               snd_soc_write(codec, WM8960_APOP1, 0);
                break;
        }
 
@@ -610,33 +556,33 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai,
 
        /* Disable the PLL: even if we are changing the frequency the
         * PLL needs to be disabled while we do so. */
-       wm8960_write(codec, WM8960_CLOCK1,
-                    wm8960_read(codec, WM8960_CLOCK1) & ~1);
-       wm8960_write(codec, WM8960_POWER2,
-                    wm8960_read(codec, WM8960_POWER2) & ~1);
+       snd_soc_write(codec, WM8960_CLOCK1,
+                    snd_soc_read(codec, WM8960_CLOCK1) & ~1);
+       snd_soc_write(codec, WM8960_POWER2,
+                    snd_soc_read(codec, WM8960_POWER2) & ~1);
 
        if (!freq_in || !freq_out)
                return 0;
 
-       reg = wm8960_read(codec, WM8960_PLL1) & ~0x3f;
+       reg = snd_soc_read(codec, WM8960_PLL1) & ~0x3f;
        reg |= pll_div.pre_div << 4;
        reg |= pll_div.n;
 
        if (pll_div.k) {
                reg |= 0x20;
 
-               wm8960_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f);
-               wm8960_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff);
-               wm8960_write(codec, WM8960_PLL4, pll_div.k & 0x1ff);
+               snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f);
+               snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff);
+               snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0x1ff);
        }
-       wm8960_write(codec, WM8960_PLL1, reg);
+       snd_soc_write(codec, WM8960_PLL1, reg);
 
        /* Turn it on */
-       wm8960_write(codec, WM8960_POWER2,
-                    wm8960_read(codec, WM8960_POWER2) | 1);
+       snd_soc_write(codec, WM8960_POWER2,
+                    snd_soc_read(codec, WM8960_POWER2) | 1);
        msleep(250);
-       wm8960_write(codec, WM8960_CLOCK1,
-                    wm8960_read(codec, WM8960_CLOCK1) | 1);
+       snd_soc_write(codec, WM8960_CLOCK1,
+                    snd_soc_read(codec, WM8960_CLOCK1) | 1);
 
        return 0;
 }
@@ -649,28 +595,28 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
 
        switch (div_id) {
        case WM8960_SYSCLKSEL:
-               reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1fe;
-               wm8960_write(codec, WM8960_CLOCK1, reg | div);
+               reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1fe;
+               snd_soc_write(codec, WM8960_CLOCK1, reg | div);
                break;
        case WM8960_SYSCLKDIV:
-               reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1f9;
-               wm8960_write(codec, WM8960_CLOCK1, reg | div);
+               reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1f9;
+               snd_soc_write(codec, WM8960_CLOCK1, reg | div);
                break;
        case WM8960_DACDIV:
-               reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1c7;
-               wm8960_write(codec, WM8960_CLOCK1, reg | div);
+               reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1c7;
+               snd_soc_write(codec, WM8960_CLOCK1, reg | div);
                break;
        case WM8960_OPCLKDIV:
-               reg = wm8960_read(codec, WM8960_PLL1) & 0x03f;
-               wm8960_write(codec, WM8960_PLL1, reg | div);
+               reg = snd_soc_read(codec, WM8960_PLL1) & 0x03f;
+               snd_soc_write(codec, WM8960_PLL1, reg | div);
                break;
        case WM8960_DCLKDIV:
-               reg = wm8960_read(codec, WM8960_CLOCK2) & 0x03f;
-               wm8960_write(codec, WM8960_CLOCK2, reg | div);
+               reg = snd_soc_read(codec, WM8960_CLOCK2) & 0x03f;
+               snd_soc_write(codec, WM8960_CLOCK2, reg | div);
                break;
        case WM8960_TOCLKSEL:
-               reg = wm8960_read(codec, WM8960_ADDCTL1) & 0x1fd;
-               wm8960_write(codec, WM8960_ADDCTL1, reg | div);
+               reg = snd_soc_read(codec, WM8960_ADDCTL1) & 0x1fd;
+               snd_soc_write(codec, WM8960_ADDCTL1, reg | div);
                break;
        default:
                return -EINVAL;
@@ -801,7 +747,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8960 = {
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960);
 
-static int wm8960_register(struct wm8960_priv *wm8960)
+static int wm8960_register(struct wm8960_priv *wm8960,
+                          enum snd_soc_control_type control)
 {
        struct wm8960_data *pdata = wm8960->codec.dev->platform_data;
        struct snd_soc_codec *codec = &wm8960->codec;
@@ -810,7 +757,8 @@ static int wm8960_register(struct wm8960_priv *wm8960)
 
        if (wm8960_codec) {
                dev_err(codec->dev, "Another WM8960 is registered\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err;
        }
 
        if (!pdata) {
@@ -829,8 +777,6 @@ static int wm8960_register(struct wm8960_priv *wm8960)
        codec->private_data = wm8960;
        codec->name = "WM8960";
        codec->owner = THIS_MODULE;
-       codec->read = wm8960_read_reg_cache;
-       codec->write = wm8960_write;
        codec->bias_level = SND_SOC_BIAS_OFF;
        codec->set_bias_level = wm8960_set_bias_level;
        codec->dai = &wm8960_dai;
@@ -840,10 +786,16 @@ static int wm8960_register(struct wm8960_priv *wm8960)
 
        memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg));
 
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
        ret = wm8960_reset(codec);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to issue reset\n");
-               return ret;
+               goto err;
        }
 
        wm8960_dai.dev = codec->dev;
@@ -851,43 +803,48 @@ static int wm8960_register(struct wm8960_priv *wm8960)
        wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Latch the update bits */
-       reg = wm8960_read(codec, WM8960_LINVOL);
-       wm8960_write(codec, WM8960_LINVOL, reg | 0x100);
-       reg = wm8960_read(codec, WM8960_RINVOL);
-       wm8960_write(codec, WM8960_RINVOL, reg | 0x100);
-       reg = wm8960_read(codec, WM8960_LADC);
-       wm8960_write(codec, WM8960_LADC, reg | 0x100);
-       reg = wm8960_read(codec, WM8960_RADC);
-       wm8960_write(codec, WM8960_RADC, reg | 0x100);
-       reg = wm8960_read(codec, WM8960_LDAC);
-       wm8960_write(codec, WM8960_LDAC, reg | 0x100);
-       reg = wm8960_read(codec, WM8960_RDAC);
-       wm8960_write(codec, WM8960_RDAC, reg | 0x100);
-       reg = wm8960_read(codec, WM8960_LOUT1);
-       wm8960_write(codec, WM8960_LOUT1, reg | 0x100);
-       reg = wm8960_read(codec, WM8960_ROUT1);
-       wm8960_write(codec, WM8960_ROUT1, reg | 0x100);
-       reg = wm8960_read(codec, WM8960_LOUT2);
-       wm8960_write(codec, WM8960_LOUT2, reg | 0x100);
-       reg = wm8960_read(codec, WM8960_ROUT2);
-       wm8960_write(codec, WM8960_ROUT2, reg | 0x100);
+       reg = snd_soc_read(codec, WM8960_LINVOL);
+       snd_soc_write(codec, WM8960_LINVOL, reg | 0x100);
+       reg = snd_soc_read(codec, WM8960_RINVOL);
+       snd_soc_write(codec, WM8960_RINVOL, reg | 0x100);
+       reg = snd_soc_read(codec, WM8960_LADC);
+       snd_soc_write(codec, WM8960_LADC, reg | 0x100);
+       reg = snd_soc_read(codec, WM8960_RADC);
+       snd_soc_write(codec, WM8960_RADC, reg | 0x100);
+       reg = snd_soc_read(codec, WM8960_LDAC);
+       snd_soc_write(codec, WM8960_LDAC, reg | 0x100);
+       reg = snd_soc_read(codec, WM8960_RDAC);
+       snd_soc_write(codec, WM8960_RDAC, reg | 0x100);
+       reg = snd_soc_read(codec, WM8960_LOUT1);
+       snd_soc_write(codec, WM8960_LOUT1, reg | 0x100);
+       reg = snd_soc_read(codec, WM8960_ROUT1);
+       snd_soc_write(codec, WM8960_ROUT1, reg | 0x100);
+       reg = snd_soc_read(codec, WM8960_LOUT2);
+       snd_soc_write(codec, WM8960_LOUT2, reg | 0x100);
+       reg = snd_soc_read(codec, WM8960_ROUT2);
+       snd_soc_write(codec, WM8960_ROUT2, reg | 0x100);
 
        wm8960_codec = codec;
 
        ret = snd_soc_register_codec(codec);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               return ret;
+               goto err;
        }
 
        ret = snd_soc_register_dai(&wm8960_dai);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
-               snd_soc_unregister_codec(codec);
-               return ret;
+               goto err_codec;
        }
 
        return 0;
+
+err_codec:
+       snd_soc_unregister_codec(codec);
+err:
+       kfree(wm8960);
+       return ret;
 }
 
 static void wm8960_unregister(struct wm8960_priv *wm8960)
@@ -910,14 +867,13 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        codec = &wm8960->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
 
        i2c_set_clientdata(i2c, wm8960);
        codec->control_data = i2c;
 
        codec->dev = &i2c->dev;
 
-       return wm8960_register(wm8960);
+       return wm8960_register(wm8960, SND_SOC_I2C);
 }
 
 static __devexit int wm8960_i2c_remove(struct i2c_client *client)
@@ -927,6 +883,21 @@ static __devexit int wm8960_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm8960_i2c_suspend(struct i2c_client *client, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&client->dev);
+}
+
+static int wm8960_i2c_resume(struct i2c_client *client)
+{
+       return snd_soc_resume_device(&client->dev);
+}
+#else
+#define wm8960_i2c_suspend NULL
+#define wm8960_i2c_resume NULL
+#endif
+
 static const struct i2c_device_id wm8960_i2c_id[] = {
        { "wm8960", 0 },
        { }
@@ -940,6 +911,8 @@ static struct i2c_driver wm8960_i2c_driver = {
        },
        .probe =    wm8960_i2c_probe,
        .remove =   __devexit_p(wm8960_i2c_remove),
+       .suspend =  wm8960_i2c_suspend,
+       .resume =   wm8960_i2c_resume,
        .id_table = wm8960_i2c_id,
 };
 
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
new file mode 100644 (file)
index 0000000..5030320
--- /dev/null
@@ -0,0 +1,1265 @@
+/*
+ * wm8961.c  --  WM8961 ALSA SoC Audio driver
+ *
+ * Author: Mark Brown
+ *
+ * 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.
+ *
+ * Currently unimplemented features:
+ *  - ALC
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8961.h"
+
+#define WM8961_MAX_REGISTER                     0xFC
+
+static u16 wm8961_reg_defaults[] = {
+       0x009F,     /* R0   - Left Input volume */
+       0x009F,     /* R1   - Right Input volume */
+       0x0000,     /* R2   - LOUT1 volume */
+       0x0000,     /* R3   - ROUT1 volume */
+       0x0020,     /* R4   - Clocking1 */
+       0x0008,     /* R5   - ADC & DAC Control 1 */
+       0x0000,     /* R6   - ADC & DAC Control 2 */
+       0x000A,     /* R7   - Audio Interface 0 */
+       0x01F4,     /* R8   - Clocking2 */
+       0x0000,     /* R9   - Audio Interface 1 */
+       0x00FF,     /* R10  - Left DAC volume */
+       0x00FF,     /* R11  - Right DAC volume */
+       0x0000,     /* R12 */
+       0x0000,     /* R13 */
+       0x0040,     /* R14  - Audio Interface 2 */
+       0x0000,     /* R15  - Software Reset */
+       0x0000,     /* R16 */
+       0x007B,     /* R17  - ALC1 */
+       0x0000,     /* R18  - ALC2 */
+       0x0032,     /* R19  - ALC3 */
+       0x0000,     /* R20  - Noise Gate */
+       0x00C0,     /* R21  - Left ADC volume */
+       0x00C0,     /* R22  - Right ADC volume */
+       0x0120,     /* R23  - Additional control(1) */
+       0x0000,     /* R24  - Additional control(2) */
+       0x0000,     /* R25  - Pwr Mgmt (1) */
+       0x0000,     /* R26  - Pwr Mgmt (2) */
+       0x0000,     /* R27  - Additional Control (3) */
+       0x0000,     /* R28  - Anti-pop */
+       0x0000,     /* R29 */
+       0x005F,     /* R30  - Clocking 3 */
+       0x0000,     /* R31 */
+       0x0000,     /* R32  - ADCL signal path */
+       0x0000,     /* R33  - ADCR signal path */
+       0x0000,     /* R34 */
+       0x0000,     /* R35 */
+       0x0000,     /* R36 */
+       0x0000,     /* R37 */
+       0x0000,     /* R38 */
+       0x0000,     /* R39 */
+       0x0000,     /* R40  - LOUT2 volume */
+       0x0000,     /* R41  - ROUT2 volume */
+       0x0000,     /* R42 */
+       0x0000,     /* R43 */
+       0x0000,     /* R44 */
+       0x0000,     /* R45 */
+       0x0000,     /* R46 */
+       0x0000,     /* R47  - Pwr Mgmt (3) */
+       0x0023,     /* R48  - Additional Control (4) */
+       0x0000,     /* R49  - Class D Control 1 */
+       0x0000,     /* R50 */
+       0x0003,     /* R51  - Class D Control 2 */
+       0x0000,     /* R52 */
+       0x0000,     /* R53 */
+       0x0000,     /* R54 */
+       0x0000,     /* R55 */
+       0x0106,     /* R56  - Clocking 4 */
+       0x0000,     /* R57  - DSP Sidetone 0 */
+       0x0000,     /* R58  - DSP Sidetone 1 */
+       0x0000,     /* R59 */
+       0x0000,     /* R60  - DC Servo 0 */
+       0x0000,     /* R61  - DC Servo 1 */
+       0x0000,     /* R62 */
+       0x015E,     /* R63  - DC Servo 3 */
+       0x0010,     /* R64 */
+       0x0010,     /* R65  - DC Servo 5 */
+       0x0000,     /* R66 */
+       0x0001,     /* R67 */
+       0x0003,     /* R68  - Analogue PGA Bias */
+       0x0000,     /* R69  - Analogue HP 0 */
+       0x0060,     /* R70 */
+       0x01FB,     /* R71  - Analogue HP 2 */
+       0x0000,     /* R72  - Charge Pump 1 */
+       0x0065,     /* R73 */
+       0x005F,     /* R74 */
+       0x0059,     /* R75 */
+       0x006B,     /* R76 */
+       0x0038,     /* R77 */
+       0x000C,     /* R78 */
+       0x000A,     /* R79 */
+       0x006B,     /* R80 */
+       0x0000,     /* R81 */
+       0x0000,     /* R82  - Charge Pump B */
+       0x0087,     /* R83 */
+       0x0000,     /* R84 */
+       0x005C,     /* R85 */
+       0x0000,     /* R86 */
+       0x0000,     /* R87  - Write Sequencer 1 */
+       0x0000,     /* R88  - Write Sequencer 2 */
+       0x0000,     /* R89  - Write Sequencer 3 */
+       0x0000,     /* R90  - Write Sequencer 4 */
+       0x0000,     /* R91  - Write Sequencer 5 */
+       0x0000,     /* R92  - Write Sequencer 6 */
+       0x0000,     /* R93  - Write Sequencer 7 */
+       0x0000,     /* R94 */
+       0x0000,     /* R95 */
+       0x0000,     /* R96 */
+       0x0000,     /* R97 */
+       0x0000,     /* R98 */
+       0x0000,     /* R99 */
+       0x0000,     /* R100 */
+       0x0000,     /* R101 */
+       0x0000,     /* R102 */
+       0x0000,     /* R103 */
+       0x0000,     /* R104 */
+       0x0000,     /* R105 */
+       0x0000,     /* R106 */
+       0x0000,     /* R107 */
+       0x0000,     /* R108 */
+       0x0000,     /* R109 */
+       0x0000,     /* R110 */
+       0x0000,     /* R111 */
+       0x0000,     /* R112 */
+       0x0000,     /* R113 */
+       0x0000,     /* R114 */
+       0x0000,     /* R115 */
+       0x0000,     /* R116 */
+       0x0000,     /* R117 */
+       0x0000,     /* R118 */
+       0x0000,     /* R119 */
+       0x0000,     /* R120 */
+       0x0000,     /* R121 */
+       0x0000,     /* R122 */
+       0x0000,     /* R123 */
+       0x0000,     /* R124 */
+       0x0000,     /* R125 */
+       0x0000,     /* R126 */
+       0x0000,     /* R127 */
+       0x0000,     /* R128 */
+       0x0000,     /* R129 */
+       0x0000,     /* R130 */
+       0x0000,     /* R131 */
+       0x0000,     /* R132 */
+       0x0000,     /* R133 */
+       0x0000,     /* R134 */
+       0x0000,     /* R135 */
+       0x0000,     /* R136 */
+       0x0000,     /* R137 */
+       0x0000,     /* R138 */
+       0x0000,     /* R139 */
+       0x0000,     /* R140 */
+       0x0000,     /* R141 */
+       0x0000,     /* R142 */
+       0x0000,     /* R143 */
+       0x0000,     /* R144 */
+       0x0000,     /* R145 */
+       0x0000,     /* R146 */
+       0x0000,     /* R147 */
+       0x0000,     /* R148 */
+       0x0000,     /* R149 */
+       0x0000,     /* R150 */
+       0x0000,     /* R151 */
+       0x0000,     /* R152 */
+       0x0000,     /* R153 */
+       0x0000,     /* R154 */
+       0x0000,     /* R155 */
+       0x0000,     /* R156 */
+       0x0000,     /* R157 */
+       0x0000,     /* R158 */
+       0x0000,     /* R159 */
+       0x0000,     /* R160 */
+       0x0000,     /* R161 */
+       0x0000,     /* R162 */
+       0x0000,     /* R163 */
+       0x0000,     /* R164 */
+       0x0000,     /* R165 */
+       0x0000,     /* R166 */
+       0x0000,     /* R167 */
+       0x0000,     /* R168 */
+       0x0000,     /* R169 */
+       0x0000,     /* R170 */
+       0x0000,     /* R171 */
+       0x0000,     /* R172 */
+       0x0000,     /* R173 */
+       0x0000,     /* R174 */
+       0x0000,     /* R175 */
+       0x0000,     /* R176 */
+       0x0000,     /* R177 */
+       0x0000,     /* R178 */
+       0x0000,     /* R179 */
+       0x0000,     /* R180 */
+       0x0000,     /* R181 */
+       0x0000,     /* R182 */
+       0x0000,     /* R183 */
+       0x0000,     /* R184 */
+       0x0000,     /* R185 */
+       0x0000,     /* R186 */
+       0x0000,     /* R187 */
+       0x0000,     /* R188 */
+       0x0000,     /* R189 */
+       0x0000,     /* R190 */
+       0x0000,     /* R191 */
+       0x0000,     /* R192 */
+       0x0000,     /* R193 */
+       0x0000,     /* R194 */
+       0x0000,     /* R195 */
+       0x0030,     /* R196 */
+       0x0006,     /* R197 */
+       0x0000,     /* R198 */
+       0x0060,     /* R199 */
+       0x0000,     /* R200 */
+       0x003F,     /* R201 */
+       0x0000,     /* R202 */
+       0x0000,     /* R203 */
+       0x0000,     /* R204 */
+       0x0001,     /* R205 */
+       0x0000,     /* R206 */
+       0x0181,     /* R207 */
+       0x0005,     /* R208 */
+       0x0008,     /* R209 */
+       0x0008,     /* R210 */
+       0x0000,     /* R211 */
+       0x013B,     /* R212 */
+       0x0000,     /* R213 */
+       0x0000,     /* R214 */
+       0x0000,     /* R215 */
+       0x0000,     /* R216 */
+       0x0070,     /* R217 */
+       0x0000,     /* R218 */
+       0x0000,     /* R219 */
+       0x0000,     /* R220 */
+       0x0000,     /* R221 */
+       0x0000,     /* R222 */
+       0x0003,     /* R223 */
+       0x0000,     /* R224 */
+       0x0000,     /* R225 */
+       0x0001,     /* R226 */
+       0x0008,     /* R227 */
+       0x0000,     /* R228 */
+       0x0000,     /* R229 */
+       0x0000,     /* R230 */
+       0x0000,     /* R231 */
+       0x0004,     /* R232 */
+       0x0000,     /* R233 */
+       0x0000,     /* R234 */
+       0x0000,     /* R235 */
+       0x0000,     /* R236 */
+       0x0000,     /* R237 */
+       0x0080,     /* R238 */
+       0x0000,     /* R239 */
+       0x0000,     /* R240 */
+       0x0000,     /* R241 */
+       0x0000,     /* R242 */
+       0x0000,     /* R243 */
+       0x0000,     /* R244 */
+       0x0052,     /* R245 */
+       0x0110,     /* R246 */
+       0x0040,     /* R247 */
+       0x0000,     /* R248 */
+       0x0030,     /* R249 */
+       0x0000,     /* R250 */
+       0x0000,     /* R251 */
+       0x0001,     /* R252 - General test 1 */
+};
+
+struct wm8961_priv {
+       struct snd_soc_codec codec;
+       int sysclk;
+       u16 reg_cache[WM8961_MAX_REGISTER];
+};
+
+static int wm8961_volatile_register(unsigned int reg)
+{
+       switch (reg) {
+       case WM8961_SOFTWARE_RESET:
+       case WM8961_WRITE_SEQUENCER_7:
+       case WM8961_DC_SERVO_1:
+               return 1;
+
+       default:
+               return 0;
+       }
+}
+
+static int wm8961_reset(struct snd_soc_codec *codec)
+{
+       return snd_soc_write(codec, WM8961_SOFTWARE_RESET, 0);
+}
+
+/*
+ * The headphone output supports special anti-pop sequences giving
+ * silent power up and power down.
+ */
+static int wm8961_hp_event(struct snd_soc_dapm_widget *w,
+                          struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       u16 hp_reg = snd_soc_read(codec, WM8961_ANALOGUE_HP_0);
+       u16 cp_reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_1);
+       u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2);
+       u16 dcs_reg = snd_soc_read(codec, WM8961_DC_SERVO_1);
+       int timeout = 500;
+
+       if (event & SND_SOC_DAPM_POST_PMU) {
+               /* Make sure the output is shorted */
+               hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT);
+               snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
+
+               /* Enable the charge pump */
+               cp_reg |= WM8961_CP_ENA;
+               snd_soc_write(codec, WM8961_CHARGE_PUMP_1, cp_reg);
+               mdelay(5);
+
+               /* Enable the PGA */
+               pwr_reg |= WM8961_LOUT1_PGA | WM8961_ROUT1_PGA;
+               snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
+
+               /* Enable the amplifier */
+               hp_reg |= WM8961_HPR_ENA | WM8961_HPL_ENA;
+               snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
+
+               /* Second stage enable */
+               hp_reg |= WM8961_HPR_ENA_DLY | WM8961_HPL_ENA_DLY;
+               snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
+
+               /* Enable the DC servo & trigger startup */
+               dcs_reg |=
+                       WM8961_DCS_ENA_CHAN_HPR | WM8961_DCS_TRIG_STARTUP_HPR |
+                       WM8961_DCS_ENA_CHAN_HPL | WM8961_DCS_TRIG_STARTUP_HPL;
+               dev_dbg(codec->dev, "Enabling DC servo\n");
+
+               snd_soc_write(codec, WM8961_DC_SERVO_1, dcs_reg);
+               do {
+                       msleep(1);
+                       dcs_reg = snd_soc_read(codec, WM8961_DC_SERVO_1);
+               } while (--timeout &&
+                        dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR |
+                               WM8961_DCS_TRIG_STARTUP_HPL));
+               if (dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR |
+                              WM8961_DCS_TRIG_STARTUP_HPL))
+                       dev_err(codec->dev, "DC servo timed out\n");
+               else
+                       dev_dbg(codec->dev, "DC servo startup complete\n");
+
+               /* Enable the output stage */
+               hp_reg |= WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP;
+               snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
+
+               /* Remove the short on the output stage */
+               hp_reg |= WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT;
+               snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
+       }
+
+       if (event & SND_SOC_DAPM_PRE_PMD) {
+               /* Short the output */
+               hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT);
+               snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
+
+               /* Disable the output stage */
+               hp_reg &= ~(WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP);
+               snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
+
+               /* Disable DC offset cancellation */
+               dcs_reg &= ~(WM8961_DCS_ENA_CHAN_HPR |
+                            WM8961_DCS_ENA_CHAN_HPL);
+               snd_soc_write(codec, WM8961_DC_SERVO_1, dcs_reg);
+
+               /* Finish up */
+               hp_reg &= ~(WM8961_HPR_ENA_DLY | WM8961_HPR_ENA |
+                           WM8961_HPL_ENA_DLY | WM8961_HPL_ENA);
+               snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg);
+
+               /* Disable the PGA */
+               pwr_reg &= ~(WM8961_LOUT1_PGA | WM8961_ROUT1_PGA);
+               snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
+
+               /* Disable the charge pump */
+               dev_dbg(codec->dev, "Disabling charge pump\n");
+               snd_soc_write(codec, WM8961_CHARGE_PUMP_1,
+                            cp_reg & ~WM8961_CP_ENA);
+       }
+
+       return 0;
+}
+
+static int wm8961_spk_event(struct snd_soc_dapm_widget *w,
+                           struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2);
+       u16 spk_reg = snd_soc_read(codec, WM8961_CLASS_D_CONTROL_1);
+
+       if (event & SND_SOC_DAPM_POST_PMU) {
+               /* Enable the PGA */
+               pwr_reg |= WM8961_SPKL_PGA | WM8961_SPKR_PGA;
+               snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
+
+               /* Enable the amplifier */
+               spk_reg |= WM8961_SPKL_ENA | WM8961_SPKR_ENA;
+               snd_soc_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg);
+       }
+
+       if (event & SND_SOC_DAPM_PRE_PMD) {
+               /* Enable the amplifier */
+               spk_reg &= ~(WM8961_SPKL_ENA | WM8961_SPKR_ENA);
+               snd_soc_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg);
+
+               /* Enable the PGA */
+               pwr_reg &= ~(WM8961_SPKL_PGA | WM8961_SPKR_PGA);
+               snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
+       }
+
+       return 0;
+}
+
+static const char *adc_hpf_text[] = {
+       "Hi-fi", "Voice 1", "Voice 2", "Voice 3",
+};
+
+static const struct soc_enum adc_hpf =
+       SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_2, 7, 4, adc_hpf_text);
+
+static const char *dac_deemph_text[] = {
+       "None", "32kHz", "44.1kHz", "48kHz",
+};
+
+static const struct soc_enum dac_deemph =
+       SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_1, 1, 4, dac_deemph_text);
+
+static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
+static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0);
+static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1);
+static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0);
+static unsigned int boost_tlv[] = {
+       TLV_DB_RANGE_HEAD(4),
+       0, 0, TLV_DB_SCALE_ITEM(0,  0, 0),
+       1, 1, TLV_DB_SCALE_ITEM(13, 0, 0),
+       2, 2, TLV_DB_SCALE_ITEM(20, 0, 0),
+       3, 3, TLV_DB_SCALE_ITEM(29, 0, 0),
+};
+static const DECLARE_TLV_DB_SCALE(pga_tlv, -2325, 75, 0);
+
+static const struct snd_kcontrol_new wm8961_snd_controls[] = {
+SOC_DOUBLE_R_TLV("Headphone Volume", WM8961_LOUT1_VOLUME, WM8961_ROUT1_VOLUME,
+                0, 127, 0, out_tlv),
+SOC_DOUBLE_TLV("Headphone Secondary Volume", WM8961_ANALOGUE_HP_2,
+              6, 3, 7, 0, hp_sec_tlv),
+SOC_DOUBLE_R("Headphone ZC Switch", WM8961_LOUT1_VOLUME, WM8961_ROUT1_VOLUME,
+            7, 1, 0),
+
+SOC_DOUBLE_R_TLV("Speaker Volume", WM8961_LOUT2_VOLUME, WM8961_ROUT2_VOLUME,
+                0, 127, 0, out_tlv),
+SOC_DOUBLE_R("Speaker ZC Switch", WM8961_LOUT2_VOLUME, WM8961_ROUT2_VOLUME,
+          7, 1, 0),
+SOC_SINGLE("Speaker AC Gain", WM8961_CLASS_D_CONTROL_2, 0, 7, 0),
+
+SOC_SINGLE("DAC x128 OSR Switch", WM8961_ADC_DAC_CONTROL_2, 0, 1, 0),
+SOC_ENUM("DAC Deemphasis", dac_deemph),
+SOC_SINGLE("DAC Soft Mute Switch", WM8961_ADC_DAC_CONTROL_2, 3, 1, 0),
+
+SOC_DOUBLE_R_TLV("Sidetone Volume", WM8961_DSP_SIDETONE_0,
+                WM8961_DSP_SIDETONE_1, 4, 12, 0, sidetone_tlv),
+
+SOC_SINGLE("ADC High Pass Filter Switch", WM8961_ADC_DAC_CONTROL_1, 0, 1, 0),
+SOC_ENUM("ADC High Pass Filter Mode", adc_hpf),
+
+SOC_DOUBLE_R_TLV("Capture Volume",
+                WM8961_LEFT_ADC_VOLUME, WM8961_RIGHT_ADC_VOLUME,
+                1, 119, 0, adc_tlv),
+SOC_DOUBLE_R_TLV("Capture Boost Volume",
+                WM8961_ADCL_SIGNAL_PATH, WM8961_ADCR_SIGNAL_PATH,
+                4, 3, 0, boost_tlv),
+SOC_DOUBLE_R_TLV("Capture PGA Volume",
+                WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME,
+                0, 62, 0, pga_tlv),
+SOC_DOUBLE_R("Capture PGA ZC Switch",
+            WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME,
+            6, 1, 1),
+SOC_DOUBLE_R("Capture PGA Switch",
+            WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME,
+            7, 1, 1),
+};
+
+static const char *sidetone_text[] = {
+       "None", "Left", "Right"
+};
+
+static const struct soc_enum dacl_sidetone =
+       SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_0, 2, 3, sidetone_text);
+
+static const struct soc_enum dacr_sidetone =
+       SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_1, 2, 3, sidetone_text);
+
+static const struct snd_kcontrol_new dacl_mux =
+       SOC_DAPM_ENUM("DACL Sidetone", dacl_sidetone);
+
+static const struct snd_kcontrol_new dacr_mux =
+       SOC_DAPM_ENUM("DACR Sidetone", dacr_sidetone);
+
+static const struct snd_soc_dapm_widget wm8961_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("LINPUT"),
+SND_SOC_DAPM_INPUT("RINPUT"),
+
+SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8961_CLOCKING2, 4, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("Left Input", WM8961_PWR_MGMT_1, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right Input", WM8961_PWR_MGMT_1, 4, 0, NULL, 0),
+
+SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", WM8961_PWR_MGMT_1, 3, 0),
+SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", WM8961_PWR_MGMT_1, 2, 0),
+
+SND_SOC_DAPM_MICBIAS("MICBIAS", WM8961_PWR_MGMT_1, 1, 0),
+
+SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &dacl_mux),
+SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &dacr_mux),
+
+SND_SOC_DAPM_DAC("DACL", "HiFi Playback", WM8961_PWR_MGMT_2, 8, 0),
+SND_SOC_DAPM_DAC("DACR", "HiFi Playback", WM8961_PWR_MGMT_2, 7, 0),
+
+/* Handle as a mono path for DCS */
+SND_SOC_DAPM_PGA_E("Headphone Output", SND_SOC_NOPM,
+                  4, 0, NULL, 0, wm8961_hp_event,
+                  SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_PGA_E("Speaker Output", SND_SOC_NOPM,
+                  4, 0, NULL, 0, wm8961_spk_event,
+                  SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+SND_SOC_DAPM_OUTPUT("HP_L"),
+SND_SOC_DAPM_OUTPUT("HP_R"),
+SND_SOC_DAPM_OUTPUT("SPK_LN"),
+SND_SOC_DAPM_OUTPUT("SPK_LP"),
+SND_SOC_DAPM_OUTPUT("SPK_RN"),
+SND_SOC_DAPM_OUTPUT("SPK_RP"),
+};
+
+
+static const struct snd_soc_dapm_route audio_paths[] = {
+       { "DACL", NULL, "CLK_DSP" },
+       { "DACL", NULL, "DACL Sidetone" },
+       { "DACR", NULL, "CLK_DSP" },
+       { "DACR", NULL, "DACR Sidetone" },
+
+       { "DACL Sidetone", "Left", "ADCL" },
+       { "DACL Sidetone", "Right", "ADCR" },
+
+       { "DACR Sidetone", "Left", "ADCL" },
+       { "DACR Sidetone", "Right", "ADCR" },
+
+       { "HP_L", NULL, "Headphone Output" },
+       { "HP_R", NULL, "Headphone Output" },
+       { "Headphone Output", NULL, "DACL" },
+       { "Headphone Output", NULL, "DACR" },
+
+       { "SPK_LN", NULL, "Speaker Output" },
+       { "SPK_LP", NULL, "Speaker Output" },
+       { "SPK_RN", NULL, "Speaker Output" },
+       { "SPK_RP", NULL, "Speaker Output" },
+
+       { "Speaker Output", NULL, "DACL" },
+       { "Speaker Output", NULL, "DACR" },
+
+       { "ADCL", NULL, "Left Input" },
+       { "ADCL", NULL, "CLK_DSP" },
+       { "ADCR", NULL, "Right Input" },
+       { "ADCR", NULL, "CLK_DSP" },
+
+       { "Left Input", NULL, "LINPUT" },
+       { "Right Input", NULL, "RINPUT" },
+
+};
+
+/* Values for CLK_SYS_RATE */
+static struct {
+       int ratio;
+       u16 val;
+} wm8961_clk_sys_ratio[] = {
+       {  64,  0 },
+       {  128, 1 },
+       {  192, 2 },
+       {  256, 3 },
+       {  384, 4 },
+       {  512, 5 },
+       {  768, 6 },
+       { 1024, 7 },
+       { 1408, 8 },
+       { 1536, 9 },
+};
+
+/* Values for SAMPLE_RATE */
+static struct {
+       int rate;
+       u16 val;
+} wm8961_srate[] = {
+       { 48000, 0 },
+       { 44100, 0 },
+       { 32000, 1 },
+       { 22050, 2 },
+       { 24000, 2 },
+       { 16000, 3 },
+       { 11250, 4 },
+       { 12000, 4 },
+       {  8000, 5 },
+};
+
+static int wm8961_hw_params(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params,
+                           struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8961_priv *wm8961 = codec->private_data;
+       int i, best, target, fs;
+       u16 reg;
+
+       fs = params_rate(params);
+
+       if (!wm8961->sysclk) {
+               dev_err(codec->dev, "MCLK has not been specified\n");
+               return -EINVAL;
+       }
+
+       /* Find the closest sample rate for the filters */
+       best = 0;
+       for (i = 0; i < ARRAY_SIZE(wm8961_srate); i++) {
+               if (abs(wm8961_srate[i].rate - fs) <
+                   abs(wm8961_srate[best].rate - fs))
+                       best = i;
+       }
+       reg = snd_soc_read(codec, WM8961_ADDITIONAL_CONTROL_3);
+       reg &= ~WM8961_SAMPLE_RATE_MASK;
+       reg |= wm8961_srate[best].val;
+       snd_soc_write(codec, WM8961_ADDITIONAL_CONTROL_3, reg);
+       dev_dbg(codec->dev, "Selected SRATE %dHz for %dHz\n",
+               wm8961_srate[best].rate, fs);
+
+       /* Select a CLK_SYS/fs ratio equal to or higher than required */
+       target = wm8961->sysclk / fs;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && target < 64) {
+               dev_err(codec->dev,
+                       "SYSCLK must be at least 64*fs for DAC\n");
+               return -EINVAL;
+       }
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && target < 256) {
+               dev_err(codec->dev,
+                       "SYSCLK must be at least 256*fs for ADC\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(wm8961_clk_sys_ratio); i++) {
+               if (wm8961_clk_sys_ratio[i].ratio >= target)
+                       break;
+       }
+       if (i == ARRAY_SIZE(wm8961_clk_sys_ratio)) {
+               dev_err(codec->dev, "Unable to generate CLK_SYS_RATE\n");
+               return -EINVAL;
+       }
+       dev_dbg(codec->dev, "Selected CLK_SYS_RATE of %d for %d/%d=%d\n",
+               wm8961_clk_sys_ratio[i].ratio, wm8961->sysclk, fs,
+               wm8961->sysclk / fs);
+
+       reg = snd_soc_read(codec, WM8961_CLOCKING_4);
+       reg &= ~WM8961_CLK_SYS_RATE_MASK;
+       reg |= wm8961_clk_sys_ratio[i].val << WM8961_CLK_SYS_RATE_SHIFT;
+       snd_soc_write(codec, WM8961_CLOCKING_4, reg);
+
+       reg = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_0);
+       reg &= ~WM8961_WL_MASK;
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               reg |= 1 << WM8961_WL_SHIFT;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               reg |= 2 << WM8961_WL_SHIFT;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               reg |= 3 << WM8961_WL_SHIFT;
+               break;
+       default:
+               return -EINVAL;
+       }
+       snd_soc_write(codec, WM8961_AUDIO_INTERFACE_0, reg);
+
+       /* Sloping stop-band filter is recommended for <= 24kHz */
+       reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2);
+       if (fs <= 24000)
+               reg |= WM8961_DACSLOPE;
+       else
+               reg &= WM8961_DACSLOPE;
+       snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg);
+
+       return 0;
+}
+
+static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+                            unsigned int freq,
+                            int dir)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8961_priv *wm8961 = codec->private_data;
+       u16 reg = snd_soc_read(codec, WM8961_CLOCKING1);
+
+       if (freq > 33000000) {
+               dev_err(codec->dev, "MCLK must be <33MHz\n");
+               return -EINVAL;
+       }
+
+       if (freq > 16500000) {
+               dev_dbg(codec->dev, "Using MCLK/2 for %dHz MCLK\n", freq);
+               reg |= WM8961_MCLKDIV;
+               freq /= 2;
+       } else {
+               dev_dbg(codec->dev, "Using MCLK/1 for %dHz MCLK\n", freq);
+               reg &= WM8961_MCLKDIV;
+       }
+
+       snd_soc_write(codec, WM8961_CLOCKING1, reg);
+
+       wm8961->sysclk = freq;
+
+       return 0;
+}
+
+static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u16 aif = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_0);
+
+       aif &= ~(WM8961_BCLKINV | WM8961_LRP |
+                WM8961_MS | WM8961_FORMAT_MASK);
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               aif |= WM8961_MS;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_RIGHT_J:
+               break;
+
+       case SND_SOC_DAIFMT_LEFT_J:
+               aif |= 1;
+               break;
+
+       case SND_SOC_DAIFMT_I2S:
+               aif |= 2;
+               break;
+
+       case SND_SOC_DAIFMT_DSP_B:
+               aif |= WM8961_LRP;
+       case SND_SOC_DAIFMT_DSP_A:
+               aif |= 3;
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+               case SND_SOC_DAIFMT_IB_NF:
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               aif |= WM8961_LRP;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               aif |= WM8961_BCLKINV;
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               aif |= WM8961_BCLKINV | WM8961_LRP;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return snd_soc_write(codec, WM8961_AUDIO_INTERFACE_0, aif);
+}
+
+static int wm8961_set_tristate(struct snd_soc_dai *dai, int tristate)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u16 reg = snd_soc_read(codec, WM8961_ADDITIONAL_CONTROL_2);
+
+       if (tristate)
+               reg |= WM8961_TRIS;
+       else
+               reg &= ~WM8961_TRIS;
+
+       return snd_soc_write(codec, WM8961_ADDITIONAL_CONTROL_2, reg);
+}
+
+static int wm8961_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u16 reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_1);
+
+       if (mute)
+               reg |= WM8961_DACMU;
+       else
+               reg &= ~WM8961_DACMU;
+
+       msleep(17);
+
+       return snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_1, reg);
+}
+
+static int wm8961_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u16 reg;
+
+       switch (div_id) {
+       case WM8961_BCLK:
+               reg = snd_soc_read(codec, WM8961_CLOCKING2);
+               reg &= ~WM8961_BCLKDIV_MASK;
+               reg |= div;
+               snd_soc_write(codec, WM8961_CLOCKING2, reg);
+               break;
+
+       case WM8961_LRCLK:
+               reg = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_2);
+               reg &= ~WM8961_LRCLK_RATE_MASK;
+               reg |= div;
+               snd_soc_write(codec, WM8961_AUDIO_INTERFACE_2, reg);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int wm8961_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
+{
+       u16 reg;
+
+       /* This is all slightly unusual since we have no bypass paths
+        * and the output amplifier structure means we can just slam
+        * the biases straight up rather than having to ramp them
+        * slowly.
+        */
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+               break;
+
+       case SND_SOC_BIAS_PREPARE:
+               if (codec->bias_level == SND_SOC_BIAS_STANDBY) {
+                       /* Enable bias generation */
+                       reg = snd_soc_read(codec, WM8961_ANTI_POP);
+                       reg |= WM8961_BUFIOEN | WM8961_BUFDCOPEN;
+                       snd_soc_write(codec, WM8961_ANTI_POP, reg);
+
+                       /* VMID=2*50k, VREF */
+                       reg = snd_soc_read(codec, WM8961_PWR_MGMT_1);
+                       reg &= ~WM8961_VMIDSEL_MASK;
+                       reg |= (1 << WM8961_VMIDSEL_SHIFT) | WM8961_VREF;
+                       snd_soc_write(codec, WM8961_PWR_MGMT_1, reg);
+               }
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->bias_level == SND_SOC_BIAS_PREPARE) {
+                       /* VREF off */
+                       reg = snd_soc_read(codec, WM8961_PWR_MGMT_1);
+                       reg &= ~WM8961_VREF;
+                       snd_soc_write(codec, WM8961_PWR_MGMT_1, reg);
+
+                       /* Bias generation off */
+                       reg = snd_soc_read(codec, WM8961_ANTI_POP);
+                       reg &= ~(WM8961_BUFIOEN | WM8961_BUFDCOPEN);
+                       snd_soc_write(codec, WM8961_ANTI_POP, reg);
+
+                       /* VMID off */
+                       reg = snd_soc_read(codec, WM8961_PWR_MGMT_1);
+                       reg &= ~WM8961_VMIDSEL_MASK;
+                       snd_soc_write(codec, WM8961_PWR_MGMT_1, reg);
+               }
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               break;
+       }
+
+       codec->bias_level = level;
+
+       return 0;
+}
+
+
+#define WM8961_RATES SNDRV_PCM_RATE_8000_48000
+
+#define WM8961_FORMATS \
+       (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+       SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops wm8961_dai_ops = {
+       .hw_params = wm8961_hw_params,
+       .set_sysclk = wm8961_set_sysclk,
+       .set_fmt = wm8961_set_fmt,
+       .digital_mute = wm8961_digital_mute,
+       .set_tristate = wm8961_set_tristate,
+       .set_clkdiv = wm8961_set_clkdiv,
+};
+
+struct snd_soc_dai wm8961_dai = {
+       .name = "WM8961",
+       .playback = {
+               .stream_name = "HiFi Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = WM8961_RATES,
+               .formats = WM8961_FORMATS,},
+       .capture = {
+               .stream_name = "HiFi Capture",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = WM8961_RATES,
+               .formats = WM8961_FORMATS,},
+       .ops = &wm8961_dai_ops,
+};
+EXPORT_SYMBOL_GPL(wm8961_dai);
+
+
+static struct snd_soc_codec *wm8961_codec;
+
+static int wm8961_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec;
+       int ret = 0;
+
+       if (wm8961_codec == NULL) {
+               dev_err(&pdev->dev, "Codec device not registered\n");
+               return -ENODEV;
+       }
+
+       socdev->card->codec = wm8961_codec;
+       codec = wm8961_codec;
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to create pcms: %d\n", ret);
+               goto pcm_err;
+       }
+
+       snd_soc_add_controls(codec, wm8961_snd_controls,
+                               ARRAY_SIZE(wm8961_snd_controls));
+       snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets,
+                                 ARRAY_SIZE(wm8961_dapm_widgets));
+       snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
+       snd_soc_dapm_new_widgets(codec);
+
+       ret = snd_soc_init_card(socdev);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to register card: %d\n", ret);
+               goto card_err;
+       }
+
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+pcm_err:
+       return ret;
+}
+
+static int wm8961_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int wm8961_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+
+       wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+       return 0;
+}
+
+static int wm8961_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+       u16 *reg_cache = codec->reg_cache;
+       int i;
+
+       for (i = 0; i < codec->reg_cache_size; i++) {
+               if (i == WM8961_SOFTWARE_RESET)
+                       continue;
+
+               snd_soc_write(codec, i, reg_cache[i]);
+       }
+
+       wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       return 0;
+}
+#else
+#define wm8961_suspend NULL
+#define wm8961_resume NULL
+#endif
+
+struct snd_soc_codec_device soc_codec_dev_wm8961 = {
+       .probe =        wm8961_probe,
+       .remove =       wm8961_remove,
+       .suspend =      wm8961_suspend,
+       .resume =       wm8961_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8961);
+
+static int wm8961_register(struct wm8961_priv *wm8961)
+{
+       struct snd_soc_codec *codec = &wm8961->codec;
+       int ret;
+       u16 reg;
+
+       if (wm8961_codec) {
+               dev_err(codec->dev, "Another WM8961 is registered\n");
+               ret = -EINVAL;
+               goto err;
+       }
+
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       codec->private_data = wm8961;
+       codec->name = "WM8961";
+       codec->owner = THIS_MODULE;
+       codec->dai = &wm8961_dai;
+       codec->num_dai = 1;
+       codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache);
+       codec->reg_cache = &wm8961->reg_cache;
+       codec->bias_level = SND_SOC_BIAS_OFF;
+       codec->set_bias_level = wm8961_set_bias_level;
+       codec->volatile_register = wm8961_volatile_register;
+
+       memcpy(codec->reg_cache, wm8961_reg_defaults,
+              sizeof(wm8961_reg_defaults));
+
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
+       reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET);
+       if (reg != 0x1801) {
+               dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* This isn't volatile - readback doesn't correspond to write */
+       reg = codec->hw_read(codec, WM8961_RIGHT_INPUT_VOLUME);
+       dev_info(codec->dev, "WM8961 family %d revision %c\n",
+                (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT,
+                ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT)
+                + 'A');
+
+       ret = wm8961_reset(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to issue reset\n");
+               return ret;
+       }
+
+       /* Enable class W */
+       reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B);
+       reg |= WM8961_CP_DYN_PWR_MASK;
+       snd_soc_write(codec, WM8961_CHARGE_PUMP_B, reg);
+
+       /* Latch volume update bits (right channel only, we always
+        * write both out) and default ZC on. */
+       reg = snd_soc_read(codec, WM8961_ROUT1_VOLUME);
+       snd_soc_write(codec, WM8961_ROUT1_VOLUME,
+                    reg | WM8961_LO1ZC | WM8961_OUT1VU);
+       snd_soc_write(codec, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC);
+       reg = snd_soc_read(codec, WM8961_ROUT2_VOLUME);
+       snd_soc_write(codec, WM8961_ROUT2_VOLUME,
+                    reg | WM8961_SPKRZC | WM8961_SPKVU);
+       snd_soc_write(codec, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC);
+
+       reg = snd_soc_read(codec, WM8961_RIGHT_ADC_VOLUME);
+       snd_soc_write(codec, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU);
+       reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME);
+       snd_soc_write(codec, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU);
+
+       /* Use soft mute by default */
+       reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2);
+       reg |= WM8961_DACSMM;
+       snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg);
+
+       /* Use automatic clocking mode by default; for now this is all
+        * we support.
+        */
+       reg = snd_soc_read(codec, WM8961_CLOCKING_3);
+       reg &= ~WM8961_MANUAL_MODE;
+       snd_soc_write(codec, WM8961_CLOCKING_3, reg);
+
+       wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       wm8961_dai.dev = codec->dev;
+
+       wm8961_codec = codec;
+
+       ret = snd_soc_register_codec(codec);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+               return ret;
+       }
+
+       ret = snd_soc_register_dai(&wm8961_dai);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
+               snd_soc_unregister_codec(codec);
+               return ret;
+       }
+
+       return 0;
+
+err:
+       kfree(wm8961);
+       return ret;
+}
+
+static void wm8961_unregister(struct wm8961_priv *wm8961)
+{
+       wm8961_set_bias_level(&wm8961->codec, SND_SOC_BIAS_OFF);
+       snd_soc_unregister_dai(&wm8961_dai);
+       snd_soc_unregister_codec(&wm8961->codec);
+       kfree(wm8961);
+       wm8961_codec = NULL;
+}
+
+static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct wm8961_priv *wm8961;
+       struct snd_soc_codec *codec;
+
+       wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL);
+       if (wm8961 == NULL)
+               return -ENOMEM;
+
+       codec = &wm8961->codec;
+
+       i2c_set_clientdata(i2c, wm8961);
+       codec->control_data = i2c;
+
+       codec->dev = &i2c->dev;
+
+       return wm8961_register(wm8961);
+}
+
+static __devexit int wm8961_i2c_remove(struct i2c_client *client)
+{
+       struct wm8961_priv *wm8961 = i2c_get_clientdata(client);
+       wm8961_unregister(wm8961);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int wm8961_i2c_suspend(struct i2c_client *client, pm_message_t state)
+{
+       return snd_soc_suspend_device(&client->dev);
+}
+
+static int wm8961_i2c_resume(struct i2c_client *client)
+{
+       return snd_soc_resume_device(&client->dev);
+}
+#else
+#define wm8961_i2c_suspend NULL
+#define wm8961_i2c_resume NULL
+#endif
+
+static const struct i2c_device_id wm8961_i2c_id[] = {
+       { "wm8961", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id);
+
+static struct i2c_driver wm8961_i2c_driver = {
+       .driver = {
+               .name = "wm8961",
+               .owner = THIS_MODULE,
+       },
+       .probe =    wm8961_i2c_probe,
+       .remove =   __devexit_p(wm8961_i2c_remove),
+       .suspend =  wm8961_i2c_suspend,
+       .resume =   wm8961_i2c_resume,
+       .id_table = wm8961_i2c_id,
+};
+
+static int __init wm8961_modinit(void)
+{
+       int ret;
+
+       ret = i2c_add_driver(&wm8961_i2c_driver);
+       if (ret != 0) {
+               printk(KERN_ERR "Failed to register WM8961 I2C driver: %d\n",
+                      ret);
+       }
+
+       return ret;
+}
+module_init(wm8961_modinit);
+
+static void __exit wm8961_exit(void)
+{
+       i2c_del_driver(&wm8961_i2c_driver);
+}
+module_exit(wm8961_exit);
+
+
+MODULE_DESCRIPTION("ASoC WM8961 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8961.h b/sound/soc/codecs/wm8961.h
new file mode 100644 (file)
index 0000000..5513bfd
--- /dev/null
@@ -0,0 +1,866 @@
+/*
+ * wm8961.h  --  WM8961 Soc Audio driver
+ *
+ * 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 _WM8961_H
+#define _WM8961_H
+
+#include <sound/soc.h>
+
+extern struct snd_soc_codec_device soc_codec_dev_wm8961;
+extern struct snd_soc_dai wm8961_dai;
+
+#define WM8961_BCLK  1
+#define WM8961_LRCLK 2
+
+#define WM8961_BCLK_DIV_1    0
+#define WM8961_BCLK_DIV_1_5  1
+#define WM8961_BCLK_DIV_2    2
+#define WM8961_BCLK_DIV_3    3
+#define WM8961_BCLK_DIV_4    4
+#define WM8961_BCLK_DIV_5_5  5
+#define WM8961_BCLK_DIV_6    6
+#define WM8961_BCLK_DIV_8    7
+#define WM8961_BCLK_DIV_11   8
+#define WM8961_BCLK_DIV_12   9
+#define WM8961_BCLK_DIV_16  10
+#define WM8961_BCLK_DIV_24  11
+#define WM8961_BCLK_DIV_32  13
+
+
+/*
+ * Register values.
+ */
+#define WM8961_LEFT_INPUT_VOLUME                0x00
+#define WM8961_RIGHT_INPUT_VOLUME               0x01
+#define WM8961_LOUT1_VOLUME                     0x02
+#define WM8961_ROUT1_VOLUME                     0x03
+#define WM8961_CLOCKING1                        0x04
+#define WM8961_ADC_DAC_CONTROL_1                0x05
+#define WM8961_ADC_DAC_CONTROL_2                0x06
+#define WM8961_AUDIO_INTERFACE_0                0x07
+#define WM8961_CLOCKING2                        0x08
+#define WM8961_AUDIO_INTERFACE_1                0x09
+#define WM8961_LEFT_DAC_VOLUME                  0x0A
+#define WM8961_RIGHT_DAC_VOLUME                 0x0B
+#define WM8961_AUDIO_INTERFACE_2                0x0E
+#define WM8961_SOFTWARE_RESET                   0x0F
+#define WM8961_ALC1                             0x11
+#define WM8961_ALC2                             0x12
+#define WM8961_ALC3                             0x13
+#define WM8961_NOISE_GATE                       0x14
+#define WM8961_LEFT_ADC_VOLUME                  0x15
+#define WM8961_RIGHT_ADC_VOLUME                 0x16
+#define WM8961_ADDITIONAL_CONTROL_1             0x17
+#define WM8961_ADDITIONAL_CONTROL_2             0x18
+#define WM8961_PWR_MGMT_1                       0x19
+#define WM8961_PWR_MGMT_2                       0x1A
+#define WM8961_ADDITIONAL_CONTROL_3             0x1B
+#define WM8961_ANTI_POP                         0x1C
+#define WM8961_CLOCKING_3                       0x1E
+#define WM8961_ADCL_SIGNAL_PATH                 0x20
+#define WM8961_ADCR_SIGNAL_PATH                 0x21
+#define WM8961_LOUT2_VOLUME                     0x28
+#define WM8961_ROUT2_VOLUME                     0x29
+#define WM8961_PWR_MGMT_3                       0x2F
+#define WM8961_ADDITIONAL_CONTROL_4             0x30
+#define WM8961_CLASS_D_CONTROL_1                0x31
+#define WM8961_CLASS_D_CONTROL_2                0x33
+#define WM8961_CLOCKING_4                       0x38
+#define WM8961_DSP_SIDETONE_0                   0x39
+#define WM8961_DSP_SIDETONE_1                   0x3A
+#define WM8961_DC_SERVO_0                       0x3C
+#define WM8961_DC_SERVO_1                       0x3D
+#define WM8961_DC_SERVO_3                       0x3F
+#define WM8961_DC_SERVO_5                       0x41
+#define WM8961_ANALOGUE_PGA_BIAS                0x44
+#define WM8961_ANALOGUE_HP_0                    0x45
+#define WM8961_ANALOGUE_HP_2                    0x47
+#define WM8961_CHARGE_PUMP_1                    0x48
+#define WM8961_CHARGE_PUMP_B                    0x52
+#define WM8961_WRITE_SEQUENCER_1                0x57
+#define WM8961_WRITE_SEQUENCER_2                0x58
+#define WM8961_WRITE_SEQUENCER_3                0x59
+#define WM8961_WRITE_SEQUENCER_4                0x5A
+#define WM8961_WRITE_SEQUENCER_5                0x5B
+#define WM8961_WRITE_SEQUENCER_6                0x5C
+#define WM8961_WRITE_SEQUENCER_7                0x5D
+#define WM8961_GENERAL_TEST_1                   0xFC
+
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Left Input volume
+ */
+#define WM8961_IPVU                             0x0100  /* IPVU */
+#define WM8961_IPVU_MASK                        0x0100  /* IPVU */
+#define WM8961_IPVU_SHIFT                            8  /* IPVU */
+#define WM8961_IPVU_WIDTH                            1  /* IPVU */
+#define WM8961_LINMUTE                          0x0080  /* LINMUTE */
+#define WM8961_LINMUTE_MASK                     0x0080  /* LINMUTE */
+#define WM8961_LINMUTE_SHIFT                         7  /* LINMUTE */
+#define WM8961_LINMUTE_WIDTH                         1  /* LINMUTE */
+#define WM8961_LIZC                             0x0040  /* LIZC */
+#define WM8961_LIZC_MASK                        0x0040  /* LIZC */
+#define WM8961_LIZC_SHIFT                            6  /* LIZC */
+#define WM8961_LIZC_WIDTH                            1  /* LIZC */
+#define WM8961_LINVOL_MASK                      0x003F  /* LINVOL - [5:0] */
+#define WM8961_LINVOL_SHIFT                          0  /* LINVOL - [5:0] */
+#define WM8961_LINVOL_WIDTH                          6  /* LINVOL - [5:0] */
+
+/*
+ * R1 (0x01) - Right Input volume
+ */
+#define WM8961_DEVICE_ID_MASK                   0xF000  /* DEVICE_ID - [15:12] */
+#define WM8961_DEVICE_ID_SHIFT                      12  /* DEVICE_ID - [15:12] */
+#define WM8961_DEVICE_ID_WIDTH                       4  /* DEVICE_ID - [15:12] */
+#define WM8961_CHIP_REV_MASK                    0x0E00  /* CHIP_REV - [11:9] */
+#define WM8961_CHIP_REV_SHIFT                        9  /* CHIP_REV - [11:9] */
+#define WM8961_CHIP_REV_WIDTH                        3  /* CHIP_REV - [11:9] */
+#define WM8961_IPVU                             0x0100  /* IPVU */
+#define WM8961_IPVU_MASK                        0x0100  /* IPVU */
+#define WM8961_IPVU_SHIFT                            8  /* IPVU */
+#define WM8961_IPVU_WIDTH                            1  /* IPVU */
+#define WM8961_RINMUTE                          0x0080  /* RINMUTE */
+#define WM8961_RINMUTE_MASK                     0x0080  /* RINMUTE */
+#define WM8961_RINMUTE_SHIFT                         7  /* RINMUTE */
+#define WM8961_RINMUTE_WIDTH                         1  /* RINMUTE */
+#define WM8961_RIZC                             0x0040  /* RIZC */
+#define WM8961_RIZC_MASK                        0x0040  /* RIZC */
+#define WM8961_RIZC_SHIFT                            6  /* RIZC */
+#define WM8961_RIZC_WIDTH                            1  /* RIZC */
+#define WM8961_RINVOL_MASK                      0x003F  /* RINVOL - [5:0] */
+#define WM8961_RINVOL_SHIFT                          0  /* RINVOL - [5:0] */
+#define WM8961_RINVOL_WIDTH                          6  /* RINVOL - [5:0] */
+
+/*
+ * R2 (0x02) - LOUT1 volume
+ */
+#define WM8961_OUT1VU                           0x0100  /* OUT1VU */
+#define WM8961_OUT1VU_MASK                      0x0100  /* OUT1VU */
+#define WM8961_OUT1VU_SHIFT                          8  /* OUT1VU */
+#define WM8961_OUT1VU_WIDTH                          1  /* OUT1VU */
+#define WM8961_LO1ZC                            0x0080  /* LO1ZC */
+#define WM8961_LO1ZC_MASK                       0x0080  /* LO1ZC */
+#define WM8961_LO1ZC_SHIFT                           7  /* LO1ZC */
+#define WM8961_LO1ZC_WIDTH                           1  /* LO1ZC */
+#define WM8961_LOUT1VOL_MASK                    0x007F  /* LOUT1VOL - [6:0] */
+#define WM8961_LOUT1VOL_SHIFT                        0  /* LOUT1VOL - [6:0] */
+#define WM8961_LOUT1VOL_WIDTH                        7  /* LOUT1VOL - [6:0] */
+
+/*
+ * R3 (0x03) - ROUT1 volume
+ */
+#define WM8961_OUT1VU                           0x0100  /* OUT1VU */
+#define WM8961_OUT1VU_MASK                      0x0100  /* OUT1VU */
+#define WM8961_OUT1VU_SHIFT                          8  /* OUT1VU */
+#define WM8961_OUT1VU_WIDTH                          1  /* OUT1VU */
+#define WM8961_RO1ZC                            0x0080  /* RO1ZC */
+#define WM8961_RO1ZC_MASK                       0x0080  /* RO1ZC */
+#define WM8961_RO1ZC_SHIFT                           7  /* RO1ZC */
+#define WM8961_RO1ZC_WIDTH                           1  /* RO1ZC */
+#define WM8961_ROUT1VOL_MASK                    0x007F  /* ROUT1VOL - [6:0] */
+#define WM8961_ROUT1VOL_SHIFT                        0  /* ROUT1VOL - [6:0] */
+#define WM8961_ROUT1VOL_WIDTH                        7  /* ROUT1VOL - [6:0] */
+
+/*
+ * R4 (0x04) - Clocking1
+ */
+#define WM8961_ADCDIV_MASK                      0x01C0  /* ADCDIV - [8:6] */
+#define WM8961_ADCDIV_SHIFT                          6  /* ADCDIV - [8:6] */
+#define WM8961_ADCDIV_WIDTH                          3  /* ADCDIV - [8:6] */
+#define WM8961_DACDIV_MASK                      0x0038  /* DACDIV - [5:3] */
+#define WM8961_DACDIV_SHIFT                          3  /* DACDIV - [5:3] */
+#define WM8961_DACDIV_WIDTH                          3  /* DACDIV - [5:3] */
+#define WM8961_MCLKDIV                          0x0004  /* MCLKDIV */
+#define WM8961_MCLKDIV_MASK                     0x0004  /* MCLKDIV */
+#define WM8961_MCLKDIV_SHIFT                         2  /* MCLKDIV */
+#define WM8961_MCLKDIV_WIDTH                         1  /* MCLKDIV */
+
+/*
+ * R5 (0x05) - ADC & DAC Control 1
+ */
+#define WM8961_ADCPOL_MASK                      0x0060  /* ADCPOL - [6:5] */
+#define WM8961_ADCPOL_SHIFT                          5  /* ADCPOL - [6:5] */
+#define WM8961_ADCPOL_WIDTH                          2  /* ADCPOL - [6:5] */
+#define WM8961_DACMU                            0x0008  /* DACMU */
+#define WM8961_DACMU_MASK                       0x0008  /* DACMU */
+#define WM8961_DACMU_SHIFT                           3  /* DACMU */
+#define WM8961_DACMU_WIDTH                           1  /* DACMU */
+#define WM8961_DEEMPH_MASK                      0x0006  /* DEEMPH - [2:1] */
+#define WM8961_DEEMPH_SHIFT                          1  /* DEEMPH - [2:1] */
+#define WM8961_DEEMPH_WIDTH                          2  /* DEEMPH - [2:1] */
+#define WM8961_ADCHPD                           0x0001  /* ADCHPD */
+#define WM8961_ADCHPD_MASK                      0x0001  /* ADCHPD */
+#define WM8961_ADCHPD_SHIFT                          0  /* ADCHPD */
+#define WM8961_ADCHPD_WIDTH                          1  /* ADCHPD */
+
+/*
+ * R6 (0x06) - ADC & DAC Control 2
+ */
+#define WM8961_ADC_HPF_CUT_MASK                 0x0180  /* ADC_HPF_CUT - [8:7] */
+#define WM8961_ADC_HPF_CUT_SHIFT                     7  /* ADC_HPF_CUT - [8:7] */
+#define WM8961_ADC_HPF_CUT_WIDTH                     2  /* ADC_HPF_CUT - [8:7] */
+#define WM8961_DACPOL_MASK                      0x0060  /* DACPOL - [6:5] */
+#define WM8961_DACPOL_SHIFT                          5  /* DACPOL - [6:5] */
+#define WM8961_DACPOL_WIDTH                          2  /* DACPOL - [6:5] */
+#define WM8961_DACSMM                           0x0008  /* DACSMM */
+#define WM8961_DACSMM_MASK                      0x0008  /* DACSMM */
+#define WM8961_DACSMM_SHIFT                          3  /* DACSMM */
+#define WM8961_DACSMM_WIDTH                          1  /* DACSMM */
+#define WM8961_DACMR                            0x0004  /* DACMR */
+#define WM8961_DACMR_MASK                       0x0004  /* DACMR */
+#define WM8961_DACMR_SHIFT                           2  /* DACMR */
+#define WM8961_DACMR_WIDTH                           1  /* DACMR */
+#define WM8961_DACSLOPE                         0x0002  /* DACSLOPE */
+#define WM8961_DACSLOPE_MASK                    0x0002  /* DACSLOPE */
+#define WM8961_DACSLOPE_SHIFT                        1  /* DACSLOPE */
+#define WM8961_DACSLOPE_WIDTH                        1  /* DACSLOPE */
+#define WM8961_DAC_OSR128                       0x0001  /* DAC_OSR128 */
+#define WM8961_DAC_OSR128_MASK                  0x0001  /* DAC_OSR128 */
+#define WM8961_DAC_OSR128_SHIFT                      0  /* DAC_OSR128 */
+#define WM8961_DAC_OSR128_WIDTH                      1  /* DAC_OSR128 */
+
+/*
+ * R7 (0x07) - Audio Interface 0
+ */
+#define WM8961_ALRSWAP                          0x0100  /* ALRSWAP */
+#define WM8961_ALRSWAP_MASK                     0x0100  /* ALRSWAP */
+#define WM8961_ALRSWAP_SHIFT                         8  /* ALRSWAP */
+#define WM8961_ALRSWAP_WIDTH                         1  /* ALRSWAP */
+#define WM8961_BCLKINV                          0x0080  /* BCLKINV */
+#define WM8961_BCLKINV_MASK                     0x0080  /* BCLKINV */
+#define WM8961_BCLKINV_SHIFT                         7  /* BCLKINV */
+#define WM8961_BCLKINV_WIDTH                         1  /* BCLKINV */
+#define WM8961_MS                               0x0040  /* MS */
+#define WM8961_MS_MASK                          0x0040  /* MS */
+#define WM8961_MS_SHIFT                              6  /* MS */
+#define WM8961_MS_WIDTH                              1  /* MS */
+#define WM8961_DLRSWAP                          0x0020  /* DLRSWAP */
+#define WM8961_DLRSWAP_MASK                     0x0020  /* DLRSWAP */
+#define WM8961_DLRSWAP_SHIFT                         5  /* DLRSWAP */
+#define WM8961_DLRSWAP_WIDTH                         1  /* DLRSWAP */
+#define WM8961_LRP                              0x0010  /* LRP */
+#define WM8961_LRP_MASK                         0x0010  /* LRP */
+#define WM8961_LRP_SHIFT                             4  /* LRP */
+#define WM8961_LRP_WIDTH                             1  /* LRP */
+#define WM8961_WL_MASK                          0x000C  /* WL - [3:2] */
+#define WM8961_WL_SHIFT                              2  /* WL - [3:2] */
+#define WM8961_WL_WIDTH                              2  /* WL - [3:2] */
+#define WM8961_FORMAT_MASK                      0x0003  /* FORMAT - [1:0] */
+#define WM8961_FORMAT_SHIFT                          0  /* FORMAT - [1:0] */
+#define WM8961_FORMAT_WIDTH                          2  /* FORMAT - [1:0] */
+
+/*
+ * R8 (0x08) - Clocking2
+ */
+#define WM8961_DCLKDIV_MASK                     0x01C0  /* DCLKDIV - [8:6] */
+#define WM8961_DCLKDIV_SHIFT                         6  /* DCLKDIV - [8:6] */
+#define WM8961_DCLKDIV_WIDTH                         3  /* DCLKDIV - [8:6] */
+#define WM8961_CLK_SYS_ENA                      0x0020  /* CLK_SYS_ENA */
+#define WM8961_CLK_SYS_ENA_MASK                 0x0020  /* CLK_SYS_ENA */
+#define WM8961_CLK_SYS_ENA_SHIFT                     5  /* CLK_SYS_ENA */
+#define WM8961_CLK_SYS_ENA_WIDTH                     1  /* CLK_SYS_ENA */
+#define WM8961_CLK_DSP_ENA                      0x0010  /* CLK_DSP_ENA */
+#define WM8961_CLK_DSP_ENA_MASK                 0x0010  /* CLK_DSP_ENA */
+#define WM8961_CLK_DSP_ENA_SHIFT                     4  /* CLK_DSP_ENA */
+#define WM8961_CLK_DSP_ENA_WIDTH                     1  /* CLK_DSP_ENA */
+#define WM8961_BCLKDIV_MASK                     0x000F  /* BCLKDIV - [3:0] */
+#define WM8961_BCLKDIV_SHIFT                         0  /* BCLKDIV - [3:0] */
+#define WM8961_BCLKDIV_WIDTH                         4  /* BCLKDIV - [3:0] */
+
+/*
+ * R9 (0x09) - Audio Interface 1
+ */
+#define WM8961_DACCOMP_MASK                     0x0018  /* DACCOMP - [4:3] */
+#define WM8961_DACCOMP_SHIFT                         3  /* DACCOMP - [4:3] */
+#define WM8961_DACCOMP_WIDTH                         2  /* DACCOMP - [4:3] */
+#define WM8961_ADCCOMP_MASK                     0x0006  /* ADCCOMP - [2:1] */
+#define WM8961_ADCCOMP_SHIFT                         1  /* ADCCOMP - [2:1] */
+#define WM8961_ADCCOMP_WIDTH                         2  /* ADCCOMP - [2:1] */
+#define WM8961_LOOPBACK                         0x0001  /* LOOPBACK */
+#define WM8961_LOOPBACK_MASK                    0x0001  /* LOOPBACK */
+#define WM8961_LOOPBACK_SHIFT                        0  /* LOOPBACK */
+#define WM8961_LOOPBACK_WIDTH                        1  /* LOOPBACK */
+
+/*
+ * R10 (0x0A) - Left DAC volume
+ */
+#define WM8961_DACVU                            0x0100  /* DACVU */
+#define WM8961_DACVU_MASK                       0x0100  /* DACVU */
+#define WM8961_DACVU_SHIFT                           8  /* DACVU */
+#define WM8961_DACVU_WIDTH                           1  /* DACVU */
+#define WM8961_LDACVOL_MASK                     0x00FF  /* LDACVOL - [7:0] */
+#define WM8961_LDACVOL_SHIFT                         0  /* LDACVOL - [7:0] */
+#define WM8961_LDACVOL_WIDTH                         8  /* LDACVOL - [7:0] */
+
+/*
+ * R11 (0x0B) - Right DAC volume
+ */
+#define WM8961_DACVU                            0x0100  /* DACVU */
+#define WM8961_DACVU_MASK                       0x0100  /* DACVU */
+#define WM8961_DACVU_SHIFT                           8  /* DACVU */
+#define WM8961_DACVU_WIDTH                           1  /* DACVU */
+#define WM8961_RDACVOL_MASK                     0x00FF  /* RDACVOL - [7:0] */
+#define WM8961_RDACVOL_SHIFT                         0  /* RDACVOL - [7:0] */
+#define WM8961_RDACVOL_WIDTH                         8  /* RDACVOL - [7:0] */
+
+/*
+ * R14 (0x0E) - Audio Interface 2
+ */
+#define WM8961_LRCLK_RATE_MASK                  0x01FF  /* LRCLK_RATE - [8:0] */
+#define WM8961_LRCLK_RATE_SHIFT                      0  /* LRCLK_RATE - [8:0] */
+#define WM8961_LRCLK_RATE_WIDTH                      9  /* LRCLK_RATE - [8:0] */
+
+/*
+ * R15 (0x0F) - Software Reset
+ */
+#define WM8961_SW_RST_DEV_ID1_MASK              0xFFFF  /* SW_RST_DEV_ID1 - [15:0] */
+#define WM8961_SW_RST_DEV_ID1_SHIFT                  0  /* SW_RST_DEV_ID1 - [15:0] */
+#define WM8961_SW_RST_DEV_ID1_WIDTH                 16  /* SW_RST_DEV_ID1 - [15:0] */
+
+/*
+ * R17 (0x11) - ALC1
+ */
+#define WM8961_ALCSEL_MASK                      0x0180  /* ALCSEL - [8:7] */
+#define WM8961_ALCSEL_SHIFT                          7  /* ALCSEL - [8:7] */
+#define WM8961_ALCSEL_WIDTH                          2  /* ALCSEL - [8:7] */
+#define WM8961_MAXGAIN_MASK                     0x0070  /* MAXGAIN - [6:4] */
+#define WM8961_MAXGAIN_SHIFT                         4  /* MAXGAIN - [6:4] */
+#define WM8961_MAXGAIN_WIDTH                         3  /* MAXGAIN - [6:4] */
+#define WM8961_ALCL_MASK                        0x000F  /* ALCL - [3:0] */
+#define WM8961_ALCL_SHIFT                            0  /* ALCL - [3:0] */
+#define WM8961_ALCL_WIDTH                            4  /* ALCL - [3:0] */
+
+/*
+ * R18 (0x12) - ALC2
+ */
+#define WM8961_ALCZC                            0x0080  /* ALCZC */
+#define WM8961_ALCZC_MASK                       0x0080  /* ALCZC */
+#define WM8961_ALCZC_SHIFT                           7  /* ALCZC */
+#define WM8961_ALCZC_WIDTH                           1  /* ALCZC */
+#define WM8961_MINGAIN_MASK                     0x0070  /* MINGAIN - [6:4] */
+#define WM8961_MINGAIN_SHIFT                         4  /* MINGAIN - [6:4] */
+#define WM8961_MINGAIN_WIDTH                         3  /* MINGAIN - [6:4] */
+#define WM8961_HLD_MASK                         0x000F  /* HLD - [3:0] */
+#define WM8961_HLD_SHIFT                             0  /* HLD - [3:0] */
+#define WM8961_HLD_WIDTH                             4  /* HLD - [3:0] */
+
+/*
+ * R19 (0x13) - ALC3
+ */
+#define WM8961_ALCMODE                          0x0100  /* ALCMODE */
+#define WM8961_ALCMODE_MASK                     0x0100  /* ALCMODE */
+#define WM8961_ALCMODE_SHIFT                         8  /* ALCMODE */
+#define WM8961_ALCMODE_WIDTH                         1  /* ALCMODE */
+#define WM8961_DCY_MASK                         0x00F0  /* DCY - [7:4] */
+#define WM8961_DCY_SHIFT                             4  /* DCY - [7:4] */
+#define WM8961_DCY_WIDTH                             4  /* DCY - [7:4] */
+#define WM8961_ATK_MASK                         0x000F  /* ATK - [3:0] */
+#define WM8961_ATK_SHIFT                             0  /* ATK - [3:0] */
+#define WM8961_ATK_WIDTH                             4  /* ATK - [3:0] */
+
+/*
+ * R20 (0x14) - Noise Gate
+ */
+#define WM8961_NGTH_MASK                        0x00F8  /* NGTH - [7:3] */
+#define WM8961_NGTH_SHIFT                            3  /* NGTH - [7:3] */
+#define WM8961_NGTH_WIDTH                            5  /* NGTH - [7:3] */
+#define WM8961_NGG                              0x0002  /* NGG */
+#define WM8961_NGG_MASK                         0x0002  /* NGG */
+#define WM8961_NGG_SHIFT                             1  /* NGG */
+#define WM8961_NGG_WIDTH                             1  /* NGG */
+#define WM8961_NGAT                             0x0001  /* NGAT */
+#define WM8961_NGAT_MASK                        0x0001  /* NGAT */
+#define WM8961_NGAT_SHIFT                            0  /* NGAT */
+#define WM8961_NGAT_WIDTH                            1  /* NGAT */
+
+/*
+ * R21 (0x15) - Left ADC volume
+ */
+#define WM8961_ADCVU                            0x0100  /* ADCVU */
+#define WM8961_ADCVU_MASK                       0x0100  /* ADCVU */
+#define WM8961_ADCVU_SHIFT                           8  /* ADCVU */
+#define WM8961_ADCVU_WIDTH                           1  /* ADCVU */
+#define WM8961_LADCVOL_MASK                     0x00FF  /* LADCVOL - [7:0] */
+#define WM8961_LADCVOL_SHIFT                         0  /* LADCVOL - [7:0] */
+#define WM8961_LADCVOL_WIDTH                         8  /* LADCVOL - [7:0] */
+
+/*
+ * R22 (0x16) - Right ADC volume
+ */
+#define WM8961_ADCVU                            0x0100  /* ADCVU */
+#define WM8961_ADCVU_MASK                       0x0100  /* ADCVU */
+#define WM8961_ADCVU_SHIFT                           8  /* ADCVU */
+#define WM8961_ADCVU_WIDTH                           1  /* ADCVU */
+#define WM8961_RADCVOL_MASK                     0x00FF  /* RADCVOL - [7:0] */
+#define WM8961_RADCVOL_SHIFT                         0  /* RADCVOL - [7:0] */
+#define WM8961_RADCVOL_WIDTH                         8  /* RADCVOL - [7:0] */
+
+/*
+ * R23 (0x17) - Additional control(1)
+ */
+#define WM8961_TSDEN                            0x0100  /* TSDEN */
+#define WM8961_TSDEN_MASK                       0x0100  /* TSDEN */
+#define WM8961_TSDEN_SHIFT                           8  /* TSDEN */
+#define WM8961_TSDEN_WIDTH                           1  /* TSDEN */
+#define WM8961_DMONOMIX                         0x0010  /* DMONOMIX */
+#define WM8961_DMONOMIX_MASK                    0x0010  /* DMONOMIX */
+#define WM8961_DMONOMIX_SHIFT                        4  /* DMONOMIX */
+#define WM8961_DMONOMIX_WIDTH                        1  /* DMONOMIX */
+#define WM8961_TOEN                             0x0001  /* TOEN */
+#define WM8961_TOEN_MASK                        0x0001  /* TOEN */
+#define WM8961_TOEN_SHIFT                            0  /* TOEN */
+#define WM8961_TOEN_WIDTH                            1  /* TOEN */
+
+/*
+ * R24 (0x18) - Additional control(2)
+ */
+#define WM8961_TRIS                             0x0008  /* TRIS */
+#define WM8961_TRIS_MASK                        0x0008  /* TRIS */
+#define WM8961_TRIS_SHIFT                            3  /* TRIS */
+#define WM8961_TRIS_WIDTH                            1  /* TRIS */
+
+/*
+ * R25 (0x19) - Pwr Mgmt (1)
+ */
+#define WM8961_VMIDSEL_MASK                     0x0180  /* VMIDSEL - [8:7] */
+#define WM8961_VMIDSEL_SHIFT                         7  /* VMIDSEL - [8:7] */
+#define WM8961_VMIDSEL_WIDTH                         2  /* VMIDSEL - [8:7] */
+#define WM8961_VREF                             0x0040  /* VREF */
+#define WM8961_VREF_MASK                        0x0040  /* VREF */
+#define WM8961_VREF_SHIFT                            6  /* VREF */
+#define WM8961_VREF_WIDTH                            1  /* VREF */
+#define WM8961_AINL                             0x0020  /* AINL */
+#define WM8961_AINL_MASK                        0x0020  /* AINL */
+#define WM8961_AINL_SHIFT                            5  /* AINL */
+#define WM8961_AINL_WIDTH                            1  /* AINL */
+#define WM8961_AINR                             0x0010  /* AINR */
+#define WM8961_AINR_MASK                        0x0010  /* AINR */
+#define WM8961_AINR_SHIFT                            4  /* AINR */
+#define WM8961_AINR_WIDTH                            1  /* AINR */
+#define WM8961_ADCL                             0x0008  /* ADCL */
+#define WM8961_ADCL_MASK                        0x0008  /* ADCL */
+#define WM8961_ADCL_SHIFT                            3  /* ADCL */
+#define WM8961_ADCL_WIDTH                            1  /* ADCL */
+#define WM8961_ADCR                             0x0004  /* ADCR */
+#define WM8961_ADCR_MASK                        0x0004  /* ADCR */
+#define WM8961_ADCR_SHIFT                            2  /* ADCR */
+#define WM8961_ADCR_WIDTH                            1  /* ADCR */
+#define WM8961_MICB                             0x0002  /* MICB */
+#define WM8961_MICB_MASK                        0x0002  /* MICB */
+#define WM8961_MICB_SHIFT                            1  /* MICB */
+#define WM8961_MICB_WIDTH                            1  /* MICB */
+
+/*
+ * R26 (0x1A) - Pwr Mgmt (2)
+ */
+#define WM8961_DACL                             0x0100  /* DACL */
+#define WM8961_DACL_MASK                        0x0100  /* DACL */
+#define WM8961_DACL_SHIFT                            8  /* DACL */
+#define WM8961_DACL_WIDTH                            1  /* DACL */
+#define WM8961_DACR                             0x0080  /* DACR */
+#define WM8961_DACR_MASK                        0x0080  /* DACR */
+#define WM8961_DACR_SHIFT                            7  /* DACR */
+#define WM8961_DACR_WIDTH                            1  /* DACR */
+#define WM8961_LOUT1_PGA                        0x0040  /* LOUT1_PGA */
+#define WM8961_LOUT1_PGA_MASK                   0x0040  /* LOUT1_PGA */
+#define WM8961_LOUT1_PGA_SHIFT                       6  /* LOUT1_PGA */
+#define WM8961_LOUT1_PGA_WIDTH                       1  /* LOUT1_PGA */
+#define WM8961_ROUT1_PGA                        0x0020  /* ROUT1_PGA */
+#define WM8961_ROUT1_PGA_MASK                   0x0020  /* ROUT1_PGA */
+#define WM8961_ROUT1_PGA_SHIFT                       5  /* ROUT1_PGA */
+#define WM8961_ROUT1_PGA_WIDTH                       1  /* ROUT1_PGA */
+#define WM8961_SPKL_PGA                         0x0010  /* SPKL_PGA */
+#define WM8961_SPKL_PGA_MASK                    0x0010  /* SPKL_PGA */
+#define WM8961_SPKL_PGA_SHIFT                        4  /* SPKL_PGA */
+#define WM8961_SPKL_PGA_WIDTH                        1  /* SPKL_PGA */
+#define WM8961_SPKR_PGA                         0x0008  /* SPKR_PGA */
+#define WM8961_SPKR_PGA_MASK                    0x0008  /* SPKR_PGA */
+#define WM8961_SPKR_PGA_SHIFT                        3  /* SPKR_PGA */
+#define WM8961_SPKR_PGA_WIDTH                        1  /* SPKR_PGA */
+
+/*
+ * R27 (0x1B) - Additional Control (3)
+ */
+#define WM8961_SAMPLE_RATE_MASK                 0x0007  /* SAMPLE_RATE - [2:0] */
+#define WM8961_SAMPLE_RATE_SHIFT                     0  /* SAMPLE_RATE - [2:0] */
+#define WM8961_SAMPLE_RATE_WIDTH                     3  /* SAMPLE_RATE - [2:0] */
+
+/*
+ * R28 (0x1C) - Anti-pop
+ */
+#define WM8961_BUFDCOPEN                        0x0010  /* BUFDCOPEN */
+#define WM8961_BUFDCOPEN_MASK                   0x0010  /* BUFDCOPEN */
+#define WM8961_BUFDCOPEN_SHIFT                       4  /* BUFDCOPEN */
+#define WM8961_BUFDCOPEN_WIDTH                       1  /* BUFDCOPEN */
+#define WM8961_BUFIOEN                          0x0008  /* BUFIOEN */
+#define WM8961_BUFIOEN_MASK                     0x0008  /* BUFIOEN */
+#define WM8961_BUFIOEN_SHIFT                         3  /* BUFIOEN */
+#define WM8961_BUFIOEN_WIDTH                         1  /* BUFIOEN */
+#define WM8961_SOFT_ST                          0x0004  /* SOFT_ST */
+#define WM8961_SOFT_ST_MASK                     0x0004  /* SOFT_ST */
+#define WM8961_SOFT_ST_SHIFT                         2  /* SOFT_ST */
+#define WM8961_SOFT_ST_WIDTH                         1  /* SOFT_ST */
+
+/*
+ * R30 (0x1E) - Clocking 3
+ */
+#define WM8961_CLK_TO_DIV_MASK                  0x0180  /* CLK_TO_DIV - [8:7] */
+#define WM8961_CLK_TO_DIV_SHIFT                      7  /* CLK_TO_DIV - [8:7] */
+#define WM8961_CLK_TO_DIV_WIDTH                      2  /* CLK_TO_DIV - [8:7] */
+#define WM8961_CLK_256K_DIV_MASK                0x007E  /* CLK_256K_DIV - [6:1] */
+#define WM8961_CLK_256K_DIV_SHIFT                    1  /* CLK_256K_DIV - [6:1] */
+#define WM8961_CLK_256K_DIV_WIDTH                    6  /* CLK_256K_DIV - [6:1] */
+#define WM8961_MANUAL_MODE                      0x0001  /* MANUAL_MODE */
+#define WM8961_MANUAL_MODE_MASK                 0x0001  /* MANUAL_MODE */
+#define WM8961_MANUAL_MODE_SHIFT                     0  /* MANUAL_MODE */
+#define WM8961_MANUAL_MODE_WIDTH                     1  /* MANUAL_MODE */
+
+/*
+ * R32 (0x20) - ADCL signal path
+ */
+#define WM8961_LMICBOOST_MASK                   0x0030  /* LMICBOOST - [5:4] */
+#define WM8961_LMICBOOST_SHIFT                       4  /* LMICBOOST - [5:4] */
+#define WM8961_LMICBOOST_WIDTH                       2  /* LMICBOOST - [5:4] */
+
+/*
+ * R33 (0x21) - ADCR signal path
+ */
+#define WM8961_RMICBOOST_MASK                   0x0030  /* RMICBOOST - [5:4] */
+#define WM8961_RMICBOOST_SHIFT                       4  /* RMICBOOST - [5:4] */
+#define WM8961_RMICBOOST_WIDTH                       2  /* RMICBOOST - [5:4] */
+
+/*
+ * R40 (0x28) - LOUT2 volume
+ */
+#define WM8961_SPKVU                            0x0100  /* SPKVU */
+#define WM8961_SPKVU_MASK                       0x0100  /* SPKVU */
+#define WM8961_SPKVU_SHIFT                           8  /* SPKVU */
+#define WM8961_SPKVU_WIDTH                           1  /* SPKVU */
+#define WM8961_SPKLZC                           0x0080  /* SPKLZC */
+#define WM8961_SPKLZC_MASK                      0x0080  /* SPKLZC */
+#define WM8961_SPKLZC_SHIFT                          7  /* SPKLZC */
+#define WM8961_SPKLZC_WIDTH                          1  /* SPKLZC */
+#define WM8961_SPKLVOL_MASK                     0x007F  /* SPKLVOL - [6:0] */
+#define WM8961_SPKLVOL_SHIFT                         0  /* SPKLVOL - [6:0] */
+#define WM8961_SPKLVOL_WIDTH                         7  /* SPKLVOL - [6:0] */
+
+/*
+ * R41 (0x29) - ROUT2 volume
+ */
+#define WM8961_SPKVU                            0x0100  /* SPKVU */
+#define WM8961_SPKVU_MASK                       0x0100  /* SPKVU */
+#define WM8961_SPKVU_SHIFT                           8  /* SPKVU */
+#define WM8961_SPKVU_WIDTH                           1  /* SPKVU */
+#define WM8961_SPKRZC                           0x0080  /* SPKRZC */
+#define WM8961_SPKRZC_MASK                      0x0080  /* SPKRZC */
+#define WM8961_SPKRZC_SHIFT                          7  /* SPKRZC */
+#define WM8961_SPKRZC_WIDTH                          1  /* SPKRZC */
+#define WM8961_SPKRVOL_MASK                     0x007F  /* SPKRVOL - [6:0] */
+#define WM8961_SPKRVOL_SHIFT                         0  /* SPKRVOL - [6:0] */
+#define WM8961_SPKRVOL_WIDTH                         7  /* SPKRVOL - [6:0] */
+
+/*
+ * R47 (0x2F) - Pwr Mgmt (3)
+ */
+#define WM8961_TEMP_SHUT                        0x0002  /* TEMP_SHUT */
+#define WM8961_TEMP_SHUT_MASK                   0x0002  /* TEMP_SHUT */
+#define WM8961_TEMP_SHUT_SHIFT                       1  /* TEMP_SHUT */
+#define WM8961_TEMP_SHUT_WIDTH                       1  /* TEMP_SHUT */
+#define WM8961_TEMP_WARN                        0x0001  /* TEMP_WARN */
+#define WM8961_TEMP_WARN_MASK                   0x0001  /* TEMP_WARN */
+#define WM8961_TEMP_WARN_SHIFT                       0  /* TEMP_WARN */
+#define WM8961_TEMP_WARN_WIDTH                       1  /* TEMP_WARN */
+
+/*
+ * R48 (0x30) - Additional Control (4)
+ */
+#define WM8961_TSENSEN                          0x0002  /* TSENSEN */
+#define WM8961_TSENSEN_MASK                     0x0002  /* TSENSEN */
+#define WM8961_TSENSEN_SHIFT                         1  /* TSENSEN */
+#define WM8961_TSENSEN_WIDTH                         1  /* TSENSEN */
+#define WM8961_MBSEL                            0x0001  /* MBSEL */
+#define WM8961_MBSEL_MASK                       0x0001  /* MBSEL */
+#define WM8961_MBSEL_SHIFT                           0  /* MBSEL */
+#define WM8961_MBSEL_WIDTH                           1  /* MBSEL */
+
+/*
+ * R49 (0x31) - Class D Control 1
+ */
+#define WM8961_SPKR_ENA                         0x0080  /* SPKR_ENA */
+#define WM8961_SPKR_ENA_MASK                    0x0080  /* SPKR_ENA */
+#define WM8961_SPKR_ENA_SHIFT                        7  /* SPKR_ENA */
+#define WM8961_SPKR_ENA_WIDTH                        1  /* SPKR_ENA */
+#define WM8961_SPKL_ENA                         0x0040  /* SPKL_ENA */
+#define WM8961_SPKL_ENA_MASK                    0x0040  /* SPKL_ENA */
+#define WM8961_SPKL_ENA_SHIFT                        6  /* SPKL_ENA */
+#define WM8961_SPKL_ENA_WIDTH                        1  /* SPKL_ENA */
+
+/*
+ * R51 (0x33) - Class D Control 2
+ */
+#define WM8961_CLASSD_ACGAIN_MASK               0x0007  /* CLASSD_ACGAIN - [2:0] */
+#define WM8961_CLASSD_ACGAIN_SHIFT                   0  /* CLASSD_ACGAIN - [2:0] */
+#define WM8961_CLASSD_ACGAIN_WIDTH                   3  /* CLASSD_ACGAIN - [2:0] */
+
+/*
+ * R56 (0x38) - Clocking 4
+ */
+#define WM8961_CLK_DCS_DIV_MASK                 0x01E0  /* CLK_DCS_DIV - [8:5] */
+#define WM8961_CLK_DCS_DIV_SHIFT                     5  /* CLK_DCS_DIV - [8:5] */
+#define WM8961_CLK_DCS_DIV_WIDTH                     4  /* CLK_DCS_DIV - [8:5] */
+#define WM8961_CLK_SYS_RATE_MASK                0x001E  /* CLK_SYS_RATE - [4:1] */
+#define WM8961_CLK_SYS_RATE_SHIFT                    1  /* CLK_SYS_RATE - [4:1] */
+#define WM8961_CLK_SYS_RATE_WIDTH                    4  /* CLK_SYS_RATE - [4:1] */
+
+/*
+ * R57 (0x39) - DSP Sidetone 0
+ */
+#define WM8961_ADCR_DAC_SVOL_MASK               0x00F0  /* ADCR_DAC_SVOL - [7:4] */
+#define WM8961_ADCR_DAC_SVOL_SHIFT                   4  /* ADCR_DAC_SVOL - [7:4] */
+#define WM8961_ADCR_DAC_SVOL_WIDTH                   4  /* ADCR_DAC_SVOL - [7:4] */
+#define WM8961_ADC_TO_DACR_MASK                 0x000C  /* ADC_TO_DACR - [3:2] */
+#define WM8961_ADC_TO_DACR_SHIFT                     2  /* ADC_TO_DACR - [3:2] */
+#define WM8961_ADC_TO_DACR_WIDTH                     2  /* ADC_TO_DACR - [3:2] */
+
+/*
+ * R58 (0x3A) - DSP Sidetone 1
+ */
+#define WM8961_ADCL_DAC_SVOL_MASK               0x00F0  /* ADCL_DAC_SVOL - [7:4] */
+#define WM8961_ADCL_DAC_SVOL_SHIFT                   4  /* ADCL_DAC_SVOL - [7:4] */
+#define WM8961_ADCL_DAC_SVOL_WIDTH                   4  /* ADCL_DAC_SVOL - [7:4] */
+#define WM8961_ADC_TO_DACL_MASK                 0x000C  /* ADC_TO_DACL - [3:2] */
+#define WM8961_ADC_TO_DACL_SHIFT                     2  /* ADC_TO_DACL - [3:2] */
+#define WM8961_ADC_TO_DACL_WIDTH                     2  /* ADC_TO_DACL - [3:2] */
+
+/*
+ * R60 (0x3C) - DC Servo 0
+ */
+#define WM8961_DCS_ENA_CHAN_INL                 0x0080  /* DCS_ENA_CHAN_INL */
+#define WM8961_DCS_ENA_CHAN_INL_MASK            0x0080  /* DCS_ENA_CHAN_INL */
+#define WM8961_DCS_ENA_CHAN_INL_SHIFT                7  /* DCS_ENA_CHAN_INL */
+#define WM8961_DCS_ENA_CHAN_INL_WIDTH                1  /* DCS_ENA_CHAN_INL */
+#define WM8961_DCS_TRIG_STARTUP_INL             0x0040  /* DCS_TRIG_STARTUP_INL */
+#define WM8961_DCS_TRIG_STARTUP_INL_MASK        0x0040  /* DCS_TRIG_STARTUP_INL */
+#define WM8961_DCS_TRIG_STARTUP_INL_SHIFT            6  /* DCS_TRIG_STARTUP_INL */
+#define WM8961_DCS_TRIG_STARTUP_INL_WIDTH            1  /* DCS_TRIG_STARTUP_INL */
+#define WM8961_DCS_TRIG_SERIES_INL              0x0010  /* DCS_TRIG_SERIES_INL */
+#define WM8961_DCS_TRIG_SERIES_INL_MASK         0x0010  /* DCS_TRIG_SERIES_INL */
+#define WM8961_DCS_TRIG_SERIES_INL_SHIFT             4  /* DCS_TRIG_SERIES_INL */
+#define WM8961_DCS_TRIG_SERIES_INL_WIDTH             1  /* DCS_TRIG_SERIES_INL */
+#define WM8961_DCS_ENA_CHAN_INR                 0x0008  /* DCS_ENA_CHAN_INR */
+#define WM8961_DCS_ENA_CHAN_INR_MASK            0x0008  /* DCS_ENA_CHAN_INR */
+#define WM8961_DCS_ENA_CHAN_INR_SHIFT                3  /* DCS_ENA_CHAN_INR */
+#define WM8961_DCS_ENA_CHAN_INR_WIDTH                1  /* DCS_ENA_CHAN_INR */
+#define WM8961_DCS_TRIG_STARTUP_INR             0x0004  /* DCS_TRIG_STARTUP_INR */
+#define WM8961_DCS_TRIG_STARTUP_INR_MASK        0x0004  /* DCS_TRIG_STARTUP_INR */
+#define WM8961_DCS_TRIG_STARTUP_INR_SHIFT            2  /* DCS_TRIG_STARTUP_INR */
+#define WM8961_DCS_TRIG_STARTUP_INR_WIDTH            1  /* DCS_TRIG_STARTUP_INR */
+#define WM8961_DCS_TRIG_SERIES_INR              0x0001  /* DCS_TRIG_SERIES_INR */
+#define WM8961_DCS_TRIG_SERIES_INR_MASK         0x0001  /* DCS_TRIG_SERIES_INR */
+#define WM8961_DCS_TRIG_SERIES_INR_SHIFT             0  /* DCS_TRIG_SERIES_INR */
+#define WM8961_DCS_TRIG_SERIES_INR_WIDTH             1  /* DCS_TRIG_SERIES_INR */
+
+/*
+ * R61 (0x3D) - DC Servo 1
+ */
+#define WM8961_DCS_ENA_CHAN_HPL                 0x0080  /* DCS_ENA_CHAN_HPL */
+#define WM8961_DCS_ENA_CHAN_HPL_MASK            0x0080  /* DCS_ENA_CHAN_HPL */
+#define WM8961_DCS_ENA_CHAN_HPL_SHIFT                7  /* DCS_ENA_CHAN_HPL */
+#define WM8961_DCS_ENA_CHAN_HPL_WIDTH                1  /* DCS_ENA_CHAN_HPL */
+#define WM8961_DCS_TRIG_STARTUP_HPL             0x0040  /* DCS_TRIG_STARTUP_HPL */
+#define WM8961_DCS_TRIG_STARTUP_HPL_MASK        0x0040  /* DCS_TRIG_STARTUP_HPL */
+#define WM8961_DCS_TRIG_STARTUP_HPL_SHIFT            6  /* DCS_TRIG_STARTUP_HPL */
+#define WM8961_DCS_TRIG_STARTUP_HPL_WIDTH            1  /* DCS_TRIG_STARTUP_HPL */
+#define WM8961_DCS_TRIG_SERIES_HPL              0x0010  /* DCS_TRIG_SERIES_HPL */
+#define WM8961_DCS_TRIG_SERIES_HPL_MASK         0x0010  /* DCS_TRIG_SERIES_HPL */
+#define WM8961_DCS_TRIG_SERIES_HPL_SHIFT             4  /* DCS_TRIG_SERIES_HPL */
+#define WM8961_DCS_TRIG_SERIES_HPL_WIDTH             1  /* DCS_TRIG_SERIES_HPL */
+#define WM8961_DCS_ENA_CHAN_HPR                 0x0008  /* DCS_ENA_CHAN_HPR */
+#define WM8961_DCS_ENA_CHAN_HPR_MASK            0x0008  /* DCS_ENA_CHAN_HPR */
+#define WM8961_DCS_ENA_CHAN_HPR_SHIFT                3  /* DCS_ENA_CHAN_HPR */
+#define WM8961_DCS_ENA_CHAN_HPR_WIDTH                1  /* DCS_ENA_CHAN_HPR */
+#define WM8961_DCS_TRIG_STARTUP_HPR             0x0004  /* DCS_TRIG_STARTUP_HPR */
+#define WM8961_DCS_TRIG_STARTUP_HPR_MASK        0x0004  /* DCS_TRIG_STARTUP_HPR */
+#define WM8961_DCS_TRIG_STARTUP_HPR_SHIFT            2  /* DCS_TRIG_STARTUP_HPR */
+#define WM8961_DCS_TRIG_STARTUP_HPR_WIDTH            1  /* DCS_TRIG_STARTUP_HPR */
+#define WM8961_DCS_TRIG_SERIES_HPR              0x0001  /* DCS_TRIG_SERIES_HPR */
+#define WM8961_DCS_TRIG_SERIES_HPR_MASK         0x0001  /* DCS_TRIG_SERIES_HPR */
+#define WM8961_DCS_TRIG_SERIES_HPR_SHIFT             0  /* DCS_TRIG_SERIES_HPR */
+#define WM8961_DCS_TRIG_SERIES_HPR_WIDTH             1  /* DCS_TRIG_SERIES_HPR */
+
+/*
+ * R63 (0x3F) - DC Servo 3
+ */
+#define WM8961_DCS_FILT_BW_SERIES_MASK          0x0030  /* DCS_FILT_BW_SERIES - [5:4] */
+#define WM8961_DCS_FILT_BW_SERIES_SHIFT              4  /* DCS_FILT_BW_SERIES - [5:4] */
+#define WM8961_DCS_FILT_BW_SERIES_WIDTH              2  /* DCS_FILT_BW_SERIES - [5:4] */
+
+/*
+ * R65 (0x41) - DC Servo 5
+ */
+#define WM8961_DCS_SERIES_NO_HP_MASK            0x007F  /* DCS_SERIES_NO_HP - [6:0] */
+#define WM8961_DCS_SERIES_NO_HP_SHIFT                0  /* DCS_SERIES_NO_HP - [6:0] */
+#define WM8961_DCS_SERIES_NO_HP_WIDTH                7  /* DCS_SERIES_NO_HP - [6:0] */
+
+/*
+ * R68 (0x44) - Analogue PGA Bias
+ */
+#define WM8961_HP_PGAS_BIAS_MASK                0x0007  /* HP_PGAS_BIAS - [2:0] */
+#define WM8961_HP_PGAS_BIAS_SHIFT                    0  /* HP_PGAS_BIAS - [2:0] */
+#define WM8961_HP_PGAS_BIAS_WIDTH                    3  /* HP_PGAS_BIAS - [2:0] */
+
+/*
+ * R69 (0x45) - Analogue HP 0
+ */
+#define WM8961_HPL_RMV_SHORT                    0x0080  /* HPL_RMV_SHORT */
+#define WM8961_HPL_RMV_SHORT_MASK               0x0080  /* HPL_RMV_SHORT */
+#define WM8961_HPL_RMV_SHORT_SHIFT                   7  /* HPL_RMV_SHORT */
+#define WM8961_HPL_RMV_SHORT_WIDTH                   1  /* HPL_RMV_SHORT */
+#define WM8961_HPL_ENA_OUTP                     0x0040  /* HPL_ENA_OUTP */
+#define WM8961_HPL_ENA_OUTP_MASK                0x0040  /* HPL_ENA_OUTP */
+#define WM8961_HPL_ENA_OUTP_SHIFT                    6  /* HPL_ENA_OUTP */
+#define WM8961_HPL_ENA_OUTP_WIDTH                    1  /* HPL_ENA_OUTP */
+#define WM8961_HPL_ENA_DLY                      0x0020  /* HPL_ENA_DLY */
+#define WM8961_HPL_ENA_DLY_MASK                 0x0020  /* HPL_ENA_DLY */
+#define WM8961_HPL_ENA_DLY_SHIFT                     5  /* HPL_ENA_DLY */
+#define WM8961_HPL_ENA_DLY_WIDTH                     1  /* HPL_ENA_DLY */
+#define WM8961_HPL_ENA                          0x0010  /* HPL_ENA */
+#define WM8961_HPL_ENA_MASK                     0x0010  /* HPL_ENA */
+#define WM8961_HPL_ENA_SHIFT                         4  /* HPL_ENA */
+#define WM8961_HPL_ENA_WIDTH                         1  /* HPL_ENA */
+#define WM8961_HPR_RMV_SHORT                    0x0008  /* HPR_RMV_SHORT */
+#define WM8961_HPR_RMV_SHORT_MASK               0x0008  /* HPR_RMV_SHORT */
+#define WM8961_HPR_RMV_SHORT_SHIFT                   3  /* HPR_RMV_SHORT */
+#define WM8961_HPR_RMV_SHORT_WIDTH                   1  /* HPR_RMV_SHORT */
+#define WM8961_HPR_ENA_OUTP                     0x0004  /* HPR_ENA_OUTP */
+#define WM8961_HPR_ENA_OUTP_MASK                0x0004  /* HPR_ENA_OUTP */
+#define WM8961_HPR_ENA_OUTP_SHIFT                    2  /* HPR_ENA_OUTP */
+#define WM8961_HPR_ENA_OUTP_WIDTH                    1  /* HPR_ENA_OUTP */
+#define WM8961_HPR_ENA_DLY                      0x0002  /* HPR_ENA_DLY */
+#define WM8961_HPR_ENA_DLY_MASK                 0x0002  /* HPR_ENA_DLY */
+#define WM8961_HPR_ENA_DLY_SHIFT                     1  /* HPR_ENA_DLY */
+#define WM8961_HPR_ENA_DLY_WIDTH                     1  /* HPR_ENA_DLY */
+#define WM8961_HPR_ENA                          0x0001  /* HPR_ENA */
+#define WM8961_HPR_ENA_MASK                     0x0001  /* HPR_ENA */
+#define WM8961_HPR_ENA_SHIFT                         0  /* HPR_ENA */
+#define WM8961_HPR_ENA_WIDTH                         1  /* HPR_ENA */
+
+/*
+ * R71 (0x47) - Analogue HP 2
+ */
+#define WM8961_HPL_VOL_MASK                     0x01C0  /* HPL_VOL - [8:6] */
+#define WM8961_HPL_VOL_SHIFT                         6  /* HPL_VOL - [8:6] */
+#define WM8961_HPL_VOL_WIDTH                         3  /* HPL_VOL - [8:6] */
+#define WM8961_HPR_VOL_MASK                     0x0038  /* HPR_VOL - [5:3] */
+#define WM8961_HPR_VOL_SHIFT                         3  /* HPR_VOL - [5:3] */
+#define WM8961_HPR_VOL_WIDTH                         3  /* HPR_VOL - [5:3] */
+#define WM8961_HP_BIAS_BOOST_MASK               0x0007  /* HP_BIAS_BOOST - [2:0] */
+#define WM8961_HP_BIAS_BOOST_SHIFT                   0  /* HP_BIAS_BOOST - [2:0] */
+#define WM8961_HP_BIAS_BOOST_WIDTH                   3  /* HP_BIAS_BOOST - [2:0] */
+
+/*
+ * R72 (0x48) - Charge Pump 1
+ */
+#define WM8961_CP_ENA                           0x0001  /* CP_ENA */
+#define WM8961_CP_ENA_MASK                      0x0001  /* CP_ENA */
+#define WM8961_CP_ENA_SHIFT                          0  /* CP_ENA */
+#define WM8961_CP_ENA_WIDTH                          1  /* CP_ENA */
+
+/*
+ * R82 (0x52) - Charge Pump B
+ */
+#define WM8961_CP_DYN_PWR_MASK                  0x0003  /* CP_DYN_PWR - [1:0] */
+#define WM8961_CP_DYN_PWR_SHIFT                      0  /* CP_DYN_PWR - [1:0] */
+#define WM8961_CP_DYN_PWR_WIDTH                      2  /* CP_DYN_PWR - [1:0] */
+
+/*
+ * R87 (0x57) - Write Sequencer 1
+ */
+#define WM8961_WSEQ_ENA                         0x0020  /* WSEQ_ENA */
+#define WM8961_WSEQ_ENA_MASK                    0x0020  /* WSEQ_ENA */
+#define WM8961_WSEQ_ENA_SHIFT                        5  /* WSEQ_ENA */
+#define WM8961_WSEQ_ENA_WIDTH                        1  /* WSEQ_ENA */
+#define WM8961_WSEQ_WRITE_INDEX_MASK            0x001F  /* WSEQ_WRITE_INDEX - [4:0] */
+#define WM8961_WSEQ_WRITE_INDEX_SHIFT                0  /* WSEQ_WRITE_INDEX - [4:0] */
+#define WM8961_WSEQ_WRITE_INDEX_WIDTH                5  /* WSEQ_WRITE_INDEX - [4:0] */
+
+/*
+ * R88 (0x58) - Write Sequencer 2
+ */
+#define WM8961_WSEQ_EOS                         0x0100  /* WSEQ_EOS */
+#define WM8961_WSEQ_EOS_MASK                    0x0100  /* WSEQ_EOS */
+#define WM8961_WSEQ_EOS_SHIFT                        8  /* WSEQ_EOS */
+#define WM8961_WSEQ_EOS_WIDTH                        1  /* WSEQ_EOS */
+#define WM8961_WSEQ_ADDR_MASK                   0x00FF  /* WSEQ_ADDR - [7:0] */
+#define WM8961_WSEQ_ADDR_SHIFT                       0  /* WSEQ_ADDR - [7:0] */
+#define WM8961_WSEQ_ADDR_WIDTH                       8  /* WSEQ_ADDR - [7:0] */
+
+/*
+ * R89 (0x59) - Write Sequencer 3
+ */
+#define WM8961_WSEQ_DATA_MASK                   0x00FF  /* WSEQ_DATA - [7:0] */
+#define WM8961_WSEQ_DATA_SHIFT                       0  /* WSEQ_DATA - [7:0] */
+#define WM8961_WSEQ_DATA_WIDTH                       8  /* WSEQ_DATA - [7:0] */
+
+/*
+ * R90 (0x5A) - Write Sequencer 4
+ */
+#define WM8961_WSEQ_ABORT                       0x0100  /* WSEQ_ABORT */
+#define WM8961_WSEQ_ABORT_MASK                  0x0100  /* WSEQ_ABORT */
+#define WM8961_WSEQ_ABORT_SHIFT                      8  /* WSEQ_ABORT */
+#define WM8961_WSEQ_ABORT_WIDTH                      1  /* WSEQ_ABORT */
+#define WM8961_WSEQ_START                       0x0080  /* WSEQ_START */
+#define WM8961_WSEQ_START_MASK                  0x0080  /* WSEQ_START */
+#define WM8961_WSEQ_START_SHIFT                      7  /* WSEQ_START */
+#define WM8961_WSEQ_START_WIDTH                      1  /* WSEQ_START */
+#define WM8961_WSEQ_START_INDEX_MASK            0x003F  /* WSEQ_START_INDEX - [5:0] */
+#define WM8961_WSEQ_START_INDEX_SHIFT                0  /* WSEQ_START_INDEX - [5:0] */
+#define WM8961_WSEQ_START_INDEX_WIDTH                6  /* WSEQ_START_INDEX - [5:0] */
+
+/*
+ * R91 (0x5B) - Write Sequencer 5
+ */
+#define WM8961_WSEQ_DATA_WIDTH_MASK             0x0070  /* WSEQ_DATA_WIDTH - [6:4] */
+#define WM8961_WSEQ_DATA_WIDTH_SHIFT                 4  /* WSEQ_DATA_WIDTH - [6:4] */
+#define WM8961_WSEQ_DATA_WIDTH_WIDTH                 3  /* WSEQ_DATA_WIDTH - [6:4] */
+#define WM8961_WSEQ_DATA_START_MASK             0x000F  /* WSEQ_DATA_START - [3:0] */
+#define WM8961_WSEQ_DATA_START_SHIFT                 0  /* WSEQ_DATA_START - [3:0] */
+#define WM8961_WSEQ_DATA_START_WIDTH                 4  /* WSEQ_DATA_START - [3:0] */
+
+/*
+ * R92 (0x5C) - Write Sequencer 6
+ */
+#define WM8961_WSEQ_DELAY_MASK                  0x000F  /* WSEQ_DELAY - [3:0] */
+#define WM8961_WSEQ_DELAY_SHIFT                      0  /* WSEQ_DELAY - [3:0] */
+#define WM8961_WSEQ_DELAY_WIDTH                      4  /* WSEQ_DELAY - [3:0] */
+
+/*
+ * R93 (0x5D) - Write Sequencer 7
+ */
+#define WM8961_WSEQ_BUSY                        0x0001  /* WSEQ_BUSY */
+#define WM8961_WSEQ_BUSY_MASK                   0x0001  /* WSEQ_BUSY */
+#define WM8961_WSEQ_BUSY_SHIFT                       0  /* WSEQ_BUSY */
+#define WM8961_WSEQ_BUSY_WIDTH                       1  /* WSEQ_BUSY */
+
+/*
+ * R252 (0xFC) - General test 1
+ */
+#define WM8961_ARA_ENA                          0x0002  /* ARA_ENA */
+#define WM8961_ARA_ENA_MASK                     0x0002  /* ARA_ENA */
+#define WM8961_ARA_ENA_SHIFT                         1  /* ARA_ENA */
+#define WM8961_ARA_ENA_WIDTH                         1  /* ARA_ENA */
+#define WM8961_AUTO_INC                         0x0001  /* AUTO_INC */
+#define WM8961_AUTO_INC_MASK                    0x0001  /* AUTO_INC */
+#define WM8961_AUTO_INC_SHIFT                        0  /* AUTO_INC */
+#define WM8961_AUTO_INC_WIDTH                        1  /* AUTO_INC */
+
+#endif
index 032dca22dbd3dce34746a3e3bc65717c051c7501..d66efb0546eadf3846aa81adaff2003bd8675dcf 100644 (file)
@@ -59,44 +59,7 @@ static const u16 wm8971_reg[] = {
        0x0079, 0x0079, 0x0079,          /* 40 */
 };
 
-static inline unsigned int wm8971_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg < WM8971_REG_COUNT)
-               return cache[reg];
-
-       return -1;
-}
-
-static inline void wm8971_write_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg < WM8971_REG_COUNT)
-               cache[reg] = value;
-}
-
-static int wm8971_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
-{
-       u8 data[2];
-
-       /* data is
-        *   D15..D9 WM8753 register offset
-        *   D8...D0 register data
-        */
-       data[0] = (reg << 1) | ((value >> 8) & 0x0001);
-       data[1] = value & 0x00ff;
-
-       wm8971_write_reg_cache (codec, reg, value);
-       if (codec->hw_write(codec->control_data, data, 2) == 2)
-               return 0;
-       else
-               return -EIO;
-}
-
-#define wm8971_reset(c)        wm8971_write(c, WM8971_RESET, 0)
+#define wm8971_reset(c)        snd_soc_write(c, WM8971_RESET, 0)
 
 /* WM8971 Controls */
 static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" };
@@ -521,7 +484,7 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8971_write(codec, WM8971_IFACE, iface);
+       snd_soc_write(codec, WM8971_IFACE, iface);
        return 0;
 }
 
@@ -533,8 +496,8 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->card->codec;
        struct wm8971_priv *wm8971 = codec->private_data;
-       u16 iface = wm8971_read_reg_cache(codec, WM8971_IFACE) & 0x1f3;
-       u16 srate = wm8971_read_reg_cache(codec, WM8971_SRATE) & 0x1c0;
+       u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3;
+       u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0;
        int coeff = get_coeff(wm8971->sysclk, params_rate(params));
 
        /* bit size */
@@ -553,9 +516,9 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
        }
 
        /* set iface & srate */
-       wm8971_write(codec, WM8971_IFACE, iface);
+       snd_soc_write(codec, WM8971_IFACE, iface);
        if (coeff >= 0)
-               wm8971_write(codec, WM8971_SRATE, srate |
+               snd_soc_write(codec, WM8971_SRATE, srate |
                        (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
 
        return 0;
@@ -564,33 +527,33 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
 static int wm8971_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u16 mute_reg = wm8971_read_reg_cache(codec, WM8971_ADCDAC) & 0xfff7;
+       u16 mute_reg = snd_soc_read(codec, WM8971_ADCDAC) & 0xfff7;
 
        if (mute)
-               wm8971_write(codec, WM8971_ADCDAC, mute_reg | 0x8);
+               snd_soc_write(codec, WM8971_ADCDAC, mute_reg | 0x8);
        else
-               wm8971_write(codec, WM8971_ADCDAC, mute_reg);
+               snd_soc_write(codec, WM8971_ADCDAC, mute_reg);
        return 0;
 }
 
 static int wm8971_set_bias_level(struct snd_soc_codec *codec,
        enum snd_soc_bias_level level)
 {
-       u16 pwr_reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e;
+       u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
                /* set vmid to 50k and unmute dac */
-               wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x00c1);
+               snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x00c1);
                break;
        case SND_SOC_BIAS_PREPARE:
                break;
        case SND_SOC_BIAS_STANDBY:
                /* mute dac and set vmid to 500k, enable VREF */
-               wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
+               snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
                break;
        case SND_SOC_BIAS_OFF:
-               wm8971_write(codec, WM8971_PWR1, 0x0001);
+               snd_soc_write(codec, WM8971_PWR1, 0x0001);
                break;
        }
        codec->bias_level = level;
@@ -667,8 +630,8 @@ static int wm8971_resume(struct platform_device *pdev)
 
        /* charge wm8971 caps */
        if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
-               reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e;
-               wm8971_write(codec, WM8971_PWR1, reg | 0x01c0);
+               reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
+               snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0);
                codec->bias_level = SND_SOC_BIAS_ON;
                queue_delayed_work(wm8971_workq, &codec->delayed_work,
                        msecs_to_jiffies(1000));
@@ -677,15 +640,14 @@ static int wm8971_resume(struct platform_device *pdev)
        return 0;
 }
 
-static int wm8971_init(struct snd_soc_device *socdev)
+static int wm8971_init(struct snd_soc_device *socdev,
+                      enum snd_soc_control_type control)
 {
        struct snd_soc_codec *codec = socdev->card->codec;
        int reg, ret = 0;
 
        codec->name = "WM8971";
        codec->owner = THIS_MODULE;
-       codec->read = wm8971_read_reg_cache;
-       codec->write = wm8971_write;
        codec->set_bias_level = wm8971_set_bias_level;
        codec->dai = &wm8971_dai;
        codec->reg_cache_size = ARRAY_SIZE(wm8971_reg);
@@ -695,42 +657,48 @@ static int wm8971_init(struct snd_soc_device *socdev)
        if (codec->reg_cache == NULL)
                return -ENOMEM;
 
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       if (ret < 0) {
+               printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
        wm8971_reset(codec);
 
        /* register pcms */
        ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
        if (ret < 0) {
                printk(KERN_ERR "wm8971: failed to create pcms\n");
-               goto pcm_err;
+               goto err;
        }
 
        /* charge output caps - set vmid to 5k for quick power up */
-       reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e;
-       wm8971_write(codec, WM8971_PWR1, reg | 0x01c0);
+       reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
+       snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0);
        codec->bias_level = SND_SOC_BIAS_STANDBY;
        queue_delayed_work(wm8971_workq, &codec->delayed_work,
                msecs_to_jiffies(1000));
 
        /* set the update bits */
-       reg = wm8971_read_reg_cache(codec, WM8971_LDAC);
-       wm8971_write(codec, WM8971_LDAC, reg | 0x0100);
-       reg = wm8971_read_reg_cache(codec, WM8971_RDAC);
-       wm8971_write(codec, WM8971_RDAC, reg | 0x0100);
-
-       reg = wm8971_read_reg_cache(codec, WM8971_LOUT1V);
-       wm8971_write(codec, WM8971_LOUT1V, reg | 0x0100);
-       reg = wm8971_read_reg_cache(codec, WM8971_ROUT1V);
-       wm8971_write(codec, WM8971_ROUT1V, reg | 0x0100);
-
-       reg = wm8971_read_reg_cache(codec, WM8971_LOUT2V);
-       wm8971_write(codec, WM8971_LOUT2V, reg | 0x0100);
-       reg = wm8971_read_reg_cache(codec, WM8971_ROUT2V);
-       wm8971_write(codec, WM8971_ROUT2V, reg | 0x0100);
-
-       reg = wm8971_read_reg_cache(codec, WM8971_LINVOL);
-       wm8971_write(codec, WM8971_LINVOL, reg | 0x0100);
-       reg = wm8971_read_reg_cache(codec, WM8971_RINVOL);
-       wm8971_write(codec, WM8971_RINVOL, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8971_LDAC);
+       snd_soc_write(codec, WM8971_LDAC, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8971_RDAC);
+       snd_soc_write(codec, WM8971_RDAC, reg | 0x0100);
+
+       reg = snd_soc_read(codec, WM8971_LOUT1V);
+       snd_soc_write(codec, WM8971_LOUT1V, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8971_ROUT1V);
+       snd_soc_write(codec, WM8971_ROUT1V, reg | 0x0100);
+
+       reg = snd_soc_read(codec, WM8971_LOUT2V);
+       snd_soc_write(codec, WM8971_LOUT2V, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8971_ROUT2V);
+       snd_soc_write(codec, WM8971_ROUT2V, reg | 0x0100);
+
+       reg = snd_soc_read(codec, WM8971_LINVOL);
+       snd_soc_write(codec, WM8971_LINVOL, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8971_RINVOL);
+       snd_soc_write(codec, WM8971_RINVOL, reg | 0x0100);
 
        snd_soc_add_controls(codec, wm8971_snd_controls,
                                ARRAY_SIZE(wm8971_snd_controls));
@@ -745,7 +713,7 @@ static int wm8971_init(struct snd_soc_device *socdev)
 card_err:
        snd_soc_free_pcms(socdev);
        snd_soc_dapm_free(socdev);
-pcm_err:
+err:
        kfree(codec->reg_cache);
        return ret;
 }
@@ -767,7 +735,7 @@ static int wm8971_i2c_probe(struct i2c_client *i2c,
 
        codec->control_data = i2c;
 
-       ret = wm8971_init(socdev);
+       ret = wm8971_init(socdev, SND_SOC_I2C);
        if (ret < 0)
                pr_err("failed to initialise WM8971\n");
 
@@ -877,7 +845,6 @@ static int wm8971_probe(struct platform_device *pdev)
 
 #if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
        if (setup->i2c_address) {
-               codec->hw_write = (hw_write_t)i2c_master_send;
                ret = wm8971_add_i2c_device(pdev, setup);
        }
 #endif
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
new file mode 100644 (file)
index 0000000..98d663a
--- /dev/null
@@ -0,0 +1,807 @@
+/*
+ * wm8974.c  --  WM8974 ALSA Soc Audio driver
+ *
+ * Copyright 2006-2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Liam Girdwood <linux@wolfsonmicro.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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8974.h"
+
+static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0050, 0x0000, 0x0140, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x00ff,
+       0x0000, 0x0000, 0x0100, 0x00ff,
+       0x0000, 0x0000, 0x012c, 0x002c,
+       0x002c, 0x002c, 0x002c, 0x0000,
+       0x0032, 0x0000, 0x0000, 0x0000,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0038, 0x000b, 0x0032, 0x0000,
+       0x0008, 0x000c, 0x0093, 0x00e9,
+       0x0000, 0x0000, 0x0000, 0x0000,
+       0x0003, 0x0010, 0x0000, 0x0000,
+       0x0000, 0x0002, 0x0000, 0x0000,
+       0x0000, 0x0000, 0x0039, 0x0000,
+       0x0000,
+};
+
+#define WM8974_POWER1_BIASEN  0x08
+#define WM8974_POWER1_BUFIOEN 0x10
+
+struct wm8974_priv {
+       struct snd_soc_codec codec;
+       u16 reg_cache[WM8974_CACHEREGNUM];
+};
+
+static struct snd_soc_codec *wm8974_codec;
+
+#define wm8974_reset(c)        snd_soc_write(c, WM8974_RESET, 0)
+
+static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" };
+static const char *wm8974_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz" };
+static const char *wm8974_eqmode[] = {"Capture", "Playback" };
+static const char *wm8974_bw[] = {"Narrow", "Wide" };
+static const char *wm8974_eq1[] = {"80Hz", "105Hz", "135Hz", "175Hz" };
+static const char *wm8974_eq2[] = {"230Hz", "300Hz", "385Hz", "500Hz" };
+static const char *wm8974_eq3[] = {"650Hz", "850Hz", "1.1kHz", "1.4kHz" };
+static const char *wm8974_eq4[] = {"1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" };
+static const char *wm8974_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz" };
+static const char *wm8974_alc[] = {"ALC", "Limiter" };
+
+static const struct soc_enum wm8974_enum[] = {
+       SOC_ENUM_SINGLE(WM8974_COMP, 1, 4, wm8974_companding), /* adc */
+       SOC_ENUM_SINGLE(WM8974_COMP, 3, 4, wm8974_companding), /* dac */
+       SOC_ENUM_SINGLE(WM8974_DAC,  4, 4, wm8974_deemp),
+       SOC_ENUM_SINGLE(WM8974_EQ1,  8, 2, wm8974_eqmode),
+
+       SOC_ENUM_SINGLE(WM8974_EQ1,  5, 4, wm8974_eq1),
+       SOC_ENUM_SINGLE(WM8974_EQ2,  8, 2, wm8974_bw),
+       SOC_ENUM_SINGLE(WM8974_EQ2,  5, 4, wm8974_eq2),
+       SOC_ENUM_SINGLE(WM8974_EQ3,  8, 2, wm8974_bw),
+
+       SOC_ENUM_SINGLE(WM8974_EQ3,  5, 4, wm8974_eq3),
+       SOC_ENUM_SINGLE(WM8974_EQ4,  8, 2, wm8974_bw),
+       SOC_ENUM_SINGLE(WM8974_EQ4,  5, 4, wm8974_eq4),
+       SOC_ENUM_SINGLE(WM8974_EQ5,  8, 2, wm8974_bw),
+
+       SOC_ENUM_SINGLE(WM8974_EQ5,  5, 4, wm8974_eq5),
+       SOC_ENUM_SINGLE(WM8974_ALC3,  8, 2, wm8974_alc),
+};
+
+static const char *wm8974_auxmode_text[] = { "Buffer", "Mixer" };
+
+static const struct soc_enum wm8974_auxmode =
+       SOC_ENUM_SINGLE(WM8974_INPUT,  3, 2, wm8974_auxmode_text);
+
+static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1);
+static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1200, 75, 0);
+static const DECLARE_TLV_DB_SCALE(spk_tlv, -5700, 100, 0);
+
+static const struct snd_kcontrol_new wm8974_snd_controls[] = {
+
+SOC_SINGLE("Digital Loopback Switch", WM8974_COMP, 0, 1, 0),
+
+SOC_ENUM("DAC Companding", wm8974_enum[1]),
+SOC_ENUM("ADC Companding", wm8974_enum[0]),
+
+SOC_ENUM("Playback De-emphasis", wm8974_enum[2]),
+SOC_SINGLE("DAC Inversion Switch", WM8974_DAC, 0, 1, 0),
+
+SOC_SINGLE_TLV("PCM Volume", WM8974_DACVOL, 0, 255, 0, digital_tlv),
+
+SOC_SINGLE("High Pass Filter Switch", WM8974_ADC, 8, 1, 0),
+SOC_SINGLE("High Pass Cut Off", WM8974_ADC, 4, 7, 0),
+SOC_SINGLE("ADC Inversion Switch", WM8974_ADC, 0, 1, 0),
+
+SOC_SINGLE_TLV("Capture Volume", WM8974_ADCVOL,  0, 255, 0, digital_tlv),
+
+SOC_ENUM("Equaliser Function", wm8974_enum[3]),
+SOC_ENUM("EQ1 Cut Off", wm8974_enum[4]),
+SOC_SINGLE_TLV("EQ1 Volume", WM8974_EQ1,  0, 24, 1, eq_tlv),
+
+SOC_ENUM("Equaliser EQ2 Bandwith", wm8974_enum[5]),
+SOC_ENUM("EQ2 Cut Off", wm8974_enum[6]),
+SOC_SINGLE_TLV("EQ2 Volume", WM8974_EQ2,  0, 24, 1, eq_tlv),
+
+SOC_ENUM("Equaliser EQ3 Bandwith", wm8974_enum[7]),
+SOC_ENUM("EQ3 Cut Off", wm8974_enum[8]),
+SOC_SINGLE_TLV("EQ3 Volume", WM8974_EQ3,  0, 24, 1, eq_tlv),
+
+SOC_ENUM("Equaliser EQ4 Bandwith", wm8974_enum[9]),
+SOC_ENUM("EQ4 Cut Off", wm8974_enum[10]),
+SOC_SINGLE_TLV("EQ4 Volume", WM8974_EQ4,  0, 24, 1, eq_tlv),
+
+SOC_ENUM("Equaliser EQ5 Bandwith", wm8974_enum[11]),
+SOC_ENUM("EQ5 Cut Off", wm8974_enum[12]),
+SOC_SINGLE_TLV("EQ5 Volume", WM8974_EQ5,  0, 24, 1, eq_tlv),
+
+SOC_SINGLE("DAC Playback Limiter Switch", WM8974_DACLIM1,  8, 1, 0),
+SOC_SINGLE("DAC Playback Limiter Decay", WM8974_DACLIM1,  4, 15, 0),
+SOC_SINGLE("DAC Playback Limiter Attack", WM8974_DACLIM1,  0, 15, 0),
+
+SOC_SINGLE("DAC Playback Limiter Threshold", WM8974_DACLIM2,  4, 7, 0),
+SOC_SINGLE("DAC Playback Limiter Boost", WM8974_DACLIM2,  0, 15, 0),
+
+SOC_SINGLE("ALC Enable Switch", WM8974_ALC1,  8, 1, 0),
+SOC_SINGLE("ALC Capture Max Gain", WM8974_ALC1,  3, 7, 0),
+SOC_SINGLE("ALC Capture Min Gain", WM8974_ALC1,  0, 7, 0),
+
+SOC_SINGLE("ALC Capture ZC Switch", WM8974_ALC2,  8, 1, 0),
+SOC_SINGLE("ALC Capture Hold", WM8974_ALC2,  4, 7, 0),
+SOC_SINGLE("ALC Capture Target", WM8974_ALC2,  0, 15, 0),
+
+SOC_ENUM("ALC Capture Mode", wm8974_enum[13]),
+SOC_SINGLE("ALC Capture Decay", WM8974_ALC3,  4, 15, 0),
+SOC_SINGLE("ALC Capture Attack", WM8974_ALC3,  0, 15, 0),
+
+SOC_SINGLE("ALC Capture Noise Gate Switch", WM8974_NGATE,  3, 1, 0),
+SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8974_NGATE,  0, 7, 0),
+
+SOC_SINGLE("Capture PGA ZC Switch", WM8974_INPPGA,  7, 1, 0),
+SOC_SINGLE_TLV("Capture PGA Volume", WM8974_INPPGA,  0, 63, 0, inpga_tlv),
+
+SOC_SINGLE("Speaker Playback ZC Switch", WM8974_SPKVOL,  7, 1, 0),
+SOC_SINGLE("Speaker Playback Switch", WM8974_SPKVOL,  6, 1, 1),
+SOC_SINGLE_TLV("Speaker Playback Volume", WM8974_SPKVOL,  0, 63, 0, spk_tlv),
+
+SOC_ENUM("Aux Mode", wm8974_auxmode),
+
+SOC_SINGLE("Capture Boost(+20dB)", WM8974_ADCBOOST,  8, 1, 0),
+SOC_SINGLE("Mono Playback Switch", WM8974_MONOMIX, 6, 1, 1),
+};
+
+/* Speaker Output Mixer */
+static const struct snd_kcontrol_new wm8974_speaker_mixer_controls[] = {
+SOC_DAPM_SINGLE("Line Bypass Switch", WM8974_SPKMIX, 1, 1, 0),
+SOC_DAPM_SINGLE("Aux Playback Switch", WM8974_SPKMIX, 5, 1, 0),
+SOC_DAPM_SINGLE("PCM Playback Switch", WM8974_SPKMIX, 0, 1, 1),
+};
+
+/* Mono Output Mixer */
+static const struct snd_kcontrol_new wm8974_mono_mixer_controls[] = {
+SOC_DAPM_SINGLE("Line Bypass Switch", WM8974_MONOMIX, 1, 1, 0),
+SOC_DAPM_SINGLE("Aux Playback Switch", WM8974_MONOMIX, 2, 1, 0),
+SOC_DAPM_SINGLE("PCM Playback Switch", WM8974_MONOMIX, 0, 1, 0),
+};
+
+/* Boost mixer */
+static const struct snd_kcontrol_new wm8974_boost_mixer[] = {
+SOC_DAPM_SINGLE("Aux Switch", WM8974_INPPGA, 6, 1, 0),
+};
+
+/* Input PGA */
+static const struct snd_kcontrol_new wm8974_inpga[] = {
+SOC_DAPM_SINGLE("Aux Switch", WM8974_INPUT, 2, 1, 0),
+SOC_DAPM_SINGLE("MicN Switch", WM8974_INPUT, 1, 1, 0),
+SOC_DAPM_SINGLE("MicP Switch", WM8974_INPUT, 0, 1, 0),
+};
+
+/* AUX Input boost vol */
+static const struct snd_kcontrol_new wm8974_aux_boost_controls =
+SOC_DAPM_SINGLE("Aux Volume", WM8974_ADCBOOST, 0, 7, 0);
+
+/* Mic Input boost vol */
+static const struct snd_kcontrol_new wm8974_mic_boost_controls =
+SOC_DAPM_SINGLE("Mic Volume", WM8974_ADCBOOST, 4, 7, 0);
+
+static const struct snd_soc_dapm_widget wm8974_dapm_widgets[] = {
+SND_SOC_DAPM_MIXER("Speaker Mixer", WM8974_POWER3, 2, 0,
+       &wm8974_speaker_mixer_controls[0],
+       ARRAY_SIZE(wm8974_speaker_mixer_controls)),
+SND_SOC_DAPM_MIXER("Mono Mixer", WM8974_POWER3, 3, 0,
+       &wm8974_mono_mixer_controls[0],
+       ARRAY_SIZE(wm8974_mono_mixer_controls)),
+SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8974_POWER3, 0, 0),
+SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8974_POWER2, 0, 0),
+SND_SOC_DAPM_PGA("Aux Input", WM8974_POWER1, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA("SpkN Out", WM8974_POWER3, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA("SpkP Out", WM8974_POWER3, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Mono Out", WM8974_POWER3, 7, 0, NULL, 0),
+
+SND_SOC_DAPM_MIXER("Input PGA", WM8974_POWER2, 2, 0, wm8974_inpga,
+                  ARRAY_SIZE(wm8974_inpga)),
+SND_SOC_DAPM_MIXER("Boost Mixer", WM8974_POWER2, 4, 0,
+                  wm8974_boost_mixer, ARRAY_SIZE(wm8974_boost_mixer)),
+
+SND_SOC_DAPM_MICBIAS("Mic Bias", WM8974_POWER1, 4, 0),
+
+SND_SOC_DAPM_INPUT("MICN"),
+SND_SOC_DAPM_INPUT("MICP"),
+SND_SOC_DAPM_INPUT("AUX"),
+SND_SOC_DAPM_OUTPUT("MONOOUT"),
+SND_SOC_DAPM_OUTPUT("SPKOUTP"),
+SND_SOC_DAPM_OUTPUT("SPKOUTN"),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+       /* Mono output mixer */
+       {"Mono Mixer", "PCM Playback Switch", "DAC"},
+       {"Mono Mixer", "Aux Playback Switch", "Aux Input"},
+       {"Mono Mixer", "Line Bypass Switch", "Boost Mixer"},
+
+       /* Speaker output mixer */
+       {"Speaker Mixer", "PCM Playback Switch", "DAC"},
+       {"Speaker Mixer", "Aux Playback Switch", "Aux Input"},
+       {"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"},
+
+       /* Outputs */
+       {"Mono Out", NULL, "Mono Mixer"},
+       {"MONOOUT", NULL, "Mono Out"},
+       {"SpkN Out", NULL, "Speaker Mixer"},
+       {"SpkP Out", NULL, "Speaker Mixer"},
+       {"SPKOUTN", NULL, "SpkN Out"},
+       {"SPKOUTP", NULL, "SpkP Out"},
+
+       /* Boost Mixer */
+       {"ADC", NULL, "Boost Mixer"},
+       {"Boost Mixer", "Aux Switch", "Aux Input"},
+       {"Boost Mixer", NULL, "Input PGA"},
+       {"Boost Mixer", NULL, "MICP"},
+
+       /* Input PGA */
+       {"Input PGA", "Aux Switch", "Aux Input"},
+       {"Input PGA", "MicN Switch", "MICN"},
+       {"Input PGA", "MicP Switch", "MICP"},
+
+       /* Inputs */
+       {"Aux Input", NULL, "AUX"},
+};
+
+static int wm8974_add_widgets(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_new_controls(codec, wm8974_dapm_widgets,
+                                 ARRAY_SIZE(wm8974_dapm_widgets));
+
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+       snd_soc_dapm_new_widgets(codec);
+       return 0;
+}
+
+struct pll_ {
+       unsigned int pre_div:4; /* prescale - 1 */
+       unsigned int n:4;
+       unsigned int k;
+};
+
+static struct pll_ pll_div;
+
+/* The size in bits of the pll divide multiplied by 10
+ * to allow rounding later */
+#define FIXED_PLL_SIZE ((1 << 24) * 10)
+
+static void pll_factors(unsigned int target, unsigned int source)
+{
+       unsigned long long Kpart;
+       unsigned int K, Ndiv, Nmod;
+
+       Ndiv = target / source;
+       if (Ndiv < 6) {
+               source >>= 1;
+               pll_div.pre_div = 1;
+               Ndiv = target / source;
+       } else
+               pll_div.pre_div = 0;
+
+       if ((Ndiv < 6) || (Ndiv > 12))
+               printk(KERN_WARNING
+                       "WM8974 N value %u outwith recommended range!\n",
+                       Ndiv);
+
+       pll_div.n = Ndiv;
+       Nmod = target % source;
+       Kpart = FIXED_PLL_SIZE * (long long)Nmod;
+
+       do_div(Kpart, source);
+
+       K = Kpart & 0xFFFFFFFF;
+
+       /* Check if we need to round */
+       if ((K % 10) >= 5)
+               K += 5;
+
+       /* Move down to proper range now rounding is done */
+       K /= 10;
+
+       pll_div.k = K;
+}
+
+static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai,
+               int pll_id, unsigned int freq_in, unsigned int freq_out)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 reg;
+
+       if (freq_in == 0 || freq_out == 0) {
+               /* Clock CODEC directly from MCLK */
+               reg = snd_soc_read(codec, WM8974_CLOCK);
+               snd_soc_write(codec, WM8974_CLOCK, reg & 0x0ff);
+
+               /* Turn off PLL */
+               reg = snd_soc_read(codec, WM8974_POWER1);
+               snd_soc_write(codec, WM8974_POWER1, reg & 0x1df);
+               return 0;
+       }
+
+       pll_factors(freq_out*4, freq_in);
+
+       snd_soc_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n);
+       snd_soc_write(codec, WM8974_PLLK1, pll_div.k >> 18);
+       snd_soc_write(codec, WM8974_PLLK2, (pll_div.k >> 9) & 0x1ff);
+       snd_soc_write(codec, WM8974_PLLK3, pll_div.k & 0x1ff);
+       reg = snd_soc_read(codec, WM8974_POWER1);
+       snd_soc_write(codec, WM8974_POWER1, reg | 0x020);
+
+       /* Run CODEC from PLL instead of MCLK */
+       reg = snd_soc_read(codec, WM8974_CLOCK);
+       snd_soc_write(codec, WM8974_CLOCK, reg | 0x100);
+
+       return 0;
+}
+
+/*
+ * Configure WM8974 clock dividers.
+ */
+static int wm8974_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
+               int div_id, int div)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 reg;
+
+       switch (div_id) {
+       case WM8974_OPCLKDIV:
+               reg = snd_soc_read(codec, WM8974_GPIO) & 0x1cf;
+               snd_soc_write(codec, WM8974_GPIO, reg | div);
+               break;
+       case WM8974_MCLKDIV:
+               reg = snd_soc_read(codec, WM8974_CLOCK) & 0x11f;
+               snd_soc_write(codec, WM8974_CLOCK, reg | div);
+               break;
+       case WM8974_ADCCLK:
+               reg = snd_soc_read(codec, WM8974_ADC) & 0x1f7;
+               snd_soc_write(codec, WM8974_ADC, reg | div);
+               break;
+       case WM8974_DACCLK:
+               reg = snd_soc_read(codec, WM8974_DAC) & 0x1f7;
+               snd_soc_write(codec, WM8974_DAC, reg | div);
+               break;
+       case WM8974_BCLKDIV:
+               reg = snd_soc_read(codec, WM8974_CLOCK) & 0x1e3;
+               snd_soc_write(codec, WM8974_CLOCK, reg | div);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int wm8974_set_dai_fmt(struct snd_soc_dai *codec_dai,
+               unsigned int fmt)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       u16 iface = 0;
+       u16 clk = snd_soc_read(codec, WM8974_CLOCK) & 0x1fe;
+
+       /* set master/slave audio interface */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBM_CFM:
+               clk |= 0x0001;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFS:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* interface format */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               iface |= 0x0010;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               iface |= 0x0008;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               iface |= 0x00018;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* clock inversion */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               iface |= 0x0180;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               iface |= 0x0100;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               iface |= 0x0080;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       snd_soc_write(codec, WM8974_IFACE, iface);
+       snd_soc_write(codec, WM8974_CLOCK, clk);
+       return 0;
+}
+
+static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params,
+                               struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u16 iface = snd_soc_read(codec, WM8974_IFACE) & 0x19f;
+       u16 adn = snd_soc_read(codec, WM8974_ADD) & 0x1f1;
+
+       /* bit size */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               iface |= 0x0020;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               iface |= 0x0040;
+               break;
+       case SNDRV_PCM_FORMAT_S32_LE:
+               iface |= 0x0060;
+               break;
+       }
+
+       /* filter coefficient */
+       switch (params_rate(params)) {
+       case SNDRV_PCM_RATE_8000:
+               adn |= 0x5 << 1;
+               break;
+       case SNDRV_PCM_RATE_11025:
+               adn |= 0x4 << 1;
+               break;
+       case SNDRV_PCM_RATE_16000:
+               adn |= 0x3 << 1;
+               break;
+       case SNDRV_PCM_RATE_22050:
+               adn |= 0x2 << 1;
+               break;
+       case SNDRV_PCM_RATE_32000:
+               adn |= 0x1 << 1;
+               break;
+       case SNDRV_PCM_RATE_44100:
+       case SNDRV_PCM_RATE_48000:
+               break;
+       }
+
+       snd_soc_write(codec, WM8974_IFACE, iface);
+       snd_soc_write(codec, WM8974_ADD, adn);
+       return 0;
+}
+
+static int wm8974_mute(struct snd_soc_dai *dai, int mute)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       u16 mute_reg = snd_soc_read(codec, WM8974_DAC) & 0xffbf;
+
+       if (mute)
+               snd_soc_write(codec, WM8974_DAC, mute_reg | 0x40);
+       else
+               snd_soc_write(codec, WM8974_DAC, mute_reg);
+       return 0;
+}
+
+/* liam need to make this lower power with dapm */
+static int wm8974_set_bias_level(struct snd_soc_codec *codec,
+       enum snd_soc_bias_level level)
+{
+       u16 power1 = snd_soc_read(codec, WM8974_POWER1) & ~0x3;
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+       case SND_SOC_BIAS_PREPARE:
+               power1 |= 0x1;  /* VMID 50k */
+               snd_soc_write(codec, WM8974_POWER1, power1);
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN;
+
+               if (codec->bias_level == SND_SOC_BIAS_OFF) {
+                       /* Initial cap charge at VMID 5k */
+                       snd_soc_write(codec, WM8974_POWER1, power1 | 0x3);
+                       mdelay(100);
+               }
+
+               power1 |= 0x2;  /* VMID 500k */
+               snd_soc_write(codec, WM8974_POWER1, power1);
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               snd_soc_write(codec, WM8974_POWER1, 0);
+               snd_soc_write(codec, WM8974_POWER2, 0);
+               snd_soc_write(codec, WM8974_POWER3, 0);
+               break;
+       }
+
+       codec->bias_level = level;
+       return 0;
+}
+
+#define WM8974_RATES (SNDRV_PCM_RATE_8000_48000)
+
+#define WM8974_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+       SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops wm8974_ops = {
+       .hw_params = wm8974_pcm_hw_params,
+       .digital_mute = wm8974_mute,
+       .set_fmt = wm8974_set_dai_fmt,
+       .set_clkdiv = wm8974_set_dai_clkdiv,
+       .set_pll = wm8974_set_dai_pll,
+};
+
+struct snd_soc_dai wm8974_dai = {
+       .name = "WM8974 HiFi",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 1,
+               .channels_max = 2,   /* Only 1 channel of data */
+               .rates = WM8974_RATES,
+               .formats = WM8974_FORMATS,},
+       .capture = {
+               .stream_name = "Capture",
+               .channels_min = 1,
+               .channels_max = 2,   /* Only 1 channel of data */
+               .rates = WM8974_RATES,
+               .formats = WM8974_FORMATS,},
+       .ops = &wm8974_ops,
+       .symmetric_rates = 1,
+};
+EXPORT_SYMBOL_GPL(wm8974_dai);
+
+static int wm8974_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+
+       wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF);
+       return 0;
+}
+
+static int wm8974_resume(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec = socdev->card->codec;
+       int i;
+       u8 data[2];
+       u16 *cache = codec->reg_cache;
+
+       /* Sync reg_cache with the hardware */
+       for (i = 0; i < ARRAY_SIZE(wm8974_reg); i++) {
+               data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
+               data[1] = cache[i] & 0x00ff;
+               codec->hw_write(codec->control_data, data, 2);
+       }
+       wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       wm8974_set_bias_level(codec, codec->suspend_bias_level);
+       return 0;
+}
+
+static int wm8974_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec;
+       int ret = 0;
+
+       if (wm8974_codec == NULL) {
+               dev_err(&pdev->dev, "Codec device not registered\n");
+               return -ENODEV;
+       }
+
+       socdev->card->codec = wm8974_codec;
+       codec = wm8974_codec;
+
+       /* register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to create pcms: %d\n", ret);
+               goto pcm_err;
+       }
+
+       snd_soc_add_controls(codec, wm8974_snd_controls,
+                            ARRAY_SIZE(wm8974_snd_controls));
+       wm8974_add_widgets(codec);
+       ret = snd_soc_init_card(socdev);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to register card: %d\n", ret);
+               goto card_err;
+       }
+
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+pcm_err:
+       return ret;
+}
+
+/* power down chip */
+static int wm8974_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+
+       return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8974 = {
+       .probe =        wm8974_probe,
+       .remove =       wm8974_remove,
+       .suspend =      wm8974_suspend,
+       .resume =       wm8974_resume,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8974);
+
+static __devinit int wm8974_register(struct wm8974_priv *wm8974)
+{
+       int ret;
+       struct snd_soc_codec *codec = &wm8974->codec;
+
+       if (wm8974_codec) {
+               dev_err(codec->dev, "Another WM8974 is registered\n");
+               return -EINVAL;
+       }
+
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       codec->private_data = wm8974;
+       codec->name = "WM8974";
+       codec->owner = THIS_MODULE;
+       codec->bias_level = SND_SOC_BIAS_OFF;
+       codec->set_bias_level = wm8974_set_bias_level;
+       codec->dai = &wm8974_dai;
+       codec->num_dai = 1;
+       codec->reg_cache_size = WM8974_CACHEREGNUM;
+       codec->reg_cache = &wm8974->reg_cache;
+
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
+       memcpy(codec->reg_cache, wm8974_reg, sizeof(wm8974_reg));
+
+       ret = wm8974_reset(codec);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to issue reset\n");
+               goto err;
+       }
+
+       wm8974_dai.dev = codec->dev;
+
+       wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+       wm8974_codec = codec;
+
+       ret = snd_soc_register_codec(codec);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register codec: %d\n", ret);
+               goto err;
+       }
+
+       ret = snd_soc_register_dai(&wm8974_dai);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
+               goto err_codec;
+       }
+
+       return 0;
+
+err_codec:
+       snd_soc_unregister_codec(codec);
+err:
+       kfree(wm8974);
+       return ret;
+}
+
+static __devexit void wm8974_unregister(struct wm8974_priv *wm8974)
+{
+       wm8974_set_bias_level(&wm8974->codec, SND_SOC_BIAS_OFF);
+       snd_soc_unregister_dai(&wm8974_dai);
+       snd_soc_unregister_codec(&wm8974->codec);
+       kfree(wm8974);
+       wm8974_codec = NULL;
+}
+
+static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct wm8974_priv *wm8974;
+       struct snd_soc_codec *codec;
+
+       wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL);
+       if (wm8974 == NULL)
+               return -ENOMEM;
+
+       codec = &wm8974->codec;
+       codec->hw_write = (hw_write_t)i2c_master_send;
+
+       i2c_set_clientdata(i2c, wm8974);
+       codec->control_data = i2c;
+
+       codec->dev = &i2c->dev;
+
+       return wm8974_register(wm8974);
+}
+
+static __devexit int wm8974_i2c_remove(struct i2c_client *client)
+{
+       struct wm8974_priv *wm8974 = i2c_get_clientdata(client);
+       wm8974_unregister(wm8974);
+       return 0;
+}
+
+static const struct i2c_device_id wm8974_i2c_id[] = {
+       { "wm8974", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id);
+
+static struct i2c_driver wm8974_i2c_driver = {
+       .driver = {
+               .name = "WM8974",
+               .owner = THIS_MODULE,
+       },
+       .probe =    wm8974_i2c_probe,
+       .remove =   __devexit_p(wm8974_i2c_remove),
+       .id_table = wm8974_i2c_id,
+};
+
+static int __init wm8974_modinit(void)
+{
+       return i2c_add_driver(&wm8974_i2c_driver);
+}
+module_init(wm8974_modinit);
+
+static void __exit wm8974_exit(void)
+{
+       i2c_del_driver(&wm8974_i2c_driver);
+}
+module_exit(wm8974_exit);
+
+MODULE_DESCRIPTION("ASoC WM8974 driver");
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8974.h b/sound/soc/codecs/wm8974.h
new file mode 100644 (file)
index 0000000..98de956
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * wm8974.h  --  WM8974 Soc Audio driver
+ *
+ * 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 _WM8974_H
+#define _WM8974_H
+
+/* WM8974 register space */
+
+#define WM8974_RESET           0x0
+#define WM8974_POWER1          0x1
+#define WM8974_POWER2          0x2
+#define WM8974_POWER3          0x3
+#define WM8974_IFACE           0x4
+#define WM8974_COMP            0x5
+#define WM8974_CLOCK           0x6
+#define WM8974_ADD             0x7
+#define WM8974_GPIO            0x8
+#define WM8974_DAC             0xa
+#define WM8974_DACVOL          0xb
+#define WM8974_ADC             0xe
+#define WM8974_ADCVOL          0xf
+#define WM8974_EQ1             0x12
+#define WM8974_EQ2             0x13
+#define WM8974_EQ3             0x14
+#define WM8974_EQ4             0x15
+#define WM8974_EQ5             0x16
+#define WM8974_DACLIM1         0x18
+#define WM8974_DACLIM2         0x19
+#define WM8974_NOTCH1          0x1b
+#define WM8974_NOTCH2          0x1c
+#define WM8974_NOTCH3          0x1d
+#define WM8974_NOTCH4          0x1e
+#define WM8974_ALC1            0x20
+#define WM8974_ALC2            0x21
+#define WM8974_ALC3            0x22
+#define WM8974_NGATE           0x23
+#define WM8974_PLLN            0x24
+#define WM8974_PLLK1           0x25
+#define WM8974_PLLK2           0x26
+#define WM8974_PLLK3           0x27
+#define WM8974_ATTEN           0x28
+#define WM8974_INPUT           0x2c
+#define WM8974_INPPGA          0x2d
+#define WM8974_ADCBOOST                0x2f
+#define WM8974_OUTPUT          0x31
+#define WM8974_SPKMIX          0x32
+#define WM8974_SPKVOL          0x36
+#define WM8974_MONOMIX         0x38
+
+#define WM8974_CACHEREGNUM     57
+
+/* Clock divider Id's */
+#define WM8974_OPCLKDIV                0
+#define WM8974_MCLKDIV         1
+#define WM8974_ADCCLK          2
+#define WM8974_DACCLK          3
+#define WM8974_BCLKDIV         4
+
+/* DAC clock dividers */
+#define WM8974_DACCLK_F2       (1 << 3)
+#define WM8974_DACCLK_F4       (0 << 3)
+
+/* ADC clock dividers */
+#define WM8974_ADCCLK_F2       (1 << 3)
+#define WM8974_ADCCLK_F4       (0 << 3)
+
+/* PLL Out dividers */
+#define WM8974_OPCLKDIV_1      (0 << 4)
+#define WM8974_OPCLKDIV_2      (1 << 4)
+#define WM8974_OPCLKDIV_3      (2 << 4)
+#define WM8974_OPCLKDIV_4      (3 << 4)
+
+/* BCLK clock dividers */
+#define WM8974_BCLKDIV_1       (0 << 2)
+#define WM8974_BCLKDIV_2       (1 << 2)
+#define WM8974_BCLKDIV_4       (2 << 2)
+#define WM8974_BCLKDIV_8       (3 << 2)
+#define WM8974_BCLKDIV_16      (4 << 2)
+#define WM8974_BCLKDIV_32      (5 << 2)
+
+/* MCLK clock dividers */
+#define WM8974_MCLKDIV_1       (0 << 5)
+#define WM8974_MCLKDIV_1_5     (1 << 5)
+#define WM8974_MCLKDIV_2       (2 << 5)
+#define WM8974_MCLKDIV_3       (3 << 5)
+#define WM8974_MCLKDIV_4       (4 << 5)
+#define WM8974_MCLKDIV_6       (5 << 5)
+#define WM8974_MCLKDIV_8       (6 << 5)
+#define WM8974_MCLKDIV_12      (7 << 5)
+
+extern struct snd_soc_dai wm8974_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8974;
+
+#endif
index c05f71803aa8a30f07da731d70591800c5a844fe..3f530f8a972af3547a9da579e4db2f8f519e4e58 100644 (file)
@@ -57,50 +57,7 @@ struct wm8988_priv {
 };
 
 
-/*
- * read wm8988 register cache
- */
-static inline unsigned int wm8988_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg > WM8988_NUM_REG)
-               return -1;
-       return cache[reg];
-}
-
-/*
- * write wm8988 register cache
- */
-static inline void wm8988_write_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg > WM8988_NUM_REG)
-               return;
-       cache[reg] = value;
-}
-
-static int wm8988_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
-{
-       u8 data[2];
-
-       /* data is
-        *   D15..D9 WM8753 register offset
-        *   D8...D0 register data
-        */
-       data[0] = (reg << 1) | ((value >> 8) & 0x0001);
-       data[1] = value & 0x00ff;
-
-       wm8988_write_reg_cache(codec, reg, value);
-       if (codec->hw_write(codec->control_data, data, 2) == 2)
-               return 0;
-       else
-               return -EIO;
-}
-
-#define wm8988_reset(c)        wm8988_write(c, WM8988_RESET, 0)
+#define wm8988_reset(c)        snd_soc_write(c, WM8988_RESET, 0)
 
 /*
  * WM8988 Controls
@@ -226,15 +183,15 @@ static int wm8988_lrc_control(struct snd_soc_dapm_widget *w,
                              struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_codec *codec = w->codec;
-       u16 adctl2 = wm8988_read_reg_cache(codec, WM8988_ADCTL2);
+       u16 adctl2 = snd_soc_read(codec, WM8988_ADCTL2);
 
        /* Use the DAC to gate LRC if active, otherwise use ADC */
-       if (wm8988_read_reg_cache(codec, WM8988_PWR2) & 0x180)
+       if (snd_soc_read(codec, WM8988_PWR2) & 0x180)
                adctl2 &= ~0x4;
        else
                adctl2 |= 0x4;
 
-       return wm8988_write(codec, WM8988_ADCTL2, adctl2);
+       return snd_soc_write(codec, WM8988_ADCTL2, adctl2);
 }
 
 static const char *wm8988_line_texts[] = {
@@ -619,7 +576,7 @@ static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8988_write(codec, WM8988_IFACE, iface);
+       snd_soc_write(codec, WM8988_IFACE, iface);
        return 0;
 }
 
@@ -653,8 +610,8 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->card->codec;
        struct wm8988_priv *wm8988 = codec->private_data;
-       u16 iface = wm8988_read_reg_cache(codec, WM8988_IFACE) & 0x1f3;
-       u16 srate = wm8988_read_reg_cache(codec, WM8988_SRATE) & 0x180;
+       u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3;
+       u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180;
        int coeff;
 
        coeff = get_coeff(wm8988->sysclk, params_rate(params));
@@ -685,9 +642,9 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
        }
 
        /* set iface & srate */
-       wm8988_write(codec, WM8988_IFACE, iface);
+       snd_soc_write(codec, WM8988_IFACE, iface);
        if (coeff >= 0)
-               wm8988_write(codec, WM8988_SRATE, srate |
+               snd_soc_write(codec, WM8988_SRATE, srate |
                        (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
 
        return 0;
@@ -696,19 +653,19 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
 static int wm8988_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u16 mute_reg = wm8988_read_reg_cache(codec, WM8988_ADCDAC) & 0xfff7;
+       u16 mute_reg = snd_soc_read(codec, WM8988_ADCDAC) & 0xfff7;
 
        if (mute)
-               wm8988_write(codec, WM8988_ADCDAC, mute_reg | 0x8);
+               snd_soc_write(codec, WM8988_ADCDAC, mute_reg | 0x8);
        else
-               wm8988_write(codec, WM8988_ADCDAC, mute_reg);
+               snd_soc_write(codec, WM8988_ADCDAC, mute_reg);
        return 0;
 }
 
 static int wm8988_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
-       u16 pwr_reg = wm8988_read_reg_cache(codec, WM8988_PWR1) & ~0x1c1;
+       u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
@@ -716,24 +673,24 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
 
        case SND_SOC_BIAS_PREPARE:
                /* VREF, VMID=2x50k, digital enabled */
-               wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x00c0);
+               snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x00c0);
                break;
 
        case SND_SOC_BIAS_STANDBY:
                if (codec->bias_level == SND_SOC_BIAS_OFF) {
                        /* VREF, VMID=2x5k */
-                       wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
+                       snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
 
                        /* Charge caps */
                        msleep(100);
                }
 
                /* VREF, VMID=2*500k, digital stopped */
-               wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x0141);
+               snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x0141);
                break;
 
        case SND_SOC_BIAS_OFF:
-               wm8988_write(codec, WM8988_PWR1, 0x0000);
+               snd_soc_write(codec, WM8988_PWR1, 0x0000);
                break;
        }
        codec->bias_level = level;
@@ -868,7 +825,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8988 = {
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988);
 
-static int wm8988_register(struct wm8988_priv *wm8988)
+static int wm8988_register(struct wm8988_priv *wm8988,
+                          enum snd_soc_control_type control)
 {
        struct snd_soc_codec *codec = &wm8988->codec;
        int ret;
@@ -887,8 +845,6 @@ static int wm8988_register(struct wm8988_priv *wm8988)
        codec->private_data = wm8988;
        codec->name = "WM8988";
        codec->owner = THIS_MODULE;
-       codec->read = wm8988_read_reg_cache;
-       codec->write = wm8988_write;
        codec->dai = &wm8988_dai;
        codec->num_dai = 1;
        codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache);
@@ -899,23 +855,29 @@ static int wm8988_register(struct wm8988_priv *wm8988)
        memcpy(codec->reg_cache, wm8988_reg,
               sizeof(wm8988_reg));
 
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
+       if (ret < 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               goto err;
+       }
+
        ret = wm8988_reset(codec);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to issue reset\n");
-               return ret;
+               goto err;
        }
 
        /* set the update bits (we always update left then right) */
-       reg = wm8988_read_reg_cache(codec, WM8988_RADC);
-       wm8988_write(codec, WM8988_RADC, reg | 0x100);
-       reg = wm8988_read_reg_cache(codec, WM8988_RDAC);
-       wm8988_write(codec, WM8988_RDAC, reg | 0x0100);
-       reg = wm8988_read_reg_cache(codec, WM8988_ROUT1V);
-       wm8988_write(codec, WM8988_ROUT1V, reg | 0x0100);
-       reg = wm8988_read_reg_cache(codec, WM8988_ROUT2V);
-       wm8988_write(codec, WM8988_ROUT2V, reg | 0x0100);
-       reg = wm8988_read_reg_cache(codec, WM8988_RINVOL);
-       wm8988_write(codec, WM8988_RINVOL, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8988_RADC);
+       snd_soc_write(codec, WM8988_RADC, reg | 0x100);
+       reg = snd_soc_read(codec, WM8988_RDAC);
+       snd_soc_write(codec, WM8988_RDAC, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8988_ROUT1V);
+       snd_soc_write(codec, WM8988_ROUT1V, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8988_ROUT2V);
+       snd_soc_write(codec, WM8988_ROUT2V, reg | 0x0100);
+       reg = snd_soc_read(codec, WM8988_RINVOL);
+       snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100);
 
        wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY);
 
@@ -926,18 +888,20 @@ static int wm8988_register(struct wm8988_priv *wm8988)
        ret = snd_soc_register_codec(codec);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to register codec: %d\n", ret);
-               return ret;
+               goto err;
        }
 
        ret = snd_soc_register_dai(&wm8988_dai);
        if (ret != 0) {
                dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
                snd_soc_unregister_codec(codec);
-               return ret;
+               goto err_codec;
        }
 
        return 0;
 
+err_codec:
+       snd_soc_unregister_codec(codec);
 err:
        kfree(wm8988);
        return ret;
@@ -964,14 +928,13 @@ static int wm8988_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        codec = &wm8988->codec;
-       codec->hw_write = (hw_write_t)i2c_master_send;
 
        i2c_set_clientdata(i2c, wm8988);
        codec->control_data = i2c;
 
        codec->dev = &i2c->dev;
 
-       return wm8988_register(wm8988);
+       return wm8988_register(wm8988, SND_SOC_I2C);
 }
 
 static int wm8988_i2c_remove(struct i2c_client *client)
@@ -981,6 +944,21 @@ static int wm8988_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm8988_i2c_suspend(struct i2c_client *client, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&client->dev);
+}
+
+static int wm8988_i2c_resume(struct i2c_client *client)
+{
+       return snd_soc_resume_device(&client->dev);
+}
+#else
+#define wm8988_i2c_suspend NULL
+#define wm8988_i2c_resume NULL
+#endif
+
 static const struct i2c_device_id wm8988_i2c_id[] = {
        { "wm8988", 0 },
        { }
@@ -994,35 +972,13 @@ static struct i2c_driver wm8988_i2c_driver = {
        },
        .probe = wm8988_i2c_probe,
        .remove = wm8988_i2c_remove,
+       .suspend = wm8988_i2c_suspend,
+       .resume = wm8988_i2c_resume,
        .id_table = wm8988_i2c_id,
 };
 #endif
 
 #if defined(CONFIG_SPI_MASTER)
-static int wm8988_spi_write(struct spi_device *spi, const char *data, int len)
-{
-       struct spi_transfer t;
-       struct spi_message m;
-       u8 msg[2];
-
-       if (len <= 0)
-               return 0;
-
-       msg[0] = data[0];
-       msg[1] = data[1];
-
-       spi_message_init(&m);
-       memset(&t, 0, (sizeof t));
-
-       t.tx_buf = &msg[0];
-       t.len = len;
-
-       spi_message_add_tail(&t, &m);
-       spi_sync(spi, &m);
-
-       return len;
-}
-
 static int __devinit wm8988_spi_probe(struct spi_device *spi)
 {
        struct wm8988_priv *wm8988;
@@ -1033,24 +989,38 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
                return -ENOMEM;
 
        codec = &wm8988->codec;
-       codec->hw_write = (hw_write_t)wm8988_spi_write;
        codec->control_data = spi;
        codec->dev = &spi->dev;
 
-       spi->dev.driver_data = wm8988;
+       dev_set_drvdata(&spi->dev, wm8988);
 
-       return wm8988_register(wm8988);
+       return wm8988_register(wm8988, SND_SOC_SPI);
 }
 
 static int __devexit wm8988_spi_remove(struct spi_device *spi)
 {
-       struct wm8988_priv *wm8988 = spi->dev.driver_data;
+       struct wm8988_priv *wm8988 = dev_get_drvdata(&spi->dev);
 
        wm8988_unregister(wm8988);
 
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm8988_spi_suspend(struct spi_device *spi, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&spi->dev);
+}
+
+static int wm8988_spi_resume(struct spi_device *spi)
+{
+       return snd_soc_resume_device(&spi->dev);
+}
+#else
+#define wm8988_spi_suspend NULL
+#define wm8988_spi_resume NULL
+#endif
+
 static struct spi_driver wm8988_spi_driver = {
        .driver = {
                .name   = "wm8988",
@@ -1059,6 +1029,8 @@ static struct spi_driver wm8988_spi_driver = {
        },
        .probe          = wm8988_spi_probe,
        .remove         = __devexit_p(wm8988_spi_remove),
+       .suspend        = wm8988_spi_suspend,
+       .resume         = wm8988_spi_resume,
 };
 #endif
 
index d029818350e9fe9d5778c3fbb4087b0245d58023..2d702db4131db36f17d854621c99767777c64c17 100644 (file)
@@ -108,53 +108,7 @@ static const u16 wm8990_reg[] = {
        0x0000,     /* R63 - Driver internal */
 };
 
-/*
- * read wm8990 register cache
- */
-static inline unsigned int wm8990_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       BUG_ON(reg >= ARRAY_SIZE(wm8990_reg));
-       return cache[reg];
-}
-
-/*
- * write wm8990 register cache
- */
-static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-
-       /* Reset register and reserved registers are uncached */
-       if (reg == 0 || reg >= ARRAY_SIZE(wm8990_reg))
-               return;
-
-       cache[reg] = value;
-}
-
-/*
- * write to the wm8990 register space
- */
-static int wm8990_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
-{
-       u8 data[3];
-
-       data[0] = reg & 0xFF;
-       data[1] = (value >> 8) & 0xFF;
-       data[2] = value & 0xFF;
-
-       wm8990_write_reg_cache(codec, reg, value);
-
-       if (codec->hw_write(codec->control_data, data, 3) == 2)
-               return 0;
-       else
-               return -EIO;
-}
-
-#define wm8990_reset(c) wm8990_write(c, WM8990_RESET, 0)
+#define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0)
 
 static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600);
 
@@ -187,8 +141,8 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
                return ret;
 
        /* now hit the volume update bits (always bit 8) */
-       val = wm8990_read_reg_cache(codec, reg);
-       return wm8990_write(codec, reg, val | 0x0100);
+       val = snd_soc_read(codec, reg);
+       return snd_soc_write(codec, reg, val | 0x0100);
 }
 
 #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\
@@ -427,8 +381,8 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
 {
        u16 reg, fakepower;
 
-       reg = wm8990_read_reg_cache(w->codec, WM8990_POWER_MANAGEMENT_2);
-       fakepower = wm8990_read_reg_cache(w->codec, WM8990_INTDRIVBITS);
+       reg = snd_soc_read(w->codec, WM8990_POWER_MANAGEMENT_2);
+       fakepower = snd_soc_read(w->codec, WM8990_INTDRIVBITS);
 
        if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) |
                (1 << WM8990_AINLMUX_PWR_BIT))) {
@@ -443,7 +397,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
        } else {
                reg &= ~WM8990_AINL_ENA;
        }
-       wm8990_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
+       snd_soc_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
 
        return 0;
 }
@@ -457,7 +411,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
 
        switch (reg_shift) {
        case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) :
-               reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER1);
+               reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER1);
                if (reg & WM8990_LDLO) {
                        printk(KERN_WARNING
                        "Cannot set as Output Mixer 1 LDLO Set\n");
@@ -465,7 +419,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
                }
                break;
        case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8):
-               reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER2);
+               reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER2);
                if (reg & WM8990_RDRO) {
                        printk(KERN_WARNING
                        "Cannot set as Output Mixer 2 RDRO Set\n");
@@ -473,7 +427,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
                }
                break;
        case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8):
-               reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER);
+               reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER);
                if (reg & WM8990_LDSPK) {
                        printk(KERN_WARNING
                        "Cannot set as Speaker Mixer LDSPK Set\n");
@@ -481,7 +435,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
                }
                break;
        case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8):
-               reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER);
+               reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER);
                if (reg & WM8990_RDSPK) {
                        printk(KERN_WARNING
                        "Cannot set as Speaker Mixer RDSPK Set\n");
@@ -1029,24 +983,24 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai,
                pll_factors(&pll_div, freq_out * 4, freq_in);
 
                /* Turn on PLL */
-               reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
+               reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
                reg |= WM8990_PLL_ENA;
-               wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
+               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
 
                /* sysclk comes from PLL */
-               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2);
-               wm8990_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
+               reg = snd_soc_read(codec, WM8990_CLOCKING_2);
+               snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
 
                /* set up N , fractional mode and pre-divisor if neccessary */
-               wm8990_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
+               snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
                        (pll_div.div2?WM8990_PRESCALE:0));
-               wm8990_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
-               wm8990_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF));
+               snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
+               snd_soc_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF));
        } else {
                /* Turn on PLL */
-               reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
+               reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
                reg &= ~WM8990_PLL_ENA;
-               wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
+               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
        }
        return 0;
 }
@@ -1073,8 +1027,8 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai,
        struct snd_soc_codec *codec = codec_dai->codec;
        u16 audio1, audio3;
 
-       audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1);
-       audio3 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_3);
+       audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1);
+       audio3 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_3);
 
        /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1115,8 +1069,8 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
-       wm8990_write(codec, WM8990_AUDIO_INTERFACE_3, audio3);
+       snd_soc_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
+       snd_soc_write(codec, WM8990_AUDIO_INTERFACE_3, audio3);
        return 0;
 }
 
@@ -1128,24 +1082,24 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
 
        switch (div_id) {
        case WM8990_MCLK_DIV:
-               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
+               reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
                        ~WM8990_MCLK_DIV_MASK;
-               wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
+               snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
                break;
        case WM8990_DACCLK_DIV:
-               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
+               reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
                        ~WM8990_DAC_CLKDIV_MASK;
-               wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
+               snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
                break;
        case WM8990_ADCCLK_DIV:
-               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) &
+               reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
                        ~WM8990_ADC_CLKDIV_MASK;
-               wm8990_write(codec, WM8990_CLOCKING_2, reg | div);
+               snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
                break;
        case WM8990_BCLK_DIV:
-               reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_1) &
+               reg = snd_soc_read(codec, WM8990_CLOCKING_1) &
                        ~WM8990_BCLK_DIV_MASK;
-               wm8990_write(codec, WM8990_CLOCKING_1, reg | div);
+               snd_soc_write(codec, WM8990_CLOCKING_1, reg | div);
                break;
        default:
                return -EINVAL;
@@ -1164,7 +1118,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_codec *codec = socdev->card->codec;
-       u16 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1);
+       u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1);
 
        audio1 &= ~WM8990_AIF_WL_MASK;
        /* bit size */
@@ -1182,7 +1136,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
                break;
        }
 
-       wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
+       snd_soc_write(codec, WM8990_AUDIO_INTERFACE_1, audio1);
        return 0;
 }
 
@@ -1191,12 +1145,12 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute)
        struct snd_soc_codec *codec = dai->codec;
        u16 val;
 
-       val  = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE;
+       val  = snd_soc_read(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE;
 
        if (mute)
-               wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
+               snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
        else
-               wm8990_write(codec, WM8990_DAC_CTRL, val);
+               snd_soc_write(codec, WM8990_DAC_CTRL, val);
 
        return 0;
 }
@@ -1212,21 +1166,21 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
 
        case SND_SOC_BIAS_PREPARE:
                /* VMID=2*50k */
-               val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) &
+               val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
                        ~WM8990_VMID_MODE_MASK;
-               wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
+               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
                break;
 
        case SND_SOC_BIAS_STANDBY:
                if (codec->bias_level == SND_SOC_BIAS_OFF) {
                        /* Enable all output discharge bits */
-                       wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
+                       snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
                                WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
                                WM8990_DIS_OUT4 | WM8990_DIS_LOUT |
                                WM8990_DIS_ROUT);
 
                        /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */
-                       wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+                       snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
                                     WM8990_BUFDCOPEN | WM8990_POBCTRL |
                                     WM8990_VMIDTOG);
 
@@ -1234,83 +1188,83 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
                        msleep(msecs_to_jiffies(300));
 
                        /* Disable VMIDTOG */
-                       wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+                       snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
                                     WM8990_BUFDCOPEN | WM8990_POBCTRL);
 
                        /* disable all output discharge bits */
-                       wm8990_write(codec, WM8990_ANTIPOP1, 0);
+                       snd_soc_write(codec, WM8990_ANTIPOP1, 0);
 
                        /* Enable outputs */
-                       wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00);
+                       snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00);
 
                        msleep(msecs_to_jiffies(50));
 
                        /* Enable VMID at 2x50k */
-                       wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02);
+                       snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02);
 
                        msleep(msecs_to_jiffies(100));
 
                        /* Enable VREF */
-                       wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
+                       snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
 
                        msleep(msecs_to_jiffies(600));
 
                        /* Enable BUFIOEN */
-                       wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+                       snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
                                     WM8990_BUFDCOPEN | WM8990_POBCTRL |
                                     WM8990_BUFIOEN);
 
                        /* Disable outputs */
-                       wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3);
+                       snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3);
 
                        /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
-                       wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN);
+                       snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN);
 
                        /* Enable workaround for ADC clocking issue. */
-                       wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0x2);
-                       wm8990_write(codec, WM8990_EXT_CTL1, 0xa003);
-                       wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0);
+                       snd_soc_write(codec, WM8990_EXT_ACCESS_ENA, 0x2);
+                       snd_soc_write(codec, WM8990_EXT_CTL1, 0xa003);
+                       snd_soc_write(codec, WM8990_EXT_ACCESS_ENA, 0);
                }
 
                /* VMID=2*250k */
-               val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) &
+               val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
                        ~WM8990_VMID_MODE_MASK;
-               wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
+               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
                break;
 
        case SND_SOC_BIAS_OFF:
                /* Enable POBCTRL and SOFT_ST */
-               wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+               snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
                        WM8990_POBCTRL | WM8990_BUFIOEN);
 
                /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */
-               wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
+               snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST |
                        WM8990_BUFDCOPEN | WM8990_POBCTRL |
                        WM8990_BUFIOEN);
 
                /* mute DAC */
-               val = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL);
-               wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
+               val = snd_soc_read(codec, WM8990_DAC_CTRL);
+               snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
 
                /* Enable any disabled outputs */
-               wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
+               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
 
                /* Disable VMID */
-               wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01);
+               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01);
 
                msleep(msecs_to_jiffies(300));
 
                /* Enable all output discharge bits */
-               wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
+               snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
                        WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
                        WM8990_DIS_OUT4 | WM8990_DIS_LOUT |
                        WM8990_DIS_ROUT);
 
                /* Disable VREF */
-               wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0);
+               snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0);
 
                /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
-               wm8990_write(codec, WM8990_ANTIPOP2, 0x0);
+               snd_soc_write(codec, WM8990_ANTIPOP2, 0x0);
                break;
        }
 
@@ -1411,8 +1365,6 @@ static int wm8990_init(struct snd_soc_device *socdev)
 
        codec->name = "WM8990";
        codec->owner = THIS_MODULE;
-       codec->read = wm8990_read_reg_cache;
-       codec->write = wm8990_write;
        codec->set_bias_level = wm8990_set_bias_level;
        codec->dai = &wm8990_dai;
        codec->num_dai = 2;
@@ -1422,6 +1374,12 @@ static int wm8990_init(struct snd_soc_device *socdev)
        if (codec->reg_cache == NULL)
                return -ENOMEM;
 
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+       if (ret < 0) {
+               printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret);
+               goto pcm_err;
+       }
+
        wm8990_reset(codec);
 
        /* register pcms */
@@ -1435,18 +1393,18 @@ static int wm8990_init(struct snd_soc_device *socdev)
        codec->bias_level = SND_SOC_BIAS_OFF;
        wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
-       reg = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_4);
-       wm8990_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1);
+       reg = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_4);
+       snd_soc_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1);
 
-       reg = wm8990_read_reg_cache(codec, WM8990_GPIO1_GPIO2) &
+       reg = snd_soc_read(codec, WM8990_GPIO1_GPIO2) &
                ~WM8990_GPIO1_SEL_MASK;
-       wm8990_write(codec, WM8990_GPIO1_GPIO2, reg | 1);
+       snd_soc_write(codec, WM8990_GPIO1_GPIO2, reg | 1);
 
-       reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2);
-       wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA);
+       reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
+       snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA);
 
-       wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
-       wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
+       snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
+       snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
 
        snd_soc_add_controls(codec, wm8990_snd_controls,
                                ARRAY_SIZE(wm8990_snd_controls));
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
new file mode 100644 (file)
index 0000000..d998799
--- /dev/null
@@ -0,0 +1,1675 @@
+/*
+ * wm8993.c -- WM8993 ALSA SoC audio driver
+ *
+ * Copyright 2009 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/wm8993.h>
+
+#include "wm8993.h"
+#include "wm_hubs.h"
+
+static u16 wm8993_reg_defaults[WM8993_REGISTER_COUNT] = {
+       0x8993,     /* R0   - Software Reset */
+       0x0000,     /* R1   - Power Management (1) */
+       0x6000,     /* R2   - Power Management (2) */
+       0x0000,     /* R3   - Power Management (3) */
+       0x4050,     /* R4   - Audio Interface (1) */
+       0x4000,     /* R5   - Audio Interface (2) */
+       0x01C8,     /* R6   - Clocking 1 */
+       0x0000,     /* R7   - Clocking 2 */
+       0x0000,     /* R8   - Audio Interface (3) */
+       0x0040,     /* R9   - Audio Interface (4) */
+       0x0004,     /* R10  - DAC CTRL */
+       0x00C0,     /* R11  - Left DAC Digital Volume */
+       0x00C0,     /* R12  - Right DAC Digital Volume */
+       0x0000,     /* R13  - Digital Side Tone */
+       0x0300,     /* R14  - ADC CTRL */
+       0x00C0,     /* R15  - Left ADC Digital Volume */
+       0x00C0,     /* R16  - Right ADC Digital Volume */
+       0x0000,     /* R17 */
+       0x0000,     /* R18  - GPIO CTRL 1 */
+       0x0010,     /* R19  - GPIO1 */
+       0x0000,     /* R20  - IRQ_DEBOUNCE */
+       0x0000,     /* R21 */
+       0x8000,     /* R22  - GPIOCTRL 2 */
+       0x0800,     /* R23  - GPIO_POL */
+       0x008B,     /* R24  - Left Line Input 1&2 Volume */
+       0x008B,     /* R25  - Left Line Input 3&4 Volume */
+       0x008B,     /* R26  - Right Line Input 1&2 Volume */
+       0x008B,     /* R27  - Right Line Input 3&4 Volume */
+       0x006D,     /* R28  - Left Output Volume */
+       0x006D,     /* R29  - Right Output Volume */
+       0x0066,     /* R30  - Line Outputs Volume */
+       0x0020,     /* R31  - HPOUT2 Volume */
+       0x0079,     /* R32  - Left OPGA Volume */
+       0x0079,     /* R33  - Right OPGA Volume */
+       0x0003,     /* R34  - SPKMIXL Attenuation */
+       0x0003,     /* R35  - SPKMIXR Attenuation */
+       0x0011,     /* R36  - SPKOUT Mixers */
+       0x0100,     /* R37  - SPKOUT Boost */
+       0x0079,     /* R38  - Speaker Volume Left */
+       0x0079,     /* R39  - Speaker Volume Right */
+       0x0000,     /* R40  - Input Mixer2 */
+       0x0000,     /* R41  - Input Mixer3 */
+       0x0000,     /* R42  - Input Mixer4 */
+       0x0000,     /* R43  - Input Mixer5 */
+       0x0000,     /* R44  - Input Mixer6 */
+       0x0000,     /* R45  - Output Mixer1 */
+       0x0000,     /* R46  - Output Mixer2 */
+       0x0000,     /* R47  - Output Mixer3 */
+       0x0000,     /* R48  - Output Mixer4 */
+       0x0000,     /* R49  - Output Mixer5 */
+       0x0000,     /* R50  - Output Mixer6 */
+       0x0000,     /* R51  - HPOUT2 Mixer */
+       0x0000,     /* R52  - Line Mixer1 */
+       0x0000,     /* R53  - Line Mixer2 */
+       0x0000,     /* R54  - Speaker Mixer */
+       0x0000,     /* R55  - Additional Control */
+       0x0000,     /* R56  - AntiPOP1 */
+       0x0000,     /* R57  - AntiPOP2 */
+       0x0000,     /* R58  - MICBIAS */
+       0x0000,     /* R59 */
+       0x0000,     /* R60  - FLL Control 1 */
+       0x0000,     /* R61  - FLL Control 2 */
+       0x0000,     /* R62  - FLL Control 3 */
+       0x2EE0,     /* R63  - FLL Control 4 */
+       0x0002,     /* R64  - FLL Control 5 */
+       0x2287,     /* R65  - Clocking 3 */
+       0x025F,     /* R66  - Clocking 4 */
+       0x0000,     /* R67  - MW Slave Control */
+       0x0000,     /* R68 */
+       0x0002,     /* R69  - Bus Control 1 */
+       0x0000,     /* R70  - Write Sequencer 0 */
+       0x0000,     /* R71  - Write Sequencer 1 */
+       0x0000,     /* R72  - Write Sequencer 2 */
+       0x0000,     /* R73  - Write Sequencer 3 */
+       0x0000,     /* R74  - Write Sequencer 4 */
+       0x0000,     /* R75  - Write Sequencer 5 */
+       0x1F25,     /* R76  - Charge Pump 1 */
+       0x0000,     /* R77 */
+       0x0000,     /* R78 */
+       0x0000,     /* R79 */
+       0x0000,     /* R80 */
+       0x0000,     /* R81  - Class W 0 */
+       0x0000,     /* R82 */
+       0x0000,     /* R83 */
+       0x0000,     /* R84  - DC Servo 0 */
+       0x054A,     /* R85  - DC Servo 1 */
+       0x0000,     /* R86 */
+       0x0000,     /* R87  - DC Servo 3 */
+       0x0000,     /* R88  - DC Servo Readback 0 */
+       0x0000,     /* R89  - DC Servo Readback 1 */
+       0x0000,     /* R90  - DC Servo Readback 2 */
+       0x0000,     /* R91 */
+       0x0000,     /* R92 */
+       0x0000,     /* R93 */
+       0x0000,     /* R94 */
+       0x0000,     /* R95 */
+       0x0100,     /* R96  - Analogue HP 0 */
+       0x0000,     /* R97 */
+       0x0000,     /* R98  - EQ1 */
+       0x000C,     /* R99  - EQ2 */
+       0x000C,     /* R100 - EQ3 */
+       0x000C,     /* R101 - EQ4 */
+       0x000C,     /* R102 - EQ5 */
+       0x000C,     /* R103 - EQ6 */
+       0x0FCA,     /* R104 - EQ7 */
+       0x0400,     /* R105 - EQ8 */
+       0x00D8,     /* R106 - EQ9 */
+       0x1EB5,     /* R107 - EQ10 */
+       0xF145,     /* R108 - EQ11 */
+       0x0B75,     /* R109 - EQ12 */
+       0x01C5,     /* R110 - EQ13 */
+       0x1C58,     /* R111 - EQ14 */
+       0xF373,     /* R112 - EQ15 */
+       0x0A54,     /* R113 - EQ16 */
+       0x0558,     /* R114 - EQ17 */
+       0x168E,     /* R115 - EQ18 */
+       0xF829,     /* R116 - EQ19 */
+       0x07AD,     /* R117 - EQ20 */
+       0x1103,     /* R118 - EQ21 */
+       0x0564,     /* R119 - EQ22 */
+       0x0559,     /* R120 - EQ23 */
+       0x4000,     /* R121 - EQ24 */
+       0x0000,     /* R122 - Digital Pulls */
+       0x0F08,     /* R123 - DRC Control 1 */
+       0x0000,     /* R124 - DRC Control 2 */
+       0x0080,     /* R125 - DRC Control 3 */
+       0x0000,     /* R126 - DRC Control 4 */
+};
+
+static struct {
+       int ratio;
+       int clk_sys_rate;
+} clk_sys_rates[] = {
+       { 64,   0 },
+       { 128,  1 },
+       { 192,  2 },
+       { 256,  3 },
+       { 384,  4 },
+       { 512,  5 },
+       { 768,  6 },
+       { 1024, 7 },
+       { 1408, 8 },
+       { 1536, 9 },
+};
+
+static struct {
+       int rate;
+       int sample_rate;
+} sample_rates[] = {
+       { 8000,  0  },
+       { 11025, 1  },
+       { 12000, 1  },
+       { 16000, 2  },
+       { 22050, 3  },
+       { 24000, 3  },
+       { 32000, 4  },
+       { 44100, 5  },
+       { 48000, 5  },
+};
+
+static struct {
+       int div; /* *10 due to .5s */
+       int bclk_div;
+} bclk_divs[] = {
+       { 10,  0  },
+       { 15,  1  },
+       { 20,  2  },
+       { 30,  3  },
+       { 40,  4  },
+       { 55,  5  },
+       { 60,  6  },
+       { 80,  7  },
+       { 110, 8  },
+       { 120, 9  },
+       { 160, 10 },
+       { 220, 11 },
+       { 240, 12 },
+       { 320, 13 },
+       { 440, 14 },
+       { 480, 15 },
+};
+
+struct wm8993_priv {
+       u16 reg_cache[WM8993_REGISTER_COUNT];
+       struct wm8993_platform_data pdata;
+       struct snd_soc_codec codec;
+       int master;
+       int sysclk_source;
+       int tdm_slots;
+       int tdm_width;
+       unsigned int mclk_rate;
+       unsigned int sysclk_rate;
+       unsigned int fs;
+       unsigned int bclk;
+       int class_w_users;
+       unsigned int fll_fref;
+       unsigned int fll_fout;
+};
+
+static unsigned int wm8993_read_hw(struct snd_soc_codec *codec, u8 reg)
+{
+       struct i2c_msg xfer[2];
+       u16 data;
+       int ret;
+       struct i2c_client *i2c = codec->control_data;
+
+       /* Write register */
+       xfer[0].addr = i2c->addr;
+       xfer[0].flags = 0;
+       xfer[0].len = 1;
+       xfer[0].buf = &reg;
+
+       /* Read data */
+       xfer[1].addr = i2c->addr;
+       xfer[1].flags = I2C_M_RD;
+       xfer[1].len = 2;
+       xfer[1].buf = (u8 *)&data;
+
+       ret = i2c_transfer(i2c->adapter, xfer, 2);
+       if (ret != 2) {
+               dev_err(codec->dev, "Failed to read 0x%x: %d\n", reg, ret);
+               return 0;
+       }
+
+       return (data >> 8) | ((data & 0xff) << 8);
+}
+
+static int wm8993_volatile(unsigned int reg)
+{
+       switch (reg) {
+       case WM8993_SOFTWARE_RESET:
+       case WM8993_DC_SERVO_0:
+       case WM8993_DC_SERVO_READBACK_0:
+       case WM8993_DC_SERVO_READBACK_1:
+       case WM8993_DC_SERVO_READBACK_2:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static unsigned int wm8993_read(struct snd_soc_codec *codec,
+                               unsigned int reg)
+{
+       u16 *reg_cache = codec->reg_cache;
+
+       BUG_ON(reg > WM8993_MAX_REGISTER);
+
+       if (wm8993_volatile(reg))
+               return wm8993_read_hw(codec, reg);
+       else
+               return reg_cache[reg];
+}
+
+static int wm8993_write(struct snd_soc_codec *codec, unsigned int reg,
+                       unsigned int value)
+{
+       u16 *reg_cache = codec->reg_cache;
+       u8 data[3];
+       int ret;
+
+       BUG_ON(reg > WM8993_MAX_REGISTER);
+
+       /* data is
+        *   D15..D9 WM8993 register offset
+        *   D8...D0 register data
+        */
+       data[0] = reg;
+       data[1] = value >> 8;
+       data[2] = value & 0x00ff;
+
+       if (!wm8993_volatile(reg))
+               reg_cache[reg] = value;
+
+       ret = codec->hw_write(codec->control_data, data, 3);
+
+       if (ret == 3)
+               return 0;
+       if (ret < 0)
+               return ret;
+       return -EIO;
+}
+
+struct _fll_div {
+       u16 fll_fratio;
+       u16 fll_outdiv;
+       u16 fll_clk_ref_div;
+       u16 n;
+       u16 k;
+};
+
+/* The size in bits of the FLL divide multiplied by 10
+ * to allow rounding later */
+#define FIXED_FLL_SIZE ((1 << 16) * 10)
+
+static struct {
+       unsigned int min;
+       unsigned int max;
+       u16 fll_fratio;
+       int ratio;
+} fll_fratios[] = {
+       {       0,    64000, 4, 16 },
+       {   64000,   128000, 3,  8 },
+       {  128000,   256000, 2,  4 },
+       {  256000,  1000000, 1,  2 },
+       { 1000000, 13500000, 0,  1 },
+};
+
+static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
+                      unsigned int Fout)
+{
+       u64 Kpart;
+       unsigned int K, Ndiv, Nmod, target;
+       unsigned int div;
+       int i;
+
+       /* Fref must be <=13.5MHz */
+       div = 1;
+       fll_div->fll_clk_ref_div = 0;
+       while ((Fref / div) > 13500000) {
+               div *= 2;
+               fll_div->fll_clk_ref_div++;
+
+               if (div > 8) {
+                       pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
+                              Fref);
+                       return -EINVAL;
+               }
+       }
+
+       pr_debug("Fref=%u Fout=%u\n", Fref, Fout);
+
+       /* Apply the division for our remaining calculations */
+       Fref /= div;
+
+       /* Fvco should be 90-100MHz; don't check the upper bound */
+       div = 0;
+       target = Fout * 2;
+       while (target < 90000000) {
+               div++;
+               target *= 2;
+               if (div > 7) {
+                       pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
+                              Fout);
+                       return -EINVAL;
+               }
+       }
+       fll_div->fll_outdiv = div;
+
+       pr_debug("Fvco=%dHz\n", target);
+
+       /* Find an appropraite FLL_FRATIO and factor it out of the target */
+       for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
+               if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
+                       fll_div->fll_fratio = fll_fratios[i].fll_fratio;
+                       target /= fll_fratios[i].ratio;
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(fll_fratios)) {
+               pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
+               return -EINVAL;
+       }
+
+       /* Now, calculate N.K */
+       Ndiv = target / Fref;
+
+       fll_div->n = Ndiv;
+       Nmod = target % Fref;
+       pr_debug("Nmod=%d\n", Nmod);
+
+       /* Calculate fractional part - scale up so we can round. */
+       Kpart = FIXED_FLL_SIZE * (long long)Nmod;
+
+       do_div(Kpart, Fref);
+
+       K = Kpart & 0xFFFFFFFF;
+
+       if ((K % 10) >= 5)
+               K += 5;
+
+       /* Move down to proper range now rounding is done */
+       fll_div->k = K / 10;
+
+       pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n",
+                fll_div->n, fll_div->k,
+                fll_div->fll_fratio, fll_div->fll_outdiv,
+                fll_div->fll_clk_ref_div);
+
+       return 0;
+}
+
+static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id,
+                         unsigned int Fref, unsigned int Fout)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8993_priv *wm8993 = codec->private_data;
+       u16 reg1, reg4, reg5;
+       struct _fll_div fll_div;
+       int ret;
+
+       /* Any change? */
+       if (Fref == wm8993->fll_fref && Fout == wm8993->fll_fout)
+               return 0;
+
+       /* Disable the FLL */
+       if (Fout == 0) {
+               dev_dbg(codec->dev, "FLL disabled\n");
+               wm8993->fll_fref = 0;
+               wm8993->fll_fout = 0;
+
+               reg1 = wm8993_read(codec, WM8993_FLL_CONTROL_1);
+               reg1 &= ~WM8993_FLL_ENA;
+               wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1);
+
+               return 0;
+       }
+
+       ret = fll_factors(&fll_div, Fref, Fout);
+       if (ret != 0)
+               return ret;
+
+       reg5 = wm8993_read(codec, WM8993_FLL_CONTROL_5);
+       reg5 &= ~WM8993_FLL_CLK_SRC_MASK;
+
+       switch (fll_id) {
+       case WM8993_FLL_MCLK:
+               break;
+
+       case WM8993_FLL_LRCLK:
+               reg5 |= 1;
+               break;
+
+       case WM8993_FLL_BCLK:
+               reg5 |= 2;
+               break;
+
+       default:
+               dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id);
+               return -EINVAL;
+       }
+
+       /* Any FLL configuration change requires that the FLL be
+        * disabled first. */
+       reg1 = wm8993_read(codec, WM8993_FLL_CONTROL_1);
+       reg1 &= ~WM8993_FLL_ENA;
+       wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1);
+
+       /* Apply the configuration */
+       if (fll_div.k)
+               reg1 |= WM8993_FLL_FRAC_MASK;
+       else
+               reg1 &= ~WM8993_FLL_FRAC_MASK;
+       wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1);
+
+       wm8993_write(codec, WM8993_FLL_CONTROL_2,
+                    (fll_div.fll_outdiv << WM8993_FLL_OUTDIV_SHIFT) |
+                    (fll_div.fll_fratio << WM8993_FLL_FRATIO_SHIFT));
+       wm8993_write(codec, WM8993_FLL_CONTROL_3, fll_div.k);
+
+       reg4 = wm8993_read(codec, WM8993_FLL_CONTROL_4);
+       reg4 &= ~WM8993_FLL_N_MASK;
+       reg4 |= fll_div.n << WM8993_FLL_N_SHIFT;
+       wm8993_write(codec, WM8993_FLL_CONTROL_4, reg4);
+
+       reg5 &= ~WM8993_FLL_CLK_REF_DIV_MASK;
+       reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT;
+       wm8993_write(codec, WM8993_FLL_CONTROL_5, reg5);
+
+       /* Enable the FLL */
+       wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA);
+
+       dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
+
+       wm8993->fll_fref = Fref;
+       wm8993->fll_fout = Fout;
+
+       return 0;
+}
+
+static int configure_clock(struct snd_soc_codec *codec)
+{
+       struct wm8993_priv *wm8993 = codec->private_data;
+       unsigned int reg;
+
+       /* This should be done on init() for bypass paths */
+       switch (wm8993->sysclk_source) {
+       case WM8993_SYSCLK_MCLK:
+               dev_dbg(codec->dev, "Using %dHz MCLK\n", wm8993->mclk_rate);
+
+               reg = wm8993_read(codec, WM8993_CLOCKING_2);
+               reg &= ~(WM8993_MCLK_DIV | WM8993_SYSCLK_SRC);
+               if (wm8993->mclk_rate > 13500000) {
+                       reg |= WM8993_MCLK_DIV;
+                       wm8993->sysclk_rate = wm8993->mclk_rate / 2;
+               } else {
+                       reg &= ~WM8993_MCLK_DIV;
+                       wm8993->sysclk_rate = wm8993->mclk_rate;
+               }
+               wm8993_write(codec, WM8993_CLOCKING_2, reg);
+               break;
+
+       case WM8993_SYSCLK_FLL:
+               dev_dbg(codec->dev, "Using %dHz FLL clock\n",
+                       wm8993->fll_fout);
+
+               reg = wm8993_read(codec, WM8993_CLOCKING_2);
+               reg |= WM8993_SYSCLK_SRC;
+               if (wm8993->fll_fout > 13500000) {
+                       reg |= WM8993_MCLK_DIV;
+                       wm8993->sysclk_rate = wm8993->fll_fout / 2;
+               } else {
+                       reg &= ~WM8993_MCLK_DIV;
+                       wm8993->sysclk_rate = wm8993->fll_fout;
+               }
+               wm8993_write(codec, WM8993_CLOCKING_2, reg);
+               break;
+
+       default:
+               dev_err(codec->dev, "System clock not configured\n");
+               return -EINVAL;
+       }
+
+       dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm8993->sysclk_rate);
+
+       return 0;
+}
+
+static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0);
+static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0);
+static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0);
+static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0);
+static const unsigned int drc_max_tlv[] = {
+       TLV_DB_RANGE_HEAD(4),
+       0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0),
+       3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0),
+};
+static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0);
+static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -1800, 300, 0);
+static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
+static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0);
+
+static const char *dac_deemph_text[] = {
+       "None",
+       "32kHz",
+       "44.1kHz",
+       "48kHz",
+};
+
+static const struct soc_enum dac_deemph =
+       SOC_ENUM_SINGLE(WM8993_DAC_CTRL, 4, 4, dac_deemph_text);
+
+static const char *adc_hpf_text[] = {
+       "Hi-Fi",
+       "Voice 1",
+       "Voice 2",
+       "Voice 3",
+};
+
+static const struct soc_enum adc_hpf =
+       SOC_ENUM_SINGLE(WM8993_ADC_CTRL, 5, 4, adc_hpf_text);
+
+static const char *drc_path_text[] = {
+       "ADC",
+       "DAC"
+};
+
+static const struct soc_enum drc_path =
+       SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 14, 2, drc_path_text);
+
+static const char *drc_r0_text[] = {
+       "1",
+       "1/2",
+       "1/4",
+       "1/8",
+       "1/16",
+       "0",
+};
+
+static const struct soc_enum drc_r0 =
+       SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 8, 6, drc_r0_text);
+
+static const char *drc_r1_text[] = {
+       "1",
+       "1/2",
+       "1/4",
+       "1/8",
+       "0",
+};
+
+static const struct soc_enum drc_r1 =
+       SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_4, 13, 5, drc_r1_text);
+
+static const char *drc_attack_text[] = {
+       "Reserved",
+       "181us",
+       "363us",
+       "726us",
+       "1.45ms",
+       "2.9ms",
+       "5.8ms",
+       "11.6ms",
+       "23.2ms",
+       "46.4ms",
+       "92.8ms",
+       "185.6ms",
+};
+
+static const struct soc_enum drc_attack =
+       SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 12, 12, drc_attack_text);
+
+static const char *drc_decay_text[] = {
+       "186ms",
+       "372ms",
+       "743ms",
+       "1.49s",
+       "2.97ms",
+       "5.94ms",
+       "11.89ms",
+       "23.78ms",
+       "47.56ms",
+};
+
+static const struct soc_enum drc_decay =
+       SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 8, 9, drc_decay_text);
+
+static const char *drc_ff_text[] = {
+       "5 samples",
+       "9 samples",
+};
+
+static const struct soc_enum drc_ff =
+       SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 7, 2, drc_ff_text);
+
+static const char *drc_qr_rate_text[] = {
+       "0.725ms",
+       "1.45ms",
+       "5.8ms",
+};
+
+static const struct soc_enum drc_qr_rate =
+       SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 0, 3, drc_qr_rate_text);
+
+static const char *drc_smooth_text[] = {
+       "Low",
+       "Medium",
+       "High",
+};
+
+static const struct soc_enum drc_smooth =
+       SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 4, 3, drc_smooth_text);
+
+static const struct snd_kcontrol_new wm8993_snd_controls[] = {
+SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE,
+              5, 9, 12, 0, sidetone_tlv),
+
+SOC_SINGLE("DRC Switch", WM8993_DRC_CONTROL_1, 15, 1, 0),
+SOC_ENUM("DRC Path", drc_path),
+SOC_SINGLE_TLV("DRC Compressor Threashold Volume", WM8993_DRC_CONTROL_2,
+              2, 60, 1, drc_comp_threash),
+SOC_SINGLE_TLV("DRC Compressor Amplitude Volume", WM8993_DRC_CONTROL_3,
+              11, 30, 1, drc_comp_amp),
+SOC_ENUM("DRC R0", drc_r0),
+SOC_ENUM("DRC R1", drc_r1),
+SOC_SINGLE_TLV("DRC Minimum Volume", WM8993_DRC_CONTROL_1, 2, 3, 1,
+              drc_min_tlv),
+SOC_SINGLE_TLV("DRC Maximum Volume", WM8993_DRC_CONTROL_1, 0, 3, 0,
+              drc_max_tlv),
+SOC_ENUM("DRC Attack Rate", drc_attack),
+SOC_ENUM("DRC Decay Rate", drc_decay),
+SOC_ENUM("DRC FF Delay", drc_ff),
+SOC_SINGLE("DRC Anti-clip Switch", WM8993_DRC_CONTROL_1, 9, 1, 0),
+SOC_SINGLE("DRC Quick Release Switch", WM8993_DRC_CONTROL_1, 10, 1, 0),
+SOC_SINGLE_TLV("DRC Quick Release Volume", WM8993_DRC_CONTROL_3, 2, 3, 0,
+              drc_qr_tlv),
+SOC_ENUM("DRC Quick Release Rate", drc_qr_rate),
+SOC_SINGLE("DRC Smoothing Switch", WM8993_DRC_CONTROL_1, 11, 1, 0),
+SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8993_DRC_CONTROL_1, 8, 1, 0),
+SOC_ENUM("DRC Smoothing Hysteresis Threashold", drc_smooth),
+SOC_SINGLE_TLV("DRC Startup Volume", WM8993_DRC_CONTROL_4, 8, 18, 0,
+              drc_startup_tlv),
+
+SOC_SINGLE("EQ Switch", WM8993_EQ1, 0, 1, 0),
+
+SOC_DOUBLE_R_TLV("Capture Volume", WM8993_LEFT_ADC_DIGITAL_VOLUME,
+                WM8993_RIGHT_ADC_DIGITAL_VOLUME, 1, 96, 0, digital_tlv),
+SOC_SINGLE("ADC High Pass Filter Switch", WM8993_ADC_CTRL, 8, 1, 0),
+SOC_ENUM("ADC High Pass Filter Mode", adc_hpf),
+
+SOC_DOUBLE_R_TLV("Playback Volume", WM8993_LEFT_DAC_DIGITAL_VOLUME,
+                WM8993_RIGHT_DAC_DIGITAL_VOLUME, 1, 96, 0, digital_tlv),
+SOC_SINGLE_TLV("Playback Boost Volume", WM8993_AUDIO_INTERFACE_2, 10, 3, 0,
+              dac_boost_tlv),
+SOC_ENUM("DAC Deemphasis", dac_deemph),
+
+SOC_SINGLE_TLV("SPKL DAC Volume", WM8993_SPKMIXL_ATTENUATION,
+              2, 1, 1, wm_hubs_spkmix_tlv),
+
+SOC_SINGLE_TLV("SPKR DAC Volume", WM8993_SPKMIXR_ATTENUATION,
+              2, 1, 1, wm_hubs_spkmix_tlv),
+};
+
+static const struct snd_kcontrol_new wm8993_eq_controls[] = {
+SOC_SINGLE_TLV("EQ1 Volume", WM8993_EQ2, 0, 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Volume", WM8993_EQ3, 0, 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Volume", WM8993_EQ4, 0, 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Volume", WM8993_EQ5, 0, 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ5 Volume", WM8993_EQ6, 0, 24, 0, eq_tlv),
+};
+
+static int clk_sys_event(struct snd_soc_dapm_widget *w,
+                        struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               return configure_clock(codec);
+
+       case SND_SOC_DAPM_POST_PMD:
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * When used with DAC outputs only the WM8993 charge pump supports
+ * operation in class W mode, providing very low power consumption
+ * when used with digital sources.  Enable and disable this mode
+ * automatically depending on the mixer configuration.
+ *
+ * Currently the only supported paths are the direct DAC->headphone
+ * paths (which provide minimum power consumption anyway).
+ */
+static int class_w_put(struct snd_kcontrol *kcontrol,
+                      struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
+       struct snd_soc_codec *codec = widget->codec;
+       struct wm8993_priv *wm8993 = codec->private_data;
+       int ret;
+
+       /* Turn it off if we're using the main output mixer */
+       if (ucontrol->value.integer.value[0] == 0) {
+               if (wm8993->class_w_users == 0) {
+                       dev_dbg(codec->dev, "Disabling Class W\n");
+                       snd_soc_update_bits(codec, WM8993_CLASS_W_0,
+                                           WM8993_CP_DYN_FREQ |
+                                           WM8993_CP_DYN_V,
+                                           0);
+               }
+               wm8993->class_w_users++;
+       }
+
+       /* Implement the change */
+       ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+       /* Enable it if we're using the direct DAC path */
+       if (ucontrol->value.integer.value[0] == 1) {
+               if (wm8993->class_w_users == 1) {
+                       dev_dbg(codec->dev, "Enabling Class W\n");
+                       snd_soc_update_bits(codec, WM8993_CLASS_W_0,
+                                           WM8993_CP_DYN_FREQ |
+                                           WM8993_CP_DYN_V,
+                                           WM8993_CP_DYN_FREQ |
+                                           WM8993_CP_DYN_V);
+               }
+               wm8993->class_w_users--;
+       }
+
+       dev_dbg(codec->dev, "Indirect DAC use count now %d\n",
+               wm8993->class_w_users);
+
+       return ret;
+}
+
+#define SOC_DAPM_ENUM_W(xname, xenum) \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+       .info = snd_soc_info_enum_double, \
+       .get = snd_soc_dapm_get_enum_double, \
+       .put = class_w_put, \
+       .private_value = (unsigned long)&xenum }
+
+static const char *hp_mux_text[] = {
+       "Mixer",
+       "DAC",
+};
+
+static const struct soc_enum hpl_enum =
+       SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text);
+
+static const struct snd_kcontrol_new hpl_mux =
+       SOC_DAPM_ENUM_W("Left Headphone Mux", hpl_enum);
+
+static const struct soc_enum hpr_enum =
+       SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text);
+
+static const struct snd_kcontrol_new hpr_mux =
+       SOC_DAPM_ENUM_W("Right Headphone Mux", hpr_enum);
+
+static const struct snd_kcontrol_new left_speaker_mixer[] = {
+SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 7, 1, 0),
+SOC_DAPM_SINGLE("IN1LP Switch", WM8993_SPEAKER_MIXER, 5, 1, 0),
+SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 3, 1, 0),
+SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_speaker_mixer[] = {
+SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 6, 1, 0),
+SOC_DAPM_SINGLE("IN1RP Switch", WM8993_SPEAKER_MIXER, 4, 1, 0),
+SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 2, 1, 0),
+SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 0, 1, 0),
+};
+
+static const char *aif_text[] = {
+       "Left", "Right"
+};
+
+static const struct soc_enum aifoutl_enum =
+       SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 15, 2, aif_text);
+
+static const struct snd_kcontrol_new aifoutl_mux =
+       SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum);
+
+static const struct soc_enum aifoutr_enum =
+       SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 14, 2, aif_text);
+
+static const struct snd_kcontrol_new aifoutr_mux =
+       SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum);
+
+static const struct soc_enum aifinl_enum =
+       SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 15, 2, aif_text);
+
+static const struct snd_kcontrol_new aifinl_mux =
+       SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum);
+
+static const struct soc_enum aifinr_enum =
+       SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 14, 2, aif_text);
+
+static const struct snd_kcontrol_new aifinr_mux =
+       SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum);
+
+static const char *sidetone_text[] = {
+       "None", "Left", "Right"
+};
+
+static const struct soc_enum sidetonel_enum =
+       SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 2, 3, sidetone_text);
+
+static const struct snd_kcontrol_new sidetonel_mux =
+       SOC_DAPM_ENUM("Left Sidetone", sidetonel_enum);
+
+static const struct soc_enum sidetoner_enum =
+       SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 0, 3, sidetone_text);
+
+static const struct snd_kcontrol_new sidetoner_mux =
+       SOC_DAPM_ENUM("Right Sidetone", sidetoner_enum);
+
+static const struct snd_soc_dapm_widget wm8993_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event,
+                   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0),
+
+SND_SOC_DAPM_ADC("ADCL", NULL, WM8993_POWER_MANAGEMENT_2, 1, 0),
+SND_SOC_DAPM_ADC("ADCR", NULL, WM8993_POWER_MANAGEMENT_2, 0, 0),
+
+SND_SOC_DAPM_MUX("AIFOUTL Mux", SND_SOC_NOPM, 0, 0, &aifoutl_mux),
+SND_SOC_DAPM_MUX("AIFOUTR Mux", SND_SOC_NOPM, 0, 0, &aifoutr_mux),
+
+SND_SOC_DAPM_AIF_OUT("AIFOUTL", "Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIFOUTR", "Capture", 1, SND_SOC_NOPM, 0, 0),
+
+SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0),
+
+SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &aifinl_mux),
+SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &aifinr_mux),
+
+SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &sidetonel_mux),
+SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &sidetoner_mux),
+
+SND_SOC_DAPM_DAC("DACL", NULL, WM8993_POWER_MANAGEMENT_3, 1, 0),
+SND_SOC_DAPM_DAC("DACR", NULL, WM8993_POWER_MANAGEMENT_3, 0, 0),
+
+SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux),
+SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux),
+
+SND_SOC_DAPM_MIXER("SPKL", WM8993_POWER_MANAGEMENT_3, 8, 0,
+                  left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
+SND_SOC_DAPM_MIXER("SPKR", WM8993_POWER_MANAGEMENT_3, 9, 0,
+                  right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
+
+};
+
+static const struct snd_soc_dapm_route routes[] = {
+       { "ADCL", NULL, "CLK_SYS" },
+       { "ADCL", NULL, "CLK_DSP" },
+       { "ADCR", NULL, "CLK_SYS" },
+       { "ADCR", NULL, "CLK_DSP" },
+
+       { "AIFOUTL Mux", "Left", "ADCL" },
+       { "AIFOUTL Mux", "Right", "ADCR" },
+       { "AIFOUTR Mux", "Left", "ADCL" },
+       { "AIFOUTR Mux", "Right", "ADCR" },
+
+       { "AIFOUTL", NULL, "AIFOUTL Mux" },
+       { "AIFOUTR", NULL, "AIFOUTR Mux" },
+
+       { "DACL Mux", "Left", "AIFINL" },
+       { "DACL Mux", "Right", "AIFINR" },
+       { "DACR Mux", "Left", "AIFINL" },
+       { "DACR Mux", "Right", "AIFINR" },
+
+       { "DACL Sidetone", "Left", "ADCL" },
+       { "DACL Sidetone", "Right", "ADCR" },
+       { "DACR Sidetone", "Left", "ADCL" },
+       { "DACR Sidetone", "Right", "ADCR" },
+
+       { "DACL", NULL, "CLK_SYS" },
+       { "DACL", NULL, "CLK_DSP" },
+       { "DACL", NULL, "DACL Mux" },
+       { "DACL", NULL, "DACL Sidetone" },
+       { "DACR", NULL, "CLK_SYS" },
+       { "DACR", NULL, "CLK_DSP" },
+       { "DACR", NULL, "DACR Mux" },
+       { "DACR", NULL, "DACR Sidetone" },
+
+       { "Left Output Mixer", "DAC Switch", "DACL" },
+
+       { "Right Output Mixer", "DAC Switch", "DACR" },
+
+       { "Left Output PGA", NULL, "CLK_SYS" },
+
+       { "Right Output PGA", NULL, "CLK_SYS" },
+
+       { "SPKL", "DAC Switch", "DACL" },
+       { "SPKL", NULL, "CLK_SYS" },
+
+       { "SPKR", "DAC Switch", "DACR" },
+       { "SPKR", NULL, "CLK_SYS" },
+
+       { "Left Headphone Mux", "DAC", "DACL" },
+       { "Right Headphone Mux", "DAC", "DACR" },
+};
+
+static int wm8993_set_bias_level(struct snd_soc_codec *codec,
+                                enum snd_soc_bias_level level)
+{
+       struct wm8993_priv *wm8993 = codec->private_data;
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+       case SND_SOC_BIAS_PREPARE:
+               /* VMID=2*40k */
+               snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
+                                   WM8993_VMID_SEL_MASK, 0x2);
+               snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_2,
+                                   WM8993_TSHUT_ENA, WM8993_TSHUT_ENA);
+               break;
+
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->bias_level == SND_SOC_BIAS_OFF) {
+                       /* Bring up VMID with fast soft start */
+                       snd_soc_update_bits(codec, WM8993_ANTIPOP2,
+                                           WM8993_STARTUP_BIAS_ENA |
+                                           WM8993_VMID_BUF_ENA |
+                                           WM8993_VMID_RAMP_MASK |
+                                           WM8993_BIAS_SRC,
+                                           WM8993_STARTUP_BIAS_ENA |
+                                           WM8993_VMID_BUF_ENA |
+                                           WM8993_VMID_RAMP_MASK |
+                                           WM8993_BIAS_SRC);
+
+                       /* If either line output is single ended we
+                        * need the VMID buffer */
+                       if (!wm8993->pdata.lineout1_diff ||
+                           !wm8993->pdata.lineout2_diff)
+                               snd_soc_update_bits(codec, WM8993_ANTIPOP1,
+                                                WM8993_LINEOUT_VMID_BUF_ENA,
+                                                WM8993_LINEOUT_VMID_BUF_ENA);
+
+                       /* VMID=2*40k */
+                       snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
+                                           WM8993_VMID_SEL_MASK |
+                                           WM8993_BIAS_ENA,
+                                           WM8993_BIAS_ENA | 0x2);
+                       msleep(32);
+
+                       /* Switch to normal bias */
+                       snd_soc_update_bits(codec, WM8993_ANTIPOP2,
+                                           WM8993_BIAS_SRC |
+                                           WM8993_STARTUP_BIAS_ENA, 0);
+               }
+
+               /* VMID=2*240k */
+               snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
+                                   WM8993_VMID_SEL_MASK, 0x4);
+
+               snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_2,
+                                   WM8993_TSHUT_ENA, 0);
+               break;
+
+       case SND_SOC_BIAS_OFF:
+               snd_soc_update_bits(codec, WM8993_ANTIPOP1,
+                                   WM8993_LINEOUT_VMID_BUF_ENA, 0);
+
+               snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
+                                   WM8993_VMID_SEL_MASK | WM8993_BIAS_ENA,
+                                   0);
+               break;
+       }
+
+       codec->bias_level = level;
+
+       return 0;
+}
+
+static int wm8993_set_sysclk(struct snd_soc_dai *codec_dai,
+                            int clk_id, unsigned int freq, int dir)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       struct wm8993_priv *wm8993 = codec->private_data;
+
+       switch (clk_id) {
+       case WM8993_SYSCLK_MCLK:
+               wm8993->mclk_rate = freq;
+       case WM8993_SYSCLK_FLL:
+               wm8993->sysclk_source = clk_id;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int wm8993_set_dai_fmt(struct snd_soc_dai *dai,
+                             unsigned int fmt)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8993_priv *wm8993 = codec->private_data;
+       unsigned int aif1 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_1);
+       unsigned int aif4 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_4);
+
+       aif1 &= ~(WM8993_BCLK_DIR | WM8993_AIF_BCLK_INV |
+                 WM8993_AIF_LRCLK_INV | WM8993_AIF_FMT_MASK);
+       aif4 &= ~WM8993_LRCLK_DIR;
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               wm8993->master = 0;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFM:
+               aif4 |= WM8993_LRCLK_DIR;
+               wm8993->master = 1;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFS:
+               aif1 |= WM8993_BCLK_DIR;
+               wm8993->master = 1;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               aif1 |= WM8993_BCLK_DIR;
+               aif4 |= WM8993_LRCLK_DIR;
+               wm8993->master = 1;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_B:
+               aif1 |= WM8993_AIF_LRCLK_INV;
+       case SND_SOC_DAIFMT_DSP_A:
+               aif1 |= 0x18;
+               break;
+       case SND_SOC_DAIFMT_I2S:
+               aif1 |= 0x10;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               aif1 |= 0x8;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+       case SND_SOC_DAIFMT_DSP_B:
+               /* frame inversion not valid for DSP modes */
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       aif1 |= WM8993_AIF_BCLK_INV;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+
+       case SND_SOC_DAIFMT_I2S:
+       case SND_SOC_DAIFMT_RIGHT_J:
+       case SND_SOC_DAIFMT_LEFT_J:
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+                       break;
+               case SND_SOC_DAIFMT_IB_IF:
+                       aif1 |= WM8993_AIF_BCLK_INV | WM8993_AIF_LRCLK_INV;
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       aif1 |= WM8993_AIF_BCLK_INV;
+                       break;
+               case SND_SOC_DAIFMT_NB_IF:
+                       aif1 |= WM8993_AIF_LRCLK_INV;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       wm8993_write(codec, WM8993_AUDIO_INTERFACE_1, aif1);
+       wm8993_write(codec, WM8993_AUDIO_INTERFACE_4, aif4);
+
+       return 0;
+}
+
+static int wm8993_hw_params(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params,
+                           struct snd_soc_dai *dai)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8993_priv *wm8993 = codec->private_data;
+       int ret, i, best, best_val, cur_val;
+       unsigned int clocking1, clocking3, aif1, aif4;
+
+       clocking1 = wm8993_read(codec, WM8993_CLOCKING_1);
+       clocking1 &= ~WM8993_BCLK_DIV_MASK;
+
+       clocking3 = wm8993_read(codec, WM8993_CLOCKING_3);
+       clocking3 &= ~(WM8993_CLK_SYS_RATE_MASK | WM8993_SAMPLE_RATE_MASK);
+
+       aif1 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_1);
+       aif1 &= ~WM8993_AIF_WL_MASK;
+
+       aif4 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_4);
+       aif4 &= ~WM8993_LRCLK_RATE_MASK;
+
+       /* What BCLK do we need? */
+       wm8993->fs = params_rate(params);
+       wm8993->bclk = 2 * wm8993->fs;
+       if (wm8993->tdm_slots) {
+               dev_dbg(codec->dev, "Configuring for %d %d bit TDM slots\n",
+                       wm8993->tdm_slots, wm8993->tdm_width);
+               wm8993->bclk *= wm8993->tdm_width * wm8993->tdm_slots;
+       } else {
+               switch (params_format(params)) {
+               case SNDRV_PCM_FORMAT_S16_LE:
+                       wm8993->bclk *= 16;
+                       break;
+               case SNDRV_PCM_FORMAT_S20_3LE:
+                       wm8993->bclk *= 20;
+                       aif1 |= 0x8;
+                       break;
+               case SNDRV_PCM_FORMAT_S24_LE:
+                       wm8993->bclk *= 24;
+                       aif1 |= 0x10;
+                       break;
+               case SNDRV_PCM_FORMAT_S32_LE:
+                       wm8993->bclk *= 32;
+                       aif1 |= 0x18;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+
+       dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm8993->bclk);
+
+       ret = configure_clock(codec);
+       if (ret != 0)
+               return ret;
+
+       /* Select nearest CLK_SYS_RATE */
+       best = 0;
+       best_val = abs((wm8993->sysclk_rate / clk_sys_rates[0].ratio)
+                      - wm8993->fs);
+       for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) {
+               cur_val = abs((wm8993->sysclk_rate /
+                              clk_sys_rates[i].ratio) - wm8993->fs);;
+               if (cur_val < best_val) {
+                       best = i;
+                       best_val = cur_val;
+               }
+       }
+       dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n",
+               clk_sys_rates[best].ratio);
+       clocking3 |= (clk_sys_rates[best].clk_sys_rate
+                     << WM8993_CLK_SYS_RATE_SHIFT);
+
+       /* SAMPLE_RATE */
+       best = 0;
+       best_val = abs(wm8993->fs - sample_rates[0].rate);
+       for (i = 1; i < ARRAY_SIZE(sample_rates); i++) {
+               /* Closest match */
+               cur_val = abs(wm8993->fs - sample_rates[i].rate);
+               if (cur_val < best_val) {
+                       best = i;
+                       best_val = cur_val;
+               }
+       }
+       dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n",
+               sample_rates[best].rate);
+       clocking3 |= (sample_rates[best].sample_rate
+                     << WM8993_SAMPLE_RATE_SHIFT);
+
+       /* BCLK_DIV */
+       best = 0;
+       best_val = INT_MAX;
+       for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
+               cur_val = ((wm8993->sysclk_rate * 10) / bclk_divs[i].div)
+                       - wm8993->bclk;
+               if (cur_val < 0) /* Table is sorted */
+                       break;
+               if (cur_val < best_val) {
+                       best = i;
+                       best_val = cur_val;
+               }
+       }
+       wm8993->bclk = (wm8993->sysclk_rate * 10) / bclk_divs[best].div;
+       dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n",
+               bclk_divs[best].div, wm8993->bclk);
+       clocking1 |= bclk_divs[best].bclk_div << WM8993_BCLK_DIV_SHIFT;
+
+       /* LRCLK is a simple fraction of BCLK */
+       dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm8993->bclk / wm8993->fs);
+       aif4 |= wm8993->bclk / wm8993->fs;
+
+       wm8993_write(codec, WM8993_CLOCKING_1, clocking1);
+       wm8993_write(codec, WM8993_CLOCKING_3, clocking3);
+       wm8993_write(codec, WM8993_AUDIO_INTERFACE_1, aif1);
+       wm8993_write(codec, WM8993_AUDIO_INTERFACE_4, aif4);
+
+       /* ReTune Mobile? */
+       if (wm8993->pdata.num_retune_configs) {
+               u16 eq1 = wm8993_read(codec, WM8993_EQ1);
+               struct wm8993_retune_mobile_setting *s;
+
+               best = 0;
+               best_val = abs(wm8993->pdata.retune_configs[0].rate
+                              - wm8993->fs);
+               for (i = 0; i < wm8993->pdata.num_retune_configs; i++) {
+                       cur_val = abs(wm8993->pdata.retune_configs[i].rate
+                                     - wm8993->fs);
+                       if (cur_val < best_val) {
+                               best_val = cur_val;
+                               best = i;
+                       }
+               }
+               s = &wm8993->pdata.retune_configs[best];
+
+               dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n",
+                       s->name, s->rate);
+
+               /* Disable EQ while we reconfigure */
+               snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, 0);
+
+               for (i = 1; i < ARRAY_SIZE(s->config); i++)
+                       wm8993_write(codec, WM8993_EQ1 + i, s->config[i]);
+
+               snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, eq1);
+       }
+
+       return 0;
+}
+
+static int wm8993_digital_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+       struct snd_soc_codec *codec = codec_dai->codec;
+       unsigned int reg;
+
+       reg = wm8993_read(codec, WM8993_DAC_CTRL);
+
+       if (mute)
+               reg |= WM8993_DAC_MUTE;
+       else
+               reg &= ~WM8993_DAC_MUTE;
+
+       wm8993_write(codec, WM8993_DAC_CTRL, reg);
+
+       return 0;
+}
+
+static int wm8993_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+                              unsigned int rx_mask, int slots, int slot_width)
+{
+       struct snd_soc_codec *codec = dai->codec;
+       struct wm8993_priv *wm8993 = codec->private_data;
+       int aif1 = 0;
+       int aif2 = 0;
+
+       /* Don't need to validate anything if we're turning off TDM */
+       if (slots == 0) {
+               wm8993->tdm_slots = 0;
+               goto out;
+       }
+
+       /* Note that we allow configurations we can't handle ourselves - 
+        * for example, we can generate clocks for slots 2 and up even if
+        * we can't use those slots ourselves.
+        */
+       aif1 |= WM8993_AIFADC_TDM;
+       aif2 |= WM8993_AIFDAC_TDM;
+
+       switch (rx_mask) {
+       case 3:
+               break;
+       case 0xc:
+               aif1 |= WM8993_AIFADC_TDM_CHAN;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+
+       switch (tx_mask) {
+       case 3:
+               break;
+       case 0xc:
+               aif2 |= WM8993_AIFDAC_TDM_CHAN;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+out:
+       wm8993->tdm_width = slot_width;
+       wm8993->tdm_slots = slots / 2;
+
+       snd_soc_update_bits(codec, WM8993_AUDIO_INTERFACE_1,
+                           WM8993_AIFADC_TDM | WM8993_AIFADC_TDM_CHAN, aif1);
+       snd_soc_update_bits(codec, WM8993_AUDIO_INTERFACE_2,
+                           WM8993_AIFDAC_TDM | WM8993_AIFDAC_TDM_CHAN, aif2);
+
+       return 0;
+}
+
+static struct snd_soc_dai_ops wm8993_ops = {
+       .set_sysclk = wm8993_set_sysclk,
+       .set_fmt = wm8993_set_dai_fmt,
+       .hw_params = wm8993_hw_params,
+       .digital_mute = wm8993_digital_mute,
+       .set_pll = wm8993_set_fll,
+       .set_tdm_slot = wm8993_set_tdm_slot,
+};
+
+#define WM8993_RATES SNDRV_PCM_RATE_8000_48000
+
+#define WM8993_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+                       SNDRV_PCM_FMTBIT_S20_3LE |\
+                       SNDRV_PCM_FMTBIT_S24_LE |\
+                       SNDRV_PCM_FMTBIT_S32_LE)
+
+struct snd_soc_dai wm8993_dai = {
+       .name = "WM8993",
+       .playback = {
+               .stream_name = "Playback",
+               .channels_min = 1,
+               .channels_max = 2,
+               .rates = WM8993_RATES,
+               .formats = WM8993_FORMATS,
+       },
+       .capture = {
+                .stream_name = "Capture",
+                .channels_min = 1,
+                .channels_max = 2,
+                .rates = WM8993_RATES,
+                .formats = WM8993_FORMATS,
+        },
+       .ops = &wm8993_ops,
+       .symmetric_rates = 1,
+};
+EXPORT_SYMBOL_GPL(wm8993_dai);
+
+static struct snd_soc_codec *wm8993_codec;
+
+static int wm8993_probe(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_codec *codec;
+       struct wm8993_priv *wm8993;
+       int ret = 0;
+
+       if (!wm8993_codec) {
+               dev_err(&pdev->dev, "I2C device not yet probed\n");
+               goto err;
+       }
+
+       socdev->card->codec = wm8993_codec;
+       codec = wm8993_codec;
+       wm8993 = codec->private_data;
+
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to create pcms\n");
+               goto err;
+       }
+
+       snd_soc_add_controls(codec, wm8993_snd_controls,
+                            ARRAY_SIZE(wm8993_snd_controls));
+       if (wm8993->pdata.num_retune_configs != 0) {
+               dev_dbg(codec->dev, "Using ReTune Mobile\n");
+       } else {
+               dev_dbg(codec->dev, "No ReTune Mobile, using normal EQ\n");
+               snd_soc_add_controls(codec, wm8993_eq_controls,
+                                    ARRAY_SIZE(wm8993_eq_controls));
+       }
+
+       snd_soc_dapm_new_controls(codec, wm8993_dapm_widgets,
+                                 ARRAY_SIZE(wm8993_dapm_widgets));
+       wm_hubs_add_analogue_controls(codec);
+
+       snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes));
+       wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
+                                   wm8993->pdata.lineout2_diff);
+
+       snd_soc_dapm_new_widgets(codec);
+
+       ret = snd_soc_init_card(socdev);
+       if (ret < 0) {
+               dev_err(codec->dev, "failed to register card\n");
+               goto card_err;
+       }
+
+       return ret;
+
+card_err:
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+err:
+       return ret;
+}
+
+static int wm8993_remove(struct platform_device *pdev)
+{
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+
+       snd_soc_free_pcms(socdev);
+       snd_soc_dapm_free(socdev);
+
+       return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8993 = {
+       .probe =        wm8993_probe,
+       .remove =       wm8993_remove,
+};
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993);
+
+static int wm8993_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
+{
+       struct wm8993_priv *wm8993;
+       struct snd_soc_codec *codec;
+       unsigned int val;
+       int ret;
+
+       if (wm8993_codec) {
+               dev_err(&i2c->dev, "A WM8993 is already registered\n");
+               return -EINVAL;
+       }
+
+       wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL);
+       if (wm8993 == NULL)
+               return -ENOMEM;
+
+       codec = &wm8993->codec;
+       if (i2c->dev.platform_data)
+               memcpy(&wm8993->pdata, i2c->dev.platform_data,
+                      sizeof(wm8993->pdata));
+
+       mutex_init(&codec->mutex);
+       INIT_LIST_HEAD(&codec->dapm_widgets);
+       INIT_LIST_HEAD(&codec->dapm_paths);
+
+       codec->name = "WM8993";
+       codec->read = wm8993_read;
+       codec->write = wm8993_write;
+       codec->hw_write = (hw_write_t)i2c_master_send;
+       codec->reg_cache = wm8993->reg_cache;
+       codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache);
+       codec->bias_level = SND_SOC_BIAS_OFF;
+       codec->set_bias_level = wm8993_set_bias_level;
+       codec->dai = &wm8993_dai;
+       codec->num_dai = 1;
+       codec->private_data = wm8993;
+
+       memcpy(wm8993->reg_cache, wm8993_reg_defaults,
+              sizeof(wm8993->reg_cache));
+
+       i2c_set_clientdata(i2c, wm8993);
+       codec->control_data = i2c;
+       wm8993_codec = codec;
+
+       codec->dev = &i2c->dev;
+
+       val = wm8993_read_hw(codec, WM8993_SOFTWARE_RESET);
+       if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) {
+               dev_err(codec->dev, "Invalid ID register value %x\n", val);
+               ret = -EINVAL;
+               goto err;
+       }
+
+       ret = wm8993_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
+       if (ret != 0)
+               goto err;
+
+       /* By default we're using the output mixers */
+       wm8993->class_w_users = 2;
+
+       /* Latch volume update bits and default ZC on */
+       snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME,
+                           WM8993_DAC_VU, WM8993_DAC_VU);
+       snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME,
+                           WM8993_ADC_VU, WM8993_ADC_VU);
+
+       /* Manualy manage the HPOUT sequencing for independent stereo
+        * control. */
+       snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0,
+                           WM8993_HPOUT1_AUTO_PU, 0);
+
+       /* Use automatic clock configuration */
+       snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0);
+
+       if (!wm8993->pdata.lineout1_diff)
+               snd_soc_update_bits(codec, WM8993_LINE_MIXER1,
+                                   WM8993_LINEOUT1_MODE,
+                                   WM8993_LINEOUT1_MODE);
+       if (!wm8993->pdata.lineout2_diff)
+               snd_soc_update_bits(codec, WM8993_LINE_MIXER2,
+                                   WM8993_LINEOUT2_MODE,
+                                   WM8993_LINEOUT2_MODE);
+
+       if (wm8993->pdata.lineout1fb)
+               snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
+                                   WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB);
+
+       if (wm8993->pdata.lineout2fb)
+               snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
+                                   WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB);
+
+       /* Apply the microphone bias/detection configuration - the
+        * platform data is directly applicable to the register. */
+       snd_soc_update_bits(codec, WM8993_MICBIAS,
+                           WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK |
+                           WM8993_MICB1_LVL | WM8993_MICB2_LVL,
+                           wm8993->pdata.jd_scthr << WM8993_JD_SCTHR_SHIFT |
+                           wm8993->pdata.jd_thr << WM8993_JD_THR_SHIFT |
+                           wm8993->pdata.micbias1_lvl |
+                           wm8993->pdata.micbias1_lvl << 1);
+
+       ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+       if (ret != 0)
+               goto err;
+
+       wm8993_dai.dev = codec->dev;
+
+       ret = snd_soc_register_dai(&wm8993_dai);
+       if (ret != 0)
+               goto err_bias;
+
+       ret = snd_soc_register_codec(codec);
+
+       return 0;
+
+err_bias:
+       wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
+err:
+       wm8993_codec = NULL;
+       kfree(wm8993);
+       return ret;
+}
+
+static int wm8993_i2c_remove(struct i2c_client *client)
+{
+       struct wm8993_priv *wm8993 = i2c_get_clientdata(client);
+
+       snd_soc_unregister_codec(&wm8993->codec);
+       snd_soc_unregister_dai(&wm8993_dai);
+
+       wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF);
+       kfree(wm8993);
+
+       return 0;
+}
+
+static const struct i2c_device_id wm8993_i2c_id[] = {
+       { "wm8993", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id);
+
+static struct i2c_driver wm8993_i2c_driver = {
+       .driver = {
+               .name = "WM8993",
+               .owner = THIS_MODULE,
+       },
+       .probe = wm8993_i2c_probe,
+       .remove = wm8993_i2c_remove,
+       .id_table = wm8993_i2c_id,
+};
+
+
+static int __init wm8993_modinit(void)
+{
+       int ret;
+
+       ret = i2c_add_driver(&wm8993_i2c_driver);
+       if (ret != 0)
+               pr_err("WM8993: Unable to register I2C driver: %d\n", ret);
+
+       return ret;
+}
+module_init(wm8993_modinit);
+
+static void __exit wm8993_exit(void)
+{
+       i2c_del_driver(&wm8993_i2c_driver);
+}
+module_exit(wm8993_exit);
+
+
+MODULE_DESCRIPTION("ASoC WM8993 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8993.h b/sound/soc/codecs/wm8993.h
new file mode 100644 (file)
index 0000000..30e71ca
--- /dev/null
@@ -0,0 +1,2132 @@
+#ifndef WM8993_H
+#define WM8993_H
+
+extern struct snd_soc_dai wm8993_dai;
+extern struct snd_soc_codec_device soc_codec_dev_wm8993;
+
+#define WM8993_SYSCLK_MCLK     1
+#define WM8993_SYSCLK_FLL      2
+
+#define WM8993_FLL_MCLK  1
+#define WM8993_FLL_BCLK  2
+#define WM8993_FLL_LRCLK 3
+
+/*
+ * Register values.
+ */
+#define WM8993_SOFTWARE_RESET                   0x00
+#define WM8993_POWER_MANAGEMENT_1               0x01
+#define WM8993_POWER_MANAGEMENT_2               0x02
+#define WM8993_POWER_MANAGEMENT_3               0x03
+#define WM8993_AUDIO_INTERFACE_1                0x04
+#define WM8993_AUDIO_INTERFACE_2                0x05
+#define WM8993_CLOCKING_1                       0x06
+#define WM8993_CLOCKING_2                       0x07
+#define WM8993_AUDIO_INTERFACE_3                0x08
+#define WM8993_AUDIO_INTERFACE_4                0x09
+#define WM8993_DAC_CTRL                         0x0A
+#define WM8993_LEFT_DAC_DIGITAL_VOLUME          0x0B
+#define WM8993_RIGHT_DAC_DIGITAL_VOLUME         0x0C
+#define WM8993_DIGITAL_SIDE_TONE                0x0D
+#define WM8993_ADC_CTRL                         0x0E
+#define WM8993_LEFT_ADC_DIGITAL_VOLUME          0x0F
+#define WM8993_RIGHT_ADC_DIGITAL_VOLUME         0x10
+#define WM8993_GPIO_CTRL_1                      0x12
+#define WM8993_GPIO1                            0x13
+#define WM8993_IRQ_DEBOUNCE                     0x14
+#define WM8993_GPIOCTRL_2                       0x16
+#define WM8993_GPIO_POL                         0x17
+#define WM8993_LEFT_LINE_INPUT_1_2_VOLUME       0x18
+#define WM8993_LEFT_LINE_INPUT_3_4_VOLUME       0x19
+#define WM8993_RIGHT_LINE_INPUT_1_2_VOLUME      0x1A
+#define WM8993_RIGHT_LINE_INPUT_3_4_VOLUME      0x1B
+#define WM8993_LEFT_OUTPUT_VOLUME               0x1C
+#define WM8993_RIGHT_OUTPUT_VOLUME              0x1D
+#define WM8993_LINE_OUTPUTS_VOLUME              0x1E
+#define WM8993_HPOUT2_VOLUME                    0x1F
+#define WM8993_LEFT_OPGA_VOLUME                 0x20
+#define WM8993_RIGHT_OPGA_VOLUME                0x21
+#define WM8993_SPKMIXL_ATTENUATION              0x22
+#define WM8993_SPKMIXR_ATTENUATION              0x23
+#define WM8993_SPKOUT_MIXERS                    0x24
+#define WM8993_SPKOUT_BOOST                     0x25
+#define WM8993_SPEAKER_VOLUME_LEFT              0x26
+#define WM8993_SPEAKER_VOLUME_RIGHT             0x27
+#define WM8993_INPUT_MIXER2                     0x28
+#define WM8993_INPUT_MIXER3                     0x29
+#define WM8993_INPUT_MIXER4                     0x2A
+#define WM8993_INPUT_MIXER5                     0x2B
+#define WM8993_INPUT_MIXER6                     0x2C
+#define WM8993_OUTPUT_MIXER1                    0x2D
+#define WM8993_OUTPUT_MIXER2                    0x2E
+#define WM8993_OUTPUT_MIXER3                    0x2F
+#define WM8993_OUTPUT_MIXER4                    0x30
+#define WM8993_OUTPUT_MIXER5                    0x31
+#define WM8993_OUTPUT_MIXER6                    0x32
+#define WM8993_HPOUT2_MIXER                     0x33
+#define WM8993_LINE_MIXER1                      0x34
+#define WM8993_LINE_MIXER2                      0x35
+#define WM8993_SPEAKER_MIXER                    0x36
+#define WM8993_ADDITIONAL_CONTROL               0x37
+#define WM8993_ANTIPOP1                         0x38
+#define WM8993_ANTIPOP2                         0x39
+#define WM8993_MICBIAS                          0x3A
+#define WM8993_FLL_CONTROL_1                    0x3C
+#define WM8993_FLL_CONTROL_2                    0x3D
+#define WM8993_FLL_CONTROL_3                    0x3E
+#define WM8993_FLL_CONTROL_4                    0x3F
+#define WM8993_FLL_CONTROL_5                    0x40
+#define WM8993_CLOCKING_3                       0x41
+#define WM8993_CLOCKING_4                       0x42
+#define WM8993_MW_SLAVE_CONTROL                 0x43
+#define WM8993_BUS_CONTROL_1                    0x45
+#define WM8993_WRITE_SEQUENCER_0                0x46
+#define WM8993_WRITE_SEQUENCER_1                0x47
+#define WM8993_WRITE_SEQUENCER_2                0x48
+#define WM8993_WRITE_SEQUENCER_3                0x49
+#define WM8993_WRITE_SEQUENCER_4                0x4A
+#define WM8993_WRITE_SEQUENCER_5                0x4B
+#define WM8993_CHARGE_PUMP_1                    0x4C
+#define WM8993_CLASS_W_0                        0x51
+#define WM8993_DC_SERVO_0                       0x54
+#define WM8993_DC_SERVO_1                       0x55
+#define WM8993_DC_SERVO_3                       0x57
+#define WM8993_DC_SERVO_READBACK_0              0x58
+#define WM8993_DC_SERVO_READBACK_1              0x59
+#define WM8993_DC_SERVO_READBACK_2              0x5A
+#define WM8993_ANALOGUE_HP_0                    0x60
+#define WM8993_EQ1                              0x62
+#define WM8993_EQ2                              0x63
+#define WM8993_EQ3                              0x64
+#define WM8993_EQ4                              0x65
+#define WM8993_EQ5                              0x66
+#define WM8993_EQ6                              0x67
+#define WM8993_EQ7                              0x68
+#define WM8993_EQ8                              0x69
+#define WM8993_EQ9                              0x6A
+#define WM8993_EQ10                             0x6B
+#define WM8993_EQ11                             0x6C
+#define WM8993_EQ12                             0x6D
+#define WM8993_EQ13                             0x6E
+#define WM8993_EQ14                             0x6F
+#define WM8993_EQ15                             0x70
+#define WM8993_EQ16                             0x71
+#define WM8993_EQ17                             0x72
+#define WM8993_EQ18                             0x73
+#define WM8993_EQ19                             0x74
+#define WM8993_EQ20                             0x75
+#define WM8993_EQ21                             0x76
+#define WM8993_EQ22                             0x77
+#define WM8993_EQ23                             0x78
+#define WM8993_EQ24                             0x79
+#define WM8993_DIGITAL_PULLS                    0x7A
+#define WM8993_DRC_CONTROL_1                    0x7B
+#define WM8993_DRC_CONTROL_2                    0x7C
+#define WM8993_DRC_CONTROL_3                    0x7D
+#define WM8993_DRC_CONTROL_4                    0x7E
+
+#define WM8993_REGISTER_COUNT                   0x7F
+#define WM8993_MAX_REGISTER                     0x7E
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Software Reset
+ */
+#define WM8993_SW_RESET_MASK                    0xFFFF  /* SW_RESET - [15:0] */
+#define WM8993_SW_RESET_SHIFT                        0  /* SW_RESET - [15:0] */
+#define WM8993_SW_RESET_WIDTH                       16  /* SW_RESET - [15:0] */
+
+/*
+ * R1 (0x01) - Power Management (1)
+ */
+#define WM8993_SPKOUTR_ENA                      0x2000  /* SPKOUTR_ENA */
+#define WM8993_SPKOUTR_ENA_MASK                 0x2000  /* SPKOUTR_ENA */
+#define WM8993_SPKOUTR_ENA_SHIFT                    13  /* SPKOUTR_ENA */
+#define WM8993_SPKOUTR_ENA_WIDTH                     1  /* SPKOUTR_ENA */
+#define WM8993_SPKOUTL_ENA                      0x1000  /* SPKOUTL_ENA */
+#define WM8993_SPKOUTL_ENA_MASK                 0x1000  /* SPKOUTL_ENA */
+#define WM8993_SPKOUTL_ENA_SHIFT                    12  /* SPKOUTL_ENA */
+#define WM8993_SPKOUTL_ENA_WIDTH                     1  /* SPKOUTL_ENA */
+#define WM8993_HPOUT2_ENA                       0x0800  /* HPOUT2_ENA */
+#define WM8993_HPOUT2_ENA_MASK                  0x0800  /* HPOUT2_ENA */
+#define WM8993_HPOUT2_ENA_SHIFT                     11  /* HPOUT2_ENA */
+#define WM8993_HPOUT2_ENA_WIDTH                      1  /* HPOUT2_ENA */
+#define WM8993_HPOUT1L_ENA                      0x0200  /* HPOUT1L_ENA */
+#define WM8993_HPOUT1L_ENA_MASK                 0x0200  /* HPOUT1L_ENA */
+#define WM8993_HPOUT1L_ENA_SHIFT                     9  /* HPOUT1L_ENA */
+#define WM8993_HPOUT1L_ENA_WIDTH                     1  /* HPOUT1L_ENA */
+#define WM8993_HPOUT1R_ENA                      0x0100  /* HPOUT1R_ENA */
+#define WM8993_HPOUT1R_ENA_MASK                 0x0100  /* HPOUT1R_ENA */
+#define WM8993_HPOUT1R_ENA_SHIFT                     8  /* HPOUT1R_ENA */
+#define WM8993_HPOUT1R_ENA_WIDTH                     1  /* HPOUT1R_ENA */
+#define WM8993_MICB2_ENA                        0x0020  /* MICB2_ENA */
+#define WM8993_MICB2_ENA_MASK                   0x0020  /* MICB2_ENA */
+#define WM8993_MICB2_ENA_SHIFT                       5  /* MICB2_ENA */
+#define WM8993_MICB2_ENA_WIDTH                       1  /* MICB2_ENA */
+#define WM8993_MICB1_ENA                        0x0010  /* MICB1_ENA */
+#define WM8993_MICB1_ENA_MASK                   0x0010  /* MICB1_ENA */
+#define WM8993_MICB1_ENA_SHIFT                       4  /* MICB1_ENA */
+#define WM8993_MICB1_ENA_WIDTH                       1  /* MICB1_ENA */
+#define WM8993_VMID_SEL_MASK                    0x0006  /* VMID_SEL - [2:1] */
+#define WM8993_VMID_SEL_SHIFT                        1  /* VMID_SEL - [2:1] */
+#define WM8993_VMID_SEL_WIDTH                        2  /* VMID_SEL - [2:1] */
+#define WM8993_BIAS_ENA                         0x0001  /* BIAS_ENA */
+#define WM8993_BIAS_ENA_MASK                    0x0001  /* BIAS_ENA */
+#define WM8993_BIAS_ENA_SHIFT                        0  /* BIAS_ENA */
+#define WM8993_BIAS_ENA_WIDTH                        1  /* BIAS_ENA */
+
+/*
+ * R2 (0x02) - Power Management (2)
+ */
+#define WM8993_TSHUT_ENA                        0x4000  /* TSHUT_ENA */
+#define WM8993_TSHUT_ENA_MASK                   0x4000  /* TSHUT_ENA */
+#define WM8993_TSHUT_ENA_SHIFT                      14  /* TSHUT_ENA */
+#define WM8993_TSHUT_ENA_WIDTH                       1  /* TSHUT_ENA */
+#define WM8993_TSHUT_OPDIS                      0x2000  /* TSHUT_OPDIS */
+#define WM8993_TSHUT_OPDIS_MASK                 0x2000  /* TSHUT_OPDIS */
+#define WM8993_TSHUT_OPDIS_SHIFT                    13  /* TSHUT_OPDIS */
+#define WM8993_TSHUT_OPDIS_WIDTH                     1  /* TSHUT_OPDIS */
+#define WM8993_OPCLK_ENA                        0x0800  /* OPCLK_ENA */
+#define WM8993_OPCLK_ENA_MASK                   0x0800  /* OPCLK_ENA */
+#define WM8993_OPCLK_ENA_SHIFT                      11  /* OPCLK_ENA */
+#define WM8993_OPCLK_ENA_WIDTH                       1  /* OPCLK_ENA */
+#define WM8993_MIXINL_ENA                       0x0200  /* MIXINL_ENA */
+#define WM8993_MIXINL_ENA_MASK                  0x0200  /* MIXINL_ENA */
+#define WM8993_MIXINL_ENA_SHIFT                      9  /* MIXINL_ENA */
+#define WM8993_MIXINL_ENA_WIDTH                      1  /* MIXINL_ENA */
+#define WM8993_MIXINR_ENA                       0x0100  /* MIXINR_ENA */
+#define WM8993_MIXINR_ENA_MASK                  0x0100  /* MIXINR_ENA */
+#define WM8993_MIXINR_ENA_SHIFT                      8  /* MIXINR_ENA */
+#define WM8993_MIXINR_ENA_WIDTH                      1  /* MIXINR_ENA */
+#define WM8993_IN2L_ENA                         0x0080  /* IN2L_ENA */
+#define WM8993_IN2L_ENA_MASK                    0x0080  /* IN2L_ENA */
+#define WM8993_IN2L_ENA_SHIFT                        7  /* IN2L_ENA */
+#define WM8993_IN2L_ENA_WIDTH                        1  /* IN2L_ENA */
+#define WM8993_IN1L_ENA                         0x0040  /* IN1L_ENA */
+#define WM8993_IN1L_ENA_MASK                    0x0040  /* IN1L_ENA */
+#define WM8993_IN1L_ENA_SHIFT                        6  /* IN1L_ENA */
+#define WM8993_IN1L_ENA_WIDTH                        1  /* IN1L_ENA */
+#define WM8993_IN2R_ENA                         0x0020  /* IN2R_ENA */
+#define WM8993_IN2R_ENA_MASK                    0x0020  /* IN2R_ENA */
+#define WM8993_IN2R_ENA_SHIFT                        5  /* IN2R_ENA */
+#define WM8993_IN2R_ENA_WIDTH                        1  /* IN2R_ENA */
+#define WM8993_IN1R_ENA                         0x0010  /* IN1R_ENA */
+#define WM8993_IN1R_ENA_MASK                    0x0010  /* IN1R_ENA */
+#define WM8993_IN1R_ENA_SHIFT                        4  /* IN1R_ENA */
+#define WM8993_IN1R_ENA_WIDTH                        1  /* IN1R_ENA */
+#define WM8993_ADCL_ENA                         0x0002  /* ADCL_ENA */
+#define WM8993_ADCL_ENA_MASK                    0x0002  /* ADCL_ENA */
+#define WM8993_ADCL_ENA_SHIFT                        1  /* ADCL_ENA */
+#define WM8993_ADCL_ENA_WIDTH                        1  /* ADCL_ENA */
+#define WM8993_ADCR_ENA                         0x0001  /* ADCR_ENA */
+#define WM8993_ADCR_ENA_MASK                    0x0001  /* ADCR_ENA */
+#define WM8993_ADCR_ENA_SHIFT                        0  /* ADCR_ENA */
+#define WM8993_ADCR_ENA_WIDTH                        1  /* ADCR_ENA */
+
+/*
+ * R3 (0x03) - Power Management (3)
+ */
+#define WM8993_LINEOUT1N_ENA                    0x2000  /* LINEOUT1N_ENA */
+#define WM8993_LINEOUT1N_ENA_MASK               0x2000  /* LINEOUT1N_ENA */
+#define WM8993_LINEOUT1N_ENA_SHIFT                  13  /* LINEOUT1N_ENA */
+#define WM8993_LINEOUT1N_ENA_WIDTH                   1  /* LINEOUT1N_ENA */
+#define WM8993_LINEOUT1P_ENA                    0x1000  /* LINEOUT1P_ENA */
+#define WM8993_LINEOUT1P_ENA_MASK               0x1000  /* LINEOUT1P_ENA */
+#define WM8993_LINEOUT1P_ENA_SHIFT                  12  /* LINEOUT1P_ENA */
+#define WM8993_LINEOUT1P_ENA_WIDTH                   1  /* LINEOUT1P_ENA */
+#define WM8993_LINEOUT2N_ENA                    0x0800  /* LINEOUT2N_ENA */
+#define WM8993_LINEOUT2N_ENA_MASK               0x0800  /* LINEOUT2N_ENA */
+#define WM8993_LINEOUT2N_ENA_SHIFT                  11  /* LINEOUT2N_ENA */
+#define WM8993_LINEOUT2N_ENA_WIDTH                   1  /* LINEOUT2N_ENA */
+#define WM8993_LINEOUT2P_ENA                    0x0400  /* LINEOUT2P_ENA */
+#define WM8993_LINEOUT2P_ENA_MASK               0x0400  /* LINEOUT2P_ENA */
+#define WM8993_LINEOUT2P_ENA_SHIFT                  10  /* LINEOUT2P_ENA */
+#define WM8993_LINEOUT2P_ENA_WIDTH                   1  /* LINEOUT2P_ENA */
+#define WM8993_SPKRVOL_ENA                      0x0200  /* SPKRVOL_ENA */
+#define WM8993_SPKRVOL_ENA_MASK                 0x0200  /* SPKRVOL_ENA */
+#define WM8993_SPKRVOL_ENA_SHIFT                     9  /* SPKRVOL_ENA */
+#define WM8993_SPKRVOL_ENA_WIDTH                     1  /* SPKRVOL_ENA */
+#define WM8993_SPKLVOL_ENA                      0x0100  /* SPKLVOL_ENA */
+#define WM8993_SPKLVOL_ENA_MASK                 0x0100  /* SPKLVOL_ENA */
+#define WM8993_SPKLVOL_ENA_SHIFT                     8  /* SPKLVOL_ENA */
+#define WM8993_SPKLVOL_ENA_WIDTH                     1  /* SPKLVOL_ENA */
+#define WM8993_MIXOUTLVOL_ENA                   0x0080  /* MIXOUTLVOL_ENA */
+#define WM8993_MIXOUTLVOL_ENA_MASK              0x0080  /* MIXOUTLVOL_ENA */
+#define WM8993_MIXOUTLVOL_ENA_SHIFT                  7  /* MIXOUTLVOL_ENA */
+#define WM8993_MIXOUTLVOL_ENA_WIDTH                  1  /* MIXOUTLVOL_ENA */
+#define WM8993_MIXOUTRVOL_ENA                   0x0040  /* MIXOUTRVOL_ENA */
+#define WM8993_MIXOUTRVOL_ENA_MASK              0x0040  /* MIXOUTRVOL_ENA */
+#define WM8993_MIXOUTRVOL_ENA_SHIFT                  6  /* MIXOUTRVOL_ENA */
+#define WM8993_MIXOUTRVOL_ENA_WIDTH                  1  /* MIXOUTRVOL_ENA */
+#define WM8993_MIXOUTL_ENA                      0x0020  /* MIXOUTL_ENA */
+#define WM8993_MIXOUTL_ENA_MASK                 0x0020  /* MIXOUTL_ENA */
+#define WM8993_MIXOUTL_ENA_SHIFT                     5  /* MIXOUTL_ENA */
+#define WM8993_MIXOUTL_ENA_WIDTH                     1  /* MIXOUTL_ENA */
+#define WM8993_MIXOUTR_ENA                      0x0010  /* MIXOUTR_ENA */
+#define WM8993_MIXOUTR_ENA_MASK                 0x0010  /* MIXOUTR_ENA */
+#define WM8993_MIXOUTR_ENA_SHIFT                     4  /* MIXOUTR_ENA */
+#define WM8993_MIXOUTR_ENA_WIDTH                     1  /* MIXOUTR_ENA */
+#define WM8993_DACL_ENA                         0x0002  /* DACL_ENA */
+#define WM8993_DACL_ENA_MASK                    0x0002  /* DACL_ENA */
+#define WM8993_DACL_ENA_SHIFT                        1  /* DACL_ENA */
+#define WM8993_DACL_ENA_WIDTH                        1  /* DACL_ENA */
+#define WM8993_DACR_ENA                         0x0001  /* DACR_ENA */
+#define WM8993_DACR_ENA_MASK                    0x0001  /* DACR_ENA */
+#define WM8993_DACR_ENA_SHIFT                        0  /* DACR_ENA */
+#define WM8993_DACR_ENA_WIDTH                        1  /* DACR_ENA */
+
+/*
+ * R4 (0x04) - Audio Interface (1)
+ */
+#define WM8993_AIFADCL_SRC                      0x8000  /* AIFADCL_SRC */
+#define WM8993_AIFADCL_SRC_MASK                 0x8000  /* AIFADCL_SRC */
+#define WM8993_AIFADCL_SRC_SHIFT                    15  /* AIFADCL_SRC */
+#define WM8993_AIFADCL_SRC_WIDTH                     1  /* AIFADCL_SRC */
+#define WM8993_AIFADCR_SRC                      0x4000  /* AIFADCR_SRC */
+#define WM8993_AIFADCR_SRC_MASK                 0x4000  /* AIFADCR_SRC */
+#define WM8993_AIFADCR_SRC_SHIFT                    14  /* AIFADCR_SRC */
+#define WM8993_AIFADCR_SRC_WIDTH                     1  /* AIFADCR_SRC */
+#define WM8993_AIFADC_TDM                       0x2000  /* AIFADC_TDM */
+#define WM8993_AIFADC_TDM_MASK                  0x2000  /* AIFADC_TDM */
+#define WM8993_AIFADC_TDM_SHIFT                     13  /* AIFADC_TDM */
+#define WM8993_AIFADC_TDM_WIDTH                      1  /* AIFADC_TDM */
+#define WM8993_AIFADC_TDM_CHAN                  0x1000  /* AIFADC_TDM_CHAN */
+#define WM8993_AIFADC_TDM_CHAN_MASK             0x1000  /* AIFADC_TDM_CHAN */
+#define WM8993_AIFADC_TDM_CHAN_SHIFT                12  /* AIFADC_TDM_CHAN */
+#define WM8993_AIFADC_TDM_CHAN_WIDTH                 1  /* AIFADC_TDM_CHAN */
+#define WM8993_BCLK_DIR                         0x0200  /* BCLK_DIR */
+#define WM8993_BCLK_DIR_MASK                    0x0200  /* BCLK_DIR */
+#define WM8993_BCLK_DIR_SHIFT                        9  /* BCLK_DIR */
+#define WM8993_BCLK_DIR_WIDTH                        1  /* BCLK_DIR */
+#define WM8993_AIF_BCLK_INV                     0x0100  /* AIF_BCLK_INV */
+#define WM8993_AIF_BCLK_INV_MASK                0x0100  /* AIF_BCLK_INV */
+#define WM8993_AIF_BCLK_INV_SHIFT                    8  /* AIF_BCLK_INV */
+#define WM8993_AIF_BCLK_INV_WIDTH                    1  /* AIF_BCLK_INV */
+#define WM8993_AIF_LRCLK_INV                    0x0080  /* AIF_LRCLK_INV */
+#define WM8993_AIF_LRCLK_INV_MASK               0x0080  /* AIF_LRCLK_INV */
+#define WM8993_AIF_LRCLK_INV_SHIFT                   7  /* AIF_LRCLK_INV */
+#define WM8993_AIF_LRCLK_INV_WIDTH                   1  /* AIF_LRCLK_INV */
+#define WM8993_AIF_WL_MASK                      0x0060  /* AIF_WL - [6:5] */
+#define WM8993_AIF_WL_SHIFT                          5  /* AIF_WL - [6:5] */
+#define WM8993_AIF_WL_WIDTH                          2  /* AIF_WL - [6:5] */
+#define WM8993_AIF_FMT_MASK                     0x0018  /* AIF_FMT - [4:3] */
+#define WM8993_AIF_FMT_SHIFT                         3  /* AIF_FMT - [4:3] */
+#define WM8993_AIF_FMT_WIDTH                         2  /* AIF_FMT - [4:3] */
+
+/*
+ * R5 (0x05) - Audio Interface (2)
+ */
+#define WM8993_AIFDACL_SRC                      0x8000  /* AIFDACL_SRC */
+#define WM8993_AIFDACL_SRC_MASK                 0x8000  /* AIFDACL_SRC */
+#define WM8993_AIFDACL_SRC_SHIFT                    15  /* AIFDACL_SRC */
+#define WM8993_AIFDACL_SRC_WIDTH                     1  /* AIFDACL_SRC */
+#define WM8993_AIFDACR_SRC                      0x4000  /* AIFDACR_SRC */
+#define WM8993_AIFDACR_SRC_MASK                 0x4000  /* AIFDACR_SRC */
+#define WM8993_AIFDACR_SRC_SHIFT                    14  /* AIFDACR_SRC */
+#define WM8993_AIFDACR_SRC_WIDTH                     1  /* AIFDACR_SRC */
+#define WM8993_AIFDAC_TDM                       0x2000  /* AIFDAC_TDM */
+#define WM8993_AIFDAC_TDM_MASK                  0x2000  /* AIFDAC_TDM */
+#define WM8993_AIFDAC_TDM_SHIFT                     13  /* AIFDAC_TDM */
+#define WM8993_AIFDAC_TDM_WIDTH                      1  /* AIFDAC_TDM */
+#define WM8993_AIFDAC_TDM_CHAN                  0x1000  /* AIFDAC_TDM_CHAN */
+#define WM8993_AIFDAC_TDM_CHAN_MASK             0x1000  /* AIFDAC_TDM_CHAN */
+#define WM8993_AIFDAC_TDM_CHAN_SHIFT                12  /* AIFDAC_TDM_CHAN */
+#define WM8993_AIFDAC_TDM_CHAN_WIDTH                 1  /* AIFDAC_TDM_CHAN */
+#define WM8993_DAC_BOOST_MASK                   0x0C00  /* DAC_BOOST - [11:10] */
+#define WM8993_DAC_BOOST_SHIFT                      10  /* DAC_BOOST - [11:10] */
+#define WM8993_DAC_BOOST_WIDTH                       2  /* DAC_BOOST - [11:10] */
+#define WM8993_DAC_COMP                         0x0010  /* DAC_COMP */
+#define WM8993_DAC_COMP_MASK                    0x0010  /* DAC_COMP */
+#define WM8993_DAC_COMP_SHIFT                        4  /* DAC_COMP */
+#define WM8993_DAC_COMP_WIDTH                        1  /* DAC_COMP */
+#define WM8993_DAC_COMPMODE                     0x0008  /* DAC_COMPMODE */
+#define WM8993_DAC_COMPMODE_MASK                0x0008  /* DAC_COMPMODE */
+#define WM8993_DAC_COMPMODE_SHIFT                    3  /* DAC_COMPMODE */
+#define WM8993_DAC_COMPMODE_WIDTH                    1  /* DAC_COMPMODE */
+#define WM8993_ADC_COMP                         0x0004  /* ADC_COMP */
+#define WM8993_ADC_COMP_MASK                    0x0004  /* ADC_COMP */
+#define WM8993_ADC_COMP_SHIFT                        2  /* ADC_COMP */
+#define WM8993_ADC_COMP_WIDTH                        1  /* ADC_COMP */
+#define WM8993_ADC_COMPMODE                     0x0002  /* ADC_COMPMODE */
+#define WM8993_ADC_COMPMODE_MASK                0x0002  /* ADC_COMPMODE */
+#define WM8993_ADC_COMPMODE_SHIFT                    1  /* ADC_COMPMODE */
+#define WM8993_ADC_COMPMODE_WIDTH                    1  /* ADC_COMPMODE */
+#define WM8993_LOOPBACK                         0x0001  /* LOOPBACK */
+#define WM8993_LOOPBACK_MASK                    0x0001  /* LOOPBACK */
+#define WM8993_LOOPBACK_SHIFT                        0  /* LOOPBACK */
+#define WM8993_LOOPBACK_WIDTH                        1  /* LOOPBACK */
+
+/*
+ * R6 (0x06) - Clocking 1
+ */
+#define WM8993_TOCLK_RATE                       0x8000  /* TOCLK_RATE */
+#define WM8993_TOCLK_RATE_MASK                  0x8000  /* TOCLK_RATE */
+#define WM8993_TOCLK_RATE_SHIFT                     15  /* TOCLK_RATE */
+#define WM8993_TOCLK_RATE_WIDTH                      1  /* TOCLK_RATE */
+#define WM8993_TOCLK_ENA                        0x4000  /* TOCLK_ENA */
+#define WM8993_TOCLK_ENA_MASK                   0x4000  /* TOCLK_ENA */
+#define WM8993_TOCLK_ENA_SHIFT                      14  /* TOCLK_ENA */
+#define WM8993_TOCLK_ENA_WIDTH                       1  /* TOCLK_ENA */
+#define WM8993_OPCLK_DIV_MASK                   0x1E00  /* OPCLK_DIV - [12:9] */
+#define WM8993_OPCLK_DIV_SHIFT                       9  /* OPCLK_DIV - [12:9] */
+#define WM8993_OPCLK_DIV_WIDTH                       4  /* OPCLK_DIV - [12:9] */
+#define WM8993_DCLK_DIV_MASK                    0x01C0  /* DCLK_DIV - [8:6] */
+#define WM8993_DCLK_DIV_SHIFT                        6  /* DCLK_DIV - [8:6] */
+#define WM8993_DCLK_DIV_WIDTH                        3  /* DCLK_DIV - [8:6] */
+#define WM8993_BCLK_DIV_MASK                    0x001E  /* BCLK_DIV - [4:1] */
+#define WM8993_BCLK_DIV_SHIFT                        1  /* BCLK_DIV - [4:1] */
+#define WM8993_BCLK_DIV_WIDTH                        4  /* BCLK_DIV - [4:1] */
+
+/*
+ * R7 (0x07) - Clocking 2
+ */
+#define WM8993_MCLK_SRC                         0x8000  /* MCLK_SRC */
+#define WM8993_MCLK_SRC_MASK                    0x8000  /* MCLK_SRC */
+#define WM8993_MCLK_SRC_SHIFT                       15  /* MCLK_SRC */
+#define WM8993_MCLK_SRC_WIDTH                        1  /* MCLK_SRC */
+#define WM8993_SYSCLK_SRC                       0x4000  /* SYSCLK_SRC */
+#define WM8993_SYSCLK_SRC_MASK                  0x4000  /* SYSCLK_SRC */
+#define WM8993_SYSCLK_SRC_SHIFT                     14  /* SYSCLK_SRC */
+#define WM8993_SYSCLK_SRC_WIDTH                      1  /* SYSCLK_SRC */
+#define WM8993_MCLK_DIV                         0x1000  /* MCLK_DIV */
+#define WM8993_MCLK_DIV_MASK                    0x1000  /* MCLK_DIV */
+#define WM8993_MCLK_DIV_SHIFT                       12  /* MCLK_DIV */
+#define WM8993_MCLK_DIV_WIDTH                        1  /* MCLK_DIV */
+#define WM8993_MCLK_INV                         0x0400  /* MCLK_INV */
+#define WM8993_MCLK_INV_MASK                    0x0400  /* MCLK_INV */
+#define WM8993_MCLK_INV_SHIFT                       10  /* MCLK_INV */
+#define WM8993_MCLK_INV_WIDTH                        1  /* MCLK_INV */
+#define WM8993_ADC_DIV_MASK                     0x00E0  /* ADC_DIV - [7:5] */
+#define WM8993_ADC_DIV_SHIFT                         5  /* ADC_DIV - [7:5] */
+#define WM8993_ADC_DIV_WIDTH                         3  /* ADC_DIV - [7:5] */
+#define WM8993_DAC_DIV_MASK                     0x001C  /* DAC_DIV - [4:2] */
+#define WM8993_DAC_DIV_SHIFT                         2  /* DAC_DIV - [4:2] */
+#define WM8993_DAC_DIV_WIDTH                         3  /* DAC_DIV - [4:2] */
+
+/*
+ * R8 (0x08) - Audio Interface (3)
+ */
+#define WM8993_AIF_MSTR1                        0x8000  /* AIF_MSTR1 */
+#define WM8993_AIF_MSTR1_MASK                   0x8000  /* AIF_MSTR1 */
+#define WM8993_AIF_MSTR1_SHIFT                      15  /* AIF_MSTR1 */
+#define WM8993_AIF_MSTR1_WIDTH                       1  /* AIF_MSTR1 */
+
+/*
+ * R9 (0x09) - Audio Interface (4)
+ */
+#define WM8993_AIF_TRIS                         0x2000  /* AIF_TRIS */
+#define WM8993_AIF_TRIS_MASK                    0x2000  /* AIF_TRIS */
+#define WM8993_AIF_TRIS_SHIFT                       13  /* AIF_TRIS */
+#define WM8993_AIF_TRIS_WIDTH                        1  /* AIF_TRIS */
+#define WM8993_LRCLK_DIR                        0x0800  /* LRCLK_DIR */
+#define WM8993_LRCLK_DIR_MASK                   0x0800  /* LRCLK_DIR */
+#define WM8993_LRCLK_DIR_SHIFT                      11  /* LRCLK_DIR */
+#define WM8993_LRCLK_DIR_WIDTH                       1  /* LRCLK_DIR */
+#define WM8993_LRCLK_RATE_MASK                  0x07FF  /* LRCLK_RATE - [10:0] */
+#define WM8993_LRCLK_RATE_SHIFT                      0  /* LRCLK_RATE - [10:0] */
+#define WM8993_LRCLK_RATE_WIDTH                     11  /* LRCLK_RATE - [10:0] */
+
+/*
+ * R10 (0x0A) - DAC CTRL
+ */
+#define WM8993_DAC_OSR128                       0x2000  /* DAC_OSR128 */
+#define WM8993_DAC_OSR128_MASK                  0x2000  /* DAC_OSR128 */
+#define WM8993_DAC_OSR128_SHIFT                     13  /* DAC_OSR128 */
+#define WM8993_DAC_OSR128_WIDTH                      1  /* DAC_OSR128 */
+#define WM8993_DAC_MONO                         0x0200  /* DAC_MONO */
+#define WM8993_DAC_MONO_MASK                    0x0200  /* DAC_MONO */
+#define WM8993_DAC_MONO_SHIFT                        9  /* DAC_MONO */
+#define WM8993_DAC_MONO_WIDTH                        1  /* DAC_MONO */
+#define WM8993_DAC_SB_FILT                      0x0100  /* DAC_SB_FILT */
+#define WM8993_DAC_SB_FILT_MASK                 0x0100  /* DAC_SB_FILT */
+#define WM8993_DAC_SB_FILT_SHIFT                     8  /* DAC_SB_FILT */
+#define WM8993_DAC_SB_FILT_WIDTH                     1  /* DAC_SB_FILT */
+#define WM8993_DAC_MUTERATE                     0x0080  /* DAC_MUTERATE */
+#define WM8993_DAC_MUTERATE_MASK                0x0080  /* DAC_MUTERATE */
+#define WM8993_DAC_MUTERATE_SHIFT                    7  /* DAC_MUTERATE */
+#define WM8993_DAC_MUTERATE_WIDTH                    1  /* DAC_MUTERATE */
+#define WM8993_DAC_UNMUTE_RAMP                  0x0040  /* DAC_UNMUTE_RAMP */
+#define WM8993_DAC_UNMUTE_RAMP_MASK             0x0040  /* DAC_UNMUTE_RAMP */
+#define WM8993_DAC_UNMUTE_RAMP_SHIFT                 6  /* DAC_UNMUTE_RAMP */
+#define WM8993_DAC_UNMUTE_RAMP_WIDTH                 1  /* DAC_UNMUTE_RAMP */
+#define WM8993_DEEMPH_MASK                      0x0030  /* DEEMPH - [5:4] */
+#define WM8993_DEEMPH_SHIFT                          4  /* DEEMPH - [5:4] */
+#define WM8993_DEEMPH_WIDTH                          2  /* DEEMPH - [5:4] */
+#define WM8993_DAC_MUTE                         0x0004  /* DAC_MUTE */
+#define WM8993_DAC_MUTE_MASK                    0x0004  /* DAC_MUTE */
+#define WM8993_DAC_MUTE_SHIFT                        2  /* DAC_MUTE */
+#define WM8993_DAC_MUTE_WIDTH                        1  /* DAC_MUTE */
+#define WM8993_DACL_DATINV                      0x0002  /* DACL_DATINV */
+#define WM8993_DACL_DATINV_MASK                 0x0002  /* DACL_DATINV */
+#define WM8993_DACL_DATINV_SHIFT                     1  /* DACL_DATINV */
+#define WM8993_DACL_DATINV_WIDTH                     1  /* DACL_DATINV */
+#define WM8993_DACR_DATINV                      0x0001  /* DACR_DATINV */
+#define WM8993_DACR_DATINV_MASK                 0x0001  /* DACR_DATINV */
+#define WM8993_DACR_DATINV_SHIFT                     0  /* DACR_DATINV */
+#define WM8993_DACR_DATINV_WIDTH                     1  /* DACR_DATINV */
+
+/*
+ * R11 (0x0B) - Left DAC Digital Volume
+ */
+#define WM8993_DAC_VU                           0x0100  /* DAC_VU */
+#define WM8993_DAC_VU_MASK                      0x0100  /* DAC_VU */
+#define WM8993_DAC_VU_SHIFT                          8  /* DAC_VU */
+#define WM8993_DAC_VU_WIDTH                          1  /* DAC_VU */
+#define WM8993_DACL_VOL_MASK                    0x00FF  /* DACL_VOL - [7:0] */
+#define WM8993_DACL_VOL_SHIFT                        0  /* DACL_VOL - [7:0] */
+#define WM8993_DACL_VOL_WIDTH                        8  /* DACL_VOL - [7:0] */
+
+/*
+ * R12 (0x0C) - Right DAC Digital Volume
+ */
+#define WM8993_DAC_VU                           0x0100  /* DAC_VU */
+#define WM8993_DAC_VU_MASK                      0x0100  /* DAC_VU */
+#define WM8993_DAC_VU_SHIFT                          8  /* DAC_VU */
+#define WM8993_DAC_VU_WIDTH                          1  /* DAC_VU */
+#define WM8993_DACR_VOL_MASK                    0x00FF  /* DACR_VOL - [7:0] */
+#define WM8993_DACR_VOL_SHIFT                        0  /* DACR_VOL - [7:0] */
+#define WM8993_DACR_VOL_WIDTH                        8  /* DACR_VOL - [7:0] */
+
+/*
+ * R13 (0x0D) - Digital Side Tone
+ */
+#define WM8993_ADCL_DAC_SVOL_MASK               0x1E00  /* ADCL_DAC_SVOL - [12:9] */
+#define WM8993_ADCL_DAC_SVOL_SHIFT                   9  /* ADCL_DAC_SVOL - [12:9] */
+#define WM8993_ADCL_DAC_SVOL_WIDTH                   4  /* ADCL_DAC_SVOL - [12:9] */
+#define WM8993_ADCR_DAC_SVOL_MASK               0x01E0  /* ADCR_DAC_SVOL - [8:5] */
+#define WM8993_ADCR_DAC_SVOL_SHIFT                   5  /* ADCR_DAC_SVOL - [8:5] */
+#define WM8993_ADCR_DAC_SVOL_WIDTH                   4  /* ADCR_DAC_SVOL - [8:5] */
+#define WM8993_ADC_TO_DACL_MASK                 0x000C  /* ADC_TO_DACL - [3:2] */
+#define WM8993_ADC_TO_DACL_SHIFT                     2  /* ADC_TO_DACL - [3:2] */
+#define WM8993_ADC_TO_DACL_WIDTH                     2  /* ADC_TO_DACL - [3:2] */
+#define WM8993_ADC_TO_DACR_MASK                 0x0003  /* ADC_TO_DACR - [1:0] */
+#define WM8993_ADC_TO_DACR_SHIFT                     0  /* ADC_TO_DACR - [1:0] */
+#define WM8993_ADC_TO_DACR_WIDTH                     2  /* ADC_TO_DACR - [1:0] */
+
+/*
+ * R14 (0x0E) - ADC CTRL
+ */
+#define WM8993_ADC_OSR128                       0x0200  /* ADC_OSR128 */
+#define WM8993_ADC_OSR128_MASK                  0x0200  /* ADC_OSR128 */
+#define WM8993_ADC_OSR128_SHIFT                      9  /* ADC_OSR128 */
+#define WM8993_ADC_OSR128_WIDTH                      1  /* ADC_OSR128 */
+#define WM8993_ADC_HPF                          0x0100  /* ADC_HPF */
+#define WM8993_ADC_HPF_MASK                     0x0100  /* ADC_HPF */
+#define WM8993_ADC_HPF_SHIFT                         8  /* ADC_HPF */
+#define WM8993_ADC_HPF_WIDTH                         1  /* ADC_HPF */
+#define WM8993_ADC_HPF_CUT_MASK                 0x0060  /* ADC_HPF_CUT - [6:5] */
+#define WM8993_ADC_HPF_CUT_SHIFT                     5  /* ADC_HPF_CUT - [6:5] */
+#define WM8993_ADC_HPF_CUT_WIDTH                     2  /* ADC_HPF_CUT - [6:5] */
+#define WM8993_ADCL_DATINV                      0x0002  /* ADCL_DATINV */
+#define WM8993_ADCL_DATINV_MASK                 0x0002  /* ADCL_DATINV */
+#define WM8993_ADCL_DATINV_SHIFT                     1  /* ADCL_DATINV */
+#define WM8993_ADCL_DATINV_WIDTH                     1  /* ADCL_DATINV */
+#define WM8993_ADCR_DATINV                      0x0001  /* ADCR_DATINV */
+#define WM8993_ADCR_DATINV_MASK                 0x0001  /* ADCR_DATINV */
+#define WM8993_ADCR_DATINV_SHIFT                     0  /* ADCR_DATINV */
+#define WM8993_ADCR_DATINV_WIDTH                     1  /* ADCR_DATINV */
+
+/*
+ * R15 (0x0F) - Left ADC Digital Volume
+ */
+#define WM8993_ADC_VU                           0x0100  /* ADC_VU */
+#define WM8993_ADC_VU_MASK                      0x0100  /* ADC_VU */
+#define WM8993_ADC_VU_SHIFT                          8  /* ADC_VU */
+#define WM8993_ADC_VU_WIDTH                          1  /* ADC_VU */
+#define WM8993_ADCL_VOL_MASK                    0x00FF  /* ADCL_VOL - [7:0] */
+#define WM8993_ADCL_VOL_SHIFT                        0  /* ADCL_VOL - [7:0] */
+#define WM8993_ADCL_VOL_WIDTH                        8  /* ADCL_VOL - [7:0] */
+
+/*
+ * R16 (0x10) - Right ADC Digital Volume
+ */
+#define WM8993_ADC_VU                           0x0100  /* ADC_VU */
+#define WM8993_ADC_VU_MASK                      0x0100  /* ADC_VU */
+#define WM8993_ADC_VU_SHIFT                          8  /* ADC_VU */
+#define WM8993_ADC_VU_WIDTH                          1  /* ADC_VU */
+#define WM8993_ADCR_VOL_MASK                    0x00FF  /* ADCR_VOL - [7:0] */
+#define WM8993_ADCR_VOL_SHIFT                        0  /* ADCR_VOL - [7:0] */
+#define WM8993_ADCR_VOL_WIDTH                        8  /* ADCR_VOL - [7:0] */
+
+/*
+ * R18 (0x12) - GPIO CTRL 1
+ */
+#define WM8993_JD2_SC_EINT                      0x8000  /* JD2_SC_EINT */
+#define WM8993_JD2_SC_EINT_MASK                 0x8000  /* JD2_SC_EINT */
+#define WM8993_JD2_SC_EINT_SHIFT                    15  /* JD2_SC_EINT */
+#define WM8993_JD2_SC_EINT_WIDTH                     1  /* JD2_SC_EINT */
+#define WM8993_JD2_EINT                         0x4000  /* JD2_EINT */
+#define WM8993_JD2_EINT_MASK                    0x4000  /* JD2_EINT */
+#define WM8993_JD2_EINT_SHIFT                       14  /* JD2_EINT */
+#define WM8993_JD2_EINT_WIDTH                        1  /* JD2_EINT */
+#define WM8993_WSEQ_EINT                        0x2000  /* WSEQ_EINT */
+#define WM8993_WSEQ_EINT_MASK                   0x2000  /* WSEQ_EINT */
+#define WM8993_WSEQ_EINT_SHIFT                      13  /* WSEQ_EINT */
+#define WM8993_WSEQ_EINT_WIDTH                       1  /* WSEQ_EINT */
+#define WM8993_IRQ                              0x1000  /* IRQ */
+#define WM8993_IRQ_MASK                         0x1000  /* IRQ */
+#define WM8993_IRQ_SHIFT                            12  /* IRQ */
+#define WM8993_IRQ_WIDTH                             1  /* IRQ */
+#define WM8993_TEMPOK_EINT                      0x0800  /* TEMPOK_EINT */
+#define WM8993_TEMPOK_EINT_MASK                 0x0800  /* TEMPOK_EINT */
+#define WM8993_TEMPOK_EINT_SHIFT                    11  /* TEMPOK_EINT */
+#define WM8993_TEMPOK_EINT_WIDTH                     1  /* TEMPOK_EINT */
+#define WM8993_JD1_SC_EINT                      0x0400  /* JD1_SC_EINT */
+#define WM8993_JD1_SC_EINT_MASK                 0x0400  /* JD1_SC_EINT */
+#define WM8993_JD1_SC_EINT_SHIFT                    10  /* JD1_SC_EINT */
+#define WM8993_JD1_SC_EINT_WIDTH                     1  /* JD1_SC_EINT */
+#define WM8993_JD1_EINT                         0x0200  /* JD1_EINT */
+#define WM8993_JD1_EINT_MASK                    0x0200  /* JD1_EINT */
+#define WM8993_JD1_EINT_SHIFT                        9  /* JD1_EINT */
+#define WM8993_JD1_EINT_WIDTH                        1  /* JD1_EINT */
+#define WM8993_FLL_LOCK_EINT                    0x0100  /* FLL_LOCK_EINT */
+#define WM8993_FLL_LOCK_EINT_MASK               0x0100  /* FLL_LOCK_EINT */
+#define WM8993_FLL_LOCK_EINT_SHIFT                   8  /* FLL_LOCK_EINT */
+#define WM8993_FLL_LOCK_EINT_WIDTH                   1  /* FLL_LOCK_EINT */
+#define WM8993_GPI8_EINT                        0x0080  /* GPI8_EINT */
+#define WM8993_GPI8_EINT_MASK                   0x0080  /* GPI8_EINT */
+#define WM8993_GPI8_EINT_SHIFT                       7  /* GPI8_EINT */
+#define WM8993_GPI8_EINT_WIDTH                       1  /* GPI8_EINT */
+#define WM8993_GPI7_EINT                        0x0040  /* GPI7_EINT */
+#define WM8993_GPI7_EINT_MASK                   0x0040  /* GPI7_EINT */
+#define WM8993_GPI7_EINT_SHIFT                       6  /* GPI7_EINT */
+#define WM8993_GPI7_EINT_WIDTH                       1  /* GPI7_EINT */
+#define WM8993_GPIO1_EINT                       0x0001  /* GPIO1_EINT */
+#define WM8993_GPIO1_EINT_MASK                  0x0001  /* GPIO1_EINT */
+#define WM8993_GPIO1_EINT_SHIFT                      0  /* GPIO1_EINT */
+#define WM8993_GPIO1_EINT_WIDTH                      1  /* GPIO1_EINT */
+
+/*
+ * R19 (0x13) - GPIO1
+ */
+#define WM8993_GPIO1_PU                         0x0020  /* GPIO1_PU */
+#define WM8993_GPIO1_PU_MASK                    0x0020  /* GPIO1_PU */
+#define WM8993_GPIO1_PU_SHIFT                        5  /* GPIO1_PU */
+#define WM8993_GPIO1_PU_WIDTH                        1  /* GPIO1_PU */
+#define WM8993_GPIO1_PD                         0x0010  /* GPIO1_PD */
+#define WM8993_GPIO1_PD_MASK                    0x0010  /* GPIO1_PD */
+#define WM8993_GPIO1_PD_SHIFT                        4  /* GPIO1_PD */
+#define WM8993_GPIO1_PD_WIDTH                        1  /* GPIO1_PD */
+#define WM8993_GPIO1_SEL_MASK                   0x000F  /* GPIO1_SEL - [3:0] */
+#define WM8993_GPIO1_SEL_SHIFT                       0  /* GPIO1_SEL - [3:0] */
+#define WM8993_GPIO1_SEL_WIDTH                       4  /* GPIO1_SEL - [3:0] */
+
+/*
+ * R20 (0x14) - IRQ_DEBOUNCE
+ */
+#define WM8993_JD2_SC_DB                        0x8000  /* JD2_SC_DB */
+#define WM8993_JD2_SC_DB_MASK                   0x8000  /* JD2_SC_DB */
+#define WM8993_JD2_SC_DB_SHIFT                      15  /* JD2_SC_DB */
+#define WM8993_JD2_SC_DB_WIDTH                       1  /* JD2_SC_DB */
+#define WM8993_JD2_DB                           0x4000  /* JD2_DB */
+#define WM8993_JD2_DB_MASK                      0x4000  /* JD2_DB */
+#define WM8993_JD2_DB_SHIFT                         14  /* JD2_DB */
+#define WM8993_JD2_DB_WIDTH                          1  /* JD2_DB */
+#define WM8993_WSEQ_DB                          0x2000  /* WSEQ_DB */
+#define WM8993_WSEQ_DB_MASK                     0x2000  /* WSEQ_DB */
+#define WM8993_WSEQ_DB_SHIFT                        13  /* WSEQ_DB */
+#define WM8993_WSEQ_DB_WIDTH                         1  /* WSEQ_DB */
+#define WM8993_TEMPOK_DB                        0x0800  /* TEMPOK_DB */
+#define WM8993_TEMPOK_DB_MASK                   0x0800  /* TEMPOK_DB */
+#define WM8993_TEMPOK_DB_SHIFT                      11  /* TEMPOK_DB */
+#define WM8993_TEMPOK_DB_WIDTH                       1  /* TEMPOK_DB */
+#define WM8993_JD1_SC_DB                        0x0400  /* JD1_SC_DB */
+#define WM8993_JD1_SC_DB_MASK                   0x0400  /* JD1_SC_DB */
+#define WM8993_JD1_SC_DB_SHIFT                      10  /* JD1_SC_DB */
+#define WM8993_JD1_SC_DB_WIDTH                       1  /* JD1_SC_DB */
+#define WM8993_JD1_DB                           0x0200  /* JD1_DB */
+#define WM8993_JD1_DB_MASK                      0x0200  /* JD1_DB */
+#define WM8993_JD1_DB_SHIFT                          9  /* JD1_DB */
+#define WM8993_JD1_DB_WIDTH                          1  /* JD1_DB */
+#define WM8993_FLL_LOCK_DB                      0x0100  /* FLL_LOCK_DB */
+#define WM8993_FLL_LOCK_DB_MASK                 0x0100  /* FLL_LOCK_DB */
+#define WM8993_FLL_LOCK_DB_SHIFT                     8  /* FLL_LOCK_DB */
+#define WM8993_FLL_LOCK_DB_WIDTH                     1  /* FLL_LOCK_DB */
+#define WM8993_GPI8_DB                          0x0080  /* GPI8_DB */
+#define WM8993_GPI8_DB_MASK                     0x0080  /* GPI8_DB */
+#define WM8993_GPI8_DB_SHIFT                         7  /* GPI8_DB */
+#define WM8993_GPI8_DB_WIDTH                         1  /* GPI8_DB */
+#define WM8993_GPI7_DB                          0x0008  /* GPI7_DB */
+#define WM8993_GPI7_DB_MASK                     0x0008  /* GPI7_DB */
+#define WM8993_GPI7_DB_SHIFT                         3  /* GPI7_DB */
+#define WM8993_GPI7_DB_WIDTH                         1  /* GPI7_DB */
+#define WM8993_GPIO1_DB                         0x0001  /* GPIO1_DB */
+#define WM8993_GPIO1_DB_MASK                    0x0001  /* GPIO1_DB */
+#define WM8993_GPIO1_DB_SHIFT                        0  /* GPIO1_DB */
+#define WM8993_GPIO1_DB_WIDTH                        1  /* GPIO1_DB */
+
+/*
+ * R22 (0x16) - GPIOCTRL 2
+ */
+#define WM8993_IM_JD2_EINT                      0x2000  /* IM_JD2_EINT */
+#define WM8993_IM_JD2_EINT_MASK                 0x2000  /* IM_JD2_EINT */
+#define WM8993_IM_JD2_EINT_SHIFT                    13  /* IM_JD2_EINT */
+#define WM8993_IM_JD2_EINT_WIDTH                     1  /* IM_JD2_EINT */
+#define WM8993_IM_JD2_SC_EINT                   0x1000  /* IM_JD2_SC_EINT */
+#define WM8993_IM_JD2_SC_EINT_MASK              0x1000  /* IM_JD2_SC_EINT */
+#define WM8993_IM_JD2_SC_EINT_SHIFT                 12  /* IM_JD2_SC_EINT */
+#define WM8993_IM_JD2_SC_EINT_WIDTH                  1  /* IM_JD2_SC_EINT */
+#define WM8993_IM_TEMPOK_EINT                   0x0800  /* IM_TEMPOK_EINT */
+#define WM8993_IM_TEMPOK_EINT_MASK              0x0800  /* IM_TEMPOK_EINT */
+#define WM8993_IM_TEMPOK_EINT_SHIFT                 11  /* IM_TEMPOK_EINT */
+#define WM8993_IM_TEMPOK_EINT_WIDTH                  1  /* IM_TEMPOK_EINT */
+#define WM8993_IM_JD1_SC_EINT                   0x0400  /* IM_JD1_SC_EINT */
+#define WM8993_IM_JD1_SC_EINT_MASK              0x0400  /* IM_JD1_SC_EINT */
+#define WM8993_IM_JD1_SC_EINT_SHIFT                 10  /* IM_JD1_SC_EINT */
+#define WM8993_IM_JD1_SC_EINT_WIDTH                  1  /* IM_JD1_SC_EINT */
+#define WM8993_IM_JD1_EINT                      0x0200  /* IM_JD1_EINT */
+#define WM8993_IM_JD1_EINT_MASK                 0x0200  /* IM_JD1_EINT */
+#define WM8993_IM_JD1_EINT_SHIFT                     9  /* IM_JD1_EINT */
+#define WM8993_IM_JD1_EINT_WIDTH                     1  /* IM_JD1_EINT */
+#define WM8993_IM_FLL_LOCK_EINT                 0x0100  /* IM_FLL_LOCK_EINT */
+#define WM8993_IM_FLL_LOCK_EINT_MASK            0x0100  /* IM_FLL_LOCK_EINT */
+#define WM8993_IM_FLL_LOCK_EINT_SHIFT                8  /* IM_FLL_LOCK_EINT */
+#define WM8993_IM_FLL_LOCK_EINT_WIDTH                1  /* IM_FLL_LOCK_EINT */
+#define WM8993_IM_GPI8_EINT                     0x0040  /* IM_GPI8_EINT */
+#define WM8993_IM_GPI8_EINT_MASK                0x0040  /* IM_GPI8_EINT */
+#define WM8993_IM_GPI8_EINT_SHIFT                    6  /* IM_GPI8_EINT */
+#define WM8993_IM_GPI8_EINT_WIDTH                    1  /* IM_GPI8_EINT */
+#define WM8993_IM_GPIO1_EINT                    0x0020  /* IM_GPIO1_EINT */
+#define WM8993_IM_GPIO1_EINT_MASK               0x0020  /* IM_GPIO1_EINT */
+#define WM8993_IM_GPIO1_EINT_SHIFT                   5  /* IM_GPIO1_EINT */
+#define WM8993_IM_GPIO1_EINT_WIDTH                   1  /* IM_GPIO1_EINT */
+#define WM8993_GPI8_ENA                         0x0010  /* GPI8_ENA */
+#define WM8993_GPI8_ENA_MASK                    0x0010  /* GPI8_ENA */
+#define WM8993_GPI8_ENA_SHIFT                        4  /* GPI8_ENA */
+#define WM8993_GPI8_ENA_WIDTH                        1  /* GPI8_ENA */
+#define WM8993_IM_GPI7_EINT                     0x0004  /* IM_GPI7_EINT */
+#define WM8993_IM_GPI7_EINT_MASK                0x0004  /* IM_GPI7_EINT */
+#define WM8993_IM_GPI7_EINT_SHIFT                    2  /* IM_GPI7_EINT */
+#define WM8993_IM_GPI7_EINT_WIDTH                    1  /* IM_GPI7_EINT */
+#define WM8993_IM_WSEQ_EINT                     0x0002  /* IM_WSEQ_EINT */
+#define WM8993_IM_WSEQ_EINT_MASK                0x0002  /* IM_WSEQ_EINT */
+#define WM8993_IM_WSEQ_EINT_SHIFT                    1  /* IM_WSEQ_EINT */
+#define WM8993_IM_WSEQ_EINT_WIDTH                    1  /* IM_WSEQ_EINT */
+#define WM8993_GPI7_ENA                         0x0001  /* GPI7_ENA */
+#define WM8993_GPI7_ENA_MASK                    0x0001  /* GPI7_ENA */
+#define WM8993_GPI7_ENA_SHIFT                        0  /* GPI7_ENA */
+#define WM8993_GPI7_ENA_WIDTH                        1  /* GPI7_ENA */
+
+/*
+ * R23 (0x17) - GPIO_POL
+ */
+#define WM8993_JD2_SC_POL                       0x8000  /* JD2_SC_POL */
+#define WM8993_JD2_SC_POL_MASK                  0x8000  /* JD2_SC_POL */
+#define WM8993_JD2_SC_POL_SHIFT                     15  /* JD2_SC_POL */
+#define WM8993_JD2_SC_POL_WIDTH                      1  /* JD2_SC_POL */
+#define WM8993_JD2_POL                          0x4000  /* JD2_POL */
+#define WM8993_JD2_POL_MASK                     0x4000  /* JD2_POL */
+#define WM8993_JD2_POL_SHIFT                        14  /* JD2_POL */
+#define WM8993_JD2_POL_WIDTH                         1  /* JD2_POL */
+#define WM8993_WSEQ_POL                         0x2000  /* WSEQ_POL */
+#define WM8993_WSEQ_POL_MASK                    0x2000  /* WSEQ_POL */
+#define WM8993_WSEQ_POL_SHIFT                       13  /* WSEQ_POL */
+#define WM8993_WSEQ_POL_WIDTH                        1  /* WSEQ_POL */
+#define WM8993_IRQ_POL                          0x1000  /* IRQ_POL */
+#define WM8993_IRQ_POL_MASK                     0x1000  /* IRQ_POL */
+#define WM8993_IRQ_POL_SHIFT                        12  /* IRQ_POL */
+#define WM8993_IRQ_POL_WIDTH                         1  /* IRQ_POL */
+#define WM8993_TEMPOK_POL                       0x0800  /* TEMPOK_POL */
+#define WM8993_TEMPOK_POL_MASK                  0x0800  /* TEMPOK_POL */
+#define WM8993_TEMPOK_POL_SHIFT                     11  /* TEMPOK_POL */
+#define WM8993_TEMPOK_POL_WIDTH                      1  /* TEMPOK_POL */
+#define WM8993_JD1_SC_POL                       0x0400  /* JD1_SC_POL */
+#define WM8993_JD1_SC_POL_MASK                  0x0400  /* JD1_SC_POL */
+#define WM8993_JD1_SC_POL_SHIFT                     10  /* JD1_SC_POL */
+#define WM8993_JD1_SC_POL_WIDTH                      1  /* JD1_SC_POL */
+#define WM8993_JD1_POL                          0x0200  /* JD1_POL */
+#define WM8993_JD1_POL_MASK                     0x0200  /* JD1_POL */
+#define WM8993_JD1_POL_SHIFT                         9  /* JD1_POL */
+#define WM8993_JD1_POL_WIDTH                         1  /* JD1_POL */
+#define WM8993_FLL_LOCK_POL                     0x0100  /* FLL_LOCK_POL */
+#define WM8993_FLL_LOCK_POL_MASK                0x0100  /* FLL_LOCK_POL */
+#define WM8993_FLL_LOCK_POL_SHIFT                    8  /* FLL_LOCK_POL */
+#define WM8993_FLL_LOCK_POL_WIDTH                    1  /* FLL_LOCK_POL */
+#define WM8993_GPI8_POL                         0x0080  /* GPI8_POL */
+#define WM8993_GPI8_POL_MASK                    0x0080  /* GPI8_POL */
+#define WM8993_GPI8_POL_SHIFT                        7  /* GPI8_POL */
+#define WM8993_GPI8_POL_WIDTH                        1  /* GPI8_POL */
+#define WM8993_GPI7_POL                         0x0040  /* GPI7_POL */
+#define WM8993_GPI7_POL_MASK                    0x0040  /* GPI7_POL */
+#define WM8993_GPI7_POL_SHIFT                        6  /* GPI7_POL */
+#define WM8993_GPI7_POL_WIDTH                        1  /* GPI7_POL */
+#define WM8993_GPIO1_POL                        0x0001  /* GPIO1_POL */
+#define WM8993_GPIO1_POL_MASK                   0x0001  /* GPIO1_POL */
+#define WM8993_GPIO1_POL_SHIFT                       0  /* GPIO1_POL */
+#define WM8993_GPIO1_POL_WIDTH                       1  /* GPIO1_POL */
+
+/*
+ * R24 (0x18) - Left Line Input 1&2 Volume
+ */
+#define WM8993_IN1_VU                           0x0100  /* IN1_VU */
+#define WM8993_IN1_VU_MASK                      0x0100  /* IN1_VU */
+#define WM8993_IN1_VU_SHIFT                          8  /* IN1_VU */
+#define WM8993_IN1_VU_WIDTH                          1  /* IN1_VU */
+#define WM8993_IN1L_MUTE                        0x0080  /* IN1L_MUTE */
+#define WM8993_IN1L_MUTE_MASK                   0x0080  /* IN1L_MUTE */
+#define WM8993_IN1L_MUTE_SHIFT                       7  /* IN1L_MUTE */
+#define WM8993_IN1L_MUTE_WIDTH                       1  /* IN1L_MUTE */
+#define WM8993_IN1L_ZC                          0x0040  /* IN1L_ZC */
+#define WM8993_IN1L_ZC_MASK                     0x0040  /* IN1L_ZC */
+#define WM8993_IN1L_ZC_SHIFT                         6  /* IN1L_ZC */
+#define WM8993_IN1L_ZC_WIDTH                         1  /* IN1L_ZC */
+#define WM8993_IN1L_VOL_MASK                    0x001F  /* IN1L_VOL - [4:0] */
+#define WM8993_IN1L_VOL_SHIFT                        0  /* IN1L_VOL - [4:0] */
+#define WM8993_IN1L_VOL_WIDTH                        5  /* IN1L_VOL - [4:0] */
+
+/*
+ * R25 (0x19) - Left Line Input 3&4 Volume
+ */
+#define WM8993_IN2_VU                           0x0100  /* IN2_VU */
+#define WM8993_IN2_VU_MASK                      0x0100  /* IN2_VU */
+#define WM8993_IN2_VU_SHIFT                          8  /* IN2_VU */
+#define WM8993_IN2_VU_WIDTH                          1  /* IN2_VU */
+#define WM8993_IN2L_MUTE                        0x0080  /* IN2L_MUTE */
+#define WM8993_IN2L_MUTE_MASK                   0x0080  /* IN2L_MUTE */
+#define WM8993_IN2L_MUTE_SHIFT                       7  /* IN2L_MUTE */
+#define WM8993_IN2L_MUTE_WIDTH                       1  /* IN2L_MUTE */
+#define WM8993_IN2L_ZC                          0x0040  /* IN2L_ZC */
+#define WM8993_IN2L_ZC_MASK                     0x0040  /* IN2L_ZC */
+#define WM8993_IN2L_ZC_SHIFT                         6  /* IN2L_ZC */
+#define WM8993_IN2L_ZC_WIDTH                         1  /* IN2L_ZC */
+#define WM8993_IN2L_VOL_MASK                    0x001F  /* IN2L_VOL - [4:0] */
+#define WM8993_IN2L_VOL_SHIFT                        0  /* IN2L_VOL - [4:0] */
+#define WM8993_IN2L_VOL_WIDTH                        5  /* IN2L_VOL - [4:0] */
+
+/*
+ * R26 (0x1A) - Right Line Input 1&2 Volume
+ */
+#define WM8993_IN1_VU                           0x0100  /* IN1_VU */
+#define WM8993_IN1_VU_MASK                      0x0100  /* IN1_VU */
+#define WM8993_IN1_VU_SHIFT                          8  /* IN1_VU */
+#define WM8993_IN1_VU_WIDTH                          1  /* IN1_VU */
+#define WM8993_IN1R_MUTE                        0x0080  /* IN1R_MUTE */
+#define WM8993_IN1R_MUTE_MASK                   0x0080  /* IN1R_MUTE */
+#define WM8993_IN1R_MUTE_SHIFT                       7  /* IN1R_MUTE */
+#define WM8993_IN1R_MUTE_WIDTH                       1  /* IN1R_MUTE */
+#define WM8993_IN1R_ZC                          0x0040  /* IN1R_ZC */
+#define WM8993_IN1R_ZC_MASK                     0x0040  /* IN1R_ZC */
+#define WM8993_IN1R_ZC_SHIFT                         6  /* IN1R_ZC */
+#define WM8993_IN1R_ZC_WIDTH                         1  /* IN1R_ZC */
+#define WM8993_IN1R_VOL_MASK                    0x001F  /* IN1R_VOL - [4:0] */
+#define WM8993_IN1R_VOL_SHIFT                        0  /* IN1R_VOL - [4:0] */
+#define WM8993_IN1R_VOL_WIDTH                        5  /* IN1R_VOL - [4:0] */
+
+/*
+ * R27 (0x1B) - Right Line Input 3&4 Volume
+ */
+#define WM8993_IN2_VU                           0x0100  /* IN2_VU */
+#define WM8993_IN2_VU_MASK                      0x0100  /* IN2_VU */
+#define WM8993_IN2_VU_SHIFT                          8  /* IN2_VU */
+#define WM8993_IN2_VU_WIDTH                          1  /* IN2_VU */
+#define WM8993_IN2R_MUTE                        0x0080  /* IN2R_MUTE */
+#define WM8993_IN2R_MUTE_MASK                   0x0080  /* IN2R_MUTE */
+#define WM8993_IN2R_MUTE_SHIFT                       7  /* IN2R_MUTE */
+#define WM8993_IN2R_MUTE_WIDTH                       1  /* IN2R_MUTE */
+#define WM8993_IN2R_ZC                          0x0040  /* IN2R_ZC */
+#define WM8993_IN2R_ZC_MASK                     0x0040  /* IN2R_ZC */
+#define WM8993_IN2R_ZC_SHIFT                         6  /* IN2R_ZC */
+#define WM8993_IN2R_ZC_WIDTH                         1  /* IN2R_ZC */
+#define WM8993_IN2R_VOL_MASK                    0x001F  /* IN2R_VOL - [4:0] */
+#define WM8993_IN2R_VOL_SHIFT                        0  /* IN2R_VOL - [4:0] */
+#define WM8993_IN2R_VOL_WIDTH                        5  /* IN2R_VOL - [4:0] */
+
+/*
+ * R28 (0x1C) - Left Output Volume
+ */
+#define WM8993_HPOUT1_VU                        0x0100  /* HPOUT1_VU */
+#define WM8993_HPOUT1_VU_MASK                   0x0100  /* HPOUT1_VU */
+#define WM8993_HPOUT1_VU_SHIFT                       8  /* HPOUT1_VU */
+#define WM8993_HPOUT1_VU_WIDTH                       1  /* HPOUT1_VU */
+#define WM8993_HPOUT1L_ZC                       0x0080  /* HPOUT1L_ZC */
+#define WM8993_HPOUT1L_ZC_MASK                  0x0080  /* HPOUT1L_ZC */
+#define WM8993_HPOUT1L_ZC_SHIFT                      7  /* HPOUT1L_ZC */
+#define WM8993_HPOUT1L_ZC_WIDTH                      1  /* HPOUT1L_ZC */
+#define WM8993_HPOUT1L_MUTE_N                   0x0040  /* HPOUT1L_MUTE_N */
+#define WM8993_HPOUT1L_MUTE_N_MASK              0x0040  /* HPOUT1L_MUTE_N */
+#define WM8993_HPOUT1L_MUTE_N_SHIFT                  6  /* HPOUT1L_MUTE_N */
+#define WM8993_HPOUT1L_MUTE_N_WIDTH                  1  /* HPOUT1L_MUTE_N */
+#define WM8993_HPOUT1L_VOL_MASK                 0x003F  /* HPOUT1L_VOL - [5:0] */
+#define WM8993_HPOUT1L_VOL_SHIFT                     0  /* HPOUT1L_VOL - [5:0] */
+#define WM8993_HPOUT1L_VOL_WIDTH                     6  /* HPOUT1L_VOL - [5:0] */
+
+/*
+ * R29 (0x1D) - Right Output Volume
+ */
+#define WM8993_HPOUT1_VU                        0x0100  /* HPOUT1_VU */
+#define WM8993_HPOUT1_VU_MASK                   0x0100  /* HPOUT1_VU */
+#define WM8993_HPOUT1_VU_SHIFT                       8  /* HPOUT1_VU */
+#define WM8993_HPOUT1_VU_WIDTH                       1  /* HPOUT1_VU */
+#define WM8993_HPOUT1R_ZC                       0x0080  /* HPOUT1R_ZC */
+#define WM8993_HPOUT1R_ZC_MASK                  0x0080  /* HPOUT1R_ZC */
+#define WM8993_HPOUT1R_ZC_SHIFT                      7  /* HPOUT1R_ZC */
+#define WM8993_HPOUT1R_ZC_WIDTH                      1  /* HPOUT1R_ZC */
+#define WM8993_HPOUT1R_MUTE_N                   0x0040  /* HPOUT1R_MUTE_N */
+#define WM8993_HPOUT1R_MUTE_N_MASK              0x0040  /* HPOUT1R_MUTE_N */
+#define WM8993_HPOUT1R_MUTE_N_SHIFT                  6  /* HPOUT1R_MUTE_N */
+#define WM8993_HPOUT1R_MUTE_N_WIDTH                  1  /* HPOUT1R_MUTE_N */
+#define WM8993_HPOUT1R_VOL_MASK                 0x003F  /* HPOUT1R_VOL - [5:0] */
+#define WM8993_HPOUT1R_VOL_SHIFT                     0  /* HPOUT1R_VOL - [5:0] */
+#define WM8993_HPOUT1R_VOL_WIDTH                     6  /* HPOUT1R_VOL - [5:0] */
+
+/*
+ * R30 (0x1E) - Line Outputs Volume
+ */
+#define WM8993_LINEOUT1N_MUTE                   0x0040  /* LINEOUT1N_MUTE */
+#define WM8993_LINEOUT1N_MUTE_MASK              0x0040  /* LINEOUT1N_MUTE */
+#define WM8993_LINEOUT1N_MUTE_SHIFT                  6  /* LINEOUT1N_MUTE */
+#define WM8993_LINEOUT1N_MUTE_WIDTH                  1  /* LINEOUT1N_MUTE */
+#define WM8993_LINEOUT1P_MUTE                   0x0020  /* LINEOUT1P_MUTE */
+#define WM8993_LINEOUT1P_MUTE_MASK              0x0020  /* LINEOUT1P_MUTE */
+#define WM8993_LINEOUT1P_MUTE_SHIFT                  5  /* LINEOUT1P_MUTE */
+#define WM8993_LINEOUT1P_MUTE_WIDTH                  1  /* LINEOUT1P_MUTE */
+#define WM8993_LINEOUT1_VOL                     0x0010  /* LINEOUT1_VOL */
+#define WM8993_LINEOUT1_VOL_MASK                0x0010  /* LINEOUT1_VOL */
+#define WM8993_LINEOUT1_VOL_SHIFT                    4  /* LINEOUT1_VOL */
+#define WM8993_LINEOUT1_VOL_WIDTH                    1  /* LINEOUT1_VOL */
+#define WM8993_LINEOUT2N_MUTE                   0x0004  /* LINEOUT2N_MUTE */
+#define WM8993_LINEOUT2N_MUTE_MASK              0x0004  /* LINEOUT2N_MUTE */
+#define WM8993_LINEOUT2N_MUTE_SHIFT                  2  /* LINEOUT2N_MUTE */
+#define WM8993_LINEOUT2N_MUTE_WIDTH                  1  /* LINEOUT2N_MUTE */
+#define WM8993_LINEOUT2P_MUTE                   0x0002  /* LINEOUT2P_MUTE */
+#define WM8993_LINEOUT2P_MUTE_MASK              0x0002  /* LINEOUT2P_MUTE */
+#define WM8993_LINEOUT2P_MUTE_SHIFT                  1  /* LINEOUT2P_MUTE */
+#define WM8993_LINEOUT2P_MUTE_WIDTH                  1  /* LINEOUT2P_MUTE */
+#define WM8993_LINEOUT2_VOL                     0x0001  /* LINEOUT2_VOL */
+#define WM8993_LINEOUT2_VOL_MASK                0x0001  /* LINEOUT2_VOL */
+#define WM8993_LINEOUT2_VOL_SHIFT                    0  /* LINEOUT2_VOL */
+#define WM8993_LINEOUT2_VOL_WIDTH                    1  /* LINEOUT2_VOL */
+
+/*
+ * R31 (0x1F) - HPOUT2 Volume
+ */
+#define WM8993_HPOUT2_MUTE                      0x0020  /* HPOUT2_MUTE */
+#define WM8993_HPOUT2_MUTE_MASK                 0x0020  /* HPOUT2_MUTE */
+#define WM8993_HPOUT2_MUTE_SHIFT                     5  /* HPOUT2_MUTE */
+#define WM8993_HPOUT2_MUTE_WIDTH                     1  /* HPOUT2_MUTE */
+#define WM8993_HPOUT2_VOL                       0x0010  /* HPOUT2_VOL */
+#define WM8993_HPOUT2_VOL_MASK                  0x0010  /* HPOUT2_VOL */
+#define WM8993_HPOUT2_VOL_SHIFT                      4  /* HPOUT2_VOL */
+#define WM8993_HPOUT2_VOL_WIDTH                      1  /* HPOUT2_VOL */
+
+/*
+ * R32 (0x20) - Left OPGA Volume
+ */
+#define WM8993_MIXOUT_VU                        0x0100  /* MIXOUT_VU */
+#define WM8993_MIXOUT_VU_MASK                   0x0100  /* MIXOUT_VU */
+#define WM8993_MIXOUT_VU_SHIFT                       8  /* MIXOUT_VU */
+#define WM8993_MIXOUT_VU_WIDTH                       1  /* MIXOUT_VU */
+#define WM8993_MIXOUTL_ZC                       0x0080  /* MIXOUTL_ZC */
+#define WM8993_MIXOUTL_ZC_MASK                  0x0080  /* MIXOUTL_ZC */
+#define WM8993_MIXOUTL_ZC_SHIFT                      7  /* MIXOUTL_ZC */
+#define WM8993_MIXOUTL_ZC_WIDTH                      1  /* MIXOUTL_ZC */
+#define WM8993_MIXOUTL_MUTE_N                   0x0040  /* MIXOUTL_MUTE_N */
+#define WM8993_MIXOUTL_MUTE_N_MASK              0x0040  /* MIXOUTL_MUTE_N */
+#define WM8993_MIXOUTL_MUTE_N_SHIFT                  6  /* MIXOUTL_MUTE_N */
+#define WM8993_MIXOUTL_MUTE_N_WIDTH                  1  /* MIXOUTL_MUTE_N */
+#define WM8993_MIXOUTL_VOL_MASK                 0x003F  /* MIXOUTL_VOL - [5:0] */
+#define WM8993_MIXOUTL_VOL_SHIFT                     0  /* MIXOUTL_VOL - [5:0] */
+#define WM8993_MIXOUTL_VOL_WIDTH                     6  /* MIXOUTL_VOL - [5:0] */
+
+/*
+ * R33 (0x21) - Right OPGA Volume
+ */
+#define WM8993_MIXOUT_VU                        0x0100  /* MIXOUT_VU */
+#define WM8993_MIXOUT_VU_MASK                   0x0100  /* MIXOUT_VU */
+#define WM8993_MIXOUT_VU_SHIFT                       8  /* MIXOUT_VU */
+#define WM8993_MIXOUT_VU_WIDTH                       1  /* MIXOUT_VU */
+#define WM8993_MIXOUTR_ZC                       0x0080  /* MIXOUTR_ZC */
+#define WM8993_MIXOUTR_ZC_MASK                  0x0080  /* MIXOUTR_ZC */
+#define WM8993_MIXOUTR_ZC_SHIFT                      7  /* MIXOUTR_ZC */
+#define WM8993_MIXOUTR_ZC_WIDTH                      1  /* MIXOUTR_ZC */
+#define WM8993_MIXOUTR_MUTE_N                   0x0040  /* MIXOUTR_MUTE_N */
+#define WM8993_MIXOUTR_MUTE_N_MASK              0x0040  /* MIXOUTR_MUTE_N */
+#define WM8993_MIXOUTR_MUTE_N_SHIFT                  6  /* MIXOUTR_MUTE_N */
+#define WM8993_MIXOUTR_MUTE_N_WIDTH                  1  /* MIXOUTR_MUTE_N */
+#define WM8993_MIXOUTR_VOL_MASK                 0x003F  /* MIXOUTR_VOL - [5:0] */
+#define WM8993_MIXOUTR_VOL_SHIFT                     0  /* MIXOUTR_VOL - [5:0] */
+#define WM8993_MIXOUTR_VOL_WIDTH                     6  /* MIXOUTR_VOL - [5:0] */
+
+/*
+ * R34 (0x22) - SPKMIXL Attenuation
+ */
+#define WM8993_MIXINL_SPKMIXL_VOL               0x0020  /* MIXINL_SPKMIXL_VOL */
+#define WM8993_MIXINL_SPKMIXL_VOL_MASK          0x0020  /* MIXINL_SPKMIXL_VOL */
+#define WM8993_MIXINL_SPKMIXL_VOL_SHIFT              5  /* MIXINL_SPKMIXL_VOL */
+#define WM8993_MIXINL_SPKMIXL_VOL_WIDTH              1  /* MIXINL_SPKMIXL_VOL */
+#define WM8993_IN1LP_SPKMIXL_VOL                0x0010  /* IN1LP_SPKMIXL_VOL */
+#define WM8993_IN1LP_SPKMIXL_VOL_MASK           0x0010  /* IN1LP_SPKMIXL_VOL */
+#define WM8993_IN1LP_SPKMIXL_VOL_SHIFT               4  /* IN1LP_SPKMIXL_VOL */
+#define WM8993_IN1LP_SPKMIXL_VOL_WIDTH               1  /* IN1LP_SPKMIXL_VOL */
+#define WM8993_MIXOUTL_SPKMIXL_VOL              0x0008  /* MIXOUTL_SPKMIXL_VOL */
+#define WM8993_MIXOUTL_SPKMIXL_VOL_MASK         0x0008  /* MIXOUTL_SPKMIXL_VOL */
+#define WM8993_MIXOUTL_SPKMIXL_VOL_SHIFT             3  /* MIXOUTL_SPKMIXL_VOL */
+#define WM8993_MIXOUTL_SPKMIXL_VOL_WIDTH             1  /* MIXOUTL_SPKMIXL_VOL */
+#define WM8993_DACL_SPKMIXL_VOL                 0x0004  /* DACL_SPKMIXL_VOL */
+#define WM8993_DACL_SPKMIXL_VOL_MASK            0x0004  /* DACL_SPKMIXL_VOL */
+#define WM8993_DACL_SPKMIXL_VOL_SHIFT                2  /* DACL_SPKMIXL_VOL */
+#define WM8993_DACL_SPKMIXL_VOL_WIDTH                1  /* DACL_SPKMIXL_VOL */
+#define WM8993_SPKMIXL_VOL_MASK                 0x0003  /* SPKMIXL_VOL - [1:0] */
+#define WM8993_SPKMIXL_VOL_SHIFT                     0  /* SPKMIXL_VOL - [1:0] */
+#define WM8993_SPKMIXL_VOL_WIDTH                     2  /* SPKMIXL_VOL - [1:0] */
+
+/*
+ * R35 (0x23) - SPKMIXR Attenuation
+ */
+#define WM8993_SPKOUT_CLASSAB_MODE              0x0100  /* SPKOUT_CLASSAB_MODE */
+#define WM8993_SPKOUT_CLASSAB_MODE_MASK         0x0100  /* SPKOUT_CLASSAB_MODE */
+#define WM8993_SPKOUT_CLASSAB_MODE_SHIFT             8  /* SPKOUT_CLASSAB_MODE */
+#define WM8993_SPKOUT_CLASSAB_MODE_WIDTH             1  /* SPKOUT_CLASSAB_MODE */
+#define WM8993_MIXINR_SPKMIXR_VOL               0x0020  /* MIXINR_SPKMIXR_VOL */
+#define WM8993_MIXINR_SPKMIXR_VOL_MASK          0x0020  /* MIXINR_SPKMIXR_VOL */
+#define WM8993_MIXINR_SPKMIXR_VOL_SHIFT              5  /* MIXINR_SPKMIXR_VOL */
+#define WM8993_MIXINR_SPKMIXR_VOL_WIDTH              1  /* MIXINR_SPKMIXR_VOL */
+#define WM8993_IN1RP_SPKMIXR_VOL                0x0010  /* IN1RP_SPKMIXR_VOL */
+#define WM8993_IN1RP_SPKMIXR_VOL_MASK           0x0010  /* IN1RP_SPKMIXR_VOL */
+#define WM8993_IN1RP_SPKMIXR_VOL_SHIFT               4  /* IN1RP_SPKMIXR_VOL */
+#define WM8993_IN1RP_SPKMIXR_VOL_WIDTH               1  /* IN1RP_SPKMIXR_VOL */
+#define WM8993_MIXOUTR_SPKMIXR_VOL              0x0008  /* MIXOUTR_SPKMIXR_VOL */
+#define WM8993_MIXOUTR_SPKMIXR_VOL_MASK         0x0008  /* MIXOUTR_SPKMIXR_VOL */
+#define WM8993_MIXOUTR_SPKMIXR_VOL_SHIFT             3  /* MIXOUTR_SPKMIXR_VOL */
+#define WM8993_MIXOUTR_SPKMIXR_VOL_WIDTH             1  /* MIXOUTR_SPKMIXR_VOL */
+#define WM8993_DACR_SPKMIXR_VOL                 0x0004  /* DACR_SPKMIXR_VOL */
+#define WM8993_DACR_SPKMIXR_VOL_MASK            0x0004  /* DACR_SPKMIXR_VOL */
+#define WM8993_DACR_SPKMIXR_VOL_SHIFT                2  /* DACR_SPKMIXR_VOL */
+#define WM8993_DACR_SPKMIXR_VOL_WIDTH                1  /* DACR_SPKMIXR_VOL */
+#define WM8993_SPKMIXR_VOL_MASK                 0x0003  /* SPKMIXR_VOL - [1:0] */
+#define WM8993_SPKMIXR_VOL_SHIFT                     0  /* SPKMIXR_VOL - [1:0] */
+#define WM8993_SPKMIXR_VOL_WIDTH                     2  /* SPKMIXR_VOL - [1:0] */
+
+/*
+ * R36 (0x24) - SPKOUT Mixers
+ */
+#define WM8993_VRX_TO_SPKOUTL                   0x0020  /* VRX_TO_SPKOUTL */
+#define WM8993_VRX_TO_SPKOUTL_MASK              0x0020  /* VRX_TO_SPKOUTL */
+#define WM8993_VRX_TO_SPKOUTL_SHIFT                  5  /* VRX_TO_SPKOUTL */
+#define WM8993_VRX_TO_SPKOUTL_WIDTH                  1  /* VRX_TO_SPKOUTL */
+#define WM8993_SPKMIXL_TO_SPKOUTL               0x0010  /* SPKMIXL_TO_SPKOUTL */
+#define WM8993_SPKMIXL_TO_SPKOUTL_MASK          0x0010  /* SPKMIXL_TO_SPKOUTL */
+#define WM8993_SPKMIXL_TO_SPKOUTL_SHIFT              4  /* SPKMIXL_TO_SPKOUTL */
+#define WM8993_SPKMIXL_TO_SPKOUTL_WIDTH              1  /* SPKMIXL_TO_SPKOUTL */
+#define WM8993_SPKMIXR_TO_SPKOUTL               0x0008  /* SPKMIXR_TO_SPKOUTL */
+#define WM8993_SPKMIXR_TO_SPKOUTL_MASK          0x0008  /* SPKMIXR_TO_SPKOUTL */
+#define WM8993_SPKMIXR_TO_SPKOUTL_SHIFT              3  /* SPKMIXR_TO_SPKOUTL */
+#define WM8993_SPKMIXR_TO_SPKOUTL_WIDTH              1  /* SPKMIXR_TO_SPKOUTL */
+#define WM8993_VRX_TO_SPKOUTR                   0x0004  /* VRX_TO_SPKOUTR */
+#define WM8993_VRX_TO_SPKOUTR_MASK              0x0004  /* VRX_TO_SPKOUTR */
+#define WM8993_VRX_TO_SPKOUTR_SHIFT                  2  /* VRX_TO_SPKOUTR */
+#define WM8993_VRX_TO_SPKOUTR_WIDTH                  1  /* VRX_TO_SPKOUTR */
+#define WM8993_SPKMIXL_TO_SPKOUTR               0x0002  /* SPKMIXL_TO_SPKOUTR */
+#define WM8993_SPKMIXL_TO_SPKOUTR_MASK          0x0002  /* SPKMIXL_TO_SPKOUTR */
+#define WM8993_SPKMIXL_TO_SPKOUTR_SHIFT              1  /* SPKMIXL_TO_SPKOUTR */
+#define WM8993_SPKMIXL_TO_SPKOUTR_WIDTH              1  /* SPKMIXL_TO_SPKOUTR */
+#define WM8993_SPKMIXR_TO_SPKOUTR               0x0001  /* SPKMIXR_TO_SPKOUTR */
+#define WM8993_SPKMIXR_TO_SPKOUTR_MASK          0x0001  /* SPKMIXR_TO_SPKOUTR */
+#define WM8993_SPKMIXR_TO_SPKOUTR_SHIFT              0  /* SPKMIXR_TO_SPKOUTR */
+#define WM8993_SPKMIXR_TO_SPKOUTR_WIDTH              1  /* SPKMIXR_TO_SPKOUTR */
+
+/*
+ * R37 (0x25) - SPKOUT Boost
+ */
+#define WM8993_SPKOUTL_BOOST_MASK               0x0038  /* SPKOUTL_BOOST - [5:3] */
+#define WM8993_SPKOUTL_BOOST_SHIFT                   3  /* SPKOUTL_BOOST - [5:3] */
+#define WM8993_SPKOUTL_BOOST_WIDTH                   3  /* SPKOUTL_BOOST - [5:3] */
+#define WM8993_SPKOUTR_BOOST_MASK               0x0007  /* SPKOUTR_BOOST - [2:0] */
+#define WM8993_SPKOUTR_BOOST_SHIFT                   0  /* SPKOUTR_BOOST - [2:0] */
+#define WM8993_SPKOUTR_BOOST_WIDTH                   3  /* SPKOUTR_BOOST - [2:0] */
+
+/*
+ * R38 (0x26) - Speaker Volume Left
+ */
+#define WM8993_SPKOUT_VU                        0x0100  /* SPKOUT_VU */
+#define WM8993_SPKOUT_VU_MASK                   0x0100  /* SPKOUT_VU */
+#define WM8993_SPKOUT_VU_SHIFT                       8  /* SPKOUT_VU */
+#define WM8993_SPKOUT_VU_WIDTH                       1  /* SPKOUT_VU */
+#define WM8993_SPKOUTL_ZC                       0x0080  /* SPKOUTL_ZC */
+#define WM8993_SPKOUTL_ZC_MASK                  0x0080  /* SPKOUTL_ZC */
+#define WM8993_SPKOUTL_ZC_SHIFT                      7  /* SPKOUTL_ZC */
+#define WM8993_SPKOUTL_ZC_WIDTH                      1  /* SPKOUTL_ZC */
+#define WM8993_SPKOUTL_MUTE_N                   0x0040  /* SPKOUTL_MUTE_N */
+#define WM8993_SPKOUTL_MUTE_N_MASK              0x0040  /* SPKOUTL_MUTE_N */
+#define WM8993_SPKOUTL_MUTE_N_SHIFT                  6  /* SPKOUTL_MUTE_N */
+#define WM8993_SPKOUTL_MUTE_N_WIDTH                  1  /* SPKOUTL_MUTE_N */
+#define WM8993_SPKOUTL_VOL_MASK                 0x003F  /* SPKOUTL_VOL - [5:0] */
+#define WM8993_SPKOUTL_VOL_SHIFT                     0  /* SPKOUTL_VOL - [5:0] */
+#define WM8993_SPKOUTL_VOL_WIDTH                     6  /* SPKOUTL_VOL - [5:0] */
+
+/*
+ * R39 (0x27) - Speaker Volume Right
+ */
+#define WM8993_SPKOUT_VU                        0x0100  /* SPKOUT_VU */
+#define WM8993_SPKOUT_VU_MASK                   0x0100  /* SPKOUT_VU */
+#define WM8993_SPKOUT_VU_SHIFT                       8  /* SPKOUT_VU */
+#define WM8993_SPKOUT_VU_WIDTH                       1  /* SPKOUT_VU */
+#define WM8993_SPKOUTR_ZC                       0x0080  /* SPKOUTR_ZC */
+#define WM8993_SPKOUTR_ZC_MASK                  0x0080  /* SPKOUTR_ZC */
+#define WM8993_SPKOUTR_ZC_SHIFT                      7  /* SPKOUTR_ZC */
+#define WM8993_SPKOUTR_ZC_WIDTH                      1  /* SPKOUTR_ZC */
+#define WM8993_SPKOUTR_MUTE_N                   0x0040  /* SPKOUTR_MUTE_N */
+#define WM8993_SPKOUTR_MUTE_N_MASK              0x0040  /* SPKOUTR_MUTE_N */
+#define WM8993_SPKOUTR_MUTE_N_SHIFT                  6  /* SPKOUTR_MUTE_N */
+#define WM8993_SPKOUTR_MUTE_N_WIDTH                  1  /* SPKOUTR_MUTE_N */
+#define WM8993_SPKOUTR_VOL_MASK                 0x003F  /* SPKOUTR_VOL - [5:0] */
+#define WM8993_SPKOUTR_VOL_SHIFT                     0  /* SPKOUTR_VOL - [5:0] */
+#define WM8993_SPKOUTR_VOL_WIDTH                     6  /* SPKOUTR_VOL - [5:0] */
+
+/*
+ * R40 (0x28) - Input Mixer2
+ */
+#define WM8993_IN2LP_TO_IN2L                    0x0080  /* IN2LP_TO_IN2L */
+#define WM8993_IN2LP_TO_IN2L_MASK               0x0080  /* IN2LP_TO_IN2L */
+#define WM8993_IN2LP_TO_IN2L_SHIFT                   7  /* IN2LP_TO_IN2L */
+#define WM8993_IN2LP_TO_IN2L_WIDTH                   1  /* IN2LP_TO_IN2L */
+#define WM8993_IN2LN_TO_IN2L                    0x0040  /* IN2LN_TO_IN2L */
+#define WM8993_IN2LN_TO_IN2L_MASK               0x0040  /* IN2LN_TO_IN2L */
+#define WM8993_IN2LN_TO_IN2L_SHIFT                   6  /* IN2LN_TO_IN2L */
+#define WM8993_IN2LN_TO_IN2L_WIDTH                   1  /* IN2LN_TO_IN2L */
+#define WM8993_IN1LP_TO_IN1L                    0x0020  /* IN1LP_TO_IN1L */
+#define WM8993_IN1LP_TO_IN1L_MASK               0x0020  /* IN1LP_TO_IN1L */
+#define WM8993_IN1LP_TO_IN1L_SHIFT                   5  /* IN1LP_TO_IN1L */
+#define WM8993_IN1LP_TO_IN1L_WIDTH                   1  /* IN1LP_TO_IN1L */
+#define WM8993_IN1LN_TO_IN1L                    0x0010  /* IN1LN_TO_IN1L */
+#define WM8993_IN1LN_TO_IN1L_MASK               0x0010  /* IN1LN_TO_IN1L */
+#define WM8993_IN1LN_TO_IN1L_SHIFT                   4  /* IN1LN_TO_IN1L */
+#define WM8993_IN1LN_TO_IN1L_WIDTH                   1  /* IN1LN_TO_IN1L */
+#define WM8993_IN2RP_TO_IN2R                    0x0008  /* IN2RP_TO_IN2R */
+#define WM8993_IN2RP_TO_IN2R_MASK               0x0008  /* IN2RP_TO_IN2R */
+#define WM8993_IN2RP_TO_IN2R_SHIFT                   3  /* IN2RP_TO_IN2R */
+#define WM8993_IN2RP_TO_IN2R_WIDTH                   1  /* IN2RP_TO_IN2R */
+#define WM8993_IN2RN_TO_IN2R                    0x0004  /* IN2RN_TO_IN2R */
+#define WM8993_IN2RN_TO_IN2R_MASK               0x0004  /* IN2RN_TO_IN2R */
+#define WM8993_IN2RN_TO_IN2R_SHIFT                   2  /* IN2RN_TO_IN2R */
+#define WM8993_IN2RN_TO_IN2R_WIDTH                   1  /* IN2RN_TO_IN2R */
+#define WM8993_IN1RP_TO_IN1R                    0x0002  /* IN1RP_TO_IN1R */
+#define WM8993_IN1RP_TO_IN1R_MASK               0x0002  /* IN1RP_TO_IN1R */
+#define WM8993_IN1RP_TO_IN1R_SHIFT                   1  /* IN1RP_TO_IN1R */
+#define WM8993_IN1RP_TO_IN1R_WIDTH                   1  /* IN1RP_TO_IN1R */
+#define WM8993_IN1RN_TO_IN1R                    0x0001  /* IN1RN_TO_IN1R */
+#define WM8993_IN1RN_TO_IN1R_MASK               0x0001  /* IN1RN_TO_IN1R */
+#define WM8993_IN1RN_TO_IN1R_SHIFT                   0  /* IN1RN_TO_IN1R */
+#define WM8993_IN1RN_TO_IN1R_WIDTH                   1  /* IN1RN_TO_IN1R */
+
+/*
+ * R41 (0x29) - Input Mixer3
+ */
+#define WM8993_IN2L_TO_MIXINL                   0x0100  /* IN2L_TO_MIXINL */
+#define WM8993_IN2L_TO_MIXINL_MASK              0x0100  /* IN2L_TO_MIXINL */
+#define WM8993_IN2L_TO_MIXINL_SHIFT                  8  /* IN2L_TO_MIXINL */
+#define WM8993_IN2L_TO_MIXINL_WIDTH                  1  /* IN2L_TO_MIXINL */
+#define WM8993_IN2L_MIXINL_VOL                  0x0080  /* IN2L_MIXINL_VOL */
+#define WM8993_IN2L_MIXINL_VOL_MASK             0x0080  /* IN2L_MIXINL_VOL */
+#define WM8993_IN2L_MIXINL_VOL_SHIFT                 7  /* IN2L_MIXINL_VOL */
+#define WM8993_IN2L_MIXINL_VOL_WIDTH                 1  /* IN2L_MIXINL_VOL */
+#define WM8993_IN1L_TO_MIXINL                   0x0020  /* IN1L_TO_MIXINL */
+#define WM8993_IN1L_TO_MIXINL_MASK              0x0020  /* IN1L_TO_MIXINL */
+#define WM8993_IN1L_TO_MIXINL_SHIFT                  5  /* IN1L_TO_MIXINL */
+#define WM8993_IN1L_TO_MIXINL_WIDTH                  1  /* IN1L_TO_MIXINL */
+#define WM8993_IN1L_MIXINL_VOL                  0x0010  /* IN1L_MIXINL_VOL */
+#define WM8993_IN1L_MIXINL_VOL_MASK             0x0010  /* IN1L_MIXINL_VOL */
+#define WM8993_IN1L_MIXINL_VOL_SHIFT                 4  /* IN1L_MIXINL_VOL */
+#define WM8993_IN1L_MIXINL_VOL_WIDTH                 1  /* IN1L_MIXINL_VOL */
+#define WM8993_MIXOUTL_MIXINL_VOL_MASK          0x0007  /* MIXOUTL_MIXINL_VOL - [2:0] */
+#define WM8993_MIXOUTL_MIXINL_VOL_SHIFT              0  /* MIXOUTL_MIXINL_VOL - [2:0] */
+#define WM8993_MIXOUTL_MIXINL_VOL_WIDTH              3  /* MIXOUTL_MIXINL_VOL - [2:0] */
+
+/*
+ * R42 (0x2A) - Input Mixer4
+ */
+#define WM8993_IN2R_TO_MIXINR                   0x0100  /* IN2R_TO_MIXINR */
+#define WM8993_IN2R_TO_MIXINR_MASK              0x0100  /* IN2R_TO_MIXINR */
+#define WM8993_IN2R_TO_MIXINR_SHIFT                  8  /* IN2R_TO_MIXINR */
+#define WM8993_IN2R_TO_MIXINR_WIDTH                  1  /* IN2R_TO_MIXINR */
+#define WM8993_IN2R_MIXINR_VOL                  0x0080  /* IN2R_MIXINR_VOL */
+#define WM8993_IN2R_MIXINR_VOL_MASK             0x0080  /* IN2R_MIXINR_VOL */
+#define WM8993_IN2R_MIXINR_VOL_SHIFT                 7  /* IN2R_MIXINR_VOL */
+#define WM8993_IN2R_MIXINR_VOL_WIDTH                 1  /* IN2R_MIXINR_VOL */
+#define WM8993_IN1R_TO_MIXINR                   0x0020  /* IN1R_TO_MIXINR */
+#define WM8993_IN1R_TO_MIXINR_MASK              0x0020  /* IN1R_TO_MIXINR */
+#define WM8993_IN1R_TO_MIXINR_SHIFT                  5  /* IN1R_TO_MIXINR */
+#define WM8993_IN1R_TO_MIXINR_WIDTH                  1  /* IN1R_TO_MIXINR */
+#define WM8993_IN1R_MIXINR_VOL                  0x0010  /* IN1R_MIXINR_VOL */
+#define WM8993_IN1R_MIXINR_VOL_MASK             0x0010  /* IN1R_MIXINR_VOL */
+#define WM8993_IN1R_MIXINR_VOL_SHIFT                 4  /* IN1R_MIXINR_VOL */
+#define WM8993_IN1R_MIXINR_VOL_WIDTH                 1  /* IN1R_MIXINR_VOL */
+#define WM8993_MIXOUTR_MIXINR_VOL_MASK          0x0007  /* MIXOUTR_MIXINR_VOL - [2:0] */
+#define WM8993_MIXOUTR_MIXINR_VOL_SHIFT              0  /* MIXOUTR_MIXINR_VOL - [2:0] */
+#define WM8993_MIXOUTR_MIXINR_VOL_WIDTH              3  /* MIXOUTR_MIXINR_VOL - [2:0] */
+
+/*
+ * R43 (0x2B) - Input Mixer5
+ */
+#define WM8993_IN1LP_MIXINL_VOL_MASK            0x01C0  /* IN1LP_MIXINL_VOL - [8:6] */
+#define WM8993_IN1LP_MIXINL_VOL_SHIFT                6  /* IN1LP_MIXINL_VOL - [8:6] */
+#define WM8993_IN1LP_MIXINL_VOL_WIDTH                3  /* IN1LP_MIXINL_VOL - [8:6] */
+#define WM8993_VRX_MIXINL_VOL_MASK              0x0007  /* VRX_MIXINL_VOL - [2:0] */
+#define WM8993_VRX_MIXINL_VOL_SHIFT                  0  /* VRX_MIXINL_VOL - [2:0] */
+#define WM8993_VRX_MIXINL_VOL_WIDTH                  3  /* VRX_MIXINL_VOL - [2:0] */
+
+/*
+ * R44 (0x2C) - Input Mixer6
+ */
+#define WM8993_IN1RP_MIXINR_VOL_MASK            0x01C0  /* IN1RP_MIXINR_VOL - [8:6] */
+#define WM8993_IN1RP_MIXINR_VOL_SHIFT                6  /* IN1RP_MIXINR_VOL - [8:6] */
+#define WM8993_IN1RP_MIXINR_VOL_WIDTH                3  /* IN1RP_MIXINR_VOL - [8:6] */
+#define WM8993_VRX_MIXINR_VOL_MASK              0x0007  /* VRX_MIXINR_VOL - [2:0] */
+#define WM8993_VRX_MIXINR_VOL_SHIFT                  0  /* VRX_MIXINR_VOL - [2:0] */
+#define WM8993_VRX_MIXINR_VOL_WIDTH                  3  /* VRX_MIXINR_VOL - [2:0] */
+
+/*
+ * R45 (0x2D) - Output Mixer1
+ */
+#define WM8993_DACL_TO_HPOUT1L                  0x0100  /* DACL_TO_HPOUT1L */
+#define WM8993_DACL_TO_HPOUT1L_MASK             0x0100  /* DACL_TO_HPOUT1L */
+#define WM8993_DACL_TO_HPOUT1L_SHIFT                 8  /* DACL_TO_HPOUT1L */
+#define WM8993_DACL_TO_HPOUT1L_WIDTH                 1  /* DACL_TO_HPOUT1L */
+#define WM8993_MIXINR_TO_MIXOUTL                0x0080  /* MIXINR_TO_MIXOUTL */
+#define WM8993_MIXINR_TO_MIXOUTL_MASK           0x0080  /* MIXINR_TO_MIXOUTL */
+#define WM8993_MIXINR_TO_MIXOUTL_SHIFT               7  /* MIXINR_TO_MIXOUTL */
+#define WM8993_MIXINR_TO_MIXOUTL_WIDTH               1  /* MIXINR_TO_MIXOUTL */
+#define WM8993_MIXINL_TO_MIXOUTL                0x0040  /* MIXINL_TO_MIXOUTL */
+#define WM8993_MIXINL_TO_MIXOUTL_MASK           0x0040  /* MIXINL_TO_MIXOUTL */
+#define WM8993_MIXINL_TO_MIXOUTL_SHIFT               6  /* MIXINL_TO_MIXOUTL */
+#define WM8993_MIXINL_TO_MIXOUTL_WIDTH               1  /* MIXINL_TO_MIXOUTL */
+#define WM8993_IN2RN_TO_MIXOUTL                 0x0020  /* IN2RN_TO_MIXOUTL */
+#define WM8993_IN2RN_TO_MIXOUTL_MASK            0x0020  /* IN2RN_TO_MIXOUTL */
+#define WM8993_IN2RN_TO_MIXOUTL_SHIFT                5  /* IN2RN_TO_MIXOUTL */
+#define WM8993_IN2RN_TO_MIXOUTL_WIDTH                1  /* IN2RN_TO_MIXOUTL */
+#define WM8993_IN2LN_TO_MIXOUTL                 0x0010  /* IN2LN_TO_MIXOUTL */
+#define WM8993_IN2LN_TO_MIXOUTL_MASK            0x0010  /* IN2LN_TO_MIXOUTL */
+#define WM8993_IN2LN_TO_MIXOUTL_SHIFT                4  /* IN2LN_TO_MIXOUTL */
+#define WM8993_IN2LN_TO_MIXOUTL_WIDTH                1  /* IN2LN_TO_MIXOUTL */
+#define WM8993_IN1R_TO_MIXOUTL                  0x0008  /* IN1R_TO_MIXOUTL */
+#define WM8993_IN1R_TO_MIXOUTL_MASK             0x0008  /* IN1R_TO_MIXOUTL */
+#define WM8993_IN1R_TO_MIXOUTL_SHIFT                 3  /* IN1R_TO_MIXOUTL */
+#define WM8993_IN1R_TO_MIXOUTL_WIDTH                 1  /* IN1R_TO_MIXOUTL */
+#define WM8993_IN1L_TO_MIXOUTL                  0x0004  /* IN1L_TO_MIXOUTL */
+#define WM8993_IN1L_TO_MIXOUTL_MASK             0x0004  /* IN1L_TO_MIXOUTL */
+#define WM8993_IN1L_TO_MIXOUTL_SHIFT                 2  /* IN1L_TO_MIXOUTL */
+#define WM8993_IN1L_TO_MIXOUTL_WIDTH                 1  /* IN1L_TO_MIXOUTL */
+#define WM8993_IN2LP_TO_MIXOUTL                 0x0002  /* IN2LP_TO_MIXOUTL */
+#define WM8993_IN2LP_TO_MIXOUTL_MASK            0x0002  /* IN2LP_TO_MIXOUTL */
+#define WM8993_IN2LP_TO_MIXOUTL_SHIFT                1  /* IN2LP_TO_MIXOUTL */
+#define WM8993_IN2LP_TO_MIXOUTL_WIDTH                1  /* IN2LP_TO_MIXOUTL */
+#define WM8993_DACL_TO_MIXOUTL                  0x0001  /* DACL_TO_MIXOUTL */
+#define WM8993_DACL_TO_MIXOUTL_MASK             0x0001  /* DACL_TO_MIXOUTL */
+#define WM8993_DACL_TO_MIXOUTL_SHIFT                 0  /* DACL_TO_MIXOUTL */
+#define WM8993_DACL_TO_MIXOUTL_WIDTH                 1  /* DACL_TO_MIXOUTL */
+
+/*
+ * R46 (0x2E) - Output Mixer2
+ */
+#define WM8993_DACR_TO_HPOUT1R                  0x0100  /* DACR_TO_HPOUT1R */
+#define WM8993_DACR_TO_HPOUT1R_MASK             0x0100  /* DACR_TO_HPOUT1R */
+#define WM8993_DACR_TO_HPOUT1R_SHIFT                 8  /* DACR_TO_HPOUT1R */
+#define WM8993_DACR_TO_HPOUT1R_WIDTH                 1  /* DACR_TO_HPOUT1R */
+#define WM8993_MIXINL_TO_MIXOUTR                0x0080  /* MIXINL_TO_MIXOUTR */
+#define WM8993_MIXINL_TO_MIXOUTR_MASK           0x0080  /* MIXINL_TO_MIXOUTR */
+#define WM8993_MIXINL_TO_MIXOUTR_SHIFT               7  /* MIXINL_TO_MIXOUTR */
+#define WM8993_MIXINL_TO_MIXOUTR_WIDTH               1  /* MIXINL_TO_MIXOUTR */
+#define WM8993_MIXINR_TO_MIXOUTR                0x0040  /* MIXINR_TO_MIXOUTR */
+#define WM8993_MIXINR_TO_MIXOUTR_MASK           0x0040  /* MIXINR_TO_MIXOUTR */
+#define WM8993_MIXINR_TO_MIXOUTR_SHIFT               6  /* MIXINR_TO_MIXOUTR */
+#define WM8993_MIXINR_TO_MIXOUTR_WIDTH               1  /* MIXINR_TO_MIXOUTR */
+#define WM8993_IN2LN_TO_MIXOUTR                 0x0020  /* IN2LN_TO_MIXOUTR */
+#define WM8993_IN2LN_TO_MIXOUTR_MASK            0x0020  /* IN2LN_TO_MIXOUTR */
+#define WM8993_IN2LN_TO_MIXOUTR_SHIFT                5  /* IN2LN_TO_MIXOUTR */
+#define WM8993_IN2LN_TO_MIXOUTR_WIDTH                1  /* IN2LN_TO_MIXOUTR */
+#define WM8993_IN2RN_TO_MIXOUTR                 0x0010  /* IN2RN_TO_MIXOUTR */
+#define WM8993_IN2RN_TO_MIXOUTR_MASK            0x0010  /* IN2RN_TO_MIXOUTR */
+#define WM8993_IN2RN_TO_MIXOUTR_SHIFT                4  /* IN2RN_TO_MIXOUTR */
+#define WM8993_IN2RN_TO_MIXOUTR_WIDTH                1  /* IN2RN_TO_MIXOUTR */
+#define WM8993_IN1L_TO_MIXOUTR                  0x0008  /* IN1L_TO_MIXOUTR */
+#define WM8993_IN1L_TO_MIXOUTR_MASK             0x0008  /* IN1L_TO_MIXOUTR */
+#define WM8993_IN1L_TO_MIXOUTR_SHIFT                 3  /* IN1L_TO_MIXOUTR */
+#define WM8993_IN1L_TO_MIXOUTR_WIDTH                 1  /* IN1L_TO_MIXOUTR */
+#define WM8993_IN1R_TO_MIXOUTR                  0x0004  /* IN1R_TO_MIXOUTR */
+#define WM8993_IN1R_TO_MIXOUTR_MASK             0x0004  /* IN1R_TO_MIXOUTR */
+#define WM8993_IN1R_TO_MIXOUTR_SHIFT                 2  /* IN1R_TO_MIXOUTR */
+#define WM8993_IN1R_TO_MIXOUTR_WIDTH                 1  /* IN1R_TO_MIXOUTR */
+#define WM8993_IN2RP_TO_MIXOUTR                 0x0002  /* IN2RP_TO_MIXOUTR */
+#define WM8993_IN2RP_TO_MIXOUTR_MASK            0x0002  /* IN2RP_TO_MIXOUTR */
+#define WM8993_IN2RP_TO_MIXOUTR_SHIFT                1  /* IN2RP_TO_MIXOUTR */
+#define WM8993_IN2RP_TO_MIXOUTR_WIDTH                1  /* IN2RP_TO_MIXOUTR */
+#define WM8993_DACR_TO_MIXOUTR                  0x0001  /* DACR_TO_MIXOUTR */
+#define WM8993_DACR_TO_MIXOUTR_MASK             0x0001  /* DACR_TO_MIXOUTR */
+#define WM8993_DACR_TO_MIXOUTR_SHIFT                 0  /* DACR_TO_MIXOUTR */
+#define WM8993_DACR_TO_MIXOUTR_WIDTH                 1  /* DACR_TO_MIXOUTR */
+
+/*
+ * R47 (0x2F) - Output Mixer3
+ */
+#define WM8993_IN2LP_MIXOUTL_VOL_MASK           0x0E00  /* IN2LP_MIXOUTL_VOL - [11:9] */
+#define WM8993_IN2LP_MIXOUTL_VOL_SHIFT               9  /* IN2LP_MIXOUTL_VOL - [11:9] */
+#define WM8993_IN2LP_MIXOUTL_VOL_WIDTH               3  /* IN2LP_MIXOUTL_VOL - [11:9] */
+#define WM8993_IN2LN_MIXOUTL_VOL_MASK           0x01C0  /* IN2LN_MIXOUTL_VOL - [8:6] */
+#define WM8993_IN2LN_MIXOUTL_VOL_SHIFT               6  /* IN2LN_MIXOUTL_VOL - [8:6] */
+#define WM8993_IN2LN_MIXOUTL_VOL_WIDTH               3  /* IN2LN_MIXOUTL_VOL - [8:6] */
+#define WM8993_IN1R_MIXOUTL_VOL_MASK            0x0038  /* IN1R_MIXOUTL_VOL - [5:3] */
+#define WM8993_IN1R_MIXOUTL_VOL_SHIFT                3  /* IN1R_MIXOUTL_VOL - [5:3] */
+#define WM8993_IN1R_MIXOUTL_VOL_WIDTH                3  /* IN1R_MIXOUTL_VOL - [5:3] */
+#define WM8993_IN1L_MIXOUTL_VOL_MASK            0x0007  /* IN1L_MIXOUTL_VOL - [2:0] */
+#define WM8993_IN1L_MIXOUTL_VOL_SHIFT                0  /* IN1L_MIXOUTL_VOL - [2:0] */
+#define WM8993_IN1L_MIXOUTL_VOL_WIDTH                3  /* IN1L_MIXOUTL_VOL - [2:0] */
+
+/*
+ * R48 (0x30) - Output Mixer4
+ */
+#define WM8993_IN2RP_MIXOUTR_VOL_MASK           0x0E00  /* IN2RP_MIXOUTR_VOL - [11:9] */
+#define WM8993_IN2RP_MIXOUTR_VOL_SHIFT               9  /* IN2RP_MIXOUTR_VOL - [11:9] */
+#define WM8993_IN2RP_MIXOUTR_VOL_WIDTH               3  /* IN2RP_MIXOUTR_VOL - [11:9] */
+#define WM8993_IN2RN_MIXOUTR_VOL_MASK           0x01C0  /* IN2RN_MIXOUTR_VOL - [8:6] */
+#define WM8993_IN2RN_MIXOUTR_VOL_SHIFT               6  /* IN2RN_MIXOUTR_VOL - [8:6] */
+#define WM8993_IN2RN_MIXOUTR_VOL_WIDTH               3  /* IN2RN_MIXOUTR_VOL - [8:6] */
+#define WM8993_IN1L_MIXOUTR_VOL_MASK            0x0038  /* IN1L_MIXOUTR_VOL - [5:3] */
+#define WM8993_IN1L_MIXOUTR_VOL_SHIFT                3  /* IN1L_MIXOUTR_VOL - [5:3] */
+#define WM8993_IN1L_MIXOUTR_VOL_WIDTH                3  /* IN1L_MIXOUTR_VOL - [5:3] */
+#define WM8993_IN1R_MIXOUTR_VOL_MASK            0x0007  /* IN1R_MIXOUTR_VOL - [2:0] */
+#define WM8993_IN1R_MIXOUTR_VOL_SHIFT                0  /* IN1R_MIXOUTR_VOL - [2:0] */
+#define WM8993_IN1R_MIXOUTR_VOL_WIDTH                3  /* IN1R_MIXOUTR_VOL - [2:0] */
+
+/*
+ * R49 (0x31) - Output Mixer5
+ */
+#define WM8993_DACL_MIXOUTL_VOL_MASK            0x0E00  /* DACL_MIXOUTL_VOL - [11:9] */
+#define WM8993_DACL_MIXOUTL_VOL_SHIFT                9  /* DACL_MIXOUTL_VOL - [11:9] */
+#define WM8993_DACL_MIXOUTL_VOL_WIDTH                3  /* DACL_MIXOUTL_VOL - [11:9] */
+#define WM8993_IN2RN_MIXOUTL_VOL_MASK           0x01C0  /* IN2RN_MIXOUTL_VOL - [8:6] */
+#define WM8993_IN2RN_MIXOUTL_VOL_SHIFT               6  /* IN2RN_MIXOUTL_VOL - [8:6] */
+#define WM8993_IN2RN_MIXOUTL_VOL_WIDTH               3  /* IN2RN_MIXOUTL_VOL - [8:6] */
+#define WM8993_MIXINR_MIXOUTL_VOL_MASK          0x0038  /* MIXINR_MIXOUTL_VOL - [5:3] */
+#define WM8993_MIXINR_MIXOUTL_VOL_SHIFT              3  /* MIXINR_MIXOUTL_VOL - [5:3] */
+#define WM8993_MIXINR_MIXOUTL_VOL_WIDTH              3  /* MIXINR_MIXOUTL_VOL - [5:3] */
+#define WM8993_MIXINL_MIXOUTL_VOL_MASK          0x0007  /* MIXINL_MIXOUTL_VOL - [2:0] */
+#define WM8993_MIXINL_MIXOUTL_VOL_SHIFT              0  /* MIXINL_MIXOUTL_VOL - [2:0] */
+#define WM8993_MIXINL_MIXOUTL_VOL_WIDTH              3  /* MIXINL_MIXOUTL_VOL - [2:0] */
+
+/*
+ * R50 (0x32) - Output Mixer6
+ */
+#define WM8993_DACR_MIXOUTR_VOL_MASK            0x0E00  /* DACR_MIXOUTR_VOL - [11:9] */
+#define WM8993_DACR_MIXOUTR_VOL_SHIFT                9  /* DACR_MIXOUTR_VOL - [11:9] */
+#define WM8993_DACR_MIXOUTR_VOL_WIDTH                3  /* DACR_MIXOUTR_VOL - [11:9] */
+#define WM8993_IN2LN_MIXOUTR_VOL_MASK           0x01C0  /* IN2LN_MIXOUTR_VOL - [8:6] */
+#define WM8993_IN2LN_MIXOUTR_VOL_SHIFT               6  /* IN2LN_MIXOUTR_VOL - [8:6] */
+#define WM8993_IN2LN_MIXOUTR_VOL_WIDTH               3  /* IN2LN_MIXOUTR_VOL - [8:6] */
+#define WM8993_MIXINL_MIXOUTR_VOL_MASK          0x0038  /* MIXINL_MIXOUTR_VOL - [5:3] */
+#define WM8993_MIXINL_MIXOUTR_VOL_SHIFT              3  /* MIXINL_MIXOUTR_VOL - [5:3] */
+#define WM8993_MIXINL_MIXOUTR_VOL_WIDTH              3  /* MIXINL_MIXOUTR_VOL - [5:3] */
+#define WM8993_MIXINR_MIXOUTR_VOL_MASK          0x0007  /* MIXINR_MIXOUTR_VOL - [2:0] */
+#define WM8993_MIXINR_MIXOUTR_VOL_SHIFT              0  /* MIXINR_MIXOUTR_VOL - [2:0] */
+#define WM8993_MIXINR_MIXOUTR_VOL_WIDTH              3  /* MIXINR_MIXOUTR_VOL - [2:0] */
+
+/*
+ * R51 (0x33) - HPOUT2 Mixer
+ */
+#define WM8993_VRX_TO_HPOUT2                    0x0020  /* VRX_TO_HPOUT2 */
+#define WM8993_VRX_TO_HPOUT2_MASK               0x0020  /* VRX_TO_HPOUT2 */
+#define WM8993_VRX_TO_HPOUT2_SHIFT                   5  /* VRX_TO_HPOUT2 */
+#define WM8993_VRX_TO_HPOUT2_WIDTH                   1  /* VRX_TO_HPOUT2 */
+#define WM8993_MIXOUTLVOL_TO_HPOUT2             0x0010  /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8993_MIXOUTLVOL_TO_HPOUT2_MASK        0x0010  /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8993_MIXOUTLVOL_TO_HPOUT2_SHIFT            4  /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8993_MIXOUTLVOL_TO_HPOUT2_WIDTH            1  /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8993_MIXOUTRVOL_TO_HPOUT2             0x0008  /* MIXOUTRVOL_TO_HPOUT2 */
+#define WM8993_MIXOUTRVOL_TO_HPOUT2_MASK        0x0008  /* MIXOUTRVOL_TO_HPOUT2 */
+#define WM8993_MIXOUTRVOL_TO_HPOUT2_SHIFT            3  /* MIXOUTRVOL_TO_HPOUT2 */
+#define WM8993_MIXOUTRVOL_TO_HPOUT2_WIDTH            1  /* MIXOUTRVOL_TO_HPOUT2 */
+
+/*
+ * R52 (0x34) - Line Mixer1
+ */
+#define WM8993_MIXOUTL_TO_LINEOUT1N             0x0040  /* MIXOUTL_TO_LINEOUT1N */
+#define WM8993_MIXOUTL_TO_LINEOUT1N_MASK        0x0040  /* MIXOUTL_TO_LINEOUT1N */
+#define WM8993_MIXOUTL_TO_LINEOUT1N_SHIFT            6  /* MIXOUTL_TO_LINEOUT1N */
+#define WM8993_MIXOUTL_TO_LINEOUT1N_WIDTH            1  /* MIXOUTL_TO_LINEOUT1N */
+#define WM8993_MIXOUTR_TO_LINEOUT1N             0x0020  /* MIXOUTR_TO_LINEOUT1N */
+#define WM8993_MIXOUTR_TO_LINEOUT1N_MASK        0x0020  /* MIXOUTR_TO_LINEOUT1N */
+#define WM8993_MIXOUTR_TO_LINEOUT1N_SHIFT            5  /* MIXOUTR_TO_LINEOUT1N */
+#define WM8993_MIXOUTR_TO_LINEOUT1N_WIDTH            1  /* MIXOUTR_TO_LINEOUT1N */
+#define WM8993_LINEOUT1_MODE                    0x0010  /* LINEOUT1_MODE */
+#define WM8993_LINEOUT1_MODE_MASK               0x0010  /* LINEOUT1_MODE */
+#define WM8993_LINEOUT1_MODE_SHIFT                   4  /* LINEOUT1_MODE */
+#define WM8993_LINEOUT1_MODE_WIDTH                   1  /* LINEOUT1_MODE */
+#define WM8993_IN1R_TO_LINEOUT1P                0x0004  /* IN1R_TO_LINEOUT1P */
+#define WM8993_IN1R_TO_LINEOUT1P_MASK           0x0004  /* IN1R_TO_LINEOUT1P */
+#define WM8993_IN1R_TO_LINEOUT1P_SHIFT               2  /* IN1R_TO_LINEOUT1P */
+#define WM8993_IN1R_TO_LINEOUT1P_WIDTH               1  /* IN1R_TO_LINEOUT1P */
+#define WM8993_IN1L_TO_LINEOUT1P                0x0002  /* IN1L_TO_LINEOUT1P */
+#define WM8993_IN1L_TO_LINEOUT1P_MASK           0x0002  /* IN1L_TO_LINEOUT1P */
+#define WM8993_IN1L_TO_LINEOUT1P_SHIFT               1  /* IN1L_TO_LINEOUT1P */
+#define WM8993_IN1L_TO_LINEOUT1P_WIDTH               1  /* IN1L_TO_LINEOUT1P */
+#define WM8993_MIXOUTL_TO_LINEOUT1P             0x0001  /* MIXOUTL_TO_LINEOUT1P */
+#define WM8993_MIXOUTL_TO_LINEOUT1P_MASK        0x0001  /* MIXOUTL_TO_LINEOUT1P */
+#define WM8993_MIXOUTL_TO_LINEOUT1P_SHIFT            0  /* MIXOUTL_TO_LINEOUT1P */
+#define WM8993_MIXOUTL_TO_LINEOUT1P_WIDTH            1  /* MIXOUTL_TO_LINEOUT1P */
+
+/*
+ * R53 (0x35) - Line Mixer2
+ */
+#define WM8993_MIXOUTR_TO_LINEOUT2N             0x0040  /* MIXOUTR_TO_LINEOUT2N */
+#define WM8993_MIXOUTR_TO_LINEOUT2N_MASK        0x0040  /* MIXOUTR_TO_LINEOUT2N */
+#define WM8993_MIXOUTR_TO_LINEOUT2N_SHIFT            6  /* MIXOUTR_TO_LINEOUT2N */
+#define WM8993_MIXOUTR_TO_LINEOUT2N_WIDTH            1  /* MIXOUTR_TO_LINEOUT2N */
+#define WM8993_MIXOUTL_TO_LINEOUT2N             0x0020  /* MIXOUTL_TO_LINEOUT2N */
+#define WM8993_MIXOUTL_TO_LINEOUT2N_MASK        0x0020  /* MIXOUTL_TO_LINEOUT2N */
+#define WM8993_MIXOUTL_TO_LINEOUT2N_SHIFT            5  /* MIXOUTL_TO_LINEOUT2N */
+#define WM8993_MIXOUTL_TO_LINEOUT2N_WIDTH            1  /* MIXOUTL_TO_LINEOUT2N */
+#define WM8993_LINEOUT2_MODE                    0x0010  /* LINEOUT2_MODE */
+#define WM8993_LINEOUT2_MODE_MASK               0x0010  /* LINEOUT2_MODE */
+#define WM8993_LINEOUT2_MODE_SHIFT                   4  /* LINEOUT2_MODE */
+#define WM8993_LINEOUT2_MODE_WIDTH                   1  /* LINEOUT2_MODE */
+#define WM8993_IN1L_TO_LINEOUT2P                0x0004  /* IN1L_TO_LINEOUT2P */
+#define WM8993_IN1L_TO_LINEOUT2P_MASK           0x0004  /* IN1L_TO_LINEOUT2P */
+#define WM8993_IN1L_TO_LINEOUT2P_SHIFT               2  /* IN1L_TO_LINEOUT2P */
+#define WM8993_IN1L_TO_LINEOUT2P_WIDTH               1  /* IN1L_TO_LINEOUT2P */
+#define WM8993_IN1R_TO_LINEOUT2P                0x0002  /* IN1R_TO_LINEOUT2P */
+#define WM8993_IN1R_TO_LINEOUT2P_MASK           0x0002  /* IN1R_TO_LINEOUT2P */
+#define WM8993_IN1R_TO_LINEOUT2P_SHIFT               1  /* IN1R_TO_LINEOUT2P */
+#define WM8993_IN1R_TO_LINEOUT2P_WIDTH               1  /* IN1R_TO_LINEOUT2P */
+#define WM8993_MIXOUTR_TO_LINEOUT2P             0x0001  /* MIXOUTR_TO_LINEOUT2P */
+#define WM8993_MIXOUTR_TO_LINEOUT2P_MASK        0x0001  /* MIXOUTR_TO_LINEOUT2P */
+#define WM8993_MIXOUTR_TO_LINEOUT2P_SHIFT            0  /* MIXOUTR_TO_LINEOUT2P */
+#define WM8993_MIXOUTR_TO_LINEOUT2P_WIDTH            1  /* MIXOUTR_TO_LINEOUT2P */
+
+/*
+ * R54 (0x36) - Speaker Mixer
+ */
+#define WM8993_SPKAB_REF_SEL                    0x0100  /* SPKAB_REF_SEL */
+#define WM8993_SPKAB_REF_SEL_MASK               0x0100  /* SPKAB_REF_SEL */
+#define WM8993_SPKAB_REF_SEL_SHIFT                   8  /* SPKAB_REF_SEL */
+#define WM8993_SPKAB_REF_SEL_WIDTH                   1  /* SPKAB_REF_SEL */
+#define WM8993_MIXINL_TO_SPKMIXL                0x0080  /* MIXINL_TO_SPKMIXL */
+#define WM8993_MIXINL_TO_SPKMIXL_MASK           0x0080  /* MIXINL_TO_SPKMIXL */
+#define WM8993_MIXINL_TO_SPKMIXL_SHIFT               7  /* MIXINL_TO_SPKMIXL */
+#define WM8993_MIXINL_TO_SPKMIXL_WIDTH               1  /* MIXINL_TO_SPKMIXL */
+#define WM8993_MIXINR_TO_SPKMIXR                0x0040  /* MIXINR_TO_SPKMIXR */
+#define WM8993_MIXINR_TO_SPKMIXR_MASK           0x0040  /* MIXINR_TO_SPKMIXR */
+#define WM8993_MIXINR_TO_SPKMIXR_SHIFT               6  /* MIXINR_TO_SPKMIXR */
+#define WM8993_MIXINR_TO_SPKMIXR_WIDTH               1  /* MIXINR_TO_SPKMIXR */
+#define WM8993_IN1LP_TO_SPKMIXL                 0x0020  /* IN1LP_TO_SPKMIXL */
+#define WM8993_IN1LP_TO_SPKMIXL_MASK            0x0020  /* IN1LP_TO_SPKMIXL */
+#define WM8993_IN1LP_TO_SPKMIXL_SHIFT                5  /* IN1LP_TO_SPKMIXL */
+#define WM8993_IN1LP_TO_SPKMIXL_WIDTH                1  /* IN1LP_TO_SPKMIXL */
+#define WM8993_IN1RP_TO_SPKMIXR                 0x0010  /* IN1RP_TO_SPKMIXR */
+#define WM8993_IN1RP_TO_SPKMIXR_MASK            0x0010  /* IN1RP_TO_SPKMIXR */
+#define WM8993_IN1RP_TO_SPKMIXR_SHIFT                4  /* IN1RP_TO_SPKMIXR */
+#define WM8993_IN1RP_TO_SPKMIXR_WIDTH                1  /* IN1RP_TO_SPKMIXR */
+#define WM8993_MIXOUTL_TO_SPKMIXL               0x0008  /* MIXOUTL_TO_SPKMIXL */
+#define WM8993_MIXOUTL_TO_SPKMIXL_MASK          0x0008  /* MIXOUTL_TO_SPKMIXL */
+#define WM8993_MIXOUTL_TO_SPKMIXL_SHIFT              3  /* MIXOUTL_TO_SPKMIXL */
+#define WM8993_MIXOUTL_TO_SPKMIXL_WIDTH              1  /* MIXOUTL_TO_SPKMIXL */
+#define WM8993_MIXOUTR_TO_SPKMIXR               0x0004  /* MIXOUTR_TO_SPKMIXR */
+#define WM8993_MIXOUTR_TO_SPKMIXR_MASK          0x0004  /* MIXOUTR_TO_SPKMIXR */
+#define WM8993_MIXOUTR_TO_SPKMIXR_SHIFT              2  /* MIXOUTR_TO_SPKMIXR */
+#define WM8993_MIXOUTR_TO_SPKMIXR_WIDTH              1  /* MIXOUTR_TO_SPKMIXR */
+#define WM8993_DACL_TO_SPKMIXL                  0x0002  /* DACL_TO_SPKMIXL */
+#define WM8993_DACL_TO_SPKMIXL_MASK             0x0002  /* DACL_TO_SPKMIXL */
+#define WM8993_DACL_TO_SPKMIXL_SHIFT                 1  /* DACL_TO_SPKMIXL */
+#define WM8993_DACL_TO_SPKMIXL_WIDTH                 1  /* DACL_TO_SPKMIXL */
+#define WM8993_DACR_TO_SPKMIXR                  0x0001  /* DACR_TO_SPKMIXR */
+#define WM8993_DACR_TO_SPKMIXR_MASK             0x0001  /* DACR_TO_SPKMIXR */
+#define WM8993_DACR_TO_SPKMIXR_SHIFT                 0  /* DACR_TO_SPKMIXR */
+#define WM8993_DACR_TO_SPKMIXR_WIDTH                 1  /* DACR_TO_SPKMIXR */
+
+/*
+ * R55 (0x37) - Additional Control
+ */
+#define WM8993_LINEOUT1_FB                      0x0080  /* LINEOUT1_FB */
+#define WM8993_LINEOUT1_FB_MASK                 0x0080  /* LINEOUT1_FB */
+#define WM8993_LINEOUT1_FB_SHIFT                     7  /* LINEOUT1_FB */
+#define WM8993_LINEOUT1_FB_WIDTH                     1  /* LINEOUT1_FB */
+#define WM8993_LINEOUT2_FB                      0x0040  /* LINEOUT2_FB */
+#define WM8993_LINEOUT2_FB_MASK                 0x0040  /* LINEOUT2_FB */
+#define WM8993_LINEOUT2_FB_SHIFT                     6  /* LINEOUT2_FB */
+#define WM8993_LINEOUT2_FB_WIDTH                     1  /* LINEOUT2_FB */
+#define WM8993_VROI                             0x0001  /* VROI */
+#define WM8993_VROI_MASK                        0x0001  /* VROI */
+#define WM8993_VROI_SHIFT                            0  /* VROI */
+#define WM8993_VROI_WIDTH                            1  /* VROI */
+
+/*
+ * R56 (0x38) - AntiPOP1
+ */
+#define WM8993_LINEOUT_VMID_BUF_ENA             0x0080  /* LINEOUT_VMID_BUF_ENA */
+#define WM8993_LINEOUT_VMID_BUF_ENA_MASK        0x0080  /* LINEOUT_VMID_BUF_ENA */
+#define WM8993_LINEOUT_VMID_BUF_ENA_SHIFT            7  /* LINEOUT_VMID_BUF_ENA */
+#define WM8993_LINEOUT_VMID_BUF_ENA_WIDTH            1  /* LINEOUT_VMID_BUF_ENA */
+#define WM8993_HPOUT2_IN_ENA                    0x0040  /* HPOUT2_IN_ENA */
+#define WM8993_HPOUT2_IN_ENA_MASK               0x0040  /* HPOUT2_IN_ENA */
+#define WM8993_HPOUT2_IN_ENA_SHIFT                   6  /* HPOUT2_IN_ENA */
+#define WM8993_HPOUT2_IN_ENA_WIDTH                   1  /* HPOUT2_IN_ENA */
+#define WM8993_LINEOUT1_DISCH                   0x0020  /* LINEOUT1_DISCH */
+#define WM8993_LINEOUT1_DISCH_MASK              0x0020  /* LINEOUT1_DISCH */
+#define WM8993_LINEOUT1_DISCH_SHIFT                  5  /* LINEOUT1_DISCH */
+#define WM8993_LINEOUT1_DISCH_WIDTH                  1  /* LINEOUT1_DISCH */
+#define WM8993_LINEOUT2_DISCH                   0x0010  /* LINEOUT2_DISCH */
+#define WM8993_LINEOUT2_DISCH_MASK              0x0010  /* LINEOUT2_DISCH */
+#define WM8993_LINEOUT2_DISCH_SHIFT                  4  /* LINEOUT2_DISCH */
+#define WM8993_LINEOUT2_DISCH_WIDTH                  1  /* LINEOUT2_DISCH */
+
+/*
+ * R57 (0x39) - AntiPOP2
+ */
+#define WM8993_VMID_RAMP_MASK                   0x0060  /* VMID_RAMP - [6:5] */
+#define WM8993_VMID_RAMP_SHIFT                       5  /* VMID_RAMP - [6:5] */
+#define WM8993_VMID_RAMP_WIDTH                       2  /* VMID_RAMP - [6:5] */
+#define WM8993_VMID_BUF_ENA                     0x0008  /* VMID_BUF_ENA */
+#define WM8993_VMID_BUF_ENA_MASK                0x0008  /* VMID_BUF_ENA */
+#define WM8993_VMID_BUF_ENA_SHIFT                    3  /* VMID_BUF_ENA */
+#define WM8993_VMID_BUF_ENA_WIDTH                    1  /* VMID_BUF_ENA */
+#define WM8993_STARTUP_BIAS_ENA                 0x0004  /* STARTUP_BIAS_ENA */
+#define WM8993_STARTUP_BIAS_ENA_MASK            0x0004  /* STARTUP_BIAS_ENA */
+#define WM8993_STARTUP_BIAS_ENA_SHIFT                2  /* STARTUP_BIAS_ENA */
+#define WM8993_STARTUP_BIAS_ENA_WIDTH                1  /* STARTUP_BIAS_ENA */
+#define WM8993_BIAS_SRC                         0x0002  /* BIAS_SRC */
+#define WM8993_BIAS_SRC_MASK                    0x0002  /* BIAS_SRC */
+#define WM8993_BIAS_SRC_SHIFT                        1  /* BIAS_SRC */
+#define WM8993_BIAS_SRC_WIDTH                        1  /* BIAS_SRC */
+#define WM8993_VMID_DISCH                       0x0001  /* VMID_DISCH */
+#define WM8993_VMID_DISCH_MASK                  0x0001  /* VMID_DISCH */
+#define WM8993_VMID_DISCH_SHIFT                      0  /* VMID_DISCH */
+#define WM8993_VMID_DISCH_WIDTH                      1  /* VMID_DISCH */
+
+/*
+ * R58 (0x3A) - MICBIAS
+ */
+#define WM8993_JD_SCTHR_MASK                    0x00C0  /* JD_SCTHR - [7:6] */
+#define WM8993_JD_SCTHR_SHIFT                        6  /* JD_SCTHR - [7:6] */
+#define WM8993_JD_SCTHR_WIDTH                        2  /* JD_SCTHR - [7:6] */
+#define WM8993_JD_THR_MASK                      0x0030  /* JD_THR - [5:4] */
+#define WM8993_JD_THR_SHIFT                          4  /* JD_THR - [5:4] */
+#define WM8993_JD_THR_WIDTH                          2  /* JD_THR - [5:4] */
+#define WM8993_JD_ENA                           0x0004  /* JD_ENA */
+#define WM8993_JD_ENA_MASK                      0x0004  /* JD_ENA */
+#define WM8993_JD_ENA_SHIFT                          2  /* JD_ENA */
+#define WM8993_JD_ENA_WIDTH                          1  /* JD_ENA */
+#define WM8993_MICB2_LVL                        0x0002  /* MICB2_LVL */
+#define WM8993_MICB2_LVL_MASK                   0x0002  /* MICB2_LVL */
+#define WM8993_MICB2_LVL_SHIFT                       1  /* MICB2_LVL */
+#define WM8993_MICB2_LVL_WIDTH                       1  /* MICB2_LVL */
+#define WM8993_MICB1_LVL                        0x0001  /* MICB1_LVL */
+#define WM8993_MICB1_LVL_MASK                   0x0001  /* MICB1_LVL */
+#define WM8993_MICB1_LVL_SHIFT                       0  /* MICB1_LVL */
+#define WM8993_MICB1_LVL_WIDTH                       1  /* MICB1_LVL */
+
+/*
+ * R60 (0x3C) - FLL Control 1
+ */
+#define WM8993_FLL_FRAC                         0x0004  /* FLL_FRAC */
+#define WM8993_FLL_FRAC_MASK                    0x0004  /* FLL_FRAC */
+#define WM8993_FLL_FRAC_SHIFT                        2  /* FLL_FRAC */
+#define WM8993_FLL_FRAC_WIDTH                        1  /* FLL_FRAC */
+#define WM8993_FLL_OSC_ENA                      0x0002  /* FLL_OSC_ENA */
+#define WM8993_FLL_OSC_ENA_MASK                 0x0002  /* FLL_OSC_ENA */
+#define WM8993_FLL_OSC_ENA_SHIFT                     1  /* FLL_OSC_ENA */
+#define WM8993_FLL_OSC_ENA_WIDTH                     1  /* FLL_OSC_ENA */
+#define WM8993_FLL_ENA                          0x0001  /* FLL_ENA */
+#define WM8993_FLL_ENA_MASK                     0x0001  /* FLL_ENA */
+#define WM8993_FLL_ENA_SHIFT                         0  /* FLL_ENA */
+#define WM8993_FLL_ENA_WIDTH                         1  /* FLL_ENA */
+
+/*
+ * R61 (0x3D) - FLL Control 2
+ */
+#define WM8993_FLL_OUTDIV_MASK                  0x0700  /* FLL_OUTDIV - [10:8] */
+#define WM8993_FLL_OUTDIV_SHIFT                      8  /* FLL_OUTDIV - [10:8] */
+#define WM8993_FLL_OUTDIV_WIDTH                      3  /* FLL_OUTDIV - [10:8] */
+#define WM8993_FLL_CTRL_RATE_MASK               0x0070  /* FLL_CTRL_RATE - [6:4] */
+#define WM8993_FLL_CTRL_RATE_SHIFT                   4  /* FLL_CTRL_RATE - [6:4] */
+#define WM8993_FLL_CTRL_RATE_WIDTH                   3  /* FLL_CTRL_RATE - [6:4] */
+#define WM8993_FLL_FRATIO_MASK                  0x0007  /* FLL_FRATIO - [2:0] */
+#define WM8993_FLL_FRATIO_SHIFT                      0  /* FLL_FRATIO - [2:0] */
+#define WM8993_FLL_FRATIO_WIDTH                      3  /* FLL_FRATIO - [2:0] */
+
+/*
+ * R62 (0x3E) - FLL Control 3
+ */
+#define WM8993_FLL_K_MASK                       0xFFFF  /* FLL_K - [15:0] */
+#define WM8993_FLL_K_SHIFT                           0  /* FLL_K - [15:0] */
+#define WM8993_FLL_K_WIDTH                          16  /* FLL_K - [15:0] */
+
+/*
+ * R63 (0x3F) - FLL Control 4
+ */
+#define WM8993_FLL_N_MASK                       0x7FE0  /* FLL_N - [14:5] */
+#define WM8993_FLL_N_SHIFT                           5  /* FLL_N - [14:5] */
+#define WM8993_FLL_N_WIDTH                          10  /* FLL_N - [14:5] */
+#define WM8993_FLL_GAIN_MASK                    0x000F  /* FLL_GAIN - [3:0] */
+#define WM8993_FLL_GAIN_SHIFT                        0  /* FLL_GAIN - [3:0] */
+#define WM8993_FLL_GAIN_WIDTH                        4  /* FLL_GAIN - [3:0] */
+
+/*
+ * R64 (0x40) - FLL Control 5
+ */
+#define WM8993_FLL_FRC_NCO_VAL_MASK             0x1F80  /* FLL_FRC_NCO_VAL - [12:7] */
+#define WM8993_FLL_FRC_NCO_VAL_SHIFT                 7  /* FLL_FRC_NCO_VAL - [12:7] */
+#define WM8993_FLL_FRC_NCO_VAL_WIDTH                 6  /* FLL_FRC_NCO_VAL - [12:7] */
+#define WM8993_FLL_FRC_NCO                      0x0040  /* FLL_FRC_NCO */
+#define WM8993_FLL_FRC_NCO_MASK                 0x0040  /* FLL_FRC_NCO */
+#define WM8993_FLL_FRC_NCO_SHIFT                     6  /* FLL_FRC_NCO */
+#define WM8993_FLL_FRC_NCO_WIDTH                     1  /* FLL_FRC_NCO */
+#define WM8993_FLL_CLK_REF_DIV_MASK             0x0018  /* FLL_CLK_REF_DIV - [4:3] */
+#define WM8993_FLL_CLK_REF_DIV_SHIFT                 3  /* FLL_CLK_REF_DIV - [4:3] */
+#define WM8993_FLL_CLK_REF_DIV_WIDTH                 2  /* FLL_CLK_REF_DIV - [4:3] */
+#define WM8993_FLL_CLK_SRC_MASK                 0x0003  /* FLL_CLK_SRC - [1:0] */
+#define WM8993_FLL_CLK_SRC_SHIFT                     0  /* FLL_CLK_SRC - [1:0] */
+#define WM8993_FLL_CLK_SRC_WIDTH                     2  /* FLL_CLK_SRC - [1:0] */
+
+/*
+ * R65 (0x41) - Clocking 3
+ */
+#define WM8993_CLK_DCS_DIV_MASK                 0x3C00  /* CLK_DCS_DIV - [13:10] */
+#define WM8993_CLK_DCS_DIV_SHIFT                    10  /* CLK_DCS_DIV - [13:10] */
+#define WM8993_CLK_DCS_DIV_WIDTH                     4  /* CLK_DCS_DIV - [13:10] */
+#define WM8993_SAMPLE_RATE_MASK                 0x0380  /* SAMPLE_RATE - [9:7] */
+#define WM8993_SAMPLE_RATE_SHIFT                     7  /* SAMPLE_RATE - [9:7] */
+#define WM8993_SAMPLE_RATE_WIDTH                     3  /* SAMPLE_RATE - [9:7] */
+#define WM8993_CLK_SYS_RATE_MASK                0x001E  /* CLK_SYS_RATE - [4:1] */
+#define WM8993_CLK_SYS_RATE_SHIFT                    1  /* CLK_SYS_RATE - [4:1] */
+#define WM8993_CLK_SYS_RATE_WIDTH                    4  /* CLK_SYS_RATE - [4:1] */
+#define WM8993_CLK_DSP_ENA                      0x0001  /* CLK_DSP_ENA */
+#define WM8993_CLK_DSP_ENA_MASK                 0x0001  /* CLK_DSP_ENA */
+#define WM8993_CLK_DSP_ENA_SHIFT                     0  /* CLK_DSP_ENA */
+#define WM8993_CLK_DSP_ENA_WIDTH                     1  /* CLK_DSP_ENA */
+
+/*
+ * R66 (0x42) - Clocking 4
+ */
+#define WM8993_DAC_DIV4                         0x0200  /* DAC_DIV4 */
+#define WM8993_DAC_DIV4_MASK                    0x0200  /* DAC_DIV4 */
+#define WM8993_DAC_DIV4_SHIFT                        9  /* DAC_DIV4 */
+#define WM8993_DAC_DIV4_WIDTH                        1  /* DAC_DIV4 */
+#define WM8993_CLK_256K_DIV_MASK                0x007E  /* CLK_256K_DIV - [6:1] */
+#define WM8993_CLK_256K_DIV_SHIFT                    1  /* CLK_256K_DIV - [6:1] */
+#define WM8993_CLK_256K_DIV_WIDTH                    6  /* CLK_256K_DIV - [6:1] */
+#define WM8993_SR_MODE                          0x0001  /* SR_MODE */
+#define WM8993_SR_MODE_MASK                     0x0001  /* SR_MODE */
+#define WM8993_SR_MODE_SHIFT                         0  /* SR_MODE */
+#define WM8993_SR_MODE_WIDTH                         1  /* SR_MODE */
+
+/*
+ * R67 (0x43) - MW Slave Control
+ */
+#define WM8993_MASK_WRITE_ENA                   0x0001  /* MASK_WRITE_ENA */
+#define WM8993_MASK_WRITE_ENA_MASK              0x0001  /* MASK_WRITE_ENA */
+#define WM8993_MASK_WRITE_ENA_SHIFT                  0  /* MASK_WRITE_ENA */
+#define WM8993_MASK_WRITE_ENA_WIDTH                  1  /* MASK_WRITE_ENA */
+
+/*
+ * R69 (0x45) - Bus Control 1
+ */
+#define WM8993_CLK_SYS_ENA                      0x0002  /* CLK_SYS_ENA */
+#define WM8993_CLK_SYS_ENA_MASK                 0x0002  /* CLK_SYS_ENA */
+#define WM8993_CLK_SYS_ENA_SHIFT                     1  /* CLK_SYS_ENA */
+#define WM8993_CLK_SYS_ENA_WIDTH                     1  /* CLK_SYS_ENA */
+
+/*
+ * R70 (0x46) - Write Sequencer 0
+ */
+#define WM8993_WSEQ_ENA                         0x0100  /* WSEQ_ENA */
+#define WM8993_WSEQ_ENA_MASK                    0x0100  /* WSEQ_ENA */
+#define WM8993_WSEQ_ENA_SHIFT                        8  /* WSEQ_ENA */
+#define WM8993_WSEQ_ENA_WIDTH                        1  /* WSEQ_ENA */
+#define WM8993_WSEQ_WRITE_INDEX_MASK            0x001F  /* WSEQ_WRITE_INDEX - [4:0] */
+#define WM8993_WSEQ_WRITE_INDEX_SHIFT                0  /* WSEQ_WRITE_INDEX - [4:0] */
+#define WM8993_WSEQ_WRITE_INDEX_WIDTH                5  /* WSEQ_WRITE_INDEX - [4:0] */
+
+/*
+ * R71 (0x47) - Write Sequencer 1
+ */
+#define WM8993_WSEQ_DATA_WIDTH_MASK             0x7000  /* WSEQ_DATA_WIDTH - [14:12] */
+#define WM8993_WSEQ_DATA_WIDTH_SHIFT                12  /* WSEQ_DATA_WIDTH - [14:12] */
+#define WM8993_WSEQ_DATA_WIDTH_WIDTH                 3  /* WSEQ_DATA_WIDTH - [14:12] */
+#define WM8993_WSEQ_DATA_START_MASK             0x0F00  /* WSEQ_DATA_START - [11:8] */
+#define WM8993_WSEQ_DATA_START_SHIFT                 8  /* WSEQ_DATA_START - [11:8] */
+#define WM8993_WSEQ_DATA_START_WIDTH                 4  /* WSEQ_DATA_START - [11:8] */
+#define WM8993_WSEQ_ADDR_MASK                   0x00FF  /* WSEQ_ADDR - [7:0] */
+#define WM8993_WSEQ_ADDR_SHIFT                       0  /* WSEQ_ADDR - [7:0] */
+#define WM8993_WSEQ_ADDR_WIDTH                       8  /* WSEQ_ADDR - [7:0] */
+
+/*
+ * R72 (0x48) - Write Sequencer 2
+ */
+#define WM8993_WSEQ_EOS                         0x4000  /* WSEQ_EOS */
+#define WM8993_WSEQ_EOS_MASK                    0x4000  /* WSEQ_EOS */
+#define WM8993_WSEQ_EOS_SHIFT                       14  /* WSEQ_EOS */
+#define WM8993_WSEQ_EOS_WIDTH                        1  /* WSEQ_EOS */
+#define WM8993_WSEQ_DELAY_MASK                  0x0F00  /* WSEQ_DELAY - [11:8] */
+#define WM8993_WSEQ_DELAY_SHIFT                      8  /* WSEQ_DELAY - [11:8] */
+#define WM8993_WSEQ_DELAY_WIDTH                      4  /* WSEQ_DELAY - [11:8] */
+#define WM8993_WSEQ_DATA_MASK                   0x00FF  /* WSEQ_DATA - [7:0] */
+#define WM8993_WSEQ_DATA_SHIFT                       0  /* WSEQ_DATA - [7:0] */
+#define WM8993_WSEQ_DATA_WIDTH                       8  /* WSEQ_DATA - [7:0] */
+
+/*
+ * R73 (0x49) - Write Sequencer 3
+ */
+#define WM8993_WSEQ_ABORT                       0x0200  /* WSEQ_ABORT */
+#define WM8993_WSEQ_ABORT_MASK                  0x0200  /* WSEQ_ABORT */
+#define WM8993_WSEQ_ABORT_SHIFT                      9  /* WSEQ_ABORT */
+#define WM8993_WSEQ_ABORT_WIDTH                      1  /* WSEQ_ABORT */
+#define WM8993_WSEQ_START                       0x0100  /* WSEQ_START */
+#define WM8993_WSEQ_START_MASK                  0x0100  /* WSEQ_START */
+#define WM8993_WSEQ_START_SHIFT                      8  /* WSEQ_START */
+#define WM8993_WSEQ_START_WIDTH                      1  /* WSEQ_START */
+#define WM8993_WSEQ_START_INDEX_MASK            0x003F  /* WSEQ_START_INDEX - [5:0] */
+#define WM8993_WSEQ_START_INDEX_SHIFT                0  /* WSEQ_START_INDEX - [5:0] */
+#define WM8993_WSEQ_START_INDEX_WIDTH                6  /* WSEQ_START_INDEX - [5:0] */
+
+/*
+ * R74 (0x4A) - Write Sequencer 4
+ */
+#define WM8993_WSEQ_BUSY                        0x0001  /* WSEQ_BUSY */
+#define WM8993_WSEQ_BUSY_MASK                   0x0001  /* WSEQ_BUSY */
+#define WM8993_WSEQ_BUSY_SHIFT                       0  /* WSEQ_BUSY */
+#define WM8993_WSEQ_BUSY_WIDTH                       1  /* WSEQ_BUSY */
+
+/*
+ * R75 (0x4B) - Write Sequencer 5
+ */
+#define WM8993_WSEQ_CURRENT_INDEX_MASK          0x003F  /* WSEQ_CURRENT_INDEX - [5:0] */
+#define WM8993_WSEQ_CURRENT_INDEX_SHIFT              0  /* WSEQ_CURRENT_INDEX - [5:0] */
+#define WM8993_WSEQ_CURRENT_INDEX_WIDTH              6  /* WSEQ_CURRENT_INDEX - [5:0] */
+
+/*
+ * R76 (0x4C) - Charge Pump 1
+ */
+#define WM8993_CP_ENA                           0x8000  /* CP_ENA */
+#define WM8993_CP_ENA_MASK                      0x8000  /* CP_ENA */
+#define WM8993_CP_ENA_SHIFT                         15  /* CP_ENA */
+#define WM8993_CP_ENA_WIDTH                          1  /* CP_ENA */
+
+/*
+ * R81 (0x51) - Class W 0
+ */
+#define WM8993_CP_DYN_FREQ                      0x0002  /* CP_DYN_FREQ */
+#define WM8993_CP_DYN_FREQ_MASK                 0x0002  /* CP_DYN_FREQ */
+#define WM8993_CP_DYN_FREQ_SHIFT                     1  /* CP_DYN_FREQ */
+#define WM8993_CP_DYN_FREQ_WIDTH                     1  /* CP_DYN_FREQ */
+#define WM8993_CP_DYN_V                         0x0001  /* CP_DYN_V */
+#define WM8993_CP_DYN_V_MASK                    0x0001  /* CP_DYN_V */
+#define WM8993_CP_DYN_V_SHIFT                        0  /* CP_DYN_V */
+#define WM8993_CP_DYN_V_WIDTH                        1  /* CP_DYN_V */
+
+/*
+ * R84 (0x54) - DC Servo 0
+ */
+#define WM8993_DCS_TRIG_SINGLE_1                0x2000  /* DCS_TRIG_SINGLE_1 */
+#define WM8993_DCS_TRIG_SINGLE_1_MASK           0x2000  /* DCS_TRIG_SINGLE_1 */
+#define WM8993_DCS_TRIG_SINGLE_1_SHIFT              13  /* DCS_TRIG_SINGLE_1 */
+#define WM8993_DCS_TRIG_SINGLE_1_WIDTH               1  /* DCS_TRIG_SINGLE_1 */
+#define WM8993_DCS_TRIG_SINGLE_0                0x1000  /* DCS_TRIG_SINGLE_0 */
+#define WM8993_DCS_TRIG_SINGLE_0_MASK           0x1000  /* DCS_TRIG_SINGLE_0 */
+#define WM8993_DCS_TRIG_SINGLE_0_SHIFT              12  /* DCS_TRIG_SINGLE_0 */
+#define WM8993_DCS_TRIG_SINGLE_0_WIDTH               1  /* DCS_TRIG_SINGLE_0 */
+#define WM8993_DCS_TRIG_SERIES_1                0x0200  /* DCS_TRIG_SERIES_1 */
+#define WM8993_DCS_TRIG_SERIES_1_MASK           0x0200  /* DCS_TRIG_SERIES_1 */
+#define WM8993_DCS_TRIG_SERIES_1_SHIFT               9  /* DCS_TRIG_SERIES_1 */
+#define WM8993_DCS_TRIG_SERIES_1_WIDTH               1  /* DCS_TRIG_SERIES_1 */
+#define WM8993_DCS_TRIG_SERIES_0                0x0100  /* DCS_TRIG_SERIES_0 */
+#define WM8993_DCS_TRIG_SERIES_0_MASK           0x0100  /* DCS_TRIG_SERIES_0 */
+#define WM8993_DCS_TRIG_SERIES_0_SHIFT               8  /* DCS_TRIG_SERIES_0 */
+#define WM8993_DCS_TRIG_SERIES_0_WIDTH               1  /* DCS_TRIG_SERIES_0 */
+#define WM8993_DCS_TRIG_STARTUP_1               0x0020  /* DCS_TRIG_STARTUP_1 */
+#define WM8993_DCS_TRIG_STARTUP_1_MASK          0x0020  /* DCS_TRIG_STARTUP_1 */
+#define WM8993_DCS_TRIG_STARTUP_1_SHIFT              5  /* DCS_TRIG_STARTUP_1 */
+#define WM8993_DCS_TRIG_STARTUP_1_WIDTH              1  /* DCS_TRIG_STARTUP_1 */
+#define WM8993_DCS_TRIG_STARTUP_0               0x0010  /* DCS_TRIG_STARTUP_0 */
+#define WM8993_DCS_TRIG_STARTUP_0_MASK          0x0010  /* DCS_TRIG_STARTUP_0 */
+#define WM8993_DCS_TRIG_STARTUP_0_SHIFT              4  /* DCS_TRIG_STARTUP_0 */
+#define WM8993_DCS_TRIG_STARTUP_0_WIDTH              1  /* DCS_TRIG_STARTUP_0 */
+#define WM8993_DCS_TRIG_DAC_WR_1                0x0008  /* DCS_TRIG_DAC_WR_1 */
+#define WM8993_DCS_TRIG_DAC_WR_1_MASK           0x0008  /* DCS_TRIG_DAC_WR_1 */
+#define WM8993_DCS_TRIG_DAC_WR_1_SHIFT               3  /* DCS_TRIG_DAC_WR_1 */
+#define WM8993_DCS_TRIG_DAC_WR_1_WIDTH               1  /* DCS_TRIG_DAC_WR_1 */
+#define WM8993_DCS_TRIG_DAC_WR_0                0x0004  /* DCS_TRIG_DAC_WR_0 */
+#define WM8993_DCS_TRIG_DAC_WR_0_MASK           0x0004  /* DCS_TRIG_DAC_WR_0 */
+#define WM8993_DCS_TRIG_DAC_WR_0_SHIFT               2  /* DCS_TRIG_DAC_WR_0 */
+#define WM8993_DCS_TRIG_DAC_WR_0_WIDTH               1  /* DCS_TRIG_DAC_WR_0 */
+#define WM8993_DCS_ENA_CHAN_1                   0x0002  /* DCS_ENA_CHAN_1 */
+#define WM8993_DCS_ENA_CHAN_1_MASK              0x0002  /* DCS_ENA_CHAN_1 */
+#define WM8993_DCS_ENA_CHAN_1_SHIFT                  1  /* DCS_ENA_CHAN_1 */
+#define WM8993_DCS_ENA_CHAN_1_WIDTH                  1  /* DCS_ENA_CHAN_1 */
+#define WM8993_DCS_ENA_CHAN_0                   0x0001  /* DCS_ENA_CHAN_0 */
+#define WM8993_DCS_ENA_CHAN_0_MASK              0x0001  /* DCS_ENA_CHAN_0 */
+#define WM8993_DCS_ENA_CHAN_0_SHIFT                  0  /* DCS_ENA_CHAN_0 */
+#define WM8993_DCS_ENA_CHAN_0_WIDTH                  1  /* DCS_ENA_CHAN_0 */
+
+/*
+ * R85 (0x55) - DC Servo 1
+ */
+#define WM8993_DCS_SERIES_NO_01_MASK            0x0FE0  /* DCS_SERIES_NO_01 - [11:5] */
+#define WM8993_DCS_SERIES_NO_01_SHIFT                5  /* DCS_SERIES_NO_01 - [11:5] */
+#define WM8993_DCS_SERIES_NO_01_WIDTH                7  /* DCS_SERIES_NO_01 - [11:5] */
+#define WM8993_DCS_TIMER_PERIOD_01_MASK         0x000F  /* DCS_TIMER_PERIOD_01 - [3:0] */
+#define WM8993_DCS_TIMER_PERIOD_01_SHIFT             0  /* DCS_TIMER_PERIOD_01 - [3:0] */
+#define WM8993_DCS_TIMER_PERIOD_01_WIDTH             4  /* DCS_TIMER_PERIOD_01 - [3:0] */
+
+/*
+ * R87 (0x57) - DC Servo 3
+ */
+#define WM8993_DCS_DAC_WR_VAL_1_MASK            0xFF00  /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8993_DCS_DAC_WR_VAL_1_SHIFT                8  /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8993_DCS_DAC_WR_VAL_1_WIDTH                8  /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8993_DCS_DAC_WR_VAL_0_MASK            0x00FF  /* DCS_DAC_WR_VAL_0 - [7:0] */
+#define WM8993_DCS_DAC_WR_VAL_0_SHIFT                0  /* DCS_DAC_WR_VAL_0 - [7:0] */
+#define WM8993_DCS_DAC_WR_VAL_0_WIDTH                8  /* DCS_DAC_WR_VAL_0 - [7:0] */
+
+/*
+ * R88 (0x58) - DC Servo Readback 0
+ */
+#define WM8993_DCS_DATAPATH_BUSY                0x4000  /* DCS_DATAPATH_BUSY */
+#define WM8993_DCS_DATAPATH_BUSY_MASK           0x4000  /* DCS_DATAPATH_BUSY */
+#define WM8993_DCS_DATAPATH_BUSY_SHIFT              14  /* DCS_DATAPATH_BUSY */
+#define WM8993_DCS_DATAPATH_BUSY_WIDTH               1  /* DCS_DATAPATH_BUSY */
+#define WM8993_DCS_CHANNEL_MASK                 0x3000  /* DCS_CHANNEL - [13:12] */
+#define WM8993_DCS_CHANNEL_SHIFT                    12  /* DCS_CHANNEL - [13:12] */
+#define WM8993_DCS_CHANNEL_WIDTH                     2  /* DCS_CHANNEL - [13:12] */
+#define WM8993_DCS_CAL_COMPLETE_MASK            0x0300  /* DCS_CAL_COMPLETE - [9:8] */
+#define WM8993_DCS_CAL_COMPLETE_SHIFT                8  /* DCS_CAL_COMPLETE - [9:8] */
+#define WM8993_DCS_CAL_COMPLETE_WIDTH                2  /* DCS_CAL_COMPLETE - [9:8] */
+#define WM8993_DCS_DAC_WR_COMPLETE_MASK         0x0030  /* DCS_DAC_WR_COMPLETE - [5:4] */
+#define WM8993_DCS_DAC_WR_COMPLETE_SHIFT             4  /* DCS_DAC_WR_COMPLETE - [5:4] */
+#define WM8993_DCS_DAC_WR_COMPLETE_WIDTH             2  /* DCS_DAC_WR_COMPLETE - [5:4] */
+#define WM8993_DCS_STARTUP_COMPLETE_MASK        0x0003  /* DCS_STARTUP_COMPLETE - [1:0] */
+#define WM8993_DCS_STARTUP_COMPLETE_SHIFT            0  /* DCS_STARTUP_COMPLETE - [1:0] */
+#define WM8993_DCS_STARTUP_COMPLETE_WIDTH            2  /* DCS_STARTUP_COMPLETE - [1:0] */
+
+/*
+ * R89 (0x59) - DC Servo Readback 1
+ */
+#define WM8993_DCS_INTEG_CHAN_1_MASK            0x00FF  /* DCS_INTEG_CHAN_1 - [7:0] */
+#define WM8993_DCS_INTEG_CHAN_1_SHIFT                0  /* DCS_INTEG_CHAN_1 - [7:0] */
+#define WM8993_DCS_INTEG_CHAN_1_WIDTH                8  /* DCS_INTEG_CHAN_1 - [7:0] */
+
+/*
+ * R90 (0x5A) - DC Servo Readback 2
+ */
+#define WM8993_DCS_INTEG_CHAN_0_MASK            0x00FF  /* DCS_INTEG_CHAN_0 - [7:0] */
+#define WM8993_DCS_INTEG_CHAN_0_SHIFT                0  /* DCS_INTEG_CHAN_0 - [7:0] */
+#define WM8993_DCS_INTEG_CHAN_0_WIDTH                8  /* DCS_INTEG_CHAN_0 - [7:0] */
+
+/*
+ * R96 (0x60) - Analogue HP 0
+ */
+#define WM8993_HPOUT1_AUTO_PU                   0x0100  /* HPOUT1_AUTO_PU */
+#define WM8993_HPOUT1_AUTO_PU_MASK              0x0100  /* HPOUT1_AUTO_PU */
+#define WM8993_HPOUT1_AUTO_PU_SHIFT                  8  /* HPOUT1_AUTO_PU */
+#define WM8993_HPOUT1_AUTO_PU_WIDTH                  1  /* HPOUT1_AUTO_PU */
+#define WM8993_HPOUT1L_RMV_SHORT                0x0080  /* HPOUT1L_RMV_SHORT */
+#define WM8993_HPOUT1L_RMV_SHORT_MASK           0x0080  /* HPOUT1L_RMV_SHORT */
+#define WM8993_HPOUT1L_RMV_SHORT_SHIFT               7  /* HPOUT1L_RMV_SHORT */
+#define WM8993_HPOUT1L_RMV_SHORT_WIDTH               1  /* HPOUT1L_RMV_SHORT */
+#define WM8993_HPOUT1L_OUTP                     0x0040  /* HPOUT1L_OUTP */
+#define WM8993_HPOUT1L_OUTP_MASK                0x0040  /* HPOUT1L_OUTP */
+#define WM8993_HPOUT1L_OUTP_SHIFT                    6  /* HPOUT1L_OUTP */
+#define WM8993_HPOUT1L_OUTP_WIDTH                    1  /* HPOUT1L_OUTP */
+#define WM8993_HPOUT1L_DLY                      0x0020  /* HPOUT1L_DLY */
+#define WM8993_HPOUT1L_DLY_MASK                 0x0020  /* HPOUT1L_DLY */
+#define WM8993_HPOUT1L_DLY_SHIFT                     5  /* HPOUT1L_DLY */
+#define WM8993_HPOUT1L_DLY_WIDTH                     1  /* HPOUT1L_DLY */
+#define WM8993_HPOUT1R_RMV_SHORT                0x0008  /* HPOUT1R_RMV_SHORT */
+#define WM8993_HPOUT1R_RMV_SHORT_MASK           0x0008  /* HPOUT1R_RMV_SHORT */
+#define WM8993_HPOUT1R_RMV_SHORT_SHIFT               3  /* HPOUT1R_RMV_SHORT */
+#define WM8993_HPOUT1R_RMV_SHORT_WIDTH               1  /* HPOUT1R_RMV_SHORT */
+#define WM8993_HPOUT1R_OUTP                     0x0004  /* HPOUT1R_OUTP */
+#define WM8993_HPOUT1R_OUTP_MASK                0x0004  /* HPOUT1R_OUTP */
+#define WM8993_HPOUT1R_OUTP_SHIFT                    2  /* HPOUT1R_OUTP */
+#define WM8993_HPOUT1R_OUTP_WIDTH                    1  /* HPOUT1R_OUTP */
+#define WM8993_HPOUT1R_DLY                      0x0002  /* HPOUT1R_DLY */
+#define WM8993_HPOUT1R_DLY_MASK                 0x0002  /* HPOUT1R_DLY */
+#define WM8993_HPOUT1R_DLY_SHIFT                     1  /* HPOUT1R_DLY */
+#define WM8993_HPOUT1R_DLY_WIDTH                     1  /* HPOUT1R_DLY */
+
+/*
+ * R98 (0x62) - EQ1
+ */
+#define WM8993_EQ_ENA                           0x0001  /* EQ_ENA */
+#define WM8993_EQ_ENA_MASK                      0x0001  /* EQ_ENA */
+#define WM8993_EQ_ENA_SHIFT                          0  /* EQ_ENA */
+#define WM8993_EQ_ENA_WIDTH                          1  /* EQ_ENA */
+
+/*
+ * R99 (0x63) - EQ2
+ */
+#define WM8993_EQ_B1_GAIN_MASK                  0x001F  /* EQ_B1_GAIN - [4:0] */
+#define WM8993_EQ_B1_GAIN_SHIFT                      0  /* EQ_B1_GAIN - [4:0] */
+#define WM8993_EQ_B1_GAIN_WIDTH                      5  /* EQ_B1_GAIN - [4:0] */
+
+/*
+ * R100 (0x64) - EQ3
+ */
+#define WM8993_EQ_B2_GAIN_MASK                  0x001F  /* EQ_B2_GAIN - [4:0] */
+#define WM8993_EQ_B2_GAIN_SHIFT                      0  /* EQ_B2_GAIN - [4:0] */
+#define WM8993_EQ_B2_GAIN_WIDTH                      5  /* EQ_B2_GAIN - [4:0] */
+
+/*
+ * R101 (0x65) - EQ4
+ */
+#define WM8993_EQ_B3_GAIN_MASK                  0x001F  /* EQ_B3_GAIN - [4:0] */
+#define WM8993_EQ_B3_GAIN_SHIFT                      0  /* EQ_B3_GAIN - [4:0] */
+#define WM8993_EQ_B3_GAIN_WIDTH                      5  /* EQ_B3_GAIN - [4:0] */
+
+/*
+ * R102 (0x66) - EQ5
+ */
+#define WM8993_EQ_B4_GAIN_MASK                  0x001F  /* EQ_B4_GAIN - [4:0] */
+#define WM8993_EQ_B4_GAIN_SHIFT                      0  /* EQ_B4_GAIN - [4:0] */
+#define WM8993_EQ_B4_GAIN_WIDTH                      5  /* EQ_B4_GAIN - [4:0] */
+
+/*
+ * R103 (0x67) - EQ6
+ */
+#define WM8993_EQ_B5_GAIN_MASK                  0x001F  /* EQ_B5_GAIN - [4:0] */
+#define WM8993_EQ_B5_GAIN_SHIFT                      0  /* EQ_B5_GAIN - [4:0] */
+#define WM8993_EQ_B5_GAIN_WIDTH                      5  /* EQ_B5_GAIN - [4:0] */
+
+/*
+ * R104 (0x68) - EQ7
+ */
+#define WM8993_EQ_B1_A_MASK                     0xFFFF  /* EQ_B1_A - [15:0] */
+#define WM8993_EQ_B1_A_SHIFT                         0  /* EQ_B1_A - [15:0] */
+#define WM8993_EQ_B1_A_WIDTH                        16  /* EQ_B1_A - [15:0] */
+
+/*
+ * R105 (0x69) - EQ8
+ */
+#define WM8993_EQ_B1_B_MASK                     0xFFFF  /* EQ_B1_B - [15:0] */
+#define WM8993_EQ_B1_B_SHIFT                         0  /* EQ_B1_B - [15:0] */
+#define WM8993_EQ_B1_B_WIDTH                        16  /* EQ_B1_B - [15:0] */
+
+/*
+ * R106 (0x6A) - EQ9
+ */
+#define WM8993_EQ_B1_PG_MASK                    0xFFFF  /* EQ_B1_PG - [15:0] */
+#define WM8993_EQ_B1_PG_SHIFT                        0  /* EQ_B1_PG - [15:0] */
+#define WM8993_EQ_B1_PG_WIDTH                       16  /* EQ_B1_PG - [15:0] */
+
+/*
+ * R107 (0x6B) - EQ10
+ */
+#define WM8993_EQ_B2_A_MASK                     0xFFFF  /* EQ_B2_A - [15:0] */
+#define WM8993_EQ_B2_A_SHIFT                         0  /* EQ_B2_A - [15:0] */
+#define WM8993_EQ_B2_A_WIDTH                        16  /* EQ_B2_A - [15:0] */
+
+/*
+ * R108 (0x6C) - EQ11
+ */
+#define WM8993_EQ_B2_B_MASK                     0xFFFF  /* EQ_B2_B - [15:0] */
+#define WM8993_EQ_B2_B_SHIFT                         0  /* EQ_B2_B - [15:0] */
+#define WM8993_EQ_B2_B_WIDTH                        16  /* EQ_B2_B - [15:0] */
+
+/*
+ * R109 (0x6D) - EQ12
+ */
+#define WM8993_EQ_B2_C_MASK                     0xFFFF  /* EQ_B2_C - [15:0] */
+#define WM8993_EQ_B2_C_SHIFT                         0  /* EQ_B2_C - [15:0] */
+#define WM8993_EQ_B2_C_WIDTH                        16  /* EQ_B2_C - [15:0] */
+
+/*
+ * R110 (0x6E) - EQ13
+ */
+#define WM8993_EQ_B2_PG_MASK                    0xFFFF  /* EQ_B2_PG - [15:0] */
+#define WM8993_EQ_B2_PG_SHIFT                        0  /* EQ_B2_PG - [15:0] */
+#define WM8993_EQ_B2_PG_WIDTH                       16  /* EQ_B2_PG - [15:0] */
+
+/*
+ * R111 (0x6F) - EQ14
+ */
+#define WM8993_EQ_B3_A_MASK                     0xFFFF  /* EQ_B3_A - [15:0] */
+#define WM8993_EQ_B3_A_SHIFT                         0  /* EQ_B3_A - [15:0] */
+#define WM8993_EQ_B3_A_WIDTH                        16  /* EQ_B3_A - [15:0] */
+
+/*
+ * R112 (0x70) - EQ15
+ */
+#define WM8993_EQ_B3_B_MASK                     0xFFFF  /* EQ_B3_B - [15:0] */
+#define WM8993_EQ_B3_B_SHIFT                         0  /* EQ_B3_B - [15:0] */
+#define WM8993_EQ_B3_B_WIDTH                        16  /* EQ_B3_B - [15:0] */
+
+/*
+ * R113 (0x71) - EQ16
+ */
+#define WM8993_EQ_B3_C_MASK                     0xFFFF  /* EQ_B3_C - [15:0] */
+#define WM8993_EQ_B3_C_SHIFT                         0  /* EQ_B3_C - [15:0] */
+#define WM8993_EQ_B3_C_WIDTH                        16  /* EQ_B3_C - [15:0] */
+
+/*
+ * R114 (0x72) - EQ17
+ */
+#define WM8993_EQ_B3_PG_MASK                    0xFFFF  /* EQ_B3_PG - [15:0] */
+#define WM8993_EQ_B3_PG_SHIFT                        0  /* EQ_B3_PG - [15:0] */
+#define WM8993_EQ_B3_PG_WIDTH                       16  /* EQ_B3_PG - [15:0] */
+
+/*
+ * R115 (0x73) - EQ18
+ */
+#define WM8993_EQ_B4_A_MASK                     0xFFFF  /* EQ_B4_A - [15:0] */
+#define WM8993_EQ_B4_A_SHIFT                         0  /* EQ_B4_A - [15:0] */
+#define WM8993_EQ_B4_A_WIDTH                        16  /* EQ_B4_A - [15:0] */
+
+/*
+ * R116 (0x74) - EQ19
+ */
+#define WM8993_EQ_B4_B_MASK                     0xFFFF  /* EQ_B4_B - [15:0] */
+#define WM8993_EQ_B4_B_SHIFT                         0  /* EQ_B4_B - [15:0] */
+#define WM8993_EQ_B4_B_WIDTH                        16  /* EQ_B4_B - [15:0] */
+
+/*
+ * R117 (0x75) - EQ20
+ */
+#define WM8993_EQ_B4_C_MASK                     0xFFFF  /* EQ_B4_C - [15:0] */
+#define WM8993_EQ_B4_C_SHIFT                         0  /* EQ_B4_C - [15:0] */
+#define WM8993_EQ_B4_C_WIDTH                        16  /* EQ_B4_C - [15:0] */
+
+/*
+ * R118 (0x76) - EQ21
+ */
+#define WM8993_EQ_B4_PG_MASK                    0xFFFF  /* EQ_B4_PG - [15:0] */
+#define WM8993_EQ_B4_PG_SHIFT                        0  /* EQ_B4_PG - [15:0] */
+#define WM8993_EQ_B4_PG_WIDTH                       16  /* EQ_B4_PG - [15:0] */
+
+/*
+ * R119 (0x77) - EQ22
+ */
+#define WM8993_EQ_B5_A_MASK                     0xFFFF  /* EQ_B5_A - [15:0] */
+#define WM8993_EQ_B5_A_SHIFT                         0  /* EQ_B5_A - [15:0] */
+#define WM8993_EQ_B5_A_WIDTH                        16  /* EQ_B5_A - [15:0] */
+
+/*
+ * R120 (0x78) - EQ23
+ */
+#define WM8993_EQ_B5_B_MASK                     0xFFFF  /* EQ_B5_B - [15:0] */
+#define WM8993_EQ_B5_B_SHIFT                         0  /* EQ_B5_B - [15:0] */
+#define WM8993_EQ_B5_B_WIDTH                        16  /* EQ_B5_B - [15:0] */
+
+/*
+ * R121 (0x79) - EQ24
+ */
+#define WM8993_EQ_B5_PG_MASK                    0xFFFF  /* EQ_B5_PG - [15:0] */
+#define WM8993_EQ_B5_PG_SHIFT                        0  /* EQ_B5_PG - [15:0] */
+#define WM8993_EQ_B5_PG_WIDTH                       16  /* EQ_B5_PG - [15:0] */
+
+/*
+ * R122 (0x7A) - Digital Pulls
+ */
+#define WM8993_MCLK_PU                          0x0080  /* MCLK_PU */
+#define WM8993_MCLK_PU_MASK                     0x0080  /* MCLK_PU */
+#define WM8993_MCLK_PU_SHIFT                         7  /* MCLK_PU */
+#define WM8993_MCLK_PU_WIDTH                         1  /* MCLK_PU */
+#define WM8993_MCLK_PD                          0x0040  /* MCLK_PD */
+#define WM8993_MCLK_PD_MASK                     0x0040  /* MCLK_PD */
+#define WM8993_MCLK_PD_SHIFT                         6  /* MCLK_PD */
+#define WM8993_MCLK_PD_WIDTH                         1  /* MCLK_PD */
+#define WM8993_DACDAT_PU                        0x0020  /* DACDAT_PU */
+#define WM8993_DACDAT_PU_MASK                   0x0020  /* DACDAT_PU */
+#define WM8993_DACDAT_PU_SHIFT                       5  /* DACDAT_PU */
+#define WM8993_DACDAT_PU_WIDTH                       1  /* DACDAT_PU */
+#define WM8993_DACDAT_PD                        0x0010  /* DACDAT_PD */
+#define WM8993_DACDAT_PD_MASK                   0x0010  /* DACDAT_PD */
+#define WM8993_DACDAT_PD_SHIFT                       4  /* DACDAT_PD */
+#define WM8993_DACDAT_PD_WIDTH                       1  /* DACDAT_PD */
+#define WM8993_LRCLK_PU                         0x0008  /* LRCLK_PU */
+#define WM8993_LRCLK_PU_MASK                    0x0008  /* LRCLK_PU */
+#define WM8993_LRCLK_PU_SHIFT                        3  /* LRCLK_PU */
+#define WM8993_LRCLK_PU_WIDTH                        1  /* LRCLK_PU */
+#define WM8993_LRCLK_PD                         0x0004  /* LRCLK_PD */
+#define WM8993_LRCLK_PD_MASK                    0x0004  /* LRCLK_PD */
+#define WM8993_LRCLK_PD_SHIFT                        2  /* LRCLK_PD */
+#define WM8993_LRCLK_PD_WIDTH                        1  /* LRCLK_PD */
+#define WM8993_BCLK_PU                          0x0002  /* BCLK_PU */
+#define WM8993_BCLK_PU_MASK                     0x0002  /* BCLK_PU */
+#define WM8993_BCLK_PU_SHIFT                         1  /* BCLK_PU */
+#define WM8993_BCLK_PU_WIDTH                         1  /* BCLK_PU */
+#define WM8993_BCLK_PD                          0x0001  /* BCLK_PD */
+#define WM8993_BCLK_PD_MASK                     0x0001  /* BCLK_PD */
+#define WM8993_BCLK_PD_SHIFT                         0  /* BCLK_PD */
+#define WM8993_BCLK_PD_WIDTH                         1  /* BCLK_PD */
+
+/*
+ * R123 (0x7B) - DRC Control 1
+ */
+#define WM8993_DRC_ENA                          0x8000  /* DRC_ENA */
+#define WM8993_DRC_ENA_MASK                     0x8000  /* DRC_ENA */
+#define WM8993_DRC_ENA_SHIFT                        15  /* DRC_ENA */
+#define WM8993_DRC_ENA_WIDTH                         1  /* DRC_ENA */
+#define WM8993_DRC_DAC_PATH                     0x4000  /* DRC_DAC_PATH */
+#define WM8993_DRC_DAC_PATH_MASK                0x4000  /* DRC_DAC_PATH */
+#define WM8993_DRC_DAC_PATH_SHIFT                   14  /* DRC_DAC_PATH */
+#define WM8993_DRC_DAC_PATH_WIDTH                    1  /* DRC_DAC_PATH */
+#define WM8993_DRC_SMOOTH_ENA                   0x0800  /* DRC_SMOOTH_ENA */
+#define WM8993_DRC_SMOOTH_ENA_MASK              0x0800  /* DRC_SMOOTH_ENA */
+#define WM8993_DRC_SMOOTH_ENA_SHIFT                 11  /* DRC_SMOOTH_ENA */
+#define WM8993_DRC_SMOOTH_ENA_WIDTH                  1  /* DRC_SMOOTH_ENA */
+#define WM8993_DRC_QR_ENA                       0x0400  /* DRC_QR_ENA */
+#define WM8993_DRC_QR_ENA_MASK                  0x0400  /* DRC_QR_ENA */
+#define WM8993_DRC_QR_ENA_SHIFT                     10  /* DRC_QR_ENA */
+#define WM8993_DRC_QR_ENA_WIDTH                      1  /* DRC_QR_ENA */
+#define WM8993_DRC_ANTICLIP_ENA                 0x0200  /* DRC_ANTICLIP_ENA */
+#define WM8993_DRC_ANTICLIP_ENA_MASK            0x0200  /* DRC_ANTICLIP_ENA */
+#define WM8993_DRC_ANTICLIP_ENA_SHIFT                9  /* DRC_ANTICLIP_ENA */
+#define WM8993_DRC_ANTICLIP_ENA_WIDTH                1  /* DRC_ANTICLIP_ENA */
+#define WM8993_DRC_HYST_ENA                     0x0100  /* DRC_HYST_ENA */
+#define WM8993_DRC_HYST_ENA_MASK                0x0100  /* DRC_HYST_ENA */
+#define WM8993_DRC_HYST_ENA_SHIFT                    8  /* DRC_HYST_ENA */
+#define WM8993_DRC_HYST_ENA_WIDTH                    1  /* DRC_HYST_ENA */
+#define WM8993_DRC_THRESH_HYST_MASK             0x0030  /* DRC_THRESH_HYST - [5:4] */
+#define WM8993_DRC_THRESH_HYST_SHIFT                 4  /* DRC_THRESH_HYST - [5:4] */
+#define WM8993_DRC_THRESH_HYST_WIDTH                 2  /* DRC_THRESH_HYST - [5:4] */
+#define WM8993_DRC_MINGAIN_MASK                 0x000C  /* DRC_MINGAIN - [3:2] */
+#define WM8993_DRC_MINGAIN_SHIFT                     2  /* DRC_MINGAIN - [3:2] */
+#define WM8993_DRC_MINGAIN_WIDTH                     2  /* DRC_MINGAIN - [3:2] */
+#define WM8993_DRC_MAXGAIN_MASK                 0x0003  /* DRC_MAXGAIN - [1:0] */
+#define WM8993_DRC_MAXGAIN_SHIFT                     0  /* DRC_MAXGAIN - [1:0] */
+#define WM8993_DRC_MAXGAIN_WIDTH                     2  /* DRC_MAXGAIN - [1:0] */
+
+/*
+ * R124 (0x7C) - DRC Control 2
+ */
+#define WM8993_DRC_ATTACK_RATE_MASK             0xF000  /* DRC_ATTACK_RATE - [15:12] */
+#define WM8993_DRC_ATTACK_RATE_SHIFT                12  /* DRC_ATTACK_RATE - [15:12] */
+#define WM8993_DRC_ATTACK_RATE_WIDTH                 4  /* DRC_ATTACK_RATE - [15:12] */
+#define WM8993_DRC_DECAY_RATE_MASK              0x0F00  /* DRC_DECAY_RATE - [11:8] */
+#define WM8993_DRC_DECAY_RATE_SHIFT                  8  /* DRC_DECAY_RATE - [11:8] */
+#define WM8993_DRC_DECAY_RATE_WIDTH                  4  /* DRC_DECAY_RATE - [11:8] */
+#define WM8993_DRC_THRESH_COMP_MASK             0x00FC  /* DRC_THRESH_COMP - [7:2] */
+#define WM8993_DRC_THRESH_COMP_SHIFT                 2  /* DRC_THRESH_COMP - [7:2] */
+#define WM8993_DRC_THRESH_COMP_WIDTH                 6  /* DRC_THRESH_COMP - [7:2] */
+
+/*
+ * R125 (0x7D) - DRC Control 3
+ */
+#define WM8993_DRC_AMP_COMP_MASK                0xF800  /* DRC_AMP_COMP - [15:11] */
+#define WM8993_DRC_AMP_COMP_SHIFT                   11  /* DRC_AMP_COMP - [15:11] */
+#define WM8993_DRC_AMP_COMP_WIDTH                    5  /* DRC_AMP_COMP - [15:11] */
+#define WM8993_DRC_R0_SLOPE_COMP_MASK           0x0700  /* DRC_R0_SLOPE_COMP - [10:8] */
+#define WM8993_DRC_R0_SLOPE_COMP_SHIFT               8  /* DRC_R0_SLOPE_COMP - [10:8] */
+#define WM8993_DRC_R0_SLOPE_COMP_WIDTH               3  /* DRC_R0_SLOPE_COMP - [10:8] */
+#define WM8993_DRC_FF_DELAY                     0x0080  /* DRC_FF_DELAY */
+#define WM8993_DRC_FF_DELAY_MASK                0x0080  /* DRC_FF_DELAY */
+#define WM8993_DRC_FF_DELAY_SHIFT                    7  /* DRC_FF_DELAY */
+#define WM8993_DRC_FF_DELAY_WIDTH                    1  /* DRC_FF_DELAY */
+#define WM8993_DRC_THRESH_QR_MASK               0x000C  /* DRC_THRESH_QR - [3:2] */
+#define WM8993_DRC_THRESH_QR_SHIFT                   2  /* DRC_THRESH_QR - [3:2] */
+#define WM8993_DRC_THRESH_QR_WIDTH                   2  /* DRC_THRESH_QR - [3:2] */
+#define WM8993_DRC_RATE_QR_MASK                 0x0003  /* DRC_RATE_QR - [1:0] */
+#define WM8993_DRC_RATE_QR_SHIFT                     0  /* DRC_RATE_QR - [1:0] */
+#define WM8993_DRC_RATE_QR_WIDTH                     2  /* DRC_RATE_QR - [1:0] */
+
+/*
+ * R126 (0x7E) - DRC Control 4
+ */
+#define WM8993_DRC_R1_SLOPE_COMP_MASK           0xE000  /* DRC_R1_SLOPE_COMP - [15:13] */
+#define WM8993_DRC_R1_SLOPE_COMP_SHIFT              13  /* DRC_R1_SLOPE_COMP - [15:13] */
+#define WM8993_DRC_R1_SLOPE_COMP_WIDTH               3  /* DRC_R1_SLOPE_COMP - [15:13] */
+#define WM8993_DRC_STARTUP_GAIN_MASK            0x1F00  /* DRC_STARTUP_GAIN - [12:8] */
+#define WM8993_DRC_STARTUP_GAIN_SHIFT                8  /* DRC_STARTUP_GAIN - [12:8] */
+#define WM8993_DRC_STARTUP_GAIN_WIDTH                5  /* DRC_STARTUP_GAIN - [12:8] */
+
+#endif
index 86fc57e25f97781693073f976c8685dcccf7e36f..c64e55aa63b6df4cf0508e340fba43e89f97fc88 100644 (file)
@@ -165,87 +165,23 @@ struct wm9081_priv {
        int master;
        int fll_fref;
        int fll_fout;
+       int tdm_width;
        struct wm9081_retune_mobile_config *retune;
 };
 
-static int wm9081_reg_is_volatile(int reg)
+static int wm9081_volatile_register(unsigned int reg)
 {
        switch (reg) {
+       case WM9081_SOFTWARE_RESET:
+               return 1;
        default:
                return 0;
        }
 }
 
-static unsigned int wm9081_read_reg_cache(struct snd_soc_codec *codec,
-                                         unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       BUG_ON(reg > WM9081_MAX_REGISTER);
-       return cache[reg];
-}
-
-static unsigned int wm9081_read_hw(struct snd_soc_codec *codec, u8 reg)
-{
-       struct i2c_msg xfer[2];
-       u16 data;
-       int ret;
-       struct i2c_client *client = codec->control_data;
-
-       BUG_ON(reg > WM9081_MAX_REGISTER);
-
-       /* Write register */
-       xfer[0].addr = client->addr;
-       xfer[0].flags = 0;
-       xfer[0].len = 1;
-       xfer[0].buf = &reg;
-
-       /* Read data */
-       xfer[1].addr = client->addr;
-       xfer[1].flags = I2C_M_RD;
-       xfer[1].len = 2;
-       xfer[1].buf = (u8 *)&data;
-
-       ret = i2c_transfer(client->adapter, xfer, 2);
-       if (ret != 2) {
-               dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
-               return 0;
-       }
-
-       return (data >> 8) | ((data & 0xff) << 8);
-}
-
-static unsigned int wm9081_read(struct snd_soc_codec *codec, unsigned int reg)
-{
-       if (wm9081_reg_is_volatile(reg))
-               return wm9081_read_hw(codec, reg);
-       else
-               return wm9081_read_reg_cache(codec, reg);
-}
-
-static int wm9081_write(struct snd_soc_codec *codec, unsigned int reg,
-                       unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-       u8 data[3];
-
-       BUG_ON(reg > WM9081_MAX_REGISTER);
-
-       if (!wm9081_reg_is_volatile(reg))
-               cache[reg] = value;
-
-       data[0] = reg;
-       data[1] = value >> 8;
-       data[2] = value & 0x00ff;
-
-       if (codec->hw_write(codec->control_data, data, 3) == 3)
-               return 0;
-       else
-               return -EIO;
-}
-
 static int wm9081_reset(struct snd_soc_codec *codec)
 {
-       return wm9081_write(codec, WM9081_SOFTWARE_RESET, 0);
+       return snd_soc_write(codec, WM9081_SOFTWARE_RESET, 0);
 }
 
 static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0);
@@ -356,7 +292,7 @@ static int speaker_mode_get(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        unsigned int reg;
 
-       reg = wm9081_read(codec, WM9081_ANALOGUE_SPEAKER_2);
+       reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2);
        if (reg & WM9081_SPK_MODE)
                ucontrol->value.integer.value[0] = 1;
        else
@@ -375,8 +311,8 @@ static int speaker_mode_put(struct snd_kcontrol *kcontrol,
                            struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       unsigned int reg_pwr = wm9081_read(codec, WM9081_POWER_MANAGEMENT);
-       unsigned int reg2 = wm9081_read(codec, WM9081_ANALOGUE_SPEAKER_2);
+       unsigned int reg_pwr = snd_soc_read(codec, WM9081_POWER_MANAGEMENT);
+       unsigned int reg2 = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2);
 
        /* Are we changing anything? */
        if (ucontrol->value.integer.value[0] ==
@@ -397,7 +333,7 @@ static int speaker_mode_put(struct snd_kcontrol *kcontrol,
                reg2 &= ~WM9081_SPK_MODE;
        }
 
-       wm9081_write(codec, WM9081_ANALOGUE_SPEAKER_2, reg2);
+       snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_2, reg2);
 
        return 0;
 }
@@ -456,7 +392,7 @@ static int speaker_event(struct snd_soc_dapm_widget *w,
                         struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_codec *codec = w->codec;
-       unsigned int reg = wm9081_read(codec, WM9081_POWER_MANAGEMENT);
+       unsigned int reg = snd_soc_read(codec, WM9081_POWER_MANAGEMENT);
 
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
@@ -468,7 +404,7 @@ static int speaker_event(struct snd_soc_dapm_widget *w,
                break;
        }
 
-       wm9081_write(codec, WM9081_POWER_MANAGEMENT, reg);
+       snd_soc_write(codec, WM9081_POWER_MANAGEMENT, reg);
 
        return 0;
 }
@@ -607,7 +543,7 @@ static int wm9081_set_fll(struct snd_soc_codec *codec, int fll_id,
        if (ret != 0)
                return ret;
 
-       reg5 = wm9081_read(codec, WM9081_FLL_CONTROL_5);
+       reg5 = snd_soc_read(codec, WM9081_FLL_CONTROL_5);
        reg5 &= ~WM9081_FLL_CLK_SRC_MASK;
 
        switch (fll_id) {
@@ -621,44 +557,44 @@ static int wm9081_set_fll(struct snd_soc_codec *codec, int fll_id,
        }
 
        /* Disable CLK_SYS while we reconfigure */
-       clk_sys_reg = wm9081_read(codec, WM9081_CLOCK_CONTROL_3);
+       clk_sys_reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_3);
        if (clk_sys_reg & WM9081_CLK_SYS_ENA)
-               wm9081_write(codec, WM9081_CLOCK_CONTROL_3,
+               snd_soc_write(codec, WM9081_CLOCK_CONTROL_3,
                             clk_sys_reg & ~WM9081_CLK_SYS_ENA);
 
        /* Any FLL configuration change requires that the FLL be
         * disabled first. */
-       reg1 = wm9081_read(codec, WM9081_FLL_CONTROL_1);
+       reg1 = snd_soc_read(codec, WM9081_FLL_CONTROL_1);
        reg1 &= ~WM9081_FLL_ENA;
-       wm9081_write(codec, WM9081_FLL_CONTROL_1, reg1);
+       snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1);
 
        /* Apply the configuration */
        if (fll_div.k)
                reg1 |= WM9081_FLL_FRAC_MASK;
        else
                reg1 &= ~WM9081_FLL_FRAC_MASK;
-       wm9081_write(codec, WM9081_FLL_CONTROL_1, reg1);
+       snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1);
 
-       wm9081_write(codec, WM9081_FLL_CONTROL_2,
+       snd_soc_write(codec, WM9081_FLL_CONTROL_2,
                     (fll_div.fll_outdiv << WM9081_FLL_OUTDIV_SHIFT) |
                     (fll_div.fll_fratio << WM9081_FLL_FRATIO_SHIFT));
-       wm9081_write(codec, WM9081_FLL_CONTROL_3, fll_div.k);
+       snd_soc_write(codec, WM9081_FLL_CONTROL_3, fll_div.k);
 
-       reg4 = wm9081_read(codec, WM9081_FLL_CONTROL_4);
+       reg4 = snd_soc_read(codec, WM9081_FLL_CONTROL_4);
        reg4 &= ~WM9081_FLL_N_MASK;
        reg4 |= fll_div.n << WM9081_FLL_N_SHIFT;
-       wm9081_write(codec, WM9081_FLL_CONTROL_4, reg4);
+       snd_soc_write(codec, WM9081_FLL_CONTROL_4, reg4);
 
        reg5 &= ~WM9081_FLL_CLK_REF_DIV_MASK;
        reg5 |= fll_div.fll_clk_ref_div << WM9081_FLL_CLK_REF_DIV_SHIFT;
-       wm9081_write(codec, WM9081_FLL_CONTROL_5, reg5);
+       snd_soc_write(codec, WM9081_FLL_CONTROL_5, reg5);
 
        /* Enable the FLL */
-       wm9081_write(codec, WM9081_FLL_CONTROL_1, reg1 | WM9081_FLL_ENA);
+       snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1 | WM9081_FLL_ENA);
 
        /* Then bring CLK_SYS up again if it was disabled */
        if (clk_sys_reg & WM9081_CLK_SYS_ENA)
-               wm9081_write(codec, WM9081_CLOCK_CONTROL_3, clk_sys_reg);
+               snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, clk_sys_reg);
 
        dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
 
@@ -707,6 +643,10 @@ static int configure_clock(struct snd_soc_codec *codec)
                                    target > 3000000)
                                        break;
                        }
+
+                       if (i == ARRAY_SIZE(clk_sys_rates))
+                               return -EINVAL;
+
                } else if (wm9081->fs) {
                        for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) {
                                new_sysclk = clk_sys_rates[i].ratio
@@ -714,6 +654,10 @@ static int configure_clock(struct snd_soc_codec *codec)
                                if (new_sysclk > 3000000)
                                        break;
                        }
+
+                       if (i == ARRAY_SIZE(clk_sys_rates))
+                               return -EINVAL;
+
                } else {
                        new_sysclk = 12288000;
                }
@@ -734,19 +678,19 @@ static int configure_clock(struct snd_soc_codec *codec)
                return -EINVAL;
        }
 
-       reg = wm9081_read(codec, WM9081_CLOCK_CONTROL_1);
+       reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_1);
        if (mclkdiv)
                reg |= WM9081_MCLKDIV2;
        else
                reg &= ~WM9081_MCLKDIV2;
-       wm9081_write(codec, WM9081_CLOCK_CONTROL_1, reg);
+       snd_soc_write(codec, WM9081_CLOCK_CONTROL_1, reg);
 
-       reg = wm9081_read(codec, WM9081_CLOCK_CONTROL_3);
+       reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_3);
        if (fll)
                reg |= WM9081_CLK_SRC_SEL;
        else
                reg &= ~WM9081_CLK_SRC_SEL;
-       wm9081_write(codec, WM9081_CLOCK_CONTROL_3, reg);
+       snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, reg);
 
        dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm9081->sysclk_rate);
 
@@ -846,76 +790,76 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
 
        case SND_SOC_BIAS_PREPARE:
                /* VMID=2*40k */
-               reg = wm9081_read(codec, WM9081_VMID_CONTROL);
+               reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
                reg &= ~WM9081_VMID_SEL_MASK;
                reg |= 0x2;
-               wm9081_write(codec, WM9081_VMID_CONTROL, reg);
+               snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
 
                /* Normal bias current */
-               reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
+               reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
                reg &= ~WM9081_STBY_BIAS_ENA;
-               wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
+               snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
                break;
 
        case SND_SOC_BIAS_STANDBY:
                /* Initial cold start */
                if (codec->bias_level == SND_SOC_BIAS_OFF) {
                        /* Disable LINEOUT discharge */
-                       reg = wm9081_read(codec, WM9081_ANTI_POP_CONTROL);
+                       reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL);
                        reg &= ~WM9081_LINEOUT_DISCH;
-                       wm9081_write(codec, WM9081_ANTI_POP_CONTROL, reg);
+                       snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg);
 
                        /* Select startup bias source */
-                       reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
+                       reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
                        reg |= WM9081_BIAS_SRC | WM9081_BIAS_ENA;
-                       wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
+                       snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
 
                        /* VMID 2*4k; Soft VMID ramp enable */
-                       reg = wm9081_read(codec, WM9081_VMID_CONTROL);
+                       reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
                        reg |= WM9081_VMID_RAMP | 0x6;
-                       wm9081_write(codec, WM9081_VMID_CONTROL, reg);
+                       snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
 
                        mdelay(100);
 
                        /* Normal bias enable & soft start off */
                        reg |= WM9081_BIAS_ENA;
                        reg &= ~WM9081_VMID_RAMP;
-                       wm9081_write(codec, WM9081_VMID_CONTROL, reg);
+                       snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
 
                        /* Standard bias source */
-                       reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
+                       reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
                        reg &= ~WM9081_BIAS_SRC;
-                       wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
+                       snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
                }
 
                /* VMID 2*240k */
-               reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
+               reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
                reg &= ~WM9081_VMID_SEL_MASK;
                reg |= 0x40;
-               wm9081_write(codec, WM9081_VMID_CONTROL, reg);
+               snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
 
                /* Standby bias current on */
-               reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
+               reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
                reg |= WM9081_STBY_BIAS_ENA;
-               wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
+               snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
                break;
 
        case SND_SOC_BIAS_OFF:
                /* Startup bias source */
-               reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1);
+               reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
                reg |= WM9081_BIAS_SRC;
-               wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg);
+               snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
 
                /* Disable VMID and biases with soft ramping */
-               reg = wm9081_read(codec, WM9081_VMID_CONTROL);
+               reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
                reg &= ~(WM9081_VMID_SEL_MASK | WM9081_BIAS_ENA);
                reg |= WM9081_VMID_RAMP;
-               wm9081_write(codec, WM9081_VMID_CONTROL, reg);
+               snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
 
                /* Actively discharge LINEOUT */
-               reg = wm9081_read(codec, WM9081_ANTI_POP_CONTROL);
+               reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL);
                reg |= WM9081_LINEOUT_DISCH;
-               wm9081_write(codec, WM9081_ANTI_POP_CONTROL, reg);
+               snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg);
                break;
        }
 
@@ -929,7 +873,7 @@ static int wm9081_set_dai_fmt(struct snd_soc_dai *dai,
 {
        struct snd_soc_codec *codec = dai->codec;
        struct wm9081_priv *wm9081 = codec->private_data;
-       unsigned int aif2 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_2);
+       unsigned int aif2 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_2);
 
        aif2 &= ~(WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV |
                  WM9081_BCLK_DIR | WM9081_LRCLK_DIR | WM9081_AIF_FMT_MASK);
@@ -1010,7 +954,7 @@ static int wm9081_set_dai_fmt(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       wm9081_write(codec, WM9081_AUDIO_INTERFACE_2, aif2);
+       snd_soc_write(codec, WM9081_AUDIO_INTERFACE_2, aif2);
 
        return 0;
 }
@@ -1024,47 +968,51 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream,
        int ret, i, best, best_val, cur_val;
        unsigned int clk_ctrl2, aif1, aif2, aif3, aif4;
 
-       clk_ctrl2 = wm9081_read(codec, WM9081_CLOCK_CONTROL_2);
+       clk_ctrl2 = snd_soc_read(codec, WM9081_CLOCK_CONTROL_2);
        clk_ctrl2 &= ~(WM9081_CLK_SYS_RATE_MASK | WM9081_SAMPLE_RATE_MASK);
 
-       aif1 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_1);
+       aif1 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_1);
 
-       aif2 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_2);
+       aif2 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_2);
        aif2 &= ~WM9081_AIF_WL_MASK;
 
-       aif3 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_3);
+       aif3 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_3);
        aif3 &= ~WM9081_BCLK_DIV_MASK;
 
-       aif4 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_4);
+       aif4 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_4);
        aif4 &= ~WM9081_LRCLK_RATE_MASK;
 
-       /* What BCLK do we need? */
        wm9081->fs = params_rate(params);
-       wm9081->bclk = 2 * wm9081->fs;
-       switch (params_format(params)) {
-       case SNDRV_PCM_FORMAT_S16_LE:
-               wm9081->bclk *= 16;
-               break;
-       case SNDRV_PCM_FORMAT_S20_3LE:
-               wm9081->bclk *= 20;
-               aif2 |= 0x4;
-               break;
-       case SNDRV_PCM_FORMAT_S24_LE:
-               wm9081->bclk *= 24;
-               aif2 |= 0x8;
-               break;
-       case SNDRV_PCM_FORMAT_S32_LE:
-               wm9081->bclk *= 32;
-               aif2 |= 0xc;
-               break;
-       default:
-               return -EINVAL;
-       }
 
-       if (aif1 & WM9081_AIFDAC_TDM_MODE_MASK) {
+       if (wm9081->tdm_width) {
+               /* If TDM is set up then that fixes our BCLK. */
                int slots = ((aif1 & WM9081_AIFDAC_TDM_MODE_MASK) >>
                             WM9081_AIFDAC_TDM_MODE_SHIFT) + 1;
-               wm9081->bclk *= slots;
+
+               wm9081->bclk = wm9081->fs * wm9081->tdm_width * slots;
+       } else {
+               /* Otherwise work out a BCLK from the sample size */
+               wm9081->bclk = 2 * wm9081->fs;
+
+               switch (params_format(params)) {
+               case SNDRV_PCM_FORMAT_S16_LE:
+                       wm9081->bclk *= 16;
+                       break;
+               case SNDRV_PCM_FORMAT_S20_3LE:
+                       wm9081->bclk *= 20;
+                       aif2 |= 0x4;
+                       break;
+               case SNDRV_PCM_FORMAT_S24_LE:
+                       wm9081->bclk *= 24;
+                       aif2 |= 0x8;
+                       break;
+               case SNDRV_PCM_FORMAT_S32_LE:
+                       wm9081->bclk *= 32;
+                       aif2 |= 0xc;
+                       break;
+               default:
+                       return -EINVAL;
+               }
        }
 
        dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm9081->bclk);
@@ -1149,22 +1097,22 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream,
                        s->name, s->rate);
 
                /* If the EQ is enabled then disable it while we write out */
-               eq1 = wm9081_read(codec, WM9081_EQ_1) & WM9081_EQ_ENA;
+               eq1 = snd_soc_read(codec, WM9081_EQ_1) & WM9081_EQ_ENA;
                if (eq1 & WM9081_EQ_ENA)
-                       wm9081_write(codec, WM9081_EQ_1, 0);
+                       snd_soc_write(codec, WM9081_EQ_1, 0);
 
                /* Write out the other values */
                for (i = 1; i < ARRAY_SIZE(s->config); i++)
-                       wm9081_write(codec, WM9081_EQ_1 + i, s->config[i]);
+                       snd_soc_write(codec, WM9081_EQ_1 + i, s->config[i]);
 
                eq1 |= (s->config[0] & ~WM9081_EQ_ENA);
-               wm9081_write(codec, WM9081_EQ_1, eq1);
+               snd_soc_write(codec, WM9081_EQ_1, eq1);
        }
 
-       wm9081_write(codec, WM9081_CLOCK_CONTROL_2, clk_ctrl2);
-       wm9081_write(codec, WM9081_AUDIO_INTERFACE_2, aif2);
-       wm9081_write(codec, WM9081_AUDIO_INTERFACE_3, aif3);
-       wm9081_write(codec, WM9081_AUDIO_INTERFACE_4, aif4);
+       snd_soc_write(codec, WM9081_CLOCK_CONTROL_2, clk_ctrl2);
+       snd_soc_write(codec, WM9081_AUDIO_INTERFACE_2, aif2);
+       snd_soc_write(codec, WM9081_AUDIO_INTERFACE_3, aif3);
+       snd_soc_write(codec, WM9081_AUDIO_INTERFACE_4, aif4);
 
        return 0;
 }
@@ -1174,14 +1122,14 @@ static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute)
        struct snd_soc_codec *codec = codec_dai->codec;
        unsigned int reg;
 
-       reg = wm9081_read(codec, WM9081_DAC_DIGITAL_2);
+       reg = snd_soc_read(codec, WM9081_DAC_DIGITAL_2);
 
        if (mute)
                reg |= WM9081_DAC_MUTE;
        else
                reg &= ~WM9081_DAC_MUTE;
 
-       wm9081_write(codec, WM9081_DAC_DIGITAL_2, reg);
+       snd_soc_write(codec, WM9081_DAC_DIGITAL_2, reg);
 
        return 0;
 }
@@ -1207,19 +1155,25 @@ static int wm9081_set_sysclk(struct snd_soc_dai *codec_dai,
 }
 
 static int wm9081_set_tdm_slot(struct snd_soc_dai *dai,
-                              unsigned int mask, int slots)
+       unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
 {
        struct snd_soc_codec *codec = dai->codec;
-       unsigned int aif1 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_1);
+       struct wm9081_priv *wm9081 = codec->private_data;
+       unsigned int aif1 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_1);
 
        aif1 &= ~(WM9081_AIFDAC_TDM_SLOT_MASK | WM9081_AIFDAC_TDM_MODE_MASK);
 
-       if (slots < 1 || slots > 4)
+       if (slots < 0 || slots > 4)
                return -EINVAL;
 
+       wm9081->tdm_width = slot_width;
+
+       if (slots == 0)
+               slots = 1;
+
        aif1 |= (slots - 1) << WM9081_AIFDAC_TDM_MODE_SHIFT;
 
-       switch (mask) {
+       switch (rx_mask) {
        case 1:
                break;
        case 2:
@@ -1235,7 +1189,7 @@ static int wm9081_set_tdm_slot(struct snd_soc_dai *dai,
                return -EINVAL;
        }
 
-       wm9081_write(codec, WM9081_AUDIO_INTERFACE_1, aif1);
+       snd_soc_write(codec, WM9081_AUDIO_INTERFACE_1, aif1);
 
        return 0;
 }
@@ -1357,7 +1311,7 @@ static int wm9081_resume(struct platform_device *pdev)
                if (i == WM9081_SOFTWARE_RESET)
                        continue;
 
-               wm9081_write(codec, i, reg_cache[i]);
+               snd_soc_write(codec, i, reg_cache[i]);
        }
 
        wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1377,7 +1331,8 @@ struct snd_soc_codec_device soc_codec_dev_wm9081 = {
 };
 EXPORT_SYMBOL_GPL(soc_codec_dev_wm9081);
 
-static int wm9081_register(struct wm9081_priv *wm9081)
+static int wm9081_register(struct wm9081_priv *wm9081,
+                          enum snd_soc_control_type control)
 {
        struct snd_soc_codec *codec = &wm9081->codec;
        int ret;
@@ -1396,19 +1351,24 @@ static int wm9081_register(struct wm9081_priv *wm9081)
        codec->private_data = wm9081;
        codec->name = "WM9081";
        codec->owner = THIS_MODULE;
-       codec->read = wm9081_read;
-       codec->write = wm9081_write;
        codec->dai = &wm9081_dai;
        codec->num_dai = 1;
        codec->reg_cache_size = ARRAY_SIZE(wm9081->reg_cache);
        codec->reg_cache = &wm9081->reg_cache;
        codec->bias_level = SND_SOC_BIAS_OFF;
        codec->set_bias_level = wm9081_set_bias_level;
+       codec->volatile_register = wm9081_volatile_register;
 
        memcpy(codec->reg_cache, wm9081_reg_defaults,
               sizeof(wm9081_reg_defaults));
 
-       reg = wm9081_read_hw(codec, WM9081_SOFTWARE_RESET);
+       ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
+       if (ret != 0) {
+               dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+               return ret;
+       }
+
+       reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET);
        if (reg != 0x9081) {
                dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
                ret = -EINVAL;
@@ -1424,10 +1384,10 @@ static int wm9081_register(struct wm9081_priv *wm9081)
        wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Enable zero cross by default */
-       reg = wm9081_read(codec, WM9081_ANALOGUE_LINEOUT);
-       wm9081_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC);
-       reg = wm9081_read(codec, WM9081_ANALOGUE_SPEAKER_PGA);
-       wm9081_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
+       reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT);
+       snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC);
+       reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA);
+       snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
                     reg | WM9081_SPKPGAZC);
 
        wm9081_dai.dev = codec->dev;
@@ -1482,7 +1442,7 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
 
        codec->dev = &i2c->dev;
 
-       return wm9081_register(wm9081);
+       return wm9081_register(wm9081, SND_SOC_I2C);
 }
 
 static __devexit int wm9081_i2c_remove(struct i2c_client *client)
@@ -1492,6 +1452,21 @@ static __devexit int wm9081_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm9081_i2c_suspend(struct i2c_client *client, pm_message_t msg)
+{
+       return snd_soc_suspend_device(&client->dev);
+}
+
+static int wm9081_i2c_resume(struct i2c_client *client)
+{
+       return snd_soc_resume_device(&client->dev);
+}
+#else
+#define wm9081_i2c_suspend NULL
+#define wm9081_i2c_resume NULL
+#endif
+
 static const struct i2c_device_id wm9081_i2c_id[] = {
        { "wm9081", 0 },
        { }
@@ -1505,6 +1480,8 @@ static struct i2c_driver wm9081_i2c_driver = {
        },
        .probe =    wm9081_i2c_probe,
        .remove =   __devexit_p(wm9081_i2c_remove),
+       .suspend =  wm9081_i2c_suspend,
+       .resume =   wm9081_i2c_resume,
        .id_table = wm9081_i2c_id,
 };
 
index fa88b463e71f37f4a07bc830db69c50d2e52b39c..e7d2840d9e59d22e344b6c9792fe1be6ec9b1fd9 100644 (file)
@@ -406,7 +406,7 @@ static int wm9705_soc_probe(struct platform_device *pdev)
        ret = snd_soc_init_card(socdev);
        if (ret < 0) {
                printk(KERN_ERR "wm9705: failed to register card\n");
-               goto pcm_err;
+               goto reset_err;
        }
 
        return 0;
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
new file mode 100644 (file)
index 0000000..e542027
--- /dev/null
@@ -0,0 +1,743 @@
+/*
+ * wm_hubs.c  --  WM8993/4 common code
+ *
+ * Copyright 2009 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "wm8993.h"
+#include "wm_hubs.h"
+
+const DECLARE_TLV_DB_SCALE(wm_hubs_spkmix_tlv, -300, 300, 0);
+EXPORT_SYMBOL_GPL(wm_hubs_spkmix_tlv);
+
+static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(inmix_sw_tlv, 0, 3000, 0);
+static const DECLARE_TLV_DB_SCALE(inmix_tlv, -1500, 300, 1);
+static const DECLARE_TLV_DB_SCALE(earpiece_tlv, -600, 600, 0);
+static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0);
+static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1);
+static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0);
+static const unsigned int spkboost_tlv[] = {
+       TLV_DB_RANGE_HEAD(7),
+       0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
+       7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
+};
+static const DECLARE_TLV_DB_SCALE(line_tlv, -600, 600, 0);
+
+static const char *speaker_ref_text[] = {
+       "SPKVDD/2",
+       "VMID",
+};
+
+static const struct soc_enum speaker_ref =
+       SOC_ENUM_SINGLE(WM8993_SPEAKER_MIXER, 8, 2, speaker_ref_text);
+
+static const char *speaker_mode_text[] = {
+       "Class D",
+       "Class AB",
+};
+
+static const struct soc_enum speaker_mode =
+       SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text);
+
+static void wait_for_dc_servo(struct snd_soc_codec *codec)
+{
+       unsigned int reg;
+       int count = 0;
+
+       dev_dbg(codec->dev, "Waiting for DC servo...\n");
+       do {
+               count++;
+               msleep(1);
+               reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0);
+               dev_dbg(codec->dev, "DC servo status: %x\n", reg);
+       } while ((reg & WM8993_DCS_CAL_COMPLETE_MASK)
+                != WM8993_DCS_CAL_COMPLETE_MASK && count < 1000);
+
+       if ((reg & WM8993_DCS_CAL_COMPLETE_MASK)
+           != WM8993_DCS_CAL_COMPLETE_MASK)
+               dev_err(codec->dev, "Timed out waiting for DC Servo\n");
+}
+
+/*
+ * Update the DC servo calibration on gain changes
+ */
+static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
+                             struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       int ret;
+
+       ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+
+       /* Only need to do this if the outputs are active */
+       if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1)
+           & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA))
+               snd_soc_update_bits(codec,
+                                   WM8993_DC_SERVO_0,
+                                   WM8993_DCS_TRIG_SINGLE_0 |
+                                   WM8993_DCS_TRIG_SINGLE_1,
+                                   WM8993_DCS_TRIG_SINGLE_0 |
+                                   WM8993_DCS_TRIG_SINGLE_1);
+
+       return ret;
+}
+
+static const struct snd_kcontrol_new analogue_snd_controls[] = {
+SOC_SINGLE_TLV("IN1L Volume", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,
+              inpga_tlv),
+SOC_SINGLE("IN1L Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 1),
+SOC_SINGLE("IN1L ZC Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 0),
+
+SOC_SINGLE_TLV("IN1R Volume", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,
+              inpga_tlv),
+SOC_SINGLE("IN1R Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 1),
+SOC_SINGLE("IN1R ZC Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 0),
+
+
+SOC_SINGLE_TLV("IN2L Volume", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,
+              inpga_tlv),
+SOC_SINGLE("IN2L Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 1),
+SOC_SINGLE("IN2L ZC Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 0),
+
+SOC_SINGLE_TLV("IN2R Volume", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,
+              inpga_tlv),
+SOC_SINGLE("IN2R Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 1),
+SOC_SINGLE("IN2R ZC Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 0),
+
+SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8993_INPUT_MIXER3, 7, 1, 0,
+              inmix_sw_tlv),
+SOC_SINGLE_TLV("MIXINL IN1L Volume", WM8993_INPUT_MIXER3, 4, 1, 0,
+              inmix_sw_tlv),
+SOC_SINGLE_TLV("MIXINL Output Record Volume", WM8993_INPUT_MIXER3, 0, 7, 0,
+              inmix_tlv),
+SOC_SINGLE_TLV("MIXINL IN1LP Volume", WM8993_INPUT_MIXER5, 6, 7, 0, inmix_tlv),
+SOC_SINGLE_TLV("MIXINL Direct Voice Volume", WM8993_INPUT_MIXER5, 0, 6, 0,
+              inmix_tlv),
+
+SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8993_INPUT_MIXER4, 7, 1, 0,
+              inmix_sw_tlv),
+SOC_SINGLE_TLV("MIXINR IN1R Volume", WM8993_INPUT_MIXER4, 4, 1, 0,
+              inmix_sw_tlv),
+SOC_SINGLE_TLV("MIXINR Output Record Volume", WM8993_INPUT_MIXER4, 0, 7, 0,
+              inmix_tlv),
+SOC_SINGLE_TLV("MIXINR IN1RP Volume", WM8993_INPUT_MIXER6, 6, 7, 0, inmix_tlv),
+SOC_SINGLE_TLV("MIXINR Direct Voice Volume", WM8993_INPUT_MIXER6, 0, 6, 0,
+              inmix_tlv),
+
+SOC_SINGLE_TLV("Left Output Mixer IN2RN Volume", WM8993_OUTPUT_MIXER5, 6, 7, 1,
+              outmix_tlv),
+SOC_SINGLE_TLV("Left Output Mixer IN2LN Volume", WM8993_OUTPUT_MIXER3, 6, 7, 1,
+              outmix_tlv),
+SOC_SINGLE_TLV("Left Output Mixer IN2LP Volume", WM8993_OUTPUT_MIXER3, 9, 7, 1,
+              outmix_tlv),
+SOC_SINGLE_TLV("Left Output Mixer IN1L Volume", WM8993_OUTPUT_MIXER3, 0, 7, 1,
+              outmix_tlv),
+SOC_SINGLE_TLV("Left Output Mixer IN1R Volume", WM8993_OUTPUT_MIXER3, 3, 7, 1,
+              outmix_tlv),
+SOC_SINGLE_TLV("Left Output Mixer Right Input Volume",
+              WM8993_OUTPUT_MIXER5, 3, 7, 1, outmix_tlv),
+SOC_SINGLE_TLV("Left Output Mixer Left Input Volume",
+              WM8993_OUTPUT_MIXER5, 0, 7, 1, outmix_tlv),
+SOC_SINGLE_TLV("Left Output Mixer DAC Volume", WM8993_OUTPUT_MIXER5, 9, 7, 1,
+              outmix_tlv),
+
+SOC_SINGLE_TLV("Right Output Mixer IN2LN Volume",
+              WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv),
+SOC_SINGLE_TLV("Right Output Mixer IN2RN Volume",
+              WM8993_OUTPUT_MIXER4, 6, 7, 1, outmix_tlv),
+SOC_SINGLE_TLV("Right Output Mixer IN1L Volume",
+              WM8993_OUTPUT_MIXER4, 3, 7, 1, outmix_tlv),
+SOC_SINGLE_TLV("Right Output Mixer IN1R Volume",
+              WM8993_OUTPUT_MIXER4, 0, 7, 1, outmix_tlv),
+SOC_SINGLE_TLV("Right Output Mixer IN2RP Volume",
+              WM8993_OUTPUT_MIXER4, 9, 7, 1, outmix_tlv),
+SOC_SINGLE_TLV("Right Output Mixer Left Input Volume",
+              WM8993_OUTPUT_MIXER6, 3, 7, 1, outmix_tlv),
+SOC_SINGLE_TLV("Right Output Mixer Right Input Volume",
+              WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv),
+SOC_SINGLE_TLV("Right Output Mixer DAC Volume",
+              WM8993_OUTPUT_MIXER6, 9, 7, 1, outmix_tlv),
+
+SOC_DOUBLE_R_TLV("Output Volume", WM8993_LEFT_OPGA_VOLUME,
+                WM8993_RIGHT_OPGA_VOLUME, 0, 63, 0, outpga_tlv),
+SOC_DOUBLE_R("Output Switch", WM8993_LEFT_OPGA_VOLUME,
+            WM8993_RIGHT_OPGA_VOLUME, 6, 1, 0),
+SOC_DOUBLE_R("Output ZC Switch", WM8993_LEFT_OPGA_VOLUME,
+            WM8993_RIGHT_OPGA_VOLUME, 7, 1, 0),
+
+SOC_SINGLE("Earpiece Switch", WM8993_HPOUT2_VOLUME, 5, 1, 1),
+SOC_SINGLE_TLV("Earpiece Volume", WM8993_HPOUT2_VOLUME, 4, 1, 1, earpiece_tlv),
+
+SOC_SINGLE_TLV("SPKL Input Volume", WM8993_SPKMIXL_ATTENUATION,
+              5, 1, 1, wm_hubs_spkmix_tlv),
+SOC_SINGLE_TLV("SPKL IN1LP Volume", WM8993_SPKMIXL_ATTENUATION,
+              4, 1, 1, wm_hubs_spkmix_tlv),
+SOC_SINGLE_TLV("SPKL Output Volume", WM8993_SPKMIXL_ATTENUATION,
+              3, 1, 1, wm_hubs_spkmix_tlv),
+
+SOC_SINGLE_TLV("SPKR Input Volume", WM8993_SPKMIXR_ATTENUATION,
+              5, 1, 1, wm_hubs_spkmix_tlv),
+SOC_SINGLE_TLV("SPKR IN1RP Volume", WM8993_SPKMIXR_ATTENUATION,
+              4, 1, 1, wm_hubs_spkmix_tlv),
+SOC_SINGLE_TLV("SPKR Output Volume", WM8993_SPKMIXR_ATTENUATION,
+              3, 1, 1, wm_hubs_spkmix_tlv),
+
+SOC_DOUBLE_R_TLV("Speaker Mixer Volume",
+                WM8993_SPKMIXL_ATTENUATION, WM8993_SPKMIXR_ATTENUATION,
+                0, 3, 1, spkmixout_tlv),
+SOC_DOUBLE_R_TLV("Speaker Volume",
+                WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
+                0, 63, 0, outpga_tlv),
+SOC_DOUBLE_R("Speaker Switch",
+            WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
+            6, 1, 0),
+SOC_DOUBLE_R("Speaker ZC Switch",
+            WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
+            7, 1, 0),
+SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 0, 3, 7, 0,
+              spkboost_tlv),
+SOC_ENUM("Speaker Reference", speaker_ref),
+SOC_ENUM("Speaker Mode", speaker_mode),
+
+{
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Volume",
+       .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+                SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .tlv.p = outpga_tlv,
+       .info = snd_soc_info_volsw_2r,
+       .get = snd_soc_get_volsw_2r, .put = wm8993_put_dc_servo,
+       .private_value = (unsigned long)&(struct soc_mixer_control) {
+               .reg = WM8993_LEFT_OUTPUT_VOLUME,
+               .rreg = WM8993_RIGHT_OUTPUT_VOLUME,
+               .shift = 0, .max = 63
+       },
+},
+SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME,
+            WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0),
+SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME,
+            WM8993_RIGHT_OUTPUT_VOLUME, 7, 1, 0),
+
+SOC_SINGLE("LINEOUT1N Switch", WM8993_LINE_OUTPUTS_VOLUME, 6, 1, 1),
+SOC_SINGLE("LINEOUT1P Switch", WM8993_LINE_OUTPUTS_VOLUME, 5, 1, 1),
+SOC_SINGLE_TLV("LINEOUT1 Volume", WM8993_LINE_OUTPUTS_VOLUME, 4, 1, 1,
+              line_tlv),
+
+SOC_SINGLE("LINEOUT2N Switch", WM8993_LINE_OUTPUTS_VOLUME, 2, 1, 1),
+SOC_SINGLE("LINEOUT2P Switch", WM8993_LINE_OUTPUTS_VOLUME, 1, 1, 1),
+SOC_SINGLE_TLV("LINEOUT2 Volume", WM8993_LINE_OUTPUTS_VOLUME, 0, 1, 1,
+              line_tlv),
+};
+
+static int hp_event(struct snd_soc_dapm_widget *w,
+                   struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       unsigned int reg = snd_soc_read(codec, WM8993_ANALOGUE_HP_0);
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1,
+                                   WM8993_CP_ENA, WM8993_CP_ENA);
+
+               msleep(5);
+
+               snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
+                                   WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA,
+                                   WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA);
+
+               reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY;
+               snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg);
+
+               /* Start the DC servo */
+               snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
+                                   0xFFFF,
+                                   WM8993_DCS_ENA_CHAN_0 |
+                                   WM8993_DCS_ENA_CHAN_1 |
+                                   WM8993_DCS_TRIG_STARTUP_1 |
+                                   WM8993_DCS_TRIG_STARTUP_0);
+               wait_for_dc_servo(codec);
+
+               reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT |
+                       WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT;
+               snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg);
+               break;
+
+       case SND_SOC_DAPM_PRE_PMD:
+               reg &= ~(WM8993_HPOUT1L_RMV_SHORT |
+                        WM8993_HPOUT1L_DLY |
+                        WM8993_HPOUT1L_OUTP |
+                        WM8993_HPOUT1R_RMV_SHORT |
+                        WM8993_HPOUT1R_DLY |
+                        WM8993_HPOUT1R_OUTP);
+
+               snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
+                                   0xffff, 0);
+
+               snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg);
+               snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
+                                   WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA,
+                                   0);
+
+               snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1,
+                                   WM8993_CP_ENA, 0);
+               break;
+       }
+
+       return 0;
+}
+
+static int earpiece_event(struct snd_soc_dapm_widget *w,
+                         struct snd_kcontrol *control, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       u16 reg = snd_soc_read(codec, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA;
+
+       switch (event) {
+       case SND_SOC_DAPM_PRE_PMU:
+               reg |= WM8993_HPOUT2_IN_ENA;
+               snd_soc_write(codec, WM8993_ANTIPOP1, reg);
+               udelay(50);
+               break;
+
+       case SND_SOC_DAPM_POST_PMD:
+               snd_soc_write(codec, WM8993_ANTIPOP1, reg);
+               break;
+
+       default:
+               BUG();
+               break;
+       }
+
+       return 0;
+}
+
+static const struct snd_kcontrol_new in1l_pga[] = {
+SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new in1r_pga[] = {
+SOC_DAPM_SINGLE("IN1RP Switch", WM8993_INPUT_MIXER2, 1, 1, 0),
+SOC_DAPM_SINGLE("IN1RN Switch", WM8993_INPUT_MIXER2, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new in2l_pga[] = {
+SOC_DAPM_SINGLE("IN2LP Switch", WM8993_INPUT_MIXER2, 7, 1, 0),
+SOC_DAPM_SINGLE("IN2LN Switch", WM8993_INPUT_MIXER2, 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new in2r_pga[] = {
+SOC_DAPM_SINGLE("IN2RP Switch", WM8993_INPUT_MIXER2, 3, 1, 0),
+SOC_DAPM_SINGLE("IN2RN Switch", WM8993_INPUT_MIXER2, 2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mixinl[] = {
+SOC_DAPM_SINGLE("IN2L Switch", WM8993_INPUT_MIXER3, 8, 1, 0),
+SOC_DAPM_SINGLE("IN1L Switch", WM8993_INPUT_MIXER3, 5, 1, 0),
+};
+
+static const struct snd_kcontrol_new mixinr[] = {
+SOC_DAPM_SINGLE("IN2R Switch", WM8993_INPUT_MIXER4, 8, 1, 0),
+SOC_DAPM_SINGLE("IN1R Switch", WM8993_INPUT_MIXER4, 5, 1, 0),
+};
+
+static const struct snd_kcontrol_new left_output_mixer[] = {
+SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER1, 7, 1, 0),
+SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER1, 6, 1, 0),
+SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER1, 5, 1, 0),
+SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER1, 4, 1, 0),
+SOC_DAPM_SINGLE("IN2LP Switch", WM8993_OUTPUT_MIXER1, 1, 1, 0),
+SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER1, 3, 1, 0),
+SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER1, 2, 1, 0),
+SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER1, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_output_mixer[] = {
+SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER2, 7, 1, 0),
+SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER2, 6, 1, 0),
+SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER2, 4, 1, 0),
+SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER2, 3, 1, 0),
+SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER2, 2, 1, 0),
+SOC_DAPM_SINGLE("IN2RP Switch", WM8993_OUTPUT_MIXER2, 1, 1, 0),
+SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER2, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new earpiece_mixer[] = {
+SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_HPOUT2_MIXER, 5, 1, 0),
+SOC_DAPM_SINGLE("Left Output Switch", WM8993_HPOUT2_MIXER, 4, 1, 0),
+SOC_DAPM_SINGLE("Right Output Switch", WM8993_HPOUT2_MIXER, 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new left_speaker_boost[] = {
+SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 5, 1, 0),
+SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 4, 1, 0),
+SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_speaker_boost[] = {
+SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 2, 1, 0),
+SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 1, 1, 0),
+SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new line1_mix[] = {
+SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER1, 2, 1, 0),
+SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER1, 1, 1, 0),
+SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new line1n_mix[] = {
+SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 6, 1, 0),
+SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER1, 5, 1, 0),
+};
+
+static const struct snd_kcontrol_new line1p_mix[] = {
+SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new line2_mix[] = {
+SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0),
+SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0),
+SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new line2n_mix[] = {
+SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
+SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+};
+
+static const struct snd_kcontrol_new line2p_mix[] = {
+SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget analogue_dapm_widgets[] = {
+SND_SOC_DAPM_INPUT("IN1LN"),
+SND_SOC_DAPM_INPUT("IN1LP"),
+SND_SOC_DAPM_INPUT("IN2LN"),
+SND_SOC_DAPM_INPUT("IN2LP/VXRN"),
+SND_SOC_DAPM_INPUT("IN1RN"),
+SND_SOC_DAPM_INPUT("IN1RP"),
+SND_SOC_DAPM_INPUT("IN2RN"),
+SND_SOC_DAPM_INPUT("IN2RP/VXRP"),
+
+SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0),
+SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0),
+
+SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
+                  in1l_pga, ARRAY_SIZE(in1l_pga)),
+SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0,
+                  in1r_pga, ARRAY_SIZE(in1r_pga)),
+
+SND_SOC_DAPM_MIXER("IN2L PGA", WM8993_POWER_MANAGEMENT_2, 7, 0,
+                  in2l_pga, ARRAY_SIZE(in2l_pga)),
+SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0,
+                  in2r_pga, ARRAY_SIZE(in2r_pga)),
+
+/* Dummy widgets to represent differential paths */
+SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0,
+                  mixinl, ARRAY_SIZE(mixinl)),
+SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0,
+                  mixinr, ARRAY_SIZE(mixinr)),
+
+SND_SOC_DAPM_MIXER("Left Output Mixer", WM8993_POWER_MANAGEMENT_3, 5, 0,
+                  left_output_mixer, ARRAY_SIZE(left_output_mixer)),
+SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0,
+                  right_output_mixer, ARRAY_SIZE(right_output_mixer)),
+
+SND_SOC_DAPM_PGA("Left Output PGA", WM8993_POWER_MANAGEMENT_3, 7, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0,
+                  NULL, 0,
+                  hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
+                  earpiece_mixer, ARRAY_SIZE(earpiece_mixer)),
+SND_SOC_DAPM_PGA_E("Earpiece Driver", WM8993_POWER_MANAGEMENT_1, 11, 0,
+                  NULL, 0, earpiece_event,
+                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+SND_SOC_DAPM_MIXER("SPKL Boost", SND_SOC_NOPM, 0, 0,
+                  left_speaker_boost, ARRAY_SIZE(left_speaker_boost)),
+SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0,
+                  right_speaker_boost, ARRAY_SIZE(right_speaker_boost)),
+
+SND_SOC_DAPM_PGA("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
+                NULL, 0),
+
+SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0,
+                  line1_mix, ARRAY_SIZE(line1_mix)),
+SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0,
+                  line2_mix, ARRAY_SIZE(line2_mix)),
+
+SND_SOC_DAPM_MIXER("LINEOUT1N Mixer", SND_SOC_NOPM, 0, 0,
+                  line1n_mix, ARRAY_SIZE(line1n_mix)),
+SND_SOC_DAPM_MIXER("LINEOUT1P Mixer", SND_SOC_NOPM, 0, 0,
+                  line1p_mix, ARRAY_SIZE(line1p_mix)),
+SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0,
+                  line2n_mix, ARRAY_SIZE(line2n_mix)),
+SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0,
+                  line2p_mix, ARRAY_SIZE(line2p_mix)),
+
+SND_SOC_DAPM_PGA("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
+                NULL, 0),
+SND_SOC_DAPM_PGA("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
+                NULL, 0),
+
+SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
+SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
+SND_SOC_DAPM_OUTPUT("SPKOUTRP"),
+SND_SOC_DAPM_OUTPUT("SPKOUTRN"),
+SND_SOC_DAPM_OUTPUT("HPOUT1L"),
+SND_SOC_DAPM_OUTPUT("HPOUT1R"),
+SND_SOC_DAPM_OUTPUT("HPOUT2P"),
+SND_SOC_DAPM_OUTPUT("HPOUT2N"),
+SND_SOC_DAPM_OUTPUT("LINEOUT1P"),
+SND_SOC_DAPM_OUTPUT("LINEOUT1N"),
+SND_SOC_DAPM_OUTPUT("LINEOUT2P"),
+SND_SOC_DAPM_OUTPUT("LINEOUT2N"),
+};
+
+static const struct snd_soc_dapm_route analogue_routes[] = {
+       { "IN1L PGA", "IN1LP Switch", "IN1LP" },
+       { "IN1L PGA", "IN1LN Switch", "IN1LN" },
+
+       { "IN1R PGA", "IN1RP Switch", "IN1RP" },
+       { "IN1R PGA", "IN1RN Switch", "IN1RN" },
+
+       { "IN2L PGA", "IN2LP Switch", "IN2LP/VXRN" },
+       { "IN2L PGA", "IN2LN Switch", "IN2LN" },
+
+       { "IN2R PGA", "IN2RP Switch", "IN2RP/VXRP" },
+       { "IN2R PGA", "IN2RN Switch", "IN2RN" },
+
+       { "Direct Voice", NULL, "IN2LP/VXRN" },
+       { "Direct Voice", NULL, "IN2RP/VXRP" },
+
+       { "MIXINL", "IN1L Switch", "IN1L PGA" },
+       { "MIXINL", "IN2L Switch", "IN2L PGA" },
+       { "MIXINL", NULL, "Direct Voice" },
+       { "MIXINL", NULL, "IN1LP" },
+       { "MIXINL", NULL, "Left Output Mixer" },
+
+       { "MIXINR", "IN1R Switch", "IN1R PGA" },
+       { "MIXINR", "IN2R Switch", "IN2R PGA" },
+       { "MIXINR", NULL, "Direct Voice" },
+       { "MIXINR", NULL, "IN1RP" },
+       { "MIXINR", NULL, "Right Output Mixer" },
+
+       { "ADCL", NULL, "MIXINL" },
+       { "ADCR", NULL, "MIXINR" },
+
+       { "Left Output Mixer", "Left Input Switch", "MIXINL" },
+       { "Left Output Mixer", "Right Input Switch", "MIXINR" },
+       { "Left Output Mixer", "IN2RN Switch", "IN2RN" },
+       { "Left Output Mixer", "IN2LN Switch", "IN2LN" },
+       { "Left Output Mixer", "IN2LP Switch", "IN2LP/VXRN" },
+       { "Left Output Mixer", "IN1L Switch", "IN1L PGA" },
+       { "Left Output Mixer", "IN1R Switch", "IN1R PGA" },
+
+       { "Right Output Mixer", "Left Input Switch", "MIXINL" },
+       { "Right Output Mixer", "Right Input Switch", "MIXINR" },
+       { "Right Output Mixer", "IN2LN Switch", "IN2LN" },
+       { "Right Output Mixer", "IN2RN Switch", "IN2RN" },
+       { "Right Output Mixer", "IN2RP Switch", "IN2RP/VXRP" },
+       { "Right Output Mixer", "IN1L Switch", "IN1L PGA" },
+       { "Right Output Mixer", "IN1R Switch", "IN1R PGA" },
+
+       { "Left Output PGA", NULL, "Left Output Mixer" },
+       { "Left Output PGA", NULL, "TOCLK" },
+
+       { "Right Output PGA", NULL, "Right Output Mixer" },
+       { "Right Output PGA", NULL, "TOCLK" },
+
+       { "Earpiece Mixer", "Direct Voice Switch", "Direct Voice" },
+       { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" },
+       { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" },
+
+       { "Earpiece Driver", NULL, "Earpiece Mixer" },
+       { "HPOUT2N", NULL, "Earpiece Driver" },
+       { "HPOUT2P", NULL, "Earpiece Driver" },
+
+       { "SPKL", "Input Switch", "MIXINL" },
+       { "SPKL", "IN1LP Switch", "IN1LP" },
+       { "SPKL", "Output Switch", "Left Output Mixer" },
+       { "SPKL", NULL, "TOCLK" },
+
+       { "SPKR", "Input Switch", "MIXINR" },
+       { "SPKR", "IN1RP Switch", "IN1RP" },
+       { "SPKR", "Output Switch", "Right Output Mixer" },
+       { "SPKR", NULL, "TOCLK" },
+
+       { "SPKL Boost", "Direct Voice Switch", "Direct Voice" },
+       { "SPKL Boost", "SPKL Switch", "SPKL" },
+       { "SPKL Boost", "SPKR Switch", "SPKR" },
+
+       { "SPKR Boost", "Direct Voice Switch", "Direct Voice" },
+       { "SPKR Boost", "SPKR Switch", "SPKR" },
+       { "SPKR Boost", "SPKL Switch", "SPKL" },
+
+       { "SPKL Driver", NULL, "SPKL Boost" },
+       { "SPKL Driver", NULL, "CLK_SYS" },
+
+       { "SPKR Driver", NULL, "SPKR Boost" },
+       { "SPKR Driver", NULL, "CLK_SYS" },
+
+       { "SPKOUTLP", NULL, "SPKL Driver" },
+       { "SPKOUTLN", NULL, "SPKL Driver" },
+       { "SPKOUTRP", NULL, "SPKR Driver" },
+       { "SPKOUTRN", NULL, "SPKR Driver" },
+
+       { "Left Headphone Mux", "Mixer", "Left Output Mixer" },
+       { "Right Headphone Mux", "Mixer", "Right Output Mixer" },
+
+       { "Headphone PGA", NULL, "Left Headphone Mux" },
+       { "Headphone PGA", NULL, "Right Headphone Mux" },
+       { "Headphone PGA", NULL, "CLK_SYS" },
+
+       { "HPOUT1L", NULL, "Headphone PGA" },
+       { "HPOUT1R", NULL, "Headphone PGA" },
+
+       { "LINEOUT1N", NULL, "LINEOUT1N Driver" },
+       { "LINEOUT1P", NULL, "LINEOUT1P Driver" },
+       { "LINEOUT2N", NULL, "LINEOUT2N Driver" },
+       { "LINEOUT2P", NULL, "LINEOUT2P Driver" },
+};
+
+static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
+       { "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" },
+       { "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" },
+       { "LINEOUT1 Mixer", "Output Switch", "Left Output Mixer" },
+
+       { "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" },
+       { "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" },
+};
+
+static const struct snd_soc_dapm_route lineout1_se_routes[] = {
+       { "LINEOUT1N Mixer", "Left Output Switch", "Left Output Mixer" },
+       { "LINEOUT1N Mixer", "Right Output Switch", "Left Output Mixer" },
+
+       { "LINEOUT1P Mixer", "Left Output Switch", "Left Output Mixer" },
+
+       { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
+       { "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" },
+};
+
+static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
+       { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" },
+       { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" },
+       { "LINEOUT2 Mixer", "Output Switch", "Right Output Mixer" },
+
+       { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" },
+       { "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" },
+};
+
+static const struct snd_soc_dapm_route lineout2_se_routes[] = {
+       { "LINEOUT2N Mixer", "Left Output Switch", "Left Output Mixer" },
+       { "LINEOUT2N Mixer", "Right Output Switch", "Left Output Mixer" },
+
+       { "LINEOUT2P Mixer", "Right Output Switch", "Right Output Mixer" },
+
+       { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
+       { "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" },
+};
+
+int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec)
+{
+       /* Latch volume update bits & default ZC on */
+       snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_1_2_VOLUME,
+                           WM8993_IN1_VU, WM8993_IN1_VU);
+       snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_1_2_VOLUME,
+                           WM8993_IN1_VU, WM8993_IN1_VU);
+       snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_3_4_VOLUME,
+                           WM8993_IN2_VU, WM8993_IN2_VU);
+       snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME,
+                           WM8993_IN2_VU, WM8993_IN2_VU);
+
+       snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_RIGHT,
+                           WM8993_SPKOUT_VU, WM8993_SPKOUT_VU);
+
+       snd_soc_update_bits(codec, WM8993_LEFT_OUTPUT_VOLUME,
+                           WM8993_HPOUT1L_ZC, WM8993_HPOUT1L_ZC);
+       snd_soc_update_bits(codec, WM8993_RIGHT_OUTPUT_VOLUME,
+                           WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC,
+                           WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC);
+
+       snd_soc_update_bits(codec, WM8993_LEFT_OPGA_VOLUME,
+                           WM8993_MIXOUTL_ZC, WM8993_MIXOUTL_ZC);
+       snd_soc_update_bits(codec, WM8993_RIGHT_OPGA_VOLUME,
+                           WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU,
+                           WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU);
+
+       snd_soc_add_controls(codec, analogue_snd_controls,
+                            ARRAY_SIZE(analogue_snd_controls));
+
+       snd_soc_dapm_new_controls(codec, analogue_dapm_widgets,
+                                 ARRAY_SIZE(analogue_dapm_widgets));
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_controls);
+
+int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec,
+                               int lineout1_diff, int lineout2_diff)
+{
+       snd_soc_dapm_add_routes(codec, analogue_routes,
+                               ARRAY_SIZE(analogue_routes));
+
+       if (lineout1_diff)
+               snd_soc_dapm_add_routes(codec,
+                                       lineout1_diff_routes,
+                                       ARRAY_SIZE(lineout1_diff_routes));
+       else
+               snd_soc_dapm_add_routes(codec,
+                                       lineout1_se_routes,
+                                       ARRAY_SIZE(lineout1_se_routes));
+
+       if (lineout2_diff)
+               snd_soc_dapm_add_routes(codec,
+                                       lineout2_diff_routes,
+                                       ARRAY_SIZE(lineout2_diff_routes));
+       else
+               snd_soc_dapm_add_routes(codec,
+                                       lineout2_se_routes,
+                                       ARRAY_SIZE(lineout2_se_routes));
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes);
+
+MODULE_DESCRIPTION("Shared support for Wolfson hubs products");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
new file mode 100644 (file)
index 0000000..ec09cb6
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * wm_hubs.h  --  WM899x common code
+ *
+ * Copyright 2009 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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.
+ */
+
+#ifndef _WM_HUBS_H
+#define _WM_HUBS_H
+
+struct snd_soc_codec;
+
+extern const unsigned int wm_hubs_spkmix_tlv[];
+
+extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *);
+extern int wm_hubs_add_analogue_routes(struct snd_soc_codec *, int, int);
+
+#endif
index 411a710be660bf09fd9bc9be5bb384bbd896f311..4dfd4ad9d90e35f1abe920b02de591613557095b 100644 (file)
@@ -9,6 +9,9 @@ config SND_DAVINCI_SOC
 config SND_DAVINCI_SOC_I2S
        tristate
 
+config SND_DAVINCI_SOC_MCASP
+       tristate
+
 config SND_DAVINCI_SOC_EVM
        tristate "SoC Audio support for DaVinci DM6446 or DM355 EVM"
        depends on SND_DAVINCI_SOC
@@ -19,6 +22,16 @@ config SND_DAVINCI_SOC_EVM
          Say Y if you want to add support for SoC audio on TI
          DaVinci DM6446 or DM355 EVM platforms.
 
+config  SND_DM6467_SOC_EVM
+       tristate "SoC Audio support for DaVinci DM6467 EVM"
+       depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM
+       select SND_DAVINCI_SOC_MCASP
+       select SND_SOC_TLV320AIC3X
+       select SND_SOC_SPDIF
+
+       help
+         Say Y if you want to add support for SoC audio on TI
+
 config SND_DAVINCI_SOC_SFFSDR
        tristate "SoC Audio support for SFFSDR"
        depends on SND_DAVINCI_SOC && MACH_SFFSDR
@@ -28,3 +41,23 @@ config SND_DAVINCI_SOC_SFFSDR
        help
          Say Y if you want to add support for SoC audio on
          Lyrtech SFFSDR board.
+
+config  SND_DA830_SOC_EVM
+       tristate "SoC Audio support for DA830/OMAP-L137 EVM"
+       depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM
+       select SND_DAVINCI_SOC_MCASP
+       select SND_SOC_TLV320AIC3X
+
+       help
+         Say Y if you want to add support for SoC audio on TI
+         DA830/OMAP-L137 EVM
+
+config  SND_DA850_SOC_EVM
+       tristate "SoC Audio support for DA850/OMAP-L138 EVM"
+       depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM
+       select SND_DAVINCI_SOC_MCASP
+       select SND_SOC_TLV320AIC3X
+       help
+         Say Y if you want to add support for SoC audio on TI
+         DA850/OMAP-L138 EVM
+
index ca8bae1fc3f6ff00b062dd42094bd4c7035fe619..a6939d71b988b3f0cba740881622e852b0acaf9c 100644 (file)
@@ -1,13 +1,18 @@
 # DAVINCI Platform Support
 snd-soc-davinci-objs := davinci-pcm.o
 snd-soc-davinci-i2s-objs := davinci-i2s.o
+snd-soc-davinci-mcasp-objs:= davinci-mcasp.o
 
 obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o
 obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
+obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o
 
 # DAVINCI Machine Support
 snd-soc-evm-objs := davinci-evm.o
 snd-soc-sffsdr-objs := davinci-sffsdr.o
 
 obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
+obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o
+obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o
+obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o
 obj-$(CONFIG_SND_DAVINCI_SOC_SFFSDR) += snd-soc-sffsdr.o
index 58fd1cbedd88eb4dba2e64b05bf189801b1239c2..67414f65940577c745913ba7050f854b7527e0b7 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/i2c.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <mach/mux.h>
 
 #include "../codecs/tlv320aic3x.h"
+#include "../codecs/spdif_transciever.h"
 #include "davinci-pcm.h"
 #include "davinci-i2s.h"
-
+#include "davinci-mcasp.h"
 
 #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
                SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
@@ -43,7 +45,7 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
        unsigned sysclk;
 
        /* ASP1 on DM355 EVM is clocked by an external oscillator */
-       if (machine_is_davinci_dm355_evm())
+       if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm())
                sysclk = 27000000;
 
        /* ASP0 in DM6446 EVM is clocked by U55, as configured by
@@ -53,6 +55,10 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
        else if (machine_is_davinci_evm())
                sysclk = 12288000;
 
+       else if (machine_is_davinci_da830_evm() ||
+                               machine_is_davinci_da850_evm())
+               sysclk = 24576000;
+
        else
                return -EINVAL;
 
@@ -144,6 +150,32 @@ static struct snd_soc_dai_link evm_dai = {
        .ops = &evm_ops,
 };
 
+static struct snd_soc_dai_link dm6467_evm_dai[] = {
+       {
+               .name = "TLV320AIC3X",
+               .stream_name = "AIC3X",
+               .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI],
+               .codec_dai = &aic3x_dai,
+               .init = evm_aic3x_init,
+               .ops = &evm_ops,
+       },
+       {
+               .name = "McASP",
+               .stream_name = "spdif",
+               .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI],
+               .codec_dai = &dit_stub_dai,
+               .ops = &evm_ops,
+       },
+};
+static struct snd_soc_dai_link da8xx_evm_dai = {
+       .name = "TLV320AIC3X",
+       .stream_name = "AIC3X",
+       .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI],
+       .codec_dai = &aic3x_dai,
+       .init = evm_aic3x_init,
+       .ops = &evm_ops,
+};
+
 /* davinci-evm audio machine driver */
 static struct snd_soc_card snd_soc_card_evm = {
        .name = "DaVinci EVM",
@@ -152,73 +184,80 @@ static struct snd_soc_card snd_soc_card_evm = {
        .num_links = 1,
 };
 
-/* evm audio private data */
-static struct aic3x_setup_data evm_aic3x_setup = {
-       .i2c_bus = 1,
-       .i2c_address = 0x1b,
+/* davinci dm6467 evm audio machine driver */
+static struct snd_soc_card dm6467_snd_soc_card_evm = {
+       .name = "DaVinci DM6467 EVM",
+       .platform = &davinci_soc_platform,
+       .dai_link = dm6467_evm_dai,
+       .num_links = ARRAY_SIZE(dm6467_evm_dai),
 };
 
+static struct snd_soc_card da830_snd_soc_card = {
+       .name = "DA830/OMAP-L137 EVM",
+       .dai_link = &da8xx_evm_dai,
+       .platform = &davinci_soc_platform,
+       .num_links = 1,
+};
+
+static struct snd_soc_card da850_snd_soc_card = {
+       .name = "DA850/OMAP-L138 EVM",
+       .dai_link = &da8xx_evm_dai,
+       .platform = &davinci_soc_platform,
+       .num_links = 1,
+};
+
+static struct aic3x_setup_data aic3x_setup;
+
 /* evm audio subsystem */
 static struct snd_soc_device evm_snd_devdata = {
        .card = &snd_soc_card_evm,
        .codec_dev = &soc_codec_dev_aic3x,
-       .codec_data = &evm_aic3x_setup,
-};
-
-/* DM6446 EVM uses ASP0; line-out is a pair of RCA jacks */
-static struct resource evm_snd_resources[] = {
-       {
-               .start = DAVINCI_ASP0_BASE,
-               .end = DAVINCI_ASP0_BASE + SZ_8K - 1,
-               .flags = IORESOURCE_MEM,
-       },
+       .codec_data = &aic3x_setup,
 };
 
-static struct evm_snd_platform_data evm_snd_data = {
-       .tx_dma_ch      = DAVINCI_DMA_ASP0_TX,
-       .rx_dma_ch      = DAVINCI_DMA_ASP0_RX,
+/* evm audio subsystem */
+static struct snd_soc_device dm6467_evm_snd_devdata = {
+       .card = &dm6467_snd_soc_card_evm,
+       .codec_dev = &soc_codec_dev_aic3x,
+       .codec_data = &aic3x_setup,
 };
 
-/* DM335 EVM uses ASP1; line-out is a stereo mini-jack */
-static struct resource dm335evm_snd_resources[] = {
-       {
-               .start = DAVINCI_ASP1_BASE,
-               .end = DAVINCI_ASP1_BASE + SZ_8K - 1,
-               .flags = IORESOURCE_MEM,
-       },
+/* evm audio subsystem */
+static struct snd_soc_device da830_evm_snd_devdata = {
+       .card = &da830_snd_soc_card,
+       .codec_dev = &soc_codec_dev_aic3x,
+       .codec_data = &aic3x_setup,
 };
 
-static struct evm_snd_platform_data dm335evm_snd_data = {
-       .tx_dma_ch      = DAVINCI_DMA_ASP1_TX,
-       .rx_dma_ch      = DAVINCI_DMA_ASP1_RX,
+static struct snd_soc_device da850_evm_snd_devdata = {
+       .card           = &da850_snd_soc_card,
+       .codec_dev      = &soc_codec_dev_aic3x,
+       .codec_data     = &aic3x_setup,
 };
 
 static struct platform_device *evm_snd_device;
 
 static int __init evm_init(void)
 {
-       struct resource *resources;
-       unsigned num_resources;
-       struct evm_snd_platform_data *data;
+       struct snd_soc_device *evm_snd_dev_data;
        int index;
        int ret;
 
        if (machine_is_davinci_evm()) {
-               davinci_cfg_reg(DM644X_MCBSP);
-
-               resources = evm_snd_resources;
-               num_resources = ARRAY_SIZE(evm_snd_resources);
-               data = &evm_snd_data;
+               evm_snd_dev_data = &evm_snd_devdata;
                index = 0;
        } else if (machine_is_davinci_dm355_evm()) {
-               /* we don't use ASP1 IRQs, or we'd need to mux them ... */
-               davinci_cfg_reg(DM355_EVT8_ASP1_TX);
-               davinci_cfg_reg(DM355_EVT9_ASP1_RX);
-
-               resources = dm335evm_snd_resources;
-               num_resources = ARRAY_SIZE(dm335evm_snd_resources);
-               data = &dm335evm_snd_data;
+               evm_snd_dev_data = &evm_snd_devdata;
+               index = 1;
+       } else if (machine_is_davinci_dm6467_evm()) {
+               evm_snd_dev_data = &dm6467_evm_snd_devdata;
+               index = 0;
+       } else if (machine_is_davinci_da830_evm()) {
+               evm_snd_dev_data = &da830_evm_snd_devdata;
                index = 1;
+       } else if (machine_is_davinci_da850_evm()) {
+               evm_snd_dev_data = &da850_evm_snd_devdata;
+               index = 0;
        } else
                return -EINVAL;
 
@@ -226,17 +265,8 @@ static int __init evm_init(void)
        if (!evm_snd_device)
                return -ENOMEM;
 
-       platform_set_drvdata(evm_snd_device, &evm_snd_devdata);
-       evm_snd_devdata.dev = &evm_snd_device->dev;
-       platform_device_add_data(evm_snd_device, data, sizeof(*data));
-
-       ret = platform_device_add_resources(evm_snd_device, resources,
-                       num_resources);
-       if (ret) {
-               platform_device_put(evm_snd_device);
-               return ret;
-       }
-
+       platform_set_drvdata(evm_snd_device, evm_snd_dev_data);
+       evm_snd_dev_data->dev = &evm_snd_device->dev;
        ret = platform_device_add(evm_snd_device);
        if (ret)
                platform_device_put(evm_snd_device);
index b1ea52fc83c7b58a3090957c8351393c816696ea..4ae707048021886c45533ec6c5f6ca5cadf3999c 100644 (file)
@@ -22,6 +22,8 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 
+#include <mach/asp.h>
+
 #include "davinci-pcm.h"
 
 
@@ -63,6 +65,7 @@
 #define DAVINCI_MCBSP_RCR_RWDLEN1(v)   ((v) << 5)
 #define DAVINCI_MCBSP_RCR_RFRLEN1(v)   ((v) << 8)
 #define DAVINCI_MCBSP_RCR_RDATDLY(v)   ((v) << 16)
+#define DAVINCI_MCBSP_RCR_RFIG         (1 << 18)
 #define DAVINCI_MCBSP_RCR_RWDLEN2(v)   ((v) << 21)
 
 #define DAVINCI_MCBSP_XCR_XWDLEN1(v)   ((v) << 5)
 #define DAVINCI_MCBSP_PCR_FSRM         (1 << 10)
 #define DAVINCI_MCBSP_PCR_FSXM         (1 << 11)
 
-#define MOD_REG_BIT(val, mask, set) do { \
-       if (set) { \
-               val |= mask; \
-       } else { \
-               val &= ~mask; \
-       } \
-} while (0)
-
 enum {
        DAVINCI_MCBSP_WORD_8 = 0,
        DAVINCI_MCBSP_WORD_12,
@@ -102,18 +97,19 @@ enum {
        DAVINCI_MCBSP_WORD_32,
 };
 
-static struct davinci_pcm_dma_params davinci_i2s_pcm_out = {
-       .name = "I2S PCM Stereo out",
-};
-
-static struct davinci_pcm_dma_params davinci_i2s_pcm_in = {
-       .name = "I2S PCM Stereo in",
-};
-
 struct davinci_mcbsp_dev {
+       /*
+        * dma_params must be first because rtd->dai->cpu_dai->private_data
+        * is cast to a pointer of an array of struct davinci_pcm_dma_params in
+        * davinci_pcm_open.
+        */
+       struct davinci_pcm_dma_params   dma_params[2];
        void __iomem                    *base;
+#define MOD_DSP_A      0
+#define MOD_DSP_B      1
+       int                             mode;
+       u32                             pcr;
        struct clk                      *clk;
-       struct davinci_pcm_dma_params   *dma_params[2];
 };
 
 static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
@@ -127,97 +123,93 @@ static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg)
        return __raw_readl(dev->base + reg);
 }
 
-static void davinci_mcbsp_start(struct snd_pcm_substream *substream)
+static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback)
+{
+       u32 m = playback ? DAVINCI_MCBSP_PCR_CLKXP : DAVINCI_MCBSP_PCR_CLKRP;
+       /* The clock needs to toggle to complete reset.
+        * So, fake it by toggling the clk polarity.
+        */
+       davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m);
+       davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr);
+}
+
+static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
+               struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
        struct snd_soc_device *socdev = rtd->socdev;
        struct snd_soc_platform *platform = socdev->card->platform;
-       u32 w;
-       int ret;
-
-       /* Start the sample generator and enable transmitter/receiver */
-       w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
-       MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1);
-       davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+       int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       u32 spcr;
+       u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
+       spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+       if (spcr & mask) {
+               /* start off disabled */
+               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
+                               spcr & ~mask);
+               toggle_clock(dev, playback);
+       }
+       if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM |
+                       DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) {
+               /* Start the sample generator */
+               spcr |= DAVINCI_MCBSP_SPCR_GRST;
+               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
+       }
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+       if (playback) {
                /* Stop the DMA to avoid data loss */
                /* while the transmitter is out of reset to handle XSYNCERR */
                if (platform->pcm_ops->trigger) {
-                       ret = platform->pcm_ops->trigger(substream,
+                       int ret = platform->pcm_ops->trigger(substream,
                                SNDRV_PCM_TRIGGER_STOP);
                        if (ret < 0)
                                printk(KERN_DEBUG "Playback DMA stop failed\n");
                }
 
                /* Enable the transmitter */
-               w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
-               MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
-               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+               spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+               spcr |= DAVINCI_MCBSP_SPCR_XRST;
+               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
 
                /* wait for any unexpected frame sync error to occur */
                udelay(100);
 
                /* Disable the transmitter to clear any outstanding XSYNCERR */
-               w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
-               MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0);
-               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+               spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+               spcr &= ~DAVINCI_MCBSP_SPCR_XRST;
+               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
+               toggle_clock(dev, playback);
 
                /* Restart the DMA */
                if (platform->pcm_ops->trigger) {
-                       ret = platform->pcm_ops->trigger(substream,
+                       int ret = platform->pcm_ops->trigger(substream,
                                SNDRV_PCM_TRIGGER_START);
                        if (ret < 0)
                                printk(KERN_DEBUG "Playback DMA start failed\n");
                }
-               /* Enable the transmitter */
-               w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
-               MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
-               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
-
-       } else {
-
-               /* Enable the reciever */
-               w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
-               MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1);
-               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
        }
 
+       /* Enable transmitter or receiver */
+       spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+       spcr |= mask;
 
-       /* Start frame sync */
-       w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
-       MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_FRST, 1);
-       davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+       if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) {
+               /* Start frame sync */
+               spcr |= DAVINCI_MCBSP_SPCR_FRST;
+       }
+       davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
 }
 
-static void davinci_mcbsp_stop(struct snd_pcm_substream *substream)
+static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
-       u32 w;
+       u32 spcr;
 
        /* Reset transmitter/receiver and sample rate/frame sync generators */
-       w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
-       MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST |
-                      DAVINCI_MCBSP_SPCR_FRST, 0);
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0);
-       else
-               MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 0);
-       davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
-}
-
-static int davinci_i2s_startup(struct snd_pcm_substream *substream,
-                              struct snd_soc_dai *dai)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
-       struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
-
-       cpu_dai->dma_data = dev->dma_params[substream->stream];
-
-       return 0;
+       spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+       spcr &= ~(DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST);
+       spcr &= playback ? ~DAVINCI_MCBSP_SPCR_XRST : ~DAVINCI_MCBSP_SPCR_RRST;
+       davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
+       toggle_clock(dev, playback);
 }
 
 #define DEFAULT_BITPERSAMPLE   16
@@ -228,12 +220,11 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
        unsigned int pcr;
        unsigned int srgr;
-       unsigned int rcr;
-       unsigned int xcr;
        srgr = DAVINCI_MCBSP_SRGR_FSGM |
                DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
                DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1);
 
+       /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
                /* cpu is master */
@@ -258,11 +249,8 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                return -EINVAL;
        }
 
-       rcr = DAVINCI_MCBSP_RCR_RFRLEN1(1);
-       xcr = DAVINCI_MCBSP_XCR_XFIG | DAVINCI_MCBSP_XCR_XFRLEN1(1);
+       /* interface format */
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-       case SND_SOC_DAIFMT_DSP_B:
-               break;
        case SND_SOC_DAIFMT_I2S:
                /* Davinci doesn't support TRUE I2S, but some codecs will have
                 * the left and right channels contiguous. This allows
@@ -282,8 +270,10 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                 */
                fmt ^= SND_SOC_DAIFMT_NB_IF;
        case SND_SOC_DAIFMT_DSP_A:
-               rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);
-               xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
+               dev->mode = MOD_DSP_A;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               dev->mode = MOD_DSP_B;
                break;
        default:
                printk(KERN_ERR "%s:bad format\n", __func__);
@@ -343,9 +333,8 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                return -EINVAL;
        }
        davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
+       dev->pcr = pcr;
        davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr);
-       davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
-       davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
        return 0;
 }
 
@@ -353,31 +342,41 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *params,
                                 struct snd_soc_dai *dai)
 {
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
-       struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
+       struct davinci_mcbsp_dev *dev = dai->private_data;
+       struct davinci_pcm_dma_params *dma_params =
+                                       &dev->dma_params[substream->stream];
        struct snd_interval *i = NULL;
        int mcbsp_word_length;
-       u32 w;
+       unsigned int rcr, xcr, srgr;
+       u32 spcr;
 
        /* general line settings */
-       w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+       spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
        if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
-               w |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
-               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+               spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
+               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
        } else {
-               w |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
-               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
+               spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
+               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
        }
 
        i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
-       w = DAVINCI_MCBSP_SRGR_FSGM;
-       MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1), 1);
+       srgr = DAVINCI_MCBSP_SRGR_FSGM;
+       srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);
 
        i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);
-       MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1), 1);
-       davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w);
+       srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);
+       davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
 
+       rcr = DAVINCI_MCBSP_RCR_RFIG;
+       xcr = DAVINCI_MCBSP_XCR_XFIG;
+       if (dev->mode == MOD_DSP_B) {
+               rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0);
+               xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0);
+       } else {
+               rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);
+               xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
+       }
        /* Determine xfer data type */
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S8:
@@ -397,18 +396,31 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
-               w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG);
-               MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
-                              DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1);
-               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w);
+       dma_params->acnt  = dma_params->data_type;
+       rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1);
+       xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1);
 
-       } else {
-               w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG);
-               MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
-                              DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1);
-               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w);
+       rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
+               DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
+       xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
+               DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length);
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
+       else
+               davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
+       return 0;
+}
 
+static int davinci_i2s_prepare(struct snd_pcm_substream *substream,
+               struct snd_soc_dai *dai)
+{
+       struct davinci_mcbsp_dev *dev = dai->private_data;
+       int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       davinci_mcbsp_stop(dev, playback);
+       if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) {
+               /* codec is master */
+               davinci_mcbsp_start(dev, substream);
        }
        return 0;
 }
@@ -416,35 +428,71 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
 static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
                               struct snd_soc_dai *dai)
 {
+       struct davinci_mcbsp_dev *dev = dai->private_data;
        int ret = 0;
+       int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0)
+               return 0;       /* return if codec is master */
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               davinci_mcbsp_start(substream);
+               davinci_mcbsp_start(dev, substream);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               davinci_mcbsp_stop(substream);
+               davinci_mcbsp_stop(dev, playback);
                break;
        default:
                ret = -EINVAL;
        }
-
        return ret;
 }
 
-static int davinci_i2s_probe(struct platform_device *pdev,
-                            struct snd_soc_dai *dai)
+static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
+               struct snd_soc_dai *dai)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai;
+       struct davinci_mcbsp_dev *dev = dai->private_data;
+       int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       davinci_mcbsp_stop(dev, playback);
+}
+
+#define DAVINCI_I2S_RATES      SNDRV_PCM_RATE_8000_96000
+
+static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
+       .shutdown       = davinci_i2s_shutdown,
+       .prepare        = davinci_i2s_prepare,
+       .trigger        = davinci_i2s_trigger,
+       .hw_params      = davinci_i2s_hw_params,
+       .set_fmt        = davinci_i2s_set_dai_fmt,
+
+};
+
+struct snd_soc_dai davinci_i2s_dai = {
+       .name = "davinci-i2s",
+       .id = 0,
+       .playback = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = DAVINCI_I2S_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .capture = {
+               .channels_min = 2,
+               .channels_max = 2,
+               .rates = DAVINCI_I2S_RATES,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .ops = &davinci_i2s_dai_ops,
+
+};
+EXPORT_SYMBOL_GPL(davinci_i2s_dai);
+
+static int davinci_i2s_probe(struct platform_device *pdev)
+{
+       struct snd_platform_data *pdata = pdev->dev.platform_data;
        struct davinci_mcbsp_dev *dev;
-       struct resource *mem, *ioarea;
-       struct evm_snd_platform_data *pdata;
+       struct resource *mem, *ioarea, *res;
        int ret;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -466,8 +514,6 @@ static int davinci_i2s_probe(struct platform_device *pdev,
                goto err_release_region;
        }
 
-       cpu_dai->private_data = dev;
-
        dev->clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(dev->clk)) {
                ret = -ENODEV;
@@ -476,18 +522,35 @@ static int davinci_i2s_probe(struct platform_device *pdev,
        clk_enable(dev->clk);
 
        dev->base = (void __iomem *)IO_ADDRESS(mem->start);
-       pdata = pdev->dev.platform_data;
 
-       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &davinci_i2s_pcm_out;
-       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = pdata->tx_dma_ch;
-       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->dma_addr =
+       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr =
            (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG);
 
-       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &davinci_i2s_pcm_in;
-       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = pdata->rx_dma_ch;
-       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->dma_addr =
+       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr =
            (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG);
 
+       /* first TX, then RX */
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "no DMA resource\n");
+               ret = -ENXIO;
+               goto err_free_mem;
+       }
+       dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel = res->start;
+
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!res) {
+               dev_err(&pdev->dev, "no DMA resource\n");
+               ret = -ENXIO;
+               goto err_free_mem;
+       }
+       dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
+
+       davinci_i2s_dai.private_data = dev;
+       ret = snd_soc_register_dai(&davinci_i2s_dai);
+       if (ret != 0)
+               goto err_free_mem;
+
        return 0;
 
 err_free_mem:
@@ -498,62 +561,40 @@ err_release_region:
        return ret;
 }
 
-static void davinci_i2s_remove(struct platform_device *pdev,
-                              struct snd_soc_dai *dai)
+static int davinci_i2s_remove(struct platform_device *pdev)
 {
-       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
-       struct snd_soc_card *card = socdev->card;
-       struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai;
-       struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
+       struct davinci_mcbsp_dev *dev = davinci_i2s_dai.private_data;
        struct resource *mem;
 
+       snd_soc_unregister_dai(&davinci_i2s_dai);
        clk_disable(dev->clk);
        clk_put(dev->clk);
        dev->clk = NULL;
-
        kfree(dev);
-
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(mem->start, (mem->end - mem->start) + 1);
-}
-
-#define DAVINCI_I2S_RATES      SNDRV_PCM_RATE_8000_96000
 
-static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
-       .startup        = davinci_i2s_startup,
-       .trigger        = davinci_i2s_trigger,
-       .hw_params      = davinci_i2s_hw_params,
-       .set_fmt        = davinci_i2s_set_dai_fmt,
-};
+       return 0;
+}
 
-struct snd_soc_dai davinci_i2s_dai = {
-       .name = "davinci-i2s",
-       .id = 0,
-       .probe = davinci_i2s_probe,
-       .remove = davinci_i2s_remove,
-       .playback = {
-               .channels_min = 2,
-               .channels_max = 2,
-               .rates = DAVINCI_I2S_RATES,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
-       .capture = {
-               .channels_min = 2,
-               .channels_max = 2,
-               .rates = DAVINCI_I2S_RATES,
-               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
-       .ops = &davinci_i2s_dai_ops,
+static struct platform_driver davinci_mcbsp_driver = {
+       .probe          = davinci_i2s_probe,
+       .remove         = davinci_i2s_remove,
+       .driver         = {
+               .name   = "davinci-asp",
+               .owner  = THIS_MODULE,
+       },
 };
-EXPORT_SYMBOL_GPL(davinci_i2s_dai);
 
 static int __init davinci_i2s_init(void)
 {
-       return snd_soc_register_dai(&davinci_i2s_dai);
+       return platform_driver_register(&davinci_mcbsp_driver);
 }
 module_init(davinci_i2s_init);
 
 static void __exit davinci_i2s_exit(void)
 {
-       snd_soc_unregister_dai(&davinci_i2s_dai);
+       platform_driver_unregister(&davinci_mcbsp_driver);
 }
 module_exit(davinci_i2s_exit);
 
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
new file mode 100644 (file)
index 0000000..5d1f98a
--- /dev/null
@@ -0,0 +1,969 @@
+/*
+ * ALSA SoC McASP Audio Layer for TI DAVINCI processor
+ *
+ * Multi-channel Audio Serial Port Driver
+ *
+ * Author: Nirmal Pandey <n-pandey@ti.com>,
+ *         Suresh Rajashekara <suresh.r@ti.com>
+ *         Steve Chen <schen@.mvista.com>
+ *
+ * Copyright:   (C) 2009 MontaVista Software, Inc., <source@mvista.com>
+ * Copyright:   (C) 2009  Texas Instruments, India
+ *
+ * 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/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "davinci-pcm.h"
+#include "davinci-mcasp.h"
+
+/*
+ * McASP register definitions
+ */
+#define DAVINCI_MCASP_PID_REG          0x00
+#define DAVINCI_MCASP_PWREMUMGT_REG    0x04
+
+#define DAVINCI_MCASP_PFUNC_REG                0x10
+#define DAVINCI_MCASP_PDIR_REG         0x14
+#define DAVINCI_MCASP_PDOUT_REG                0x18
+#define DAVINCI_MCASP_PDSET_REG                0x1c
+
+#define DAVINCI_MCASP_PDCLR_REG                0x20
+
+#define DAVINCI_MCASP_TLGC_REG         0x30
+#define DAVINCI_MCASP_TLMR_REG         0x34
+
+#define DAVINCI_MCASP_GBLCTL_REG       0x44
+#define DAVINCI_MCASP_AMUTE_REG                0x48
+#define DAVINCI_MCASP_LBCTL_REG                0x4c
+
+#define DAVINCI_MCASP_TXDITCTL_REG     0x50
+
+#define DAVINCI_MCASP_GBLCTLR_REG      0x60
+#define DAVINCI_MCASP_RXMASK_REG       0x64
+#define DAVINCI_MCASP_RXFMT_REG                0x68
+#define DAVINCI_MCASP_RXFMCTL_REG      0x6c
+
+#define DAVINCI_MCASP_ACLKRCTL_REG     0x70
+#define DAVINCI_MCASP_AHCLKRCTL_REG    0x74
+#define DAVINCI_MCASP_RXTDM_REG                0x78
+#define DAVINCI_MCASP_EVTCTLR_REG      0x7c
+
+#define DAVINCI_MCASP_RXSTAT_REG       0x80
+#define DAVINCI_MCASP_RXTDMSLOT_REG    0x84
+#define DAVINCI_MCASP_RXCLKCHK_REG     0x88
+#define DAVINCI_MCASP_REVTCTL_REG      0x8c
+
+#define DAVINCI_MCASP_GBLCTLX_REG      0xa0
+#define DAVINCI_MCASP_TXMASK_REG       0xa4
+#define DAVINCI_MCASP_TXFMT_REG                0xa8
+#define DAVINCI_MCASP_TXFMCTL_REG      0xac
+
+#define DAVINCI_MCASP_ACLKXCTL_REG     0xb0
+#define DAVINCI_MCASP_AHCLKXCTL_REG    0xb4
+#define DAVINCI_MCASP_TXTDM_REG                0xb8
+#define DAVINCI_MCASP_EVTCTLX_REG      0xbc
+
+#define DAVINCI_MCASP_TXSTAT_REG       0xc0
+#define DAVINCI_MCASP_TXTDMSLOT_REG    0xc4
+#define DAVINCI_MCASP_TXCLKCHK_REG     0xc8
+#define DAVINCI_MCASP_XEVTCTL_REG      0xcc
+
+/* Left(even TDM Slot) Channel Status Register File */
+#define DAVINCI_MCASP_DITCSRA_REG      0x100
+/* Right(odd TDM slot) Channel Status Register File */
+#define DAVINCI_MCASP_DITCSRB_REG      0x118
+/* Left(even TDM slot) User Data Register File */
+#define DAVINCI_MCASP_DITUDRA_REG      0x130
+/* Right(odd TDM Slot) User Data Register File */
+#define DAVINCI_MCASP_DITUDRB_REG      0x148
+
+/* Serializer n Control Register */
+#define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180
+#define DAVINCI_MCASP_XRSRCTL_REG(n)   (DAVINCI_MCASP_XRSRCTL_BASE_REG + \
+                                               (n << 2))
+
+/* Transmit Buffer for Serializer n */
+#define DAVINCI_MCASP_TXBUF_REG                0x200
+/* Receive Buffer for Serializer n */
+#define DAVINCI_MCASP_RXBUF_REG                0x280
+
+/* McASP FIFO Registers */
+#define DAVINCI_MCASP_WFIFOCTL         (0x1010)
+#define DAVINCI_MCASP_WFIFOSTS         (0x1014)
+#define DAVINCI_MCASP_RFIFOCTL         (0x1018)
+#define DAVINCI_MCASP_RFIFOSTS         (0x101C)
+
+/*
+ * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management
+ *     Register Bits
+ */
+#define MCASP_FREE     BIT(0)
+#define MCASP_SOFT     BIT(1)
+
+/*
+ * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits
+ */
+#define AXR(n)         (1<<n)
+#define PFUNC_AMUTE    BIT(25)
+#define ACLKX          BIT(26)
+#define AHCLKX         BIT(27)
+#define AFSX           BIT(28)
+#define ACLKR          BIT(29)
+#define AHCLKR         BIT(30)
+#define AFSR           BIT(31)
+
+/*
+ * DAVINCI_MCASP_PDIR_REG - Pin Direction Register Bits
+ */
+#define AXR(n)         (1<<n)
+#define PDIR_AMUTE     BIT(25)
+#define ACLKX          BIT(26)
+#define AHCLKX         BIT(27)
+#define AFSX           BIT(28)
+#define ACLKR          BIT(29)
+#define AHCLKR         BIT(30)
+#define AFSR           BIT(31)
+
+/*
+ * DAVINCI_MCASP_TXDITCTL_REG - Transmit DIT Control Register Bits
+ */
+#define DITEN  BIT(0)  /* Transmit DIT mode enable/disable */
+#define VA     BIT(2)
+#define VB     BIT(3)
+
+/*
+ * DAVINCI_MCASP_TXFMT_REG - Transmit Bitstream Format Register Bits
+ */
+#define TXROT(val)     (val)
+#define TXSEL          BIT(3)
+#define TXSSZ(val)     (val<<4)
+#define TXPBIT(val)    (val<<8)
+#define TXPAD(val)     (val<<13)
+#define TXORD          BIT(15)
+#define FSXDLY(val)    (val<<16)
+
+/*
+ * DAVINCI_MCASP_RXFMT_REG - Receive Bitstream Format Register Bits
+ */
+#define RXROT(val)     (val)
+#define RXSEL          BIT(3)
+#define RXSSZ(val)     (val<<4)
+#define RXPBIT(val)    (val<<8)
+#define RXPAD(val)     (val<<13)
+#define RXORD          BIT(15)
+#define FSRDLY(val)    (val<<16)
+
+/*
+ * DAVINCI_MCASP_TXFMCTL_REG -  Transmit Frame Control Register Bits
+ */
+#define FSXPOL         BIT(0)
+#define AFSXE          BIT(1)
+#define FSXDUR         BIT(4)
+#define FSXMOD(val)    (val<<7)
+
+/*
+ * DAVINCI_MCASP_RXFMCTL_REG - Receive Frame Control Register Bits
+ */
+#define FSRPOL         BIT(0)
+#define AFSRE          BIT(1)
+#define FSRDUR         BIT(4)
+#define FSRMOD(val)    (val<<7)
+
+/*
+ * DAVINCI_MCASP_ACLKXCTL_REG - Transmit Clock Control Register Bits
+ */
+#define ACLKXDIV(val)  (val)
+#define ACLKXE         BIT(5)
+#define TX_ASYNC       BIT(6)
+#define ACLKXPOL       BIT(7)
+
+/*
+ * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits
+ */
+#define ACLKRDIV(val)  (val)
+#define ACLKRE         BIT(5)
+#define RX_ASYNC       BIT(6)
+#define ACLKRPOL       BIT(7)
+
+/*
+ * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control
+ *     Register Bits
+ */
+#define AHCLKXDIV(val) (val)
+#define AHCLKXPOL      BIT(14)
+#define AHCLKXE                BIT(15)
+
+/*
+ * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control
+ *     Register Bits
+ */
+#define AHCLKRDIV(val) (val)
+#define AHCLKRPOL      BIT(14)
+#define AHCLKRE                BIT(15)
+
+/*
+ * DAVINCI_MCASP_XRSRCTL_BASE_REG -  Serializer Control Register Bits
+ */
+#define MODE(val)      (val)
+#define DISMOD         (val)(val<<2)
+#define TXSTATE                BIT(4)
+#define RXSTATE                BIT(5)
+
+/*
+ * DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits
+ */
+#define LBEN           BIT(0)
+#define LBORD          BIT(1)
+#define LBGENMODE(val) (val<<2)
+
+/*
+ * DAVINCI_MCASP_TXTDMSLOT_REG - Transmit TDM Slot Register configuration
+ */
+#define TXTDMS(n)      (1<<n)
+
+/*
+ * DAVINCI_MCASP_RXTDMSLOT_REG - Receive TDM Slot Register configuration
+ */
+#define RXTDMS(n)      (1<<n)
+
+/*
+ * DAVINCI_MCASP_GBLCTL_REG -  Global Control Register Bits
+ */
+#define RXCLKRST       BIT(0)  /* Receiver Clock Divider Reset */
+#define RXHCLKRST      BIT(1)  /* Receiver High Frequency Clock Divider */
+#define RXSERCLR       BIT(2)  /* Receiver Serializer Clear */
+#define RXSMRST                BIT(3)  /* Receiver State Machine Reset */
+#define RXFSRST                BIT(4)  /* Frame Sync Generator Reset */
+#define TXCLKRST       BIT(8)  /* Transmitter Clock Divider Reset */
+#define TXHCLKRST      BIT(9)  /* Transmitter High Frequency Clock Divider*/
+#define TXSERCLR       BIT(10) /* Transmit Serializer Clear */
+#define TXSMRST                BIT(11) /* Transmitter State Machine Reset */
+#define TXFSRST                BIT(12) /* Frame Sync Generator Reset */
+
+/*
+ * DAVINCI_MCASP_AMUTE_REG -  Mute Control Register Bits
+ */
+#define MUTENA(val)    (val)
+#define MUTEINPOL      BIT(2)
+#define MUTEINENA      BIT(3)
+#define MUTEIN         BIT(4)
+#define MUTER          BIT(5)
+#define MUTEX          BIT(6)
+#define MUTEFSR                BIT(7)
+#define MUTEFSX                BIT(8)
+#define MUTEBADCLKR    BIT(9)
+#define MUTEBADCLKX    BIT(10)
+#define MUTERXDMAERR   BIT(11)
+#define MUTETXDMAERR   BIT(12)
+
+/*
+ * DAVINCI_MCASP_REVTCTL_REG - Receiver DMA Event Control Register bits
+ */
+#define RXDATADMADIS   BIT(0)
+
+/*
+ * DAVINCI_MCASP_XEVTCTL_REG - Transmitter DMA Event Control Register bits
+ */
+#define TXDATADMADIS   BIT(0)
+
+/*
+ * DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits
+ */
+#define FIFO_ENABLE    BIT(16)
+#define NUMEVT_MASK    (0xFF << 8)
+#define NUMDMA_MASK    (0xFF)
+
+#define DAVINCI_MCASP_NUM_SERIALIZER   16
+
+static inline void mcasp_set_bits(void __iomem *reg, u32 val)
+{
+       __raw_writel(__raw_readl(reg) | val, reg);
+}
+
+static inline void mcasp_clr_bits(void __iomem *reg, u32 val)
+{
+       __raw_writel((__raw_readl(reg) & ~(val)), reg);
+}
+
+static inline void mcasp_mod_bits(void __iomem *reg, u32 val, u32 mask)
+{
+       __raw_writel((__raw_readl(reg) & ~mask) | val, reg);
+}
+
+static inline void mcasp_set_reg(void __iomem *reg, u32 val)
+{
+       __raw_writel(val, reg);
+}
+
+static inline u32 mcasp_get_reg(void __iomem *reg)
+{
+       return (unsigned int)__raw_readl(reg);
+}
+
+static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
+{
+       int i = 0;
+
+       mcasp_set_bits(regs, val);
+
+       /* programming GBLCTL needs to read back from GBLCTL and verfiy */
+       /* loop count is to avoid the lock-up */
+       for (i = 0; i < 1000; i++) {
+               if ((mcasp_get_reg(regs) & val) == val)
+                       break;
+       }
+
+       if (i == 1000 && ((mcasp_get_reg(regs) & val) != val))
+               printk(KERN_ERR "GBLCTL write error\n");
+}
+
+static void mcasp_start_rx(struct davinci_audio_dev *dev)
+{
+       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
+       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
+       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
+
+       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
+       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
+
+       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
+       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
+}
+
+static void mcasp_start_tx(struct davinci_audio_dev *dev)
+{
+       u8 offset = 0, i;
+       u32 cnt;
+
+       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
+       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
+       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
+
+       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
+       mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
+       for (i = 0; i < dev->num_serializer; i++) {
+               if (dev->serial_dir[i] == TX_MODE) {
+                       offset = i;
+                       break;
+               }
+       }
+
+       /* wait for TX ready */
+       cnt = 0;
+       while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) &
+                TXSTATE) && (cnt < 100000))
+               cnt++;
+
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0);
+}
+
+static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)
+{
+       if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               if (dev->txnumevt)      /* enable FIFO */
+                       mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
+                                                               FIFO_ENABLE);
+               mcasp_start_tx(dev);
+       } else {
+               if (dev->rxnumevt)      /* enable FIFO */
+                       mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
+                                                               FIFO_ENABLE);
+               mcasp_start_rx(dev);
+       }
+}
+
+static void mcasp_stop_rx(struct davinci_audio_dev *dev)
+{
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0);
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
+}
+
+static void mcasp_stop_tx(struct davinci_audio_dev *dev)
+{
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0);
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
+}
+
+static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream)
+{
+       if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               if (dev->txnumevt)      /* disable FIFO */
+                       mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
+                                                               FIFO_ENABLE);
+               mcasp_stop_tx(dev);
+       } else {
+               if (dev->rxnumevt)      /* disable FIFO */
+                       mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
+                                                               FIFO_ENABLE);
+               mcasp_stop_rx(dev);
+       }
+}
+
+static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+                                        unsigned int fmt)
+{
+       struct davinci_audio_dev *dev = cpu_dai->private_data;
+       void __iomem *base = dev->base;
+
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               /* codec is clock and frame slave */
+               mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+               mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+
+               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+               mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+
+               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 26));
+               break;
+       case SND_SOC_DAIFMT_CBM_CFS:
+               /* codec is clock master and frame slave */
+               mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+               mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+
+               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+               mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+
+               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x2d << 26));
+               break;
+       case SND_SOC_DAIFMT_CBM_CFM:
+               /* codec is clock and frame master */
+               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE);
+               mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE);
+
+               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
+               mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
+
+               mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, (0x3f << 26));
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_IB_NF:
+               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+               mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+
+               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+               mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+               break;
+
+       case SND_SOC_DAIFMT_NB_IF:
+               mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+               mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+
+               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+               mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+               break;
+
+       case SND_SOC_DAIFMT_IB_IF:
+               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+               mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+
+               mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+               mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+               break;
+
+       case SND_SOC_DAIFMT_NB_NF:
+               mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL);
+               mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL);
+
+               mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL);
+               mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int davinci_config_channel_size(struct davinci_audio_dev *dev,
+                                      int channel_size)
+{
+       u32 fmt = 0;
+       u32 mask, rotate;
+
+       switch (channel_size) {
+       case DAVINCI_AUDIO_WORD_8:
+               fmt = 0x03;
+               rotate = 6;
+               mask = 0x000000ff;
+               break;
+
+       case DAVINCI_AUDIO_WORD_12:
+               fmt = 0x05;
+               rotate = 5;
+               mask = 0x00000fff;
+               break;
+
+       case DAVINCI_AUDIO_WORD_16:
+               fmt = 0x07;
+               rotate = 4;
+               mask = 0x0000ffff;
+               break;
+
+       case DAVINCI_AUDIO_WORD_20:
+               fmt = 0x09;
+               rotate = 3;
+               mask = 0x000fffff;
+               break;
+
+       case DAVINCI_AUDIO_WORD_24:
+               fmt = 0x0B;
+               rotate = 2;
+               mask = 0x00ffffff;
+               break;
+
+       case DAVINCI_AUDIO_WORD_28:
+               fmt = 0x0D;
+               rotate = 1;
+               mask = 0x0fffffff;
+               break;
+
+       case DAVINCI_AUDIO_WORD_32:
+               fmt = 0x0F;
+               rotate = 0;
+               mask = 0xffffffff;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
+                                       RXSSZ(fmt), RXSSZ(0x0F));
+       mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
+                                       TXSSZ(fmt), TXSSZ(0x0F));
+       mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXROT(rotate),
+                                                       TXROT(7));
+       mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXROT(rotate),
+                                                       RXROT(7));
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask);
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, mask);
+
+       return 0;
+}
+
+static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
+{
+       int i;
+       u8 tx_ser = 0;
+       u8 rx_ser = 0;
+
+       /* Default configuration */
+       mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
+
+       /* All PINS as McASP */
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000);
+
+       if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG,
+                               TXDATADMADIS);
+       } else {
+               mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_REVTCTL_REG,
+                               RXDATADMADIS);
+       }
+
+       for (i = 0; i < dev->num_serializer; i++) {
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
+                                       dev->serial_dir[i]);
+               if (dev->serial_dir[i] == TX_MODE) {
+                       mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
+                                       AXR(i));
+                       tx_ser++;
+               } else if (dev->serial_dir[i] == RX_MODE) {
+                       mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
+                                       AXR(i));
+                       rx_ser++;
+               }
+       }
+
+       if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               if (dev->txnumevt * tx_ser > 64)
+                       dev->txnumevt = 1;
+
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, tx_ser,
+                                                               NUMDMA_MASK);
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL,
+                               ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE);
+       }
+
+       if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) {
+               if (dev->rxnumevt * rx_ser > 64)
+                       dev->rxnumevt = 1;
+
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, rx_ser,
+                                                               NUMDMA_MASK);
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL,
+                               ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE);
+       }
+}
+
+static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
+{
+       int i, active_slots;
+       u32 mask = 0;
+
+       active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots;
+       for (i = 0; i < active_slots; i++)
+               mask |= (1 << i);
+
+       mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
+
+       if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               /* bit stream is MSB first  with no delay */
+               /* DSP_B mode */
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
+                               AHCLKXE);
+               mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
+
+               if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
+                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
+                                       FSXMOD(dev->tdm_slots), FSXMOD(0x1FF));
+               else
+                       printk(KERN_ERR "playback tdm slot %d not supported\n",
+                               dev->tdm_slots);
+
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+       } else {
+               /* bit stream is MSB first with no delay */
+               /* DSP_B mode */
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
+                               AHCLKRE);
+               mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
+
+               if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32))
+                       mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG,
+                                       FSRMOD(dev->tdm_slots), FSRMOD(0x1FF));
+               else
+                       printk(KERN_ERR "capture tdm slot %d not supported\n",
+                               dev->tdm_slots);
+
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+       }
+}
+
+/* S/PDIF */
+static void davinci_hw_dit_param(struct davinci_audio_dev *dev)
+{
+       /* Set the PDIR for Serialiser as output */
+       mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX);
+
+       /* TXMASK for 24 bits */
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF);
+
+       /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
+          and LSB first */
+       mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
+                                               TXROT(6) | TXSSZ(15));
+
+       /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG,
+                                               AFSXE | FSXMOD(0x180));
+
+       /* Set the TX tdm : for all the slots */
+       mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF);
+
+       /* Set the TX clock controls : div = 1 and internal */
+       mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
+                                               ACLKXE | TX_ASYNC);
+
+       mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
+
+       /* Only 44100 and 48000 are valid, both have the same setting */
+       mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3));
+
+       /* Enable the DIT */
+       mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN);
+}
+
+static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
+                                       struct snd_pcm_hw_params *params,
+                                       struct snd_soc_dai *cpu_dai)
+{
+       struct davinci_audio_dev *dev = cpu_dai->private_data;
+       struct davinci_pcm_dma_params *dma_params =
+                                       &dev->dma_params[substream->stream];
+       int word_length;
+       u8 numevt;
+
+       davinci_hw_common_param(dev, substream->stream);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               numevt = dev->txnumevt;
+       else
+               numevt = dev->rxnumevt;
+
+       if (!numevt)
+               numevt = 1;
+
+       if (dev->op_mode == DAVINCI_MCASP_DIT_MODE)
+               davinci_hw_dit_param(dev);
+       else
+               davinci_hw_param(dev, substream->stream);
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S8:
+               dma_params->data_type = 1;
+               word_length = DAVINCI_AUDIO_WORD_8;
+               break;
+
+       case SNDRV_PCM_FORMAT_S16_LE:
+               dma_params->data_type = 2;
+               word_length = DAVINCI_AUDIO_WORD_16;
+               break;
+
+       case SNDRV_PCM_FORMAT_S32_LE:
+               dma_params->data_type = 4;
+               word_length = DAVINCI_AUDIO_WORD_32;
+               break;
+
+       default:
+               printk(KERN_WARNING "davinci-mcasp: unsupported PCM format");
+               return -EINVAL;
+       }
+
+       if (dev->version == MCASP_VERSION_2) {
+               dma_params->data_type *= numevt;
+               dma_params->acnt = 4 * numevt;
+       } else
+               dma_params->acnt = dma_params->data_type;
+
+       davinci_config_channel_size(dev, word_length);
+
+       return 0;
+}
+
+static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
+                                    int cmd, struct snd_soc_dai *cpu_dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct davinci_audio_dev *dev = rtd->dai->cpu_dai->private_data;
+       int ret = 0;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               davinci_mcasp_start(dev, substream->stream);
+               break;
+
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               davinci_mcasp_stop(dev, substream->stream);
+               break;
+
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
+       .trigger        = davinci_mcasp_trigger,
+       .hw_params      = davinci_mcasp_hw_params,
+       .set_fmt        = davinci_mcasp_set_dai_fmt,
+
+};
+
+struct snd_soc_dai davinci_mcasp_dai[] = {
+       {
+               .name           = "davinci-i2s",
+               .id             = 0,
+               .playback       = {
+                       .channels_min   = 2,
+                       .channels_max   = 2,
+                       .rates          = DAVINCI_MCASP_RATES,
+                       .formats        = SNDRV_PCM_FMTBIT_S8 |
+                                               SNDRV_PCM_FMTBIT_S16_LE |
+                                               SNDRV_PCM_FMTBIT_S32_LE,
+               },
+               .capture        = {
+                       .channels_min   = 2,
+                       .channels_max   = 2,
+                       .rates          = DAVINCI_MCASP_RATES,
+                       .formats        = SNDRV_PCM_FMTBIT_S8 |
+                                               SNDRV_PCM_FMTBIT_S16_LE |
+                                               SNDRV_PCM_FMTBIT_S32_LE,
+               },
+               .ops            = &davinci_mcasp_dai_ops,
+
+       },
+       {
+               .name           = "davinci-dit",
+               .id             = 1,
+               .playback       = {
+                       .channels_min   = 1,
+                       .channels_max   = 384,
+                       .rates          = DAVINCI_MCASP_RATES,
+                       .formats        = SNDRV_PCM_FMTBIT_S16_LE,
+               },
+               .ops            = &davinci_mcasp_dai_ops,
+       },
+
+};
+EXPORT_SYMBOL_GPL(davinci_mcasp_dai);
+
+static int davinci_mcasp_probe(struct platform_device *pdev)
+{
+       struct davinci_pcm_dma_params *dma_data;
+       struct resource *mem, *ioarea, *res;
+       struct snd_platform_data *pdata;
+       struct davinci_audio_dev *dev;
+       int ret = 0;
+
+       dev = kzalloc(sizeof(struct davinci_audio_dev), GFP_KERNEL);
+       if (!dev)
+               return  -ENOMEM;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(&pdev->dev, "no mem resource?\n");
+               ret = -ENODEV;
+               goto err_release_data;
+       }
+
+       ioarea = request_mem_region(mem->start,
+                       (mem->end - mem->start) + 1, pdev->name);
+       if (!ioarea) {
+               dev_err(&pdev->dev, "Audio region already claimed\n");
+               ret = -EBUSY;
+               goto err_release_data;
+       }
+
+       pdata = pdev->dev.platform_data;
+       dev->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(dev->clk)) {
+               ret = -ENODEV;
+               goto err_release_region;
+       }
+
+       clk_enable(dev->clk);
+
+       dev->base = (void __iomem *)IO_ADDRESS(mem->start);
+       dev->op_mode = pdata->op_mode;
+       dev->tdm_slots = pdata->tdm_slots;
+       dev->num_serializer = pdata->num_serializer;
+       dev->serial_dir = pdata->serial_dir;
+       dev->codec_fmt = pdata->codec_fmt;
+       dev->version = pdata->version;
+       dev->txnumevt = pdata->txnumevt;
+       dev->rxnumevt = pdata->rxnumevt;
+
+       dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
+       dma_data->eventq_no = pdata->eventq_no;
+       dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
+                                                       io_v2p(dev->base));
+
+       /* first TX, then RX */
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "no DMA resource\n");
+               goto err_release_region;
+       }
+
+       dma_data->channel = res->start;
+
+       dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE];
+       dma_data->eventq_no = pdata->eventq_no;
+       dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
+                                                       io_v2p(dev->base));
+
+       res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+       if (!res) {
+               dev_err(&pdev->dev, "no DMA resource\n");
+               goto err_release_region;
+       }
+
+       dma_data->channel = res->start;
+       davinci_mcasp_dai[pdata->op_mode].private_data = dev;
+       davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev;
+       ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]);
+
+       if (ret != 0)
+               goto err_release_region;
+       return 0;
+
+err_release_region:
+       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+err_release_data:
+       kfree(dev);
+
+       return ret;
+}
+
+static int davinci_mcasp_remove(struct platform_device *pdev)
+{
+       struct snd_platform_data *pdata = pdev->dev.platform_data;
+       struct davinci_audio_dev *dev;
+       struct resource *mem;
+
+       snd_soc_unregister_dai(&davinci_mcasp_dai[pdata->op_mode]);
+       dev = davinci_mcasp_dai[pdata->op_mode].private_data;
+       clk_disable(dev->clk);
+       clk_put(dev->clk);
+       dev->clk = NULL;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+
+       kfree(dev);
+
+       return 0;
+}
+
+static struct platform_driver davinci_mcasp_driver = {
+       .probe          = davinci_mcasp_probe,
+       .remove         = davinci_mcasp_remove,
+       .driver         = {
+               .name   = "davinci-mcasp",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init davinci_mcasp_init(void)
+{
+       return platform_driver_register(&davinci_mcasp_driver);
+}
+module_init(davinci_mcasp_init);
+
+static void __exit davinci_mcasp_exit(void)
+{
+       platform_driver_unregister(&davinci_mcasp_driver);
+}
+module_exit(davinci_mcasp_exit);
+
+MODULE_AUTHOR("Steve Chen");
+MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface");
+MODULE_LICENSE("GPL");
+
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
new file mode 100644 (file)
index 0000000..9d179cc
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * ALSA SoC McASP Audio Layer for TI DAVINCI processor
+ *
+ * MCASP related definitions
+ *
+ * Author: Nirmal Pandey <n-pandey@ti.com>,
+ *         Suresh Rajashekara <suresh.r@ti.com>
+ *         Steve Chen <schen@.mvista.com>
+ *
+ * Copyright:   (C) 2009 MontaVista Software, Inc., <source@mvista.com>
+ * Copyright:   (C) 2009  Texas Instruments, India
+ *
+ * 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 DAVINCI_MCASP_H
+#define DAVINCI_MCASP_H
+
+#include <linux/io.h>
+#include <mach/asp.h>
+#include "davinci-pcm.h"
+
+extern struct snd_soc_dai davinci_mcasp_dai[];
+
+#define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_96000
+#define DAVINCI_MCASP_I2S_DAI  0
+#define DAVINCI_MCASP_DIT_DAI  1
+
+enum {
+       DAVINCI_AUDIO_WORD_8 = 0,
+       DAVINCI_AUDIO_WORD_12,
+       DAVINCI_AUDIO_WORD_16,
+       DAVINCI_AUDIO_WORD_20,
+       DAVINCI_AUDIO_WORD_24,
+       DAVINCI_AUDIO_WORD_32,
+       DAVINCI_AUDIO_WORD_28,  /* This is only valid for McASP */
+};
+
+struct davinci_audio_dev {
+       /*
+        * dma_params must be first because rtd->dai->cpu_dai->private_data
+        * is cast to a pointer of an array of struct davinci_pcm_dma_params in
+        * davinci_pcm_open.
+        */
+       struct davinci_pcm_dma_params dma_params[2];
+       void __iomem *base;
+       int sample_rate;
+       struct clk *clk;
+       unsigned int codec_fmt;
+
+       /* McASP specific data */
+       int     tdm_slots;
+       u8      op_mode;
+       u8      num_serializer;
+       u8      *serial_dir;
+       u8      version;
+
+       /* McASP FIFO related */
+       u8      txnumevt;
+       u8      rxnumevt;
+};
+
+#endif /* DAVINCI_MCASP_H */
index a059965884896d78b7a0a1c15889c777675db867..359e99ec7244b08be127aa8b20d10a0762199d13 100644 (file)
@@ -67,6 +67,7 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
        dma_addr_t src, dst;
        unsigned short src_bidx, dst_bidx;
        unsigned int data_type;
+       unsigned short acnt;
        unsigned int count;
 
        period_size = snd_pcm_lib_period_bytes(substream);
@@ -91,11 +92,12 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
                dst_bidx = data_type;
        }
 
+       acnt = prtd->params->acnt;
        edma_set_src(lch, src, INCR, W8BIT);
        edma_set_dest(lch, dst, INCR, W8BIT);
        edma_set_src_index(lch, src_bidx, 0);
        edma_set_dest_index(lch, dst_bidx, 0);
-       edma_set_transfer_params(lch, data_type, count, 1, 0, ASYNC);
+       edma_set_transfer_params(lch, acnt, count, 1, 0, ASYNC);
 
        prtd->period++;
        if (unlikely(prtd->period >= runtime->periods))
@@ -124,16 +126,9 @@ static void davinci_pcm_dma_irq(unsigned lch, u16 ch_status, void *data)
 static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
 {
        struct davinci_runtime_data *prtd = substream->runtime->private_data;
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct davinci_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_data;
        struct edmacc_param p_ram;
        int ret;
 
-       if (!dma_data)
-               return -ENODEV;
-
-       prtd->params = dma_data;
-
        /* Request master DMA channel */
        ret = edma_alloc_channel(prtd->params->channel,
                                  davinci_pcm_dma_irq, substream,
@@ -206,6 +201,7 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
        /* Copy self-linked parameter RAM entry into master channel */
        edma_read_slot(prtd->slave_lch, &temp);
        edma_write_slot(prtd->master_lch, &temp);
+       davinci_pcm_enqueue_dma(substream);
 
        return 0;
 }
@@ -241,14 +237,25 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct davinci_runtime_data *prtd;
        int ret = 0;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct davinci_pcm_dma_params *pa = rtd->dai->cpu_dai->private_data;
+       struct davinci_pcm_dma_params *params = &pa[substream->stream];
+       if (!params)
+               return -ENODEV;
 
        snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware);
+       /* ensure that buffer size is a multiple of period size */
+       ret = snd_pcm_hw_constraint_integer(runtime,
+                                               SNDRV_PCM_HW_PARAM_PERIODS);
+       if (ret < 0)
+               return ret;
 
        prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL);
        if (prtd == NULL)
                return -ENOMEM;
 
        spin_lock_init(&prtd->lock);
+       prtd->params = params;
 
        runtime->private_data = prtd;
 
index 62cb4eb07e34404121f7075a2c6de05c28fe40bb..8746606efc893114a10f4135fe2420006da96321 100644 (file)
 #ifndef _DAVINCI_PCM_H
 #define _DAVINCI_PCM_H
 
+#include <mach/edma.h>
+#include <mach/asp.h>
+
+
 struct davinci_pcm_dma_params {
-       char *name;             /* stream identifier */
-       int channel;            /* sync dma channel ID */
-       dma_addr_t dma_addr;    /* device physical address for DMA */
-       unsigned int data_type; /* xfer data type */
+       int channel;                    /* sync dma channel ID */
+       unsigned short acnt;
+       dma_addr_t dma_addr;            /* device physical address for DMA */
+       enum dma_event_q eventq_no;     /* event queue number */
+       unsigned char data_type;        /* xfer data type */
+       unsigned char convert_mono_stereo;
 };
 
-struct evm_snd_platform_data {
-       int tx_dma_ch;
-       int rx_dma_ch;
-};
 
 extern struct snd_soc_platform davinci_soc_platform;
 
index 5dbebf82249ca735776d942ed9e3335e7b300b09..8cb65ccad35fb8cfcf96caac60cd2b0e1adb468e 100644 (file)
@@ -33,7 +33,7 @@ config SND_SOC_MPC5200_I2S
 config SND_SOC_MPC5200_AC97
        tristate "Freescale MPC5200 PSC in AC97 mode driver"
        depends on PPC_MPC52xx && PPC_BESTCOMM
-       select AC97_BUS
+       select SND_SOC_AC97_BUS
        select SND_MPC52xx_DMA
        select PPC_BESTCOMM_GEN_BD
        help
@@ -41,7 +41,7 @@ config SND_SOC_MPC5200_AC97
 
 config SND_MPC52xx_SOC_PCM030
        tristate "SoC AC97 Audio support for Phytec pcm030 and WM9712"
-       depends on PPC_MPC5200_SIMPLE && BROKEN
+       depends on PPC_MPC5200_SIMPLE
        select SND_SOC_MPC5200_AC97
        select SND_SOC_WM9712
        help
@@ -50,7 +50,7 @@ config SND_MPC52xx_SOC_PCM030
 
 config SND_MPC52xx_SOC_EFIKA
        tristate "SoC AC97 Audio support for bbplan Efika and STAC9766"
-       depends on PPC_EFIKA && BROKEN
+       depends on PPC_EFIKA
        select SND_SOC_MPC5200_AC97
        select SND_SOC_STAC9766
        help
index 85b0e75695048465728b3d5de2ee76374ff60c09..3326e2a1e8633a9ee357541c687536ec701f6f62 100644 (file)
@@ -30,6 +30,8 @@
 #include "mpc5200_psc_ac97.h"
 #include "../codecs/stac9766.h"
 
+#define DRV_NAME "efika-audio-fabric"
+
 static struct snd_soc_device device;
 static struct snd_soc_card card;
 
index efec33a1c5bddc443e56b0807f76aace8c58a569..6096d22283e6e5043386724cf11caf54b597f536 100644 (file)
@@ -69,6 +69,23 @@ static void psc_dma_bcom_enqueue_next_buffer(struct psc_dma_stream *s)
 
 static void psc_dma_bcom_enqueue_tx(struct psc_dma_stream *s)
 {
+       if (s->appl_ptr > s->runtime->control->appl_ptr) {
+               /*
+                * In this case s->runtime->control->appl_ptr has wrapped around.
+                * Play the data to the end of the boundary, then wrap our own
+                * appl_ptr back around.
+                */
+               while (s->appl_ptr < s->runtime->boundary) {
+                       if (bcom_queue_full(s->bcom_task))
+                               return;
+
+                       s->appl_ptr += s->period_size;
+
+                       psc_dma_bcom_enqueue_next_buffer(s);
+               }
+               s->appl_ptr -= s->runtime->boundary;
+       }
+
        while (s->appl_ptr < s->runtime->control->appl_ptr) {
 
                if (bcom_queue_full(s->bcom_task))
@@ -430,6 +447,7 @@ int mpc5200_audio_dma_create(struct of_device *op)
        int size, irq, rc;
        const __be32 *prop;
        void __iomem *regs;
+       int ret;
 
        /* Fetch the registers and IRQ of the PSC */
        irq = irq_of_parse_and_map(op->node, 0);
@@ -446,16 +464,19 @@ int mpc5200_audio_dma_create(struct of_device *op)
        /* Allocate and initialize the driver private data */
        psc_dma = kzalloc(sizeof *psc_dma, GFP_KERNEL);
        if (!psc_dma) {
-               iounmap(regs);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto out_unmap;
        }
 
        /* Get the PSC ID */
        prop = of_get_property(op->node, "cell-index", &size);
-       if (!prop || size < sizeof *prop)
-               return -ENODEV;
+       if (!prop || size < sizeof *prop) {
+               ret = -ENODEV;
+               goto out_free;
+       }
 
        spin_lock_init(&psc_dma->lock);
+       mutex_init(&psc_dma->mutex);
        psc_dma->id = be32_to_cpu(*prop);
        psc_dma->irq = irq;
        psc_dma->psc_regs = regs;
@@ -475,9 +496,8 @@ int mpc5200_audio_dma_create(struct of_device *op)
        if (!psc_dma->capture.bcom_task ||
            !psc_dma->playback.bcom_task) {
                dev_err(&op->dev, "Could not allocate bestcomm tasks\n");
-               iounmap(regs);
-               kfree(psc_dma);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto out_free;
        }
 
        /* Disable all interrupts and reset the PSC */
@@ -519,12 +539,8 @@ int mpc5200_audio_dma_create(struct of_device *op)
                          &psc_dma_bcom_irq_tx, IRQF_SHARED,
                          "psc-dma-playback", &psc_dma->playback);
        if (rc) {
-               free_irq(psc_dma->irq, psc_dma);
-               free_irq(psc_dma->capture.irq,
-                        &psc_dma->capture);
-               free_irq(psc_dma->playback.irq,
-                        &psc_dma->playback);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto out_irq;
        }
 
        /* Save what we've done so it can be found again later */
@@ -532,6 +548,15 @@ int mpc5200_audio_dma_create(struct of_device *op)
 
        /* Tell the ASoC OF helpers about it */
        return snd_soc_register_platform(&mpc5200_audio_dma_platform);
+out_irq:
+       free_irq(psc_dma->irq, psc_dma);
+       free_irq(psc_dma->capture.irq, &psc_dma->capture);
+       free_irq(psc_dma->playback.irq, &psc_dma->playback);
+out_free:
+       kfree(psc_dma);
+out_unmap:
+       iounmap(regs);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create);
 
index 2000803f06a721f236d7caae1104993cedbfeff7..8d396bb9d9fe405db9c10dc12d14e2dedabfaf58 100644 (file)
@@ -55,6 +55,7 @@ struct psc_dma {
        unsigned int irq;
        struct device *dev;
        spinlock_t lock;
+       struct mutex mutex;
        u32 sicr;
        uint sysclk;
        int imr;
index 794a247b3eb55ec758a55a9b21e43533cc25e891..c4ae3e096bb9154376a3a3760e3cf4897cad65a3 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
+#include <linux/delay.h>
 
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -34,13 +35,20 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
        int status;
        unsigned int val;
 
+       mutex_lock(&psc_dma->mutex);
+
        /* Wait for command send status zero = ready */
        status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
                                MPC52xx_PSC_SR_CMDSEND), 100, 0);
        if (status == 0) {
                pr_err("timeout on ac97 bus (rdy)\n");
+               mutex_unlock(&psc_dma->mutex);
                return -ENODEV;
        }
+
+       /* Force clear the data valid bit */
+       in_be32(&psc_dma->psc_regs->ac97_data);
+
        /* Send the read */
        out_be32(&psc_dma->psc_regs->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24));
 
@@ -50,16 +58,19 @@ static unsigned short psc_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
        if (status == 0) {
                pr_err("timeout on ac97 read (val) %x\n",
                                in_be16(&psc_dma->psc_regs->sr_csr.status));
+               mutex_unlock(&psc_dma->mutex);
                return -ENODEV;
        }
        /* Get the data */
        val = in_be32(&psc_dma->psc_regs->ac97_data);
        if (((val >> 24) & 0x7f) != reg) {
                pr_err("reg echo error on ac97 read\n");
+               mutex_unlock(&psc_dma->mutex);
                return -ENODEV;
        }
        val = (val >> 8) & 0xffff;
 
+       mutex_unlock(&psc_dma->mutex);
        return (unsigned short) val;
 }
 
@@ -68,16 +79,21 @@ static void psc_ac97_write(struct snd_ac97 *ac97,
 {
        int status;
 
+       mutex_lock(&psc_dma->mutex);
+
        /* Wait for command status zero = ready */
        status = spin_event_timeout(!(in_be16(&psc_dma->psc_regs->sr_csr.status) &
                                MPC52xx_PSC_SR_CMDSEND), 100, 0);
        if (status == 0) {
                pr_err("timeout on ac97 bus (write)\n");
-               return;
+               goto out;
        }
        /* Write data */
        out_be32(&psc_dma->psc_regs->ac97_cmd,
                        ((reg & 0x7f) << 24) | (val << 8));
+
+ out:
+       mutex_unlock(&psc_dma->mutex);
 }
 
 static void psc_ac97_warm_reset(struct snd_ac97 *ac97)
@@ -97,7 +113,7 @@ static void psc_ac97_cold_reset(struct snd_ac97 *ac97)
        out_8(&regs->op1, MPC52xx_PSC_OP_RES);
        udelay(10);
        out_8(&regs->op0, MPC52xx_PSC_OP_RES);
-       udelay(50);
+       msleep(1);
        psc_ac97_warm_reset(ac97);
 }
 
index 8766f7a3893d92aac0797d40652cadc77216af23..b928ef7d28eb82461e7ac3513bef6534d2addf75 100644 (file)
@@ -30,6 +30,8 @@
 #include "mpc5200_psc_ac97.h"
 #include "../codecs/wm9712.h"
 
+#define DRV_NAME "pcm030-audio-fabric"
+
 static struct snd_soc_device device;
 static struct snd_soc_card card;
 
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
new file mode 100644 (file)
index 0000000..a700562
--- /dev/null
@@ -0,0 +1,21 @@
+config SND_MX1_MX2_SOC
+       tristate "SoC Audio for Freecale i.MX1x i.MX2x CPUs"
+       depends on ARCH_MX2 || ARCH_MX1
+       select SND_PCM
+       help
+         Say Y or M if you want to add support for codecs attached to
+         the MX1 or MX2 SSI interface.
+
+config SND_MXC_SOC_SSI
+       tristate
+
+config SND_SOC_MX27VIS_WM8974
+       tristate "SoC Audio support for MX27 - WM8974 Visstrim_sm10 board"
+       depends on SND_MX1_MX2_SOC && MACH_MX27 && MACH_IMX27_VISSTRIM_M10
+       select SND_MXC_SOC_SSI
+       select SND_SOC_WM8974
+       help
+         Say Y if you want to add support for SoC audio on Visstrim SM10
+         board with WM8974.
+
+
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile
new file mode 100644 (file)
index 0000000..c2ffd2c
--- /dev/null
@@ -0,0 +1,10 @@
+# i.MX Platform Support
+snd-soc-mx1_mx2-objs := mx1_mx2-pcm.o
+snd-soc-mxc-ssi-objs := mxc-ssi.o
+
+obj-$(CONFIG_SND_MX1_MX2_SOC) += snd-soc-mx1_mx2.o
+obj-$(CONFIG_SND_MXC_SOC_SSI) += snd-soc-mxc-ssi.o
+
+# i.MX Machine Support
+snd-soc-mx27vis-wm8974-objs := mx27vis_wm8974.o
+obj-$(CONFIG_SND_SOC_MX27VIS_WM8974) += snd-soc-mx27vis-wm8974.o
diff --git a/sound/soc/imx/mx1_mx2-pcm.c b/sound/soc/imx/mx1_mx2-pcm.c
new file mode 100644 (file)
index 0000000..b838665
--- /dev/null
@@ -0,0 +1,488 @@
+/*
+ * mx1_mx2-pcm.c -- ALSA SoC interface for Freescale i.MX1x, i.MX2x CPUs
+ *
+ * Copyright 2009 Vista Silicon S.L.
+ * Author: Javier Martin
+ *         javier.martin@vista-silicon.com
+ *
+ * Based on mxc-pcm.c by Liam Girdwood.
+ *
+ * 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/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <asm/dma.h>
+#include <mach/hardware.h>
+#include <mach/dma-mx1-mx2.h>
+
+#include "mx1_mx2-pcm.h"
+
+
+static const struct snd_pcm_hardware mx1_mx2_pcm_hardware = {
+       .info                   = (SNDRV_PCM_INFO_INTERLEAVED |
+                                  SNDRV_PCM_INFO_BLOCK_TRANSFER |
+                                  SNDRV_PCM_INFO_MMAP |
+                                  SNDRV_PCM_INFO_MMAP_VALID),
+       .formats                = SNDRV_PCM_FMTBIT_S16_LE,
+       .buffer_bytes_max       = 32 * 1024,
+       .period_bytes_min       = 64,
+       .period_bytes_max       = 8 * 1024,
+       .periods_min            = 2,
+       .periods_max            = 255,
+       .fifo_size              = 0,
+};
+
+struct mx1_mx2_runtime_data {
+       int dma_ch;
+       int active;
+       unsigned int period;
+       unsigned int periods;
+       int tx_spin;
+       spinlock_t dma_lock;
+       struct mx1_mx2_pcm_dma_params *dma_params;
+};
+
+
+/**
+  * This function stops the current dma transfer for playback
+  * and clears the dma pointers.
+  *
+  * @param     substream       pointer to the structure of the current stream.
+  *
+  */
+static int audio_stop_dma(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct mx1_mx2_runtime_data *prtd = runtime->private_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&prtd->dma_lock, flags);
+
+       pr_debug("%s\n", __func__);
+
+       prtd->active = 0;
+       prtd->period = 0;
+       prtd->periods = 0;
+
+       /* this stops the dma channel and clears the buffer ptrs */
+
+       imx_dma_disable(prtd->dma_ch);
+
+       spin_unlock_irqrestore(&prtd->dma_lock, flags);
+
+       return 0;
+}
+
+/**
+  * This function is called whenever a new audio block needs to be
+  * transferred to the codec. The function receives the address and the size
+  * of the new block and start a new DMA transfer.
+  *
+  * @param     substream       pointer to the structure of the current stream.
+  *
+  */
+static int dma_new_period(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime =  substream->runtime;
+       struct mx1_mx2_runtime_data *prtd = runtime->private_data;
+       unsigned int dma_size;
+       unsigned int offset;
+       int ret = 0;
+       dma_addr_t mem_addr;
+       unsigned int dev_addr;
+
+       if (prtd->active) {
+               dma_size = frames_to_bytes(runtime, runtime->period_size);
+               offset = dma_size * prtd->period;
+
+               pr_debug("%s: period (%d) out of (%d)\n", __func__,
+                       prtd->period,
+                       runtime->periods);
+               pr_debug("period_size %d frames\n offset %d bytes\n",
+                       (unsigned int)runtime->period_size,
+                       offset);
+               pr_debug("dma_size %d bytes\n", dma_size);
+
+               snd_BUG_ON(dma_size > mx1_mx2_pcm_hardware.period_bytes_max);
+
+               mem_addr = (dma_addr_t)(runtime->dma_addr + offset);
+               dev_addr = prtd->dma_params->per_address;
+               pr_debug("%s: mem_addr is %x\n dev_addr is %x\n",
+                                __func__, mem_addr, dev_addr);
+
+               ret = imx_dma_setup_single(prtd->dma_ch, mem_addr,
+                                       dma_size, dev_addr,
+                                       prtd->dma_params->transfer_type);
+               if (ret < 0) {
+                       printk(KERN_ERR "Error %d configuring DMA\n", ret);
+                       return ret;
+               }
+               imx_dma_enable(prtd->dma_ch);
+
+               pr_debug("%s: transfer enabled\nmem_addr = %x\n",
+                       __func__, (unsigned int) mem_addr);
+               pr_debug("dev_addr = %x\ndma_size = %d\n",
+                       (unsigned int) dev_addr, dma_size);
+
+               prtd->tx_spin = 1; /* FGA little trick to retrieve DMA pos */
+               prtd->period++;
+               prtd->period %= runtime->periods;
+    }
+       return ret;
+}
+
+
+/**
+  * This is a callback which will be called
+  * when a TX transfer finishes. The call occurs
+  * in interrupt context.
+  *
+  * @param     dat     pointer to the structure of the current stream.
+  *
+  */
+static void audio_dma_irq(int channel, void *data)
+{
+       struct snd_pcm_substream *substream;
+       struct snd_pcm_runtime *runtime;
+       struct mx1_mx2_runtime_data *prtd;
+       unsigned int dma_size;
+       unsigned int previous_period;
+       unsigned int offset;
+
+       substream = data;
+       runtime = substream->runtime;
+       prtd = runtime->private_data;
+       previous_period  = prtd->periods;
+       dma_size = frames_to_bytes(runtime, runtime->period_size);
+       offset = dma_size * previous_period;
+
+       prtd->tx_spin = 0;
+       prtd->periods++;
+       prtd->periods %= runtime->periods;
+
+       pr_debug("%s: irq per %d offset %x\n", __func__, prtd->periods, offset);
+
+       /*
+         * If we are getting a callback for an active stream then we inform
+         * the PCM middle layer we've finished a period
+         */
+       if (prtd->active)
+               snd_pcm_period_elapsed(substream);
+
+       /*
+         * Trig next DMA transfer
+         */
+       dma_new_period(substream);
+}
+
+/**
+  * This function configures the hardware to allow audio
+  * playback operations. It is called by ALSA framework.
+  *
+  * @param     substream       pointer to the structure of the current stream.
+  *
+  * @return              0 on success, -1 otherwise.
+  */
+static int
+snd_mx1_mx2_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime =  substream->runtime;
+       struct mx1_mx2_runtime_data *prtd = runtime->private_data;
+
+       prtd->period = 0;
+       prtd->periods = 0;
+
+       return 0;
+}
+
+static int mx1_mx2_pcm_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *hw_params)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int ret;
+
+       ret = snd_pcm_lib_malloc_pages(substream,
+                                       params_buffer_bytes(hw_params));
+       if (ret < 0) {
+               printk(KERN_ERR "%s: Error %d failed to malloc pcm pages \n",
+               __func__, ret);
+               return ret;
+       }
+
+       pr_debug("%s: snd_imx1_mx2_audio_hw_params runtime->dma_addr 0x(%x)\n",
+               __func__, (unsigned int)runtime->dma_addr);
+       pr_debug("%s: snd_imx1_mx2_audio_hw_params runtime->dma_area 0x(%x)\n",
+               __func__, (unsigned int)runtime->dma_area);
+       pr_debug("%s: snd_imx1_mx2_audio_hw_params runtime->dma_bytes 0x(%x)\n",
+               __func__, (unsigned int)runtime->dma_bytes);
+
+       return ret;
+}
+
+static int mx1_mx2_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct mx1_mx2_runtime_data *prtd = runtime->private_data;
+
+       imx_dma_free(prtd->dma_ch);
+
+       snd_pcm_lib_free_pages(substream);
+
+       return 0;
+}
+
+static int mx1_mx2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct mx1_mx2_runtime_data *prtd = substream->runtime->private_data;
+       int ret = 0;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               prtd->tx_spin = 0;
+               /* requested stream startup */
+               prtd->active = 1;
+               pr_debug("%s: starting dma_new_period\n", __func__);
+               ret = dma_new_period(substream);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               /* requested stream shutdown */
+               pr_debug("%s: stopping dma transfer\n", __func__);
+               ret = audio_stop_dma(substream);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static snd_pcm_uframes_t
+mx1_mx2_pcm_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct mx1_mx2_runtime_data *prtd = runtime->private_data;
+       unsigned int offset = 0;
+
+       /* tx_spin value is used here to check if a transfer is active */
+       if (prtd->tx_spin) {
+               offset = (runtime->period_size * (prtd->periods)) +
+                                               (runtime->period_size >> 1);
+               if (offset >= runtime->buffer_size)
+                       offset = runtime->period_size >> 1;
+       } else {
+               offset = (runtime->period_size * (prtd->periods));
+               if (offset >= runtime->buffer_size)
+                       offset = 0;
+       }
+       pr_debug("%s: pointer offset %x\n", __func__, offset);
+
+       return offset;
+}
+
+static int mx1_mx2_pcm_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct mx1_mx2_runtime_data *prtd;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct mx1_mx2_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_data;
+       int ret;
+
+       snd_soc_set_runtime_hwparams(substream, &mx1_mx2_pcm_hardware);
+
+       ret = snd_pcm_hw_constraint_integer(runtime,
+                                       SNDRV_PCM_HW_PARAM_PERIODS);
+       if (ret < 0)
+               return ret;
+
+       prtd = kzalloc(sizeof(struct mx1_mx2_runtime_data), GFP_KERNEL);
+       if (prtd == NULL) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       runtime->private_data = prtd;
+
+       if (!dma_data)
+               return -ENODEV;
+
+       prtd->dma_params = dma_data;
+
+       pr_debug("%s: Requesting dma channel (%s)\n", __func__,
+                                               prtd->dma_params->name);
+       prtd->dma_ch = imx_dma_request_by_prio(prtd->dma_params->name,
+                                               DMA_PRIO_HIGH);
+       if (prtd->dma_ch < 0) {
+               printk(KERN_ERR "Error %d requesting dma channel\n", ret);
+               return ret;
+       }
+       imx_dma_config_burstlen(prtd->dma_ch,
+                               prtd->dma_params->watermark_level);
+
+       ret = imx_dma_config_channel(prtd->dma_ch,
+                       prtd->dma_params->per_config,
+                       prtd->dma_params->mem_config,
+                       prtd->dma_params->event_id, 0);
+
+       if (ret) {
+               pr_debug(KERN_ERR "Error %d configuring dma channel %d\n",
+                       ret, prtd->dma_ch);
+               return ret;
+       }
+
+       pr_debug("%s: Setting tx dma callback function\n", __func__);
+       ret = imx_dma_setup_handlers(prtd->dma_ch,
+                               audio_dma_irq, NULL,
+                               (void *)substream);
+       if (ret < 0) {
+               printk(KERN_ERR "Error %d setting dma callback function\n", ret);
+               return ret;
+       }
+       return 0;
+
+ out:
+       return ret;
+}
+
+static int mx1_mx2_pcm_close(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct mx1_mx2_runtime_data *prtd = runtime->private_data;
+
+       kfree(prtd);
+
+       return 0;
+}
+
+static int mx1_mx2_pcm_mmap(struct snd_pcm_substream *substream,
+                               struct vm_area_struct *vma)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+                                    runtime->dma_area,
+                                    runtime->dma_addr,
+                                    runtime->dma_bytes);
+}
+
+static struct snd_pcm_ops mx1_mx2_pcm_ops = {
+       .open           = mx1_mx2_pcm_open,
+       .close          = mx1_mx2_pcm_close,
+       .ioctl          = snd_pcm_lib_ioctl,
+       .hw_params      = mx1_mx2_pcm_hw_params,
+       .hw_free        = mx1_mx2_pcm_hw_free,
+       .prepare        = snd_mx1_mx2_prepare,
+       .trigger        = mx1_mx2_pcm_trigger,
+       .pointer        = mx1_mx2_pcm_pointer,
+       .mmap           = mx1_mx2_pcm_mmap,
+};
+
+static u64 mx1_mx2_pcm_dmamask = 0xffffffff;
+
+static int mx1_mx2_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+       struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+       struct snd_dma_buffer *buf = &substream->dma_buffer;
+       size_t size = mx1_mx2_pcm_hardware.buffer_bytes_max;
+       buf->dev.type = SNDRV_DMA_TYPE_DEV;
+       buf->dev.dev = pcm->card->dev;
+       buf->private_data = NULL;
+
+       /* Reserve uncached-buffered memory area for DMA */
+       buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+                                          &buf->addr, GFP_KERNEL);
+
+       pr_debug("%s: preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
+               __func__, (void *) buf->area, (void *) buf->addr, size);
+
+       if (!buf->area)
+               return -ENOMEM;
+
+       buf->bytes = size;
+       return 0;
+}
+
+static void mx1_mx2_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+       struct snd_pcm_substream *substream;
+       struct snd_dma_buffer *buf;
+       int stream;
+
+       for (stream = 0; stream < 2; stream++) {
+               substream = pcm->streams[stream].substream;
+               if (!substream)
+                       continue;
+
+               buf = &substream->dma_buffer;
+               if (!buf->area)
+                       continue;
+
+               dma_free_writecombine(pcm->card->dev, buf->bytes,
+                                     buf->area, buf->addr);
+               buf->area = NULL;
+       }
+}
+
+static int mx1_mx2_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
+       struct snd_pcm *pcm)
+{
+       int ret = 0;
+
+       if (!card->dev->dma_mask)
+               card->dev->dma_mask = &mx1_mx2_pcm_dmamask;
+       if (!card->dev->coherent_dma_mask)
+               card->dev->coherent_dma_mask = 0xffffffff;
+
+       if (dai->playback.channels_min) {
+               ret = mx1_mx2_pcm_preallocate_dma_buffer(pcm,
+                       SNDRV_PCM_STREAM_PLAYBACK);
+               pr_debug("%s: preallocate playback buffer\n", __func__);
+               if (ret)
+                       goto out;
+       }
+
+       if (dai->capture.channels_min) {
+               ret = mx1_mx2_pcm_preallocate_dma_buffer(pcm,
+                       SNDRV_PCM_STREAM_CAPTURE);
+               pr_debug("%s: preallocate capture buffer\n", __func__);
+               if (ret)
+                       goto out;
+       }
+ out:
+       return ret;
+}
+
+struct snd_soc_platform mx1_mx2_soc_platform = {
+       .name           = "mx1_mx2-audio",
+       .pcm_ops        = &mx1_mx2_pcm_ops,
+       .pcm_new        = mx1_mx2_pcm_new,
+       .pcm_free       = mx1_mx2_pcm_free_dma_buffers,
+};
+EXPORT_SYMBOL_GPL(mx1_mx2_soc_platform);
+
+static int __init mx1_mx2_soc_platform_init(void)
+{
+       return snd_soc_register_platform(&mx1_mx2_soc_platform);
+}
+module_init(mx1_mx2_soc_platform_init);
+
+static void __exit mx1_mx2_soc_platform_exit(void)
+{
+       snd_soc_unregister_platform(&mx1_mx2_soc_platform);
+}
+module_exit(mx1_mx2_soc_platform_exit);
+
+MODULE_AUTHOR("Javier Martin, javier.martin@vista-silicon.com");
+MODULE_DESCRIPTION("Freescale i.MX2x, i.MX1x PCM DMA module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/imx/mx1_mx2-pcm.h b/sound/soc/imx/mx1_mx2-pcm.h
new file mode 100644 (file)
index 0000000..2e52810
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * mx1_mx2-pcm.h :- ASoC platform header for Freescale i.MX1x, i.MX2x
+ *
+ * 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 _MX1_MX2_PCM_H
+#define _MX1_MX2_PCM_H
+
+/* DMA information for mx1_mx2 platforms */
+struct mx1_mx2_pcm_dma_params {
+       char *name;                     /* stream identifier */
+       unsigned int transfer_type;     /* READ or WRITE DMA transfer */
+       dma_addr_t per_address;         /* physical address of SSI fifo */
+       int event_id;                   /* fixed DMA number for SSI fifo */
+       int watermark_level;            /* SSI fifo watermark level */
+       int per_config;                 /* DMA Config flags for peripheral */
+       int mem_config;                 /* DMA Config flags for RAM */
+ };
+
+/* platform data */
+extern struct snd_soc_platform mx1_mx2_soc_platform;
+
+#endif
diff --git a/sound/soc/imx/mx27vis_wm8974.c b/sound/soc/imx/mx27vis_wm8974.c
new file mode 100644 (file)
index 0000000..e4dcb53
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * mx27vis_wm8974.c  --  SoC audio for mx27vis
+ *
+ * Copyright 2009 Vista Silicon S.L.
+ * Author: Javier Martin
+ *         javier.martin@vista-silicon.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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+
+#include "../codecs/wm8974.h"
+#include "mx1_mx2-pcm.h"
+#include "mxc-ssi.h"
+#include <mach/gpio.h>
+#include <mach/iomux.h>
+
+#define IGNORED_ARG 0
+
+
+static struct snd_soc_card mx27vis;
+
+/**
+  * This function connects SSI1 (HPCR1) as slave to
+  * SSI1 external signals (PPCR1)
+  * As slave, HPCR1 must set TFSDIR and TCLKDIR as inputs from
+  * port 4
+  */
+void audmux_connect_1_4(void)
+{
+       pr_debug("AUDMUX: normal operation mode\n");
+       /* Reset HPCR1 and PPCR1 */
+
+       DAM_HPCR1 = 0x00000000;
+       DAM_PPCR1 = 0x00000000;
+
+       /* set to synchronous */
+       DAM_HPCR1 |= AUDMUX_HPCR_SYN;
+       DAM_PPCR1 |= AUDMUX_PPCR_SYN;
+
+
+       /* set Rx sources 1 <--> 4 */
+       DAM_HPCR1 |= AUDMUX_HPCR_RXDSEL(3); /* port 4 */
+       DAM_PPCR1 |= AUDMUX_PPCR_RXDSEL(0); /* port 1 */
+
+       /* set Tx frame and Clock direction and source  4 --> 1 output */
+       DAM_HPCR1 |= AUDMUX_HPCR_TFSDIR | AUDMUX_HPCR_TCLKDIR;
+       DAM_HPCR1 |= AUDMUX_HPCR_TFCSEL(3); /* TxDS and TxCclk from port 4 */
+
+       return;
+}
+
+static int mx27vis_hifi_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       unsigned int pll_out = 0, bclk = 0, fmt = 0, mclk = 0;
+       int ret = 0;
+
+       /*
+        * The WM8974 is better at generating accurate audio clocks than the
+        * MX27 SSI controller, so we will use it as master when we can.
+        */
+       switch (params_rate(params)) {
+       case 8000:
+               fmt = SND_SOC_DAIFMT_CBM_CFM;
+               mclk = WM8974_MCLKDIV_12;
+               pll_out = 24576000;
+               break;
+       case 16000:
+               fmt = SND_SOC_DAIFMT_CBM_CFM;
+               pll_out = 12288000;
+               break;
+       case 48000:
+               fmt = SND_SOC_DAIFMT_CBM_CFM;
+               bclk = WM8974_BCLKDIV_4;
+               pll_out = 12288000;
+               break;
+       case 96000:
+               fmt = SND_SOC_DAIFMT_CBM_CFM;
+               bclk = WM8974_BCLKDIV_2;
+               pll_out = 12288000;
+               break;
+       case 11025:
+               fmt = SND_SOC_DAIFMT_CBM_CFM;
+               bclk = WM8974_BCLKDIV_16;
+               pll_out = 11289600;
+               break;
+       case 22050:
+               fmt = SND_SOC_DAIFMT_CBM_CFM;
+               bclk = WM8974_BCLKDIV_8;
+               pll_out = 11289600;
+               break;
+       case 44100:
+               fmt = SND_SOC_DAIFMT_CBM_CFM;
+               bclk = WM8974_BCLKDIV_4;
+               mclk = WM8974_MCLKDIV_2;
+               pll_out = 11289600;
+               break;
+       case 88200:
+               fmt = SND_SOC_DAIFMT_CBM_CFM;
+               bclk = WM8974_BCLKDIV_2;
+               pll_out = 11289600;
+               break;
+       }
+
+       /* set codec DAI configuration */
+       ret = codec_dai->ops->set_fmt(codec_dai,
+               SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
+               SND_SOC_DAIFMT_SYNC | fmt);
+       if (ret < 0) {
+               printk(KERN_ERR "Error from codec DAI configuration\n");
+               return ret;
+       }
+
+       /* set cpu DAI configuration */
+       ret = cpu_dai->ops->set_fmt(cpu_dai,
+               SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+               SND_SOC_DAIFMT_SYNC | fmt);
+       if (ret < 0) {
+               printk(KERN_ERR "Error from cpu DAI configuration\n");
+               return ret;
+       }
+
+       /* Put DC field of STCCR to 1 (not zero) */
+       ret = cpu_dai->ops->set_tdm_slot(cpu_dai, 0, 2);
+
+       /* set the SSI system clock as input */
+       ret = cpu_dai->ops->set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0,
+               SND_SOC_CLOCK_IN);
+       if (ret < 0) {
+               printk(KERN_ERR "Error when setting system SSI clk\n");
+               return ret;
+       }
+
+       /* set codec BCLK division for sample rate */
+       ret = codec_dai->ops->set_clkdiv(codec_dai, WM8974_BCLKDIV, bclk);
+       if (ret < 0) {
+               printk(KERN_ERR "Error when setting BCLK division\n");
+               return ret;
+       }
+
+
+       /* codec PLL input is 25 MHz */
+       ret = codec_dai->ops->set_pll(codec_dai, IGNORED_ARG,
+                                       25000000, pll_out);
+       if (ret < 0) {
+               printk(KERN_ERR "Error when setting PLL input\n");
+               return ret;
+       }
+
+       /*set codec MCLK division for sample rate */
+       ret = codec_dai->ops->set_clkdiv(codec_dai, WM8974_MCLKDIV, mclk);
+       if (ret < 0) {
+               printk(KERN_ERR "Error when setting MCLK division\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int mx27vis_hifi_hw_free(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+
+       /* disable the PLL */
+       return codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, 0, 0);
+}
+
+/*
+ * mx27vis WM8974 HiFi DAI opserations.
+ */
+static struct snd_soc_ops mx27vis_hifi_ops = {
+       .hw_params = mx27vis_hifi_hw_params,
+       .hw_free = mx27vis_hifi_hw_free,
+};
+
+
+static int mx27vis_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       return 0;
+}
+
+static int mx27vis_resume(struct platform_device *pdev)
+{
+       return 0;
+}
+
+static int mx27vis_probe(struct platform_device *pdev)
+{
+       int ret = 0;
+
+       ret = get_ssi_clk(0, &pdev->dev);
+
+       if (ret < 0) {
+               printk(KERN_ERR "%s: cant get ssi clock\n", __func__);
+               return ret;
+       }
+
+
+       return 0;
+}
+
+static int mx27vis_remove(struct platform_device *pdev)
+{
+       put_ssi_clk(0);
+       return 0;
+}
+
+static struct snd_soc_dai_link mx27vis_dai[] = {
+{ /* Hifi Playback*/
+       .name = "WM8974",
+       .stream_name = "WM8974 HiFi",
+       .cpu_dai = &imx_ssi_pcm_dai[0],
+       .codec_dai = &wm8974_dai,
+       .ops = &mx27vis_hifi_ops,
+},
+};
+
+static struct snd_soc_card mx27vis = {
+       .name = "mx27vis",
+       .platform = &mx1_mx2_soc_platform,
+       .probe = mx27vis_probe,
+       .remove = mx27vis_remove,
+       .suspend_pre = mx27vis_suspend,
+       .resume_post = mx27vis_resume,
+       .dai_link = mx27vis_dai,
+       .num_links = ARRAY_SIZE(mx27vis_dai),
+};
+
+static struct snd_soc_device mx27vis_snd_devdata = {
+       .card = &mx27vis,
+       .codec_dev = &soc_codec_dev_wm8974,
+};
+
+static struct platform_device *mx27vis_snd_device;
+
+/* Temporal definition of board specific behaviour */
+void gpio_ssi_active(int ssi_num)
+{
+       int ret = 0;
+
+       unsigned int ssi1_pins[] = {
+               PC20_PF_SSI1_FS,
+               PC21_PF_SSI1_RXD,
+               PC22_PF_SSI1_TXD,
+               PC23_PF_SSI1_CLK,
+       };
+       unsigned int ssi2_pins[] = {
+               PC24_PF_SSI2_FS,
+               PC25_PF_SSI2_RXD,
+               PC26_PF_SSI2_TXD,
+               PC27_PF_SSI2_CLK,
+       };
+       if (ssi_num == 0)
+               ret = mxc_gpio_setup_multiple_pins(ssi1_pins,
+                               ARRAY_SIZE(ssi1_pins), "USB OTG");
+       else
+               ret = mxc_gpio_setup_multiple_pins(ssi2_pins,
+                               ARRAY_SIZE(ssi2_pins), "USB OTG");
+       if (ret)
+               printk(KERN_ERR "Error requesting ssi %x pins\n", ssi_num);
+}
+
+
+static int __init mx27vis_init(void)
+{
+       int ret;
+
+       mx27vis_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!mx27vis_snd_device)
+               return -ENOMEM;
+
+       platform_set_drvdata(mx27vis_snd_device, &mx27vis_snd_devdata);
+       mx27vis_snd_devdata.dev = &mx27vis_snd_device->dev;
+       ret = platform_device_add(mx27vis_snd_device);
+
+       if (ret) {
+               printk(KERN_ERR "ASoC: Platform device allocation failed\n");
+               platform_device_put(mx27vis_snd_device);
+       }
+
+       /* WM8974 uses SSI1 (HPCR1) via AUDMUX port 4 for audio (PPCR1) */
+       gpio_ssi_active(0);
+       audmux_connect_1_4();
+
+       return ret;
+}
+
+static void __exit mx27vis_exit(void)
+{
+       /* We should call some "ssi_gpio_inactive()" properly */
+}
+
+module_init(mx27vis_init);
+module_exit(mx27vis_exit);
+
+
+MODULE_AUTHOR("Javier Martin, javier.martin@vista-silicon.com");
+MODULE_DESCRIPTION("ALSA SoC WM8974 mx27vis");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/imx/mxc-ssi.c b/sound/soc/imx/mxc-ssi.c
new file mode 100644 (file)
index 0000000..3806ff2
--- /dev/null
@@ -0,0 +1,868 @@
+/*
+ * mxc-ssi.c  --  SSI driver for Freescale IMX
+ *
+ * Copyright 2006 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ *  Based on mxc-alsa-mc13783 (C) 2006 Freescale.
+ *
+ *  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:
+ *   Need to rework SSI register defs when new defs go into mainline.
+ *   Add support for TDM and FIFO 1.
+ *   Add support for i.mx3x DMA interface.
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <mach/dma-mx1-mx2.h>
+#include <asm/mach-types.h>
+
+#include "mxc-ssi.h"
+#include "mx1_mx2-pcm.h"
+
+#define SSI1_PORT      0
+#define SSI2_PORT      1
+
+static int ssi_active[2] = {0, 0};
+
+/* DMA information for mx1_mx2 platforms */
+static struct mx1_mx2_pcm_dma_params imx_ssi1_pcm_stereo_out0 = {
+       .name                   = "SSI1 PCM Stereo out 0",
+       .transfer_type = DMA_MODE_WRITE,
+       .per_address = SSI1_BASE_ADDR + STX0,
+       .event_id = DMA_REQ_SSI1_TX0,
+       .watermark_level = TXFIFO_WATERMARK,
+       .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
+       .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
+};
+
+static struct mx1_mx2_pcm_dma_params imx_ssi1_pcm_stereo_out1 = {
+       .name                   = "SSI1 PCM Stereo out 1",
+       .transfer_type = DMA_MODE_WRITE,
+       .per_address = SSI1_BASE_ADDR + STX1,
+       .event_id = DMA_REQ_SSI1_TX1,
+       .watermark_level = TXFIFO_WATERMARK,
+       .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
+       .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
+};
+
+static struct mx1_mx2_pcm_dma_params imx_ssi1_pcm_stereo_in0 = {
+       .name                   = "SSI1 PCM Stereo in 0",
+       .transfer_type = DMA_MODE_READ,
+       .per_address = SSI1_BASE_ADDR + SRX0,
+       .event_id = DMA_REQ_SSI1_RX0,
+       .watermark_level = RXFIFO_WATERMARK,
+       .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
+       .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
+};
+
+static struct mx1_mx2_pcm_dma_params imx_ssi1_pcm_stereo_in1 = {
+       .name                   = "SSI1 PCM Stereo in 1",
+       .transfer_type = DMA_MODE_READ,
+       .per_address = SSI1_BASE_ADDR + SRX1,
+       .event_id = DMA_REQ_SSI1_RX1,
+       .watermark_level = RXFIFO_WATERMARK,
+       .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
+       .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
+};
+
+static struct mx1_mx2_pcm_dma_params imx_ssi2_pcm_stereo_out0 = {
+       .name                   = "SSI2 PCM Stereo out 0",
+       .transfer_type = DMA_MODE_WRITE,
+       .per_address = SSI2_BASE_ADDR + STX0,
+       .event_id = DMA_REQ_SSI2_TX0,
+       .watermark_level = TXFIFO_WATERMARK,
+       .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
+       .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
+};
+
+static struct mx1_mx2_pcm_dma_params imx_ssi2_pcm_stereo_out1 = {
+       .name                   = "SSI2 PCM Stereo out 1",
+       .transfer_type = DMA_MODE_WRITE,
+       .per_address = SSI2_BASE_ADDR + STX1,
+       .event_id = DMA_REQ_SSI2_TX1,
+       .watermark_level = TXFIFO_WATERMARK,
+       .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
+       .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
+};
+
+static struct mx1_mx2_pcm_dma_params imx_ssi2_pcm_stereo_in0 = {
+       .name                   = "SSI2 PCM Stereo in 0",
+       .transfer_type = DMA_MODE_READ,
+       .per_address = SSI2_BASE_ADDR + SRX0,
+       .event_id = DMA_REQ_SSI2_RX0,
+       .watermark_level = RXFIFO_WATERMARK,
+       .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
+       .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
+};
+
+static struct mx1_mx2_pcm_dma_params imx_ssi2_pcm_stereo_in1 = {
+       .name                   = "SSI2 PCM Stereo in 1",
+       .transfer_type = DMA_MODE_READ,
+       .per_address = SSI2_BASE_ADDR + SRX1,
+       .event_id = DMA_REQ_SSI2_RX1,
+       .watermark_level = RXFIFO_WATERMARK,
+       .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO,
+       .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
+};
+
+static struct clk *ssi_clk0, *ssi_clk1;
+
+int get_ssi_clk(int ssi, struct device *dev)
+{
+       switch (ssi) {
+       case 0:
+               ssi_clk0 = clk_get(dev, "ssi1");
+               if (IS_ERR(ssi_clk0))
+                       return PTR_ERR(ssi_clk0);
+               return 0;
+       case 1:
+               ssi_clk1 = clk_get(dev, "ssi2");
+               if (IS_ERR(ssi_clk1))
+                       return PTR_ERR(ssi_clk1);
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+EXPORT_SYMBOL(get_ssi_clk);
+
+void put_ssi_clk(int ssi)
+{
+       switch (ssi) {
+       case 0:
+               clk_put(ssi_clk0);
+               ssi_clk0 = NULL;
+               break;
+       case 1:
+               clk_put(ssi_clk1);
+               ssi_clk1 = NULL;
+               break;
+       }
+}
+EXPORT_SYMBOL(put_ssi_clk);
+
+/*
+ * SSI system clock configuration.
+ * Should only be called when port is inactive (i.e. SSIEN = 0).
+ */
+static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
+       int clk_id, unsigned int freq, int dir)
+{
+       u32 scr;
+
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
+               scr = SSI1_SCR;
+               pr_debug("%s: SCR for SSI1 is %x\n", __func__, scr);
+       } else {
+               scr = SSI2_SCR;
+               pr_debug("%s: SCR for SSI2 is %x\n", __func__, scr);
+       }
+
+       if (scr & SSI_SCR_SSIEN) {
+               printk(KERN_WARNING "Warning ssi already enabled\n");
+               return 0;
+       }
+
+       switch (clk_id) {
+       case IMX_SSP_SYS_CLK:
+               if (dir == SND_SOC_CLOCK_OUT) {
+                       scr |= SSI_SCR_SYS_CLK_EN;
+                       pr_debug("%s: clk of is output\n", __func__);
+               } else {
+                       scr &= ~SSI_SCR_SYS_CLK_EN;
+                       pr_debug("%s: clk of is input\n", __func__);
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
+               pr_debug("%s: writeback of SSI1_SCR\n", __func__);
+               SSI1_SCR = scr;
+       } else {
+               pr_debug("%s: writeback of SSI2_SCR\n", __func__);
+               SSI2_SCR = scr;
+       }
+
+       return 0;
+}
+
+/*
+ * SSI Clock dividers
+ * Should only be called when port is inactive (i.e. SSIEN = 0).
+ */
+static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
+       int div_id, int div)
+{
+       u32 stccr, srccr;
+
+       pr_debug("%s\n", __func__);
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
+               if (SSI1_SCR & SSI_SCR_SSIEN)
+                       return 0;
+               srccr = SSI1_STCCR;
+               stccr = SSI1_STCCR;
+       } else {
+               if (SSI2_SCR & SSI_SCR_SSIEN)
+                       return 0;
+               srccr = SSI2_STCCR;
+               stccr = SSI2_STCCR;
+       }
+
+       switch (div_id) {
+       case IMX_SSI_TX_DIV_2:
+               stccr &= ~SSI_STCCR_DIV2;
+               stccr |= div;
+               break;
+       case IMX_SSI_TX_DIV_PSR:
+               stccr &= ~SSI_STCCR_PSR;
+               stccr |= div;
+               break;
+       case IMX_SSI_TX_DIV_PM:
+               stccr &= ~0xff;
+               stccr |= SSI_STCCR_PM(div);
+               break;
+       case IMX_SSI_RX_DIV_2:
+               stccr &= ~SSI_STCCR_DIV2;
+               stccr |= div;
+               break;
+       case IMX_SSI_RX_DIV_PSR:
+               stccr &= ~SSI_STCCR_PSR;
+               stccr |= div;
+               break;
+       case IMX_SSI_RX_DIV_PM:
+               stccr &= ~0xff;
+               stccr |= SSI_STCCR_PM(div);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
+               SSI1_STCCR = stccr;
+               SSI1_SRCCR = srccr;
+       } else {
+               SSI2_STCCR = stccr;
+               SSI2_SRCCR = srccr;
+       }
+       return 0;
+}
+
+/*
+ * SSI Network Mode or TDM slots configuration.
+ * Should only be called when port is inactive (i.e. SSIEN = 0).
+ */
+static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
+       unsigned int mask, int slots)
+{
+       u32 stmsk, srmsk, stccr;
+
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
+               if (SSI1_SCR & SSI_SCR_SSIEN) {
+                       printk(KERN_WARNING "Warning ssi already enabled\n");
+                       return 0;
+               }
+               stccr = SSI1_STCCR;
+       } else {
+               if (SSI2_SCR & SSI_SCR_SSIEN) {
+                       printk(KERN_WARNING "Warning ssi already enabled\n");
+                       return 0;
+               }
+               stccr = SSI2_STCCR;
+       }
+
+       stmsk = srmsk = mask;
+       stccr &= ~SSI_STCCR_DC_MASK;
+       stccr |= SSI_STCCR_DC(slots - 1);
+
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
+               SSI1_STMSK = stmsk;
+               SSI1_SRMSK = srmsk;
+               SSI1_SRCCR = SSI1_STCCR = stccr;
+       } else {
+               SSI2_STMSK = stmsk;
+               SSI2_SRMSK = srmsk;
+               SSI2_SRCCR = SSI2_STCCR = stccr;
+       }
+
+       return 0;
+}
+
+/*
+ * SSI DAI format configuration.
+ * Should only be called when port is inactive (i.e. SSIEN = 0).
+ * Note: We don't use the I2S modes but instead manually configure the
+ * SSI for I2S.
+ */
+static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+               unsigned int fmt)
+{
+       u32 stcr = 0, srcr = 0, scr;
+
+       /*
+        * This is done to avoid this function to modify
+        * previous set values in stcr
+        */
+       stcr = SSI1_STCR;
+
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2)
+               scr = SSI1_SCR & ~(SSI_SCR_SYN | SSI_SCR_NET);
+       else
+               scr = SSI2_SCR & ~(SSI_SCR_SYN | SSI_SCR_NET);
+
+       if (scr & SSI_SCR_SSIEN) {
+               printk(KERN_WARNING "Warning ssi already enabled\n");
+               return 0;
+       }
+
+       /* DAI mode */
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               /* data on rising edge of bclk, frame low 1clk before data */
+               stcr |= SSI_STCR_TFSI | SSI_STCR_TEFS | SSI_STCR_TXBIT0;
+               srcr |= SSI_SRCR_RFSI | SSI_SRCR_REFS | SSI_SRCR_RXBIT0;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               /* data on rising edge of bclk, frame high with data */
+               stcr |= SSI_STCR_TXBIT0;
+               srcr |= SSI_SRCR_RXBIT0;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               /* data on rising edge of bclk, frame high with data */
+               stcr |= SSI_STCR_TFSL;
+               srcr |= SSI_SRCR_RFSL;
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               /* data on rising edge of bclk, frame high 1clk before data */
+               stcr |= SSI_STCR_TFSL | SSI_STCR_TEFS;
+               srcr |= SSI_SRCR_RFSL | SSI_SRCR_REFS;
+               break;
+       }
+
+       /* DAI clock inversion */
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_IB_IF:
+               stcr |= SSI_STCR_TFSI;
+               stcr &= ~SSI_STCR_TSCKP;
+               srcr |= SSI_SRCR_RFSI;
+               srcr &= ~SSI_SRCR_RSCKP;
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               stcr &= ~(SSI_STCR_TSCKP | SSI_STCR_TFSI);
+               srcr &= ~(SSI_SRCR_RSCKP | SSI_SRCR_RFSI);
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               stcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP;
+               srcr |= SSI_SRCR_RFSI | SSI_SRCR_RSCKP;
+               break;
+       case SND_SOC_DAIFMT_NB_NF:
+               stcr &= ~SSI_STCR_TFSI;
+               stcr |= SSI_STCR_TSCKP;
+               srcr &= ~SSI_SRCR_RFSI;
+               srcr |= SSI_SRCR_RSCKP;
+               break;
+       }
+
+       /* DAI clock master masks */
+       switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+       case SND_SOC_DAIFMT_CBS_CFS:
+               stcr |= SSI_STCR_TFDIR | SSI_STCR_TXDIR;
+               srcr |= SSI_SRCR_RFDIR | SSI_SRCR_RXDIR;
+               break;
+       case SND_SOC_DAIFMT_CBM_CFS:
+               stcr |= SSI_STCR_TFDIR;
+               srcr |= SSI_SRCR_RFDIR;
+               break;
+       case SND_SOC_DAIFMT_CBS_CFM:
+               stcr |= SSI_STCR_TXDIR;
+               srcr |= SSI_SRCR_RXDIR;
+               break;
+       }
+
+       /* sync */
+       if (!(fmt & SND_SOC_DAIFMT_ASYNC))
+               scr |= SSI_SCR_SYN;
+
+       /* tdm - only for stereo atm */
+       if (fmt & SND_SOC_DAIFMT_TDM)
+               scr |= SSI_SCR_NET;
+
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
+               SSI1_STCR = stcr;
+               SSI1_SRCR = srcr;
+               SSI1_SCR = scr;
+       } else {
+               SSI2_STCR = stcr;
+               SSI2_SRCR = srcr;
+               SSI2_SCR = scr;
+       }
+
+       return 0;
+}
+
+static int imx_ssi_startup(struct snd_pcm_substream *substream,
+                       struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               /* set up TX DMA params */
+               switch (cpu_dai->id) {
+               case IMX_DAI_SSI0:
+                       cpu_dai->dma_data = &imx_ssi1_pcm_stereo_out0;
+                       break;
+               case IMX_DAI_SSI1:
+                       cpu_dai->dma_data = &imx_ssi1_pcm_stereo_out1;
+                       break;
+               case IMX_DAI_SSI2:
+                       cpu_dai->dma_data = &imx_ssi2_pcm_stereo_out0;
+                       break;
+               case IMX_DAI_SSI3:
+                       cpu_dai->dma_data = &imx_ssi2_pcm_stereo_out1;
+               }
+               pr_debug("%s: (playback)\n", __func__);
+       } else {
+               /* set up RX DMA params */
+               switch (cpu_dai->id) {
+               case IMX_DAI_SSI0:
+                       cpu_dai->dma_data = &imx_ssi1_pcm_stereo_in0;
+                       break;
+               case IMX_DAI_SSI1:
+                       cpu_dai->dma_data = &imx_ssi1_pcm_stereo_in1;
+                       break;
+               case IMX_DAI_SSI2:
+                       cpu_dai->dma_data = &imx_ssi2_pcm_stereo_in0;
+                       break;
+               case IMX_DAI_SSI3:
+                       cpu_dai->dma_data = &imx_ssi2_pcm_stereo_in1;
+               }
+               pr_debug("%s: (capture)\n", __func__);
+       }
+
+       /*
+        * we cant really change any SSI values after SSI is enabled
+        * need to fix in software for max flexibility - lrg
+        */
+       if (cpu_dai->active) {
+               printk(KERN_WARNING "Warning ssi already enabled\n");
+               return 0;
+       }
+
+       /* reset the SSI port - Sect 45.4.4 */
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
+
+               if (!ssi_clk0)
+                       return -EINVAL;
+
+               if (ssi_active[SSI1_PORT]++) {
+                       pr_debug("%s: exit before reset\n", __func__);
+                       return 0;
+               }
+
+               /* SSI1 Reset */
+               SSI1_SCR = 0;
+
+               SSI1_SFCSR = SSI_SFCSR_RFWM1(RXFIFO_WATERMARK) |
+                       SSI_SFCSR_RFWM0(RXFIFO_WATERMARK) |
+                       SSI_SFCSR_TFWM1(TXFIFO_WATERMARK) |
+                       SSI_SFCSR_TFWM0(TXFIFO_WATERMARK);
+       } else {
+
+               if (!ssi_clk1)
+                       return -EINVAL;
+
+               if (ssi_active[SSI2_PORT]++) {
+                       pr_debug("%s: exit before reset\n", __func__);
+                       return 0;
+               }
+
+               /* SSI2 Reset */
+               SSI2_SCR = 0;
+
+               SSI2_SFCSR = SSI_SFCSR_RFWM1(RXFIFO_WATERMARK) |
+                       SSI_SFCSR_RFWM0(RXFIFO_WATERMARK) |
+                       SSI_SFCSR_TFWM1(TXFIFO_WATERMARK) |
+                       SSI_SFCSR_TFWM0(TXFIFO_WATERMARK);
+       }
+
+       return 0;
+}
+
+int imx_ssi_hw_tx_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       u32 stccr, stcr, sier;
+
+       pr_debug("%s\n", __func__);
+
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
+               stccr = SSI1_STCCR & ~SSI_STCCR_WL_MASK;
+               stcr = SSI1_STCR;
+               sier = SSI1_SIER;
+       } else {
+               stccr = SSI2_STCCR & ~SSI_STCCR_WL_MASK;
+               stcr = SSI2_STCR;
+               sier = SSI2_SIER;
+       }
+
+       /* DAI data (word) size */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               stccr |= SSI_STCCR_WL(16);
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               stccr |= SSI_STCCR_WL(20);
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               stccr |= SSI_STCCR_WL(24);
+               break;
+       }
+
+       /* enable interrupts */
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2)
+               stcr |= SSI_STCR_TFEN0;
+       else
+               stcr |= SSI_STCR_TFEN1;
+       sier |= SSI_SIER_TDMAE;
+
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
+               SSI1_STCR = stcr;
+               SSI1_STCCR = stccr;
+               SSI1_SIER = sier;
+       } else {
+               SSI2_STCR = stcr;
+               SSI2_STCCR = stccr;
+               SSI2_SIER = sier;
+       }
+
+       return 0;
+}
+
+int imx_ssi_hw_rx_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       u32 srccr, srcr, sier;
+
+       pr_debug("%s\n", __func__);
+
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
+               srccr = SSI1_SRCCR & ~SSI_SRCCR_WL_MASK;
+               srcr = SSI1_SRCR;
+               sier = SSI1_SIER;
+       } else {
+               srccr = SSI2_SRCCR & ~SSI_SRCCR_WL_MASK;
+               srcr = SSI2_SRCR;
+               sier = SSI2_SIER;
+       }
+
+       /* DAI data (word) size */
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S16_LE:
+               srccr |= SSI_SRCCR_WL(16);
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               srccr |= SSI_SRCCR_WL(20);
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               srccr |= SSI_SRCCR_WL(24);
+               break;
+       }
+
+       /* enable interrupts */
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2)
+               srcr |= SSI_SRCR_RFEN0;
+       else
+               srcr |= SSI_SRCR_RFEN1;
+       sier |= SSI_SIER_RDMAE;
+
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
+               SSI1_SRCR = srcr;
+               SSI1_SRCCR = srccr;
+               SSI1_SIER = sier;
+       } else {
+               SSI2_SRCR = srcr;
+               SSI2_SRCCR = srccr;
+               SSI2_SIER = sier;
+       }
+
+       return 0;
+}
+
+/*
+ * Should only be called when port is inactive (i.e. SSIEN = 0),
+ * although can be called multiple times by upper layers.
+ */
+int imx_ssi_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params,
+                               struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+       int ret;
+
+       /* cant change any parameters when SSI is running */
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
+               if (SSI1_SCR & SSI_SCR_SSIEN) {
+                       printk(KERN_WARNING "Warning ssi already enabled\n");
+                       return 0;
+               }
+       } else {
+               if (SSI2_SCR & SSI_SCR_SSIEN) {
+                       printk(KERN_WARNING "Warning ssi already enabled\n");
+                       return 0;
+               }
+       }
+
+       /*
+        * Configure both tx and rx params with the same settings. This is
+        * really a harware restriction because SSI must be disabled until
+        * we can change those values. If there is an active audio stream in
+        * one direction, enabling the other direction with different
+        * settings would mean disturbing the running one.
+        */
+       ret = imx_ssi_hw_tx_params(substream, params);
+       if (ret < 0)
+               return ret;
+       return imx_ssi_hw_rx_params(substream, params);
+}
+
+int imx_ssi_prepare(struct snd_pcm_substream *substream,
+                       struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       int ret;
+
+       pr_debug("%s\n", __func__);
+
+       /* Enable clks here to follow SSI recommended init sequence */
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) {
+               ret = clk_enable(ssi_clk0);
+               if (ret < 0)
+                       printk(KERN_ERR "Unable to enable ssi_clk0\n");
+       } else {
+               ret = clk_enable(ssi_clk1);
+               if (ret < 0)
+                       printk(KERN_ERR "Unable to enable ssi_clk1\n");
+       }
+
+       return 0;
+}
+
+static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
+                       struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       u32 scr;
+
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2)
+               scr = SSI1_SCR;
+       else
+               scr = SSI2_SCR;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+                       scr |= SSI_SCR_TE | SSI_SCR_SSIEN;
+               else
+                       scr |= SSI_SCR_RE | SSI_SCR_SSIEN;
+               break;
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_STOP:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+                       scr &= ~SSI_SCR_TE;
+               else
+                       scr &= ~SSI_SCR_RE;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2)
+               SSI1_SCR = scr;
+       else
+               SSI2_SCR = scr;
+
+       return 0;
+}
+
+static void imx_ssi_shutdown(struct snd_pcm_substream *substream,
+                       struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+
+       /* shutdown SSI if neither Tx or Rx is active */
+       if (!cpu_dai->active) {
+
+               if (cpu_dai->id == IMX_DAI_SSI0 ||
+                       cpu_dai->id == IMX_DAI_SSI2) {
+
+                       if (--ssi_active[SSI1_PORT] > 1)
+                               return;
+
+                       SSI1_SCR = 0;
+                       clk_disable(ssi_clk0);
+               } else {
+                       if (--ssi_active[SSI2_PORT])
+                               return;
+                       SSI2_SCR = 0;
+                       clk_disable(ssi_clk1);
+               }
+       }
+}
+
+#ifdef CONFIG_PM
+static int imx_ssi_suspend(struct platform_device *dev,
+       struct snd_soc_dai *dai)
+{
+       return 0;
+}
+
+static int imx_ssi_resume(struct platform_device *pdev,
+       struct snd_soc_dai *dai)
+{
+       return 0;
+}
+
+#else
+#define imx_ssi_suspend        NULL
+#define imx_ssi_resume NULL
+#endif
+
+#define IMX_SSI_RATES \
+       (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \
+       SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
+       SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+       SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \
+       SNDRV_PCM_RATE_96000)
+
+#define IMX_SSI_BITS \
+       (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+       SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
+       .startup = imx_ssi_startup,
+       .shutdown = imx_ssi_shutdown,
+       .trigger = imx_ssi_trigger,
+       .prepare = imx_ssi_prepare,
+       .hw_params = imx_ssi_hw_params,
+       .set_sysclk = imx_ssi_set_dai_sysclk,
+       .set_clkdiv = imx_ssi_set_dai_clkdiv,
+       .set_fmt = imx_ssi_set_dai_fmt,
+       .set_tdm_slot = imx_ssi_set_dai_tdm_slot,
+};
+
+struct snd_soc_dai imx_ssi_pcm_dai[] = {
+{
+       .name = "imx-i2s-1-0",
+       .id = IMX_DAI_SSI0,
+       .suspend = imx_ssi_suspend,
+       .resume = imx_ssi_resume,
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .formats = IMX_SSI_BITS,
+               .rates = IMX_SSI_RATES,},
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .formats = IMX_SSI_BITS,
+               .rates = IMX_SSI_RATES,},
+       .ops = &imx_ssi_pcm_dai_ops,
+},
+{
+       .name = "imx-i2s-2-0",
+       .id = IMX_DAI_SSI1,
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .formats = IMX_SSI_BITS,
+               .rates = IMX_SSI_RATES,},
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .formats = IMX_SSI_BITS,
+               .rates = IMX_SSI_RATES,},
+       .ops = &imx_ssi_pcm_dai_ops,
+},
+{
+       .name = "imx-i2s-1-1",
+       .id = IMX_DAI_SSI2,
+       .suspend = imx_ssi_suspend,
+       .resume = imx_ssi_resume,
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .formats = IMX_SSI_BITS,
+               .rates = IMX_SSI_RATES,},
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .formats = IMX_SSI_BITS,
+               .rates = IMX_SSI_RATES,},
+       .ops = &imx_ssi_pcm_dai_ops,
+},
+{
+       .name = "imx-i2s-2-1",
+       .id = IMX_DAI_SSI3,
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .formats = IMX_SSI_BITS,
+               .rates = IMX_SSI_RATES,},
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 2,
+               .formats = IMX_SSI_BITS,
+               .rates = IMX_SSI_RATES,},
+       .ops = &imx_ssi_pcm_dai_ops,
+},
+};
+EXPORT_SYMBOL_GPL(imx_ssi_pcm_dai);
+
+static int __init imx_ssi_init(void)
+{
+       return snd_soc_register_dais(imx_ssi_pcm_dai,
+                               ARRAY_SIZE(imx_ssi_pcm_dai));
+}
+
+static void __exit imx_ssi_exit(void)
+{
+       snd_soc_unregister_dais(imx_ssi_pcm_dai,
+                               ARRAY_SIZE(imx_ssi_pcm_dai));
+}
+
+module_init(imx_ssi_init);
+module_exit(imx_ssi_exit);
+MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com");
+MODULE_DESCRIPTION("i.MX ASoC I2S driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/imx/mxc-ssi.h b/sound/soc/imx/mxc-ssi.h
new file mode 100644 (file)
index 0000000..12bbdc9
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * 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 _IMX_SSI_H
+#define _IMX_SSI_H
+
+#include <mach/hardware.h>
+
+/* SSI regs definition - MOVE to /arch/arm/plat-mxc/include/mach/ when stable */
+#define SSI1_IO_BASE_ADDR      IO_ADDRESS(SSI1_BASE_ADDR)
+#define SSI2_IO_BASE_ADDR      IO_ADDRESS(SSI2_BASE_ADDR)
+
+#define STX0   0x00
+#define STX1   0x04
+#define SRX0   0x08
+#define SRX1   0x0c
+#define SCR    0x10
+#define SISR   0x14
+#define SIER   0x18
+#define STCR   0x1c
+#define SRCR   0x20
+#define STCCR  0x24
+#define SRCCR  0x28
+#define SFCSR  0x2c
+#define STR    0x30
+#define SOR    0x34
+#define SACNT  0x38
+#define SACADD 0x3c
+#define SACDAT 0x40
+#define SATAG  0x44
+#define STMSK  0x48
+#define SRMSK  0x4c
+
+#define SSI1_STX0      (*((volatile u32 *)(SSI1_IO_BASE_ADDR + STX0)))
+#define SSI1_STX1   (*((volatile u32 *)(SSI1_IO_BASE_ADDR + STX1)))
+#define SSI1_SRX0   (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SRX0)))
+#define SSI1_SRX1   (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SRX1)))
+#define SSI1_SCR    (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SCR)))
+#define SSI1_SISR   (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SISR)))
+#define SSI1_SIER   (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SIER)))
+#define SSI1_STCR   (*((volatile u32 *)(SSI1_IO_BASE_ADDR + STCR)))
+#define SSI1_SRCR   (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SRCR)))
+#define SSI1_STCCR  (*((volatile u32 *)(SSI1_IO_BASE_ADDR + STCCR)))
+#define SSI1_SRCCR  (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SRCCR)))
+#define SSI1_SFCSR  (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SFCSR)))
+#define SSI1_STR    (*((volatile u32 *)(SSI1_IO_BASE_ADDR + STR)))
+#define SSI1_SOR    (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SOR)))
+#define SSI1_SACNT  (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SACNT)))
+#define SSI1_SACADD (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SACADD)))
+#define SSI1_SACDAT (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SACDAT)))
+#define SSI1_SATAG  (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SATAG)))
+#define SSI1_STMSK  (*((volatile u32 *)(SSI1_IO_BASE_ADDR + STMSK)))
+#define SSI1_SRMSK  (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SRMSK)))
+
+
+#define SSI2_STX0      (*((volatile u32 *)(SSI2_IO_BASE_ADDR + STX0)))
+#define SSI2_STX1   (*((volatile u32 *)(SSI2_IO_BASE_ADDR + STX1)))
+#define SSI2_SRX0   (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SRX0)))
+#define SSI2_SRX1   (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SRX1)))
+#define SSI2_SCR    (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SCR)))
+#define SSI2_SISR   (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SISR)))
+#define SSI2_SIER   (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SIER)))
+#define SSI2_STCR   (*((volatile u32 *)(SSI2_IO_BASE_ADDR + STCR)))
+#define SSI2_SRCR   (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SRCR)))
+#define SSI2_STCCR  (*((volatile u32 *)(SSI2_IO_BASE_ADDR + STCCR)))
+#define SSI2_SRCCR  (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SRCCR)))
+#define SSI2_SFCSR  (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SFCSR)))
+#define SSI2_STR    (*((volatile u32 *)(SSI2_IO_BASE_ADDR + STR)))
+#define SSI2_SOR    (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SOR)))
+#define SSI2_SACNT  (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SACNT)))
+#define SSI2_SACADD (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SACADD)))
+#define SSI2_SACDAT (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SACDAT)))
+#define SSI2_SATAG  (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SATAG)))
+#define SSI2_STMSK  (*((volatile u32 *)(SSI2_IO_BASE_ADDR + STMSK)))
+#define SSI2_SRMSK  (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SRMSK)))
+
+#define SSI_SCR_CLK_IST        (1 << 9)
+#define SSI_SCR_TCH_EN         (1 << 8)
+#define SSI_SCR_SYS_CLK_EN     (1 << 7)
+#define SSI_SCR_I2S_MODE_NORM  (0 << 5)
+#define SSI_SCR_I2S_MODE_MSTR  (1 << 5)
+#define SSI_SCR_I2S_MODE_SLAVE (2 << 5)
+#define SSI_SCR_SYN            (1 << 4)
+#define SSI_SCR_NET            (1 << 3)
+#define SSI_SCR_RE             (1 << 2)
+#define SSI_SCR_TE             (1 << 1)
+#define SSI_SCR_SSIEN          (1 << 0)
+
+#define SSI_SISR_CMDAU         (1 << 18)
+#define SSI_SISR_CMDDU         (1 << 17)
+#define SSI_SISR_RXT           (1 << 16)
+#define SSI_SISR_RDR1          (1 << 15)
+#define SSI_SISR_RDR0          (1 << 14)
+#define SSI_SISR_TDE1          (1 << 13)
+#define SSI_SISR_TDE0          (1 << 12)
+#define SSI_SISR_ROE1          (1 << 11)
+#define SSI_SISR_ROE0          (1 << 10)
+#define SSI_SISR_TUE1          (1 << 9)
+#define SSI_SISR_TUE0          (1 << 8)
+#define SSI_SISR_TFS           (1 << 7)
+#define SSI_SISR_RFS           (1 << 6)
+#define SSI_SISR_TLS           (1 << 5)
+#define SSI_SISR_RLS           (1 << 4)
+#define SSI_SISR_RFF1          (1 << 3)
+#define SSI_SISR_RFF0          (1 << 2)
+#define SSI_SISR_TFE1          (1 << 1)
+#define SSI_SISR_TFE0          (1 << 0)
+
+#define SSI_SIER_RDMAE         (1 << 22)
+#define SSI_SIER_RIE           (1 << 21)
+#define SSI_SIER_TDMAE         (1 << 20)
+#define SSI_SIER_TIE           (1 << 19)
+#define SSI_SIER_CMDAU_EN      (1 << 18)
+#define SSI_SIER_CMDDU_EN      (1 << 17)
+#define SSI_SIER_RXT_EN        (1 << 16)
+#define SSI_SIER_RDR1_EN       (1 << 15)
+#define SSI_SIER_RDR0_EN       (1 << 14)
+#define SSI_SIER_TDE1_EN       (1 << 13)
+#define SSI_SIER_TDE0_EN       (1 << 12)
+#define SSI_SIER_ROE1_EN       (1 << 11)
+#define SSI_SIER_ROE0_EN       (1 << 10)
+#define SSI_SIER_TUE1_EN       (1 << 9)
+#define SSI_SIER_TUE0_EN       (1 << 8)
+#define SSI_SIER_TFS_EN        (1 << 7)
+#define SSI_SIER_RFS_EN        (1 << 6)
+#define SSI_SIER_TLS_EN        (1 << 5)
+#define SSI_SIER_RLS_EN        (1 << 4)
+#define SSI_SIER_RFF1_EN       (1 << 3)
+#define SSI_SIER_RFF0_EN       (1 << 2)
+#define SSI_SIER_TFE1_EN       (1 << 1)
+#define SSI_SIER_TFE0_EN       (1 << 0)
+
+#define SSI_STCR_TXBIT0        (1 << 9)
+#define SSI_STCR_TFEN1         (1 << 8)
+#define SSI_STCR_TFEN0         (1 << 7)
+#define SSI_STCR_TFDIR         (1 << 6)
+#define SSI_STCR_TXDIR         (1 << 5)
+#define SSI_STCR_TSHFD         (1 << 4)
+#define SSI_STCR_TSCKP         (1 << 3)
+#define SSI_STCR_TFSI          (1 << 2)
+#define SSI_STCR_TFSL          (1 << 1)
+#define SSI_STCR_TEFS          (1 << 0)
+
+#define SSI_SRCR_RXBIT0        (1 << 9)
+#define SSI_SRCR_RFEN1         (1 << 8)
+#define SSI_SRCR_RFEN0         (1 << 7)
+#define SSI_SRCR_RFDIR         (1 << 6)
+#define SSI_SRCR_RXDIR         (1 << 5)
+#define SSI_SRCR_RSHFD         (1 << 4)
+#define SSI_SRCR_RSCKP         (1 << 3)
+#define SSI_SRCR_RFSI          (1 << 2)
+#define SSI_SRCR_RFSL          (1 << 1)
+#define SSI_SRCR_REFS          (1 << 0)
+
+#define SSI_STCCR_DIV2         (1 << 18)
+#define SSI_STCCR_PSR          (1 << 15)
+#define SSI_STCCR_WL(x)        ((((x) - 2) >> 1) << 13)
+#define SSI_STCCR_DC(x)        (((x) & 0x1f) << 8)
+#define SSI_STCCR_PM(x)        (((x) & 0xff) << 0)
+#define SSI_STCCR_WL_MASK        (0xf << 13)
+#define SSI_STCCR_DC_MASK        (0x1f << 8)
+#define SSI_STCCR_PM_MASK        (0xff << 0)
+
+#define SSI_SRCCR_DIV2         (1 << 18)
+#define SSI_SRCCR_PSR          (1 << 15)
+#define SSI_SRCCR_WL(x)        ((((x) - 2) >> 1) << 13)
+#define SSI_SRCCR_DC(x)        (((x) & 0x1f) << 8)
+#define SSI_SRCCR_PM(x)        (((x) & 0xff) << 0)
+#define SSI_SRCCR_WL_MASK        (0xf << 13)
+#define SSI_SRCCR_DC_MASK        (0x1f << 8)
+#define SSI_SRCCR_PM_MASK        (0xff << 0)
+
+
+#define SSI_SFCSR_RFCNT1(x)   (((x) & 0xf) << 28)
+#define SSI_SFCSR_TFCNT1(x)   (((x) & 0xf) << 24)
+#define SSI_SFCSR_RFWM1(x)    (((x) & 0xf) << 20)
+#define SSI_SFCSR_TFWM1(x)    (((x) & 0xf) << 16)
+#define SSI_SFCSR_RFCNT0(x)   (((x) & 0xf) << 12)
+#define SSI_SFCSR_TFCNT0(x)   (((x) & 0xf) <<  8)
+#define SSI_SFCSR_RFWM0(x)    (((x) & 0xf) <<  4)
+#define SSI_SFCSR_TFWM0(x)    (((x) & 0xf) <<  0)
+
+#define SSI_STR_TEST          (1 << 15)
+#define SSI_STR_RCK2TCK       (1 << 14)
+#define SSI_STR_RFS2TFS       (1 << 13)
+#define SSI_STR_RXSTATE(x)    (((x) & 0xf) << 8)
+#define SSI_STR_TXD2RXD       (1 <<  7)
+#define SSI_STR_TCK2RCK       (1 <<  6)
+#define SSI_STR_TFS2RFS       (1 <<  5)
+#define SSI_STR_TXSTATE(x)    (((x) & 0xf) << 0)
+
+#define SSI_SOR_CLKOFF        (1 << 6)
+#define SSI_SOR_RX_CLR        (1 << 5)
+#define SSI_SOR_TX_CLR        (1 << 4)
+#define SSI_SOR_INIT          (1 << 3)
+#define SSI_SOR_WAIT(x)       (((x) & 0x3) << 1)
+#define SSI_SOR_SYNRST        (1 << 0)
+
+#define SSI_SACNT_FRDIV(x)    (((x) & 0x3f) << 5)
+#define SSI_SACNT_WR          (x << 4)
+#define SSI_SACNT_RD          (x << 3)
+#define SSI_SACNT_TIF         (x << 2)
+#define SSI_SACNT_FV          (x << 1)
+#define SSI_SACNT_AC97EN      (x << 0)
+
+/* Watermarks for FIFO's */
+#define TXFIFO_WATERMARK                               0x4
+#define RXFIFO_WATERMARK                               0x4
+
+/* i.MX DAI SSP ID's */
+#define IMX_DAI_SSI0                   0 /* SSI1 FIFO 0 */
+#define IMX_DAI_SSI1                   1 /* SSI1 FIFO 1 */
+#define IMX_DAI_SSI2                   2 /* SSI2 FIFO 0 */
+#define IMX_DAI_SSI3                   3 /* SSI2 FIFO 1 */
+
+/* SSI clock sources */
+#define IMX_SSP_SYS_CLK                0
+
+/* SSI audio dividers */
+#define IMX_SSI_TX_DIV_2                       0
+#define IMX_SSI_TX_DIV_PSR                     1
+#define IMX_SSI_TX_DIV_PM                      2
+#define IMX_SSI_RX_DIV_2                       3
+#define IMX_SSI_RX_DIV_PSR                     4
+#define IMX_SSI_RX_DIV_PM                      5
+
+
+/* SSI Div 2 */
+#define IMX_SSI_DIV_2_OFF              (~SSI_STCCR_DIV2)
+#define IMX_SSI_DIV_2_ON               SSI_STCCR_DIV2
+
+extern struct snd_soc_dai imx_ssi_pcm_dai[4];
+extern int get_ssi_clk(int ssi, struct device *dev);
+extern void put_ssi_clk(int ssi);
+#endif
index b771238662b6407fa8a10aa5e1050dbc633a1389..2dee9839be86035f6b668655dcf84aa12d9e843c 100644 (file)
@@ -15,6 +15,14 @@ config SND_OMAP_SOC_N810
        help
          Say Y if you want to add support for SoC audio on Nokia N810.
 
+config SND_OMAP_SOC_AMS_DELTA
+       tristate "SoC Audio support for Amstrad E3 (Delta) videophone"
+       depends on SND_OMAP_SOC && MACH_AMS_DELTA
+       select SND_OMAP_SOC_MCBSP
+       select SND_SOC_CX20442
+       help
+         Say Y if you want to add support for SoC audio on Amstrad Delta.
+
 config SND_OMAP_SOC_OSK5912
        tristate "SoC Audio support for omap osk5912"
        depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C
@@ -72,4 +80,11 @@ config SND_OMAP_SOC_OMAP3_BEAGLE
        help
          Say Y if you want to add support for SoC audio on the Beagleboard.
 
+config SND_OMAP_SOC_ZOOM2
+       tristate "SoC Audio support for Zoom2"
+       depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2
+       select SND_OMAP_SOC_MCBSP
+       select SND_SOC_TWL4030
+       help
+         Say Y if you want to add support for Soc audio on Zoom2 board.
 
index a37f498623896426d0b50a6529834d1b9ee90888..02d69471dcb5ae051fe8879f927fa0216802bb11 100644 (file)
@@ -7,6 +7,7 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
 
 # OMAP Machine Support
 snd-soc-n810-objs := n810.o
+snd-soc-ams-delta-objs := ams-delta.o
 snd-soc-osk5912-objs := osk5912.o
 snd-soc-overo-objs := overo.o
 snd-soc-omap2evm-objs := omap2evm.o
@@ -14,8 +15,10 @@ snd-soc-omap3evm-objs := omap3evm.o
 snd-soc-sdp3430-objs := sdp3430.o
 snd-soc-omap3pandora-objs := omap3pandora.o
 snd-soc-omap3beagle-objs := omap3beagle.o
+snd-soc-zoom2-objs := zoom2.o
 
 obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
+obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o
 obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
 obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
 obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
@@ -23,3 +26,4 @@ obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o
 obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
 obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
 obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
+obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
new file mode 100644 (file)
index 0000000..5a5166a
--- /dev/null
@@ -0,0 +1,646 @@
+/*
+ * ams-delta.c  --  SoC audio for Amstrad E3 (Delta) videophone
+ *
+ * Copyright (C) 2009 Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
+ *
+ * Initially based on sound/soc/omap/osk5912.x
+ * Copyright (C) 2008 Mistral Solutions
+ *
+ * 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 the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/gpio.h>
+#include <linux/spinlock.h>
+#include <linux/tty.h>
+
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+
+#include <asm/mach-types.h>
+
+#include <mach/board-ams-delta.h>
+#include <mach/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/cx20442.h"
+
+
+/* Board specific DAPM widgets */
+ const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = {
+       /* Handset */
+       SND_SOC_DAPM_MIC("Mouthpiece", NULL),
+       SND_SOC_DAPM_HP("Earpiece", NULL),
+       /* Handsfree/Speakerphone */
+       SND_SOC_DAPM_MIC("Microphone", NULL),
+       SND_SOC_DAPM_SPK("Speaker", NULL),
+};
+
+/* How they are connected to codec pins */
+static const struct snd_soc_dapm_route ams_delta_audio_map[] = {
+       {"TELIN", NULL, "Mouthpiece"},
+       {"Earpiece", NULL, "TELOUT"},
+
+       {"MIC", NULL, "Microphone"},
+       {"Speaker", NULL, "SPKOUT"},
+};
+
+/*
+ * Controls, functional after the modem line discipline is activated.
+ */
+
+/* Virtual switch: audio input/output constellations */
+static const char *ams_delta_audio_mode[] =
+       {"Mixed", "Handset", "Handsfree", "Speakerphone"};
+
+/* Selection <-> pin translation */
+#define AMS_DELTA_MOUTHPIECE   0
+#define AMS_DELTA_EARPIECE     1
+#define AMS_DELTA_MICROPHONE   2
+#define AMS_DELTA_SPEAKER      3
+#define AMS_DELTA_AGC          4
+
+#define AMS_DELTA_MIXED                ((1 << AMS_DELTA_EARPIECE) | \
+                                               (1 << AMS_DELTA_MICROPHONE))
+#define AMS_DELTA_HANDSET      ((1 << AMS_DELTA_MOUTHPIECE) | \
+                                               (1 << AMS_DELTA_EARPIECE))
+#define AMS_DELTA_HANDSFREE    ((1 << AMS_DELTA_MICROPHONE) | \
+                                               (1 << AMS_DELTA_SPEAKER))
+#define AMS_DELTA_SPEAKERPHONE (AMS_DELTA_HANDSFREE | (1 << AMS_DELTA_AGC))
+
+unsigned short ams_delta_audio_mode_pins[] = {
+       AMS_DELTA_MIXED,
+       AMS_DELTA_HANDSET,
+       AMS_DELTA_HANDSFREE,
+       AMS_DELTA_SPEAKERPHONE,
+};
+
+static unsigned short ams_delta_audio_agc;
+
+static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+       struct soc_enum *control = (struct soc_enum *)kcontrol->private_value;
+       unsigned short pins;
+       int pin, changed = 0;
+
+       /* Refuse any mode changes if we are not able to control the codec. */
+       if (!codec->control_data)
+               return -EUNATCH;
+
+       if (ucontrol->value.enumerated.item[0] >= control->max)
+               return -EINVAL;
+
+       mutex_lock(&codec->mutex);
+
+       /* Translate selection to bitmap */
+       pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]];
+
+       /* Setup pins after corresponding bits if changed */
+       pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE));
+       if (pin != snd_soc_dapm_get_pin_status(codec, "Mouthpiece")) {
+               changed = 1;
+               if (pin)
+                       snd_soc_dapm_enable_pin(codec, "Mouthpiece");
+               else
+                       snd_soc_dapm_disable_pin(codec, "Mouthpiece");
+       }
+       pin = !!(pins & (1 << AMS_DELTA_EARPIECE));
+       if (pin != snd_soc_dapm_get_pin_status(codec, "Earpiece")) {
+               changed = 1;
+               if (pin)
+                       snd_soc_dapm_enable_pin(codec, "Earpiece");
+               else
+                       snd_soc_dapm_disable_pin(codec, "Earpiece");
+       }
+       pin = !!(pins & (1 << AMS_DELTA_MICROPHONE));
+       if (pin != snd_soc_dapm_get_pin_status(codec, "Microphone")) {
+               changed = 1;
+               if (pin)
+                       snd_soc_dapm_enable_pin(codec, "Microphone");
+               else
+                       snd_soc_dapm_disable_pin(codec, "Microphone");
+       }
+       pin = !!(pins & (1 << AMS_DELTA_SPEAKER));
+       if (pin != snd_soc_dapm_get_pin_status(codec, "Speaker")) {
+               changed = 1;
+               if (pin)
+                       snd_soc_dapm_enable_pin(codec, "Speaker");
+               else
+                       snd_soc_dapm_disable_pin(codec, "Speaker");
+       }
+       pin = !!(pins & (1 << AMS_DELTA_AGC));
+       if (pin != ams_delta_audio_agc) {
+               ams_delta_audio_agc = pin;
+               changed = 1;
+               if (pin)
+                       snd_soc_dapm_enable_pin(codec, "AGCIN");
+               else
+                       snd_soc_dapm_disable_pin(codec, "AGCIN");
+       }
+       if (changed)
+               snd_soc_dapm_sync(codec);
+
+       mutex_unlock(&codec->mutex);
+
+       return changed;
+}
+
+static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+       unsigned short pins, mode;
+
+       pins = ((snd_soc_dapm_get_pin_status(codec, "Mouthpiece") <<
+                                                       AMS_DELTA_MOUTHPIECE) |
+                       (snd_soc_dapm_get_pin_status(codec, "Earpiece") <<
+                                                       AMS_DELTA_EARPIECE));
+       if (pins)
+               pins |= (snd_soc_dapm_get_pin_status(codec, "Microphone") <<
+                                                       AMS_DELTA_MICROPHONE);
+       else
+               pins = ((snd_soc_dapm_get_pin_status(codec, "Microphone") <<
+                                                       AMS_DELTA_MICROPHONE) |
+                       (snd_soc_dapm_get_pin_status(codec, "Speaker") <<
+                                                       AMS_DELTA_SPEAKER) |
+                       (ams_delta_audio_agc << AMS_DELTA_AGC));
+
+       for (mode = 0; mode < ARRAY_SIZE(ams_delta_audio_mode); mode++)
+               if (pins == ams_delta_audio_mode_pins[mode])
+                       break;
+
+       if (mode >= ARRAY_SIZE(ams_delta_audio_mode))
+               return -EINVAL;
+
+       ucontrol->value.enumerated.item[0] = mode;
+
+       return 0;
+}
+
+static const struct soc_enum ams_delta_audio_enum[] = {
+       SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ams_delta_audio_mode),
+                                               ams_delta_audio_mode),
+};
+
+static const struct snd_kcontrol_new ams_delta_audio_controls[] = {
+       SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum[0],
+                       ams_delta_get_audio_mode, ams_delta_set_audio_mode),
+};
+
+/* Hook switch */
+static struct snd_soc_jack ams_delta_hook_switch;
+static struct snd_soc_jack_gpio ams_delta_hook_switch_gpios[] = {
+       {
+               .gpio = 4,
+               .name = "hook_switch",
+               .report = SND_JACK_HEADSET,
+               .invert = 1,
+               .debounce_time = 150,
+       }
+};
+
+/* After we are able to control the codec over the modem,
+ * the hook switch can be used for dynamic DAPM reconfiguration. */
+static struct snd_soc_jack_pin ams_delta_hook_switch_pins[] = {
+       /* Handset */
+       {
+               .pin = "Mouthpiece",
+               .mask = SND_JACK_MICROPHONE,
+       },
+       {
+               .pin = "Earpiece",
+               .mask = SND_JACK_HEADPHONE,
+       },
+       /* Handsfree */
+       {
+               .pin = "Microphone",
+               .mask = SND_JACK_MICROPHONE,
+               .invert = 1,
+       },
+       {
+               .pin = "Speaker",
+               .mask = SND_JACK_HEADPHONE,
+               .invert = 1,
+       },
+};
+
+
+/*
+ * Modem line discipline, required for making above controls functional.
+ * Activated from userspace with ldattach, possibly invoked from udev rule.
+ */
+
+/* To actually apply any modem controlled configuration changes to the codec,
+ * we must connect codec DAI pins to the modem for a moment.  Be carefull not
+ * to interfere with our digital mute function that shares the same hardware. */
+static struct timer_list cx81801_timer;
+static bool cx81801_cmd_pending;
+static bool ams_delta_muted;
+static DEFINE_SPINLOCK(ams_delta_lock);
+
+static void cx81801_timeout(unsigned long data)
+{
+       int muted;
+
+       spin_lock(&ams_delta_lock);
+       cx81801_cmd_pending = 0;
+       muted = ams_delta_muted;
+       spin_unlock(&ams_delta_lock);
+
+       /* Reconnect the codec DAI back from the modem to the CPU DAI
+        * only if digital mute still off */
+       if (!muted)
+               ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0);
+}
+
+/* Line discipline .open() */
+static int cx81801_open(struct tty_struct *tty)
+{
+       return v253_ops.open(tty);
+}
+
+/* Line discipline .close() */
+static void cx81801_close(struct tty_struct *tty)
+{
+       struct snd_soc_codec *codec = tty->disc_data;
+
+       del_timer_sync(&cx81801_timer);
+
+       v253_ops.close(tty);
+
+       /* Prevent the hook switch from further changing the DAPM pins */
+       INIT_LIST_HEAD(&ams_delta_hook_switch.pins);
+
+       /* Revert back to default audio input/output constellation */
+       snd_soc_dapm_disable_pin(codec, "Mouthpiece");
+       snd_soc_dapm_enable_pin(codec, "Earpiece");
+       snd_soc_dapm_enable_pin(codec, "Microphone");
+       snd_soc_dapm_disable_pin(codec, "Speaker");
+       snd_soc_dapm_disable_pin(codec, "AGCIN");
+       snd_soc_dapm_sync(codec);
+}
+
+/* Line discipline .hangup() */
+static int cx81801_hangup(struct tty_struct *tty)
+{
+       cx81801_close(tty);
+       return 0;
+}
+
+/* Line discipline .recieve_buf() */
+static void cx81801_receive(struct tty_struct *tty,
+                               const unsigned char *cp, char *fp, int count)
+{
+       struct snd_soc_codec *codec = tty->disc_data;
+       const unsigned char *c;
+       int apply, ret;
+
+       if (!codec->control_data) {
+               /* First modem response, complete setup procedure */
+
+               /* Initialize timer used for config pulse generation */
+               setup_timer(&cx81801_timer, cx81801_timeout, 0);
+
+               v253_ops.receive_buf(tty, cp, fp, count);
+
+               /* Link hook switch to DAPM pins */
+               ret = snd_soc_jack_add_pins(&ams_delta_hook_switch,
+                                       ARRAY_SIZE(ams_delta_hook_switch_pins),
+                                       ams_delta_hook_switch_pins);
+               if (ret)
+                       dev_warn(codec->socdev->card->dev,
+                               "Failed to link hook switch to DAPM pins, "
+                               "will continue with hook switch unlinked.\n");
+
+               return;
+       }
+
+       v253_ops.receive_buf(tty, cp, fp, count);
+
+       for (c = &cp[count - 1]; c >= cp; c--) {
+               if (*c != '\r')
+                       continue;
+               /* Complete modem response received, apply config to codec */
+
+               spin_lock_bh(&ams_delta_lock);
+               mod_timer(&cx81801_timer, jiffies + msecs_to_jiffies(150));
+               apply = !ams_delta_muted && !cx81801_cmd_pending;
+               cx81801_cmd_pending = 1;
+               spin_unlock_bh(&ams_delta_lock);
+
+               /* Apply config pulse by connecting the codec to the modem
+                * if not already done */
+               if (apply)
+                       ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
+                                               AMS_DELTA_LATCH2_MODEM_CODEC);
+               break;
+       }
+}
+
+/* Line discipline .write_wakeup() */
+static void cx81801_wakeup(struct tty_struct *tty)
+{
+       v253_ops.write_wakeup(tty);
+}
+
+static struct tty_ldisc_ops cx81801_ops = {
+       .magic = TTY_LDISC_MAGIC,
+       .name = "cx81801",
+       .owner = THIS_MODULE,
+       .open = cx81801_open,
+       .close = cx81801_close,
+       .hangup = cx81801_hangup,
+       .receive_buf = cx81801_receive,
+       .write_wakeup = cx81801_wakeup,
+};
+
+
+/*
+ * Even if not very usefull, the sound card can still work without any of the
+ * above functonality activated.  You can still control its audio input/output
+ * constellation and speakerphone gain from userspace by issueing AT commands
+ * over the modem port.
+ */
+
+static int ams_delta_hw_params(struct snd_pcm_substream *substream,
+                        struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+       /* Set cpu DAI configuration */
+       return snd_soc_dai_set_fmt(rtd->dai->cpu_dai,
+                                  SND_SOC_DAIFMT_DSP_A |
+                                  SND_SOC_DAIFMT_NB_NF |
+                                  SND_SOC_DAIFMT_CBM_CFM);
+}
+
+static struct snd_soc_ops ams_delta_ops = {
+       .hw_params = ams_delta_hw_params,
+};
+
+
+/* Board specific codec bias level control */
+static int ams_delta_set_bias_level(struct snd_soc_card *card,
+                                       enum snd_soc_bias_level level)
+{
+       struct snd_soc_codec *codec = card->codec;
+
+       switch (level) {
+       case SND_SOC_BIAS_ON:
+       case SND_SOC_BIAS_PREPARE:
+       case SND_SOC_BIAS_STANDBY:
+               if (codec->bias_level == SND_SOC_BIAS_OFF)
+                       ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_NRESET,
+                                               AMS_DELTA_LATCH2_MODEM_NRESET);
+               break;
+       case SND_SOC_BIAS_OFF:
+               if (codec->bias_level != SND_SOC_BIAS_OFF)
+                       ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_NRESET,
+                                               0);
+       }
+       codec->bias_level = level;
+
+       return 0;
+}
+
+/* Digital mute implemented using modem/CPU multiplexer.
+ * Shares hardware with codec config pulse generation */
+static bool ams_delta_muted = 1;
+
+static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+       int apply;
+
+       if (ams_delta_muted == mute)
+               return 0;
+
+       spin_lock_bh(&ams_delta_lock);
+       ams_delta_muted = mute;
+       apply = !cx81801_cmd_pending;
+       spin_unlock_bh(&ams_delta_lock);
+
+       if (apply)
+               ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
+                               mute ? AMS_DELTA_LATCH2_MODEM_CODEC : 0);
+       return 0;
+}
+
+/* Our codec DAI probably doesn't have its own .ops structure */
+static struct snd_soc_dai_ops ams_delta_dai_ops = {
+       .digital_mute = ams_delta_digital_mute,
+};
+
+/* Will be used if the codec ever has its own digital_mute function */
+static int ams_delta_startup(struct snd_pcm_substream *substream)
+{
+       return ams_delta_digital_mute(NULL, 0);
+}
+
+static void ams_delta_shutdown(struct snd_pcm_substream *substream)
+{
+       ams_delta_digital_mute(NULL, 1);
+}
+
+
+/*
+ * Card initialization
+ */
+
+static int ams_delta_cx20442_init(struct snd_soc_codec *codec)
+{
+       struct snd_soc_dai *codec_dai = codec->dai;
+       struct snd_soc_card *card = codec->socdev->card;
+       int ret;
+       /* Codec is ready, now add/activate board specific controls */
+
+       /* Set up digital mute if not provided by the codec */
+       if (!codec_dai->ops) {
+               codec_dai->ops = &ams_delta_dai_ops;
+       } else if (!codec_dai->ops->digital_mute) {
+               codec_dai->ops->digital_mute = ams_delta_digital_mute;
+       } else {
+               ams_delta_ops.startup = ams_delta_startup;
+               ams_delta_ops.shutdown = ams_delta_shutdown;
+       }
+
+       /* Set codec bias level */
+       ams_delta_set_bias_level(card, SND_SOC_BIAS_STANDBY);
+
+       /* Add hook switch - can be used to control the codec from userspace
+        * even if line discipline fails */
+       ret = snd_soc_jack_new(card, "hook_switch",
+                               SND_JACK_HEADSET, &ams_delta_hook_switch);
+       if (ret)
+               dev_warn(card->dev,
+                               "Failed to allocate resources for hook switch, "
+                               "will continue without one.\n");
+       else {
+               ret = snd_soc_jack_add_gpios(&ams_delta_hook_switch,
+                                       ARRAY_SIZE(ams_delta_hook_switch_gpios),
+                                       ams_delta_hook_switch_gpios);
+               if (ret)
+                       dev_warn(card->dev,
+                               "Failed to set up hook switch GPIO line, "
+                               "will continue with hook switch inactive.\n");
+       }
+
+       /* Register optional line discipline for over the modem control */
+       ret = tty_register_ldisc(N_V253, &cx81801_ops);
+       if (ret) {
+               dev_warn(card->dev,
+                               "Failed to register line discipline, "
+                               "will continue without any controls.\n");
+               return 0;
+       }
+
+       /* Add board specific DAPM widgets and routes */
+       ret = snd_soc_dapm_new_controls(codec, ams_delta_dapm_widgets,
+                                       ARRAY_SIZE(ams_delta_dapm_widgets));
+       if (ret) {
+               dev_warn(card->dev,
+                               "Failed to register DAPM controls, "
+                               "will continue without any.\n");
+               return 0;
+       }
+
+       ret = snd_soc_dapm_add_routes(codec, ams_delta_audio_map,
+                                       ARRAY_SIZE(ams_delta_audio_map));
+       if (ret) {
+               dev_warn(card->dev,
+                               "Failed to set up DAPM routes, "
+                               "will continue with codec default map.\n");
+               return 0;
+       }
+
+       /* Set up initial pin constellation */
+       snd_soc_dapm_disable_pin(codec, "Mouthpiece");
+       snd_soc_dapm_enable_pin(codec, "Earpiece");
+       snd_soc_dapm_enable_pin(codec, "Microphone");
+       snd_soc_dapm_disable_pin(codec, "Speaker");
+       snd_soc_dapm_disable_pin(codec, "AGCIN");
+       snd_soc_dapm_disable_pin(codec, "AGCOUT");
+       snd_soc_dapm_sync(codec);
+
+       /* Add virtual switch */
+       ret = snd_soc_add_controls(codec, ams_delta_audio_controls,
+                                       ARRAY_SIZE(ams_delta_audio_controls));
+       if (ret)
+               dev_warn(card->dev,
+                               "Failed to register audio mode control, "
+                               "will continue without it.\n");
+
+       return 0;
+}
+
+/* DAI glue - connects codec <--> CPU */
+static struct snd_soc_dai_link ams_delta_dai_link = {
+       .name = "CX20442",
+       .stream_name = "CX20442",
+       .cpu_dai = &omap_mcbsp_dai[0],
+       .codec_dai = &cx20442_dai,
+       .init = ams_delta_cx20442_init,
+       .ops = &ams_delta_ops,
+};
+
+/* Audio card driver */
+static struct snd_soc_card ams_delta_audio_card = {
+       .name = "AMS_DELTA",
+       .platform = &omap_soc_platform,
+       .dai_link = &ams_delta_dai_link,
+       .num_links = 1,
+       .set_bias_level = ams_delta_set_bias_level,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device ams_delta_snd_soc_device = {
+       .card = &ams_delta_audio_card,
+       .codec_dev = &cx20442_codec_dev,
+};
+
+/* Module init/exit */
+static struct platform_device *ams_delta_audio_platform_device;
+static struct platform_device *cx20442_platform_device;
+
+static int __init ams_delta_module_init(void)
+{
+       int ret;
+
+       if (!(machine_is_ams_delta()))
+               return -ENODEV;
+
+       ams_delta_audio_platform_device =
+                       platform_device_alloc("soc-audio", -1);
+       if (!ams_delta_audio_platform_device)
+               return -ENOMEM;
+
+       platform_set_drvdata(ams_delta_audio_platform_device,
+                               &ams_delta_snd_soc_device);
+       ams_delta_snd_soc_device.dev = &ams_delta_audio_platform_device->dev;
+       *(unsigned int *)ams_delta_dai_link.cpu_dai->private_data = OMAP_MCBSP1;
+
+       ret = platform_device_add(ams_delta_audio_platform_device);
+       if (ret)
+               goto err;
+
+       /*
+        * Codec platform device could be registered from elsewhere (board?),
+        * but I do it here as it makes sense only if used with the card.
+        */
+       cx20442_platform_device = platform_device_register_simple("cx20442",
+                                                               -1, NULL, 0);
+       return 0;
+err:
+       platform_device_put(ams_delta_audio_platform_device);
+       return ret;
+}
+module_init(ams_delta_module_init);
+
+static void __exit ams_delta_module_exit(void)
+{
+       struct snd_soc_codec *codec;
+       struct tty_struct *tty;
+
+       if (ams_delta_audio_card.codec) {
+               codec = ams_delta_audio_card.codec;
+
+               if (codec->control_data) {
+                       tty = codec->control_data;
+
+                       tty_hangup(tty);
+               }
+       }
+
+       if (tty_unregister_ldisc(N_V253) != 0)
+               dev_warn(&ams_delta_audio_platform_device->dev,
+                       "failed to unregister V253 line discipline\n");
+
+       snd_soc_jack_free_gpios(&ams_delta_hook_switch,
+                       ARRAY_SIZE(ams_delta_hook_switch_gpios),
+                       ams_delta_hook_switch_gpios);
+
+       /* Keep modem power on */
+       ams_delta_set_bias_level(&ams_delta_audio_card, SND_SOC_BIAS_STANDBY);
+
+       platform_device_unregister(cx20442_platform_device);
+       platform_device_unregister(ams_delta_audio_platform_device);
+}
+module_exit(ams_delta_module_exit);
+
+MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>");
+MODULE_DESCRIPTION("ALSA SoC driver for Amstrad E3 (Delta) videophone");
+MODULE_LICENSE("GPL");
index b60b1dfbc435f0036f9d18447b6e45c617e39439..0a505938e42bc82e3d7359b8cdcc8a2a62000cb9 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -322,8 +323,6 @@ static struct snd_soc_card snd_soc_n810 = {
 
 /* Audio private data */
 static struct aic3x_setup_data n810_aic33_setup = {
-       .i2c_bus = 2,
-       .i2c_address = 0x18,
        .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
        .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
 };
@@ -337,6 +336,13 @@ static struct snd_soc_device n810_snd_devdata = {
 
 static struct platform_device *n810_snd_device;
 
+/* temporary i2c device creation until this can be moved into the machine
+ * support file.
+*/
+static struct i2c_board_info i2c_device[] = {
+       { I2C_BOARD_INFO("tlv320aic3x", 0x1b), }
+};
+
 static int __init n810_soc_init(void)
 {
        int err;
@@ -345,6 +351,8 @@ static int __init n810_soc_init(void)
        if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax()))
                return -ENODEV;
 
+       i2c_register_board_info(1, i2c_device, ARRAY_SIZE(i2c_device));
+
        n810_snd_device = platform_device_alloc("soc-audio", -1);
        if (!n810_snd_device)
                return -ENOMEM;
index a5d46a7b196a324cebce928cfaed329afaec8cf3..3341f49402ca634226eeaa7b7e231b4c98f80fd7 100644 (file)
@@ -139,27 +139,67 @@ static const unsigned long omap34xx_mcbsp_port[][2] = {
 static const unsigned long omap34xx_mcbsp_port[][2] = {};
 #endif
 
+static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+       int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);
+       int samples;
+
+       /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
+       if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
+               samples = snd_pcm_lib_period_bytes(substream) >> 1;
+       else
+               samples = 1;
+
+       /* Configure McBSP internal buffer usage */
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, samples - 1);
+       else
+               omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, samples - 1);
+}
+
 static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
                                  struct snd_soc_dai *dai)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
+       int bus_id = mcbsp_data->bus_id;
        int err = 0;
 
-       if (cpu_is_omap343x() && mcbsp_data->bus_id == 1) {
+       if (!cpu_dai->active)
+               err = omap_mcbsp_request(bus_id);
+
+       if (cpu_is_omap343x()) {
+               int dma_op_mode = omap_mcbsp_get_dma_op_mode(bus_id);
+               int max_period;
+
                /*
                 * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer.
                 * Set constraint for minimum buffer size to the same than FIFO
                 * size in order to avoid underruns in playback startup because
                 * HW is keeping the DMA request active until FIFO is filled.
                 */
-               snd_pcm_hw_constraint_minmax(substream->runtime,
-                       SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4096, UINT_MAX);
-       }
+               if (bus_id == 1)
+                       snd_pcm_hw_constraint_minmax(substream->runtime,
+                                       SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+                                       4096, UINT_MAX);
 
-       if (!cpu_dai->active)
-               err = omap_mcbsp_request(mcbsp_data->bus_id);
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+                       max_period = omap_mcbsp_get_max_tx_threshold(bus_id);
+               else
+                       max_period = omap_mcbsp_get_max_rx_threshold(bus_id);
+
+               max_period++;
+               max_period <<= 1;
+
+               if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
+                       snd_pcm_hw_constraint_minmax(substream->runtime,
+                                               SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+                                               32, max_period);
+       }
 
        return err;
 }
@@ -183,21 +223,21 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
        struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
-       int err = 0;
+       int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               if (!mcbsp_data->active++)
-                       omap_mcbsp_start(mcbsp_data->bus_id);
+               mcbsp_data->active++;
+               omap_mcbsp_start(mcbsp_data->bus_id, play, !play);
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-               if (!--mcbsp_data->active)
-                       omap_mcbsp_stop(mcbsp_data->bus_id);
+               omap_mcbsp_stop(mcbsp_data->bus_id, play, !play);
+               mcbsp_data->active--;
                break;
        default:
                err = -EINVAL;
@@ -215,7 +255,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
        struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
        int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
-       int wlen, channels, wpf;
+       int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
        unsigned long port;
        unsigned int format;
 
@@ -231,6 +271,12 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
        } else if (cpu_is_omap343x()) {
                dma = omap24xx_dma_reqs[bus_id][substream->stream];
                port = omap34xx_mcbsp_port[bus_id][substream->stream];
+               omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold =
+                                               omap_mcbsp_set_threshold;
+               /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
+               if (omap_mcbsp_get_dma_op_mode(bus_id) ==
+                                               MCBSP_DMA_MODE_THRESHOLD)
+                       sync_mode = OMAP_DMA_SYNC_FRAME;
        } else {
                return -ENODEV;
        }
@@ -238,6 +284,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
                substream->stream ? "Audio Capture" : "Audio Playback";
        omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
        omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
+       omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode;
        cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream];
 
        if (mcbsp_data->configured) {
@@ -321,11 +368,14 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        /* Generic McBSP register settings */
        regs->spcr2     |= XINTM(3) | FREE;
        regs->spcr1     |= RINTM(3);
-       regs->rcr2      |= RFIG;
-       regs->xcr2      |= XFIG;
+       /* RFIG and XFIG are not defined in 34xx */
+       if (!cpu_is_omap34xx()) {
+               regs->rcr2      |= RFIG;
+               regs->xcr2      |= XFIG;
+       }
        if (cpu_is_omap2430() || cpu_is_omap34xx()) {
-               regs->xccr = DXENDLY(1) | XDMAEN;
-               regs->rccr = RFULL_CYCLE | RDMAEN;
+               regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE;
+               regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE;
        }
 
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -462,6 +512,40 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
        return 0;
 }
 
+static int omap_mcbsp_dai_set_rcvr_src(struct omap_mcbsp_data *mcbsp_data,
+                                      int clk_id)
+{
+       int sel_bit, set = 0;
+       u16 reg = OMAP2_CONTROL_DEVCONF0;
+
+       if (cpu_class_is_omap1())
+               return -EINVAL; /* TODO: Can this be implemented for OMAP1? */
+       if (mcbsp_data->bus_id != 0)
+               return -EINVAL;
+
+       switch (clk_id) {
+       case OMAP_MCBSP_CLKR_SRC_CLKX:
+               set = 1;
+       case OMAP_MCBSP_CLKR_SRC_CLKR:
+               sel_bit = 3;
+               break;
+       case OMAP_MCBSP_FSR_SRC_FSX:
+               set = 1;
+       case OMAP_MCBSP_FSR_SRC_FSR:
+               sel_bit = 4;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (set)
+               omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
+       else
+               omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
+
+       return 0;
+}
+
 static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
                                         int clk_id, unsigned int freq,
                                         int dir)
@@ -484,6 +568,13 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
        case OMAP_MCBSP_SYSCLK_CLKR_EXT:
                regs->pcr0      |= SCLKME;
                break;
+
+       case OMAP_MCBSP_CLKR_SRC_CLKR:
+       case OMAP_MCBSP_CLKR_SRC_CLKX:
+       case OMAP_MCBSP_FSR_SRC_FSR:
+       case OMAP_MCBSP_FSR_SRC_FSX:
+               err = omap_mcbsp_dai_set_rcvr_src(mcbsp_data, clk_id);
+               break;
        default:
                err = -ENODEV;
        }
index c8147aace813431deedee6fd0b1bdc814277b952..647d2f981ab00a00f0d2e4f2789a8853a4ca1fb3 100644 (file)
@@ -32,6 +32,10 @@ enum omap_mcbsp_clksrg_clk {
        OMAP_MCBSP_SYSCLK_CLK,          /* Internal ICLK */
        OMAP_MCBSP_SYSCLK_CLKX_EXT,     /* External CLKX pin */
        OMAP_MCBSP_SYSCLK_CLKR_EXT,     /* External CLKR pin */
+       OMAP_MCBSP_CLKR_SRC_CLKR,       /* CLKR from CLKR pin */
+       OMAP_MCBSP_CLKR_SRC_CLKX,       /* CLKR from CLKX pin */
+       OMAP_MCBSP_FSR_SRC_FSR,         /* FSR from FSR pin */
+       OMAP_MCBSP_FSR_SRC_FSX,         /* FSR from FSX pin */
 };
 
 /* McBSP dividers */
index 6454e15f7d28cb274bf3e21abe76b9b1ee6f06ee..5735945788bfda39307322bae71519a277f6ab10 100644 (file)
@@ -59,16 +59,31 @@ static void omap_pcm_dma_irq(int ch, u16 stat, void *data)
        struct omap_runtime_data *prtd = runtime->private_data;
        unsigned long flags;
 
-       if (cpu_is_omap1510()) {
+       if ((cpu_is_omap1510()) &&
+                       (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) {
                /*
-                * OMAP1510 doesn't support DMA chaining so have to restart
-                * the transfer after all periods are transferred
+                * OMAP1510 doesn't fully support DMA progress counter
+                * and there is no software emulation implemented yet,
+                * so have to maintain our own playback progress counter
+                * that can be used by omap_pcm_pointer() instead.
                 */
                spin_lock_irqsave(&prtd->lock, flags);
+               if ((stat == OMAP_DMA_LAST_IRQ) &&
+                               (prtd->period_index == runtime->periods - 1)) {
+                       /* we are in sync, do nothing */
+                       spin_unlock_irqrestore(&prtd->lock, flags);
+                       return;
+               }
                if (prtd->period_index >= 0) {
-                       if (++prtd->period_index == runtime->periods) {
+                       if (stat & OMAP_DMA_BLOCK_IRQ) {
+                               /* end of buffer reached, loop back */
+                               prtd->period_index = 0;
+                       } else if (stat & OMAP_DMA_LAST_IRQ) {
+                               /* update the counter for the last period */
+                               prtd->period_index = runtime->periods - 1;
+                       } else if (++prtd->period_index >= runtime->periods) {
+                               /* end of buffer missed? loop back */
                                prtd->period_index = 0;
-                               omap_start_dma(prtd->dma_ch);
                        }
                }
                spin_unlock_irqrestore(&prtd->lock, flags);
@@ -100,7 +115,7 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
        prtd->dma_data = dma_data;
        err = omap_request_dma(dma_data->dma_req, dma_data->name,
                               omap_pcm_dma_irq, substream, &prtd->dma_ch);
-       if (!err && !cpu_is_omap1510()) {
+       if (!err) {
                /*
                 * Link channel with itself so DMA doesn't need any
                 * reprogramming while looping the buffer
@@ -119,8 +134,7 @@ static int omap_pcm_hw_free(struct snd_pcm_substream *substream)
        if (prtd->dma_data == NULL)
                return 0;
 
-       if (!cpu_is_omap1510())
-               omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch);
+       omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch);
        omap_free_dma(prtd->dma_ch);
        prtd->dma_data = NULL;
 
@@ -148,7 +162,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
         */
        dma_params.data_type                    = OMAP_DMA_DATA_TYPE_S16;
        dma_params.trigger                      = dma_data->dma_req;
-       dma_params.sync_mode                    = OMAP_DMA_SYNC_ELEMENT;
+       dma_params.sync_mode                    = dma_data->sync_mode;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                dma_params.src_amode            = OMAP_DMA_AMODE_POST_INC;
                dma_params.dst_amode            = OMAP_DMA_AMODE_CONSTANT;
@@ -174,7 +188,15 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
        dma_params.frame_count  = runtime->periods;
        omap_set_dma_params(prtd->dma_ch, &dma_params);
 
-       omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
+       if ((cpu_is_omap1510()) &&
+                       (substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
+               omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ |
+                             OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
+       else
+               omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
+
+       omap_set_dma_src_burst_mode(prtd->dma_ch, OMAP_DMA_DATA_BURST_16);
+       omap_set_dma_dest_burst_mode(prtd->dma_ch, OMAP_DMA_DATA_BURST_16);
 
        return 0;
 }
@@ -183,6 +205,7 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct omap_runtime_data *prtd = runtime->private_data;
+       struct omap_pcm_dma_data *dma_data = prtd->dma_data;
        unsigned long flags;
        int ret = 0;
 
@@ -192,6 +215,10 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                prtd->period_index = 0;
+               /* Configure McBSP internal buffer usage */
+               if (dma_data->set_threshold)
+                       dma_data->set_threshold(substream);
+
                omap_start_dma(prtd->dma_ch);
                break;
 
@@ -216,12 +243,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
        dma_addr_t ptr;
        snd_pcm_uframes_t offset;
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-               ptr = omap_get_dma_src_pos(prtd->dma_ch);
-       else
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
                ptr = omap_get_dma_dst_pos(prtd->dma_ch);
+               offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
+       } else if (!(cpu_is_omap1510())) {
+               ptr = omap_get_dma_src_pos(prtd->dma_ch);
+               offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
+       } else
+               offset = prtd->period_index * runtime->period_size;
 
-       offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
        if (offset >= runtime->buffer_size)
                offset = 0;
 
@@ -285,7 +315,7 @@ static struct snd_pcm_ops omap_pcm_ops = {
        .mmap           = omap_pcm_mmap,
 };
 
-static u64 omap_pcm_dmamask = DMA_BIT_MASK(32);
+static u64 omap_pcm_dmamask = DMA_BIT_MASK(64);
 
 static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
        int stream)
@@ -327,7 +357,7 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm)
        }
 }
 
-int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
+static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
                 struct snd_pcm *pcm)
 {
        int ret = 0;
@@ -335,7 +365,7 @@ int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
        if (!card->dev->dma_mask)
                card->dev->dma_mask = &omap_pcm_dmamask;
        if (!card->dev->coherent_dma_mask)
-               card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+               card->dev->coherent_dma_mask = DMA_BIT_MASK(64);
 
        if (dai->playback.channels_min) {
                ret = omap_pcm_preallocate_dma_buffer(pcm,
index 8d9d26916b05b8868736fa30d071507d1d41ac6d..38a821dd4118f6b1411330013945904ce34bf9cb 100644 (file)
@@ -29,6 +29,8 @@ struct omap_pcm_dma_data {
        char            *name;          /* stream identifier */
        int             dma_req;        /* DMA request line */
        unsigned long   port_addr;      /* transmit/receive register */
+       int             sync_mode;      /* DMA sync mode */
+       void (*set_threshold)(struct snd_pcm_substream *substream);
 };
 
 extern struct snd_soc_platform omap_soc_platform;
index b719e5db4f574cbced41497987e7953591eca81e..4a3f62d1f29588442ea231a467f58f41a09a7051 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/i2c/twl4030.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include "omap-pcm.h"
 #include "../codecs/twl4030.h"
 
+/* TWL4030 PMBR1 Register */
+#define TWL4030_INTBR_PMBR1            0x0D
+/* TWL4030 PMBR1 Register GPIO6 mux bit */
+#define TWL4030_GPIO6_PWM0_MUTE(value) (value << 2)
+
 static struct snd_soc_card snd_soc_sdp3430;
 
 static int sdp3430_hw_params(struct snd_pcm_substream *substream,
@@ -96,7 +102,7 @@ static int sdp3430_hw_voice_params(struct snd_pcm_substream *substream,
        ret = snd_soc_dai_set_fmt(codec_dai,
                                SND_SOC_DAIFMT_DSP_A |
                                SND_SOC_DAIFMT_IB_NF |
-                               SND_SOC_DAIFMT_CBS_CFM);
+                               SND_SOC_DAIFMT_CBM_CFM);
        if (ret) {
                printk(KERN_ERR "can't set codec DAI configuration\n");
                return ret;
@@ -280,6 +286,7 @@ static struct snd_soc_card snd_soc_sdp3430 = {
 static struct twl4030_setup_data twl4030_setup = {
        .ramp_delay_value = 3,
        .sysclk = 26000,
+       .hs_extmute = 1,
 };
 
 /* Audio subsystem */
@@ -294,6 +301,7 @@ static struct platform_device *sdp3430_snd_device;
 static int __init sdp3430_soc_init(void)
 {
        int ret;
+       u8 pin_mux;
 
        if (!machine_is_omap_3430sdp()) {
                pr_debug("Not SDP3430!\n");
@@ -312,6 +320,14 @@ static int __init sdp3430_soc_init(void)
        *(unsigned int *)sdp3430_dai[0].cpu_dai->private_data = 1; /* McBSP2 */
        *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */
 
+       /* Set TWL4030 GPIO6 as EXTMUTE signal */
+       twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux,
+                                               TWL4030_INTBR_PMBR1);
+       pin_mux &= ~TWL4030_GPIO6_PWM0_MUTE(0x03);
+       pin_mux |= TWL4030_GPIO6_PWM0_MUTE(0x02);
+       twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, pin_mux,
+                                               TWL4030_INTBR_PMBR1);
+
        ret = platform_device_add(sdp3430_snd_device);
        if (ret)
                goto err1;
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c
new file mode 100644 (file)
index 0000000..f90b45f
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * zoom2.c  --  SoC audio for Zoom2
+ *
+ * Author: Misael Lopez Cruz <x0052729@ti.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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/mcbsp.h>
+
+#include "omap-mcbsp.h"
+#include "omap-pcm.h"
+#include "../codecs/twl4030.h"
+
+#define ZOOM2_HEADSET_MUX_GPIO         (OMAP_MAX_GPIO_LINES + 15)
+#define ZOOM2_HEADSET_EXTMUTE_GPIO     153
+
+static int zoom2_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       int ret;
+
+       /* Set codec DAI configuration */
+       ret = snd_soc_dai_set_fmt(codec_dai,
+                                 SND_SOC_DAIFMT_I2S |
+                                 SND_SOC_DAIFMT_NB_NF |
+                                 SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0) {
+               printk(KERN_ERR "can't set codec DAI configuration\n");
+               return ret;
+       }
+
+       /* Set cpu DAI configuration */
+       ret = snd_soc_dai_set_fmt(cpu_dai,
+                                 SND_SOC_DAIFMT_I2S |
+                                 SND_SOC_DAIFMT_NB_NF |
+                                 SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0) {
+               printk(KERN_ERR "can't set cpu DAI configuration\n");
+               return ret;
+       }
+
+       /* Set the codec system clock for DAC and ADC */
+       ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+                                       SND_SOC_CLOCK_IN);
+       if (ret < 0) {
+               printk(KERN_ERR "can't set codec system clock\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static struct snd_soc_ops zoom2_ops = {
+       .hw_params = zoom2_hw_params,
+};
+
+static int zoom2_hw_voice_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       int ret;
+
+       /* Set codec DAI configuration */
+       ret = snd_soc_dai_set_fmt(codec_dai,
+                               SND_SOC_DAIFMT_DSP_A |
+                               SND_SOC_DAIFMT_IB_NF |
+                               SND_SOC_DAIFMT_CBM_CFM);
+       if (ret) {
+               printk(KERN_ERR "can't set codec DAI configuration\n");
+               return ret;
+       }
+
+       /* Set cpu DAI configuration */
+       ret = snd_soc_dai_set_fmt(cpu_dai,
+                               SND_SOC_DAIFMT_DSP_A |
+                               SND_SOC_DAIFMT_IB_NF |
+                               SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0) {
+               printk(KERN_ERR "can't set cpu DAI configuration\n");
+               return ret;
+       }
+
+       /* Set the codec system clock for DAC and ADC */
+       ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
+                                       SND_SOC_CLOCK_IN);
+       if (ret < 0) {
+               printk(KERN_ERR "can't set codec system clock\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static struct snd_soc_ops zoom2_voice_ops = {
+       .hw_params = zoom2_hw_voice_params,
+};
+
+/* Zoom2 machine DAPM */
+static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets[] = {
+       SND_SOC_DAPM_MIC("Ext Mic", NULL),
+       SND_SOC_DAPM_SPK("Ext Spk", NULL),
+       SND_SOC_DAPM_MIC("Headset Mic", NULL),
+       SND_SOC_DAPM_HP("Headset Stereophone", NULL),
+       SND_SOC_DAPM_LINE("Aux In", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+       /* External Mics: MAINMIC, SUBMIC with bias*/
+       {"MAINMIC", NULL, "Mic Bias 1"},
+       {"SUBMIC", NULL, "Mic Bias 2"},
+       {"Mic Bias 1", NULL, "Ext Mic"},
+       {"Mic Bias 2", NULL, "Ext Mic"},
+
+       /* External Speakers: HFL, HFR */
+       {"Ext Spk", NULL, "HFL"},
+       {"Ext Spk", NULL, "HFR"},
+
+       /* Headset Stereophone:  HSOL, HSOR */
+       {"Headset Stereophone", NULL, "HSOL"},
+       {"Headset Stereophone", NULL, "HSOR"},
+
+       /* Headset Mic: HSMIC with bias */
+       {"HSMIC", NULL, "Headset Mic Bias"},
+       {"Headset Mic Bias", NULL, "Headset Mic"},
+
+       /* Aux In: AUXL, AUXR */
+       {"Aux In", NULL, "AUXL"},
+       {"Aux In", NULL, "AUXR"},
+};
+
+static int zoom2_twl4030_init(struct snd_soc_codec *codec)
+{
+       int ret;
+
+       /* Add Zoom2 specific widgets */
+       ret = snd_soc_dapm_new_controls(codec, zoom2_twl4030_dapm_widgets,
+                               ARRAY_SIZE(zoom2_twl4030_dapm_widgets));
+       if (ret)
+               return ret;
+
+       /* Set up Zoom2 specific audio path audio_map */
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+       /* Zoom2 connected pins */
+       snd_soc_dapm_enable_pin(codec, "Ext Mic");
+       snd_soc_dapm_enable_pin(codec, "Ext Spk");
+       snd_soc_dapm_enable_pin(codec, "Headset Mic");
+       snd_soc_dapm_enable_pin(codec, "Headset Stereophone");
+       snd_soc_dapm_enable_pin(codec, "Aux In");
+
+       /* TWL4030 not connected pins */
+       snd_soc_dapm_nc_pin(codec, "CARKITMIC");
+       snd_soc_dapm_nc_pin(codec, "DIGIMIC0");
+       snd_soc_dapm_nc_pin(codec, "DIGIMIC1");
+
+       snd_soc_dapm_nc_pin(codec, "OUTL");
+       snd_soc_dapm_nc_pin(codec, "OUTR");
+       snd_soc_dapm_nc_pin(codec, "EARPIECE");
+       snd_soc_dapm_nc_pin(codec, "PREDRIVEL");
+       snd_soc_dapm_nc_pin(codec, "PREDRIVER");
+       snd_soc_dapm_nc_pin(codec, "CARKITL");
+       snd_soc_dapm_nc_pin(codec, "CARKITR");
+
+       ret = snd_soc_dapm_sync(codec);
+
+       return ret;
+}
+
+static int zoom2_twl4030_voice_init(struct snd_soc_codec *codec)
+{
+       unsigned short reg;
+
+       /* Enable voice interface */
+       reg = codec->read(codec, TWL4030_REG_VOICE_IF);
+       reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN;
+       codec->write(codec, TWL4030_REG_VOICE_IF, reg);
+
+       return 0;
+}
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link zoom2_dai[] = {
+       {
+               .name = "TWL4030 I2S",
+               .stream_name = "TWL4030 Audio",
+               .cpu_dai = &omap_mcbsp_dai[0],
+               .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
+               .init = zoom2_twl4030_init,
+               .ops = &zoom2_ops,
+       },
+       {
+               .name = "TWL4030 PCM",
+               .stream_name = "TWL4030 Voice",
+               .cpu_dai = &omap_mcbsp_dai[1],
+               .codec_dai = &twl4030_dai[TWL4030_DAI_VOICE],
+               .init = zoom2_twl4030_voice_init,
+               .ops = &zoom2_voice_ops,
+       },
+};
+
+/* Audio machine driver */
+static struct snd_soc_card snd_soc_zoom2 = {
+       .name = "Zoom2",
+       .platform = &omap_soc_platform,
+       .dai_link = zoom2_dai,
+       .num_links = ARRAY_SIZE(zoom2_dai),
+};
+
+/* EXTMUTE callback function */
+void zoom2_set_hs_extmute(int mute)
+{
+       gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute);
+}
+
+/* twl4030 setup */
+static struct twl4030_setup_data twl4030_setup = {
+       .ramp_delay_value = 3,  /* 161 ms */
+       .sysclk = 26000,
+       .hs_extmute = 1,
+       .set_hs_extmute = zoom2_set_hs_extmute,
+};
+
+/* Audio subsystem */
+static struct snd_soc_device zoom2_snd_devdata = {
+       .card = &snd_soc_zoom2,
+       .codec_dev = &soc_codec_dev_twl4030,
+       .codec_data = &twl4030_setup,
+};
+
+static struct platform_device *zoom2_snd_device;
+
+static int __init zoom2_soc_init(void)
+{
+       int ret;
+
+       if (!machine_is_omap_zoom2()) {
+               pr_debug("Not Zoom2!\n");
+               return -ENODEV;
+       }
+       printk(KERN_INFO "Zoom2 SoC init\n");
+
+       zoom2_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!zoom2_snd_device) {
+               printk(KERN_ERR "Platform device allocation failed\n");
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(zoom2_snd_device, &zoom2_snd_devdata);
+       zoom2_snd_devdata.dev = &zoom2_snd_device->dev;
+       *(unsigned int *)zoom2_dai[0].cpu_dai->private_data = 1; /* McBSP2 */
+       *(unsigned int *)zoom2_dai[1].cpu_dai->private_data = 2; /* McBSP3 */
+
+       ret = platform_device_add(zoom2_snd_device);
+       if (ret)
+               goto err1;
+
+       BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0);
+       gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0);
+
+       BUG_ON(gpio_request(ZOOM2_HEADSET_EXTMUTE_GPIO, "ext_mute") < 0);
+       gpio_direction_output(ZOOM2_HEADSET_EXTMUTE_GPIO, 0);
+
+       return 0;
+
+err1:
+       printk(KERN_ERR "Unable to add platform device\n");
+       platform_device_put(zoom2_snd_device);
+
+       return ret;
+}
+module_init(zoom2_soc_init);
+
+static void __exit zoom2_soc_exit(void)
+{
+       gpio_free(ZOOM2_HEADSET_MUX_GPIO);
+       gpio_free(ZOOM2_HEADSET_EXTMUTE_GPIO);
+
+       platform_device_unregister(zoom2_snd_device);
+}
+module_exit(zoom2_soc_exit);
+
+MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
+MODULE_DESCRIPTION("ALSA SoC Zoom2");
+MODULE_LICENSE("GPL");
+
index 6375b4ea525dc572ca4feae6a8b69db703ecce1a..dcb3181bb3406a66fc1c5843a8b9be743a87fc78 100644 (file)
@@ -138,7 +138,7 @@ config SND_PXA2XX_SOC_MIOA701
 
 config SND_PXA2XX_SOC_IMOTE2
        tristate "SoC Audio support for IMote 2"
-       depends on SND_PXA2XX_SOC && MACH_INTELMOTE2
+       depends on SND_PXA2XX_SOC && MACH_INTELMOTE2 && I2C
        select SND_PXA2XX_SOC_I2S
        select SND_SOC_WM8940
        help
index 326955dea36cef8fb6cc3fdb05e7516e7b05e578..9f7c61e23dafbdf597a84779b231878cf6d9b12a 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/i2c.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
+#include <sound/uda1380.h>
 
 #include <mach/magician.h>
 #include <asm/mach-types.h>
@@ -188,7 +190,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
        if (ret < 0)
                return ret;
 
-       ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1);
+       ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 0, 1, width);
        if (ret < 0)
                return ret;
 
@@ -447,34 +449,47 @@ static struct snd_soc_card snd_soc_card_magician = {
        .platform = &pxa2xx_soc_platform,
 };
 
-/* magician audio private data */
-static struct uda1380_setup_data magician_uda1380_setup = {
-       .i2c_address = 0x18,
-       .dac_clk = UDA1380_DAC_CLK_WSPLL,
-};
-
 /* magician audio subsystem */
 static struct snd_soc_device magician_snd_devdata = {
        .card = &snd_soc_card_magician,
        .codec_dev = &soc_codec_dev_uda1380,
-       .codec_data = &magician_uda1380_setup,
 };
 
 static struct platform_device *magician_snd_device;
 
+/*
+ * FIXME: move into magician board file once merged into the pxa tree
+ */
+static struct uda1380_platform_data uda1380_info = {
+       .gpio_power = EGPIO_MAGICIAN_CODEC_POWER,
+       .gpio_reset = EGPIO_MAGICIAN_CODEC_RESET,
+       .dac_clk    = UDA1380_DAC_CLK_WSPLL,
+};
+
+static struct i2c_board_info i2c_board_info[] = {
+       {
+               I2C_BOARD_INFO("uda1380", 0x18),
+               .platform_data = &uda1380_info,
+       },
+};
+
 static int __init magician_init(void)
 {
        int ret;
+       struct i2c_adapter *adapter;
+       struct i2c_client *client;
 
        if (!machine_is_magician())
                return -ENODEV;
 
-       ret = gpio_request(EGPIO_MAGICIAN_CODEC_POWER, "CODEC_POWER");
-       if (ret)
-               goto err_request_power;
-       ret = gpio_request(EGPIO_MAGICIAN_CODEC_RESET, "CODEC_RESET");
-       if (ret)
-               goto err_request_reset;
+       adapter = i2c_get_adapter(0);
+       if (!adapter)
+               return -ENODEV;
+       client = i2c_new_device(adapter, i2c_board_info);
+       i2c_put_adapter(adapter);
+       if (!client)
+               return -ENODEV;
+
        ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER");
        if (ret)
                goto err_request_spk;
@@ -491,14 +506,8 @@ static int __init magician_init(void)
        if (ret)
                goto err_request_in_sel1;
 
-       gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 1);
        gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0);
 
-       /* we may need to have the clock running here - pH5 */
-       gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 1);
-       udelay(5);
-       gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 0);
-
        magician_snd_device = platform_device_alloc("soc-audio", -1);
        if (!magician_snd_device) {
                ret = -ENOMEM;
@@ -526,10 +535,6 @@ err_request_mic:
 err_request_ep:
        gpio_free(EGPIO_MAGICIAN_SPK_POWER);
 err_request_spk:
-       gpio_free(EGPIO_MAGICIAN_CODEC_RESET);
-err_request_reset:
-       gpio_free(EGPIO_MAGICIAN_CODEC_POWER);
-err_request_power:
        return ret;
 }
 
@@ -540,15 +545,12 @@ static void __exit magician_exit(void)
        gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0);
        gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0);
        gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0);
-       gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 0);
 
        gpio_free(EGPIO_MAGICIAN_IN_SEL1);
        gpio_free(EGPIO_MAGICIAN_IN_SEL0);
        gpio_free(EGPIO_MAGICIAN_MIC_POWER);
        gpio_free(EGPIO_MAGICIAN_EP_POWER);
        gpio_free(EGPIO_MAGICIAN_SPK_POWER);
-       gpio_free(EGPIO_MAGICIAN_CODEC_RESET);
-       gpio_free(EGPIO_MAGICIAN_CODEC_POWER);
 }
 
 module_init(magician_init);
index e6102fda0a7fbbe55fb654a80ebe04e668acd173..1f96e3227be51920fbc011e2f9adaeba3e0fad31 100644 (file)
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 #include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <sound/soc-dapm.h>
+#include <sound/jack.h>
 
 #include <asm/mach-types.h>
 #include <mach/audio.h>
 #include "pxa2xx-pcm.h"
 #include "pxa2xx-ac97.h"
 
-static int palm27x_jack_func = 1;
-static int palm27x_spk_func = 1;
-static int palm27x_ep_gpio = -1;
+static struct snd_soc_jack hs_jack;
 
-static void palm27x_ext_control(struct snd_soc_codec *codec)
-{
-       if (!palm27x_spk_func)
-               snd_soc_dapm_enable_pin(codec, "Speaker");
-       else
-               snd_soc_dapm_disable_pin(codec, "Speaker");
-
-       if (!palm27x_jack_func)
-               snd_soc_dapm_enable_pin(codec, "Headphone Jack");
-       else
-               snd_soc_dapm_disable_pin(codec, "Headphone Jack");
-
-       snd_soc_dapm_sync(codec);
-}
-
-static int palm27x_startup(struct snd_pcm_substream *substream)
-{
-       struct snd_soc_pcm_runtime *rtd = substream->private_data;
-       struct snd_soc_codec *codec = rtd->socdev->card->codec;
-
-       /* check the jack status at stream startup */
-       palm27x_ext_control(codec);
-       return 0;
-}
-
-static struct snd_soc_ops palm27x_ops = {
-       .startup = palm27x_startup,
+/* Headphones jack detection DAPM pins */
+static struct snd_soc_jack_pin hs_jack_pins[] = {
+       {
+               .pin    = "Headphone Jack",
+               .mask   = SND_JACK_HEADPHONE,
+       },
 };
 
-static irqreturn_t palm27x_interrupt(int irq, void *v)
-{
-       palm27x_spk_func = gpio_get_value(palm27x_ep_gpio);
-       palm27x_jack_func = !palm27x_spk_func;
-       return IRQ_HANDLED;
-}
-
-static int palm27x_get_jack(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       ucontrol->value.integer.value[0] = palm27x_jack_func;
-       return 0;
-}
-
-static int palm27x_set_jack(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
-
-       if (palm27x_jack_func == ucontrol->value.integer.value[0])
-               return 0;
-
-       palm27x_jack_func = ucontrol->value.integer.value[0];
-       palm27x_ext_control(codec);
-       return 1;
-}
-
-static int palm27x_get_spk(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       ucontrol->value.integer.value[0] = palm27x_spk_func;
-       return 0;
-}
-
-static int palm27x_set_spk(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
-
-       if (palm27x_spk_func == ucontrol->value.integer.value[0])
-               return 0;
-
-       palm27x_spk_func = ucontrol->value.integer.value[0];
-       palm27x_ext_control(codec);
-       return 1;
-}
+/* Headphones jack detection gpios */
+static struct snd_soc_jack_gpio hs_jack_gpios[] = {
+       [0] = {
+               /* gpio is set on per-platform basis */
+               .name           = "hp-gpio",
+               .report         = SND_JACK_HEADPHONE,
+               .debounce_time  = 200,
+       },
+};
 
-/* PalmTX machine dapm widgets */
+/* Palm27x machine dapm widgets */
 static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = {
        SND_SOC_DAPM_HP("Headphone Jack", NULL),
-       SND_SOC_DAPM_SPK("Speaker", NULL),
+       SND_SOC_DAPM_SPK("Ext. Speaker", NULL),
+       SND_SOC_DAPM_MIC("Ext. Microphone", NULL),
 };
 
 /* PalmTX audio map */
@@ -126,46 +66,66 @@ static const struct snd_soc_dapm_route audio_map[] = {
        {"Headphone Jack", NULL, "HPOUTR"},
 
        /* ext speaker connected to ROUT2, LOUT2 */
-       {"Speaker", NULL, "LOUT2"},
-       {"Speaker", NULL, "ROUT2"},
-};
+       {"Ext. Speaker", NULL, "LOUT2"},
+       {"Ext. Speaker", NULL, "ROUT2"},
 
-static const char *jack_function[] = {"Headphone", "Off"};
-static const char *spk_function[] = {"On", "Off"};
-static const struct soc_enum palm27x_enum[] = {
-       SOC_ENUM_SINGLE_EXT(2, jack_function),
-       SOC_ENUM_SINGLE_EXT(2, spk_function),
+       /* mic connected to MIC1 */
+       {"Ext. Microphone", NULL, "MIC1"},
 };
 
-static const struct snd_kcontrol_new palm27x_controls[] = {
-       SOC_ENUM_EXT("Jack Function", palm27x_enum[0], palm27x_get_jack,
-               palm27x_set_jack),
-       SOC_ENUM_EXT("Speaker Function", palm27x_enum[1], palm27x_get_spk,
-               palm27x_set_spk),
-};
+static struct snd_soc_card palm27x_asoc;
 
 static int palm27x_ac97_init(struct snd_soc_codec *codec)
 {
        int err;
 
+       /* add palm27x specific widgets */
+       err = snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets,
+                               ARRAY_SIZE(palm27x_dapm_widgets));
+       if (err)
+               return err;
+
+       /* set up palm27x specific audio path audio_map */
+       err = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+       if (err)
+               return err;
+
+       /* connected pins */
+       if (machine_is_palmld())
+               snd_soc_dapm_enable_pin(codec, "MIC1");
+       snd_soc_dapm_enable_pin(codec, "HPOUTL");
+       snd_soc_dapm_enable_pin(codec, "HPOUTR");
+       snd_soc_dapm_enable_pin(codec, "LOUT2");
+       snd_soc_dapm_enable_pin(codec, "ROUT2");
+
+       /* not connected pins */
        snd_soc_dapm_nc_pin(codec, "OUT3");
        snd_soc_dapm_nc_pin(codec, "MONOOUT");
+       snd_soc_dapm_nc_pin(codec, "LINEINL");
+       snd_soc_dapm_nc_pin(codec, "LINEINR");
+       snd_soc_dapm_nc_pin(codec, "PCBEEP");
+       snd_soc_dapm_nc_pin(codec, "PHONE");
+       snd_soc_dapm_nc_pin(codec, "MIC2");
+
+       err = snd_soc_dapm_sync(codec);
+       if (err)
+               return err;
 
-       /* add palm27x specific controls */
-       err = snd_soc_add_controls(codec, palm27x_controls,
-                               ARRAY_SIZE(palm27x_controls));
-       if (err < 0)
+       /* Jack detection API stuff */
+       err = snd_soc_jack_new(&palm27x_asoc, "Headphone Jack",
+                               SND_JACK_HEADPHONE, &hs_jack);
+       if (err)
                return err;
 
-       /* add palm27x specific widgets */
-       snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets,
-                               ARRAY_SIZE(palm27x_dapm_widgets));
+       err = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
+                               hs_jack_pins);
+       if (err)
+               return err;
 
-       /* set up palm27x specific audio path audio_map */
-       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+       err = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios),
+                               hs_jack_gpios);
 
-       snd_soc_dapm_sync(codec);
-       return 0;
+       return err;
 }
 
 static struct snd_soc_dai_link palm27x_dai[] = {
@@ -175,14 +135,12 @@ static struct snd_soc_dai_link palm27x_dai[] = {
        .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
        .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
        .init = palm27x_ac97_init,
-       .ops = &palm27x_ops,
 },
 {
        .name = "AC97 Aux",
        .stream_name = "AC97 Aux",
        .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
        .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
-       .ops = &palm27x_ops,
 },
 };
 
@@ -208,27 +166,17 @@ static int palm27x_asoc_probe(struct platform_device *pdev)
                machine_is_palmld() || machine_is_palmte2()))
                return -ENODEV;
 
-       if (pdev->dev.platform_data)
-               palm27x_ep_gpio = ((struct palm27x_asoc_info *)
-                       (pdev->dev.platform_data))->jack_gpio;
-
-       ret = gpio_request(palm27x_ep_gpio, "Headphone Jack");
-       if (ret)
-               return ret;
-       ret = gpio_direction_input(palm27x_ep_gpio);
-       if (ret)
-               goto err_alloc;
+       if (!pdev->dev.platform_data) {
+               dev_err(&pdev->dev, "please supply platform_data\n");
+               return -ENODEV;
+       }
 
-       if (request_irq(gpio_to_irq(palm27x_ep_gpio), palm27x_interrupt,
-                       IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-                       "Headphone jack", NULL))
-               goto err_alloc;
+       hs_jack_gpios[0].gpio = ((struct palm27x_asoc_info *)
+                       (pdev->dev.platform_data))->jack_gpio;
 
        palm27x_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!palm27x_snd_device) {
-               ret = -ENOMEM;
-               goto err_dev;
-       }
+       if (!palm27x_snd_device)
+               return -ENOMEM;
 
        platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata);
        palm27x_snd_devdata.dev = &palm27x_snd_device->dev;
@@ -241,18 +189,12 @@ static int palm27x_asoc_probe(struct platform_device *pdev)
 
 put_device:
        platform_device_put(palm27x_snd_device);
-err_dev:
-       free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
-err_alloc:
-       gpio_free(palm27x_ep_gpio);
 
        return ret;
 }
 
 static int __devexit palm27x_asoc_remove(struct platform_device *pdev)
 {
-       free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
-       gpio_free(palm27x_ep_gpio);
        platform_device_unregister(palm27x_snd_device);
        return 0;
 }
index 19c45409d94c10257548fff8219395f833412fac..5b9ed64647898c028f723138ba9789251c8416e6 100644 (file)
@@ -375,21 +375,34 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai,
  * Set the active slots in TDM/Network mode
  */
 static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
-       unsigned int mask, int slots)
+       unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
 {
        struct ssp_priv *priv = cpu_dai->private_data;
        struct ssp_device *ssp = priv->dev.ssp;
        u32 sscr0;
 
-       sscr0 = ssp_read_reg(ssp, SSCR0) & ~SSCR0_SlotsPerFrm(7);
+       sscr0 = ssp_read_reg(ssp, SSCR0);
+       sscr0 &= ~(SSCR0_MOD | SSCR0_SlotsPerFrm(8) | SSCR0_EDSS | SSCR0_DSS);
+
+       /* set slot width */
+       if (slot_width > 16)
+               sscr0 |= SSCR0_EDSS | SSCR0_DataSize(slot_width - 16);
+       else
+               sscr0 |= SSCR0_DataSize(slot_width);
+
+       if (slots > 1) {
+               /* enable network mode */
+               sscr0 |= SSCR0_MOD;
 
-       /* set number of active slots */
-       sscr0 |= SSCR0_SlotsPerFrm(slots);
+               /* set number of active slots */
+               sscr0 |= SSCR0_SlotsPerFrm(slots);
+
+               /* set active slot mask */
+               ssp_write_reg(ssp, SSTSA, tx_mask);
+               ssp_write_reg(ssp, SSRSA, rx_mask);
+       }
        ssp_write_reg(ssp, SSCR0, sscr0);
 
-       /* set active slot mask */
-       ssp_write_reg(ssp, SSTSA, mask);
-       ssp_write_reg(ssp, SSRSA, mask);
        return 0;
 }
 
@@ -457,31 +470,27 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                return -EINVAL;
        }
 
-       ssp_write_reg(ssp, SSCR0, sscr0);
-       ssp_write_reg(ssp, SSCR1, sscr1);
-       ssp_write_reg(ssp, SSPSP, sspsp);
+       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       case SND_SOC_DAIFMT_NB_NF:
+               sspsp |= SSPSP_SFRMP;
+               break;
+       case SND_SOC_DAIFMT_NB_IF:
+               break;
+       case SND_SOC_DAIFMT_IB_IF:
+               sspsp |= SSPSP_SCMODE(2);
+               break;
+       case SND_SOC_DAIFMT_IB_NF:
+               sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
+               break;
+       default:
+               return -EINVAL;
+       }
 
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
                sscr0 |= SSCR0_PSP;
                sscr1 |= SSCR1_RWOT | SSCR1_TRAIL;
-
                /* See hw_params() */
-               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-               case SND_SOC_DAIFMT_NB_NF:
-                       sspsp |= SSPSP_SFRMP;
-                       break;
-               case SND_SOC_DAIFMT_NB_IF:
-                       break;
-               case SND_SOC_DAIFMT_IB_IF:
-                       sspsp |= SSPSP_SCMODE(2);
-                       break;
-               case SND_SOC_DAIFMT_IB_NF:
-                       sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
-                       break;
-               default:
-                       return -EINVAL;
-               }
                break;
 
        case SND_SOC_DAIFMT_DSP_A:
@@ -489,22 +498,6 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        case SND_SOC_DAIFMT_DSP_B:
                sscr0 |= SSCR0_MOD | SSCR0_PSP;
                sscr1 |= SSCR1_TRAIL | SSCR1_RWOT;
-
-               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-               case SND_SOC_DAIFMT_NB_NF:
-                       sspsp |= SSPSP_SFRMP;
-                       break;
-               case SND_SOC_DAIFMT_NB_IF:
-                       break;
-               case SND_SOC_DAIFMT_IB_IF:
-                       sspsp |= SSPSP_SCMODE(2);
-                       break;
-               case SND_SOC_DAIFMT_IB_NF:
-                       sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP;
-                       break;
-               default:
-                       return -EINVAL;
-               }
                break;
 
        default:
index d9c94d71fa617dcb859a3f396868b135cf67b645..e9ae7b3a7e006cc33cc74e128f9f1429f3ebc9ac 100644 (file)
@@ -22,6 +22,7 @@
 #include <mach/hardware.h>
 #include <mach/regs-ac97.h>
 #include <mach/dma.h>
+#include <mach/audio.h>
 
 #include "pxa2xx-pcm.h"
 #include "pxa2xx-ac97.h"
@@ -241,9 +242,18 @@ EXPORT_SYMBOL_GPL(soc_ac97_ops);
 static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev)
 {
        int i;
+       pxa2xx_audio_ops_t *pdata = pdev->dev.platform_data;
 
-       for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++)
+       if (pdev->id >= 0) {
+               dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n");
+               return -ENXIO;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) {
                pxa_ac97_dai[i].dev = &pdev->dev;
+               if (pdata && pdata->codec_pdata[0])
+                       pxa_ac97_dai[i].ac97_pdata = pdata->codec_pdata[0];
+       }
 
        /* Punt most of the init to the SoC probe; we may need the machine
         * driver to do interesting things with the clocking to get us up
index 4743e262895d9f1068260762ca6c4f64df5dd17d..6b8f655d1ad826d7556317b17e1f1074fa7e49f3 100644 (file)
@@ -167,6 +167,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
 
        BUG_ON(IS_ERR(clk_i2s));
        clk_enable(clk_i2s);
+       dai->private_data = dai;
        pxa_i2s_wait();
 
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -255,7 +256,10 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
        if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) {
                SACR0 &= ~SACR0_ENB;
                pxa_i2s_wait();
-               clk_disable(clk_i2s);
+               if (dai->private_data != NULL) {
+                       clk_disable(clk_i2s);
+                       dai->private_data = NULL;
+               }
        }
 }
 
@@ -336,6 +340,7 @@ static int pxa2xx_i2s_probe(struct platform_device *dev)
                return PTR_ERR(clk_i2s);
 
        pxa_i2s_dai.dev = &dev->dev;
+       pxa_i2s_dai.private_data = NULL;
        ret = snd_soc_register_dai(&pxa_i2s_dai);
        if (ret != 0)
                clk_put(clk_i2s);
index df494d1e346f9197b11864a13ad456384c516871..923428fc1adb9184b5b42d54fd9fcaf50144afeb 100644 (file)
@@ -1,6 +1,7 @@
 config SND_S3C24XX_SOC
        tristate "SoC Audio for the Samsung S3CXXXX chips"
-       depends on ARCH_S3C2410
+       depends on ARCH_S3C2410 || ARCH_S3C64XX
+       select S3C64XX_DMA if ARCH_S3C64XX
        help
          Say Y or M if you want to add support for codecs attached to
          the S3C24XX AC97 or I2S interfaces. You will also need to
@@ -38,6 +39,15 @@ config SND_S3C24XX_SOC_NEO1973_WM8753
          Say Y if you want to add support for SoC audio on smdk2440
          with the WM8753.
 
+config SND_S3C24XX_SOC_NEO1973_GTA02_WM8753
+       tristate "Audio support for the Openmoko Neo FreeRunner (GTA02)"
+       depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA02
+       select SND_S3C24XX_SOC_I2S
+       select SND_SOC_WM8753
+       help
+         This driver provides audio support for the Openmoko Neo FreeRunner
+         smartphone.
+         
 config SND_S3C24XX_SOC_JIVE_WM8750
        tristate "SoC I2S Audio support for Jive"
        depends on SND_S3C24XX_SOC && MACH_JIVE
@@ -57,7 +67,7 @@ config SND_S3C24XX_SOC_SMDK2443_WM9710
 
 config SND_S3C24XX_SOC_LN2440SBC_ALC650
        tristate "SoC AC97 Audio support for LN2440SBC - ALC650"
-       depends on SND_S3C24XX_SOC
+       depends on SND_S3C24XX_SOC && ARCH_S3C2410
        select SND_S3C2443_SOC_AC97
        select SND_SOC_AC97_CODEC
        help
@@ -66,7 +76,26 @@ config SND_S3C24XX_SOC_LN2440SBC_ALC650
 
 config SND_S3C24XX_SOC_S3C24XX_UDA134X
        tristate "SoC I2S Audio support UDA134X wired to a S3C24XX"
-               depends on SND_S3C24XX_SOC
+               depends on SND_S3C24XX_SOC && ARCH_S3C2410
                select SND_S3C24XX_SOC_I2S
        select SND_SOC_L3
                select SND_SOC_UDA134X
+
+config SND_S3C24XX_SOC_SIMTEC
+       tristate
+       help
+         Internal node for common S3C24XX/Simtec suppor
+
+config SND_S3C24XX_SOC_SIMTEC_TLV320AIC23
+       tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards"
+       depends on SND_S3C24XX_SOC && ARCH_S3C2410
+       select SND_S3C24XX_SOC_I2S
+       select SND_SOC_TLV320AIC23
+       select SND_S3C24XX_SOC_SIMTEC
+
+config SND_S3C24XX_SOC_SIMTEC_HERMES
+       tristate "SoC I2S Audio support for Simtec Hermes board"
+       depends on SND_S3C24XX_SOC && ARCH_S3C2410
+       select SND_S3C24XX_SOC_I2S
+       select SND_SOC_TLV320AIC3X
+       select SND_S3C24XX_SOC_SIMTEC
index 07a93a2ebe5f35ca92062b4b44e972207829dc87..99f5a7dd3fc667b3fd1bc4703651839e586bac0e 100644 (file)
@@ -16,12 +16,21 @@ obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
 # S3C24XX Machine Support
 snd-soc-jive-wm8750-objs := jive_wm8750.o
 snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
+snd-soc-neo1973-gta02-wm8753-objs := neo1973_gta02_wm8753.o
 snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
 snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
 snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
+snd-soc-s3c24xx-simtec-objs := s3c24xx_simtec.o
+snd-soc-s3c24xx-simtec-hermes-objs := s3c24xx_simtec_hermes.o
+snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o
 
 obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o
 obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
+obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753) += snd-soc-neo1973-gta02-wm8753.o
 obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
 obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
 obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
+obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC) += snd-soc-s3c24xx-simtec.o
+obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o
+obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o
+
diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
new file mode 100644 (file)
index 0000000..0c52e36
--- /dev/null
@@ -0,0 +1,498 @@
+/*
+ * neo1973_gta02_wm8753.c  --  SoC audio for Openmoko Freerunner(GTA02)
+ *
+ * Copyright 2007 Openmoko Inc
+ * Author: Graeme Gregory <graeme@openmoko.org>
+ * Copyright 2007 Wolfson Microelectronics PLC.
+ * Author: Graeme Gregory <linux@wolfsonmicro.com>
+ * Copyright 2009 Wolfson Microelectronics
+ *
+ *  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/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <asm/mach-types.h>
+
+#include <plat/regs-iis.h>
+
+#include <mach/regs-clock.h>
+#include <asm/io.h>
+#include <mach/gta02.h>
+#include "../codecs/wm8753.h"
+#include "s3c24xx-pcm.h"
+#include "s3c24xx-i2s.h"
+
+static struct snd_soc_card neo1973_gta02;
+
+static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       unsigned int pll_out = 0, bclk = 0;
+       int ret = 0;
+       unsigned long iis_clkrate;
+
+       iis_clkrate = s3c24xx_i2s_get_clockrate();
+
+       switch (params_rate(params)) {
+       case 8000:
+       case 16000:
+               pll_out = 12288000;
+               break;
+       case 48000:
+               bclk = WM8753_BCLK_DIV_4;
+               pll_out = 12288000;
+               break;
+       case 96000:
+               bclk = WM8753_BCLK_DIV_2;
+               pll_out = 12288000;
+               break;
+       case 11025:
+               bclk = WM8753_BCLK_DIV_16;
+               pll_out = 11289600;
+               break;
+       case 22050:
+               bclk = WM8753_BCLK_DIV_8;
+               pll_out = 11289600;
+               break;
+       case 44100:
+               bclk = WM8753_BCLK_DIV_4;
+               pll_out = 11289600;
+               break;
+       case 88200:
+               bclk = WM8753_BCLK_DIV_2;
+               pll_out = 11289600;
+               break;
+       }
+
+       /* set codec DAI configuration */
+       ret = snd_soc_dai_set_fmt(codec_dai,
+               SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+               SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0)
+               return ret;
+
+       /* set cpu DAI configuration */
+       ret = snd_soc_dai_set_fmt(cpu_dai,
+               SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+               SND_SOC_DAIFMT_CBM_CFM);
+       if (ret < 0)
+               return ret;
+
+       /* set the codec system clock for DAC and ADC */
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
+               SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               return ret;
+
+       /* set MCLK division for sample rate */
+       ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
+               S3C2410_IISMOD_32FS);
+       if (ret < 0)
+               return ret;
+
+       /* set codec BCLK division for sample rate */
+       ret = snd_soc_dai_set_clkdiv(codec_dai,
+                                       WM8753_BCLKDIV, bclk);
+       if (ret < 0)
+               return ret;
+
+       /* set prescaler division for sample rate */
+       ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
+               S3C24XX_PRESCALE(4, 4));
+       if (ret < 0)
+               return ret;
+
+       /* codec PLL input is PCLK/4 */
+       ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1,
+               iis_clkrate / 4, pll_out);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+
+       /* disable the PLL */
+       return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0);
+}
+
+/*
+ * Neo1973 WM8753 HiFi DAI opserations.
+ */
+static struct snd_soc_ops neo1973_gta02_hifi_ops = {
+       .hw_params = neo1973_gta02_hifi_hw_params,
+       .hw_free = neo1973_gta02_hifi_hw_free,
+};
+
+static int neo1973_gta02_voice_hw_params(
+       struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       unsigned int pcmdiv = 0;
+       int ret = 0;
+       unsigned long iis_clkrate;
+
+       iis_clkrate = s3c24xx_i2s_get_clockrate();
+
+       if (params_rate(params) != 8000)
+               return -EINVAL;
+       if (params_channels(params) != 1)
+               return -EINVAL;
+
+       pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
+
+       /* todo: gg check mode (DSP_B) against CSR datasheet */
+       /* set codec DAI configuration */
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
+               SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
+       if (ret < 0)
+               return ret;
+
+       /* set the codec system clock for DAC and ADC */
+       ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK,
+               12288000, SND_SOC_CLOCK_IN);
+       if (ret < 0)
+               return ret;
+
+       /* set codec PCM division for sample rate */
+       ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV,
+                                       pcmdiv);
+       if (ret < 0)
+               return ret;
+
+       /* configue and enable PLL for 12.288MHz output */
+       ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2,
+               iis_clkrate / 4, 12288000);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+
+       /* disable the PLL */
+       return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0);
+}
+
+static struct snd_soc_ops neo1973_gta02_voice_ops = {
+       .hw_params = neo1973_gta02_voice_hw_params,
+       .hw_free = neo1973_gta02_voice_hw_free,
+};
+
+#define LM4853_AMP 1
+#define LM4853_SPK 2
+
+static u8 lm4853_state;
+
+/* This has no effect, it exists only to maintain compatibility with
+ * existing ALSA state files.
+ */
+static int lm4853_set_state(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       int val = ucontrol->value.integer.value[0];
+
+       if (val)
+               lm4853_state |= LM4853_AMP;
+       else
+               lm4853_state &= ~LM4853_AMP;
+
+       return 0;
+}
+
+static int lm4853_get_state(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.integer.value[0] = lm4853_state & LM4853_AMP;
+
+       return 0;
+}
+
+static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       int val = ucontrol->value.integer.value[0];
+
+       if (val) {
+               lm4853_state |= LM4853_SPK;
+               gpio_set_value(GTA02_GPIO_HP_IN, 0);
+       } else {
+               lm4853_state &= ~LM4853_SPK;
+               gpio_set_value(GTA02_GPIO_HP_IN, 1);
+       }
+
+       return 0;
+}
+
+static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.integer.value[0] = (lm4853_state & LM4853_SPK) >> 1;
+
+       return 0;
+}
+
+static int lm4853_event(struct snd_soc_dapm_widget *w,
+                       struct snd_kcontrol *k,
+                       int event)
+{
+       gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(value));
+
+       return 0;
+}
+
+static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
+       SND_SOC_DAPM_SPK("Stereo Out", lm4853_event),
+       SND_SOC_DAPM_LINE("GSM Line Out", NULL),
+       SND_SOC_DAPM_LINE("GSM Line In", NULL),
+       SND_SOC_DAPM_MIC("Headset Mic", NULL),
+       SND_SOC_DAPM_MIC("Handset Mic", NULL),
+       SND_SOC_DAPM_SPK("Handset Spk", NULL),
+};
+
+
+/* example machine audio_mapnections */
+static const struct snd_soc_dapm_route audio_map[] = {
+
+       /* Connections to the lm4853 amp */
+       {"Stereo Out", NULL, "LOUT1"},
+       {"Stereo Out", NULL, "ROUT1"},
+
+       /* Connections to the GSM Module */
+       {"GSM Line Out", NULL, "MONO1"},
+       {"GSM Line Out", NULL, "MONO2"},
+       {"RXP", NULL, "GSM Line In"},
+       {"RXN", NULL, "GSM Line In"},
+
+       /* Connections to Headset */
+       {"MIC1", NULL, "Mic Bias"},
+       {"Mic Bias", NULL, "Headset Mic"},
+
+       /* Call Mic */
+       {"MIC2", NULL, "Mic Bias"},
+       {"MIC2N", NULL, "Mic Bias"},
+       {"Mic Bias", NULL, "Handset Mic"},
+
+       /* Call Speaker */
+       {"Handset Spk", NULL, "LOUT2"},
+       {"Handset Spk", NULL, "ROUT2"},
+
+       /* Connect the ALC pins */
+       {"ACIN", NULL, "ACOP"},
+};
+
+static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = {
+       SOC_DAPM_PIN_SWITCH("Stereo Out"),
+       SOC_DAPM_PIN_SWITCH("GSM Line Out"),
+       SOC_DAPM_PIN_SWITCH("GSM Line In"),
+       SOC_DAPM_PIN_SWITCH("Headset Mic"),
+       SOC_DAPM_PIN_SWITCH("Handset Mic"),
+       SOC_DAPM_PIN_SWITCH("Handset Spk"),
+
+       /* This has no effect, it exists only to maintain compatibility with
+        * existing ALSA state files.
+        */
+       SOC_SINGLE_EXT("Amp State Switch", 6, 0, 1, 0,
+               lm4853_get_state,
+               lm4853_set_state),
+       SOC_SINGLE_EXT("Amp Spk Switch", 7, 0, 1, 0,
+               lm4853_get_spk,
+               lm4853_set_spk),
+};
+
+/*
+ * This is an example machine initialisation for a wm8753 connected to a
+ * neo1973 GTA02.
+ */
+static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
+{
+       int err;
+
+       /* set up NC codec pins */
+       snd_soc_dapm_nc_pin(codec, "OUT3");
+       snd_soc_dapm_nc_pin(codec, "OUT4");
+       snd_soc_dapm_nc_pin(codec, "LINE1");
+       snd_soc_dapm_nc_pin(codec, "LINE2");
+
+       /* Add neo1973 gta02 specific widgets */
+       snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
+                                 ARRAY_SIZE(wm8753_dapm_widgets));
+
+       /* add neo1973 gta02 specific controls */
+       err = snd_soc_add_controls(codec, wm8753_neo1973_gta02_controls,
+               ARRAY_SIZE(wm8753_neo1973_gta02_controls));
+
+       if (err < 0)
+               return err;
+
+       /* set up neo1973 gta02 specific audio path audio_map */
+       snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
+
+       /* set endpoints to default off mode */
+       snd_soc_dapm_disable_pin(codec, "Stereo Out");
+       snd_soc_dapm_disable_pin(codec, "GSM Line Out");
+       snd_soc_dapm_disable_pin(codec, "GSM Line In");
+       snd_soc_dapm_disable_pin(codec, "Headset Mic");
+       snd_soc_dapm_disable_pin(codec, "Handset Mic");
+       snd_soc_dapm_disable_pin(codec, "Handset Spk");
+
+       snd_soc_dapm_sync(codec);
+
+       return 0;
+}
+
+/*
+ * BT Codec DAI
+ */
+static struct snd_soc_dai bt_dai = {
+       .name = "Bluetooth",
+       .id = 0,
+       .playback = {
+               .channels_min = 1,
+               .channels_max = 1,
+               .rates = SNDRV_PCM_RATE_8000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+       .capture = {
+               .channels_min = 1,
+               .channels_max = 1,
+               .rates = SNDRV_PCM_RATE_8000,
+               .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+};
+
+static struct snd_soc_dai_link neo1973_gta02_dai[] = {
+{ /* Hifi Playback - for similatious use with voice below */
+       .name = "WM8753",
+       .stream_name = "WM8753 HiFi",
+       .cpu_dai = &s3c24xx_i2s_dai,
+       .codec_dai = &wm8753_dai[WM8753_DAI_HIFI],
+       .init = neo1973_gta02_wm8753_init,
+       .ops = &neo1973_gta02_hifi_ops,
+},
+{ /* Voice via BT */
+       .name = "Bluetooth",
+       .stream_name = "Voice",
+       .cpu_dai = &bt_dai,
+       .codec_dai = &wm8753_dai[WM8753_DAI_VOICE],
+       .ops = &neo1973_gta02_voice_ops,
+},
+};
+
+static struct snd_soc_card neo1973_gta02 = {
+       .name = "neo1973-gta02",
+       .platform = &s3c24xx_soc_platform,
+       .dai_link = neo1973_gta02_dai,
+       .num_links = ARRAY_SIZE(neo1973_gta02_dai),
+};
+
+static struct snd_soc_device neo1973_gta02_snd_devdata = {
+       .card = &neo1973_gta02,
+       .codec_dev = &soc_codec_dev_wm8753,
+};
+
+static struct platform_device *neo1973_gta02_snd_device;
+
+static int __init neo1973_gta02_init(void)
+{
+       int ret;
+
+       if (!machine_is_neo1973_gta02()) {
+               printk(KERN_INFO
+                      "Only GTA02 is supported by this ASoC driver\n");
+               return -ENODEV;
+       }
+
+       /* register bluetooth DAI here */
+       ret = snd_soc_register_dai(&bt_dai);
+       if (ret)
+               return ret;
+
+       neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!neo1973_gta02_snd_device)
+               return -ENOMEM;
+
+       platform_set_drvdata(neo1973_gta02_snd_device,
+                       &neo1973_gta02_snd_devdata);
+       neo1973_gta02_snd_devdata.dev = &neo1973_gta02_snd_device->dev;
+       ret = platform_device_add(neo1973_gta02_snd_device);
+
+       if (ret) {
+               platform_device_put(neo1973_gta02_snd_device);
+               return ret;
+       }
+
+       /* Initialise GPIOs used by amp */
+       ret = gpio_request(GTA02_GPIO_HP_IN, "GTA02_HP_IN");
+       if (ret) {
+               pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_HP_IN);
+               goto err_unregister_device;
+       }
+
+       ret = gpio_direction_output(GTA02_GPIO_AMP_HP_IN, 1);
+       if (ret) {
+               pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN);
+               goto err_free_gpio_hp_in;
+       }
+
+       ret = gpio_request(GTA02_GPIO_AMP_SHUT, "GTA02_AMP_SHUT");
+       if (ret) {
+               pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_AMP_SHUT);
+               goto err_free_gpio_hp_in;
+       }
+
+       ret = gpio_direction_output(GTA02_GPIO_AMP_SHUT, 1);
+       if (ret) {
+               pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_AMP_SHUT);
+               goto err_free_gpio_amp_shut;
+       }
+
+       return 0;
+
+err_free_gpio_amp_shut:
+       gpio_free(GTA02_GPIO_AMP_SHUT);
+err_free_gpio_hp_in:
+       gpio_free(GTA02_GPIO_HP_IN);
+err_unregister_device:
+       platform_device_unregister(neo1973_gta02_snd_device);
+       return ret;
+}
+module_init(neo1973_gta02_init);
+
+static void __exit neo1973_gta02_exit(void)
+{
+       snd_soc_unregister_dai(&bt_dai);
+       platform_device_unregister(neo1973_gta02_snd_device);
+       gpio_free(GTA02_GPIO_HP_IN);
+       gpio_free(GTA02_GPIO_AMP_SHUT);
+}
+module_exit(neo1973_gta02_exit);
+
+/* Module information */
+MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org");
+MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 GTA02");
+MODULE_LICENSE("GPL");
index 1a283170ca92d80e00394f3cbc7cb6d01ebafc98..9bc4aa35caab477f918f6f574fadb8ffbf75f319 100644 (file)
@@ -36,6 +36,7 @@
 #include <mach/dma.h>
 
 #include "s3c-i2s-v2.h"
+#include "s3c24xx-pcm.h"
 
 #undef S3C_IIS_V2_SUPPORTED
 
@@ -229,6 +230,8 @@ static void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
        pr_debug("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
 }
 
+#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+
 /*
  * Wait for the LR signal to allow synchronisation to the L/R clock
  * from the codec. May only be needed for slave mode.
@@ -236,19 +239,21 @@ static void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
 static int s3c2412_snd_lrsync(struct s3c_i2sv2_info *i2s)
 {
        u32 iiscon;
-       unsigned long timeout = jiffies + msecs_to_jiffies(5);
+       unsigned long loops = msecs_to_loops(5);
 
        pr_debug("Entered %s\n", __func__);
 
-       while (1) {
+       while (--loops) {
                iiscon = readl(i2s->regs + S3C2412_IISCON);
                if (iiscon & S3C2412_IISCON_LRINDEX)
                        break;
 
-               if (timeout < jiffies) {
-                       printk(KERN_ERR "%s: timeout\n", __func__);
-                       return -ETIMEDOUT;
-               }
+               cpu_relax();
+       }
+
+       if (!loops) {
+               printk(KERN_ERR "%s: timeout\n", __func__);
+               return -ETIMEDOUT;
        }
 
        return 0;
@@ -357,19 +362,19 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
 #endif
 
 #ifdef CONFIG_PLAT_S3C64XX
-       iismod &= ~0x606;
+       iismod &= ~(S3C64XX_IISMOD_BLC_MASK | S3C2412_IISMOD_BCLK_MASK);
        /* Sample size */
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S8:
                /* 8 bit sample, 16fs BCLK */
-               iismod |= 0x2004;
+               iismod |= (S3C64XX_IISMOD_BLC_8BIT | S3C2412_IISMOD_BCLK_16FS);
                break;
        case SNDRV_PCM_FORMAT_S16_LE:
                /* 16 bit sample, 32fs BCLK */
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
                /* 24 bit sample, 48fs BCLK */
-               iismod |= 0x4002;
+               iismod |= (S3C64XX_IISMOD_BLC_24BIT | S3C2412_IISMOD_BCLK_48FS);
                break;
        }
 #endif
@@ -387,6 +392,8 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
        int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
        unsigned long irqs;
        int ret = 0;
+       int channel = ((struct s3c24xx_pcm_dma_params *)
+                 rtd->dai->cpu_dai->dma_data)->channel;
 
        pr_debug("Entered %s\n", __func__);
 
@@ -416,6 +423,14 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
                        s3c2412_snd_txctrl(i2s, 1);
 
                local_irq_restore(irqs);
+
+               /*
+                * Load the next buffer to DMA to meet the reqirement
+                * of the auto reload mechanism of S3C24XX.
+                * This call won't bother S3C64XX.
+                */
+               s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
+
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
index 3f03d5ddfacda0b3392c0fe3b0fd487332d33052..fc1beb0930b988ef4377703cbdd531b805aea2c0 100644 (file)
@@ -47,7 +47,7 @@ static struct s3c24xx_ac97_info s3c24xx_ac97;
 
 static DECLARE_COMPLETION(ac97_completion);
 static u32 codec_ready;
-static DECLARE_MUTEX(ac97_mutex);
+static DEFINE_MUTEX(ac97_mutex);
 
 static unsigned short s3c2443_ac97_read(struct snd_ac97 *ac97,
        unsigned short reg)
@@ -56,7 +56,7 @@ static unsigned short s3c2443_ac97_read(struct snd_ac97 *ac97,
        u32 ac_codec_cmd;
        u32 stat, addr, data;
 
-       down(&ac97_mutex);
+       mutex_lock(&ac97_mutex);
 
        codec_ready = S3C_AC97_GLBSTAT_CODECREADY;
        ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD);
@@ -79,7 +79,7 @@ static unsigned short s3c2443_ac97_read(struct snd_ac97 *ac97,
                printk(KERN_ERR "s3c24xx-ac97: req addr = %02x,"
                                " rep addr = %02x\n", reg, addr);
 
-       up(&ac97_mutex);
+       mutex_unlock(&ac97_mutex);
 
        return (unsigned short)data;
 }
@@ -90,7 +90,7 @@ static void s3c2443_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
        u32 ac_glbctrl;
        u32 ac_codec_cmd;
 
-       down(&ac97_mutex);
+       mutex_lock(&ac97_mutex);
 
        codec_ready = S3C_AC97_GLBSTAT_CODECREADY;
        ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD);
@@ -109,7 +109,7 @@ static void s3c2443_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
        ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ;
        writel(ac_codec_cmd, s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD);
 
-       up(&ac97_mutex);
+       mutex_unlock(&ac97_mutex);
 
 }
 
@@ -290,6 +290,9 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
                                struct snd_soc_dai *dai)
 {
        u32 ac_glbctrl;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       int channel = ((struct s3c24xx_pcm_dma_params *)
+                 rtd->dai->cpu_dai->dma_data)->channel;
 
        ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
        switch (cmd) {
@@ -312,6 +315,8 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
        }
        writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
 
+       s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
+
        return 0;
 }
 
@@ -334,6 +339,9 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
                                    int cmd, struct snd_soc_dai *dai)
 {
        u32 ac_glbctrl;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       int channel = ((struct s3c24xx_pcm_dma_params *)
+                 rtd->dai->cpu_dai->dma_data)->channel;
 
        ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
        switch (cmd) {
@@ -349,6 +357,8 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
        }
        writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
 
+       s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
+
        return 0;
 }
 
index 556e35f0ab7341416fbf6c30c38d713f3a709b92..40e2c4790f0de95b08d0e846678422151909e366 100644 (file)
@@ -279,6 +279,9 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
                               struct snd_soc_dai *dai)
 {
        int ret = 0;
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       int channel = ((struct s3c24xx_pcm_dma_params *)
+                 rtd->dai->cpu_dai->dma_data)->channel;
 
        pr_debug("Entered %s\n", __func__);
 
@@ -296,6 +299,8 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
                        s3c24xx_snd_rxctrl(1);
                else
                        s3c24xx_snd_txctrl(1);
+
+               s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
index eecfa5eba06b0bf0b450d518368df1fe90cc52f6..5cbbdc80fde3e9d829e91fef099ae21965c54c53 100644 (file)
@@ -255,7 +255,6 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                prtd->state |= ST_RUNNING;
                s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
-               s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STARTED);
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
@@ -318,6 +317,7 @@ static int s3c24xx_pcm_open(struct snd_pcm_substream *substream)
 
        pr_debug("Entered %s\n", __func__);
 
+       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
        snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware);
 
        prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL);
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.c b/sound/soc/s3c24xx/s3c24xx_simtec.c
new file mode 100644 (file)
index 0000000..1966e0d
--- /dev/null
@@ -0,0 +1,394 @@
+/* sound/soc/s3c24xx/s3c24xx_simtec.c
+ *
+ * Copyright 2009 Simtec Electronics
+ *
+ * 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/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <plat/audio-simtec.h>
+
+#include "s3c24xx-pcm.h"
+#include "s3c24xx-i2s.h"
+#include "s3c24xx_simtec.h"
+
+static struct s3c24xx_audio_simtec_pdata *pdata;
+static struct clk *xtal_clk;
+
+static int spk_gain;
+static int spk_unmute;
+
+/**
+ * speaker_gain_get - read the speaker gain setting.
+ * @kcontrol: The control for the speaker gain.
+ * @ucontrol: The value that needs to be updated.
+ *
+ * Read the value for the AMP gain control.
+ */
+static int speaker_gain_get(struct snd_kcontrol *kcontrol,
+                           struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.integer.value[0] = spk_gain;
+       return 0;
+}
+
+/**
+ * speaker_gain_set - set the value of the speaker amp gain
+ * @value: The value to write.
+ */
+static void speaker_gain_set(int value)
+{
+       gpio_set_value_cansleep(pdata->amp_gain[0], value & 1);
+       gpio_set_value_cansleep(pdata->amp_gain[1], value >> 1);
+}
+
+/**
+ * speaker_gain_put - set the speaker gain setting.
+ * @kcontrol: The control for the speaker gain.
+ * @ucontrol: The value that needs to be set.
+ *
+ * Set the value of the speaker gain from the specified
+ * @ucontrol setting.
+ *
+ * Note, if the speaker amp is muted, then we do not set a gain value
+ * as at-least one of the ICs that is fitted will try and power up even
+ * if the main control is set to off.
+ */
+static int speaker_gain_put(struct snd_kcontrol *kcontrol,
+                           struct snd_ctl_elem_value *ucontrol)
+{
+       int value = ucontrol->value.integer.value[0];
+
+       spk_gain = value;
+
+       if (!spk_unmute)
+               speaker_gain_set(value);
+
+       return 0;
+}
+
+static const struct snd_kcontrol_new amp_gain_controls[] = {
+       SOC_SINGLE_EXT("Speaker Gain", 0, 0, 3, 0,
+                      speaker_gain_get, speaker_gain_put),
+};
+
+/**
+ * spk_unmute_state - set the unmute state of the speaker
+ * @to: zero to unmute, non-zero to ununmute.
+ */
+static void spk_unmute_state(int to)
+{
+       pr_debug("%s: to=%d\n", __func__, to);
+
+       spk_unmute = to;
+       gpio_set_value(pdata->amp_gpio, to);
+
+       /* if we're umuting, also re-set the gain */
+       if (to && pdata->amp_gain[0] > 0)
+               speaker_gain_set(spk_gain);
+}
+
+/**
+ * speaker_unmute_get - read the speaker unmute setting.
+ * @kcontrol: The control for the speaker gain.
+ * @ucontrol: The value that needs to be updated.
+ *
+ * Read the value for the AMP gain control.
+ */
+static int speaker_unmute_get(struct snd_kcontrol *kcontrol,
+                           struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.integer.value[0] = spk_unmute;
+       return 0;
+}
+
+/**
+ * speaker_unmute_put - set the speaker unmute setting.
+ * @kcontrol: The control for the speaker gain.
+ * @ucontrol: The value that needs to be set.
+ *
+ * Set the value of the speaker gain from the specified
+ * @ucontrol setting.
+ */
+static int speaker_unmute_put(struct snd_kcontrol *kcontrol,
+                           struct snd_ctl_elem_value *ucontrol)
+{
+       spk_unmute_state(ucontrol->value.integer.value[0]);
+       return 0;
+}
+
+/* This is added as a manual control as the speaker amps create clicks
+ * when their power state is changed, which are far more noticeable than
+ * anything produced by the CODEC itself.
+ */
+static const struct snd_kcontrol_new amp_unmute_controls[] = {
+       SOC_SINGLE_EXT("Speaker Switch", 0, 0, 1, 0,
+                      speaker_unmute_get, speaker_unmute_put),
+};
+
+void simtec_audio_init(struct snd_soc_codec *codec)
+{
+       if (pdata->amp_gpio > 0) {
+               pr_debug("%s: adding amp routes\n", __func__);
+
+               snd_soc_add_controls(codec, amp_unmute_controls,
+                                    ARRAY_SIZE(amp_unmute_controls));
+       }
+
+       if (pdata->amp_gain[0] > 0) {
+               pr_debug("%s: adding amp controls\n", __func__);
+               snd_soc_add_controls(codec, amp_gain_controls,
+                                    ARRAY_SIZE(amp_gain_controls));
+       }
+}
+EXPORT_SYMBOL_GPL(simtec_audio_init);
+
+#define CODEC_CLOCK 12000000
+
+/**
+ * simtec_hw_params - update hardware parameters
+ * @substream: The audio substream instance.
+ * @params: The parameters requested.
+ *
+ * Update the codec data routing and configuration  settings
+ * from the supplied data.
+ */
+static int simtec_hw_params(struct snd_pcm_substream *substream,
+                           struct snd_pcm_hw_params *params)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
+       int ret;
+
+       /* Set the CODEC as the bus clock master, I2S */
+       ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+                                 SND_SOC_DAIFMT_NB_NF |
+                                 SND_SOC_DAIFMT_CBM_CFM);
+       if (ret) {
+               pr_err("%s: failed set cpu dai format\n", __func__);
+               return ret;
+       }
+
+       /* Set the CODEC as the bus clock master */
+       ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+                                 SND_SOC_DAIFMT_NB_NF |
+                                 SND_SOC_DAIFMT_CBM_CFM);
+       if (ret) {
+               pr_err("%s: failed set codec dai format\n", __func__);
+               return ret;
+       }
+
+       ret = snd_soc_dai_set_sysclk(codec_dai, 0,
+                                    CODEC_CLOCK, SND_SOC_CLOCK_IN);
+       if (ret) {
+               pr_err( "%s: failed setting codec sysclk\n", __func__);
+               return ret;
+       }
+
+       if (pdata->use_mpllin) {
+               ret = snd_soc_dai_set_sysclk(cpu_dai, S3C24XX_CLKSRC_MPLL,
+                                            0, SND_SOC_CLOCK_OUT);
+
+               if (ret) {
+                       pr_err("%s: failed to set MPLLin as clksrc\n",
+                              __func__);
+                       return ret;
+               }
+       }
+
+       if (pdata->output_cdclk) {
+               int cdclk_scale;
+
+               cdclk_scale = clk_get_rate(xtal_clk) / CODEC_CLOCK;
+               cdclk_scale--;
+
+               ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
+                                            cdclk_scale);
+       }
+
+       return 0;
+}
+
+static int simtec_call_startup(struct s3c24xx_audio_simtec_pdata *pd)
+{
+       /* call any board supplied startup code, this currently only
+        * covers the bast/vr1000 which have a CPLD in the way of the
+        * LRCLK */
+       if (pd->startup)
+               pd->startup();
+
+       return 0;
+}
+
+static struct snd_soc_ops simtec_snd_ops = {
+       .hw_params      = simtec_hw_params,
+};
+
+/**
+ * attach_gpio_amp - get and configure the necessary gpios
+ * @dev: The device we're probing.
+ * @pd: The platform data supplied by the board.
+ *
+ * If there is a GPIO based amplifier attached to the board, claim
+ * the necessary GPIO lines for it, and set default values.
+ */
+static int attach_gpio_amp(struct device *dev,
+                          struct s3c24xx_audio_simtec_pdata *pd)
+{
+       int ret;
+
+       /* attach gpio amp gain (if any) */
+       if (pdata->amp_gain[0] > 0) {
+               ret = gpio_request(pd->amp_gain[0], "gpio-amp-gain0");
+               if (ret) {
+                       dev_err(dev, "cannot get amp gpio gain0\n");
+                       return ret;
+               }
+
+               ret = gpio_request(pd->amp_gain[1], "gpio-amp-gain1");
+               if (ret) {
+                       dev_err(dev, "cannot get amp gpio gain1\n");
+                       gpio_free(pdata->amp_gain[0]);
+                       return ret;
+               }
+
+               gpio_direction_output(pd->amp_gain[0], 0);
+               gpio_direction_output(pd->amp_gain[1], 0);
+       }
+
+       /* note, curently we assume GPA0 isn't valid amp */
+       if (pdata->amp_gpio > 0) {
+               ret = gpio_request(pd->amp_gpio, "gpio-amp");
+               if (ret) {
+                       dev_err(dev, "cannot get amp gpio %d (%d)\n",
+                               pd->amp_gpio, ret);
+                       goto err_amp;
+               }
+
+               /* set the amp off at startup */
+               spk_unmute_state(0);
+       }
+
+       return 0;
+
+err_amp:
+       if (pd->amp_gain[0] > 0) {
+               gpio_free(pd->amp_gain[0]);
+               gpio_free(pd->amp_gain[1]);
+       }
+
+       return ret;
+}
+
+static void detach_gpio_amp(struct s3c24xx_audio_simtec_pdata *pd)
+{
+       if (pd->amp_gain[0] > 0) {
+               gpio_free(pd->amp_gain[0]);
+               gpio_free(pd->amp_gain[1]);
+       }
+
+       if (pd->amp_gpio > 0)
+               gpio_free(pd->amp_gpio);
+}
+
+#ifdef CONFIG_PM
+int simtec_audio_resume(struct device *dev)
+{
+       simtec_call_startup(pdata);
+       return 0;
+}
+
+struct dev_pm_ops simtec_audio_pmops = {
+       .resume = simtec_audio_resume,
+};
+EXPORT_SYMBOL_GPL(simtec_audio_pmops);
+#endif
+
+int __devinit simtec_audio_core_probe(struct platform_device *pdev,
+                                     struct snd_soc_device *socdev)
+{
+       struct platform_device *snd_dev;
+       int ret;
+
+       socdev->card->dai_link->ops = &simtec_snd_ops;
+
+       pdata = pdev->dev.platform_data;
+       if (!pdata) {
+               dev_err(&pdev->dev, "no platform data supplied\n");
+               return -EINVAL;
+       }
+
+       simtec_call_startup(pdata);
+
+       xtal_clk = clk_get(&pdev->dev, "xtal");
+       if (IS_ERR(xtal_clk)) {
+               dev_err(&pdev->dev, "could not get clkout0\n");
+               return -EINVAL;
+       }
+
+       dev_info(&pdev->dev, "xtal rate is %ld\n", clk_get_rate(xtal_clk));
+
+       ret = attach_gpio_amp(&pdev->dev, pdata);
+       if (ret)
+               goto err_clk;
+
+       snd_dev = platform_device_alloc("soc-audio", -1);
+       if (!snd_dev) {
+               dev_err(&pdev->dev, "failed to alloc soc-audio devicec\n");
+               ret = -ENOMEM;
+               goto err_gpio;
+       }
+
+       platform_set_drvdata(snd_dev, socdev);
+       socdev->dev = &snd_dev->dev;
+
+       ret = platform_device_add(snd_dev);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to add soc-audio dev\n");
+               goto err_pdev;
+       }
+
+       platform_set_drvdata(pdev, snd_dev);
+       return 0;
+
+err_pdev:
+       platform_device_put(snd_dev);
+
+err_gpio:
+       detach_gpio_amp(pdata);
+
+err_clk:
+       clk_put(xtal_clk);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(simtec_audio_core_probe);
+
+int __devexit simtec_audio_remove(struct platform_device *pdev)
+{
+       struct platform_device *snd_dev = platform_get_drvdata(pdev);
+
+       platform_device_unregister(snd_dev);
+
+       detach_gpio_amp(pdata);
+       clk_put(xtal_clk);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(simtec_audio_remove);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("ALSA SoC Simtec Audio common support");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.h b/sound/soc/s3c24xx/s3c24xx_simtec.h
new file mode 100644 (file)
index 0000000..2714203
--- /dev/null
@@ -0,0 +1,22 @@
+/* sound/soc/s3c24xx/s3c24xx_simtec.h
+ *
+ * Copyright 2009 Simtec Electronics
+ *
+ * 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.
+*/
+
+extern void simtec_audio_init(struct snd_soc_codec *codec);
+
+extern int simtec_audio_core_probe(struct platform_device *pdev,
+                                  struct snd_soc_device *socdev);
+
+extern int simtec_audio_remove(struct platform_device *pdev);
+
+#ifdef CONFIG_PM
+extern struct dev_pm_ops simtec_audio_pmops;
+#define simtec_audio_pm &simtec_audio_pmops
+#else
+#define simtec_audio_pm NULL
+#endif
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
new file mode 100644 (file)
index 0000000..8346bd9
--- /dev/null
@@ -0,0 +1,153 @@
+/* sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
+ *
+ * Copyright 2009 Simtec Electronics
+ *
+ * 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/clk.h>
+#include <linux/platform_device.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <plat/audio-simtec.h>
+
+#include "s3c24xx-pcm.h"
+#include "s3c24xx-i2s.h"
+#include "s3c24xx_simtec.h"
+
+#include "../codecs/tlv320aic3x.h"
+
+static const struct snd_soc_dapm_widget dapm_widgets[] = {
+       SND_SOC_DAPM_LINE("GSM Out", NULL),
+       SND_SOC_DAPM_LINE("GSM In", NULL),
+       SND_SOC_DAPM_LINE("Line In", NULL),
+       SND_SOC_DAPM_LINE("Line Out", NULL),
+       SND_SOC_DAPM_LINE("ZV", NULL),
+       SND_SOC_DAPM_MIC("Mic Jack", NULL),
+       SND_SOC_DAPM_HP("Headphone Jack", NULL),
+};
+
+static const struct snd_soc_dapm_route base_map[] = {
+       /* Headphone connected to HP{L,R}OUT and HP{L,R}COM */
+
+       { "Headphone Jack", NULL, "HPLOUT" },
+       { "Headphone Jack", NULL, "HPLCOM" },
+       { "Headphone Jack", NULL, "HPROUT" },
+       { "Headphone Jack", NULL, "HPRCOM" },
+
+       /* ZV connected to Line1 */
+
+       { "LINE1L", NULL, "ZV" },
+       { "LINE1R", NULL, "ZV" },
+
+       /* Line In connected to Line2 */
+
+       { "LINE2L", NULL, "Line In" },
+       { "LINE2R", NULL, "Line In" },
+
+       /* Microphone connected to MIC3R and MIC_BIAS */
+
+       { "MIC3L", NULL, "Mic Jack" },
+
+       /* GSM connected to MONO_LOUT and MIC3L (in) */
+
+       { "GSM Out", NULL, "MONO_LOUT" },
+       { "MIC3L", NULL, "GSM In" },
+
+       /* Speaker is connected to LINEOUT{LN,LP,RN,RP}, however we are
+        * not using the DAPM to power it up and down as there it makes
+        * a click when powering up. */
+};
+
+/**
+ * simtec_hermes_init - initialise and add controls
+ * @codec; The codec instance to attach to.
+ *
+ * Attach our controls and configure the necessary codec
+ * mappings for our sound card instance.
+*/
+static int simtec_hermes_init(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_new_controls(codec, dapm_widgets,
+                                 ARRAY_SIZE(dapm_widgets));
+
+       snd_soc_dapm_add_routes(codec, base_map, ARRAY_SIZE(base_map));
+
+       snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+       snd_soc_dapm_enable_pin(codec, "Line In");
+       snd_soc_dapm_enable_pin(codec, "Line Out");
+       snd_soc_dapm_enable_pin(codec, "Mic Jack");
+
+       simtec_audio_init(codec);
+       snd_soc_dapm_sync(codec);
+
+       return 0;
+}
+
+static struct aic3x_setup_data codec_setup = {
+};
+
+static struct snd_soc_dai_link simtec_dai_aic33 = {
+       .name           = "tlv320aic33",
+       .stream_name    = "TLV320AIC33",
+       .cpu_dai        = &s3c24xx_i2s_dai,
+       .codec_dai      = &aic3x_dai,
+       .init           = simtec_hermes_init,
+};
+
+/* simtec audio machine driver */
+static struct snd_soc_card snd_soc_machine_simtec_aic33 = {
+       .name           = "Simtec-Hermes",
+       .platform       = &s3c24xx_soc_platform,
+       .dai_link       = &simtec_dai_aic33,
+       .num_links      = 1,
+};
+
+/* simtec audio subsystem */
+static struct snd_soc_device simtec_snd_devdata_aic33 = {
+       .card           = &snd_soc_machine_simtec_aic33,
+       .codec_dev      = &soc_codec_dev_aic3x,
+       .codec_data     = &codec_setup,
+};
+
+static int __devinit simtec_audio_hermes_probe(struct platform_device *pd)
+{
+       dev_info(&pd->dev, "probing....\n");
+       return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic33);
+}
+
+static struct platform_driver simtec_audio_hermes_platdrv = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "s3c24xx-simtec-hermes-snd",
+               .pm     = simtec_audio_pm,
+       },
+       .probe  = simtec_audio_hermes_probe,
+       .remove = __devexit_p(simtec_audio_remove),
+};
+
+MODULE_ALIAS("platform:s3c24xx-simtec-hermes-snd");
+
+static int __init simtec_hermes_modinit(void)
+{
+       return platform_driver_register(&simtec_audio_hermes_platdrv);
+}
+
+static void __exit simtec_hermes_modexit(void)
+{
+       platform_driver_unregister(&simtec_audio_hermes_platdrv);
+}
+
+module_init(simtec_hermes_modinit);
+module_exit(simtec_hermes_modexit);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("ALSA SoC Simtec Audio support");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
new file mode 100644 (file)
index 0000000..25797e0
--- /dev/null
@@ -0,0 +1,137 @@
+/* sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
+ *
+ * Copyright 2009 Simtec Electronics
+ *
+ * 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/clk.h>
+#include <linux/platform_device.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <plat/audio-simtec.h>
+
+#include "s3c24xx-pcm.h"
+#include "s3c24xx-i2s.h"
+#include "s3c24xx_simtec.h"
+
+#include "../codecs/tlv320aic23.h"
+
+/* supported machines:
+ *
+ * Machine     Connections             AMP
+ * -------     -----------             ---
+ * BAST                MIC, HPOUT, LOUT, LIN   TPA2001D1 (HPOUTL,R) (gain hardwired)
+ * VR1000      HPOUT, LIN              None
+ * VR2000      LIN, LOUT, MIC, HP      LM4871 (HPOUTL,R)
+ * DePicture   LIN, LOUT, MIC, HP      LM4871 (HPOUTL,R)
+ * Anubis      LIN, LOUT, MIC, HP      TPA2001D1 (HPOUTL,R)
+ */
+
+static const struct snd_soc_dapm_widget dapm_widgets[] = {
+       SND_SOC_DAPM_HP("Headphone Jack", NULL),
+       SND_SOC_DAPM_LINE("Line In", NULL),
+       SND_SOC_DAPM_LINE("Line Out", NULL),
+       SND_SOC_DAPM_MIC("Mic Jack", NULL),
+};
+
+static const struct snd_soc_dapm_route base_map[] = {
+       { "Headphone Jack", NULL, "LHPOUT"},
+       { "Headphone Jack", NULL, "RHPOUT"},
+
+       { "Line Out", NULL, "LOUT" },
+       { "Line Out", NULL, "ROUT" },
+
+       { "LLINEIN", NULL, "Line In"},
+       { "RLINEIN", NULL, "Line In"},
+
+       { "MICIN", NULL, "Mic Jack"},
+};
+
+/**
+ * simtec_tlv320aic23_init - initialise and add controls
+ * @codec; The codec instance to attach to.
+ *
+ * Attach our controls and configure the necessary codec
+ * mappings for our sound card instance.
+*/
+static int simtec_tlv320aic23_init(struct snd_soc_codec *codec)
+{
+       snd_soc_dapm_new_controls(codec, dapm_widgets,
+                                 ARRAY_SIZE(dapm_widgets));
+
+       snd_soc_dapm_add_routes(codec, base_map, ARRAY_SIZE(base_map));
+
+       snd_soc_dapm_enable_pin(codec, "Headphone Jack");
+       snd_soc_dapm_enable_pin(codec, "Line In");
+       snd_soc_dapm_enable_pin(codec, "Line Out");
+       snd_soc_dapm_enable_pin(codec, "Mic Jack");
+
+       simtec_audio_init(codec);
+       snd_soc_dapm_sync(codec);
+
+       return 0;
+}
+
+static struct snd_soc_dai_link simtec_dai_aic23 = {
+       .name           = "tlv320aic23",
+       .stream_name    = "TLV320AIC23",
+       .cpu_dai        = &s3c24xx_i2s_dai,
+       .codec_dai      = &tlv320aic23_dai,
+       .init           = simtec_tlv320aic23_init,
+};
+
+/* simtec audio machine driver */
+static struct snd_soc_card snd_soc_machine_simtec_aic23 = {
+       .name           = "Simtec",
+       .platform       = &s3c24xx_soc_platform,
+       .dai_link       = &simtec_dai_aic23,
+       .num_links      = 1,
+};
+
+/* simtec audio subsystem */
+static struct snd_soc_device simtec_snd_devdata_aic23 = {
+       .card           = &snd_soc_machine_simtec_aic23,
+       .codec_dev      = &soc_codec_dev_tlv320aic23,
+};
+
+static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd)
+{
+       return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic23);
+}
+
+static struct platform_driver simtec_audio_tlv320aic23_platdrv = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "s3c24xx-simtec-tlv320aic23",
+               .pm     = simtec_audio_pm,
+       },
+       .probe  = simtec_audio_tlv320aic23_probe,
+       .remove = __devexit_p(simtec_audio_remove),
+};
+
+MODULE_ALIAS("platform:s3c24xx-simtec-tlv320aic23");
+
+static int __init simtec_tlv320aic23_modinit(void)
+{
+       return platform_driver_register(&simtec_audio_tlv320aic23_platdrv);
+}
+
+static void __exit simtec_tlv320aic23_modexit(void)
+{
+       platform_driver_unregister(&simtec_audio_tlv320aic23_platdrv);
+}
+
+module_init(simtec_tlv320aic23_modinit);
+module_exit(simtec_tlv320aic23_modexit);
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("ALSA SoC Simtec Audio support");
+MODULE_LICENSE("GPL");
index b5f95f9781c10d6b14f9050292508b9c533135a2..c1b40ac22c052b22a986dac52435291529ad2bfd 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/timer.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/i2c.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
@@ -189,8 +190,6 @@ static struct snd_soc_card snd_soc_card_s6105 = {
 
 /* s6105 audio private data */
 static struct aic3x_setup_data s6105_aic3x_setup = {
-       .i2c_bus = 0,
-       .i2c_address = 0x18,
 };
 
 /* s6105 audio subsystem */
@@ -211,10 +210,19 @@ static struct s6000_snd_platform_data __initdata s6105_snd_data = {
 
 static struct platform_device *s6105_snd_device;
 
+/* temporary i2c device creation until this can be moved into the machine
+ * support file.
+*/
+static struct i2c_board_info i2c_device[] = {
+       { I2C_BOARD_INFO("tlv320aic33", 0x18), }
+};
+
 static int __init s6105_init(void)
 {
        int ret;
 
+       i2c_register_board_info(0, i2c_device, ARRAY_SIZE(i2c_device));
+
        s6105_snd_device = platform_device_alloc("soc-audio", -1);
        if (!s6105_snd_device)
                return -ENOMEM;
index 54bd604012af6ce2d96fab4a111f7ba519292b2c..9154b4363db386f45ea5f1cb188596536b7f3d94 100644 (file)
@@ -20,7 +20,12 @@ config SND_SOC_SH4_HAC
 config SND_SOC_SH4_SSI
        tristate
 
-
+config SND_SOC_SH4_FSI
+       tristate "SH4 FSI support"
+       depends on CPU_SUBTYPE_SH7724
+        select SH_DMA
+       help
+         This option enables FSI sound support
 
 ##
 ## Boards
@@ -35,4 +40,12 @@ config SND_SH7760_AC97
          This option enables generic sound support for the first
          AC97 unit of the SH7760.
 
+config SND_FSI_AK4642
+       bool "FSI-AK4642 sound support"
+       depends on SND_SOC_SH4_FSI
+       select SND_SOC_AK4642
+       help
+         This option enables generic sound support for the
+         FSI - AK4642 unit
+
 endmenu
index a8e8ab81cc6a0371188b07743eddbe20abe52954..a6997872f24ede65524ee4b83eb31737975f7e21 100644 (file)
@@ -5,10 +5,14 @@ obj-$(CONFIG_SND_SOC_PCM_SH7760)      += snd-soc-dma-sh7760.o
 ## audio units found on some SH-4
 snd-soc-hac-objs       := hac.o
 snd-soc-ssi-objs       := ssi.o
+snd-soc-fsi-objs       := fsi.o
 obj-$(CONFIG_SND_SOC_SH4_HAC)  += snd-soc-hac.o
 obj-$(CONFIG_SND_SOC_SH4_SSI)  += snd-soc-ssi.o
+obj-$(CONFIG_SND_SOC_SH4_FSI)  += snd-soc-fsi.o
 
 ## boards
 snd-soc-sh7760-ac97-objs       := sh7760-ac97.o
+snd-soc-fsi-ak4642-objs                := fsi-ak4642.o
 
 obj-$(CONFIG_SND_SH7760_AC97)  += snd-soc-sh7760-ac97.o
+obj-$(CONFIG_SND_FSI_AK4642)   += snd-soc-fsi-ak4642.o
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
new file mode 100644 (file)
index 0000000..c7af097
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * FSI-AK464x sound support for ms7724se
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include <sound/sh_fsi.h>
+#include <../sound/soc/codecs/ak4642.h>
+
+static struct snd_soc_dai_link fsi_dai_link = {
+       .name           = "AK4642",
+       .stream_name    = "AK4642",
+       .cpu_dai        = &fsi_soc_dai[0], /* fsi */
+       .codec_dai      = &ak4642_dai,
+       .ops            = NULL,
+};
+
+static struct snd_soc_card fsi_soc_card  = {
+       .name           = "FSI",
+       .platform       = &fsi_soc_platform,
+       .dai_link       = &fsi_dai_link,
+       .num_links      = 1,
+};
+
+static struct snd_soc_device fsi_snd_devdata = {
+       .card           = &fsi_soc_card,
+       .codec_dev      = &soc_codec_dev_ak4642,
+};
+
+#define AK4642_BUS 0
+#define AK4642_ADR 0x12
+static int ak4642_add_i2c_device(void)
+{
+       struct i2c_board_info info;
+       struct i2c_adapter *adapter;
+       struct i2c_client *client;
+
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       info.addr = AK4642_ADR;
+       strlcpy(info.type, "ak4642", I2C_NAME_SIZE);
+
+       adapter = i2c_get_adapter(AK4642_BUS);
+       if (!adapter) {
+               printk(KERN_DEBUG "can't get i2c adapter\n");
+               return -ENODEV;
+       }
+
+       client = i2c_new_device(adapter, &info);
+       i2c_put_adapter(adapter);
+       if (!client) {
+               printk(KERN_DEBUG "can't add i2c device\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static struct platform_device *fsi_snd_device;
+
+static int __init fsi_ak4642_init(void)
+{
+       int ret = -ENOMEM;
+
+       ak4642_add_i2c_device();
+
+       fsi_snd_device = platform_device_alloc("soc-audio", -1);
+       if (!fsi_snd_device)
+               goto out;
+
+       platform_set_drvdata(fsi_snd_device,
+                            &fsi_snd_devdata);
+       fsi_snd_devdata.dev = &fsi_snd_device->dev;
+       ret = platform_device_add(fsi_snd_device);
+
+       if (ret)
+               platform_device_put(fsi_snd_device);
+
+out:
+       return ret;
+}
+
+static void __exit fsi_ak4642_exit(void)
+{
+       platform_device_unregister(fsi_snd_device);
+}
+
+module_init(fsi_ak4642_init);
+module_exit(fsi_ak4642_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic SH4 FSI-AK4642 sound card");
+MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
new file mode 100644 (file)
index 0000000..4412324
--- /dev/null
@@ -0,0 +1,1004 @@
+/*
+ * Fifo-attached Serial Interface (FSI) support for SH7724
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on ssi.c
+ * Copyright (c) 2007 Manuel Lauss <mano@roarinelk.homelinux.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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#include <sound/sh_fsi.h>
+#include <asm/atomic.h>
+#include <asm/dma.h>
+#include <asm/dma-sh.h>
+
+#define DO_FMT         0x0000
+#define DOFF_CTL       0x0004
+#define DOFF_ST                0x0008
+#define DI_FMT         0x000C
+#define DIFF_CTL       0x0010
+#define DIFF_ST                0x0014
+#define CKG1           0x0018
+#define CKG2           0x001C
+#define DIDT           0x0020
+#define DODT           0x0024
+#define MUTE_ST                0x0028
+#define REG_END                MUTE_ST
+
+#define INT_ST         0x0200
+#define IEMSK          0x0204
+#define IMSK           0x0208
+#define MUTE           0x020C
+#define CLK_RST                0x0210
+#define SOFT_RST       0x0214
+#define MREG_START     INT_ST
+#define MREG_END       SOFT_RST
+
+/* DO_FMT */
+/* DI_FMT */
+#define CR_FMT(param) ((param) << 4)
+# define CR_MONO       0x0
+# define CR_MONO_D     0x1
+# define CR_PCM                0x2
+# define CR_I2S                0x3
+# define CR_TDM                0x4
+# define CR_TDM_D      0x5
+
+/* DOFF_CTL */
+/* DIFF_CTL */
+#define IRQ_HALF       0x00100000
+#define FIFO_CLR       0x00000001
+
+/* DOFF_ST */
+#define ERR_OVER       0x00000010
+#define ERR_UNDER      0x00000001
+
+/* CLK_RST */
+#define B_CLK          0x00000010
+#define A_CLK          0x00000001
+
+/* INT_ST */
+#define INT_B_IN       (1 << 12)
+#define INT_B_OUT      (1 << 8)
+#define INT_A_IN       (1 << 4)
+#define INT_A_OUT      (1 << 0)
+
+#define FSI_RATES SNDRV_PCM_RATE_8000_96000
+
+#define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
+
+/************************************************************************
+
+
+               struct
+
+
+************************************************************************/
+struct fsi_priv {
+       void __iomem *base;
+       struct snd_pcm_substream *substream;
+
+       int fifo_max;
+       int chan;
+       int dma_chan;
+
+       int byte_offset;
+       int period_len;
+       int buffer_len;
+       int periods;
+};
+
+struct fsi_master {
+       void __iomem *base;
+       int irq;
+       struct clk *clk;
+       struct fsi_priv fsia;
+       struct fsi_priv fsib;
+       struct sh_fsi_platform_info *info;
+};
+
+static struct fsi_master *master;
+
+/************************************************************************
+
+
+               basic read write function
+
+
+************************************************************************/
+static int __fsi_reg_write(u32 reg, u32 data)
+{
+       /* valid data area is 24bit */
+       data &= 0x00ffffff;
+
+       return ctrl_outl(data, reg);
+}
+
+static u32 __fsi_reg_read(u32 reg)
+{
+       return ctrl_inl(reg);
+}
+
+static int __fsi_reg_mask_set(u32 reg, u32 mask, u32 data)
+{
+       u32 val = __fsi_reg_read(reg);
+
+       val &= ~mask;
+       val |= data & mask;
+
+       return __fsi_reg_write(reg, val);
+}
+
+static int fsi_reg_write(struct fsi_priv *fsi, u32 reg, u32 data)
+{
+       if (reg > REG_END)
+               return -1;
+
+       return __fsi_reg_write((u32)(fsi->base + reg), data);
+}
+
+static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg)
+{
+       if (reg > REG_END)
+               return 0;
+
+       return __fsi_reg_read((u32)(fsi->base + reg));
+}
+
+static int fsi_reg_mask_set(struct fsi_priv *fsi, u32 reg, u32 mask, u32 data)
+{
+       if (reg > REG_END)
+               return -1;
+
+       return __fsi_reg_mask_set((u32)(fsi->base + reg), mask, data);
+}
+
+static int fsi_master_write(u32 reg, u32 data)
+{
+       if ((reg < MREG_START) ||
+           (reg > MREG_END))
+               return -1;
+
+       return __fsi_reg_write((u32)(master->base + reg), data);
+}
+
+static u32 fsi_master_read(u32 reg)
+{
+       if ((reg < MREG_START) ||
+           (reg > MREG_END))
+               return 0;
+
+       return __fsi_reg_read((u32)(master->base + reg));
+}
+
+static int fsi_master_mask_set(u32 reg, u32 mask, u32 data)
+{
+       if ((reg < MREG_START) ||
+           (reg > MREG_END))
+               return -1;
+
+       return __fsi_reg_mask_set((u32)(master->base + reg), mask, data);
+}
+
+/************************************************************************
+
+
+               basic function
+
+
+************************************************************************/
+static struct fsi_priv *fsi_get(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd;
+       struct fsi_priv *fsi = NULL;
+
+       if (!substream || !master)
+               return NULL;
+
+       rtd = substream->private_data;
+       switch (rtd->dai->cpu_dai->id) {
+       case 0:
+               fsi = &master->fsia;
+               break;
+       case 1:
+               fsi = &master->fsib;
+               break;
+       }
+
+       return fsi;
+}
+
+static int fsi_is_port_a(struct fsi_priv *fsi)
+{
+       /* return
+        * 1 : port a
+        * 0 : port b
+        */
+
+       if (fsi == &master->fsia)
+               return 1;
+
+       return 0;
+}
+
+static u32 fsi_get_info_flags(struct fsi_priv *fsi)
+{
+       int is_porta = fsi_is_port_a(fsi);
+
+       return is_porta ? master->info->porta_flags :
+               master->info->portb_flags;
+}
+
+static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play)
+{
+       u32 mode;
+       u32 flags = fsi_get_info_flags(fsi);
+
+       mode = is_play ? SH_FSI_OUT_SLAVE_MODE : SH_FSI_IN_SLAVE_MODE;
+
+       /* return
+        * 1 : master mode
+        * 0 : slave mode
+        */
+
+       return (mode & flags) != mode;
+}
+
+static u32 fsi_port_ab_io_bit(struct fsi_priv *fsi, int is_play)
+{
+       int is_porta = fsi_is_port_a(fsi);
+       u32 data;
+
+       if (is_porta)
+               data = is_play ? (1 << 0) : (1 << 4);
+       else
+               data = is_play ? (1 << 8) : (1 << 12);
+
+       return data;
+}
+
+static void fsi_stream_push(struct fsi_priv *fsi,
+                           struct snd_pcm_substream *substream,
+                           u32 buffer_len,
+                           u32 period_len)
+{
+       fsi->substream          = substream;
+       fsi->buffer_len         = buffer_len;
+       fsi->period_len         = period_len;
+       fsi->byte_offset        = 0;
+       fsi->periods            = 0;
+}
+
+static void fsi_stream_pop(struct fsi_priv *fsi)
+{
+       fsi->substream          = NULL;
+       fsi->buffer_len         = 0;
+       fsi->period_len         = 0;
+       fsi->byte_offset        = 0;
+       fsi->periods            = 0;
+}
+
+static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play)
+{
+       u32 status;
+       u32 reg = is_play ? DOFF_ST : DIFF_ST;
+       int residue;
+
+       status = fsi_reg_read(fsi, reg);
+       residue = 0x1ff & (status >> 8);
+       residue *= fsi->chan;
+
+       return residue;
+}
+
+static int fsi_get_residue(struct fsi_priv *fsi, int is_play)
+{
+       int residue;
+       int width;
+       struct snd_pcm_runtime *runtime;
+
+       runtime = fsi->substream->runtime;
+
+       /* get 1 channel data width */
+       width = frames_to_bytes(runtime, 1) / fsi->chan;
+
+       if (2 == width)
+               residue = fsi_get_fifo_residue(fsi, is_play);
+       else
+               residue = get_dma_residue(fsi->dma_chan);
+
+       return residue;
+}
+
+/************************************************************************
+
+
+               basic dma function
+
+
+************************************************************************/
+#define PORTA_DMA 0
+#define PORTB_DMA 1
+
+static int fsi_get_dma_chan(void)
+{
+       if (0 != request_dma(PORTA_DMA, "fsia"))
+               return -EIO;
+
+       if (0 != request_dma(PORTB_DMA, "fsib")) {
+               free_dma(PORTA_DMA);
+               return -EIO;
+       }
+
+       master->fsia.dma_chan = PORTA_DMA;
+       master->fsib.dma_chan = PORTB_DMA;
+
+       return 0;
+}
+
+static void fsi_free_dma_chan(void)
+{
+       dma_wait_for_completion(PORTA_DMA);
+       dma_wait_for_completion(PORTB_DMA);
+       free_dma(PORTA_DMA);
+       free_dma(PORTB_DMA);
+
+       master->fsia.dma_chan = -1;
+       master->fsib.dma_chan = -1;
+}
+
+/************************************************************************
+
+
+               ctrl function
+
+
+************************************************************************/
+static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
+{
+       u32 data = fsi_port_ab_io_bit(fsi, is_play);
+
+       fsi_master_mask_set(IMSK,  data, data);
+       fsi_master_mask_set(IEMSK, data, data);
+}
+
+static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
+{
+       u32 data = fsi_port_ab_io_bit(fsi, is_play);
+
+       fsi_master_mask_set(IMSK,  data, 0);
+       fsi_master_mask_set(IEMSK, data, 0);
+}
+
+static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable)
+{
+       u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4);
+
+       if (enable)
+               fsi_master_mask_set(CLK_RST, val, val);
+       else
+               fsi_master_mask_set(CLK_RST, val, 0);
+}
+
+static void fsi_irq_init(struct fsi_priv *fsi, int is_play)
+{
+       u32 data;
+       u32 ctrl;
+
+       data = fsi_port_ab_io_bit(fsi, is_play);
+       ctrl = is_play ? DOFF_CTL : DIFF_CTL;
+
+       /* set IMSK */
+       fsi_irq_disable(fsi, is_play);
+
+       /* set interrupt generation factor */
+       fsi_reg_write(fsi, ctrl, IRQ_HALF);
+
+       /* clear FIFO */
+       fsi_reg_mask_set(fsi, ctrl, FIFO_CLR, FIFO_CLR);
+
+       /* clear interrupt factor */
+       fsi_master_mask_set(INT_ST, data, 0);
+}
+
+static void fsi_soft_all_reset(void)
+{
+       u32 status = fsi_master_read(SOFT_RST);
+
+       /* port AB reset */
+       status &= 0x000000ff;
+       fsi_master_write(SOFT_RST, status);
+       mdelay(10);
+
+       /* soft reset */
+       status &= 0x000000f0;
+       fsi_master_write(SOFT_RST, status);
+       status |= 0x00000001;
+       fsi_master_write(SOFT_RST, status);
+       mdelay(10);
+}
+
+static void fsi_16data_push(struct fsi_priv *fsi,
+                          struct snd_pcm_runtime *runtime,
+                          int send)
+{
+       u16 *dma_start;
+       u32 snd;
+       int i;
+
+       /* get dma start position for FSI */
+       dma_start = (u16 *)runtime->dma_area;
+       dma_start += fsi->byte_offset / 2;
+
+       /*
+        * soft dma
+        * FSI can not use DMA when 16bpp
+        */
+       for (i = 0; i < send; i++) {
+               snd = (u32)dma_start[i];
+               fsi_reg_write(fsi, DODT, snd << 8);
+       }
+}
+
+static void fsi_32data_push(struct fsi_priv *fsi,
+                          struct snd_pcm_runtime *runtime,
+                          int send)
+{
+       u32 *dma_start;
+
+       /* get dma start position for FSI */
+       dma_start = (u32 *)runtime->dma_area;
+       dma_start += fsi->byte_offset / 4;
+
+       dma_wait_for_completion(fsi->dma_chan);
+       dma_configure_channel(fsi->dma_chan, (SM_INC|0x400|TS_32|TM_BUR));
+       dma_write(fsi->dma_chan, (u32)dma_start,
+                 (u32)(fsi->base + DODT), send * 4);
+}
+
+/* playback interrupt */
+static int fsi_data_push(struct fsi_priv *fsi)
+{
+       struct snd_pcm_runtime *runtime;
+       struct snd_pcm_substream *substream = NULL;
+       int send;
+       int fifo_free;
+       int width;
+
+       if (!fsi                        ||
+           !fsi->substream             ||
+           !fsi->substream->runtime)
+               return -EINVAL;
+
+       runtime = fsi->substream->runtime;
+
+       /* FSI FIFO has limit.
+        * So, this driver can not send periods data at a time
+        */
+       if (fsi->byte_offset >=
+           fsi->period_len * (fsi->periods + 1)) {
+
+               substream = fsi->substream;
+               fsi->periods = (fsi->periods + 1) % runtime->periods;
+
+               if (0 == fsi->periods)
+                       fsi->byte_offset = 0;
+       }
+
+       /* get 1 channel data width */
+       width = frames_to_bytes(runtime, 1) / fsi->chan;
+
+       /* get send size for alsa */
+       send = (fsi->buffer_len - fsi->byte_offset) / width;
+
+       /*  get FIFO free size */
+       fifo_free = (fsi->fifo_max * fsi->chan) - fsi_get_fifo_residue(fsi, 1);
+
+       /* size check */
+       if (fifo_free < send)
+               send = fifo_free;
+
+       if (2 == width)
+               fsi_16data_push(fsi, runtime, send);
+       else if (4 == width)
+               fsi_32data_push(fsi, runtime, send);
+       else
+               return -EINVAL;
+
+       fsi->byte_offset += send * width;
+
+       fsi_irq_enable(fsi, 1);
+
+       if (substream)
+               snd_pcm_period_elapsed(substream);
+
+       return 0;
+}
+
+static irqreturn_t fsi_interrupt(int irq, void *data)
+{
+       u32 status = fsi_master_read(SOFT_RST) & ~0x00000010;
+       u32 int_st = fsi_master_read(INT_ST);
+
+       /* clear irq status */
+       fsi_master_write(SOFT_RST, status);
+       fsi_master_write(SOFT_RST, status | 0x00000010);
+
+       if (int_st & INT_A_OUT)
+               fsi_data_push(&master->fsia);
+       if (int_st & INT_B_OUT)
+               fsi_data_push(&master->fsib);
+
+       fsi_master_write(INT_ST, 0x0000000);
+
+       return IRQ_HANDLED;
+}
+
+/************************************************************************
+
+
+               dai ops
+
+
+************************************************************************/
+static int fsi_dai_startup(struct snd_pcm_substream *substream,
+                          struct snd_soc_dai *dai)
+{
+       struct fsi_priv *fsi = fsi_get(substream);
+       const char *msg;
+       u32 flags = fsi_get_info_flags(fsi);
+       u32 fmt;
+       u32 reg;
+       u32 data;
+       int is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       int is_master;
+       int ret = 0;
+
+       clk_enable(master->clk);
+
+       /* CKG1 */
+       data = is_play ? (1 << 0) : (1 << 4);
+       is_master = fsi_is_master_mode(fsi, is_play);
+       if (is_master)
+               fsi_reg_mask_set(fsi, CKG1, data, data);
+       else
+               fsi_reg_mask_set(fsi, CKG1, data, 0);
+
+       /* clock inversion (CKG2) */
+       data = 0;
+       switch (SH_FSI_INVERSION_MASK & flags) {
+       case SH_FSI_LRM_INV:
+               data = 1 << 12;
+               break;
+       case SH_FSI_BRM_INV:
+               data = 1 << 8;
+               break;
+       case SH_FSI_LRS_INV:
+               data = 1 << 4;
+               break;
+       case SH_FSI_BRS_INV:
+               data = 1 << 0;
+               break;
+       }
+       fsi_reg_write(fsi, CKG2, data);
+
+       /* do fmt, di fmt */
+       data = 0;
+       reg = is_play ? DO_FMT : DI_FMT;
+       fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags);
+       switch (fmt) {
+       case SH_FSI_FMT_MONO:
+               msg = "MONO";
+               data = CR_FMT(CR_MONO);
+               fsi->chan = 1;
+               break;
+       case SH_FSI_FMT_MONO_DELAY:
+               msg = "MONO Delay";
+               data = CR_FMT(CR_MONO_D);
+               fsi->chan = 1;
+               break;
+       case SH_FSI_FMT_PCM:
+               msg = "PCM";
+               data = CR_FMT(CR_PCM);
+               fsi->chan = 2;
+               break;
+       case SH_FSI_FMT_I2S:
+               msg = "I2S";
+               data = CR_FMT(CR_I2S);
+               fsi->chan = 2;
+               break;
+       case SH_FSI_FMT_TDM:
+               msg = "TDM";
+               data = CR_FMT(CR_TDM) | (fsi->chan - 1);
+               fsi->chan = is_play ?
+                       SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
+               break;
+       case SH_FSI_FMT_TDM_DELAY:
+               msg = "TDM Delay";
+               data = CR_FMT(CR_TDM_D) | (fsi->chan - 1);
+               fsi->chan = is_play ?
+                       SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
+               break;
+       default:
+               dev_err(dai->dev, "unknown format.\n");
+               return -EINVAL;
+       }
+
+       switch (fsi->chan) {
+       case 1:
+               fsi->fifo_max = 256;
+               break;
+       case 2:
+               fsi->fifo_max = 128;
+               break;
+       case 3:
+       case 4:
+               fsi->fifo_max = 64;
+               break;
+       case 5:
+       case 6:
+       case 7:
+       case 8:
+               fsi->fifo_max = 32;
+               break;
+       default:
+               dev_err(dai->dev, "channel size error.\n");
+               return -EINVAL;
+       }
+
+       fsi_reg_write(fsi, reg, data);
+       dev_dbg(dai->dev, "use %s format (%d channel) use %d DMAC\n",
+               msg, fsi->chan, fsi->dma_chan);
+
+       /*
+        * clear clk reset if master mode
+        */
+       if (is_master)
+               fsi_clk_ctrl(fsi, 1);
+
+       /* irq setting */
+       fsi_irq_init(fsi, is_play);
+
+       return ret;
+}
+
+static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
+                            struct snd_soc_dai *dai)
+{
+       struct fsi_priv *fsi = fsi_get(substream);
+       int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+
+       fsi_irq_disable(fsi, is_play);
+       fsi_clk_ctrl(fsi, 0);
+
+       clk_disable(master->clk);
+}
+
+static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+                          struct snd_soc_dai *dai)
+{
+       struct fsi_priv *fsi = fsi_get(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+       int ret = 0;
+
+       /* capture not supported */
+       if (!is_play)
+               return -ENODEV;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               fsi_stream_push(fsi, substream,
+                               frames_to_bytes(runtime, runtime->buffer_size),
+                               frames_to_bytes(runtime, runtime->period_size));
+               ret = fsi_data_push(fsi);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               fsi_irq_disable(fsi, is_play);
+               fsi_stream_pop(fsi);
+               break;
+       }
+
+       return ret;
+}
+
+static struct snd_soc_dai_ops fsi_dai_ops = {
+       .startup        = fsi_dai_startup,
+       .shutdown       = fsi_dai_shutdown,
+       .trigger        = fsi_dai_trigger,
+};
+
+/************************************************************************
+
+
+               pcm ops
+
+
+************************************************************************/
+static struct snd_pcm_hardware fsi_pcm_hardware = {
+       .info =         SNDRV_PCM_INFO_INTERLEAVED      |
+                       SNDRV_PCM_INFO_MMAP             |
+                       SNDRV_PCM_INFO_MMAP_VALID       |
+                       SNDRV_PCM_INFO_PAUSE,
+       .formats                = FSI_FMTS,
+       .rates                  = FSI_RATES,
+       .rate_min               = 8000,
+       .rate_max               = 192000,
+       .channels_min           = 1,
+       .channels_max           = 2,
+       .buffer_bytes_max       = 64 * 1024,
+       .period_bytes_min       = 32,
+       .period_bytes_max       = 8192,
+       .periods_min            = 1,
+       .periods_max            = 32,
+       .fifo_size              = 256,
+};
+
+static int fsi_pcm_open(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int ret = 0;
+
+       snd_soc_set_runtime_hwparams(substream, &fsi_pcm_hardware);
+
+       ret = snd_pcm_hw_constraint_integer(runtime,
+                                           SNDRV_PCM_HW_PARAM_PERIODS);
+
+       return ret;
+}
+
+static int fsi_hw_params(struct snd_pcm_substream *substream,
+                        struct snd_pcm_hw_params *hw_params)
+{
+       return snd_pcm_lib_malloc_pages(substream,
+                                       params_buffer_bytes(hw_params));
+}
+
+static int fsi_hw_free(struct snd_pcm_substream *substream)
+{
+       return snd_pcm_lib_free_pages(substream);
+}
+
+static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct fsi_priv *fsi = fsi_get(substream);
+       int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+       long location;
+
+       location = (fsi->byte_offset - 1) - fsi_get_residue(fsi, is_play);
+       if (location < 0)
+               location = 0;
+
+       return bytes_to_frames(runtime, location);
+}
+
+static struct snd_pcm_ops fsi_pcm_ops = {
+       .open           = fsi_pcm_open,
+       .ioctl          = snd_pcm_lib_ioctl,
+       .hw_params      = fsi_hw_params,
+       .hw_free        = fsi_hw_free,
+       .pointer        = fsi_pointer,
+};
+
+/************************************************************************
+
+
+               snd_soc_platform
+
+
+************************************************************************/
+#define PREALLOC_BUFFER                (32 * 1024)
+#define PREALLOC_BUFFER_MAX    (32 * 1024)
+
+static void fsi_pcm_free(struct snd_pcm *pcm)
+{
+       snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
+static int fsi_pcm_new(struct snd_card *card,
+                      struct snd_soc_dai *dai,
+                      struct snd_pcm *pcm)
+{
+       /*
+        * dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel
+        * in MMAP mode (i.e. aplay -M)
+        */
+       return snd_pcm_lib_preallocate_pages_for_all(
+               pcm,
+               SNDRV_DMA_TYPE_CONTINUOUS,
+               snd_dma_continuous_data(GFP_KERNEL),
+               PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
+}
+
+/************************************************************************
+
+
+               alsa struct
+
+
+************************************************************************/
+struct snd_soc_dai fsi_soc_dai[] = {
+       {
+               .name                   = "FSIA",
+               .id                     = 0,
+               .playback = {
+                       .rates          = FSI_RATES,
+                       .formats        = FSI_FMTS,
+                       .channels_min   = 1,
+                       .channels_max   = 8,
+               },
+               /* capture not supported */
+               .ops = &fsi_dai_ops,
+       },
+       {
+               .name                   = "FSIB",
+               .id                     = 1,
+               .playback = {
+                       .rates          = FSI_RATES,
+                       .formats        = FSI_FMTS,
+                       .channels_min   = 1,
+                       .channels_max   = 8,
+               },
+               /* capture not supported */
+               .ops = &fsi_dai_ops,
+       },
+};
+EXPORT_SYMBOL_GPL(fsi_soc_dai);
+
+struct snd_soc_platform fsi_soc_platform = {
+       .name           = "fsi-pcm",
+       .pcm_ops        = &fsi_pcm_ops,
+       .pcm_new        = fsi_pcm_new,
+       .pcm_free       = fsi_pcm_free,
+};
+EXPORT_SYMBOL_GPL(fsi_soc_platform);
+
+/************************************************************************
+
+
+               platform function
+
+
+************************************************************************/
+static int fsi_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       char clk_name[8];
+       unsigned int irq;
+       int ret;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       irq = platform_get_irq(pdev, 0);
+       if (!res || !irq) {
+               dev_err(&pdev->dev, "Not enough FSI platform resources.\n");
+               ret = -ENODEV;
+               goto exit;
+       }
+
+       master = kzalloc(sizeof(*master), GFP_KERNEL);
+       if (!master) {
+               dev_err(&pdev->dev, "Could not allocate master\n");
+               ret = -ENOMEM;
+               goto exit;
+       }
+
+       master->base = ioremap_nocache(res->start, resource_size(res));
+       if (!master->base) {
+               ret = -ENXIO;
+               dev_err(&pdev->dev, "Unable to ioremap FSI registers.\n");
+               goto exit_kfree;
+       }
+
+       master->irq             = irq;
+       master->info            = pdev->dev.platform_data;
+       master->fsia.base       = master->base;
+       master->fsib.base       = master->base + 0x40;
+
+       master->fsia.dma_chan = -1;
+       master->fsib.dma_chan = -1;
+
+       ret = fsi_get_dma_chan();
+       if (ret < 0) {
+               dev_err(&pdev->dev, "cannot get dma api\n");
+               goto exit_iounmap;
+       }
+
+       /* FSI is based on SPU mstp */
+       snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id);
+       master->clk = clk_get(NULL, clk_name);
+       if (IS_ERR(master->clk)) {
+               dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name);
+               ret = -EIO;
+               goto exit_free_dma;
+       }
+
+       fsi_soc_dai[0].dev              = &pdev->dev;
+       fsi_soc_dai[1].dev              = &pdev->dev;
+
+       fsi_soft_all_reset();
+
+       ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master);
+       if (ret) {
+               dev_err(&pdev->dev, "irq request err\n");
+               goto exit_free_dma;
+       }
+
+       ret = snd_soc_register_platform(&fsi_soc_platform);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "cannot snd soc register\n");
+               goto exit_free_irq;
+       }
+
+       return snd_soc_register_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
+
+exit_free_irq:
+       free_irq(irq, master);
+exit_free_dma:
+       fsi_free_dma_chan();
+exit_iounmap:
+       iounmap(master->base);
+exit_kfree:
+       kfree(master);
+       master = NULL;
+exit:
+       return ret;
+}
+
+static int fsi_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
+       snd_soc_unregister_platform(&fsi_soc_platform);
+
+       clk_put(master->clk);
+
+       fsi_free_dma_chan();
+
+       free_irq(master->irq, master);
+
+       iounmap(master->base);
+       kfree(master);
+       master = NULL;
+       return 0;
+}
+
+static struct platform_driver fsi_driver = {
+       .driver         = {
+               .name   = "sh_fsi",
+       },
+       .probe          = fsi_probe,
+       .remove         = fsi_remove,
+};
+
+static int __init fsi_mobile_init(void)
+{
+       return platform_driver_register(&fsi_driver);
+}
+
+static void __exit fsi_mobile_exit(void)
+{
+       platform_driver_unregister(&fsi_driver);
+}
+module_init(fsi_mobile_init);
+module_exit(fsi_mobile_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SuperH onchip FSI audio driver");
+MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
new file mode 100644 (file)
index 0000000..c8ceddc
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * soc-cache.c  --  ASoC register cache helpers
+ *
+ * Copyright 2009 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.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/i2c.h>
+#include <linux/spi/spi.h>
+#include <sound/soc.h>
+
+static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
+                                    unsigned int reg)
+{
+       u16 *cache = codec->reg_cache;
+       if (reg >= codec->reg_cache_size)
+               return -1;
+       return cache[reg];
+}
+
+static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
+                            unsigned int value)
+{
+       u16 *cache = codec->reg_cache;
+       u8 data[2];
+       int ret;
+
+       BUG_ON(codec->volatile_register);
+
+       data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+       data[1] = value & 0x00ff;
+
+       if (reg < codec->reg_cache_size)
+               cache[reg] = value;
+       ret = codec->hw_write(codec->control_data, data, 2);
+       if (ret == 2)
+               return 0;
+       if (ret < 0)
+               return ret;
+       else
+               return -EIO;
+}
+
+#if defined(CONFIG_SPI_MASTER)
+static int snd_soc_7_9_spi_write(void *control_data, const char *data,
+                                int len)
+{
+       struct spi_device *spi = control_data;
+       struct spi_transfer t;
+       struct spi_message m;
+       u8 msg[2];
+
+       if (len <= 0)
+               return 0;
+
+       msg[0] = data[0];
+       msg[1] = data[1];
+
+       spi_message_init(&m);
+       memset(&t, 0, (sizeof t));
+
+       t.tx_buf = &msg[0];
+       t.len = len;
+
+       spi_message_add_tail(&t, &m);
+       spi_sync(spi, &m);
+
+       return len;
+}
+#else
+#define snd_soc_7_9_spi_write NULL
+#endif
+
+static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
+                             unsigned int value)
+{
+       u16 *reg_cache = codec->reg_cache;
+       u8 data[3];
+
+       data[0] = reg;
+       data[1] = (value >> 8) & 0xff;
+       data[2] = value & 0xff;
+
+       if (!snd_soc_codec_volatile_register(codec, reg))
+               reg_cache[reg] = value;
+
+       if (codec->hw_write(codec->control_data, data, 3) == 3)
+               return 0;
+       else
+               return -EIO;
+}
+
+static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
+                                     unsigned int reg)
+{
+       u16 *cache = codec->reg_cache;
+
+       if (reg >= codec->reg_cache_size ||
+           snd_soc_codec_volatile_register(codec, reg))
+               return codec->hw_read(codec, reg);
+       else
+               return cache[reg];
+}
+
+#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
+static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
+                                         unsigned int r)
+{
+       struct i2c_msg xfer[2];
+       u8 reg = r;
+       u16 data;
+       int ret;
+       struct i2c_client *client = codec->control_data;
+
+       /* Write register */
+       xfer[0].addr = client->addr;
+       xfer[0].flags = 0;
+       xfer[0].len = 1;
+       xfer[0].buf = &reg;
+
+       /* Read data */
+       xfer[1].addr = client->addr;
+       xfer[1].flags = I2C_M_RD;
+       xfer[1].len = 2;
+       xfer[1].buf = (u8 *)&data;
+
+       ret = i2c_transfer(client->adapter, xfer, 2);
+       if (ret != 2) {
+               dev_err(&client->dev, "i2c_transfer() returned %d\n", ret);
+               return 0;
+       }
+
+       return (data >> 8) | ((data & 0xff) << 8);
+}
+#else
+#define snd_soc_8_16_read_i2c NULL
+#endif
+
+static struct {
+       int addr_bits;
+       int data_bits;
+       int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
+       int (*spi_write)(void *, const char *, int);
+       unsigned int (*read)(struct snd_soc_codec *, unsigned int);
+       unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
+} io_types[] = {
+       { 7, 9, snd_soc_7_9_write, snd_soc_7_9_spi_write, snd_soc_7_9_read },
+       { 8, 16, snd_soc_8_16_write, NULL, snd_soc_8_16_read,
+         snd_soc_8_16_read_i2c },
+};
+
+/**
+ * snd_soc_codec_set_cache_io: Set up standard I/O functions.
+ *
+ * @codec: CODEC to configure.
+ * @type: Type of cache.
+ * @addr_bits: Number of bits of register address data.
+ * @data_bits: Number of bits of data per register.
+ * @control: Control bus used.
+ *
+ * Register formats are frequently shared between many I2C and SPI
+ * devices.  In order to promote code reuse the ASoC core provides
+ * some standard implementations of CODEC read and write operations
+ * which can be set up using this function.
+ *
+ * The caller is responsible for allocating and initialising the
+ * actual cache.
+ *
+ * Note that at present this code cannot be used by CODECs with
+ * volatile registers.
+ */
+int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
+                              int addr_bits, int data_bits,
+                              enum snd_soc_control_type control)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(io_types); i++)
+               if (io_types[i].addr_bits == addr_bits &&
+                   io_types[i].data_bits == data_bits)
+                       break;
+       if (i == ARRAY_SIZE(io_types)) {
+               printk(KERN_ERR
+                      "No I/O functions for %d bit address %d bit data\n",
+                      addr_bits, data_bits);
+               return -EINVAL;
+       }
+
+       codec->write = io_types[i].write;
+       codec->read = io_types[i].read;
+
+       switch (control) {
+       case SND_SOC_CUSTOM:
+               break;
+
+       case SND_SOC_I2C:
+#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
+               codec->hw_write = (hw_write_t)i2c_master_send;
+#endif
+               if (io_types[i].i2c_read)
+                       codec->hw_read = io_types[i].i2c_read;
+               break;
+
+       case SND_SOC_SPI:
+               if (io_types[i].spi_write)
+                       codec->hw_write = io_types[i].spi_write;
+               break;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
index 1d70829464ef3698c85df7918b9c0c4acfaf1239..7ff04ad2a97e0511d7b31d49cb7b481c9c0214ed 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/bitops.h>
 #include <linux/debugfs.h>
 #include <linux/platform_device.h>
+#include <sound/ac97_codec.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -619,8 +620,9 @@ static struct snd_pcm_ops soc_pcm_ops = {
 
 #ifdef CONFIG_PM
 /* powers down audio subsystem for suspend */
-static int soc_suspend(struct platform_device *pdev, pm_message_t state)
+static int soc_suspend(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_card *card = socdev->card;
        struct snd_soc_platform *platform = card->platform;
@@ -656,7 +658,7 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
                snd_pcm_suspend_all(card->dai_link[i].pcm);
 
        if (card->suspend_pre)
-               card->suspend_pre(pdev, state);
+               card->suspend_pre(pdev, PMSG_SUSPEND);
 
        for (i = 0; i < card->num_links; i++) {
                struct snd_soc_dai  *cpu_dai = card->dai_link[i].cpu_dai;
@@ -682,7 +684,7 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
        }
 
        if (codec_dev->suspend)
-               codec_dev->suspend(pdev, state);
+               codec_dev->suspend(pdev, PMSG_SUSPEND);
 
        for (i = 0; i < card->num_links; i++) {
                struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
@@ -691,7 +693,7 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
        }
 
        if (card->suspend_post)
-               card->suspend_post(pdev, state);
+               card->suspend_post(pdev, PMSG_SUSPEND);
 
        return 0;
 }
@@ -765,8 +767,9 @@ static void soc_resume_deferred(struct work_struct *work)
 }
 
 /* powers up audio subsystem after a suspend */
-static int soc_resume(struct platform_device *pdev)
+static int soc_resume(struct device *dev)
 {
+       struct platform_device *pdev = to_platform_device(dev);
        struct snd_soc_device *socdev = platform_get_drvdata(pdev);
        struct snd_soc_card *card = socdev->card;
        struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai;
@@ -788,6 +791,44 @@ static int soc_resume(struct platform_device *pdev)
        return 0;
 }
 
+/**
+ * snd_soc_suspend_device: Notify core of device suspend
+ *
+ * @dev: Device being suspended.
+ *
+ * In order to ensure that the entire audio subsystem is suspended in a
+ * coordinated fashion ASoC devices should suspend themselves when
+ * called by ASoC.  When the standard kernel suspend process asks the
+ * device to suspend it should call this function to initiate a suspend
+ * of the entire ASoC card.
+ *
+ * \note Currently this function is stubbed out.
+ */
+int snd_soc_suspend_device(struct device *dev)
+{
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_suspend_device);
+
+/**
+ * snd_soc_resume_device: Notify core of device resume
+ *
+ * @dev: Device being resumed.
+ *
+ * In order to ensure that the entire audio subsystem is resumed in a
+ * coordinated fashion ASoC devices should resume themselves when called
+ * by ASoC.  When the standard kernel resume process asks the device
+ * to resume it should call this function.  Once all the components of
+ * the card have notified that they are ready to be resumed the card
+ * will be resumed.
+ *
+ * \note Currently this function is stubbed out.
+ */
+int snd_soc_resume_device(struct device *dev)
+{
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_resume_device);
 #else
 #define soc_suspend    NULL
 #define soc_resume     NULL
@@ -981,16 +1022,39 @@ static int soc_remove(struct platform_device *pdev)
        return 0;
 }
 
+static int soc_poweroff(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+       struct snd_soc_card *card = socdev->card;
+
+       if (!card->instantiated)
+               return 0;
+
+       /* Flush out pmdown_time work - we actually do want to run it
+        * now, we're shutting down so no imminent restart. */
+       run_delayed_work(&card->delayed_work);
+
+       snd_soc_dapm_shutdown(socdev);
+
+       return 0;
+}
+
+static struct dev_pm_ops soc_pm_ops = {
+       .suspend = soc_suspend,
+       .resume = soc_resume,
+       .poweroff = soc_poweroff,
+};
+
 /* ASoC platform driver */
 static struct platform_driver soc_driver = {
        .driver         = {
                .name           = "soc-audio",
                .owner          = THIS_MODULE,
+               .pm             = &soc_pm_ops,
        },
        .probe          = soc_probe,
        .remove         = soc_remove,
-       .suspend        = soc_suspend,
-       .resume         = soc_resume,
 };
 
 /* create a new pcm */
@@ -1062,6 +1126,23 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
        return ret;
 }
 
+/**
+ * snd_soc_codec_volatile_register: Report if a register is volatile.
+ *
+ * @codec: CODEC to query.
+ * @reg: Register to query.
+ *
+ * Boolean function indiciating if a CODEC register is volatile.
+ */
+int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg)
+{
+       if (codec->volatile_register)
+               return codec->volatile_register(reg);
+       else
+               return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register);
+
 /* codec register dump */
 static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
 {
@@ -1075,6 +1156,9 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
 
        count += sprintf(buf, "%s registers\n", codec->name);
        for (i = 0; i < codec->reg_cache_size; i += step) {
+               if (codec->readable_register && !codec->readable_register(i))
+                       continue;
+
                count += sprintf(buf + count, "%2x: ", i);
                if (count >= PAGE_SIZE - 1)
                        break;
@@ -1183,10 +1267,18 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
        if (!codec->debugfs_pop_time)
                printk(KERN_WARNING
                       "Failed to create pop time debugfs file\n");
+
+       codec->debugfs_dapm = debugfs_create_dir("dapm", debugfs_root);
+       if (!codec->debugfs_dapm)
+               printk(KERN_WARNING
+                      "Failed to create DAPM debugfs directory\n");
+
+       snd_soc_dapm_debugfs_init(codec);
 }
 
 static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
 {
+       debugfs_remove_recursive(codec->debugfs_dapm);
        debugfs_remove(codec->debugfs_pop_time);
        debugfs_remove(codec->debugfs_reg);
 }
@@ -1264,10 +1356,10 @@ EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec);
  * Returns 1 for change else 0.
  */
 int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
-                               unsigned short mask, unsigned short value)
+                               unsigned int mask, unsigned int value)
 {
        int change;
-       unsigned short old, new;
+       unsigned int old, new;
 
        mutex_lock(&io_mutex);
        old = snd_soc_read(codec, reg);
@@ -1294,10 +1386,10 @@ EXPORT_SYMBOL_GPL(snd_soc_update_bits);
  * Returns 1 for change else 0.
  */
 int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
-                               unsigned short mask, unsigned short value)
+                               unsigned int mask, unsigned int value)
 {
        int change;
-       unsigned short old, new;
+       unsigned int old, new;
 
        mutex_lock(&io_mutex);
        old = snd_soc_read(codec, reg);
@@ -1381,8 +1473,11 @@ int snd_soc_init_card(struct snd_soc_device *socdev)
                                continue;
                        }
                }
-               if (card->dai_link[i].codec_dai->ac97_control)
+               if (card->dai_link[i].codec_dai->ac97_control) {
                        ac97 = 1;
+                       snd_ac97_dev_add_pdata(codec->ac97,
+                               card->dai_link[i].cpu_dai->ac97_pdata);
+               }
        }
        snprintf(codec->card->shortname, sizeof(codec->card->shortname),
                 "%s",  card->name);
@@ -1586,7 +1681,7 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
-       unsigned short val, bitmask;
+       unsigned int val, bitmask;
 
        for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
                ;
@@ -1615,8 +1710,8 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
-       unsigned short val;
-       unsigned short mask, bitmask;
+       unsigned int val;
+       unsigned int mask, bitmask;
 
        for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
                ;
@@ -1652,7 +1747,7 @@ int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
-       unsigned short reg_val, val, mux;
+       unsigned int reg_val, val, mux;
 
        reg_val = snd_soc_read(codec, e->reg);
        val = (reg_val >> e->shift_l) & e->mask;
@@ -1691,8 +1786,8 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
-       unsigned short val;
-       unsigned short mask;
+       unsigned int val;
+       unsigned int mask;
 
        if (ucontrol->value.enumerated.item[0] > e->max - 1)
                return -EINVAL;
@@ -1852,7 +1947,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
        int max = mc->max;
        unsigned int mask = (1 << fls(max)) - 1;
        unsigned int invert = mc->invert;
-       unsigned short val, val2, val_mask;
+       unsigned int val, val2, val_mask;
 
        val = (ucontrol->value.integer.value[0] & mask);
        if (invert)
@@ -1918,7 +2013,7 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
        unsigned int reg2 = mc->rreg;
        unsigned int shift = mc->shift;
        int max = mc->max;
-       unsigned int mask = (1<<fls(max))-1;
+       unsigned int mask = (1 << fls(max)) - 1;
        unsigned int invert = mc->invert;
 
        ucontrol->value.integer.value[0] =
@@ -1958,7 +2053,7 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
        unsigned int mask = (1 << fls(max)) - 1;
        unsigned int invert = mc->invert;
        int err;
-       unsigned short val, val2, val_mask;
+       unsigned int val, val2, val_mask;
 
        val_mask = mask << shift;
        val = (ucontrol->value.integer.value[0] & mask);
@@ -2050,7 +2145,7 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        unsigned int reg = mc->reg;
        int min = mc->min;
-       unsigned short val;
+       unsigned int val;
 
        val = (ucontrol->value.integer.value[0]+min) & 0xff;
        val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8;
@@ -2136,17 +2231,20 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
 /**
  * snd_soc_dai_set_tdm_slot - configure DAI TDM.
  * @dai: DAI
- * @mask: DAI specific mask representing used slots.
+ * @tx_mask: bitmask representing active TX slots.
+ * @rx_mask: bitmask representing active RX slots.
  * @slots: Number of slots in use.
+ * @slot_width: Width in bits for each slot.
  *
  * Configures a DAI for TDM operation. Both mask and slots are codec and DAI
  * specific.
  */
 int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
-       unsigned int mask, int slots)
+       unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
 {
        if (dai->ops && dai->ops->set_tdm_slot)
-               return dai->ops->set_tdm_slot(dai, mask, slots);
+               return dai->ops->set_tdm_slot(dai, tx_mask, rx_mask,
+                               slots, slot_width);
        else
                return -EINVAL;
 }
index 21c69074aa17a1819f7bb4b95255cafa7c57a433..f79711b9fa5b9c58de8c156b30ff0e613bf26664 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/bitops.h>
 #include <linux/platform_device.h>
 #include <linux/jiffies.h>
+#include <linux/debugfs.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 
 /* dapm power sequences - make this per codec in the future */
 static int dapm_up_seq[] = {
-       snd_soc_dapm_pre, snd_soc_dapm_supply, snd_soc_dapm_micbias,
-       snd_soc_dapm_mic, snd_soc_dapm_mux, snd_soc_dapm_value_mux,
-       snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl,
-       snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
-       snd_soc_dapm_post
+       [snd_soc_dapm_pre] = 0,
+       [snd_soc_dapm_supply] = 1,
+       [snd_soc_dapm_micbias] = 2,
+       [snd_soc_dapm_aif_in] = 3,
+       [snd_soc_dapm_aif_out] = 3,
+       [snd_soc_dapm_mic] = 4,
+       [snd_soc_dapm_mux] = 5,
+       [snd_soc_dapm_value_mux] = 5,
+       [snd_soc_dapm_dac] = 6,
+       [snd_soc_dapm_mixer] = 7,
+       [snd_soc_dapm_mixer_named_ctl] = 7,
+       [snd_soc_dapm_pga] = 8,
+       [snd_soc_dapm_adc] = 9,
+       [snd_soc_dapm_hp] = 10,
+       [snd_soc_dapm_spk] = 10,
+       [snd_soc_dapm_post] = 11,
 };
 
 static int dapm_down_seq[] = {
-       snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
-       snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer,
-       snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias,
-       snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_supply,
-       snd_soc_dapm_post
+       [snd_soc_dapm_pre] = 0,
+       [snd_soc_dapm_adc] = 1,
+       [snd_soc_dapm_hp] = 2,
+       [snd_soc_dapm_spk] = 2,
+       [snd_soc_dapm_pga] = 4,
+       [snd_soc_dapm_mixer_named_ctl] = 5,
+       [snd_soc_dapm_mixer] = 5,
+       [snd_soc_dapm_dac] = 6,
+       [snd_soc_dapm_mic] = 7,
+       [snd_soc_dapm_micbias] = 8,
+       [snd_soc_dapm_mux] = 9,
+       [snd_soc_dapm_value_mux] = 9,
+       [snd_soc_dapm_aif_in] = 10,
+       [snd_soc_dapm_aif_out] = 10,
+       [snd_soc_dapm_supply] = 11,
+       [snd_soc_dapm_post] = 12,
 };
 
 static void pop_wait(u32 pop_time)
@@ -130,8 +153,12 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
 
        if (card->set_bias_level)
                ret = card->set_bias_level(card, level);
-       if (ret == 0 && codec->set_bias_level)
-               ret = codec->set_bias_level(codec, level);
+       if (ret == 0) {
+               if (codec->set_bias_level)
+                       ret = codec->set_bias_level(codec, level);
+               else
+                       codec->bias_level = level;
+       }
 
        return ret;
 }
@@ -206,6 +233,8 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
        case snd_soc_dapm_micbias:
        case snd_soc_dapm_vmid:
        case snd_soc_dapm_supply:
+       case snd_soc_dapm_aif_in:
+       case snd_soc_dapm_aif_out:
                p->connect = 1;
        break;
        /* does effect routing - dynamically connected */
@@ -268,7 +297,7 @@ static int dapm_connect_mixer(struct snd_soc_codec *codec,
 static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
 {
        int change, power;
-       unsigned short old, new;
+       unsigned int old, new;
        struct snd_soc_codec *codec = widget->codec;
 
        /* check for valid widgets */
@@ -479,8 +508,14 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
        if (widget->id == snd_soc_dapm_supply)
                return 0;
 
-       if (widget->id == snd_soc_dapm_adc && widget->active)
-               return 1;
+       switch (widget->id) {
+       case snd_soc_dapm_adc:
+       case snd_soc_dapm_aif_out:
+               if (widget->active)
+                       return 1;
+       default:
+               break;
+       }
 
        if (widget->connected) {
                /* connected pin ? */
@@ -519,8 +554,14 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
                return 0;
 
        /* active stream ? */
-       if (widget->id == snd_soc_dapm_dac && widget->active)
-               return 1;
+       switch (widget->id) {
+       case snd_soc_dapm_dac:
+       case snd_soc_dapm_aif_in:
+               if (widget->active)
+                       return 1;
+       default:
+               break;
+       }
 
        if (widget->connected) {
                /* connected pin ? */
@@ -689,53 +730,211 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
        return power;
 }
 
-/*
- * Scan a single DAPM widget for a complete audio path and update the
- * power status appropriately.
- */
-static int dapm_power_widget(struct snd_soc_codec *codec, int event,
-                            struct snd_soc_dapm_widget *w)
+static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
+                           struct snd_soc_dapm_widget *b,
+                           int sort[])
 {
-       int ret;
+       if (sort[a->id] != sort[b->id])
+               return sort[a->id] - sort[b->id];
+       if (a->reg != b->reg)
+               return a->reg - b->reg;
 
-       switch (w->id) {
-       case snd_soc_dapm_pre:
-               if (!w->event)
-                       return 0;
+       return 0;
+}
 
-               if (event == SND_SOC_DAPM_STREAM_START) {
-                       ret = w->event(w,
-                                      NULL, SND_SOC_DAPM_PRE_PMU);
+/* Insert a widget in order into a DAPM power sequence. */
+static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
+                           struct list_head *list,
+                           int sort[])
+{
+       struct snd_soc_dapm_widget *w;
+
+       list_for_each_entry(w, list, power_list)
+               if (dapm_seq_compare(new_widget, w, sort) < 0) {
+                       list_add_tail(&new_widget->power_list, &w->power_list);
+                       return;
+               }
+
+       list_add_tail(&new_widget->power_list, list);
+}
+
+/* Apply the coalesced changes from a DAPM sequence */
+static void dapm_seq_run_coalesced(struct snd_soc_codec *codec,
+                                  struct list_head *pending)
+{
+       struct snd_soc_dapm_widget *w;
+       int reg, power, ret;
+       unsigned int value = 0;
+       unsigned int mask = 0;
+       unsigned int cur_mask;
+
+       reg = list_first_entry(pending, struct snd_soc_dapm_widget,
+                              power_list)->reg;
+
+       list_for_each_entry(w, pending, power_list) {
+               cur_mask = 1 << w->shift;
+               BUG_ON(reg != w->reg);
+
+               if (w->invert)
+                       power = !w->power;
+               else
+                       power = w->power;
+
+               mask |= cur_mask;
+               if (power)
+                       value |= cur_mask;
+
+               pop_dbg(codec->pop_time,
+                       "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
+                       w->name, reg, value, mask);
+
+               /* power up pre event */
+               if (w->power && w->event &&
+                   (w->event_flags & SND_SOC_DAPM_PRE_PMU)) {
+                       pop_dbg(codec->pop_time, "pop test : %s PRE_PMU\n",
+                               w->name);
+                       ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU);
                        if (ret < 0)
-                               return ret;
-               } else if (event == SND_SOC_DAPM_STREAM_STOP) {
-                       ret = w->event(w,
-                                      NULL, SND_SOC_DAPM_PRE_PMD);
+                               pr_err("%s: pre event failed: %d\n",
+                                      w->name, ret);
+               }
+
+               /* power down pre event */
+               if (!w->power && w->event &&
+                   (w->event_flags & SND_SOC_DAPM_PRE_PMD)) {
+                       pop_dbg(codec->pop_time, "pop test : %s PRE_PMD\n",
+                               w->name);
+                       ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD);
                        if (ret < 0)
-                               return ret;
+                               pr_err("%s: pre event failed: %d\n",
+                                      w->name, ret);
                }
-               return 0;
 
-       case snd_soc_dapm_post:
-               if (!w->event)
-                       return 0;
+               /* Lower PGA volume to reduce pops */
+               if (w->id == snd_soc_dapm_pga && !w->power)
+                       dapm_set_pga(w, w->power);
+       }
 
-               if (event == SND_SOC_DAPM_STREAM_START) {
+       if (reg >= 0) {
+               pop_dbg(codec->pop_time,
+                       "pop test : Applying 0x%x/0x%x to %x in %dms\n",
+                       value, mask, reg, codec->pop_time);
+               pop_wait(codec->pop_time);
+               snd_soc_update_bits(codec, reg, mask, value);
+       }
+
+       list_for_each_entry(w, pending, power_list) {
+               /* Raise PGA volume to reduce pops */
+               if (w->id == snd_soc_dapm_pga && w->power)
+                       dapm_set_pga(w, w->power);
+
+               /* power up post event */
+               if (w->power && w->event &&
+                   (w->event_flags & SND_SOC_DAPM_POST_PMU)) {
+                       pop_dbg(codec->pop_time, "pop test : %s POST_PMU\n",
+                               w->name);
                        ret = w->event(w,
                                       NULL, SND_SOC_DAPM_POST_PMU);
                        if (ret < 0)
-                               return ret;
-               } else if (event == SND_SOC_DAPM_STREAM_STOP) {
-                       ret = w->event(w,
-                                      NULL, SND_SOC_DAPM_POST_PMD);
+                               pr_err("%s: post event failed: %d\n",
+                                      w->name, ret);
+               }
+
+               /* power down post event */
+               if (!w->power && w->event &&
+                   (w->event_flags & SND_SOC_DAPM_POST_PMD)) {
+                       pop_dbg(codec->pop_time, "pop test : %s POST_PMD\n",
+                               w->name);
+                       ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD);
                        if (ret < 0)
-                               return ret;
+                               pr_err("%s: post event failed: %d\n",
+                                      w->name, ret);
                }
-               return 0;
+       }
+}
 
-       default:
-               return dapm_generic_apply_power(w);
+/* Apply a DAPM power sequence.
+ *
+ * We walk over a pre-sorted list of widgets to apply power to.  In
+ * order to minimise the number of writes to the device required
+ * multiple widgets will be updated in a single write where possible.
+ * Currently anything that requires more than a single write is not
+ * handled.
+ */
+static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list,
+                        int event, int sort[])
+{
+       struct snd_soc_dapm_widget *w, *n;
+       LIST_HEAD(pending);
+       int cur_sort = -1;
+       int cur_reg = SND_SOC_NOPM;
+       int ret;
+
+       list_for_each_entry_safe(w, n, list, power_list) {
+               ret = 0;
+
+               /* Do we need to apply any queued changes? */
+               if (sort[w->id] != cur_sort || w->reg != cur_reg) {
+                       if (!list_empty(&pending))
+                               dapm_seq_run_coalesced(codec, &pending);
+
+                       INIT_LIST_HEAD(&pending);
+                       cur_sort = -1;
+                       cur_reg = SND_SOC_NOPM;
+               }
+
+               switch (w->id) {
+               case snd_soc_dapm_pre:
+                       if (!w->event)
+                               list_for_each_entry_safe_continue(w, n, list,
+                                                                 power_list);
+
+                       if (event == SND_SOC_DAPM_STREAM_START)
+                               ret = w->event(w,
+                                              NULL, SND_SOC_DAPM_PRE_PMU);
+                       else if (event == SND_SOC_DAPM_STREAM_STOP)
+                               ret = w->event(w,
+                                              NULL, SND_SOC_DAPM_PRE_PMD);
+                       break;
+
+               case snd_soc_dapm_post:
+                       if (!w->event)
+                               list_for_each_entry_safe_continue(w, n, list,
+                                                                 power_list);
+
+                       if (event == SND_SOC_DAPM_STREAM_START)
+                               ret = w->event(w,
+                                              NULL, SND_SOC_DAPM_POST_PMU);
+                       else if (event == SND_SOC_DAPM_STREAM_STOP)
+                               ret = w->event(w,
+                                              NULL, SND_SOC_DAPM_POST_PMD);
+                       break;
+
+               case snd_soc_dapm_input:
+               case snd_soc_dapm_output:
+               case snd_soc_dapm_hp:
+               case snd_soc_dapm_mic:
+               case snd_soc_dapm_line:
+               case snd_soc_dapm_spk:
+                       /* No register support currently */
+                       ret = dapm_generic_apply_power(w);
+                       break;
+
+               default:
+                       /* Queue it up for application */
+                       cur_sort = sort[w->id];
+                       cur_reg = w->reg;
+                       list_move(&w->power_list, &pending);
+                       break;
+               }
+
+               if (ret < 0)
+                       pr_err("Failed to apply widget power: %d\n",
+                              ret);
        }
+
+       if (!list_empty(&pending))
+               dapm_seq_run_coalesced(codec, &pending);
 }
 
 /*
@@ -751,23 +950,22 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
 {
        struct snd_soc_device *socdev = codec->socdev;
        struct snd_soc_dapm_widget *w;
+       LIST_HEAD(up_list);
+       LIST_HEAD(down_list);
        int ret = 0;
-       int i, power;
+       int power;
        int sys_power = 0;
 
-       INIT_LIST_HEAD(&codec->up_list);
-       INIT_LIST_HEAD(&codec->down_list);
-
        /* Check which widgets we need to power and store them in
         * lists indicating if they should be powered up or down.
         */
        list_for_each_entry(w, &codec->dapm_widgets, list) {
                switch (w->id) {
                case snd_soc_dapm_pre:
-                       list_add_tail(&codec->down_list, &w->power_list);
+                       dapm_seq_insert(w, &down_list, dapm_down_seq);
                        break;
                case snd_soc_dapm_post:
-                       list_add_tail(&codec->up_list, &w->power_list);
+                       dapm_seq_insert(w, &up_list, dapm_up_seq);
                        break;
 
                default:
@@ -782,16 +980,31 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
                                continue;
 
                        if (power)
-                               list_add_tail(&w->power_list, &codec->up_list);
+                               dapm_seq_insert(w, &up_list, dapm_up_seq);
                        else
-                               list_add_tail(&w->power_list,
-                                             &codec->down_list);
+                               dapm_seq_insert(w, &down_list, dapm_down_seq);
 
                        w->power = power;
                        break;
                }
        }
 
+       /* If there are no DAPM widgets then try to figure out power from the
+        * event type.
+        */
+       if (list_empty(&codec->dapm_widgets)) {
+               switch (event) {
+               case SND_SOC_DAPM_STREAM_START:
+               case SND_SOC_DAPM_STREAM_RESUME:
+                       sys_power = 1;
+                       break;
+               case SND_SOC_DAPM_STREAM_NOP:
+                       sys_power = codec->bias_level != SND_SOC_BIAS_STANDBY;
+               default:
+                       break;
+               }
+       }
+
        /* If we're changing to all on or all off then prepare */
        if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) ||
            (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) {
@@ -802,32 +1015,10 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
        }
 
        /* Power down widgets first; try to avoid amplifying pops. */
-       for (i = 0; i < ARRAY_SIZE(dapm_down_seq); i++) {
-               list_for_each_entry(w, &codec->down_list, power_list) {
-                       /* is widget in stream order */
-                       if (w->id != dapm_down_seq[i])
-                               continue;
-
-                       ret = dapm_power_widget(codec, event, w);
-                       if (ret != 0)
-                               pr_err("Failed to power down %s: %d\n",
-                                      w->name, ret);
-               }
-       }
+       dapm_seq_run(codec, &down_list, event, dapm_down_seq);
 
        /* Now power up. */
-       for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) {
-               list_for_each_entry(w, &codec->up_list, power_list) {
-                       /* is widget in stream order */
-                       if (w->id != dapm_up_seq[i])
-                               continue;
-
-                       ret = dapm_power_widget(codec, event, w);
-                       if (ret != 0)
-                               pr_err("Failed to power up %s: %d\n",
-                                      w->name, ret);
-               }
-       }
+       dapm_seq_run(codec, &up_list, event, dapm_up_seq);
 
        /* If we just powered the last thing off drop to standby bias */
        if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) {
@@ -845,6 +1036,9 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
                        pr_err("Failed to apply active bias: %d\n", ret);
        }
 
+       pop_dbg(codec->pop_time, "DAPM sequencing finished, waiting %dms\n",
+               codec->pop_time);
+
        return 0;
 }
 
@@ -881,6 +1075,8 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
                case snd_soc_dapm_mixer:
                case snd_soc_dapm_mixer_named_ctl:
                case snd_soc_dapm_supply:
+               case snd_soc_dapm_aif_in:
+               case snd_soc_dapm_aif_out:
                        if (w->name) {
                                in = is_connected_input_ep(w);
                                dapm_clear_walk(w->codec);
@@ -906,6 +1102,93 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
 }
 #endif
 
+#ifdef CONFIG_DEBUG_FS
+static int dapm_widget_power_open_file(struct inode *inode, struct file *file)
+{
+       file->private_data = inode->i_private;
+       return 0;
+}
+
+static ssize_t dapm_widget_power_read_file(struct file *file,
+                                          char __user *user_buf,
+                                          size_t count, loff_t *ppos)
+{
+       struct snd_soc_dapm_widget *w = file->private_data;
+       char *buf;
+       int in, out;
+       ssize_t ret;
+       struct snd_soc_dapm_path *p = NULL;
+
+       buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       in = is_connected_input_ep(w);
+       dapm_clear_walk(w->codec);
+       out = is_connected_output_ep(w);
+       dapm_clear_walk(w->codec);
+
+       ret = snprintf(buf, PAGE_SIZE, "%s: %s  in %d out %d\n",
+                      w->name, w->power ? "On" : "Off", in, out);
+
+       if (w->sname)
+               ret += snprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
+                               w->sname,
+                               w->active ? "active" : "inactive");
+
+       list_for_each_entry(p, &w->sources, list_sink) {
+               if (p->connect)
+                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                                       " in  %s %s\n",
+                                       p->name ? p->name : "static",
+                                       p->source->name);
+       }
+       list_for_each_entry(p, &w->sinks, list_source) {
+               if (p->connect)
+                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                                       " out %s %s\n",
+                                       p->name ? p->name : "static",
+                                       p->sink->name);
+       }
+
+       ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+
+       kfree(buf);
+       return ret;
+}
+
+static const struct file_operations dapm_widget_power_fops = {
+       .open = dapm_widget_power_open_file,
+       .read = dapm_widget_power_read_file,
+};
+
+void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec)
+{
+       struct snd_soc_dapm_widget *w;
+       struct dentry *d;
+
+       if (!codec->debugfs_dapm)
+               return;
+
+       list_for_each_entry(w, &codec->dapm_widgets, list) {
+               if (!w->name)
+                       continue;
+
+               d = debugfs_create_file(w->name, 0444,
+                                       codec->debugfs_dapm, w,
+                                       &dapm_widget_power_fops);
+               if (!d)
+                       printk(KERN_WARNING
+                              "ASoC: Failed to create %s debugfs file\n",
+                              w->name);
+       }
+}
+#else
+void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec)
+{
+}
+#endif
+
 /* test and update the power status of a mux widget */
 static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
                                 struct snd_kcontrol *kcontrol, int mask,
@@ -1138,8 +1421,8 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
        if (wsink->id == snd_soc_dapm_input) {
                if (wsource->id == snd_soc_dapm_micbias ||
                        wsource->id == snd_soc_dapm_mic ||
-                       wsink->id == snd_soc_dapm_line ||
-                       wsink->id == snd_soc_dapm_output)
+                       wsource->id == snd_soc_dapm_line ||
+                       wsource->id == snd_soc_dapm_output)
                        wsink->ext = 1;
        }
        if (wsource->id == snd_soc_dapm_output) {
@@ -1171,6 +1454,8 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
        case snd_soc_dapm_pre:
        case snd_soc_dapm_post:
        case snd_soc_dapm_supply:
+       case snd_soc_dapm_aif_in:
+       case snd_soc_dapm_aif_out:
                list_add(&path->list, &codec->dapm_paths);
                list_add(&path->list_sink, &wsink->sources);
                list_add(&path->list_source, &wsource->sinks);
@@ -1273,9 +1558,11 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
                        dapm_new_mux(codec, w);
                        break;
                case snd_soc_dapm_adc:
+               case snd_soc_dapm_aif_out:
                        w->power_check = dapm_adc_check_power;
                        break;
                case snd_soc_dapm_dac:
+               case snd_soc_dapm_aif_in:
                        w->power_check = dapm_dac_check_power;
                        break;
                case snd_soc_dapm_pga:
@@ -1372,7 +1659,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
        int max = mc->max;
        unsigned int mask = (1 << fls(max)) - 1;
        unsigned int invert = mc->invert;
-       unsigned short val, val2, val_mask;
+       unsigned int val, val2, val_mask;
        int ret;
 
        val = (ucontrol->value.integer.value[0] & mask);
@@ -1436,7 +1723,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
-       unsigned short val, bitmask;
+       unsigned int val, bitmask;
 
        for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
                ;
@@ -1464,8 +1751,8 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
-       unsigned short val, mux;
-       unsigned short mask, bitmask;
+       unsigned int val, mux;
+       unsigned int mask, bitmask;
        int ret = 0;
 
        for (bitmask = 1; bitmask < e->max; bitmask <<= 1)
@@ -1523,7 +1810,7 @@ int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
-       unsigned short reg_val, val, mux;
+       unsigned int reg_val, val, mux;
 
        reg_val = snd_soc_read(widget->codec, e->reg);
        val = (reg_val >> e->shift_l) & e->mask;
@@ -1563,8 +1850,8 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
 {
        struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
-       unsigned short val, mux;
-       unsigned short mask;
+       unsigned int val, mux;
+       unsigned int mask;
        int ret = 0;
 
        if (ucontrol->value.enumerated.item[0] > e->max - 1)
@@ -1880,6 +2167,36 @@ void snd_soc_dapm_free(struct snd_soc_device *socdev)
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
 
+/*
+ * snd_soc_dapm_shutdown - callback for system shutdown
+ */
+void snd_soc_dapm_shutdown(struct snd_soc_device *socdev)
+{
+       struct snd_soc_codec *codec = socdev->card->codec;
+       struct snd_soc_dapm_widget *w;
+       LIST_HEAD(down_list);
+       int powerdown = 0;
+
+       list_for_each_entry(w, &codec->dapm_widgets, list) {
+               if (w->power) {
+                       dapm_seq_insert(w, &down_list, dapm_down_seq);
+                       w->power = 0;
+                       powerdown = 1;
+               }
+       }
+
+       /* If there were no widgets to power down we're already in
+        * standby.
+        */
+       if (powerdown) {
+               snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_PREPARE);
+               dapm_seq_run(codec, &down_list, 0, dapm_down_seq);
+               snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_STANDBY);
+       }
+
+       snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF);
+}
+
 /* Module information */
 MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
 MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
index 28346fb2e70c08033158920f4ae7a35032239762..1d455ab79490a70fdb0833638205a387ecccb8aa 100644 (file)
@@ -73,14 +73,15 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
        oldstatus = jack->status;
 
        jack->status &= ~mask;
-       jack->status |= status;
+       jack->status |= status & mask;
 
-       /* The DAPM sync is expensive enough to be worth skipping */
-       if (jack->status == oldstatus)
+       /* The DAPM sync is expensive enough to be worth skipping.
+        * However, empty mask means pin synchronization is desired. */
+       if (mask && (jack->status == oldstatus))
                goto out;
 
        list_for_each_entry(pin, &jack->pins, list) {
-               enable = pin->mask & status;
+               enable = pin->mask & jack->status;
 
                if (pin->invert)
                        enable = !enable;
@@ -220,6 +221,9 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
                if (ret)
                        goto err;
 
+               INIT_WORK(&gpios[i].work, gpio_work);
+               gpios[i].jack = jack;
+
                ret = request_irq(gpio_to_irq(gpios[i].gpio),
                                gpio_handler,
                                IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
@@ -228,8 +232,13 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
                if (ret)
                        goto err;
 
-               INIT_WORK(&gpios[i].work, gpio_work);
-               gpios[i].jack = jack;
+#ifdef CONFIG_GPIO_SYSFS
+               /* Expose GPIO value over sysfs for diagnostic purposes */
+               gpio_export(gpios[i].gpio, false);
+#endif
+
+               /* Update initial jack status */
+               snd_soc_jack_gpio_detect(&gpios[i]);
        }
 
        return 0;
@@ -258,6 +267,9 @@ void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
        int i;
 
        for (i = 0; i < count; i++) {
+#ifdef CONFIG_GPIO_SYSFS
+               gpio_unexport(gpios[i].gpio);
+#endif
                free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]);
                gpio_free(gpios[i].gpio);
                gpios[i].jack = NULL;
index 938a58a5a244c1d75c43ed969e3c14b64fb08bb1..efed64b8b026c18117b6b58a49d8cfb1dd467955 100644 (file)
@@ -297,15 +297,17 @@ static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
 static bool filter(struct dma_chan *chan, void *param)
 {
        struct txx9aclc_dmadata *dmadata = param;
-       char devname[20 + 2]; /* FIXME: old BUS_ID_SIZE + 2 */
+       char *devname;
+       bool found = false;
 
-       snprintf(devname, sizeof(devname), "%s.%d", dmadata->dma_res->name,
+       devname = kasprintf(GFP_KERNEL, "%s.%d", dmadata->dma_res->name,
                (int)dmadata->dma_res->start);
        if (strcmp(dev_name(chan->device->dev), devname) == 0) {
                chan->private = &dmadata->dma_slave;
-               return true;
+               found = true;
        }
-       return false;
+       kfree(devname);
+       return found;
 }
 
 static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
index 12522e6913d92d068676f4b3916571b03dae2d87..bb4b88e606bba6a533ef8647da54bf666e62be64 100644 (file)
@@ -10,6 +10,8 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/err.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
 #include <sound/core.h>
 
 #ifdef CONFIG_SOUND_OSS_CORE
@@ -29,6 +31,8 @@ MODULE_LICENSE("GPL");
 
 static char *sound_nodename(struct device *dev)
 {
+       if (MAJOR(dev->devt) == SOUND_MAJOR)
+               return NULL;
        return kasprintf(GFP_KERNEL, "snd/%s", dev_name(dev));
 }
 
@@ -104,7 +108,6 @@ module_exit(cleanup_soundcore);
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sound.h>
-#include <linux/major.h>
 #include <linux/kmod.h>
 
 #define SOUND_STEP 16
@@ -124,6 +127,46 @@ extern int msnd_classic_init(void);
 extern int msnd_pinnacle_init(void);
 #endif
 
+/*
+ * By default, OSS sound_core claims full legacy minor range (0-255)
+ * of SOUND_MAJOR to trap open attempts to any sound minor and
+ * requests modules using custom sound-slot/service-* module aliases.
+ * The only benefit of doing this is allowing use of custom module
+ * aliases instead of the standard char-major-* ones.  This behavior
+ * prevents alternative OSS implementation and is scheduled to be
+ * removed.
+ *
+ * CONFIG_SOUND_OSS_CORE_PRECLAIM and soundcore.preclaim_oss kernel
+ * parameter are added to allow distros and developers to try and
+ * switch to alternative implementations without needing to rebuild
+ * the kernel in the meantime.  If preclaim_oss is non-zero, the
+ * kernel will behave the same as before.  All SOUND_MAJOR minors are
+ * preclaimed and the custom module aliases along with standard chrdev
+ * ones are emitted if a missing device is opened.  If preclaim_oss is
+ * zero, sound_core only grabs what's actually in use and for missing
+ * devices only the standard chrdev aliases are requested.
+ *
+ * All these clutters are scheduled to be removed along with
+ * sound-slot/service-* module aliases.  Please take a look at
+ * feature-removal-schedule.txt for details.
+ */
+#ifdef CONFIG_SOUND_OSS_CORE_PRECLAIM
+static int preclaim_oss = 1;
+#else
+static int preclaim_oss = 0;
+#endif
+
+module_param(preclaim_oss, int, 0444);
+
+static int soundcore_open(struct inode *, struct file *);
+
+static const struct file_operations soundcore_fops =
+{
+       /* We must have an owner or the module locking fails */
+       .owner  = THIS_MODULE,
+       .open   = soundcore_open,
+};
+
 /*
  *     Low level list operator. Scan the ordered list, find a hole and
  *     join into it. Called with the lock asserted
@@ -216,8 +259,9 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati
 
        if (!s)
                return -ENOMEM;
-               
+
        spin_lock(&sound_loader_lock);
+retry:
        r = __sound_insert_unit(s, list, fops, index, low, top);
        spin_unlock(&sound_loader_lock);
        
@@ -228,11 +272,31 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati
        else
                sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
 
+       if (!preclaim_oss) {
+               /*
+                * Something else might have grabbed the minor.  If
+                * first free slot is requested, rescan with @low set
+                * to the next unit; otherwise, -EBUSY.
+                */
+               r = __register_chrdev(SOUND_MAJOR, s->unit_minor, 1, s->name,
+                                     &soundcore_fops);
+               if (r < 0) {
+                       spin_lock(&sound_loader_lock);
+                       __sound_remove_unit(list, s->unit_minor);
+                       if (index < 0) {
+                               low = s->unit_minor + SOUND_STEP;
+                               goto retry;
+                       }
+                       spin_unlock(&sound_loader_lock);
+                       return -EBUSY;
+               }
+       }
+
        device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
                      NULL, s->name+6);
-       return r;
+       return s->unit_minor;
 
- fail:
+fail:
        kfree(s);
        return r;
 }
@@ -251,6 +315,9 @@ static void sound_remove_unit(struct sound_unit **list, int unit)
        p = __sound_remove_unit(list, unit);
        spin_unlock(&sound_loader_lock);
        if (p) {
+               if (!preclaim_oss)
+                       __unregister_chrdev(SOUND_MAJOR, p->unit_minor, 1,
+                                           p->name);
                device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
                kfree(p);
        }
@@ -488,19 +555,6 @@ void unregister_sound_dsp(int unit)
 
 EXPORT_SYMBOL(unregister_sound_dsp);
 
-/*
- *     Now our file operations
- */
-
-static int soundcore_open(struct inode *, struct file *);
-
-static const struct file_operations soundcore_fops=
-{
-       /* We must have an owner or the module locking fails */
-       .owner  = THIS_MODULE,
-       .open   = soundcore_open,
-};
-
 static struct sound_unit *__look_for_unit(int chain, int unit)
 {
        struct sound_unit *s;
@@ -536,8 +590,9 @@ static int soundcore_open(struct inode *inode, struct file *file)
        s = __look_for_unit(chain, unit);
        if (s)
                new_fops = fops_get(s->unit_fops);
-       if (!new_fops) {
+       if (preclaim_oss && !new_fops) {
                spin_unlock(&sound_loader_lock);
+
                /*
                 *  Please, don't change this order or code.
                 *  For ALSA slot means soundcard and OSS emulation code
@@ -547,6 +602,17 @@ static int soundcore_open(struct inode *inode, struct file *file)
                 */
                request_module("sound-slot-%i", unit>>4);
                request_module("sound-service-%i-%i", unit>>4, chain);
+
+               /*
+                * sound-slot/service-* module aliases are scheduled
+                * for removal in favor of the standard char-major-*
+                * module aliases.  For the time being, generate both
+                * the legacy and standard module aliases to ease
+                * transition.
+                */
+               if (request_module("char-major-%d-%d", SOUND_MAJOR, unit) > 0)
+                       request_module("char-major-%d", SOUND_MAJOR);
+
                spin_lock(&sound_loader_lock);
                s = __look_for_unit(chain, unit);
                if (s)
@@ -590,7 +656,8 @@ static void cleanup_oss_soundcore(void)
 
 static int __init init_oss_soundcore(void)
 {
-       if (register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops)==-1) {
+       if (preclaim_oss &&
+           register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops) == -1) {
                printk(KERN_ERR "soundcore: sound device already in use.\n");
                return -EBUSY;
        }
index 523aec188ccf64efa2de3aae90f8550eee77e3aa..73525c048e7f60d7613eef093f850c6d204215e4 100644 (file)
@@ -48,6 +48,7 @@ config SND_USB_CAIAQ
            * Native Instruments Kore Controller
            * Native Instruments Kore Controller 2
            * Native Instruments Audio Kontrol 1
+           * Native Instruments Audio 2 DJ
            * Native Instruments Audio 4 DJ
            * Native Instruments Audio 8 DJ
            * Native Instruments Guitar Rig Session I/O
index 8f9b60c5d74c9714e13c58a8bf4590b9e727951d..121af0644fd9bc901fbbc62cb676738e9049e0c7 100644 (file)
@@ -646,6 +646,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_GUITARRIGMOBILE):
                dev->samplerates |= SNDRV_PCM_RATE_192000;
                /* fall thru */
+       case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ):
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
        case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
                dev->samplerates |= SNDRV_PCM_RATE_88200;
index 0e5db719de244c1ba6da224ac316b8a37106109c..83e6c1312d47c47ef1cc32eabab5b411d9dfa6b3 100644 (file)
 #include "input.h"
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.17");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.19");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
                         "{Native Instruments, RigKontrol3},"
                         "{Native Instruments, Kore Controller},"
                         "{Native Instruments, Kore Controller 2},"
                         "{Native Instruments, Audio Kontrol 1},"
+                        "{Native Instruments, Audio 2 DJ},"
                         "{Native Instruments, Audio 4 DJ},"
                         "{Native Instruments, Audio 8 DJ},"
                         "{Native Instruments, Session I/O},"
@@ -121,6 +122,11 @@ static struct usb_device_id snd_usb_id_table[] = {
                .idVendor =     USB_VID_NATIVEINSTRUMENTS,
                .idProduct =    USB_PID_AUDIO4DJ
        },
+       {
+               .match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+               .idVendor =     USB_VID_NATIVEINSTRUMENTS,
+               .idProduct =    USB_PID_AUDIO2DJ
+       },
        { /* terminator */ }
 };
 
@@ -349,7 +355,9 @@ static void __devinit setup_card(struct snd_usb_caiaqdev *dev)
                log("Unable to set up control system (ret=%d)\n", ret);
 }
 
-static int create_card(struct usb_device* usb_dev, struct snd_card **cardp)
+static int create_card(struct usb_device *usb_dev,
+                      struct usb_interface *intf,
+                      struct snd_card **cardp)
 {
        int devnum;
        int err;
@@ -374,7 +382,7 @@ static int create_card(struct usb_device* usb_dev, struct snd_card **cardp)
        dev->chip.usb_id = USB_ID(le16_to_cpu(usb_dev->descriptor.idVendor),
                                  le16_to_cpu(usb_dev->descriptor.idProduct));
        spin_lock_init(&dev->spinlock);
-       snd_card_set_dev(card, &usb_dev->dev);
+       snd_card_set_dev(card, &intf->dev);
 
        *cardp = card;
        return 0;
@@ -461,7 +469,7 @@ static int __devinit snd_probe(struct usb_interface *intf,
        struct snd_card *card;
        struct usb_device *device = interface_to_usbdev(intf);
 
-       ret = create_card(device, &card);
+       ret = create_card(device, intf, &card);
 
        if (ret < 0)
                return ret;
index ece73514854e2f302ab88da1d1a857d3f43ee3ec..44e3edf88befab4ce60071a3d9b9da72bd9a727e 100644 (file)
@@ -10,6 +10,7 @@
 #define USB_PID_KORECONTROLLER 0x4711
 #define USB_PID_KORECONTROLLER2        0x4712
 #define USB_PID_AK1            0x0815
+#define USB_PID_AUDIO2DJ       0x041c
 #define USB_PID_AUDIO4DJ       0x0839
 #define USB_PID_AUDIO8DJ       0x1978
 #define USB_PID_SESSIONIO      0x1915
index c7b902358b7b268a3dd25178639f41009dedf125..8db0374e10d5e23bd47ed08b4c1b6cb0afd60737 100644 (file)
@@ -1083,6 +1083,8 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri
        } else
                urb_packs = 1;
        urb_packs *= packs_per_ms;
+       if (subs->syncpipe)
+               urb_packs = min(urb_packs, 1U << subs->syncinterval);
 
        /* decide how many packets to be used */
        if (is_playback) {
@@ -2124,8 +2126,8 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
                fp = list_entry(p, struct audioformat, list);
                snd_iprintf(buffer, "  Interface %d\n", fp->iface);
                snd_iprintf(buffer, "    Altset %d\n", fp->altsetting);
-               snd_iprintf(buffer, "    Format: %#x (%d bits)\n",
-                           fp->format, snd_pcm_format_width(fp->format));
+               snd_iprintf(buffer, "    Format: %s\n",
+                           snd_pcm_format_name(fp->format));
                snd_iprintf(buffer, "    Channels: %d\n", fp->channels);
                snd_iprintf(buffer, "    Endpoint: %d %s (%s)\n",
                            fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
@@ -2661,7 +2663,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
        struct usb_interface_descriptor *altsd;
        int i, altno, err, stream;
        int format;
-       struct audioformat *fp;
+       struct audioformat *fp = NULL;
        unsigned char *fmt, *csep;
        int num;
 
@@ -2734,6 +2736,18 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
                        continue;
                }
 
+               /*
+                * Blue Microphones workaround: The last altsetting is identical
+                * with the previous one, except for a larger packet size, but
+                * is actually a mislabeled two-channel setting; ignore it.
+                */
+               if (fmt[4] == 1 && fmt[5] == 2 && altno == 2 && num == 3 &&
+                   fp && fp->altsetting == 1 && fp->channels == 1 &&
+                   fp->format == SNDRV_PCM_FORMAT_S16_LE &&
+                   le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
+                                                       fp->maxpacksize * 2)
+                       continue;
+
                csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
                /* Creamware Noah has this descriptor after the 2nd endpoint */
                if (!csep && altsd->bNumEndpoints >= 2)
index 2fb35cc22a3030b687d1623546196cd6e8e2de27..0eff19ceb7e1f9d74653d80c402d3930a6be8bf8 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/slab.h>
 #include <linux/timer.h>
 #include <linux/usb.h>
+#include <linux/wait.h>
 #include <sound/core.h>
 #include <sound/rawmidi.h>
 #include <sound/asequencer.h>
@@ -62,6 +63,9 @@
  */
 #define ERROR_DELAY_JIFFIES (HZ / 10)
 
+#define OUTPUT_URBS 7
+#define INPUT_URBS 7
+
 
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("USB Audio/MIDI helper module");
@@ -90,7 +94,7 @@ struct snd_usb_midi_endpoint;
 
 struct usb_protocol_ops {
        void (*input)(struct snd_usb_midi_in_endpoint*, uint8_t*, int);
-       void (*output)(struct snd_usb_midi_out_endpoint*);
+       void (*output)(struct snd_usb_midi_out_endpoint *ep, struct urb *urb);
        void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t);
        void (*init_out_endpoint)(struct snd_usb_midi_out_endpoint*);
        void (*finish_out_endpoint)(struct snd_usb_midi_out_endpoint*);
@@ -116,11 +120,15 @@ struct snd_usb_midi {
 
 struct snd_usb_midi_out_endpoint {
        struct snd_usb_midi* umidi;
-       struct urb* urb;
-       int urb_active;
+       struct out_urb_context {
+               struct urb *urb;
+               struct snd_usb_midi_out_endpoint *ep;
+       } urbs[OUTPUT_URBS];
+       unsigned int active_urbs;
+       unsigned int drain_urbs;
        int max_transfer;               /* size of urb buffer */
        struct tasklet_struct tasklet;
-
+       unsigned int next_urb;
        spinlock_t buffer_lock;
 
        struct usbmidi_out_port {
@@ -139,11 +147,13 @@ struct snd_usb_midi_out_endpoint {
                uint8_t data[2];
        } ports[0x10];
        int current_port;
+
+       wait_queue_head_t drain_wait;
 };
 
 struct snd_usb_midi_in_endpoint {
        struct snd_usb_midi* umidi;
-       struct urb* urb;
+       struct urb* urbs[INPUT_URBS];
        struct usbmidi_in_port {
                struct snd_rawmidi_substream *substream;
                u8 running_status_length;
@@ -251,10 +261,17 @@ static void snd_usbmidi_in_urb_complete(struct urb* urb)
 
 static void snd_usbmidi_out_urb_complete(struct urb* urb)
 {
-       struct snd_usb_midi_out_endpoint* ep = urb->context;
+       struct out_urb_context *context = urb->context;
+       struct snd_usb_midi_out_endpoint* ep = context->ep;
+       unsigned int urb_index;
 
        spin_lock(&ep->buffer_lock);
-       ep->urb_active = 0;
+       urb_index = context - ep->urbs;
+       ep->active_urbs &= ~(1 << urb_index);
+       if (unlikely(ep->drain_urbs)) {
+               ep->drain_urbs &= ~(1 << urb_index);
+               wake_up(&ep->drain_wait);
+       }
        spin_unlock(&ep->buffer_lock);
        if (urb->status < 0) {
                int err = snd_usbmidi_urb_error(urb->status);
@@ -274,24 +291,38 @@ static void snd_usbmidi_out_urb_complete(struct urb* urb)
  */
 static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep)
 {
-       struct urb* urb = ep->urb;
+       unsigned int urb_index;
+       struct urb* urb;
        unsigned long flags;
 
        spin_lock_irqsave(&ep->buffer_lock, flags);
-       if (ep->urb_active || ep->umidi->chip->shutdown) {
+       if (ep->umidi->chip->shutdown) {
                spin_unlock_irqrestore(&ep->buffer_lock, flags);
                return;
        }
 
-       urb->transfer_buffer_length = 0;
-       ep->umidi->usb_protocol_ops->output(ep);
+       urb_index = ep->next_urb;
+       for (;;) {
+               if (!(ep->active_urbs & (1 << urb_index))) {
+                       urb = ep->urbs[urb_index].urb;
+                       urb->transfer_buffer_length = 0;
+                       ep->umidi->usb_protocol_ops->output(ep, urb);
+                       if (urb->transfer_buffer_length == 0)
+                               break;
 
-       if (urb->transfer_buffer_length > 0) {
-               dump_urb("sending", urb->transfer_buffer,
-                        urb->transfer_buffer_length);
-               urb->dev = ep->umidi->chip->dev;
-               ep->urb_active = snd_usbmidi_submit_urb(urb, GFP_ATOMIC) >= 0;
+                       dump_urb("sending", urb->transfer_buffer,
+                                urb->transfer_buffer_length);
+                       urb->dev = ep->umidi->chip->dev;
+                       if (snd_usbmidi_submit_urb(urb, GFP_ATOMIC) < 0)
+                               break;
+                       ep->active_urbs |= 1 << urb_index;
+               }
+               if (++urb_index >= OUTPUT_URBS)
+                       urb_index = 0;
+               if (urb_index == ep->next_urb)
+                       break;
        }
+       ep->next_urb = urb_index;
        spin_unlock_irqrestore(&ep->buffer_lock, flags);
 }
 
@@ -306,7 +337,7 @@ static void snd_usbmidi_out_tasklet(unsigned long data)
 static void snd_usbmidi_error_timer(unsigned long data)
 {
        struct snd_usb_midi *umidi = (struct snd_usb_midi *)data;
-       int i;
+       unsigned int i, j;
 
        spin_lock(&umidi->disc_lock);
        if (umidi->disconnected) {
@@ -317,8 +348,10 @@ static void snd_usbmidi_error_timer(unsigned long data)
                struct snd_usb_midi_in_endpoint *in = umidi->endpoints[i].in;
                if (in && in->error_resubmit) {
                        in->error_resubmit = 0;
-                       in->urb->dev = umidi->chip->dev;
-                       snd_usbmidi_submit_urb(in->urb, GFP_ATOMIC);
+                       for (j = 0; j < INPUT_URBS; ++j) {
+                               in->urbs[j]->dev = umidi->chip->dev;
+                               snd_usbmidi_submit_urb(in->urbs[j], GFP_ATOMIC);
+                       }
                }
                if (umidi->endpoints[i].out)
                        snd_usbmidi_do_output(umidi->endpoints[i].out);
@@ -330,13 +363,14 @@ static void snd_usbmidi_error_timer(unsigned long data)
 static int send_bulk_static_data(struct snd_usb_midi_out_endpoint* ep,
                                 const void *data, int len)
 {
-       int err;
+       int err = 0;
        void *buf = kmemdup(data, len, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
        dump_urb("sending", buf, len);
-       err = usb_bulk_msg(ep->umidi->chip->dev, ep->urb->pipe, buf, len,
-                          NULL, 250);
+       if (ep->urbs[0].urb)
+               err = usb_bulk_msg(ep->umidi->chip->dev, ep->urbs[0].urb->pipe,
+                                  buf, len, NULL, 250);
        kfree(buf);
        return err;
 }
@@ -554,9 +588,9 @@ static void snd_usbmidi_transmit_byte(struct usbmidi_out_port* port,
        }
 }
 
-static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint* ep)
+static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint* ep,
+                                       struct urb *urb)
 {
-       struct urb* urb = ep->urb;
        int p;
 
        /* FIXME: lower-numbered ports can starve higher-numbered ports */
@@ -613,14 +647,15 @@ static void snd_usbmidi_novation_input(struct snd_usb_midi_in_endpoint* ep,
        snd_usbmidi_input_data(ep, 0, &buffer[2], buffer[0] - 1);
 }
 
-static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint* ep)
+static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint* ep,
+                                       struct urb *urb)
 {
        uint8_t* transfer_buffer;
        int count;
 
        if (!ep->ports[0].active)
                return;
-       transfer_buffer = ep->urb->transfer_buffer;
+       transfer_buffer = urb->transfer_buffer;
        count = snd_rawmidi_transmit(ep->ports[0].substream,
                                     &transfer_buffer[2],
                                     ep->max_transfer - 2);
@@ -630,7 +665,7 @@ static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint* ep)
        }
        transfer_buffer[0] = 0;
        transfer_buffer[1] = count;
-       ep->urb->transfer_buffer_length = 2 + count;
+       urb->transfer_buffer_length = 2 + count;
 }
 
 static struct usb_protocol_ops snd_usbmidi_novation_ops = {
@@ -648,20 +683,21 @@ static void snd_usbmidi_raw_input(struct snd_usb_midi_in_endpoint* ep,
        snd_usbmidi_input_data(ep, 0, buffer, buffer_length);
 }
 
-static void snd_usbmidi_raw_output(struct snd_usb_midi_out_endpoint* ep)
+static void snd_usbmidi_raw_output(struct snd_usb_midi_out_endpoint* ep,
+                                  struct urb *urb)
 {
        int count;
 
        if (!ep->ports[0].active)
                return;
        count = snd_rawmidi_transmit(ep->ports[0].substream,
-                                    ep->urb->transfer_buffer,
+                                    urb->transfer_buffer,
                                     ep->max_transfer);
        if (count < 1) {
                ep->ports[0].active = 0;
                return;
        }
-       ep->urb->transfer_buffer_length = count;
+       urb->transfer_buffer_length = count;
 }
 
 static struct usb_protocol_ops snd_usbmidi_raw_ops = {
@@ -681,23 +717,25 @@ static void snd_usbmidi_us122l_input(struct snd_usb_midi_in_endpoint *ep,
                snd_usbmidi_input_data(ep, 0, buffer, buffer_length);
 }
 
-static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep)
+static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep,
+                                     struct urb *urb)
 {
        int count;
 
        if (!ep->ports[0].active)
                return;
-       count = ep->urb->dev->speed == USB_SPEED_HIGH ? 1 : 2;
+       count = snd_usb_get_speed(ep->umidi->chip->dev) == USB_SPEED_HIGH
+               ? 1 : 2;
        count = snd_rawmidi_transmit(ep->ports[0].substream,
-                                    ep->urb->transfer_buffer,
+                                    urb->transfer_buffer,
                                     count);
        if (count < 1) {
                ep->ports[0].active = 0;
                return;
        }
 
-       memset(ep->urb->transfer_buffer + count, 0xFD, 9 - count);
-       ep->urb->transfer_buffer_length = count;
+       memset(urb->transfer_buffer + count, 0xFD, 9 - count);
+       urb->transfer_buffer_length = count;
 }
 
 static struct usb_protocol_ops snd_usbmidi_122l_ops = {
@@ -786,10 +824,11 @@ static void snd_usbmidi_emagic_input(struct snd_usb_midi_in_endpoint* ep,
        }
 }
 
-static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint* ep)
+static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint* ep,
+                                     struct urb *urb)
 {
        int port0 = ep->current_port;
-       uint8_t* buf = ep->urb->transfer_buffer;
+       uint8_t* buf = urb->transfer_buffer;
        int buf_free = ep->max_transfer;
        int length, i;
 
@@ -829,7 +868,7 @@ static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint* ep)
                *buf = 0xff;
                --buf_free;
        }
-       ep->urb->transfer_buffer_length = ep->max_transfer - buf_free;
+       urb->transfer_buffer_length = ep->max_transfer - buf_free;
 }
 
 static struct usb_protocol_ops snd_usbmidi_emagic_ops = {
@@ -884,6 +923,35 @@ static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream,
        }
 }
 
+static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream)
+{
+       struct usbmidi_out_port* port = substream->runtime->private_data;
+       struct snd_usb_midi_out_endpoint *ep = port->ep;
+       unsigned int drain_urbs;
+       DEFINE_WAIT(wait);
+       long timeout = msecs_to_jiffies(50);
+
+       /*
+        * The substream buffer is empty, but some data might still be in the
+        * currently active URBs, so we have to wait for those to complete.
+        */
+       spin_lock_irq(&ep->buffer_lock);
+       drain_urbs = ep->active_urbs;
+       if (drain_urbs) {
+               ep->drain_urbs |= drain_urbs;
+               do {
+                       prepare_to_wait(&ep->drain_wait, &wait,
+                                       TASK_UNINTERRUPTIBLE);
+                       spin_unlock_irq(&ep->buffer_lock);
+                       timeout = schedule_timeout(timeout);
+                       spin_lock_irq(&ep->buffer_lock);
+                       drain_urbs &= ep->drain_urbs;
+               } while (drain_urbs && timeout);
+               finish_wait(&ep->drain_wait, &wait);
+       }
+       spin_unlock_irq(&ep->buffer_lock);
+}
+
 static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream)
 {
        return 0;
@@ -908,6 +976,7 @@ static struct snd_rawmidi_ops snd_usbmidi_output_ops = {
        .open = snd_usbmidi_output_open,
        .close = snd_usbmidi_output_close,
        .trigger = snd_usbmidi_output_trigger,
+       .drain = snd_usbmidi_output_drain,
 };
 
 static struct snd_rawmidi_ops snd_usbmidi_input_ops = {
@@ -916,19 +985,26 @@ static struct snd_rawmidi_ops snd_usbmidi_input_ops = {
        .trigger = snd_usbmidi_input_trigger
 };
 
+static void free_urb_and_buffer(struct snd_usb_midi *umidi, struct urb *urb,
+                               unsigned int buffer_length)
+{
+       usb_buffer_free(umidi->chip->dev, buffer_length,
+                       urb->transfer_buffer, urb->transfer_dma);
+       usb_free_urb(urb);
+}
+
 /*
  * Frees an input endpoint.
  * May be called when ep hasn't been initialized completely.
  */
 static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint* ep)
 {
-       if (ep->urb) {
-               usb_buffer_free(ep->umidi->chip->dev,
-                               ep->urb->transfer_buffer_length,
-                               ep->urb->transfer_buffer,
-                               ep->urb->transfer_dma);
-               usb_free_urb(ep->urb);
-       }
+       unsigned int i;
+
+       for (i = 0; i < INPUT_URBS; ++i)
+               if (ep->urbs[i])
+                       free_urb_and_buffer(ep->umidi, ep->urbs[i],
+                                           ep->urbs[i]->transfer_buffer_length);
        kfree(ep);
 }
 
@@ -943,6 +1019,7 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi,
        void* buffer;
        unsigned int pipe;
        int length;
+       unsigned int i;
 
        rep->in = NULL;
        ep = kzalloc(sizeof(*ep), GFP_KERNEL);
@@ -950,30 +1027,36 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi,
                return -ENOMEM;
        ep->umidi = umidi;
 
-       ep->urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!ep->urb) {
-               snd_usbmidi_in_endpoint_delete(ep);
-               return -ENOMEM;
+       for (i = 0; i < INPUT_URBS; ++i) {
+               ep->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
+               if (!ep->urbs[i]) {
+                       snd_usbmidi_in_endpoint_delete(ep);
+                       return -ENOMEM;
+               }
        }
        if (ep_info->in_interval)
                pipe = usb_rcvintpipe(umidi->chip->dev, ep_info->in_ep);
        else
                pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep);
        length = usb_maxpacket(umidi->chip->dev, pipe, 0);
-       buffer = usb_buffer_alloc(umidi->chip->dev, length, GFP_KERNEL,
-                                 &ep->urb->transfer_dma);
-       if (!buffer) {
-               snd_usbmidi_in_endpoint_delete(ep);
-               return -ENOMEM;
+       for (i = 0; i < INPUT_URBS; ++i) {
+               buffer = usb_buffer_alloc(umidi->chip->dev, length, GFP_KERNEL,
+                                         &ep->urbs[i]->transfer_dma);
+               if (!buffer) {
+                       snd_usbmidi_in_endpoint_delete(ep);
+                       return -ENOMEM;
+               }
+               if (ep_info->in_interval)
+                       usb_fill_int_urb(ep->urbs[i], umidi->chip->dev,
+                                        pipe, buffer, length,
+                                        snd_usbmidi_in_urb_complete,
+                                        ep, ep_info->in_interval);
+               else
+                       usb_fill_bulk_urb(ep->urbs[i], umidi->chip->dev,
+                                         pipe, buffer, length,
+                                         snd_usbmidi_in_urb_complete, ep);
+               ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
        }
-       if (ep_info->in_interval)
-               usb_fill_int_urb(ep->urb, umidi->chip->dev, pipe, buffer,
-                                length, snd_usbmidi_in_urb_complete, ep,
-                                ep_info->in_interval);
-       else
-               usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer,
-                                 length, snd_usbmidi_in_urb_complete, ep);
-       ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
 
        rep->in = ep;
        return 0;
@@ -994,12 +1077,12 @@ static unsigned int snd_usbmidi_count_bits(unsigned int x)
  */
 static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint* ep)
 {
-       if (ep->urb) {
-               usb_buffer_free(ep->umidi->chip->dev, ep->max_transfer,
-                               ep->urb->transfer_buffer,
-                               ep->urb->transfer_dma);
-               usb_free_urb(ep->urb);
-       }
+       unsigned int i;
+
+       for (i = 0; i < OUTPUT_URBS; ++i)
+               if (ep->urbs[i].urb)
+                       free_urb_and_buffer(ep->umidi, ep->urbs[i].urb,
+                                           ep->max_transfer);
        kfree(ep);
 }
 
@@ -1011,7 +1094,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
                                           struct snd_usb_midi_endpoint* rep)
 {
        struct snd_usb_midi_out_endpoint* ep;
-       int i;
+       unsigned int i;
        unsigned int pipe;
        void* buffer;
 
@@ -1021,38 +1104,46 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
                return -ENOMEM;
        ep->umidi = umidi;
 
-       ep->urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!ep->urb) {
-               snd_usbmidi_out_endpoint_delete(ep);
-               return -ENOMEM;
+       for (i = 0; i < OUTPUT_URBS; ++i) {
+               ep->urbs[i].urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!ep->urbs[i].urb) {
+                       snd_usbmidi_out_endpoint_delete(ep);
+                       return -ENOMEM;
+               }
+               ep->urbs[i].ep = ep;
        }
        if (ep_info->out_interval)
                pipe = usb_sndintpipe(umidi->chip->dev, ep_info->out_ep);
        else
                pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep);
        if (umidi->chip->usb_id == USB_ID(0x0a92, 0x1020)) /* ESI M4U */
-               /* FIXME: we need more URBs to get reasonable bandwidth here: */
                ep->max_transfer = 4;
        else
                ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1);
-       buffer = usb_buffer_alloc(umidi->chip->dev, ep->max_transfer,
-                                 GFP_KERNEL, &ep->urb->transfer_dma);
-       if (!buffer) {
-               snd_usbmidi_out_endpoint_delete(ep);
-               return -ENOMEM;
+       for (i = 0; i < OUTPUT_URBS; ++i) {
+               buffer = usb_buffer_alloc(umidi->chip->dev,
+                                         ep->max_transfer, GFP_KERNEL,
+                                         &ep->urbs[i].urb->transfer_dma);
+               if (!buffer) {
+                       snd_usbmidi_out_endpoint_delete(ep);
+                       return -ENOMEM;
+               }
+               if (ep_info->out_interval)
+                       usb_fill_int_urb(ep->urbs[i].urb, umidi->chip->dev,
+                                        pipe, buffer, ep->max_transfer,
+                                        snd_usbmidi_out_urb_complete,
+                                        &ep->urbs[i], ep_info->out_interval);
+               else
+                       usb_fill_bulk_urb(ep->urbs[i].urb, umidi->chip->dev,
+                                         pipe, buffer, ep->max_transfer,
+                                         snd_usbmidi_out_urb_complete,
+                                         &ep->urbs[i]);
+               ep->urbs[i].urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
        }
-       if (ep_info->out_interval)
-               usb_fill_int_urb(ep->urb, umidi->chip->dev, pipe, buffer,
-                                ep->max_transfer, snd_usbmidi_out_urb_complete,
-                                ep, ep_info->out_interval);
-       else
-               usb_fill_bulk_urb(ep->urb, umidi->chip->dev,
-                                 pipe, buffer, ep->max_transfer,
-                                 snd_usbmidi_out_urb_complete, ep);
-       ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
 
        spin_lock_init(&ep->buffer_lock);
        tasklet_init(&ep->tasklet, snd_usbmidi_out_tasklet, (unsigned long)ep);
+       init_waitqueue_head(&ep->drain_wait);
 
        for (i = 0; i < 0x10; ++i)
                if (ep_info->out_cables & (1 << i)) {
@@ -1090,7 +1181,7 @@ static void snd_usbmidi_free(struct snd_usb_midi* umidi)
 void snd_usbmidi_disconnect(struct list_head* p)
 {
        struct snd_usb_midi* umidi;
-       int i;
+       unsigned int i, j;
 
        umidi = list_entry(p, struct snd_usb_midi, list);
        /*
@@ -1105,13 +1196,15 @@ void snd_usbmidi_disconnect(struct list_head* p)
                struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
                if (ep->out)
                        tasklet_kill(&ep->out->tasklet);
-               if (ep->out && ep->out->urb) {
-                       usb_kill_urb(ep->out->urb);
+               if (ep->out) {
+                       for (j = 0; j < OUTPUT_URBS; ++j)
+                               usb_kill_urb(ep->out->urbs[j].urb);
                        if (umidi->usb_protocol_ops->finish_out_endpoint)
                                umidi->usb_protocol_ops->finish_out_endpoint(ep->out);
                }
                if (ep->in)
-                       usb_kill_urb(ep->in->urb);
+                       for (j = 0; j < INPUT_URBS; ++j)
+                               usb_kill_urb(ep->in->urbs[j]);
                /* free endpoints here; later call can result in Oops */
                if (ep->out) {
                        snd_usbmidi_out_endpoint_delete(ep->out);
@@ -1692,20 +1785,25 @@ static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi,
 void snd_usbmidi_input_stop(struct list_head* p)
 {
        struct snd_usb_midi* umidi;
-       int i;
+       unsigned int i, j;
 
        umidi = list_entry(p, struct snd_usb_midi, list);
        for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
                struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
                if (ep->in)
-                       usb_kill_urb(ep->in->urb);
+                       for (j = 0; j < INPUT_URBS; ++j)
+                               usb_kill_urb(ep->in->urbs[j]);
        }
 }
 
 static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep)
 {
-       if (ep) {
-               struct urb* urb = ep->urb;
+       unsigned int i;
+
+       if (!ep)
+               return;
+       for (i = 0; i < INPUT_URBS; ++i) {
+               struct urb* urb = ep->urbs[i];
                urb->dev = ep->umidi->chip->dev;
                snd_usbmidi_submit_urb(urb, GFP_KERNEL);
        }
index 4bd3a7a0edc100c2dd6007a98f8247b9084b8969..9efcfd08d747b1c430ae17f9429fda3b57974a0b 100644 (file)
@@ -86,6 +86,7 @@ struct usb_mixer_interface {
        u8 rc_buffer[6];
 
        u8 audigy2nx_leds[3];
+       u8 xonar_u1_status;
 };
 
 
@@ -461,7 +462,7 @@ static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
                         unsigned int size, unsigned int __user *_tlv)
 {
        struct usb_mixer_elem_info *cval = kcontrol->private_data;
-       DECLARE_TLV_DB_SCALE(scale, 0, 0, 0);
+       DECLARE_TLV_DB_MINMAX(scale, 0, 0);
 
        if (size < sizeof(scale))
                return -ENOMEM;
@@ -469,7 +470,16 @@ static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
         * while ALSA TLV contains in 1/100 dB unit
         */
        scale[2] = (convert_signed_value(cval, cval->min) * 100) / 256;
-       scale[3] = (convert_signed_value(cval, cval->res) * 100) / 256;
+       scale[3] = (convert_signed_value(cval, cval->max) * 100) / 256;
+       if (scale[3] <= scale[2]) {
+               /* something is wrong; assume it's either from/to 0dB */
+               if (scale[2] < 0)
+                       scale[3] = 0;
+               else if (scale[2] > 0)
+                       scale[2] = 0;
+               else /* totally crap, return an error */
+                       return -EINVAL;
+       }
        if (copy_to_user(_tlv, scale, sizeof(scale)))
                return -EFAULT;
        return 0;
@@ -888,6 +898,11 @@ static struct snd_kcontrol_new usb_feature_unit_ctl = {
  * build a feature control
  */
 
+static size_t append_ctl_name(struct snd_kcontrol *kctl, const char *str)
+{
+       return strlcat(kctl->id.name, str, sizeof(kctl->id.name));
+}
+
 static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
                              unsigned int ctl_mask, int control,
                              struct usb_audio_term *iterm, int unitid)
@@ -968,13 +983,13 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
                 */
                if (! mapped_name && ! (state->oterm.type >> 16)) {
                        if ((state->oterm.type & 0xff00) == 0x0100) {
-                               len = strlcat(kctl->id.name, " Capture", sizeof(kctl->id.name));
+                               len = append_ctl_name(kctl, " Capture");
                        } else {
-                               len = strlcat(kctl->id.name + len, " Playback", sizeof(kctl->id.name));
+                               len = append_ctl_name(kctl, " Playback");
                        }
                }
-               strlcat(kctl->id.name + len, control == USB_FEATURE_MUTE ? " Switch" : " Volume",
-                       sizeof(kctl->id.name));
+               append_ctl_name(kctl, control == USB_FEATURE_MUTE ?
+                               " Switch" : " Volume");
                if (control == USB_FEATURE_VOLUME) {
                        kctl->tlv.c = mixer_vol_tlv;
                        kctl->vd[0].access |= 
@@ -990,20 +1005,35 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc,
                break;
        }
 
-       /* quirk for UDA1321/N101 */
-       /* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */
-       /* is not very clear from datasheets */
-       /* I hope that the min value is -15360 for newer firmware --jk */
+       /* volume control quirks */
        switch (state->chip->usb_id) {
        case USB_ID(0x0471, 0x0101):
        case USB_ID(0x0471, 0x0104):
        case USB_ID(0x0471, 0x0105):
        case USB_ID(0x0672, 0x1041):
+       /* quirk for UDA1321/N101.
+        * note that detection between firmware 2.1.1.7 (N101)
+        * and later 2.1.1.21 is not very clear from datasheets.
+        * I hope that the min value is -15360 for newer firmware --jk
+        */
                if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
                    cval->min == -15616) {
-                       snd_printk(KERN_INFO "using volume control quirk for the UDA1321/N101 chip\n");
+                       snd_printk(KERN_INFO
+                                "set volume quirk for UDA1321/N101 chip\n");
                        cval->max = -256;
                }
+               break;
+
+       case USB_ID(0x046d, 0x09a4):
+               if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
+                       snd_printk(KERN_INFO
+                               "set volume quirk for QuickCam E3500\n");
+                       cval->min = 6080;
+                       cval->max = 8768;
+                       cval->res = 192;
+               }
+               break;
+
        }
 
        snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
@@ -1118,7 +1148,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, unsigned char *desc,
                len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0);
        if (! len)
                len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1);
-       strlcat(kctl->id.name + len, " Volume", sizeof(kctl->id.name));
+       append_ctl_name(kctl, " Volume");
 
        snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n",
                    cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
@@ -1375,8 +1405,8 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, unsigned
                        if (! len)
                                strlcpy(kctl->id.name, name, sizeof(kctl->id.name));
                }
-               strlcat(kctl->id.name, " ", sizeof(kctl->id.name));
-               strlcat(kctl->id.name, valinfo->suffix, sizeof(kctl->id.name));
+               append_ctl_name(kctl, " ");
+               append_ctl_name(kctl, valinfo->suffix);
 
                snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n",
                            cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
@@ -1585,9 +1615,9 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, unsi
                        strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
 
                if ((state->oterm.type & 0xff00) == 0x0100)
-                       strlcat(kctl->id.name, " Capture Source", sizeof(kctl->id.name));
+                       append_ctl_name(kctl, " Capture Source");
                else
-                       strlcat(kctl->id.name, " Playback Source", sizeof(kctl->id.name));
+                       append_ctl_name(kctl, " Playback Source");
        }
 
        snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
@@ -2018,6 +2048,58 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
        }
 }
 
+static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+
+       ucontrol->value.integer.value[0] = !!(mixer->xonar_u1_status & 0x02);
+       return 0;
+}
+
+static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+       u8 old_status, new_status;
+       int err, changed;
+
+       old_status = mixer->xonar_u1_status;
+       if (ucontrol->value.integer.value[0])
+               new_status = old_status | 0x02;
+       else
+               new_status = old_status & ~0x02;
+       changed = new_status != old_status;
+       err = snd_usb_ctl_msg(mixer->chip->dev,
+                             usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+                             50, 0, &new_status, 1, 100);
+       if (err < 0)
+               return err;
+       mixer->xonar_u1_status = new_status;
+       return changed;
+}
+
+static struct snd_kcontrol_new snd_xonar_u1_output_switch = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Digital Playback Switch",
+       .info = snd_ctl_boolean_mono_info,
+       .get = snd_xonar_u1_switch_get,
+       .put = snd_xonar_u1_switch_put,
+};
+
+static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
+{
+       int err;
+
+       err = snd_ctl_add(mixer->chip->card,
+                         snd_ctl_new1(&snd_xonar_u1_output_switch, mixer));
+       if (err < 0)
+               return err;
+       mixer->xonar_u1_status = 0x05;
+       return 0;
+}
+
 int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
                         int ignore_error)
 {
@@ -2060,6 +2142,13 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
                                              snd_audigy2nx_proc_read);
        }
 
+       if (mixer->chip->usb_id == USB_ID(0x0b05, 0x1739) ||
+           mixer->chip->usb_id == USB_ID(0x0b05, 0x1743)) {
+               err = snd_xonar_u1_controls_create(mixer);
+               if (err < 0)
+                       goto _error;
+       }
+
        err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops);
        if (err < 0)
                goto _error;
index a5aae9d67f31707e585de8de10689d8099df5f1c..fd44946ce4b3a21aa4bae548144fcf6b66df676b 100644 (file)
@@ -514,7 +514,6 @@ static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp)
                US122L(card)->chip.dev->bus->busnum,
                US122L(card)->chip.dev->devnum
                );
-       snd_card_set_dev(card, &device->dev);
        *cardp = card;
        return 0;
 }
@@ -531,6 +530,7 @@ static int us122l_usb_probe(struct usb_interface *intf,
        if (err < 0)
                return err;
 
+       snd_card_set_dev(card, &intf->dev);
        if (!us122l_create_card(card)) {
                snd_card_free(card);
                return -EINVAL;
index 5ce0da23ee96fd22752b53ffcab1d7f8057672b9..cb4bb8373ca2989732459c70b14df5e2d2ad423d 100644 (file)
@@ -364,7 +364,6 @@ static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp)
                0,//us428(card)->usbmidi.ifnum,
                usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum
                );
-       snd_card_set_dev(card, &device->dev);
        *cardp = card;
        return 0;
 }
@@ -388,6 +387,7 @@ static int usX2Y_usb_probe(struct usb_device *device,
        err = usX2Y_create_card(device, &card);
        if (err < 0)
                return err;
+       snd_card_set_dev(card, &intf->dev);
        if ((err = usX2Y_hwdep_new(card, device)) < 0  ||
            (err = snd_card_register(card)) < 0) {
                snd_card_free(card);
index dd1ab6177840b039437d3b516794d23dd096fe23..9efd27f6b52f0ee7da14dda8777a050945c98086 100644 (file)
@@ -296,9 +296,10 @@ static void usX2Y_error_urb_status(struct usX2Ydev *usX2Y,
 static void usX2Y_error_sequence(struct usX2Ydev *usX2Y,
                                 struct snd_usX2Y_substream *subs, struct urb *urb)
 {
-       snd_printk(KERN_ERR "Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n"
-                  KERN_ERR "Most propably some urb of usb-frame %i is still missing.\n"
-                  KERN_ERR "Cause could be too long delays in usb-hcd interrupt handling.\n",
+       snd_printk(KERN_ERR
+"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n"
+"Most propably some urb of usb-frame %i is still missing.\n"
+"Cause could be too long delays in usb-hcd interrupt handling.\n",
                   usb_get_current_frame_number(usX2Y->chip.dev),
                   subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
                   usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame);
diff --git a/tools/perf/CREDITS b/tools/perf/CREDITS
new file mode 100644 (file)
index 0000000..c2ddcb3
--- /dev/null
@@ -0,0 +1,30 @@
+Most of the infrastructure that 'perf' uses here has been reused
+from the Git project, as of version:
+
+    66996ec: Sync with 1.6.2.4
+
+Here is an (incomplete!) list of main contributors to those files
+in util/* and elsewhere:
+
+ Alex Riesen
+ Christian Couder
+ Dmitry Potapov
+ Jeff King
+ Johannes Schindelin
+ Johannes Sixt
+ Junio C Hamano
+ Linus Torvalds
+ Matthias Kestenholz
+ Michal Ostrowski
+ Miklos Vajna
+ Petr Baudis
+ Pierre Habouzit
+ René Scharfe
+ Samuel Tardieu
+ Shawn O. Pearce
+ Steffen Prohaska
+ Steve Haslam
+
+Thanks guys!
+
+The full history of the files can be found in the upstream Git commits.
index 5457192e1b41174e447e1f36d349168e4698c985..bdd3b7ecad0a6dedbf6fc673f7daf3e40c9c49ce 100644 (file)
@@ -35,7 +35,7 @@ man7dir=$(mandir)/man7
 # DESTDIR=
 
 ASCIIDOC=asciidoc
-ASCIIDOC_EXTRA =
+ASCIIDOC_EXTRA = --unsafe
 MANPAGE_XSL = manpage-normal.xsl
 XMLTO_EXTRA =
 INSTALL?=install
diff --git a/tools/perf/Documentation/examples.txt b/tools/perf/Documentation/examples.txt
new file mode 100644 (file)
index 0000000..8eb6c48
--- /dev/null
@@ -0,0 +1,225 @@
+
+               ------------------------------
+               ****** perf by examples ******
+               ------------------------------
+
+[ From an e-mail by Ingo Molnar, http://lkml.org/lkml/2009/8/4/346 ]
+
+
+First, discovery/enumeration of available counters can be done via
+'perf list':
+
+titan:~> perf list
+  [...]
+  kmem:kmalloc                             [Tracepoint event]
+  kmem:kmem_cache_alloc                    [Tracepoint event]
+  kmem:kmalloc_node                        [Tracepoint event]
+  kmem:kmem_cache_alloc_node               [Tracepoint event]
+  kmem:kfree                               [Tracepoint event]
+  kmem:kmem_cache_free                     [Tracepoint event]
+  kmem:mm_page_free_direct                 [Tracepoint event]
+  kmem:mm_pagevec_free                     [Tracepoint event]
+  kmem:mm_page_alloc                       [Tracepoint event]
+  kmem:mm_page_alloc_zone_locked           [Tracepoint event]
+  kmem:mm_page_pcpu_drain                  [Tracepoint event]
+  kmem:mm_page_alloc_extfrag               [Tracepoint event]
+
+Then any (or all) of the above event sources can be activated and
+measured. For example the page alloc/free properties of a 'hackbench
+run' are:
+
+ titan:~> perf stat -e kmem:mm_page_pcpu_drain -e kmem:mm_page_alloc
+ -e kmem:mm_pagevec_free -e kmem:mm_page_free_direct ./hackbench 10
+ Time: 0.575
+
+ Performance counter stats for './hackbench 10':
+
+          13857  kmem:mm_page_pcpu_drain
+          27576  kmem:mm_page_alloc
+           6025  kmem:mm_pagevec_free
+          20934  kmem:mm_page_free_direct
+
+    0.613972165  seconds time elapsed
+
+You can observe the statistical properties as well, by using the
+'repeat the workload N times' feature of perf stat:
+
+ titan:~> perf stat --repeat 5 -e kmem:mm_page_pcpu_drain -e
+   kmem:mm_page_alloc -e kmem:mm_pagevec_free -e
+   kmem:mm_page_free_direct ./hackbench 10
+ Time: 0.627
+ Time: 0.644
+ Time: 0.564
+ Time: 0.559
+ Time: 0.626
+
+ Performance counter stats for './hackbench 10' (5 runs):
+
+          12920  kmem:mm_page_pcpu_drain    ( +-   3.359% )
+          25035  kmem:mm_page_alloc         ( +-   3.783% )
+           6104  kmem:mm_pagevec_free       ( +-   0.934% )
+          18376  kmem:mm_page_free_direct   ( +-   4.941% )
+
+    0.643954516  seconds time elapsed   ( +-   2.363% )
+
+Furthermore, these tracepoints can be used to sample the workload as
+well. For example the page allocations done by a 'git gc' can be
+captured the following way:
+
+ titan:~/git> perf record -f -e kmem:mm_page_alloc -c 1 ./git gc
+ Counting objects: 1148, done.
+ Delta compression using up to 2 threads.
+ Compressing objects: 100% (450/450), done.
+ Writing objects: 100% (1148/1148), done.
+ Total 1148 (delta 690), reused 1148 (delta 690)
+ [ perf record: Captured and wrote 0.267 MB perf.data (~11679 samples) ]
+
+To check which functions generated page allocations:
+
+ titan:~/git> perf report
+ # Samples: 10646
+ #
+ # Overhead          Command               Shared Object
+ # ........  ...............  ..........................
+ #
+    23.57%       git-repack  /lib64/libc-2.5.so
+    21.81%              git  /lib64/libc-2.5.so
+    14.59%              git  ./git
+    11.79%       git-repack  ./git
+     7.12%              git  /lib64/ld-2.5.so
+     3.16%       git-repack  /lib64/libpthread-2.5.so
+     2.09%       git-repack  /bin/bash
+     1.97%               rm  /lib64/libc-2.5.so
+     1.39%               mv  /lib64/ld-2.5.so
+     1.37%               mv  /lib64/libc-2.5.so
+     1.12%       git-repack  /lib64/ld-2.5.so
+     0.95%               rm  /lib64/ld-2.5.so
+     0.90%  git-update-serv  /lib64/libc-2.5.so
+     0.73%  git-update-serv  /lib64/ld-2.5.so
+     0.68%             perf  /lib64/libpthread-2.5.so
+     0.64%       git-repack  /usr/lib64/libz.so.1.2.3
+
+Or to see it on a more finegrained level:
+
+titan:~/git> perf report --sort comm,dso,symbol
+# Samples: 10646
+#
+# Overhead          Command               Shared Object  Symbol
+# ........  ...............  ..........................  ......
+#
+     9.35%       git-repack  ./git                       [.] insert_obj_hash
+     9.12%              git  ./git                       [.] insert_obj_hash
+     7.31%              git  /lib64/libc-2.5.so          [.] memcpy
+     6.34%       git-repack  /lib64/libc-2.5.so          [.] _int_malloc
+     6.24%       git-repack  /lib64/libc-2.5.so          [.] memcpy
+     5.82%       git-repack  /lib64/libc-2.5.so          [.] __GI___fork
+     5.47%              git  /lib64/libc-2.5.so          [.] _int_malloc
+     2.99%              git  /lib64/libc-2.5.so          [.] memset
+
+Furthermore, call-graph sampling can be done too, of page
+allocations - to see precisely what kind of page allocations there
+are:
+
+ titan:~/git> perf record -f -g -e kmem:mm_page_alloc -c 1 ./git gc
+ Counting objects: 1148, done.
+ Delta compression using up to 2 threads.
+ Compressing objects: 100% (450/450), done.
+ Writing objects: 100% (1148/1148), done.
+ Total 1148 (delta 690), reused 1148 (delta 690)
+ [ perf record: Captured and wrote 0.963 MB perf.data (~42069 samples) ]
+
+ titan:~/git> perf report -g
+ # Samples: 10686
+ #
+ # Overhead          Command               Shared Object
+ # ........  ...............  ..........................
+ #
+    23.25%       git-repack  /lib64/libc-2.5.so
+                |
+                |--50.00%-- _int_free
+                |
+                |--37.50%-- __GI___fork
+                |          make_child
+                |
+                |--12.50%-- ptmalloc_unlock_all2
+                |          make_child
+                |
+                 --6.25%-- __GI_strcpy
+    21.61%              git  /lib64/libc-2.5.so
+                |
+                |--30.00%-- __GI_read
+                |          |
+                |           --83.33%-- git_config_from_file
+                |                     git_config
+                |                     |
+   [...]
+
+Or you can observe the whole system's page allocations for 10
+seconds:
+
+titan:~/git> perf stat -a -e kmem:mm_page_pcpu_drain -e
+kmem:mm_page_alloc -e kmem:mm_pagevec_free -e
+kmem:mm_page_free_direct sleep 10
+
+ Performance counter stats for 'sleep 10':
+
+         171585  kmem:mm_page_pcpu_drain
+         322114  kmem:mm_page_alloc
+          73623  kmem:mm_pagevec_free
+         254115  kmem:mm_page_free_direct
+
+   10.000591410  seconds time elapsed
+
+Or observe how fluctuating the page allocations are, via statistical
+analysis done over ten 1-second intervals:
+
+ titan:~/git> perf stat --repeat 10 -a -e kmem:mm_page_pcpu_drain -e
+   kmem:mm_page_alloc -e kmem:mm_pagevec_free -e
+   kmem:mm_page_free_direct sleep 1
+
+ Performance counter stats for 'sleep 1' (10 runs):
+
+          17254  kmem:mm_page_pcpu_drain    ( +-   3.709% )
+          34394  kmem:mm_page_alloc         ( +-   4.617% )
+           7509  kmem:mm_pagevec_free       ( +-   4.820% )
+          25653  kmem:mm_page_free_direct   ( +-   3.672% )
+
+    1.058135029  seconds time elapsed   ( +-   3.089% )
+
+Or you can annotate the recorded 'git gc' run on a per symbol basis
+and check which instructions/source-code generated page allocations:
+
+ titan:~/git> perf annotate __GI___fork
+ ------------------------------------------------
+  Percent |      Source code & Disassembly of libc-2.5.so
+ ------------------------------------------------
+          :
+          :
+          :      Disassembly of section .plt:
+          :      Disassembly of section .text:
+          :
+          :      00000031a2e95560 <__fork>:
+ [...]
+     0.00 :        31a2e95602:   b8 38 00 00 00          mov    $0x38,%eax
+     0.00 :        31a2e95607:   0f 05                   syscall
+    83.42 :        31a2e95609:   48 3d 00 f0 ff ff       cmp    $0xfffffffffffff000,%rax
+     0.00 :        31a2e9560f:   0f 87 4d 01 00 00       ja     31a2e95762 <__fork+0x202>
+     0.00 :        31a2e95615:   85 c0                   test   %eax,%eax
+
+( this shows that 83.42% of __GI___fork's page allocations come from
+  the 0x38 system call it performs. )
+
+etc. etc. - a lot more is possible. I could list a dozen of
+other different usecases straight away - neither of which is
+possible via /proc/vmstat.
+
+/proc/vmstat is not in the same league really, in terms of
+expressive power of system analysis and performance
+analysis.
+
+All that the above results needed were those new tracepoints
+in include/tracing/events/kmem.h.
+
+       Ingo
+
+
index 1dbc1eeb4c01259552e17372f3e6f279195b22d9..6be696b0a2bb60a915a945cec38e9fbcf0741725 100644 (file)
@@ -29,13 +29,67 @@ OPTIONS
        Select the PMU event. Selection can be a symbolic event name
        (use 'perf list' to list all events) or a raw PMU
        event (eventsel+umask) in the form of rNNN where NNN is a
-        hexadecimal event descriptor.
+       hexadecimal event descriptor.
 
 -a::
-        system-wide collection
+        System-wide collection.
 
 -l::
-        scale counter values
+        Scale counter values.
+
+-p::
+--pid=::
+       Record events on existing pid.
+
+-r::
+--realtime=::
+       Collect data with this RT SCHED_FIFO priority.
+-A::
+--append::
+       Append to the output file to do incremental profiling.
+
+-f::
+--force::
+       Overwrite existing data file.
+
+-c::
+--count=::
+       Event period to sample.
+
+-o::
+--output=::
+       Output file name.
+
+-i::
+--inherit::
+       Child tasks inherit counters.
+-F::
+--freq=::
+       Profile at this frequency.
+
+-m::
+--mmap-pages=::
+       Number of mmap data pages.
+
+-g::
+--call-graph::
+       Do call-graph (stack chain/backtrace) recording.
+
+-v::
+--verbose::
+       Be more verbose (show counter open errors, etc).
+
+-s::
+--stat::
+       Per thread counts.
+
+-d::
+--data::
+       Sample addresses.
+
+-n::
+--no-samples::
+       Don't sample.
 
 SEE ALSO
 --------
index 52d3fc6846a976e9947b7176a520273e639dfe6d..e72e931107826e069d5bfabc3677dca7a2745af6 100644 (file)
@@ -13,13 +13,40 @@ SYNOPSIS
 DESCRIPTION
 -----------
 This command displays the performance counter profile information recorded
-via perf report.
+via perf record.
 
 OPTIONS
 -------
 -i::
 --input=::
         Input file name. (default: perf.data)
+-d::
+--dsos=::
+       Only consider symbols in these dsos. CSV that understands
+       file://filename entries.
+-n
+--show-nr-samples
+       Show the number of samples for each symbol
+-C::
+--comms=::
+       Only consider symbols in these comms. CSV that understands
+       file://filename entries.
+-S::
+--symbols=::
+       Only consider these symbols. CSV that understands
+       file://filename entries.
+
+-w::
+--field-width=::
+       Force each column width to the provided list, for large terminal
+       readability.
+
+-t::
+--field-separator=::
+
+       Use a special separator character and don't pad with spaces, replacing
+       all occurances of this separator in symbol names (and other output)
+       with a '.' character, that thus it's the only non valid separator.
 
 SEE ALSO
 --------
index c368a72721d785b3836fe5c1e2a37bdcfc3082f5..484080dd5b6faea6397949065f989248b9574604 100644 (file)
@@ -8,8 +8,8 @@ perf-stat - Run a command and gather performance counter statistics
 SYNOPSIS
 --------
 [verse]
-'perf stat' [-e <EVENT> | --event=EVENT] [-l] [-a] <command>
-'perf stat' [-e <EVENT> | --event=EVENT] [-l] [-a] -- <command> [<options>]
+'perf stat' [-e <EVENT> | --event=EVENT] [-S] [-a] <command>
+'perf stat' [-e <EVENT> | --event=EVENT] [-S] [-a] -- <command> [<options>]
 
 DESCRIPTION
 -----------
@@ -40,7 +40,7 @@ OPTIONS
 -a::
         system-wide collection
 
--l::
+-c::
         scale counter values
 
 EXAMPLES
index 539d0128972508b754dc367b70d73f87641bd0b0..4a7d558dc309c731c91559e1d81c24ca2874246e 100644 (file)
@@ -3,36 +3,122 @@ perf-top(1)
 
 NAME
 ----
-perf-top - Run a command and profile it
+perf-top - System profiling tool.
 
 SYNOPSIS
 --------
 [verse]
-'perf top' [-e <EVENT> | --event=EVENT] [-l] [-a] <command>
+'perf top' [-e <EVENT> | --event=EVENT] [<options>]
 
 DESCRIPTION
 -----------
-This command runs a command and gathers a performance counter profile
-from it.
+This command generates and displays a performance counter profile in realtime.
 
 
 OPTIONS
 -------
-<command>...::
-       Any command you can specify in a shell.
+-a::
+--all-cpus::
+        System-wide collection.  (default)
+
+-c <count>::
+--count=<count>::
+       Event period to sample.
+
+-C <cpu>::
+--CPU=<cpu>::
+       CPU to profile.
+
+-d <seconds>::
+--delay=<seconds>::
+       Number of seconds to delay between refreshes.
 
--e::
---event=::
+-e <event>::
+--event=<event>::
        Select the PMU event. Selection can be a symbolic event name
        (use 'perf list' to list all events) or a raw PMU
        event (eventsel+umask) in the form of rNNN where NNN is a
-        hexadecimal event descriptor.
+       hexadecimal event descriptor.
 
--a::
-        system-wide collection
+-E <entries>::
+--entries=<entries>::
+       Display this many functions.
+
+-f <count>::
+--count-filter=<count>::
+       Only display functions with more events than this.
+
+-F <freq>::
+--freq=<freq>::
+       Profile at this frequency.
+
+-i::
+--inherit::
+       Child tasks inherit counters, only makes sens with -p option.
+
+-k <path>::
+--vmlinux=<path>::
+       Path to vmlinux.  Required for annotation functionality.
+
+-m <pages>::
+--mmap-pages=<pages>::
+       Number of mmapped data pages.
+
+-p <pid>::
+--pid=<pid>::
+       Profile events on existing pid.
+
+-r <priority>::
+--realtime=<priority>::
+       Collect data with this RT SCHED_FIFO priority.
+
+-s <symbol>::
+--sym-annotate=<symbol>::
+        Annotate this symbol.  Requires -k option.
+
+-v::
+--verbose::
+       Be more verbose (show counter open errors, etc).
+
+-z::
+--zero::
+       Zero history across display updates.
+
+INTERACTIVE PROMPTING KEYS
+--------------------------
+
+[d]::
+       Display refresh delay.
+
+[e]::
+       Number of entries to display.
+
+[E]::
+       Event to display when multiple counters are active.
+
+[f]::
+       Profile display filter (>= hit count).
+
+[F]::
+       Annotation display filter (>= % of total).
+
+[s]::
+       Annotate symbol.
+
+[S]::
+       Stop annotation, return to full profile display.
+
+[w]::
+       Toggle between weighted sum and individual count[E]r profile.
+
+[z]::
+       Toggle event count zeroing across display updates.
+
+[qQ]::
+       Quit.
+
+Pressing any unmapped key displays a menu, and prompts for input.
 
--l::
-        scale counter values
 
 SEE ALSO
 --------
index 36d7eef4991352e429480325542c23897ba6d194..c045b4271e57250fc7c983f810b77aeaced80525 100644 (file)
@@ -158,13 +158,15 @@ uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
 uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
 
 # If we're on a 64-bit kernel, use -m64
-ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M))
-  M64 := -m64
+ifndef NO_64BIT
+       ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M))
+         M64 := -m64
+       endif
 endif
 
 # CFLAGS and LDFLAGS are for the users to override from the command line.
 
-CFLAGS = $(M64) -ggdb3 -Wall -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6
+CFLAGS = $(M64) -ggdb3 -Wall -Wextra -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6
 LDFLAGS = -lpthread -lrt -lelf -lm
 ALL_CFLAGS = $(CFLAGS)
 ALL_LDFLAGS = $(LDFLAGS)
@@ -223,7 +225,7 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
 # Those must not be GNU-specific; they are shared with perl/ which may
 # be built by a different compiler. (Note that this is an artifact now
 # but it still might be nice to keep that distinction.)
-BASIC_CFLAGS =
+BASIC_CFLAGS = -Iutil/include
 BASIC_LDFLAGS =
 
 # Guard against environment variables
@@ -289,10 +291,11 @@ export PERL_PATH
 LIB_FILE=libperf.a
 
 LIB_H += ../../include/linux/perf_counter.h
+LIB_H += ../../include/linux/rbtree.h
+LIB_H += ../../include/linux/list.h
+LIB_H += util/include/linux/list.h
 LIB_H += perf.h
-LIB_H += types.h
-LIB_H += util/list.h
-LIB_H += util/rbtree.h
+LIB_H += util/types.h
 LIB_H += util/levenshtein.h
 LIB_H += util/parse-options.h
 LIB_H += util/parse-events.h
@@ -301,9 +304,11 @@ LIB_H += util/util.h
 LIB_H += util/help.h
 LIB_H += util/strbuf.h
 LIB_H += util/string.h
+LIB_H += util/strlist.h
 LIB_H += util/run-command.h
 LIB_H += util/sigchain.h
 LIB_H += util/symbol.h
+LIB_H += util/module.h
 LIB_H += util/color.h
 
 LIB_OBJS += util/abspath.o
@@ -322,12 +327,16 @@ LIB_OBJS += util/run-command.o
 LIB_OBJS += util/quote.o
 LIB_OBJS += util/strbuf.o
 LIB_OBJS += util/string.o
+LIB_OBJS += util/strlist.o
 LIB_OBJS += util/usage.o
 LIB_OBJS += util/wrapper.o
 LIB_OBJS += util/sigchain.o
 LIB_OBJS += util/symbol.o
+LIB_OBJS += util/module.o
 LIB_OBJS += util/color.o
 LIB_OBJS += util/pager.o
+LIB_OBJS += util/header.o
+LIB_OBJS += util/callchain.o
 
 BUILTIN_OBJS += builtin-annotate.o
 BUILTIN_OBJS += builtin-help.o
@@ -338,7 +347,6 @@ BUILTIN_OBJS += builtin-stat.o
 BUILTIN_OBJS += builtin-top.o
 
 PERFLIBS = $(LIB_FILE)
-EXTLIBS =
 
 #
 # Platform specific tweaks
@@ -367,6 +375,39 @@ ifeq ($(uname_S),Darwin)
        PTHREAD_LIBS =
 endif
 
+ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
+       msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel);
+endif
+
+ifdef NO_DEMANGLE
+       BASIC_CFLAGS += -DNO_DEMANGLE
+else
+       has_bfd := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd > /dev/null 2>&1 && echo y")
+
+       ifeq ($(has_bfd),y)
+               EXTLIBS += -lbfd
+       else
+               has_bfd_iberty := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd -liberty > /dev/null 2>&1 && echo y")
+               ifeq ($(has_bfd_iberty),y)
+                       EXTLIBS += -lbfd -liberty
+               else
+                       has_bfd_iberty_z := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd -liberty -lz > /dev/null 2>&1 && echo y")
+                       ifeq ($(has_bfd_iberty_z),y)
+                               EXTLIBS += -lbfd -liberty -lz
+                       else
+                               has_cplus_demangle := $(shell sh -c "(echo 'extern char *cplus_demangle(const char *, int);'; echo 'int main(void) { cplus_demangle(0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -liberty > /dev/null 2>&1 && echo y")
+                               ifeq ($(has_cplus_demangle),y)
+                                       EXTLIBS += -liberty
+                                       BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE
+                               else
+                                       msg := $(warning No bfd.h/libbfd found, install binutils-dev[el] to gain symbol demangling)
+                                       BASIC_CFLAGS += -DNO_DEMANGLE
+                               endif
+                       endif
+               endif
+       endif
+endif
+
 ifndef CC_LD_DYNPATH
        ifdef NO_R_TO_GCC_LINKER
                # Some gcc does not accept and pass -R to the linker to specify
@@ -377,12 +418,6 @@ ifndef CC_LD_DYNPATH
        endif
 endif
 
-ifdef ZLIB_PATH
-       BASIC_CFLAGS += -I$(ZLIB_PATH)/include
-       EXTLIBS += -L$(ZLIB_PATH)/$(lib) $(CC_LD_DYNPATH)$(ZLIB_PATH)/$(lib)
-endif
-EXTLIBS += -lz
-
 ifdef NEEDS_SOCKET
        EXTLIBS += -lsocket
 endif
@@ -693,6 +728,9 @@ builtin-init-db.o: builtin-init-db.c PERF-CFLAGS
 util/config.o: util/config.c PERF-CFLAGS
        $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
 
+util/rbtree.o: ../../lib/rbtree.c PERF-CFLAGS
+       $(QUIET_CC)$(CC) -o util/rbtree.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
+
 perf-%$X: %.o $(PERFLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
 
index 7e58e3ad1508053aa9cf92147caf15e1af80cee3..5e17de984dc839d0ad86932d73bf4e2c2c85b272 100644 (file)
@@ -10,9 +10,9 @@
 #include "util/util.h"
 
 #include "util/color.h"
-#include "util/list.h"
+#include <linux/list.h>
 #include "util/cache.h"
-#include "util/rbtree.h"
+#include <linux/rbtree.h>
 #include "util/symbol.h"
 #include "util/string.h"
 
 #define SHOW_USER      2
 #define SHOW_HV                4
 
-#define MIN_GREEN              0.5
-#define MIN_RED                5.0
-
-
 static char            const *input_name = "perf.data";
 static char            *vmlinux = "vmlinux";
 
 static char            default_sort_order[] = "comm,symbol";
 static char            *sort_order = default_sort_order;
 
+static int             force;
 static int             input;
 static int             show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
 
@@ -43,6 +40,10 @@ static int           dump_trace = 0;
 
 static int             verbose;
 
+static int             modules;
+
+static int             full_paths;
+
 static int             print_line;
 
 static unsigned long   page_size;
@@ -74,20 +75,12 @@ struct fork_event {
        u32 pid, ppid;
 };
 
-struct period_event {
-       struct perf_event_header header;
-       u64 time;
-       u64 id;
-       u64 sample_period;
-};
-
 typedef union event_union {
        struct perf_event_header        header;
        struct ip_event                 ip;
        struct mmap_event               mmap;
        struct comm_event               comm;
        struct fork_event               fork;
-       struct period_event             period;
 } event_t;
 
 
@@ -160,7 +153,7 @@ static void dsos__fprintf(FILE *fp)
 
 static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
 {
-       return dso__find_symbol(kernel_dso, ip);
+       return dso__find_symbol(dso, ip);
 }
 
 static int load_kernel(void)
@@ -171,8 +164,8 @@ static int load_kernel(void)
        if (!kernel_dso)
                return -1;
 
-       err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose);
-       if (err) {
+       err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules);
+       if (err <= 0) {
                dso__delete(kernel_dso);
                kernel_dso = NULL;
        } else
@@ -203,7 +196,7 @@ static u64 map__map_ip(struct map *map, u64 ip)
        return ip - map->start + map->pgoff;
 }
 
-static u64 vdso__map_ip(struct map *map, u64 ip)
+static u64 vdso__map_ip(struct map *map __used, u64 ip)
 {
        return ip;
 }
@@ -600,7 +593,7 @@ static LIST_HEAD(hist_entry__sort_list);
 
 static int sort_dimension__add(char *tok)
 {
-       int i;
+       unsigned int i;
 
        for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
                struct sort_dimension *sd = &sort_dimensions[i];
@@ -855,7 +848,7 @@ static unsigned long total = 0,
                     total_unknown = 0;
 
 static int
-process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
+process_sample_event(event_t *event, unsigned long offset, unsigned long head)
 {
        char level;
        int show = 0;
@@ -988,6 +981,13 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
                (void *)(long)(event->header.size),
                event->fork.pid, event->fork.ppid);
 
+       /*
+        * A thread clone will have the same PID for both
+        * parent and child.
+        */
+       if (thread == parent)
+               return 0;
+
        if (!thread || !parent || thread__fork(thread, parent)) {
                dprintf("problem processing PERF_EVENT_FORK, skipping event.\n");
                return -1;
@@ -997,26 +997,13 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
        return 0;
 }
 
-static int
-process_period_event(event_t *event, unsigned long offset, unsigned long head)
-{
-       dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n",
-               (void *)(offset + head),
-               (void *)(long)(event->header.size),
-               event->period.time,
-               event->period.id,
-               event->period.sample_period);
-
-       return 0;
-}
-
 static int
 process_event(event_t *event, unsigned long offset, unsigned long head)
 {
-       if (event->header.misc & PERF_EVENT_MISC_OVERFLOW)
-               return process_overflow_event(event, offset, head);
-
        switch (event->header.type) {
+       case PERF_EVENT_SAMPLE:
+               return process_sample_event(event, offset, head);
+
        case PERF_EVENT_MMAP:
                return process_mmap_event(event, offset, head);
 
@@ -1025,9 +1012,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
 
        case PERF_EVENT_FORK:
                return process_fork_event(event, offset, head);
-
-       case PERF_EVENT_PERIOD:
-               return process_period_event(event, offset, head);
        /*
         * We dont process them right now but they are fine:
         */
@@ -1043,24 +1027,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
        return 0;
 }
 
-static char *get_color(double percent)
-{
-       char *color = PERF_COLOR_NORMAL;
-
-       /*
-        * We color high-overhead entries in red, mid-overhead
-        * entries in green - and keep the low overhead places
-        * normal:
-        */
-       if (percent >= MIN_RED)
-               color = PERF_COLOR_RED;
-       else {
-               if (percent > MIN_GREEN)
-                       color = PERF_COLOR_GREEN;
-       }
-       return color;
-}
-
 static int
 parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
 {
@@ -1069,7 +1035,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
        static const char *prev_color;
        unsigned int offset;
        size_t line_len;
-       u64 line_ip;
+       s64 line_ip;
        int ret;
        char *c;
 
@@ -1122,7 +1088,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
                } else if (sym->hist_sum)
                        percent = 100.0 * hits / sym->hist_sum;
 
-               color = get_color(percent);
+               color = get_percent_color(percent);
 
                /*
                 * Also color the filename and line if needed, with
@@ -1258,7 +1224,7 @@ static void print_summary(char *filename)
 
                sym_ext = rb_entry(node, struct sym_ext, node);
                percent = sym_ext->percent;
-               color = get_color(percent);
+               color = get_percent_color(percent);
                path = sym_ext->path;
 
                color_fprintf(stdout, color, " %7.2f %s", percent, path);
@@ -1268,19 +1234,25 @@ static void print_summary(char *filename)
 
 static void annotate_sym(struct dso *dso, struct symbol *sym)
 {
-       char *filename = dso->name;
+       char *filename = dso->name, *d_filename;
        u64 start, end, len;
        char command[PATH_MAX*2];
        FILE *file;
 
        if (!filename)
                return;
-       if (dso == kernel_dso)
+       if (sym->module)
+               filename = sym->module->path;
+       else if (dso == kernel_dso)
                filename = vmlinux;
 
        start = sym->obj_start;
        if (!start)
                start = sym->start;
+       if (full_paths)
+               d_filename = filename;
+       else
+               d_filename = basename(filename);
 
        end = start + sym->end - sym->start + 1;
        len = sym->end - sym->start;
@@ -1291,13 +1263,14 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
        }
 
        printf("\n\n------------------------------------------------\n");
-       printf(" Percent |      Source code & Disassembly of %s\n", filename);
+       printf(" Percent |      Source code & Disassembly of %s\n", d_filename);
        printf("------------------------------------------------\n");
 
        if (verbose >= 2)
                printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name);
 
-       sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (u64)start, (u64)end, filename);
+       sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
+                       (u64)start, (u64)end, filename, filename);
 
        if (verbose >= 3)
                printf("doing: %s\n", command);
@@ -1362,6 +1335,11 @@ static int __cmd_annotate(void)
                exit(-1);
        }
 
+       if (!force && (stat.st_uid != geteuid())) {
+               fprintf(stderr, "file: %s not owned by current user\n", input_name);
+               exit(-1);
+       }
+
        if (!stat.st_size) {
                fprintf(stderr, "zero-sized file, nothing to do!\n");
                exit(0);
@@ -1428,7 +1406,7 @@ more:
 
        head += size;
 
-       if (offset + head < stat.st_size)
+       if (offset + head < (unsigned long)stat.st_size)
                goto more;
 
        rc = EXIT_SUCCESS;
@@ -1467,13 +1445,18 @@ static const struct option options[] = {
                    "input file name"),
        OPT_STRING('s', "symbol", &sym_hist_filter, "symbol",
                    "symbol to annotate"),
+       OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
        OPT_BOOLEAN('v', "verbose", &verbose,
                    "be more verbose (show symbol address, etc)"),
        OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
                    "dump raw trace in ASCII"),
        OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
+       OPT_BOOLEAN('m', "modules", &modules,
+                   "load module symbols - WARNING: use only with -k and LIVE kernel"),
        OPT_BOOLEAN('l', "print-line", &print_line,
                    "print matching source lines (may be slow)"),
+       OPT_BOOLEAN('P', "full-paths", &full_paths,
+                   "Don't shorten the displayed pathnames"),
        OPT_END()
 };
 
@@ -1492,7 +1475,7 @@ static void setup_sorting(void)
        free(str);
 }
 
-int cmd_annotate(int argc, const char **argv, const char *prefix)
+int cmd_annotate(int argc, const char **argv, const char *prefix __used)
 {
        symbol__init();
 
index 0f32dc3f3c4c7a45b5d18bf8fac59aabedb8069f..2599d86a733b404db9be615519fec61b3517a1dd 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Builtin help command
  */
+#include "perf.h"
 #include "util/cache.h"
 #include "builtin.h"
 #include "util/exec_cmd.h"
@@ -277,7 +278,7 @@ static struct cmdnames main_cmds, other_cmds;
 
 void list_common_cmds_help(void)
 {
-       int i, longest = 0;
+       unsigned int i, longest = 0;
 
        for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
                if (longest < strlen(common_cmds[i].name))
@@ -415,9 +416,10 @@ static void show_html_page(const char *perf_cmd)
        open_html(page_path.buf);
 }
 
-int cmd_help(int argc, const char **argv, const char *prefix)
+int cmd_help(int argc, const char **argv, const char *prefix __used)
 {
        const char *alias;
+
        load_command_list("perf-", &main_cmds, &other_cmds);
 
        perf_config(perf_help_config, NULL);
index fe60e37c96efc85e60e83d59d1cdb7127fe198c8..d88c6961274cf2e961eec9d1b420dc0621965a6a 100644 (file)
 
 #include "perf.h"
 
-#include "util/parse-options.h"
 #include "util/parse-events.h"
+#include "util/cache.h"
 
-int cmd_list(int argc, const char **argv, const char *prefix)
+int cmd_list(int argc __used, const char **argv __used, const char *prefix __used)
 {
+       setup_pager();
        print_events();
        return 0;
 }
index d7ebbd7575432f12c53109dc8c51054dd4a25f76..89a5ddcd1ded753e6835c39935989d4c96ac2fdd 100644 (file)
@@ -14,6 +14,8 @@
 #include "util/parse-events.h"
 #include "util/string.h"
 
+#include "util/header.h"
+
 #include <unistd.h>
 #include <sched.h>
 
@@ -32,13 +34,18 @@ static int                  output;
 static const char              *output_name                    = "perf.data";
 static int                     group                           = 0;
 static unsigned int            realtime_prio                   = 0;
+static int                     raw_samples                     = 0;
 static int                     system_wide                     = 0;
+static int                     profile_cpu                     = -1;
 static pid_t                   target_pid                      = -1;
 static int                     inherit                         = 1;
 static int                     force                           = 0;
 static int                     append_file                     = 0;
 static int                     call_graph                      = 0;
 static int                     verbose                         = 0;
+static int                     inherit_stat                    = 0;
+static int                     no_samples                      = 0;
+static int                     sample_address                  = 0;
 
 static long                    samples;
 static struct timeval          last_read;
@@ -52,7 +59,8 @@ static int                    nr_poll;
 static int                     nr_cpu;
 
 static int                     file_new = 1;
-static struct perf_file_header file_header;
+
+struct perf_header             *header;
 
 struct mmap_event {
        struct perf_event_header        header;
@@ -197,46 +205,48 @@ static void sig_atexit(void)
        kill(getpid(), signr);
 }
 
-static void pid_synthesize_comm_event(pid_t pid, int full)
+static pid_t pid_synthesize_comm_event(pid_t pid, int full)
 {
        struct comm_event comm_ev;
        char filename[PATH_MAX];
        char bf[BUFSIZ];
-       int fd;
-       size_t size;
-       char *field, *sep;
+       FILE *fp;
+       size_t size = 0;
        DIR *tasks;
        struct dirent dirent, *next;
+       pid_t tgid = 0;
 
-       snprintf(filename, sizeof(filename), "/proc/%d/stat", pid);
+       snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
 
-       fd = open(filename, O_RDONLY);
-       if (fd < 0) {
+       fp = fopen(filename, "r");
+       if (fp == NULL) {
                /*
                 * We raced with a task exiting - just return:
                 */
                if (verbose)
                        fprintf(stderr, "couldn't open %s\n", filename);
-               return;
+               return 0;
        }
-       if (read(fd, bf, sizeof(bf)) < 0) {
-               fprintf(stderr, "couldn't read %s\n", filename);
-               exit(EXIT_FAILURE);
-       }
-       close(fd);
 
-       /* 9027 (cat) R 6747 9027 6747 34816 9027 ... */
        memset(&comm_ev, 0, sizeof(comm_ev));
-       field = strchr(bf, '(');
-       if (field == NULL)
-               goto out_failure;
-       sep = strchr(++field, ')');
-       if (sep == NULL)
-               goto out_failure;
-       size = sep - field;
-       memcpy(comm_ev.comm, field, size++);
-
-       comm_ev.pid = pid;
+       while (!comm_ev.comm[0] || !comm_ev.pid) {
+               if (fgets(bf, sizeof(bf), fp) == NULL)
+                       goto out_failure;
+
+               if (memcmp(bf, "Name:", 5) == 0) {
+                       char *name = bf + 5;
+                       while (*name && isspace(*name))
+                               ++name;
+                       size = strlen(name) - 1;
+                       memcpy(comm_ev.comm, name, size++);
+               } else if (memcmp(bf, "Tgid:", 5) == 0) {
+                       char *tgids = bf + 5;
+                       while (*tgids && isspace(*tgids))
+                               ++tgids;
+                       tgid = comm_ev.pid = atoi(tgids);
+               }
+       }
+
        comm_ev.header.type = PERF_EVENT_COMM;
        size = ALIGN(size, sizeof(u64));
        comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size);
@@ -245,7 +255,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
                comm_ev.tid = pid;
 
                write_output(&comm_ev, comm_ev.header.size);
-               return;
+               goto out_fclose;
        }
 
        snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
@@ -262,7 +272,10 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
                write_output(&comm_ev, comm_ev.header.size);
        }
        closedir(tasks);
-       return;
+
+out_fclose:
+       fclose(fp);
+       return tgid;
 
 out_failure:
        fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n",
@@ -270,7 +283,7 @@ out_failure:
        exit(EXIT_FAILURE);
 }
 
-static void pid_synthesize_mmap_samples(pid_t pid)
+static void pid_synthesize_mmap_samples(pid_t pid, pid_t tgid)
 {
        char filename[PATH_MAX];
        FILE *fp;
@@ -289,7 +302,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
        while (1) {
                char bf[BUFSIZ], *pbf = bf;
                struct mmap_event mmap_ev = {
-                       .header.type = PERF_EVENT_MMAP,
+                       .header = { .type = PERF_EVENT_MMAP },
                };
                int n;
                size_t size;
@@ -306,12 +319,15 @@ static void pid_synthesize_mmap_samples(pid_t pid)
                        continue;
                pbf += n + 3;
                if (*pbf == 'x') { /* vm_exec */
-                       char *execname = strrchr(bf, ' ');
+                       char *execname = strchr(bf, '/');
 
-                       if (execname == NULL || execname[1] != '/')
+                       /* Catch VDSO */
+                       if (execname == NULL)
+                               execname = strstr(bf, "[vdso]");
+
+                       if (execname == NULL)
                                continue;
 
-                       execname += 1;
                        size = strlen(execname);
                        execname[size - 1] = '\0'; /* Remove \n */
                        memcpy(mmap_ev.filename, execname, size);
@@ -319,7 +335,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
                        mmap_ev.len -= mmap_ev.start;
                        mmap_ev.header.size = (sizeof(mmap_ev) -
                                               (sizeof(mmap_ev.filename) - size));
-                       mmap_ev.pid = pid;
+                       mmap_ev.pid = tgid;
                        mmap_ev.tid = pid;
 
                        write_output(&mmap_ev, mmap_ev.header.size);
@@ -329,7 +345,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
        fclose(fp);
 }
 
-static void synthesize_samples(void)
+static void synthesize_all(void)
 {
        DIR *proc;
        struct dirent dirent, *next;
@@ -338,14 +354,14 @@ static void synthesize_samples(void)
 
        while (!readdir_r(proc, &dirent, &next) && next) {
                char *end;
-               pid_t pid;
+               pid_t pid, tgid;
 
                pid = strtol(dirent.d_name, &end, 10);
                if (*end) /* only interested in proper numerical dirents */
                        continue;
 
-               pid_synthesize_comm_event(pid, 1);
-               pid_synthesize_mmap_samples(pid);
+               tgid = pid_synthesize_comm_event(pid, 1);
+               pid_synthesize_mmap_samples(pid, tgid);
        }
 
        closedir(proc);
@@ -353,12 +369,37 @@ static void synthesize_samples(void)
 
 static int group_fd;
 
+static struct perf_header_attr *get_header_attr(struct perf_counter_attr *a, int nr)
+{
+       struct perf_header_attr *h_attr;
+
+       if (nr < header->attrs) {
+               h_attr = header->attr[nr];
+       } else {
+               h_attr = perf_header_attr__new(a);
+               perf_header__add_attr(header, h_attr);
+       }
+
+       return h_attr;
+}
+
 static void create_counter(int counter, int cpu, pid_t pid)
 {
        struct perf_counter_attr *attr = attrs + counter;
-       int track = 1;
+       struct perf_header_attr *h_attr;
+       int track = !counter; /* only the first counter needs these */
+       struct {
+               u64 count;
+               u64 time_enabled;
+               u64 time_running;
+               u64 id;
+       } read_data;
 
-       attr->sample_type       = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
+       attr->read_format       = PERF_FORMAT_TOTAL_TIME_ENABLED |
+                                 PERF_FORMAT_TOTAL_TIME_RUNNING |
+                                 PERF_FORMAT_ID;
+
+       attr->sample_type       |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
 
        if (freq) {
                attr->sample_type       |= PERF_SAMPLE_PERIOD;
@@ -366,25 +407,26 @@ static void create_counter(int counter, int cpu, pid_t pid)
                attr->sample_freq       = freq;
        }
 
+       if (no_samples)
+               attr->sample_freq = 0;
+
+       if (inherit_stat)
+               attr->inherit_stat = 1;
+
+       if (sample_address)
+               attr->sample_type       |= PERF_SAMPLE_ADDR;
+
        if (call_graph)
                attr->sample_type       |= PERF_SAMPLE_CALLCHAIN;
 
-       if (file_new) {
-               file_header.sample_type = attr->sample_type;
-       } else {
-               if (file_header.sample_type != attr->sample_type) {
-                       fprintf(stderr, "incompatible append\n");
-                       exit(-1);
-               }
-       }
+       if (raw_samples)
+               attr->sample_type       |= PERF_SAMPLE_RAW;
 
        attr->mmap              = track;
        attr->comm              = track;
        attr->inherit           = (cpu < 0) && inherit;
        attr->disabled          = 1;
 
-       track = 0; /* only the first counter needs these */
-
 try_again:
        fd[nr_cpu][counter] = sys_perf_counter_open(attr, pid, cpu, group_fd, 0);
 
@@ -393,6 +435,8 @@ try_again:
 
                if (err == EPERM)
                        die("Permission error - are you root?\n");
+               else if (err ==  ENODEV && profile_cpu != -1)
+                       die("No such device - did you specify an out-of-range profile CPU?\n");
 
                /*
                 * If it's cycles then fall back to hrtimer
@@ -415,6 +459,22 @@ try_again:
                exit(-1);
        }
 
+       h_attr = get_header_attr(attr, counter);
+
+       if (!file_new) {
+               if (memcmp(&h_attr->attr, attr, sizeof(*attr))) {
+                       fprintf(stderr, "incompatible append\n");
+                       exit(-1);
+               }
+       }
+
+       if (read(fd[nr_cpu][counter], &read_data, sizeof(read_data)) == -1) {
+               perror("Unable to read perf file descriptor\n");
+               exit(-1);
+       }
+
+       perf_header_attr__add_id(h_attr, read_data.id);
+
        assert(fd[nr_cpu][counter] >= 0);
        fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK);
 
@@ -445,11 +505,6 @@ static void open_counters(int cpu, pid_t pid)
 {
        int counter;
 
-       if (pid > 0) {
-               pid_synthesize_comm_event(pid, 0);
-               pid_synthesize_mmap_samples(pid);
-       }
-
        group_fd = -1;
        for (counter = 0; counter < nr_counters; counter++)
                create_counter(counter, cpu, pid);
@@ -459,17 +514,16 @@ static void open_counters(int cpu, pid_t pid)
 
 static void atexit_header(void)
 {
-       file_header.data_size += bytes_written;
+       header->data_size += bytes_written;
 
-       if (pwrite(output, &file_header, sizeof(file_header), 0) == -1)
-               perror("failed to write on file headers");
+       perf_header__write(header, output);
 }
 
 static int __cmd_record(int argc, const char **argv)
 {
        int i, counter;
        struct stat st;
-       pid_t pid;
+       pid_t pid = 0;
        int flags;
        int ret;
 
@@ -482,10 +536,14 @@ static int __cmd_record(int argc, const char **argv)
        signal(SIGCHLD, sig_handler);
        signal(SIGINT, sig_handler);
 
-       if (!stat(output_name, &st) && !force && !append_file) {
-               fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n",
-                               output_name);
-               exit(-1);
+       if (!stat(output_name, &st) && st.st_size) {
+               if (!force && !append_file) {
+                       fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n",
+                                       output_name);
+                       exit(-1);
+               }
+       } else {
+               append_file = 0;
        }
 
        flags = O_CREAT|O_RDWR;
@@ -500,21 +558,36 @@ static int __cmd_record(int argc, const char **argv)
                exit(-1);
        }
 
-       if (!file_new) {
-               if (read(output, &file_header, sizeof(file_header)) == -1) {
-                       perror("failed to read file headers");
-                       exit(-1);
-               }
+       if (!file_new)
+               header = perf_header__read(output);
+       else
+               header = perf_header__new();
+
+       atexit(atexit_header);
 
-               lseek(output, file_header.data_size, SEEK_CUR);
+       if (!system_wide) {
+               pid = target_pid;
+               if (pid == -1)
+                       pid = getpid();
+
+               open_counters(profile_cpu, pid);
+       } else {
+               if (profile_cpu != -1) {
+                       open_counters(profile_cpu, target_pid);
+               } else {
+                       for (i = 0; i < nr_cpus; i++)
+                               open_counters(i, target_pid);
+               }
        }
 
-       atexit(atexit_header);
+       if (file_new)
+               perf_header__write(header, output);
 
        if (!system_wide) {
-               open_counters(-1, target_pid != -1 ? target_pid : getpid());
-       } else for (i = 0; i < nr_cpus; i++)
-               open_counters(i, target_pid);
+               pid_t tgid = pid_synthesize_comm_event(pid, 0);
+               pid_synthesize_mmap_samples(pid, tgid);
+       } else
+               synthesize_all();
 
        if (target_pid == -1 && argc) {
                pid = fork();
@@ -539,10 +612,7 @@ static int __cmd_record(int argc, const char **argv)
                }
        }
 
-       if (system_wide)
-               synthesize_samples();
-
-       while (!done) {
+       for (;;) {
                int hits = samples;
 
                for (i = 0; i < nr_cpu; i++) {
@@ -550,8 +620,11 @@ static int __cmd_record(int argc, const char **argv)
                                mmap_read(&mmap_array[i][counter]);
                }
 
-               if (hits == samples)
+               if (hits == samples) {
+                       if (done)
+                               break;
                        ret = poll(event_array, nr_poll, 100);
+               }
        }
 
        /*
@@ -580,10 +653,14 @@ static const struct option options[] = {
                    "record events on existing pid"),
        OPT_INTEGER('r', "realtime", &realtime_prio,
                    "collect data with this RT SCHED_FIFO priority"),
+       OPT_BOOLEAN('R', "raw-samples", &raw_samples,
+                   "collect raw sample records from all opened counters"),
        OPT_BOOLEAN('a', "all-cpus", &system_wide,
                            "system-wide collection from all CPUs"),
        OPT_BOOLEAN('A', "append", &append_file,
                            "append to the output file to do incremental profiling"),
+       OPT_INTEGER('C', "profile_cpu", &profile_cpu,
+                           "CPU to profile on"),
        OPT_BOOLEAN('f', "force", &force,
                        "overwrite existing data file"),
        OPT_LONG('c', "count", &default_interval,
@@ -600,14 +677,21 @@ static const struct option options[] = {
                    "do call-graph (stack chain/backtrace) recording"),
        OPT_BOOLEAN('v', "verbose", &verbose,
                    "be more verbose (show counter open errors, etc)"),
+       OPT_BOOLEAN('s', "stat", &inherit_stat,
+                   "per thread counts"),
+       OPT_BOOLEAN('d', "data", &sample_address,
+                   "Sample addresses"),
+       OPT_BOOLEAN('n', "no-samples", &no_samples,
+                   "don't sample"),
        OPT_END()
 };
 
-int cmd_record(int argc, const char **argv, const char *prefix)
+int cmd_record(int argc, const char **argv, const char *prefix __used)
 {
        int counter;
 
-       argc = parse_options(argc, argv, options, record_usage, 0);
+       argc = parse_options(argc, argv, options, record_usage,
+               PARSE_OPT_STOP_AT_NON_OPTION);
        if (!argc && target_pid == -1 && !system_wide)
                usage_with_options(record_usage, options);
 
index 5eb5566f0c95426dd3f5c4c3cf196faf55080fbd..8b2ec882e6e0e8b44230c1d3648007d3d91ccbfe 100644 (file)
 #include "util/util.h"
 
 #include "util/color.h"
-#include "util/list.h"
+#include <linux/list.h>
 #include "util/cache.h"
-#include "util/rbtree.h"
+#include <linux/rbtree.h>
 #include "util/symbol.h"
 #include "util/string.h"
+#include "util/callchain.h"
+#include "util/strlist.h"
 
 #include "perf.h"
+#include "util/header.h"
 
 #include "util/parse-options.h"
 #include "util/parse-events.h"
 static char            const *input_name = "perf.data";
 static char            *vmlinux = NULL;
 
-static char            default_sort_order[] = "comm,dso";
+static char            default_sort_order[] = "comm,dso,symbol";
 static char            *sort_order = default_sort_order;
+static char            *dso_list_str, *comm_list_str, *sym_list_str,
+                       *col_width_list_str;
+static struct strlist  *dso_list, *comm_list, *sym_list;
+static char            *field_sep;
 
+static int             force;
 static int             input;
 static int             show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
 
@@ -41,7 +49,10 @@ static int           dump_trace = 0;
 static int             verbose;
 #define eprintf(x...)  do { if (verbose) fprintf(stderr, x); } while (0)
 
+static int             modules;
+
 static int             full_paths;
+static int             show_nr_samples;
 
 static unsigned long   page_size;
 static unsigned long   mmap_window = 32;
@@ -52,6 +63,18 @@ static regex_t               parent_regex;
 
 static int             exclude_other = 1;
 
+static char            callchain_default_opt[] = "fractal,0.5";
+
+static int             callchain;
+
+static
+struct callchain_param callchain_param = {
+       .mode   = CHAIN_GRAPH_REL,
+       .min_percent = 0.5
+};
+
+static u64             sample_type;
+
 struct ip_event {
        struct perf_event_header header;
        u64 ip;
@@ -59,11 +82,6 @@ struct ip_event {
        unsigned char __more_data[];
 };
 
-struct ip_callchain {
-       u64 nr;
-       u64 ips[0];
-};
-
 struct mmap_event {
        struct perf_event_header header;
        u32 pid, tid;
@@ -82,19 +100,22 @@ struct comm_event {
 struct fork_event {
        struct perf_event_header header;
        u32 pid, ppid;
+       u32 tid, ptid;
 };
 
-struct period_event {
+struct lost_event {
        struct perf_event_header header;
-       u64 time;
        u64 id;
-       u64 sample_period;
+       u64 lost;
 };
 
-struct lost_event {
+struct read_event {
        struct perf_event_header header;
+       u32 pid,tid;
+       u64 value;
+       u64 time_enabled;
+       u64 time_running;
        u64 id;
-       u64 lost;
 };
 
 typedef union event_union {
@@ -103,13 +124,41 @@ typedef union event_union {
        struct mmap_event               mmap;
        struct comm_event               comm;
        struct fork_event               fork;
-       struct period_event             period;
        struct lost_event               lost;
+       struct read_event               read;
 } event_t;
 
+static int repsep_fprintf(FILE *fp, const char *fmt, ...)
+{
+       int n;
+       va_list ap;
+
+       va_start(ap, fmt);
+       if (!field_sep)
+               n = vfprintf(fp, fmt, ap);
+       else {
+               char *bf = NULL;
+               n = vasprintf(&bf, fmt, ap);
+               if (n > 0) {
+                       char *sep = bf;
+                       while (1) {
+                               sep = strchr(sep, *field_sep);
+                               if (sep == NULL)
+                                       break;
+                               *sep = '.';
+                       }
+               }
+               fputs(bf, fp);
+               free(bf);
+       }
+       va_end(ap);
+       return n;
+}
+
 static LIST_HEAD(dsos);
 static struct dso *kernel_dso;
 static struct dso *vdso;
+static struct dso *hypervisor_dso;
 
 static void dsos__add(struct dso *dso)
 {
@@ -165,7 +214,7 @@ static void dsos__fprintf(FILE *fp)
 
 static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
 {
-       return dso__find_symbol(kernel_dso, ip);
+       return dso__find_symbol(dso, ip);
 }
 
 static int load_kernel(void)
@@ -176,8 +225,8 @@ static int load_kernel(void)
        if (!kernel_dso)
                return -1;
 
-       err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose);
-       if (err) {
+       err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules);
+       if (err <= 0) {
                dso__delete(kernel_dso);
                kernel_dso = NULL;
        } else
@@ -191,6 +240,11 @@ static int load_kernel(void)
 
        dsos__add(vdso);
 
+       hypervisor_dso = dso__new("[hypervisor]", 0);
+       if (!hypervisor_dso)
+               return -1;
+       dsos__add(hypervisor_dso);
+
        return err;
 }
 
@@ -202,7 +256,7 @@ static int strcommon(const char *pathname)
 {
        int n = 0;
 
-       while (pathname[n] == cwd[n] && n < cwdlen)
+       while (n < cwdlen && pathname[n] == cwd[n])
                ++n;
 
        return n;
@@ -222,14 +276,14 @@ static u64 map__map_ip(struct map *map, u64 ip)
        return ip - map->start + map->pgoff;
 }
 
-static u64 vdso__map_ip(struct map *map, u64 ip)
+static u64 vdso__map_ip(struct map *map __used, u64 ip)
 {
        return ip;
 }
 
 static inline int is_anon_memory(const char *filename)
 {
-     return strcmp(filename, "//anon") == 0;
+       return strcmp(filename, "//anon") == 0;
 }
 
 static struct map *map__new(struct mmap_event *event)
@@ -332,12 +386,28 @@ static struct thread *thread__new(pid_t pid)
        return self;
 }
 
+static unsigned int dsos__col_width,
+                   comms__col_width,
+                   threads__col_width;
+
 static int thread__set_comm(struct thread *self, const char *comm)
 {
        if (self->comm)
                free(self->comm);
        self->comm = strdup(comm);
-       return self->comm ? 0 : -ENOMEM;
+       if (!self->comm)
+               return -ENOMEM;
+
+       if (!col_width_list_str && !field_sep &&
+           (!comm_list || strlist__has_entry(comm_list, comm))) {
+               unsigned int slen = strlen(comm);
+               if (slen > comms__col_width) {
+                       comms__col_width = slen;
+                       threads__col_width = slen + 6;
+               }
+       }
+
+       return 0;
 }
 
 static size_t thread__fprintf(struct thread *self, FILE *fp)
@@ -400,9 +470,27 @@ static void thread__insert_map(struct thread *self, struct map *map)
 
        list_for_each_entry_safe(pos, tmp, &self->maps, node) {
                if (map__overlap(pos, map)) {
-                       list_del_init(&pos->node);
-                       /* XXX leaks dsos */
-                       free(pos);
+                       if (verbose >= 2) {
+                               printf("overlapping maps:\n");
+                               map__fprintf(map, stdout);
+                               map__fprintf(pos, stdout);
+                       }
+
+                       if (map->start <= pos->start && map->end > pos->start)
+                               pos->start = map->end;
+
+                       if (map->end >= pos->end && map->start < pos->end)
+                               pos->end = map->start;
+
+                       if (verbose >= 2) {
+                               printf("after collision:\n");
+                               map__fprintf(pos, stdout);
+                       }
+
+                       if (pos->start >= pos->end) {
+                               list_del_init(&pos->node);
+                               free(pos);
+                       }
                }
        }
 
@@ -464,17 +552,19 @@ static size_t threads__fprintf(FILE *fp)
 static struct rb_root hist;
 
 struct hist_entry {
-       struct rb_node   rb_node;
-
-       struct thread    *thread;
-       struct map       *map;
-       struct dso       *dso;
-       struct symbol    *sym;
-       struct symbol    *parent;
-       u64              ip;
-       char             level;
-
-       u64              count;
+       struct rb_node          rb_node;
+
+       struct thread           *thread;
+       struct map              *map;
+       struct dso              *dso;
+       struct symbol           *sym;
+       struct symbol           *parent;
+       u64                     ip;
+       char                    level;
+       struct callchain_node   callchain;
+       struct rb_root          sorted_chain;
+
+       u64                     count;
 };
 
 /*
@@ -488,7 +578,9 @@ struct sort_entry {
 
        int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
        int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
-       size_t  (*print)(FILE *fp, struct hist_entry *);
+       size_t  (*print)(FILE *fp, struct hist_entry *, unsigned int width);
+       unsigned int *width;
+       bool    elide;
 };
 
 static int64_t cmp_null(void *l, void *r)
@@ -510,15 +602,17 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
 }
 
 static size_t
-sort__thread_print(FILE *fp, struct hist_entry *self)
+sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
 {
-       return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid);
+       return repsep_fprintf(fp, "%*s:%5d", width - 6,
+                             self->thread->comm ?: "", self->thread->pid);
 }
 
 static struct sort_entry sort_thread = {
-       .header = "         Command:  Pid",
+       .header = "Command:  Pid",
        .cmp    = sort__thread_cmp,
        .print  = sort__thread_print,
+       .width  = &threads__col_width,
 };
 
 /* --sort comm */
@@ -542,16 +636,17 @@ sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
 }
 
 static size_t
-sort__comm_print(FILE *fp, struct hist_entry *self)
+sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
 {
-       return fprintf(fp, "%16s", self->thread->comm);
+       return repsep_fprintf(fp, "%*s", width, self->thread->comm);
 }
 
 static struct sort_entry sort_comm = {
-       .header         = "         Command",
+       .header         = "Command",
        .cmp            = sort__comm_cmp,
        .collapse       = sort__comm_collapse,
        .print          = sort__comm_print,
+       .width          = &comms__col_width,
 };
 
 /* --sort dso */
@@ -569,18 +664,19 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
 }
 
 static size_t
-sort__dso_print(FILE *fp, struct hist_entry *self)
+sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
 {
        if (self->dso)
-               return fprintf(fp, "%-25s", self->dso->name);
+               return repsep_fprintf(fp, "%-*s", width, self->dso->name);
 
-       return fprintf(fp, "%016llx         ", (u64)self->ip);
+       return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
 }
 
 static struct sort_entry sort_dso = {
-       .header = "Shared Object            ",
+       .header = "Shared Object",
        .cmp    = sort__dso_cmp,
        .print  = sort__dso_print,
+       .width  = &dsos__col_width,
 };
 
 /* --sort symbol */
@@ -600,18 +696,23 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
 }
 
 static size_t
-sort__sym_print(FILE *fp, struct hist_entry *self)
+sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
 {
        size_t ret = 0;
 
        if (verbose)
-               ret += fprintf(fp, "%#018llx  ", (u64)self->ip);
+               ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip,
+                                     dso__symtab_origin(self->dso));
 
+       ret += repsep_fprintf(fp, "[%c] ", self->level);
        if (self->sym) {
-               ret += fprintf(fp, "[%c] %s",
-                       self->dso == kernel_dso ? 'k' : '.', self->sym->name);
+               ret += repsep_fprintf(fp, "%s", self->sym->name);
+
+               if (self->sym->module)
+                       ret += repsep_fprintf(fp, "\t[%s]",
+                                            self->sym->module->name);
        } else {
-               ret += fprintf(fp, "%#016llx", (u64)self->ip);
+               ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
        }
 
        return ret;
@@ -638,19 +739,19 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
 }
 
 static size_t
-sort__parent_print(FILE *fp, struct hist_entry *self)
+sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
 {
-       size_t ret = 0;
-
-       ret += fprintf(fp, "%-20s", self->parent ? self->parent->name : "[other]");
-
-       return ret;
+       return repsep_fprintf(fp, "%-*s", width,
+                             self->parent ? self->parent->name : "[other]");
 }
 
+static unsigned int parent_symbol__col_width;
+
 static struct sort_entry sort_parent = {
-       .header = "Parent symbol       ",
+       .header = "Parent symbol",
        .cmp    = sort__parent_cmp,
        .print  = sort__parent_print,
+       .width  = &parent_symbol__col_width,
 };
 
 static int sort__need_collapse = 0;
@@ -674,7 +775,7 @@ static LIST_HEAD(hist_entry__sort_list);
 
 static int sort_dimension__add(char *tok)
 {
-       int i;
+       unsigned int i;
 
        for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
                struct sort_dimension *sd = &sort_dimensions[i];
@@ -744,6 +845,204 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
        return cmp;
 }
 
+static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask)
+{
+       int i;
+       size_t ret = 0;
+
+       ret += fprintf(fp, "%s", "                ");
+
+       for (i = 0; i < depth; i++)
+               if (depth_mask & (1 << i))
+                       ret += fprintf(fp, "|          ");
+               else
+                       ret += fprintf(fp, "           ");
+
+       ret += fprintf(fp, "\n");
+
+       return ret;
+}
+static size_t
+ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
+                      int depth_mask, int count, u64 total_samples,
+                      int hits)
+{
+       int i;
+       size_t ret = 0;
+
+       ret += fprintf(fp, "%s", "                ");
+       for (i = 0; i < depth; i++) {
+               if (depth_mask & (1 << i))
+                       ret += fprintf(fp, "|");
+               else
+                       ret += fprintf(fp, " ");
+               if (!count && i == depth - 1) {
+                       double percent;
+
+                       percent = hits * 100.0 / total_samples;
+                       ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
+               } else
+                       ret += fprintf(fp, "%s", "          ");
+       }
+       if (chain->sym)
+               ret += fprintf(fp, "%s\n", chain->sym->name);
+       else
+               ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
+
+       return ret;
+}
+
+static struct symbol *rem_sq_bracket;
+static struct callchain_list rem_hits;
+
+static void init_rem_hits(void)
+{
+       rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
+       if (!rem_sq_bracket) {
+               fprintf(stderr, "Not enough memory to display remaining hits\n");
+               return;
+       }
+
+       strcpy(rem_sq_bracket->name, "[...]");
+       rem_hits.sym = rem_sq_bracket;
+}
+
+static size_t
+callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
+                       u64 total_samples, int depth, int depth_mask)
+{
+       struct rb_node *node, *next;
+       struct callchain_node *child;
+       struct callchain_list *chain;
+       int new_depth_mask = depth_mask;
+       u64 new_total;
+       u64 remaining;
+       size_t ret = 0;
+       int i;
+
+       if (callchain_param.mode == CHAIN_GRAPH_REL)
+               new_total = self->children_hit;
+       else
+               new_total = total_samples;
+
+       remaining = new_total;
+
+       node = rb_first(&self->rb_root);
+       while (node) {
+               u64 cumul;
+
+               child = rb_entry(node, struct callchain_node, rb_node);
+               cumul = cumul_hits(child);
+               remaining -= cumul;
+
+               /*
+                * The depth mask manages the output of pipes that show
+                * the depth. We don't want to keep the pipes of the current
+                * level for the last child of this depth.
+                * Except if we have remaining filtered hits. They will
+                * supersede the last child
+                */
+               next = rb_next(node);
+               if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
+                       new_depth_mask &= ~(1 << (depth - 1));
+
+               /*
+                * But we keep the older depth mask for the line seperator
+                * to keep the level link until we reach the last child
+                */
+               ret += ipchain__fprintf_graph_line(fp, depth, depth_mask);
+               i = 0;
+               list_for_each_entry(chain, &child->val, list) {
+                       if (chain->ip >= PERF_CONTEXT_MAX)
+                               continue;
+                       ret += ipchain__fprintf_graph(fp, chain, depth,
+                                                     new_depth_mask, i++,
+                                                     new_total,
+                                                     cumul);
+               }
+               ret += callchain__fprintf_graph(fp, child, new_total,
+                                               depth + 1,
+                                               new_depth_mask | (1 << depth));
+               node = next;
+       }
+
+       if (callchain_param.mode == CHAIN_GRAPH_REL &&
+               remaining && remaining != new_total) {
+
+               if (!rem_sq_bracket)
+                       return ret;
+
+               new_depth_mask &= ~(1 << (depth - 1));
+
+               ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
+                                             new_depth_mask, 0, new_total,
+                                             remaining);
+       }
+
+       return ret;
+}
+
+static size_t
+callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
+                       u64 total_samples)
+{
+       struct callchain_list *chain;
+       size_t ret = 0;
+
+       if (!self)
+               return 0;
+
+       ret += callchain__fprintf_flat(fp, self->parent, total_samples);
+
+
+       list_for_each_entry(chain, &self->val, list) {
+               if (chain->ip >= PERF_CONTEXT_MAX)
+                       continue;
+               if (chain->sym)
+                       ret += fprintf(fp, "                %s\n", chain->sym->name);
+               else
+                       ret += fprintf(fp, "                %p\n",
+                                       (void *)(long)chain->ip);
+       }
+
+       return ret;
+}
+
+static size_t
+hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
+                             u64 total_samples)
+{
+       struct rb_node *rb_node;
+       struct callchain_node *chain;
+       size_t ret = 0;
+
+       rb_node = rb_first(&self->sorted_chain);
+       while (rb_node) {
+               double percent;
+
+               chain = rb_entry(rb_node, struct callchain_node, rb_node);
+               percent = chain->hit * 100.0 / total_samples;
+               switch (callchain_param.mode) {
+               case CHAIN_FLAT:
+                       ret += percent_color_fprintf(fp, "           %6.2f%%\n",
+                                                    percent);
+                       ret += callchain__fprintf_flat(fp, chain, total_samples);
+                       break;
+               case CHAIN_GRAPH_ABS: /* Falldown */
+               case CHAIN_GRAPH_REL:
+                       ret += callchain__fprintf_graph(fp, chain,
+                                                       total_samples, 1, 1);
+               default:
+                       break;
+               }
+               ret += fprintf(fp, "\n");
+               rb_node = rb_next(rb_node);
+       }
+
+       return ret;
+}
+
+
 static size_t
 hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
 {
@@ -753,37 +1052,33 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
        if (exclude_other && !self->parent)
                return 0;
 
-       if (total_samples) {
-               double percent = self->count * 100.0 / total_samples;
-               char *color = PERF_COLOR_NORMAL;
-
-               /*
-                * We color high-overhead entries in red, mid-overhead
-                * entries in green - and keep the low overhead places
-                * normal:
-                */
-               if (percent >= 5.0) {
-                       color = PERF_COLOR_RED;
-               } else {
-                       if (percent >= 0.5)
-                               color = PERF_COLOR_GREEN;
-               }
+       if (total_samples)
+               ret = percent_color_fprintf(fp,
+                                           field_sep ? "%.2f" : "   %6.2f%%",
+                                       (self->count * 100.0) / total_samples);
+       else
+               ret = fprintf(fp, field_sep ? "%lld" : "%12lld ", self->count);
 
-               ret = color_fprintf(fp, color, "   %6.2f%%",
-                               (self->count * 100.0) / total_samples);
-       } else
-               ret = fprintf(fp, "%12Ld ", self->count);
+       if (show_nr_samples) {
+               if (field_sep)
+                       fprintf(fp, "%c%lld", *field_sep, self->count);
+               else
+                       fprintf(fp, "%11lld", self->count);
+       }
 
        list_for_each_entry(se, &hist_entry__sort_list, list) {
-               if (exclude_other && (se == &sort_parent))
+               if (se->elide)
                        continue;
 
-               fprintf(fp, "  ");
-               ret += se->print(fp, self);
+               fprintf(fp, "%s", field_sep ?: "  ");
+               ret += se->print(fp, self, se->width ? *se->width : 0);
        }
 
        ret += fprintf(fp, "\n");
 
+       if (callchain)
+               hist_entry_callchain__fprintf(fp, self, total_samples);
+
        return ret;
 }
 
@@ -791,13 +1086,25 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
  *
  */
 
+static void dso__calc_col_width(struct dso *self)
+{
+       if (!col_width_list_str && !field_sep &&
+           (!dso_list || strlist__has_entry(dso_list, self->name))) {
+               unsigned int slen = strlen(self->name);
+               if (slen > dsos__col_width)
+                       dsos__col_width = slen;
+       }
+
+       self->slen_calculated = 1;
+}
+
 static struct symbol *
 resolve_symbol(struct thread *thread, struct map **mapp,
               struct dso **dsop, u64 *ipp)
 {
        struct dso *dso = dsop ? *dsop : NULL;
        struct map *map = mapp ? *mapp : NULL;
-       uint64_t ip = *ipp;
+       u64 ip = *ipp;
 
        if (!thread)
                return NULL;
@@ -810,11 +1117,18 @@ resolve_symbol(struct thread *thread, struct map **mapp,
 
        map = thread__find_map(thread, ip);
        if (map != NULL) {
+               /*
+                * We have to do this here as we may have a dso
+                * with no symbol hit that has a name longer than
+                * the ones with symbols sampled.
+                */
+               if (!sort_dso.elide && !map->dso->slen_calculated)
+                       dso__calc_col_width(map->dso);
+
                if (mapp)
                        *mapp = map;
 got_map:
                ip = map->map_ip(map, ip);
-               *ipp  = ip;
 
                dso = map->dso;
        } else {
@@ -828,6 +1142,8 @@ got_map:
                dso = kernel_dso;
        }
        dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
+       dprintf(" ...... map: %Lx -> %Lx\n", *ipp, ip);
+       *ipp  = ip;
 
        if (dsop)
                *dsop = dso;
@@ -846,6 +1162,58 @@ static int call__match(struct symbol *sym)
        return 0;
 }
 
+static struct symbol **
+resolve_callchain(struct thread *thread, struct map *map __used,
+                   struct ip_callchain *chain, struct hist_entry *entry)
+{
+       u64 context = PERF_CONTEXT_MAX;
+       struct symbol **syms = NULL;
+       unsigned int i;
+
+       if (callchain) {
+               syms = calloc(chain->nr, sizeof(*syms));
+               if (!syms) {
+                       fprintf(stderr, "Can't allocate memory for symbols\n");
+                       exit(-1);
+               }
+       }
+
+       for (i = 0; i < chain->nr; i++) {
+               u64 ip = chain->ips[i];
+               struct dso *dso = NULL;
+               struct symbol *sym;
+
+               if (ip >= PERF_CONTEXT_MAX) {
+                       context = ip;
+                       continue;
+               }
+
+               switch (context) {
+               case PERF_CONTEXT_HV:
+                       dso = hypervisor_dso;
+                       break;
+               case PERF_CONTEXT_KERNEL:
+                       dso = kernel_dso;
+                       break;
+               default:
+                       break;
+               }
+
+               sym = resolve_symbol(thread, NULL, &dso, &ip);
+
+               if (sym) {
+                       if (sort__has_parent && call__match(sym) &&
+                           !entry->parent)
+                               entry->parent = sym;
+                       if (!callchain)
+                               break;
+                       syms[i] = sym;
+               }
+       }
+
+       return syms;
+}
+
 /*
  * collect histogram counts
  */
@@ -858,6 +1226,7 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
        struct rb_node **p = &hist.rb_node;
        struct rb_node *parent = NULL;
        struct hist_entry *he;
+       struct symbol **syms = NULL;
        struct hist_entry entry = {
                .thread = thread,
                .map    = map,
@@ -867,39 +1236,12 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
                .level  = level,
                .count  = count,
                .parent = NULL,
+               .sorted_chain = RB_ROOT
        };
        int cmp;
 
-       if (sort__has_parent && chain) {
-               u64 context = PERF_CONTEXT_MAX;
-               int i;
-
-               for (i = 0; i < chain->nr; i++) {
-                       u64 ip = chain->ips[i];
-                       struct dso *dso = NULL;
-                       struct symbol *sym;
-
-                       if (ip >= PERF_CONTEXT_MAX) {
-                               context = ip;
-                               continue;
-                       }
-
-                       switch (context) {
-                       case PERF_CONTEXT_KERNEL:
-                               dso = kernel_dso;
-                               break;
-                       default:
-                               break;
-                       }
-
-                       sym = resolve_symbol(thread, NULL, &dso, &ip);
-
-                       if (sym && call__match(sym)) {
-                               entry.parent = sym;
-                               break;
-                       }
-               }
-       }
+       if ((sort__has_parent || callchain) && chain)
+               syms = resolve_callchain(thread, map, chain, &entry);
 
        while (*p != NULL) {
                parent = *p;
@@ -909,6 +1251,10 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
 
                if (!cmp) {
                        he->count += count;
+                       if (callchain) {
+                               append_chain(&he->callchain, chain, syms);
+                               free(syms);
+                       }
                        return 0;
                }
 
@@ -922,6 +1268,11 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
        if (!he)
                return -ENOMEM;
        *he = entry;
+       if (callchain) {
+               callchain_init(&he->callchain);
+               append_chain(&he->callchain, chain, syms);
+               free(syms);
+       }
        rb_link_node(&he->rb_node, parent, p);
        rb_insert_color(&he->rb_node, &hist);
 
@@ -992,12 +1343,16 @@ static void collapse__resort(void)
 
 static struct rb_root output_hists;
 
-static void output__insert_entry(struct hist_entry *he)
+static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
 {
        struct rb_node **p = &output_hists.rb_node;
        struct rb_node *parent = NULL;
        struct hist_entry *iter;
 
+       if (callchain)
+               callchain_param.sort(&he->sorted_chain, &he->callchain,
+                                     min_callchain_hits, &callchain_param);
+
        while (*p != NULL) {
                parent = *p;
                iter = rb_entry(parent, struct hist_entry, rb_node);
@@ -1012,11 +1367,14 @@ static void output__insert_entry(struct hist_entry *he)
        rb_insert_color(&he->rb_node, &output_hists);
 }
 
-static void output__resort(void)
+static void output__resort(u64 total_samples)
 {
        struct rb_node *next;
        struct hist_entry *n;
        struct rb_root *tree = &hist;
+       u64 min_callchain_hits;
+
+       min_callchain_hits = total_samples * (callchain_param.min_percent / 100);
 
        if (sort__need_collapse)
                tree = &collapse_hists;
@@ -1028,7 +1386,7 @@ static void output__resort(void)
                next = rb_next(&n->rb_node);
 
                rb_erase(&n->rb_node, tree);
-               output__insert_entry(n);
+               output__insert_entry(n, min_callchain_hits);
        }
 }
 
@@ -1038,35 +1396,69 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
        struct sort_entry *se;
        struct rb_node *nd;
        size_t ret = 0;
+       unsigned int width;
+       char *col_width = col_width_list_str;
 
-       fprintf(fp, "\n");
-       fprintf(fp, "#\n");
-       fprintf(fp, "# (%Ld samples)\n", (u64)total_samples);
+       init_rem_hits();
+
+       fprintf(fp, "# Samples: %Ld\n", (u64)total_samples);
        fprintf(fp, "#\n");
 
        fprintf(fp, "# Overhead");
+       if (show_nr_samples) {
+               if (field_sep)
+                       fprintf(fp, "%cSamples", *field_sep);
+               else
+                       fputs("  Samples  ", fp);
+       }
        list_for_each_entry(se, &hist_entry__sort_list, list) {
-               if (exclude_other && (se == &sort_parent))
+               if (se->elide)
+                       continue;
+               if (field_sep) {
+                       fprintf(fp, "%c%s", *field_sep, se->header);
                        continue;
-               fprintf(fp, "  %s", se->header);
+               }
+               width = strlen(se->header);
+               if (se->width) {
+                       if (col_width_list_str) {
+                               if (col_width) {
+                                       *se->width = atoi(col_width);
+                                       col_width = strchr(col_width, ',');
+                                       if (col_width)
+                                               ++col_width;
+                               }
+                       }
+                       width = *se->width = max(*se->width, width);
+               }
+               fprintf(fp, "  %*s", width, se->header);
        }
        fprintf(fp, "\n");
 
+       if (field_sep)
+               goto print_entries;
+
        fprintf(fp, "# ........");
+       if (show_nr_samples)
+               fprintf(fp, " ..........");
        list_for_each_entry(se, &hist_entry__sort_list, list) {
-               int i;
+               unsigned int i;
 
-               if (exclude_other && (se == &sort_parent))
+               if (se->elide)
                        continue;
 
                fprintf(fp, "  ");
-               for (i = 0; i < strlen(se->header); i++)
+               if (se->width)
+                       width = *se->width;
+               else
+                       width = strlen(se->header);
+               for (i = 0; i < width; i++)
                        fprintf(fp, ".");
        }
        fprintf(fp, "\n");
 
        fprintf(fp, "#\n");
 
+print_entries:
        for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
                pos = rb_entry(nd, struct hist_entry, rb_node);
                ret += hist_entry__fprintf(fp, pos, total_samples);
@@ -1075,11 +1467,13 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
        if (sort_order == default_sort_order &&
                        parent_pattern == default_parent_pattern) {
                fprintf(fp, "#\n");
-               fprintf(fp, "# (For more details, try: perf report --sort comm,dso,symbol)\n");
+               fprintf(fp, "# (For a higher level overview, try: perf report --sort comm,dso)\n");
                fprintf(fp, "#\n");
        }
        fprintf(fp, "\n");
 
+       free(rem_sq_bracket);
+
        return ret;
 }
 
@@ -1115,7 +1509,7 @@ static int validate_chain(struct ip_callchain *chain, event_t *event)
 }
 
 static int
-process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
+process_sample_event(event_t *event, unsigned long offset, unsigned long head)
 {
        char level;
        int show = 0;
@@ -1126,22 +1520,23 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
        struct map *map = NULL;
        void *more_data = event->ip.__more_data;
        struct ip_callchain *chain = NULL;
+       int cpumode;
 
-       if (event->header.type & PERF_SAMPLE_PERIOD) {
+       if (sample_type & PERF_SAMPLE_PERIOD) {
                period = *(u64 *)more_data;
                more_data += sizeof(u64);
        }
 
-       dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p period: %Ld\n",
+       dprintf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n",
                (void *)(offset + head),
                (void *)(long)(event->header.size),
                event->header.misc,
-               event->ip.pid,
+               event->ip.pid, event->ip.tid,
                (void *)(long)ip,
                (long long)period);
 
-       if (event->header.type & PERF_SAMPLE_CALLCHAIN) {
-               int i;
+       if (sample_type & PERF_SAMPLE_CALLCHAIN) {
+               unsigned int i;
 
                chain = (void *)more_data;
 
@@ -1166,7 +1561,12 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
                return -1;
        }
 
-       if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
+       if (comm_list && !strlist__has_entry(comm_list, thread->comm))
+               return 0;
+
+       cpumode = event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK;
+
+       if (cpumode == PERF_EVENT_MISC_KERNEL) {
                show = SHOW_KERNEL;
                level = 'k';
 
@@ -1174,7 +1574,7 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
 
                dprintf(" ...... dso: %s\n", dso->name);
 
-       } else if (event->header.misc & PERF_EVENT_MISC_USER) {
+       } else if (cpumode == PERF_EVENT_MISC_USER) {
 
                show = SHOW_USER;
                level = '.';
@@ -1182,12 +1582,22 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
        } else {
                show = SHOW_HV;
                level = 'H';
+
+               dso = hypervisor_dso;
+
                dprintf(" ...... dso: [hypervisor]\n");
        }
 
        if (show & show_mask) {
                struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip);
 
+               if (dso_list && (!dso || !dso->name ||
+                                !strlist__has_entry(dso_list, dso->name)))
+                       return 0;
+
+               if (sym_list && (!sym || !strlist__has_entry(sym_list, sym->name)))
+                       return 0;
+
                if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) {
                        eprintf("problem incrementing symbol count, skipping event\n");
                        return -1;
@@ -1204,10 +1614,11 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
        struct thread *thread = threads__findnew(event->mmap.pid);
        struct map *map = map__new(&event->mmap);
 
-       dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n",
+       dprintf("%p [%p]: PERF_EVENT_MMAP %d/%d: [%p(%p) @ %p]: %s\n",
                (void *)(offset + head),
                (void *)(long)(event->header.size),
                event->mmap.pid,
+               event->mmap.tid,
                (void *)(long)event->mmap.start,
                (void *)(long)event->mmap.len,
                (void *)(long)event->mmap.pgoff,
@@ -1245,15 +1656,27 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
 }
 
 static int
-process_fork_event(event_t *event, unsigned long offset, unsigned long head)
+process_task_event(event_t *event, unsigned long offset, unsigned long head)
 {
        struct thread *thread = threads__findnew(event->fork.pid);
        struct thread *parent = threads__findnew(event->fork.ppid);
 
-       dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n",
+       dprintf("%p [%p]: PERF_EVENT_%s: (%d:%d):(%d:%d)\n",
                (void *)(offset + head),
                (void *)(long)(event->header.size),
-               event->fork.pid, event->fork.ppid);
+               event->header.type == PERF_EVENT_FORK ? "FORK" : "EXIT",
+               event->fork.pid, event->fork.tid,
+               event->fork.ppid, event->fork.ptid);
+
+       /*
+        * A thread clone will have the same PID for both
+        * parent and child.
+        */
+       if (thread == parent)
+               return 0;
+
+       if (event->header.type == PERF_EVENT_EXIT)
+               return 0;
 
        if (!thread || !parent || thread__fork(thread, parent)) {
                dprintf("problem processing PERF_EVENT_FORK, skipping event.\n");
@@ -1264,19 +1687,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
        return 0;
 }
 
-static int
-process_period_event(event_t *event, unsigned long offset, unsigned long head)
-{
-       dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n",
-               (void *)(offset + head),
-               (void *)(long)(event->header.size),
-               event->period.time,
-               event->period.id,
-               event->period.sample_period);
-
-       return 0;
-}
-
 static int
 process_lost_event(event_t *event, unsigned long offset, unsigned long head)
 {
@@ -1327,15 +1737,51 @@ static void trace_event(event_t *event)
        dprintf(".\n");
 }
 
+static struct perf_header      *header;
+
+static struct perf_counter_attr *perf_header__find_attr(u64 id)
+{
+       int i;
+
+       for (i = 0; i < header->attrs; i++) {
+               struct perf_header_attr *attr = header->attr[i];
+               int j;
+
+               for (j = 0; j < attr->ids; j++) {
+                       if (attr->id[j] == id)
+                               return &attr->attr;
+               }
+       }
+
+       return NULL;
+}
+
+static int
+process_read_event(event_t *event, unsigned long offset, unsigned long head)
+{
+       struct perf_counter_attr *attr = perf_header__find_attr(event->read.id);
+
+       dprintf("%p [%p]: PERF_EVENT_READ: %d %d %s %Lu\n",
+                       (void *)(offset + head),
+                       (void *)(long)(event->header.size),
+                       event->read.pid,
+                       event->read.tid,
+                       attr ? __event_name(attr->type, attr->config)
+                            : "FAIL",
+                       event->read.value);
+
+       return 0;
+}
+
 static int
 process_event(event_t *event, unsigned long offset, unsigned long head)
 {
        trace_event(event);
 
-       if (event->header.misc & PERF_EVENT_MISC_OVERFLOW)
-               return process_overflow_event(event, offset, head);
-
        switch (event->header.type) {
+       case PERF_EVENT_SAMPLE:
+               return process_sample_event(event, offset, head);
+
        case PERF_EVENT_MMAP:
                return process_mmap_event(event, offset, head);
 
@@ -1343,14 +1789,15 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
                return process_comm_event(event, offset, head);
 
        case PERF_EVENT_FORK:
-               return process_fork_event(event, offset, head);
-
-       case PERF_EVENT_PERIOD:
-               return process_period_event(event, offset, head);
+       case PERF_EVENT_EXIT:
+               return process_task_event(event, offset, head);
 
        case PERF_EVENT_LOST:
                return process_lost_event(event, offset, head);
 
+       case PERF_EVENT_READ:
+               return process_read_event(event, offset, head);
+
        /*
         * We dont process them right now but they are fine:
         */
@@ -1366,13 +1813,28 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
        return 0;
 }
 
-static struct perf_file_header         file_header;
+static u64 perf_header__sample_type(void)
+{
+       u64 sample_type = 0;
+       int i;
+
+       for (i = 0; i < header->attrs; i++) {
+               struct perf_header_attr *attr = header->attr[i];
+
+               if (!sample_type)
+                       sample_type = attr->attr.sample_type;
+               else if (sample_type != attr->attr.sample_type)
+                       die("non matching sample_type");
+       }
+
+       return sample_type;
+}
 
 static int __cmd_report(void)
 {
        int ret, rc = EXIT_FAILURE;
        unsigned long offset = 0;
-       unsigned long head = sizeof(file_header);
+       unsigned long head, shift;
        struct stat stat;
        event_t *event;
        uint32_t size;
@@ -1395,20 +1857,41 @@ static int __cmd_report(void)
                exit(-1);
        }
 
+       if (!force && (stat.st_uid != geteuid())) {
+               fprintf(stderr, "file: %s not owned by current user\n", input_name);
+               exit(-1);
+       }
+
        if (!stat.st_size) {
                fprintf(stderr, "zero-sized file, nothing to do!\n");
                exit(0);
        }
 
-       if (read(input, &file_header, sizeof(file_header)) == -1) {
-               perror("failed to read file headers");
-               exit(-1);
-       }
+       header = perf_header__read(input);
+       head = header->data_offset;
 
-       if (sort__has_parent &&
-           !(file_header.sample_type & PERF_SAMPLE_CALLCHAIN)) {
-               fprintf(stderr, "selected --sort parent, but no callchain data\n");
-               exit(-1);
+       sample_type = perf_header__sample_type();
+
+       if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
+               if (sort__has_parent) {
+                       fprintf(stderr, "selected --sort parent, but no"
+                                       " callchain data. Did you call"
+                                       " perf record without -g?\n");
+                       exit(-1);
+               }
+               if (callchain) {
+                       fprintf(stderr, "selected -c but no callchain data."
+                                       " Did you call perf record without"
+                                       " -g?\n");
+                       exit(-1);
+               }
+       } else if (callchain_param.mode != CHAIN_NONE && !callchain) {
+                       callchain = 1;
+                       if (register_callchain_param(&callchain_param) < 0) {
+                               fprintf(stderr, "Can't register callchain"
+                                               " params\n");
+                               exit(-1);
+                       }
        }
 
        if (load_kernel() < 0) {
@@ -1426,6 +1909,11 @@ static int __cmd_report(void)
                cwd = NULL;
                cwdlen = 0;
        }
+
+       shift = page_size * (head / page_size);
+       offset += shift;
+       head -= shift;
+
 remap:
        buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
                           MAP_SHARED, input, offset);
@@ -1442,9 +1930,10 @@ more:
                size = 8;
 
        if (head + event->header.size >= page_size * mmap_window) {
-               unsigned long shift = page_size * (head / page_size);
                int ret;
 
+               shift = page_size * (head / page_size);
+
                ret = munmap(buf, page_size * mmap_window);
                assert(ret == 0);
 
@@ -1482,10 +1971,10 @@ more:
 
        head += size;
 
-       if (offset + head >= sizeof(file_header) + file_header.data_size)
+       if (offset + head >= header->data_offset + header->data_size)
                goto done;
 
-       if (offset + head < stat.st_size)
+       if (offset + head < (unsigned long)stat.st_size)
                goto more;
 
 done:
@@ -1509,12 +1998,65 @@ done:
                dsos__fprintf(stdout);
 
        collapse__resort();
-       output__resort();
+       output__resort(total);
        output__fprintf(stdout, total);
 
        return rc;
 }
 
+static int
+parse_callchain_opt(const struct option *opt __used, const char *arg,
+                   int unset __used)
+{
+       char *tok;
+       char *endptr;
+
+       callchain = 1;
+
+       if (!arg)
+               return 0;
+
+       tok = strtok((char *)arg, ",");
+       if (!tok)
+               return -1;
+
+       /* get the output mode */
+       if (!strncmp(tok, "graph", strlen(arg)))
+               callchain_param.mode = CHAIN_GRAPH_ABS;
+
+       else if (!strncmp(tok, "flat", strlen(arg)))
+               callchain_param.mode = CHAIN_FLAT;
+
+       else if (!strncmp(tok, "fractal", strlen(arg)))
+               callchain_param.mode = CHAIN_GRAPH_REL;
+
+       else if (!strncmp(tok, "none", strlen(arg))) {
+               callchain_param.mode = CHAIN_NONE;
+               callchain = 0;
+
+               return 0;
+       }
+
+       else
+               return -1;
+
+       /* get the min percentage */
+       tok = strtok(NULL, ",");
+       if (!tok)
+               goto setup;
+
+       callchain_param.min_percent = strtod(tok, &endptr);
+       if (tok == endptr)
+               return -1;
+
+setup:
+       if (register_callchain_param(&callchain_param) < 0) {
+               fprintf(stderr, "Can't register callchain params\n");
+               return -1;
+       }
+       return 0;
+}
+
 static const char * const report_usage[] = {
        "perf report [<options>] <command>",
        NULL
@@ -1528,6 +2070,11 @@ static const struct option options[] = {
        OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
                    "dump raw trace in ASCII"),
        OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
+       OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
+       OPT_BOOLEAN('m', "modules", &modules,
+                   "load module symbols - WARNING: use only with -k and LIVE kernel"),
+       OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples,
+                   "Show a column with the number of samples"),
        OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
                   "sort by key(s): pid, comm, dso, symbol, parent"),
        OPT_BOOLEAN('P', "full-paths", &full_paths,
@@ -1536,6 +2083,21 @@ static const struct option options[] = {
                   "regex filter to identify parent, see: '--sort parent'"),
        OPT_BOOLEAN('x', "exclude-other", &exclude_other,
                    "Only display entries with parent-match"),
+       OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent",
+                    "Display callchains using output_type and min percent threshold. "
+                    "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt),
+       OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]",
+                  "only consider symbols in these dsos"),
+       OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]",
+                  "only consider symbols in these comms"),
+       OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]",
+                  "only consider these symbols"),
+       OPT_STRING('w', "column-widths", &col_width_list_str,
+                  "width[,width...]",
+                  "don't try to adjust column width, use these fixed values"),
+       OPT_STRING('t', "field-separator", &field_sep, "separator",
+                  "separator for columns, no spaces will be added between "
+                  "columns '.' is reserved."),
        OPT_END()
 };
 
@@ -1554,7 +2116,26 @@ static void setup_sorting(void)
        free(str);
 }
 
-int cmd_report(int argc, const char **argv, const char *prefix)
+static void setup_list(struct strlist **list, const char *list_str,
+                      struct sort_entry *se, const char *list_name,
+                      FILE *fp)
+{
+       if (list_str) {
+               *list = strlist__new(true, list_str);
+               if (!*list) {
+                       fprintf(stderr, "problems parsing %s list\n",
+                               list_name);
+                       exit(129);
+               }
+               if (strlist__nr_entries(*list) == 1) {
+                       fprintf(fp, "# %s: %s\n", list_name,
+                               strlist__entry(*list, 0)->s);
+                       se->elide = true;
+               }
+       }
+}
+
+int cmd_report(int argc, const char **argv, const char *prefix __used)
 {
        symbol__init();
 
@@ -1564,9 +2145,10 @@ int cmd_report(int argc, const char **argv, const char *prefix)
 
        setup_sorting();
 
-       if (parent_pattern != default_parent_pattern)
+       if (parent_pattern != default_parent_pattern) {
                sort_dimension__add("parent");
-       else
+               sort_parent.elide = 1;
+       } else
                exclude_other = 0;
 
        /*
@@ -1577,5 +2159,15 @@ int cmd_report(int argc, const char **argv, const char *prefix)
 
        setup_pager();
 
+       setup_list(&dso_list, dso_list_str, &sort_dso, "dso", stdout);
+       setup_list(&comm_list, comm_list_str, &sort_comm, "comm", stdout);
+       setup_list(&sym_list, sym_list_str, &sort_sym, "symbol", stdout);
+
+       if (field_sep && *field_sep == '.') {
+               fputs("'.' is the only non valid --field-separator argument\n",
+                     stderr);
+               exit(129);
+       }
+
        return __cmd_report();
 }
index 6d3eeac1ea257b47c898dae49c6336c35c4c43f4..b4b06c7903e10085de24250224a197a8182c27d3 100644 (file)
@@ -32,6 +32,7 @@
  *   Wu Fengguang <fengguang.wu@intel.com>
  *   Mike Galbraith <efault@gmx.de>
  *   Paul Mackerras <paulus@samba.org>
+ *   Jaswinder Singh Rajput <jaswinder@kernel.org>
  *
  * Released under the GPL v2. (and only v2, not any later version)
  */
@@ -45,7 +46,7 @@
 #include <sys/prctl.h>
 #include <math.h>
 
-static struct perf_counter_attr default_attrs[MAX_COUNTERS] = {
+static struct perf_counter_attr default_attrs[] = {
 
   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK     },
   { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES},
@@ -59,42 +60,28 @@ static struct perf_counter_attr default_attrs[MAX_COUNTERS] = {
 
 };
 
+#define MAX_RUN                        100
+
 static int                     system_wide                     =  0;
-static int                     inherit                         =  1;
 static int                     verbose                         =  0;
+static unsigned int            nr_cpus                         =  0;
+static int                     run_idx                         =  0;
 
-static int                     fd[MAX_NR_CPUS][MAX_COUNTERS];
-
-static int                     target_pid                      = -1;
-static int                     nr_cpus                         =  0;
-static unsigned int            page_size;
-
+static int                     run_count                       =  1;
+static int                     inherit                         =  1;
 static int                     scale                           =  1;
+static int                     target_pid                      = -1;
+static int                     null_run                        =  0;
 
-static const unsigned int default_count[] = {
-       1000000,
-       1000000,
-         10000,
-         10000,
-       1000000,
-         10000,
-};
-
-#define MAX_RUN 100
-
-static int                     run_count               =  1;
-static int                     run_idx                 =  0;
-
-static u64                     event_res[MAX_RUN][MAX_COUNTERS][3];
-static u64                     event_scaled[MAX_RUN][MAX_COUNTERS];
-
-//static u64                   event_hist[MAX_RUN][MAX_COUNTERS][3];
-
+static int                     fd[MAX_NR_CPUS][MAX_COUNTERS];
 
 static u64                     runtime_nsecs[MAX_RUN];
 static u64                     walltime_nsecs[MAX_RUN];
 static u64                     runtime_cycles[MAX_RUN];
 
+static u64                     event_res[MAX_RUN][MAX_COUNTERS][3];
+static u64                     event_scaled[MAX_RUN][MAX_COUNTERS];
+
 static u64                     event_res_avg[MAX_COUNTERS][3];
 static u64                     event_res_noise[MAX_COUNTERS][3];
 
@@ -109,7 +96,14 @@ static u64                  walltime_nsecs_noise;
 static u64                     runtime_cycles_avg;
 static u64                     runtime_cycles_noise;
 
-static void create_perf_stat_counter(int counter)
+#define MATCH_EVENT(t, c, counter)                     \
+       (attrs[counter].type == PERF_TYPE_##t &&        \
+        attrs[counter].config == PERF_COUNT_##c)
+
+#define ERR_PERF_OPEN \
+"Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n"
+
+static void create_perf_stat_counter(int counter, int pid)
 {
        struct perf_counter_attr *attr = attrs + counter;
 
@@ -118,21 +112,23 @@ static void create_perf_stat_counter(int counter)
                                    PERF_FORMAT_TOTAL_TIME_RUNNING;
 
        if (system_wide) {
-               int cpu;
-               for (cpu = 0; cpu < nr_cpus; cpu ++) {
+               unsigned int cpu;
+
+               for (cpu = 0; cpu < nr_cpus; cpu++) {
                        fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0);
-                       if (fd[cpu][counter] < 0 && verbose) {
-                               printf("Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n", counter, fd[cpu][counter], strerror(errno));
-                       }
+                       if (fd[cpu][counter] < 0 && verbose)
+                               fprintf(stderr, ERR_PERF_OPEN, counter,
+                                       fd[cpu][counter], strerror(errno));
                }
        } else {
-               attr->inherit   = inherit;
-               attr->disabled  = 1;
-
-               fd[0][counter] = sys_perf_counter_open(attr, 0, -1, -1, 0);
-               if (fd[0][counter] < 0 && verbose) {
-                       printf("Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n", counter, fd[0][counter], strerror(errno));
-               }
+               attr->inherit        = inherit;
+               attr->disabled       = 1;
+               attr->enable_on_exec = 1;
+
+               fd[0][counter] = sys_perf_counter_open(attr, pid, -1, -1, 0);
+               if (fd[0][counter] < 0 && verbose)
+                       fprintf(stderr, ERR_PERF_OPEN, counter,
+                               fd[0][counter], strerror(errno));
        }
 }
 
@@ -141,13 +137,8 @@ static void create_perf_stat_counter(int counter)
  */
 static inline int nsec_counter(int counter)
 {
-       if (attrs[counter].type != PERF_TYPE_SOFTWARE)
-               return 0;
-
-       if (attrs[counter].config == PERF_COUNT_SW_CPU_CLOCK)
-               return 1;
-
-       if (attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
+       if (MATCH_EVENT(SOFTWARE, SW_CPU_CLOCK, counter) ||
+           MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
                return 1;
 
        return 0;
@@ -159,8 +150,8 @@ static inline int nsec_counter(int counter)
 static void read_counter(int counter)
 {
        u64 *count, single_count[3];
-       ssize_t res;
-       int cpu, nv;
+       unsigned int cpu;
+       size_t res, nv;
        int scaled;
 
        count = event_res[run_idx][counter];
@@ -168,12 +159,13 @@ static void read_counter(int counter)
        count[0] = count[1] = count[2] = 0;
 
        nv = scale ? 3 : 1;
-       for (cpu = 0; cpu < nr_cpus; cpu ++) {
+       for (cpu = 0; cpu < nr_cpus; cpu++) {
                if (fd[cpu][counter] < 0)
                        continue;
 
                res = read(fd[cpu][counter], single_count, nv * sizeof(u64));
                assert(res == nv * sizeof(u64));
+
                close(fd[cpu][counter]);
                fd[cpu][counter] = -1;
 
@@ -201,46 +193,81 @@ static void read_counter(int counter)
        /*
         * Save the full runtime - to allow normalization during printout:
         */
-       if (attrs[counter].type == PERF_TYPE_SOFTWARE &&
-               attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
+       if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
                runtime_nsecs[run_idx] = count[0];
-       if (attrs[counter].type == PERF_TYPE_HARDWARE &&
-               attrs[counter].config == PERF_COUNT_HW_CPU_CYCLES)
+       if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter))
                runtime_cycles[run_idx] = count[0];
 }
 
-static int run_perf_stat(int argc, const char **argv)
+static int run_perf_stat(int argc __used, const char **argv)
 {
        unsigned long long t0, t1;
        int status = 0;
        int counter;
        int pid;
+       int child_ready_pipe[2], go_pipe[2];
+       char buf;
 
        if (!system_wide)
                nr_cpus = 1;
 
-       for (counter = 0; counter < nr_counters; counter++)
-               create_perf_stat_counter(counter);
-
-       /*
-        * Enable counters and exec the command:
-        */
-       t0 = rdclock();
-       prctl(PR_TASK_PERF_COUNTERS_ENABLE);
+       if (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0) {
+               perror("failed to create pipes");
+               exit(1);
+       }
 
        if ((pid = fork()) < 0)
                perror("failed to fork");
 
        if (!pid) {
-               if (execvp(argv[0], (char **)argv)) {
-                       perror(argv[0]);
-                       exit(-1);
-               }
+               close(child_ready_pipe[0]);
+               close(go_pipe[1]);
+               fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
+
+               /*
+                * Do a dummy execvp to get the PLT entry resolved,
+                * so we avoid the resolver overhead on the real
+                * execvp call.
+                */
+               execvp("", (char **)argv);
+
+               /*
+                * Tell the parent we're ready to go
+                */
+               close(child_ready_pipe[1]);
+
+               /*
+                * Wait until the parent tells us to go.
+                */
+               if (read(go_pipe[0], &buf, 1) == -1)
+                       perror("unable to read pipe");
+
+               execvp(argv[0], (char **)argv);
+
+               perror(argv[0]);
+               exit(-1);
        }
 
+       /*
+        * Wait for the child to be ready to exec.
+        */
+       close(child_ready_pipe[1]);
+       close(go_pipe[0]);
+       if (read(child_ready_pipe[0], &buf, 1) == -1)
+               perror("unable to read pipe");
+       close(child_ready_pipe[0]);
+
+       for (counter = 0; counter < nr_counters; counter++)
+               create_perf_stat_counter(counter, pid);
+
+       /*
+        * Enable counters and exec the command:
+        */
+       t0 = rdclock();
+
+       close(go_pipe[1]);
        wait(&status);
 
-       prctl(PR_TASK_PERF_COUNTERS_DISABLE);
        t1 = rdclock();
 
        walltime_nsecs[run_idx] = t1 - t0;
@@ -262,11 +289,9 @@ static void nsec_printout(int counter, u64 *count, u64 *noise)
 {
        double msecs = (double)count[0] / 1000000;
 
-       fprintf(stderr, " %14.6f  %-20s", msecs, event_name(counter));
-
-       if (attrs[counter].type == PERF_TYPE_SOFTWARE &&
-               attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) {
+       fprintf(stderr, " %14.6f  %-24s", msecs, event_name(counter));
 
+       if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) {
                if (walltime_nsecs_avg)
                        fprintf(stderr, " # %10.3f CPUs ",
                                (double)count[0] / (double)walltime_nsecs_avg);
@@ -276,12 +301,10 @@ static void nsec_printout(int counter, u64 *count, u64 *noise)
 
 static void abs_printout(int counter, u64 *count, u64 *noise)
 {
-       fprintf(stderr, " %14Ld  %-20s", count[0], event_name(counter));
+       fprintf(stderr, " %14Ld  %-24s", count[0], event_name(counter));
 
        if (runtime_cycles_avg &&
-               attrs[counter].type == PERF_TYPE_HARDWARE &&
-                       attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) {
-
+           MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) {
                fprintf(stderr, " # %10.3f IPC  ",
                        (double)count[0] / (double)runtime_cycles_avg);
        } else {
@@ -306,7 +329,7 @@ static void print_counter(int counter)
        scaled = event_scaled_avg[counter];
 
        if (scaled == -1) {
-               fprintf(stderr, " %14s  %-20s\n",
+               fprintf(stderr, " %14s  %-24s\n",
                        "<not counted>", event_name(counter));
                return;
        }
@@ -364,8 +387,11 @@ static void calc_avg(void)
                                event_res_avg[j]+1, event_res[i][j]+1);
                        update_avg("counter/2", j,
                                event_res_avg[j]+2, event_res[i][j]+2);
-                       update_avg("scaled", j,
-                               event_scaled_avg + j, event_scaled[i]+j);
+                       if (event_scaled[i][j] != (u64)-1)
+                               update_avg("scaled", j,
+                                       event_scaled_avg + j, event_scaled[i]+j);
+                       else
+                               event_scaled_avg[j] = -1;
                }
        }
        runtime_nsecs_avg /= run_count;
@@ -429,11 +455,14 @@ static void print_stat(int argc, const char **argv)
        for (counter = 0; counter < nr_counters; counter++)
                print_counter(counter);
 
-
        fprintf(stderr, "\n");
-       fprintf(stderr, " %14.9f  seconds time elapsed.\n",
+       fprintf(stderr, " %14.9f  seconds time elapsed",
                        (double)walltime_nsecs_avg/1e9);
-       fprintf(stderr, "\n");
+       if (run_count > 1) {
+               fprintf(stderr, "   ( +- %7.3f%% )",
+                       100.0*(double)walltime_nsecs_noise/(double)walltime_nsecs_avg);
+       }
+       fprintf(stderr, "\n\n");
 }
 
 static volatile int signr = -1;
@@ -466,36 +495,38 @@ static const struct option options[] = {
        OPT_INTEGER('p', "pid", &target_pid,
                    "stat events on existing pid"),
        OPT_BOOLEAN('a', "all-cpus", &system_wide,
-                           "system-wide collection from all CPUs"),
-       OPT_BOOLEAN('S', "scale", &scale,
-                           "scale/normalize counters"),
+                   "system-wide collection from all CPUs"),
+       OPT_BOOLEAN('c', "scale", &scale,
+                   "scale/normalize counters"),
        OPT_BOOLEAN('v', "verbose", &verbose,
                    "be more verbose (show counter open errors, etc)"),
        OPT_INTEGER('r', "repeat", &run_count,
                    "repeat command and print average + stddev (max: 100)"),
+       OPT_BOOLEAN('n', "null", &null_run,
+                   "null run - dont start any counters"),
        OPT_END()
 };
 
-int cmd_stat(int argc, const char **argv, const char *prefix)
+int cmd_stat(int argc, const char **argv, const char *prefix __used)
 {
        int status;
 
-       page_size = sysconf(_SC_PAGE_SIZE);
-
-       memcpy(attrs, default_attrs, sizeof(attrs));
-
-       argc = parse_options(argc, argv, options, stat_usage, 0);
+       argc = parse_options(argc, argv, options, stat_usage,
+               PARSE_OPT_STOP_AT_NON_OPTION);
        if (!argc)
                usage_with_options(stat_usage, options);
        if (run_count <= 0 || run_count > MAX_RUN)
                usage_with_options(stat_usage, options);
 
-       if (!nr_counters)
-               nr_counters = 8;
+       /* Set attrs and nr_counters if no event is selected and !null_run */
+       if (!null_run && !nr_counters) {
+               memcpy(attrs, default_attrs, sizeof(default_attrs));
+               nr_counters = ARRAY_SIZE(default_attrs);
+       }
 
        nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
        assert(nr_cpus <= MAX_NR_CPUS);
-       assert(nr_cpus >= 0);
+       assert((int)nr_cpus >= 0);
 
        /*
         * We dont want to block the signals - that would cause
@@ -511,7 +542,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix)
        status = 0;
        for (run_idx = 0; run_idx < run_count; run_idx++) {
                if (run_count != 1 && verbose)
-                       fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx+1);
+                       fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1);
                status = run_perf_stat(argc, argv);
        }
 
index 5352b5e352ed3a87552c917bd63a50ff301a620e..7de28ce9ca260b8610a2e3f30858de1ed413eb15 100644 (file)
@@ -23,7 +23,7 @@
 #include "util/symbol.h"
 #include "util/color.h"
 #include "util/util.h"
-#include "util/rbtree.h"
+#include <linux/rbtree.h>
 #include "util/parse-options.h"
 #include "util/parse-events.h"
 
@@ -31,6 +31,8 @@
 #include <fcntl.h>
 
 #include <stdio.h>
+#include <termios.h>
+#include <unistd.h>
 
 #include <errno.h>
 #include <time.h>
@@ -54,10 +56,11 @@ static int                  system_wide                     =  0;
 
 static int                     default_interval                = 100000;
 
-static u64                     count_filter                    =  5;
+static int                     count_filter                    =  5;
 static int                     print_entries                   = 15;
 
 static int                     target_pid                      = -1;
+static int                     inherit                         =  0;
 static int                     profile_cpu                     = -1;
 static int                     nr_cpus                         =  0;
 static unsigned int            realtime_prio                   =  0;
@@ -66,15 +69,29 @@ static unsigned int         page_size;
 static unsigned int            mmap_pages                      = 16;
 static int                     freq                            =  0;
 static int                     verbose                         =  0;
-
-static char                    *sym_filter;
-static unsigned long           filter_start;
-static unsigned long           filter_end;
+static char                    *vmlinux                        =  NULL;
 
 static int                     delay_secs                      =  2;
 static int                     zero;
 static int                     dump_symtab;
 
+/*
+ * Source
+ */
+
+struct source_line {
+       u64                     eip;
+       unsigned long           count[MAX_COUNTERS];
+       char                    *line;
+       struct source_line      *next;
+};
+
+static char                    *sym_filter                     =  NULL;
+struct sym_entry               *sym_filter_entry               =  NULL;
+static int                     sym_pcnt_filter                 =  5;
+static int                     sym_counter                     =  0;
+static int                     display_weighted                = -1;
+
 /*
  * Symbols
  */
@@ -89,9 +106,237 @@ struct sym_entry {
        unsigned long           snap_count;
        double                  weight;
        int                     skip;
+       struct source_line      *source;
+       struct source_line      *lines;
+       struct source_line      **lines_tail;
+       pthread_mutex_t         source_lock;
 };
 
-struct sym_entry               *sym_filter_entry;
+/*
+ * Source functions
+ */
+
+static void parse_source(struct sym_entry *syme)
+{
+       struct symbol *sym;
+       struct module *module;
+       struct section *section = NULL;
+       FILE *file;
+       char command[PATH_MAX*2], *path = vmlinux;
+       u64 start, end, len;
+
+       if (!syme)
+               return;
+
+       if (syme->lines) {
+               pthread_mutex_lock(&syme->source_lock);
+               goto out_assign;
+       }
+
+       sym = (struct symbol *)(syme + 1);
+       module = sym->module;
+
+       if (module)
+               path = module->path;
+       if (!path)
+               return;
+
+       start = sym->obj_start;
+       if (!start)
+               start = sym->start;
+
+       if (module) {
+               section = module->sections->find_section(module->sections, ".text");
+               if (section)
+                       start -= section->vma;
+       }
+
+       end = start + sym->end - sym->start + 1;
+       len = sym->end - sym->start;
+
+       sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", start, end, path);
+
+       file = popen(command, "r");
+       if (!file)
+               return;
+
+       pthread_mutex_lock(&syme->source_lock);
+       syme->lines_tail = &syme->lines;
+       while (!feof(file)) {
+               struct source_line *src;
+               size_t dummy = 0;
+               char *c;
+
+               src = malloc(sizeof(struct source_line));
+               assert(src != NULL);
+               memset(src, 0, sizeof(struct source_line));
+
+               if (getline(&src->line, &dummy, file) < 0)
+                       break;
+               if (!src->line)
+                       break;
+
+               c = strchr(src->line, '\n');
+               if (c)
+                       *c = 0;
+
+               src->next = NULL;
+               *syme->lines_tail = src;
+               syme->lines_tail = &src->next;
+
+               if (strlen(src->line)>8 && src->line[8] == ':') {
+                       src->eip = strtoull(src->line, NULL, 16);
+                       if (section)
+                               src->eip += section->vma;
+               }
+               if (strlen(src->line)>8 && src->line[16] == ':') {
+                       src->eip = strtoull(src->line, NULL, 16);
+                       if (section)
+                               src->eip += section->vma;
+               }
+       }
+       pclose(file);
+out_assign:
+       sym_filter_entry = syme;
+       pthread_mutex_unlock(&syme->source_lock);
+}
+
+static void __zero_source_counters(struct sym_entry *syme)
+{
+       int i;
+       struct source_line *line;
+
+       line = syme->lines;
+       while (line) {
+               for (i = 0; i < nr_counters; i++)
+                       line->count[i] = 0;
+               line = line->next;
+       }
+}
+
+static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
+{
+       struct source_line *line;
+
+       if (syme != sym_filter_entry)
+               return;
+
+       if (pthread_mutex_trylock(&syme->source_lock))
+               return;
+
+       if (!syme->source)
+               goto out_unlock;
+
+       for (line = syme->lines; line; line = line->next) {
+               if (line->eip == ip) {
+                       line->count[counter]++;
+                       break;
+               }
+               if (line->eip > ip)
+                       break;
+       }
+out_unlock:
+       pthread_mutex_unlock(&syme->source_lock);
+}
+
+static void lookup_sym_source(struct sym_entry *syme)
+{
+       struct symbol *symbol = (struct symbol *)(syme + 1);
+       struct source_line *line;
+       char pattern[PATH_MAX];
+       char *idx;
+
+       sprintf(pattern, "<%s>:", symbol->name);
+
+       if (symbol->module) {
+               idx = strstr(pattern, "\t");
+               if (idx)
+                       *idx = 0;
+       }
+
+       pthread_mutex_lock(&syme->source_lock);
+       for (line = syme->lines; line; line = line->next) {
+               if (strstr(line->line, pattern)) {
+                       syme->source = line;
+                       break;
+               }
+       }
+       pthread_mutex_unlock(&syme->source_lock);
+}
+
+static void show_lines(struct source_line *queue, int count, int total)
+{
+       int i;
+       struct source_line *line;
+
+       line = queue;
+       for (i = 0; i < count; i++) {
+               float pcnt = 100.0*(float)line->count[sym_counter]/(float)total;
+
+               printf("%8li %4.1f%%\t%s\n", line->count[sym_counter], pcnt, line->line);
+               line = line->next;
+       }
+}
+
+#define TRACE_COUNT     3
+
+static void show_details(struct sym_entry *syme)
+{
+       struct symbol *symbol;
+       struct source_line *line;
+       struct source_line *line_queue = NULL;
+       int displayed = 0;
+       int line_queue_count = 0, total = 0, more = 0;
+
+       if (!syme)
+               return;
+
+       if (!syme->source)
+               lookup_sym_source(syme);
+
+       if (!syme->source)
+               return;
+
+       symbol = (struct symbol *)(syme + 1);
+       printf("Showing %s for %s\n", event_name(sym_counter), symbol->name);
+       printf("  Events  Pcnt (>=%d%%)\n", sym_pcnt_filter);
+
+       pthread_mutex_lock(&syme->source_lock);
+       line = syme->source;
+       while (line) {
+               total += line->count[sym_counter];
+               line = line->next;
+       }
+
+       line = syme->source;
+       while (line) {
+               float pcnt = 0.0;
+
+               if (!line_queue_count)
+                       line_queue = line;
+               line_queue_count++;
+
+               if (line->count[sym_counter])
+                       pcnt = 100.0 * line->count[sym_counter] / (float)total;
+               if (pcnt >= (float)sym_pcnt_filter) {
+                       if (displayed <= print_entries)
+                               show_lines(line_queue, line_queue_count, total);
+                       else more++;
+                       displayed += line_queue_count;
+                       line_queue_count = 0;
+                       line_queue = NULL;
+               } else if (line_queue_count > TRACE_COUNT) {
+                       line_queue = line_queue->next;
+                       line_queue_count--;
+               }
+
+               line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8;
+               line = line->next;
+       }
+       pthread_mutex_unlock(&syme->source_lock);
+       if (more)
+               printf("%d lines not displayed, maybe increase display entries [e]\n", more);
+}
 
 struct dso                     *kernel_dso;
 
@@ -110,6 +355,9 @@ static double sym_weight(const struct sym_entry *sym)
        double weight = sym->snap_count;
        int counter;
 
+       if (!display_weighted)
+               return weight;
+
        for (counter = 1; counter < nr_counters-1; counter++)
                weight *= sym->count[counter];
 
@@ -157,7 +405,7 @@ static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
 static void print_sym_table(void)
 {
        int printed = 0, j;
-       int counter;
+       int counter, snap = !display_weighted ? sym_counter : 0;
        float samples_per_sec = samples/delay_secs;
        float ksamples_per_sec = (samples-userspace_samples)/delay_secs;
        float sum_ksamples = 0.0;
@@ -173,7 +421,7 @@ static void print_sym_table(void)
        pthread_mutex_unlock(&active_symbols_lock);
 
        list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
-               syme->snap_count = syme->count[0];
+               syme->snap_count = syme->count[snap];
                if (syme->snap_count != 0) {
                        syme->weight = sym_weight(syme);
                        rb_insert_active_sym(&tmp, syme);
@@ -193,7 +441,7 @@ static void print_sym_table(void)
                samples_per_sec,
                100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec)));
 
-       if (nr_counters == 1) {
+       if (nr_counters == 1 || !display_weighted) {
                printf("%Ld", (u64)attrs[0].sample_period);
                if (freq)
                        printf("Hz ");
@@ -201,7 +449,9 @@ static void print_sym_table(void)
                        printf(" ");
        }
 
-       for (counter = 0; counter < nr_counters; counter++) {
+       if (!display_weighted)
+               printf("%s", event_name(sym_counter));
+       else for (counter = 0; counter < nr_counters; counter++) {
                if (counter)
                        printf("/");
 
@@ -226,6 +476,11 @@ static void print_sym_table(void)
 
        printf("------------------------------------------------------------------------------\n\n");
 
+       if (sym_filter_entry) {
+               show_details(sym_filter_entry);
+               return;
+       }
+
        if (nr_counters == 1)
                printf("             samples    pcnt");
        else
@@ -238,59 +493,300 @@ static void print_sym_table(void)
        for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
                struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node);
                struct symbol *sym = (struct symbol *)(syme + 1);
-               char *color = PERF_COLOR_NORMAL;
                double pcnt;
 
-               if (++printed > print_entries || syme->snap_count < count_filter)
+               if (++printed > print_entries || (int)syme->snap_count < count_filter)
                        continue;
 
                pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
                                         sum_ksamples));
 
-               /*
-                * We color high-overhead entries in red, mid-overhead
-                * entries in green - and keep the low overhead places
-                * normal:
-                */
-               if (pcnt >= 5.0) {
-                       color = PERF_COLOR_RED;
-               } else {
-                       if (pcnt >= 0.5)
-                               color = PERF_COLOR_GREEN;
-               }
-
-               if (nr_counters == 1)
+               if (nr_counters == 1 || !display_weighted)
                        printf("%20.2f - ", syme->weight);
                else
                        printf("%9.1f %10ld - ", syme->weight, syme->snap_count);
 
-               color_fprintf(stdout, color, "%4.1f%%", pcnt);
-               printf(" - %016llx : %s\n", sym->start, sym->name);
+               percent_color_fprintf(stdout, "%4.1f%%", pcnt);
+               printf(" - %016llx : %s", sym->start, sym->name);
+               if (sym->module)
+                       printf("\t[%s]", sym->module->name);
+               printf("\n");
+       }
+}
+
+static void prompt_integer(int *target, const char *msg)
+{
+       char *buf = malloc(0), *p;
+       size_t dummy = 0;
+       int tmp;
+
+       fprintf(stdout, "\n%s: ", msg);
+       if (getline(&buf, &dummy, stdin) < 0)
+               return;
+
+       p = strchr(buf, '\n');
+       if (p)
+               *p = 0;
+
+       p = buf;
+       while(*p) {
+               if (!isdigit(*p))
+                       goto out_free;
+               p++;
+       }
+       tmp = strtoul(buf, NULL, 10);
+       *target = tmp;
+out_free:
+       free(buf);
+}
+
+static void prompt_percent(int *target, const char *msg)
+{
+       int tmp = 0;
+
+       prompt_integer(&tmp, msg);
+       if (tmp >= 0 && tmp <= 100)
+               *target = tmp;
+}
+
+static void prompt_symbol(struct sym_entry **target, const char *msg)
+{
+       char *buf = malloc(0), *p;
+       struct sym_entry *syme = *target, *n, *found = NULL;
+       size_t dummy = 0;
+
+       /* zero counters of active symbol */
+       if (syme) {
+               pthread_mutex_lock(&syme->source_lock);
+               __zero_source_counters(syme);
+               *target = NULL;
+               pthread_mutex_unlock(&syme->source_lock);
+       }
+
+       fprintf(stdout, "\n%s: ", msg);
+       if (getline(&buf, &dummy, stdin) < 0)
+               goto out_free;
+
+       p = strchr(buf, '\n');
+       if (p)
+               *p = 0;
+
+       pthread_mutex_lock(&active_symbols_lock);
+       syme = list_entry(active_symbols.next, struct sym_entry, node);
+       pthread_mutex_unlock(&active_symbols_lock);
+
+       list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
+               struct symbol *sym = (struct symbol *)(syme + 1);
+
+               if (!strcmp(buf, sym->name)) {
+                       found = syme;
+                       break;
+               }
        }
+
+       if (!found) {
+               fprintf(stderr, "Sorry, %s is not active.\n", sym_filter);
+               sleep(1);
+               return;
+       } else
+               parse_source(found);
+
+out_free:
+       free(buf);
 }
 
-static void *display_thread(void *arg)
+static void print_mapped_keys(void)
+{
+       char *name = NULL;
+
+       if (sym_filter_entry) {
+               struct symbol *sym = (struct symbol *)(sym_filter_entry+1);
+               name = sym->name;
+       }
+
+       fprintf(stdout, "\nMapped keys:\n");
+       fprintf(stdout, "\t[d]     display refresh delay.             \t(%d)\n", delay_secs);
+       fprintf(stdout, "\t[e]     display entries (lines).           \t(%d)\n", print_entries);
+
+       if (nr_counters > 1)
+               fprintf(stdout, "\t[E]     active event counter.              \t(%s)\n", event_name(sym_counter));
+
+       fprintf(stdout, "\t[f]     profile display filter (count).    \t(%d)\n", count_filter);
+
+       if (vmlinux) {
+               fprintf(stdout, "\t[F]     annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter);
+               fprintf(stdout, "\t[s]     annotate symbol.                   \t(%s)\n", name?: "NULL");
+               fprintf(stdout, "\t[S]     stop annotation.\n");
+       }
+
+       if (nr_counters > 1)
+               fprintf(stdout, "\t[w]     toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0);
+
+       fprintf(stdout, "\t[z]     toggle sample zeroing.             \t(%d)\n", zero ? 1 : 0);
+       fprintf(stdout, "\t[qQ]    quit.\n");
+}
+
+static int key_mapped(int c)
+{
+       switch (c) {
+               case 'd':
+               case 'e':
+               case 'f':
+               case 'z':
+               case 'q':
+               case 'Q':
+                       return 1;
+               case 'E':
+               case 'w':
+                       return nr_counters > 1 ? 1 : 0;
+               case 'F':
+               case 's':
+               case 'S':
+                       return vmlinux ? 1 : 0;
+       }
+
+       return 0;
+}
+
+static void handle_keypress(int c)
+{
+       if (!key_mapped(c)) {
+               struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
+               struct termios tc, save;
+
+               print_mapped_keys();
+               fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
+               fflush(stdout);
+
+               tcgetattr(0, &save);
+               tc = save;
+               tc.c_lflag &= ~(ICANON | ECHO);
+               tc.c_cc[VMIN] = 0;
+               tc.c_cc[VTIME] = 0;
+               tcsetattr(0, TCSANOW, &tc);
+
+               poll(&stdin_poll, 1, -1);
+               c = getc(stdin);
+
+               tcsetattr(0, TCSAFLUSH, &save);
+               if (!key_mapped(c))
+                       return;
+       }
+
+       switch (c) {
+               case 'd':
+                       prompt_integer(&delay_secs, "Enter display delay");
+                       break;
+               case 'e':
+                       prompt_integer(&print_entries, "Enter display entries (lines)");
+                       break;
+               case 'E':
+                       if (nr_counters > 1) {
+                               int i;
+
+                               fprintf(stderr, "\nAvailable events:");
+                               for (i = 0; i < nr_counters; i++)
+                                       fprintf(stderr, "\n\t%d %s", i, event_name(i));
+
+                               prompt_integer(&sym_counter, "Enter details event counter");
+
+                               if (sym_counter >= nr_counters) {
+                                       fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(0));
+                                       sym_counter = 0;
+                                       sleep(1);
+                               }
+                       } else sym_counter = 0;
+                       break;
+               case 'f':
+                       prompt_integer(&count_filter, "Enter display event count filter");
+                       break;
+               case 'F':
+                       prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)");
+                       break;
+               case 'q':
+               case 'Q':
+                       printf("exiting.\n");
+                       exit(0);
+               case 's':
+                       prompt_symbol(&sym_filter_entry, "Enter details symbol");
+                       break;
+               case 'S':
+                       if (!sym_filter_entry)
+                               break;
+                       else {
+                               struct sym_entry *syme = sym_filter_entry;
+
+                               pthread_mutex_lock(&syme->source_lock);
+                               sym_filter_entry = NULL;
+                               __zero_source_counters(syme);
+                               pthread_mutex_unlock(&syme->source_lock);
+                       }
+                       break;
+               case 'w':
+                       display_weighted = ~display_weighted;
+                       break;
+               case 'z':
+                       zero = ~zero;
+                       break;
+       }
+}
+
+static void *display_thread(void *arg __used)
 {
        struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
-       int delay_msecs = delay_secs * 1000;
+       struct termios tc, save;
+       int delay_msecs, c;
 
-       printf("PerfTop refresh period: %d seconds\n", delay_secs);
+       tcgetattr(0, &save);
+       tc = save;
+       tc.c_lflag &= ~(ICANON | ECHO);
+       tc.c_cc[VMIN] = 0;
+       tc.c_cc[VTIME] = 0;
+
+repeat:
+       delay_msecs = delay_secs * 1000;
+       tcsetattr(0, TCSANOW, &tc);
+       /* trash return*/
+       getc(stdin);
 
        do {
                print_sym_table();
        } while (!poll(&stdin_poll, 1, delay_msecs) == 1);
 
-       printf("key pressed - exiting.\n");
-       exit(0);
+       c = getc(stdin);
+       tcsetattr(0, TCSAFLUSH, &save);
+
+       handle_keypress(c);
+       goto repeat;
 
        return NULL;
 }
 
+/* Tag samples to be skipped. */
+static const char *skip_symbols[] = {
+       "default_idle",
+       "cpu_idle",
+       "enter_idle",
+       "exit_idle",
+       "mwait_idle",
+       "mwait_idle_with_hints",
+       "ppc64_runlatch_off",
+       "pseries_dedicated_idle_sleep",
+       NULL
+};
+
 static int symbol_filter(struct dso *self, struct symbol *sym)
 {
-       static int filter_match;
        struct sym_entry *syme;
        const char *name = sym->name;
+       int i;
+
+       /*
+        * ppc64 uses function descriptors and appends a '.' to the
+        * start of every instruction address. Remove it.
+        */
+       if (name[0] == '.')
+               name++;
 
        if (!strcmp(name, "_text") ||
            !strcmp(name, "_etext") ||
@@ -302,37 +798,17 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
                return 1;
 
        syme = dso__sym_priv(self, sym);
-       /* Tag samples to be skipped. */
-       if (!strcmp("default_idle", name) ||
-           !strcmp("cpu_idle", name) ||
-           !strcmp("enter_idle", name) ||
-           !strcmp("exit_idle", name) ||
-           !strcmp("mwait_idle", name))
-               syme->skip = 1;
-
-       if (filter_match == 1) {
-               filter_end = sym->start;
-               filter_match = -1;
-               if (filter_end - filter_start > 10000) {
-                       fprintf(stderr,
-                               "hm, too large filter symbol <%s> - skipping.\n",
-                               sym_filter);
-                       fprintf(stderr, "symbol filter start: %016lx\n",
-                               filter_start);
-                       fprintf(stderr, "                end: %016lx\n",
-                               filter_end);
-                       filter_end = filter_start = 0;
-                       sym_filter = NULL;
-                       sleep(1);
+       pthread_mutex_init(&syme->source_lock, NULL);
+       if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter))
+               sym_filter_entry = syme;
+
+       for (i = 0; skip_symbols[i]; i++) {
+               if (!strcmp(skip_symbols[i], name)) {
+                       syme->skip = 1;
+                       break;
                }
        }
 
-       if (filter_match == 0 && sym_filter && !strcmp(name, sym_filter)) {
-               filter_match = 1;
-               filter_start = sym->start;
-       }
-
-
        return 0;
 }
 
@@ -340,12 +816,13 @@ static int parse_symbols(void)
 {
        struct rb_node *node;
        struct symbol  *sym;
+       int modules = vmlinux ? 1 : 0;
 
        kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry));
        if (kernel_dso == NULL)
                return -1;
 
-       if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1) != 0)
+       if (dso__load_kernel(kernel_dso, vmlinux, symbol_filter, verbose, modules) <= 0)
                goto out_delete_dso;
 
        node = rb_first(&kernel_dso->syms);
@@ -367,8 +844,6 @@ out_delete_dso:
        return -1;
 }
 
-#define TRACE_COUNT     3
-
 /*
  * Binary search in the histogram table and record the hit:
  */
@@ -381,6 +856,7 @@ static void record_ip(u64 ip, int counter)
 
                if (!syme->skip) {
                        syme->count[counter]++;
+                       record_precise_ip(syme, counter, ip);
                        pthread_mutex_lock(&active_symbols_lock);
                        if (list_empty(&syme->node) || !syme->node.next)
                                __list_insert_active_sym(syme);
@@ -392,11 +868,11 @@ static void record_ip(u64 ip, int counter)
        samples--;
 }
 
-static void process_event(u64 ip, int counter)
+static void process_event(u64 ip, int counter, int user)
 {
        samples++;
 
-       if (ip < min_ip || ip > max_ip) {
+       if (user) {
                userspace_samples++;
                return;
        }
@@ -407,7 +883,7 @@ static void process_event(u64 ip, int counter)
 struct mmap_data {
        int                     counter;
        void                    *base;
-       unsigned int            mask;
+       int                     mask;
        unsigned int            prev;
 };
 
@@ -509,9 +985,10 @@ static void mmap_read_counter(struct mmap_data *md)
 
                old += size;
 
-               if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) {
-                       if (event->header.type & PERF_SAMPLE_IP)
-                               process_event(event->ip.ip, md->counter);
+               if (event->header.type == PERF_EVENT_SAMPLE) {
+                       int user =
+       (event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK) == PERF_EVENT_MISC_USER;
+                       process_event(event->ip.ip, md->counter, user);
                }
        }
 
@@ -537,7 +1014,7 @@ int group_fd;
 static void start_counter(int i, int counter)
 {
        struct perf_counter_attr *attr;
-       unsigned int cpu;
+       int cpu;
 
        cpu = profile_cpu;
        if (target_pid == -1 && profile_cpu == -1)
@@ -547,6 +1024,7 @@ static void start_counter(int i, int counter)
 
        attr->sample_type       = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
        attr->freq              = freq;
+       attr->inherit           = (cpu < 0) && inherit;
 
 try_again:
        fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0);
@@ -660,6 +1138,7 @@ static const struct option options[] = {
                            "system-wide collection from all CPUs"),
        OPT_INTEGER('C', "CPU", &profile_cpu,
                    "CPU to profile on"),
+       OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
        OPT_INTEGER('m', "mmap-pages", &mmap_pages,
                    "number of mmap data pages"),
        OPT_INTEGER('r', "realtime", &realtime_prio,
@@ -672,9 +1151,11 @@ static const struct option options[] = {
                    "only display functions with more events than this"),
        OPT_BOOLEAN('g', "group", &group,
                            "put the counters into a counter group"),
-       OPT_STRING('s', "sym-filter", &sym_filter, "pattern",
-                   "only display symbols matchig this pattern"),
-       OPT_BOOLEAN('z', "zero", &group,
+       OPT_BOOLEAN('i', "inherit", &inherit,
+                   "child tasks inherit counters"),
+       OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name",
+                   "symbol to annotate - requires -k option"),
+       OPT_BOOLEAN('z', "zero", &zero,
                    "zero history across updates"),
        OPT_INTEGER('F', "freq", &freq,
                    "profile at this frequency"),
@@ -685,10 +1166,12 @@ static const struct option options[] = {
        OPT_END()
 };
 
-int cmd_top(int argc, const char **argv, const char *prefix)
+int cmd_top(int argc, const char **argv, const char *prefix __used)
 {
        int counter;
 
+       symbol__init();
+
        page_size = sysconf(_SC_PAGE_SIZE);
 
        argc = parse_options(argc, argv, options, top_usage, 0);
@@ -714,6 +1197,7 @@ int cmd_top(int argc, const char **argv, const char *prefix)
                delay_secs = 1;
 
        parse_symbols();
+       parse_source(sym_filter_entry);
 
        /*
         * Fill in the ones not specifically initialized via -c:
index 4eb725933703b6e8c41c558e46f11d705cc9d41f..31982ad064b4781c7b78dd5f9ef32f3f29dd3523 100644 (file)
@@ -12,6 +12,8 @@
 #include "util/cache.h"
 #include "util/quote.h"
 #include "util/run-command.h"
+#include "util/parse-events.h"
+#include "util/string.h"
 
 const char perf_usage_string[] =
        "perf [--version] [--help] COMMAND [ARGS]";
@@ -25,6 +27,8 @@ struct pager_config {
        int val;
 };
 
+static char debugfs_mntpt[MAXPATHLEN];
+
 static int pager_command_config(const char *var, const char *value, void *data)
 {
        struct pager_config *c = data;
@@ -56,6 +60,15 @@ static void commit_pager_choice(void) {
        }
 }
 
+static void set_debugfs_path(void)
+{
+       char *path;
+
+       path = getenv(PERF_DEBUGFS_ENVIRONMENT);
+       snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt,
+                "tracing/events");
+}
+
 static int handle_options(const char*** argv, int* argc, int* envchanged)
 {
        int handled = 0;
@@ -122,6 +135,22 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
                        setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
                        if (envchanged)
                                *envchanged = 1;
+               } else if (!strcmp(cmd, "--debugfs-dir")) {
+                       if (*argc < 2) {
+                               fprintf(stderr, "No directory given for --debugfs-dir.\n");
+                               usage(perf_usage_string);
+                       }
+                       strncpy(debugfs_mntpt, (*argv)[1], MAXPATHLEN);
+                       debugfs_mntpt[MAXPATHLEN - 1] = '\0';
+                       if (envchanged)
+                               *envchanged = 1;
+                       (*argv)++;
+                       (*argc)--;
+               } else if (!prefixcmp(cmd, "--debugfs-dir=")) {
+                       strncpy(debugfs_mntpt, cmd + 14, MAXPATHLEN);
+                       debugfs_mntpt[MAXPATHLEN - 1] = '\0';
+                       if (envchanged)
+                               *envchanged = 1;
                } else {
                        fprintf(stderr, "Unknown option: %s\n", cmd);
                        usage(perf_usage_string);
@@ -228,9 +257,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
        if (use_pager == -1 && p->option & USE_PAGER)
                use_pager = 1;
        commit_pager_choice();
-
-       if (p->option & NEED_WORK_TREE)
-               /* setup_work_tree() */;
+       set_debugfs_path();
 
        status = p->fn(argc, argv, prefix);
        if (status)
@@ -266,7 +293,7 @@ static void handle_internal_command(int argc, const char **argv)
                { "annotate", cmd_annotate, 0 },
                { "version", cmd_version, 0 },
        };
-       int i;
+       unsigned int i;
        static const char ext[] = STRIP_EXTENSION;
 
        if (sizeof(ext) > 1) {
@@ -349,6 +376,49 @@ static int run_argv(int *argcp, const char ***argv)
        return done_alias;
 }
 
+/* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */
+static void get_debugfs_mntpt(void)
+{
+       FILE *file;
+       char fs_type[100];
+       char debugfs[MAXPATHLEN];
+
+       /*
+        * try the standard location
+        */
+       if (valid_debugfs_mount("/sys/kernel/debug/") == 0) {
+               strcpy(debugfs_mntpt, "/sys/kernel/debug/");
+               return;
+       }
+
+       /*
+        * try the sane location
+        */
+       if (valid_debugfs_mount("/debug/") == 0) {
+               strcpy(debugfs_mntpt, "/debug/");
+               return;
+       }
+
+       /*
+        * give up and parse /proc/mounts
+        */
+       file = fopen("/proc/mounts", "r");
+       if (file == NULL)
+               return;
+
+       while (fscanf(file, "%*s %"
+                     STR(MAXPATHLEN)
+                     "s %99s %*s %*d %*d\n",
+                     debugfs, fs_type) == 2) {
+               if (strcmp(fs_type, "debugfs") == 0)
+                       break;
+       }
+       fclose(file);
+       if (strcmp(fs_type, "debugfs") == 0) {
+               strncpy(debugfs_mntpt, debugfs, MAXPATHLEN);
+               debugfs_mntpt[MAXPATHLEN - 1] = '\0';
+       }
+}
 
 int main(int argc, const char **argv)
 {
@@ -357,7 +427,8 @@ int main(int argc, const char **argv)
        cmd = perf_extract_argv0_path(argv[0]);
        if (!cmd)
                cmd = "perf-help";
-
+       /* get debugfs mount point from /proc/mounts */
+       get_debugfs_mntpt();
        /*
         * "perf-xxxx" is the same as "perf xxxx", but we obviously:
         *
@@ -380,6 +451,7 @@ int main(int argc, const char **argv)
        argc--;
        handle_options(&argv, &argc, NULL);
        commit_pager_choice();
+       set_debugfs_path();
        if (argc > 0) {
                if (!prefixcmp(argv[0], "--"))
                        argv[0] += 2;
index ceb68aa51f7f5eaeaa109a250ac0ceb9ddc68665..e5148e2b6134242f3b42c3dd59fafd54a7acb60f 100644 (file)
@@ -1,7 +1,13 @@
 #ifndef _PERF_PERF_H
 #define _PERF_PERF_H
 
-#if defined(__x86_64__) || defined(__i386__)
+#if defined(__i386__)
+#include "../../arch/x86/include/asm/unistd.h"
+#define rmb()          asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
+#define cpu_relax()    asm volatile("rep; nop" ::: "memory");
+#endif
+
+#if defined(__x86_64__)
 #include "../../arch/x86/include/asm/unistd.h"
 #define rmb()          asm volatile("lfence" ::: "memory")
 #define cpu_relax()    asm volatile("rep; nop" ::: "memory");
 #define cpu_relax()    asm volatile("" ::: "memory");
 #endif
 
+#ifdef __sh__
+#include "../../arch/sh/include/asm/unistd.h"
+#if defined(__SH4A__) || defined(__SH5__)
+# define rmb()         asm volatile("synco" ::: "memory")
+#else
+# define rmb()         asm volatile("" ::: "memory")
+#endif
+#define cpu_relax()    asm volatile("" ::: "memory")
+#endif
+
+#ifdef __hppa__
+#include "../../arch/parisc/include/asm/unistd.h"
+#define rmb()          asm volatile("" ::: "memory")
+#define cpu_relax()    asm volatile("" ::: "memory");
+#endif
+
 #include <time.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/syscall.h>
 
 #include "../../include/linux/perf_counter.h"
-#include "types.h"
+#include "util/types.h"
 
 /*
  * prctl(PR_TASK_PERF_COUNTERS_DISABLE) will (cheaply) disable all
@@ -52,6 +74,8 @@ static inline unsigned long long rdclock(void)
 #define __user
 #define asmlinkage
 
+#define __used         __attribute__((__unused__))
+
 #define unlikely(x)    __builtin_expect(!!(x), 0)
 #define min(x, y) ({                           \
        typeof(x) _min1 = (x);                  \
@@ -72,10 +96,9 @@ sys_perf_counter_open(struct perf_counter_attr *attr,
 #define MAX_COUNTERS                   256
 #define MAX_NR_CPUS                    256
 
-struct perf_file_header {
-       u64     version;
-       u64     sample_type;
-       u64     data_size;
+struct ip_callchain {
+       u64 nr;
+       u64 ips[0];
 };
 
 #endif
index 9b3dd2b428df8c4e95ed0dce7e281419744cf14e..b8144e80bb1e5b436d95f1c96757fe34b9451946 100644 (file)
@@ -3,7 +3,7 @@
 static const char *alias_key;
 static char *alias_val;
 
-static int alias_lookup_cb(const char *k, const char *v, void *cb)
+static int alias_lookup_cb(const char *k, const char *v, void *cb __used)
 {
        if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) {
                if (!v)
index 393d6146d13b38743641adb819c2552a56716043..4b50c412b9c574ecafc10c1c4cbaa48d8535194e 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "util.h"
 #include "strbuf.h"
+#include "../perf.h"
 
 #define PERF_DIR_ENVIRONMENT "PERF_DIR"
 #define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE"
@@ -17,6 +18,7 @@
 #define PERFATTRIBUTES_FILE ".perfattributes"
 #define INFOATTRIBUTES_FILE "info/attributes"
 #define ATTRIBUTE_MACRO_PREFIX "[attr]"
+#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
 
 typedef int (*config_fn_t)(const char *, const char *, void *);
 extern int perf_default_config(const char *, const char *, void *);
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
new file mode 100644 (file)
index 0000000..0114734
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2009, Frederic Weisbecker <fweisbec@gmail.com>
+ *
+ * Handle the callchains from the stream in an ad-hoc radix tree and then
+ * sort them in an rbtree.
+ *
+ * Using a radix for code path provides a fast retrieval and factorizes
+ * memory use. Also that lets us use the paths in a hierarchical graph view.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <math.h>
+
+#include "callchain.h"
+
+#define chain_for_each_child(child, parent)    \
+       list_for_each_entry(child, &parent->children, brothers)
+
+static void
+rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
+                   enum chain_mode mode)
+{
+       struct rb_node **p = &root->rb_node;
+       struct rb_node *parent = NULL;
+       struct callchain_node *rnode;
+       u64 chain_cumul = cumul_hits(chain);
+
+       while (*p) {
+               u64 rnode_cumul;
+
+               parent = *p;
+               rnode = rb_entry(parent, struct callchain_node, rb_node);
+               rnode_cumul = cumul_hits(rnode);
+
+               switch (mode) {
+               case CHAIN_FLAT:
+                       if (rnode->hit < chain->hit)
+                               p = &(*p)->rb_left;
+                       else
+                               p = &(*p)->rb_right;
+                       break;
+               case CHAIN_GRAPH_ABS: /* Falldown */
+               case CHAIN_GRAPH_REL:
+                       if (rnode_cumul < chain_cumul)
+                               p = &(*p)->rb_left;
+                       else
+                               p = &(*p)->rb_right;
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       rb_link_node(&chain->rb_node, parent, p);
+       rb_insert_color(&chain->rb_node, root);
+}
+
+static void
+__sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
+                 u64 min_hit)
+{
+       struct callchain_node *child;
+
+       chain_for_each_child(child, node)
+               __sort_chain_flat(rb_root, child, min_hit);
+
+       if (node->hit && node->hit >= min_hit)
+               rb_insert_callchain(rb_root, node, CHAIN_FLAT);
+}
+
+/*
+ * Once we get every callchains from the stream, we can now
+ * sort them by hit
+ */
+static void
+sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
+               u64 min_hit, struct callchain_param *param __used)
+{
+       __sort_chain_flat(rb_root, node, min_hit);
+}
+
+static void __sort_chain_graph_abs(struct callchain_node *node,
+                                  u64 min_hit)
+{
+       struct callchain_node *child;
+
+       node->rb_root = RB_ROOT;
+
+       chain_for_each_child(child, node) {
+               __sort_chain_graph_abs(child, min_hit);
+               if (cumul_hits(child) >= min_hit)
+                       rb_insert_callchain(&node->rb_root, child,
+                                           CHAIN_GRAPH_ABS);
+       }
+}
+
+static void
+sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_node *chain_root,
+                    u64 min_hit, struct callchain_param *param __used)
+{
+       __sort_chain_graph_abs(chain_root, min_hit);
+       rb_root->rb_node = chain_root->rb_root.rb_node;
+}
+
+static void __sort_chain_graph_rel(struct callchain_node *node,
+                                  double min_percent)
+{
+       struct callchain_node *child;
+       u64 min_hit;
+
+       node->rb_root = RB_ROOT;
+       min_hit = ceil(node->children_hit * min_percent);
+
+       chain_for_each_child(child, node) {
+               __sort_chain_graph_rel(child, min_percent);
+               if (cumul_hits(child) >= min_hit)
+                       rb_insert_callchain(&node->rb_root, child,
+                                           CHAIN_GRAPH_REL);
+       }
+}
+
+static void
+sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_node *chain_root,
+                    u64 min_hit __used, struct callchain_param *param)
+{
+       __sort_chain_graph_rel(chain_root, param->min_percent / 100.0);
+       rb_root->rb_node = chain_root->rb_root.rb_node;
+}
+
+int register_callchain_param(struct callchain_param *param)
+{
+       switch (param->mode) {
+       case CHAIN_GRAPH_ABS:
+               param->sort = sort_chain_graph_abs;
+               break;
+       case CHAIN_GRAPH_REL:
+               param->sort = sort_chain_graph_rel;
+               break;
+       case CHAIN_FLAT:
+               param->sort = sort_chain_flat;
+               break;
+       default:
+               return -1;
+       }
+       return 0;
+}
+
+/*
+ * Create a child for a parent. If inherit_children, then the new child
+ * will become the new parent of it's parent children
+ */
+static struct callchain_node *
+create_child(struct callchain_node *parent, bool inherit_children)
+{
+       struct callchain_node *new;
+
+       new = malloc(sizeof(*new));
+       if (!new) {
+               perror("not enough memory to create child for code path tree");
+               return NULL;
+       }
+       new->parent = parent;
+       INIT_LIST_HEAD(&new->children);
+       INIT_LIST_HEAD(&new->val);
+
+       if (inherit_children) {
+               struct callchain_node *next;
+
+               list_splice(&parent->children, &new->children);
+               INIT_LIST_HEAD(&parent->children);
+
+               chain_for_each_child(next, new)
+                       next->parent = new;
+       }
+       list_add_tail(&new->brothers, &parent->children);
+
+       return new;
+}
+
+/*
+ * Fill the node with callchain values
+ */
+static void
+fill_node(struct callchain_node *node, struct ip_callchain *chain,
+         int start, struct symbol **syms)
+{
+       unsigned int i;
+
+       for (i = start; i < chain->nr; i++) {
+               struct callchain_list *call;
+
+               call = malloc(sizeof(*call));
+               if (!call) {
+                       perror("not enough memory for the code path tree");
+                       return;
+               }
+               call->ip = chain->ips[i];
+               call->sym = syms[i];
+               list_add_tail(&call->list, &node->val);
+       }
+       node->val_nr = chain->nr - start;
+       if (!node->val_nr)
+               printf("Warning: empty node in callchain tree\n");
+}
+
+static void
+add_child(struct callchain_node *parent, struct ip_callchain *chain,
+         int start, struct symbol **syms)
+{
+       struct callchain_node *new;
+
+       new = create_child(parent, false);
+       fill_node(new, chain, start, syms);
+
+       new->children_hit = 0;
+       new->hit = 1;
+}
+
+/*
+ * Split the parent in two parts (a new child is created) and
+ * give a part of its callchain to the created child.
+ * Then create another child to host the given callchain of new branch
+ */
+static void
+split_add_child(struct callchain_node *parent, struct ip_callchain *chain,
+               struct callchain_list *to_split, int idx_parents, int idx_local,
+               struct symbol **syms)
+{
+       struct callchain_node *new;
+       struct list_head *old_tail;
+       unsigned int idx_total = idx_parents + idx_local;
+
+       /* split */
+       new = create_child(parent, true);
+
+       /* split the callchain and move a part to the new child */
+       old_tail = parent->val.prev;
+       list_del_range(&to_split->list, old_tail);
+       new->val.next = &to_split->list;
+       new->val.prev = old_tail;
+       to_split->list.prev = &new->val;
+       old_tail->next = &new->val;
+
+       /* split the hits */
+       new->hit = parent->hit;
+       new->children_hit = parent->children_hit;
+       parent->children_hit = cumul_hits(new);
+       new->val_nr = parent->val_nr - idx_local;
+       parent->val_nr = idx_local;
+
+       /* create a new child for the new branch if any */
+       if (idx_total < chain->nr) {
+               parent->hit = 0;
+               add_child(parent, chain, idx_total, syms);
+               parent->children_hit++;
+       } else {
+               parent->hit = 1;
+       }
+}
+
+static int
+__append_chain(struct callchain_node *root, struct ip_callchain *chain,
+              unsigned int start, struct symbol **syms);
+
+static void
+__append_chain_children(struct callchain_node *root, struct ip_callchain *chain,
+                       struct symbol **syms, unsigned int start)
+{
+       struct callchain_node *rnode;
+
+       /* lookup in childrens */
+       chain_for_each_child(rnode, root) {
+               unsigned int ret = __append_chain(rnode, chain, start, syms);
+
+               if (!ret)
+                       goto inc_children_hit;
+       }
+       /* nothing in children, add to the current node */
+       add_child(root, chain, start, syms);
+
+inc_children_hit:
+       root->children_hit++;
+}
+
+static int
+__append_chain(struct callchain_node *root, struct ip_callchain *chain,
+              unsigned int start, struct symbol **syms)
+{
+       struct callchain_list *cnode;
+       unsigned int i = start;
+       bool found = false;
+
+       /*
+        * Lookup in the current node
+        * If we have a symbol, then compare the start to match
+        * anywhere inside a function.
+        */
+       list_for_each_entry(cnode, &root->val, list) {
+               if (i == chain->nr)
+                       break;
+               if (cnode->sym && syms[i]) {
+                       if (cnode->sym->start != syms[i]->start)
+                               break;
+               } else if (cnode->ip != chain->ips[i])
+                       break;
+               if (!found)
+                       found = true;
+               i++;
+       }
+
+       /* matches not, relay on the parent */
+       if (!found)
+               return -1;
+
+       /* we match only a part of the node. Split it and add the new chain */
+       if (i - start < root->val_nr) {
+               split_add_child(root, chain, cnode, start, i - start, syms);
+               return 0;
+       }
+
+       /* we match 100% of the path, increment the hit */
+       if (i - start == root->val_nr && i == chain->nr) {
+               root->hit++;
+               return 0;
+       }
+
+       /* We match the node and still have a part remaining */
+       __append_chain_children(root, chain, syms, i);
+
+       return 0;
+}
+
+void append_chain(struct callchain_node *root, struct ip_callchain *chain,
+                 struct symbol **syms)
+{
+       if (!chain->nr)
+               return;
+       __append_chain_children(root, chain, syms, 0);
+}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
new file mode 100644 (file)
index 0000000..a926ae4
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __PERF_CALLCHAIN_H
+#define __PERF_CALLCHAIN_H
+
+#include "../perf.h"
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include "symbol.h"
+
+enum chain_mode {
+       CHAIN_NONE,
+       CHAIN_FLAT,
+       CHAIN_GRAPH_ABS,
+       CHAIN_GRAPH_REL
+};
+
+struct callchain_node {
+       struct callchain_node   *parent;
+       struct list_head        brothers;
+       struct list_head        children;
+       struct list_head        val;
+       struct rb_node          rb_node; /* to sort nodes in an rbtree */
+       struct rb_root          rb_root; /* sorted tree of children */
+       unsigned int            val_nr;
+       u64                     hit;
+       u64                     children_hit;
+};
+
+struct callchain_param;
+
+typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_node *,
+                                u64, struct callchain_param *);
+
+struct callchain_param {
+       enum chain_mode         mode;
+       double                  min_percent;
+       sort_chain_func_t       sort;
+};
+
+struct callchain_list {
+       u64                     ip;
+       struct symbol           *sym;
+       struct list_head        list;
+};
+
+static inline void callchain_init(struct callchain_node *node)
+{
+       INIT_LIST_HEAD(&node->brothers);
+       INIT_LIST_HEAD(&node->children);
+       INIT_LIST_HEAD(&node->val);
+}
+
+static inline u64 cumul_hits(struct callchain_node *node)
+{
+       return node->hit + node->children_hit;
+}
+
+int register_callchain_param(struct callchain_param *param);
+void append_chain(struct callchain_node *root, struct ip_callchain *chain,
+                 struct symbol **syms);
+#endif
index 9a8c20ccc53e28dd99ab6bd2f27f548fe85532fe..90a044d1fe7dffe526a50d8afdb5ac888ff31209 100644 (file)
@@ -11,7 +11,8 @@ static int parse_color(const char *name, int len)
        };
        char *end;
        int i;
-       for (i = 0; i < ARRAY_SIZE(color_names); i++) {
+
+       for (i = 0; i < (int)ARRAY_SIZE(color_names); i++) {
                const char *str = color_names[i];
                if (!strncasecmp(name, str, len) && !str[len])
                        return i - 1;
@@ -28,7 +29,8 @@ static int parse_attr(const char *name, int len)
        static const char * const attr_names[] = {
                "bold", "dim", "ul", "blink", "reverse"
        };
-       int i;
+       unsigned int i;
+
        for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
                const char *str = attr_names[i];
                if (!strncasecmp(name, str, len) && !str[len])
@@ -222,10 +224,12 @@ int color_fwrite_lines(FILE *fp, const char *color,
 {
        if (!*color)
                return fwrite(buf, count, 1, fp) != 1;
+
        while (count) {
                char *p = memchr(buf, '\n', count);
+
                if (p != buf && (fputs(color, fp) < 0 ||
-                               fwrite(buf, p ? p - buf : count, 1, fp) != 1 ||
+                               fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 ||
                                fputs(PERF_COLOR_RESET, fp) < 0))
                        return -1;
                if (!p)
@@ -238,4 +242,31 @@ int color_fwrite_lines(FILE *fp, const char *color,
        return 0;
 }
 
+char *get_percent_color(double percent)
+{
+       char *color = PERF_COLOR_NORMAL;
 
+       /*
+        * We color high-overhead entries in red, mid-overhead
+        * entries in green - and keep the low overhead places
+        * normal:
+        */
+       if (percent >= MIN_RED)
+               color = PERF_COLOR_RED;
+       else {
+               if (percent > MIN_GREEN)
+                       color = PERF_COLOR_GREEN;
+       }
+       return color;
+}
+
+int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
+{
+       int r;
+       char *color;
+
+       color = get_percent_color(percent);
+       r = color_fprintf(fp, color, fmt, percent);
+
+       return r;
+}
index 5abfd379582b40428f62807b5aefa81a239a49d2..706cec50bd25188d3f123c338e4c22436f859d80 100644 (file)
@@ -15,6 +15,9 @@
 #define PERF_COLOR_CYAN                "\033[36m"
 #define PERF_COLOR_BG_RED      "\033[41m"
 
+#define MIN_GREEN      0.5
+#define MIN_RED                5.0
+
 /*
  * This variable stores the value of color.ui
  */
@@ -32,5 +35,7 @@ void color_parse_mem(const char *value, int len, const char *var, char *dst);
 int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
 int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
 int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
+int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
+char *get_percent_color(double percent);
 
 #endif /* COLOR_H */
index 3dd13faa6a27f9e1378184bd3349c2a3cf51f073..780df541006dd2dae77608ade75ad23069203d5f 100644 (file)
@@ -47,10 +47,12 @@ static int get_next_char(void)
 static char *parse_value(void)
 {
        static char value[1024];
-       int quote = 0, comment = 0, len = 0, space = 0;
+       int quote = 0, comment = 0, space = 0;
+       size_t len = 0;
 
        for (;;) {
                int c = get_next_char();
+
                if (len >= sizeof(value) - 1)
                        return NULL;
                if (c == '\n') {
@@ -353,13 +355,13 @@ int perf_config_string(const char **dest, const char *var, const char *value)
        return 0;
 }
 
-static int perf_default_core_config(const char *var, const char *value)
+static int perf_default_core_config(const char *var __used, const char *value __used)
 {
        /* Add other config variables here and to Documentation/config.txt. */
        return 0;
 }
 
-int perf_default_config(const char *var, const char *value, void *dummy)
+int perf_default_config(const char *var, const char *value, void *dummy __used)
 {
        if (!prefixcmp(var, "core."))
                return perf_default_core_config(var, value);
@@ -471,10 +473,10 @@ static int matches(const char* key, const char* value)
                  !regexec(store.value_regex, value, 0, NULL, 0)));
 }
 
-static int store_aux(const char* key, const char* value, void *cb)
+static int store_aux(const char* key, const char* value, void *cb __used)
 {
+       int section_len;
        const char *ep;
-       size_t section_len;
 
        switch (store.state) {
        case KEY_SEEN:
@@ -551,7 +553,7 @@ static int store_write_section(int fd, const char* key)
                strbuf_addf(&sb, "[%.*s]\n", store.baselen, key);
        }
 
-       success = write_in_full(fd, sb.buf, sb.len) == sb.len;
+       success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len);
        strbuf_release(&sb);
 
        return success;
@@ -599,7 +601,7 @@ static int store_write_pair(int fd, const char* key, const char* value)
                }
        strbuf_addf(&sb, "%s\n", quote);
 
-       success = write_in_full(fd, sb.buf, sb.len) == sb.len;
+       success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len);
        strbuf_release(&sb);
 
        return success;
@@ -741,7 +743,7 @@ int perf_config_set_multivar(const char* key, const char* value,
        } else {
                struct stat st;
                char* contents;
-               size_t contents_sz, copy_begin, copy_end;
+               ssize_t contents_sz, copy_begin, copy_end;
                int i, new_line = 0;
 
                if (value_regex == NULL)
index d39292263153021ac44a6f9b4e2779ce63478094..34a3528673822622019687929f0499c4ebc0de1a 100644 (file)
@@ -1,6 +1,9 @@
 #include "cache.h"
 #include "exec_cmd.h"
 #include "quote.h"
+
+#include <string.h>
+
 #define MAX_ARGS       32
 
 extern char **environ;
@@ -51,7 +54,7 @@ const char *perf_extract_argv0_path(const char *argv0)
                slash--;
 
        if (slash >= argv0) {
-               argv0_path = strndup(argv0, slash - argv0);
+               argv0_path = xstrndup(argv0, slash - argv0);
                return slash + 1;
        }
 
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
new file mode 100644 (file)
index 0000000..b92a457
--- /dev/null
@@ -0,0 +1,245 @@
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "util.h"
+#include "header.h"
+
+/*
+ *
+ */
+
+struct perf_header_attr *perf_header_attr__new(struct perf_counter_attr *attr)
+{
+       struct perf_header_attr *self = malloc(sizeof(*self));
+
+       if (!self)
+               die("nomem");
+
+       self->attr = *attr;
+       self->ids = 0;
+       self->size = 1;
+       self->id = malloc(sizeof(u64));
+
+       if (!self->id)
+               die("nomem");
+
+       return self;
+}
+
+void perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
+{
+       int pos = self->ids;
+
+       self->ids++;
+       if (self->ids > self->size) {
+               self->size *= 2;
+               self->id = realloc(self->id, self->size * sizeof(u64));
+               if (!self->id)
+                       die("nomem");
+       }
+       self->id[pos] = id;
+}
+
+/*
+ *
+ */
+
+struct perf_header *perf_header__new(void)
+{
+       struct perf_header *self = malloc(sizeof(*self));
+
+       if (!self)
+               die("nomem");
+
+       self->frozen = 0;
+
+       self->attrs = 0;
+       self->size = 1;
+       self->attr = malloc(sizeof(void *));
+
+       if (!self->attr)
+               die("nomem");
+
+       self->data_offset = 0;
+       self->data_size = 0;
+
+       return self;
+}
+
+void perf_header__add_attr(struct perf_header *self,
+                          struct perf_header_attr *attr)
+{
+       int pos = self->attrs;
+
+       if (self->frozen)
+               die("frozen");
+
+       self->attrs++;
+       if (self->attrs > self->size) {
+               self->size *= 2;
+               self->attr = realloc(self->attr, self->size * sizeof(void *));
+               if (!self->attr)
+                       die("nomem");
+       }
+       self->attr[pos] = attr;
+}
+
+static const char *__perf_magic = "PERFFILE";
+
+#define PERF_MAGIC     (*(u64 *)__perf_magic)
+
+struct perf_file_section {
+       u64 offset;
+       u64 size;
+};
+
+struct perf_file_attr {
+       struct perf_counter_attr        attr;
+       struct perf_file_section        ids;
+};
+
+struct perf_file_header {
+       u64                             magic;
+       u64                             size;
+       u64                             attr_size;
+       struct perf_file_section        attrs;
+       struct perf_file_section        data;
+};
+
+static void do_write(int fd, void *buf, size_t size)
+{
+       while (size) {
+               int ret = write(fd, buf, size);
+
+               if (ret < 0)
+                       die("failed to write");
+
+               size -= ret;
+               buf += ret;
+       }
+}
+
+void perf_header__write(struct perf_header *self, int fd)
+{
+       struct perf_file_header f_header;
+       struct perf_file_attr   f_attr;
+       struct perf_header_attr *attr;
+       int i;
+
+       lseek(fd, sizeof(f_header), SEEK_SET);
+
+
+       for (i = 0; i < self->attrs; i++) {
+               attr = self->attr[i];
+
+               attr->id_offset = lseek(fd, 0, SEEK_CUR);
+               do_write(fd, attr->id, attr->ids * sizeof(u64));
+       }
+
+
+       self->attr_offset = lseek(fd, 0, SEEK_CUR);
+
+       for (i = 0; i < self->attrs; i++) {
+               attr = self->attr[i];
+
+               f_attr = (struct perf_file_attr){
+                       .attr = attr->attr,
+                       .ids  = {
+                               .offset = attr->id_offset,
+                               .size   = attr->ids * sizeof(u64),
+                       }
+               };
+               do_write(fd, &f_attr, sizeof(f_attr));
+       }
+
+
+       self->data_offset = lseek(fd, 0, SEEK_CUR);
+
+       f_header = (struct perf_file_header){
+               .magic     = PERF_MAGIC,
+               .size      = sizeof(f_header),
+               .attr_size = sizeof(f_attr),
+               .attrs = {
+                       .offset = self->attr_offset,
+                       .size   = self->attrs * sizeof(f_attr),
+               },
+               .data = {
+                       .offset = self->data_offset,
+                       .size   = self->data_size,
+               },
+       };
+
+       lseek(fd, 0, SEEK_SET);
+       do_write(fd, &f_header, sizeof(f_header));
+       lseek(fd, self->data_offset + self->data_size, SEEK_SET);
+
+       self->frozen = 1;
+}
+
+static void do_read(int fd, void *buf, size_t size)
+{
+       while (size) {
+               int ret = read(fd, buf, size);
+
+               if (ret < 0)
+                       die("failed to read");
+               if (ret == 0)
+                       die("failed to read: missing data");
+
+               size -= ret;
+               buf += ret;
+       }
+}
+
+struct perf_header *perf_header__read(int fd)
+{
+       struct perf_header      *self = perf_header__new();
+       struct perf_file_header f_header;
+       struct perf_file_attr   f_attr;
+       u64                     f_id;
+
+       int nr_attrs, nr_ids, i, j;
+
+       lseek(fd, 0, SEEK_SET);
+       do_read(fd, &f_header, sizeof(f_header));
+
+       if (f_header.magic      != PERF_MAGIC           ||
+           f_header.size       != sizeof(f_header)     ||
+           f_header.attr_size  != sizeof(f_attr))
+               die("incompatible file format");
+
+       nr_attrs = f_header.attrs.size / sizeof(f_attr);
+       lseek(fd, f_header.attrs.offset, SEEK_SET);
+
+       for (i = 0; i < nr_attrs; i++) {
+               struct perf_header_attr *attr;
+               off_t tmp;
+
+               do_read(fd, &f_attr, sizeof(f_attr));
+               tmp = lseek(fd, 0, SEEK_CUR);
+
+               attr = perf_header_attr__new(&f_attr.attr);
+
+               nr_ids = f_attr.ids.size / sizeof(u64);
+               lseek(fd, f_attr.ids.offset, SEEK_SET);
+
+               for (j = 0; j < nr_ids; j++) {
+                       do_read(fd, &f_id, sizeof(f_id));
+
+                       perf_header_attr__add_id(attr, f_id);
+               }
+               perf_header__add_attr(self, attr);
+               lseek(fd, tmp, SEEK_SET);
+       }
+
+       self->data_offset = f_header.data.offset;
+       self->data_size   = f_header.data.size;
+
+       lseek(fd, self->data_offset + self->data_size, SEEK_SET);
+
+       self->frozen = 1;
+
+       return self;
+}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
new file mode 100644 (file)
index 0000000..bf28044
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _PERF_HEADER_H
+#define _PERF_HEADER_H
+
+#include "../../../include/linux/perf_counter.h"
+#include <sys/types.h>
+#include "types.h"
+
+struct perf_header_attr {
+       struct perf_counter_attr attr;
+       int ids, size;
+       u64 *id;
+       off_t id_offset;
+};
+
+struct perf_header {
+       int frozen;
+       int attrs, size;
+       struct perf_header_attr **attr;
+       s64 attr_offset;
+       u64 data_offset;
+       u64 data_size;
+};
+
+struct perf_header *perf_header__read(int fd);
+void perf_header__write(struct perf_header *self, int fd);
+
+void perf_header__add_attr(struct perf_header *self,
+                          struct perf_header_attr *attr);
+
+struct perf_header_attr *
+perf_header_attr__new(struct perf_counter_attr *attr);
+void perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
+
+
+struct perf_header *perf_header__new(void);
+
+#endif /* _PERF_HEADER_H */
index 6653f7dd1d784f96fcd8161cafc7fb78895dc6e4..fbb00978b2e2988045f4f970964b7c5826c1cba4 100644 (file)
@@ -26,7 +26,7 @@ static int term_columns(void)
        return 80;
 }
 
-void add_cmdname(struct cmdnames *cmds, const char *name, int len)
+void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
 {
        struct cmdname *ent = malloc(sizeof(*ent) + len + 1);
 
@@ -40,7 +40,8 @@ void add_cmdname(struct cmdnames *cmds, const char *name, int len)
 
 static void clean_cmdnames(struct cmdnames *cmds)
 {
-       int i;
+       unsigned int i;
+
        for (i = 0; i < cmds->cnt; ++i)
                free(cmds->names[i]);
        free(cmds->names);
@@ -57,7 +58,7 @@ static int cmdname_compare(const void *a_, const void *b_)
 
 static void uniq(struct cmdnames *cmds)
 {
-       int i, j;
+       unsigned int i, j;
 
        if (!cmds->cnt)
                return;
@@ -71,7 +72,7 @@ static void uniq(struct cmdnames *cmds)
 
 void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
 {
-       int ci, cj, ei;
+       size_t ci, cj, ei;
        int cmp;
 
        ci = cj = ei = 0;
@@ -106,8 +107,9 @@ static void pretty_print_string_list(struct cmdnames *cmds, int longest)
                printf("  ");
 
                for (j = 0; j < cols; j++) {
-                       int n = j * rows + i;
-                       int size = space;
+                       unsigned int n = j * rows + i;
+                       unsigned int size = space;
+
                        if (n >= cmds->cnt)
                                break;
                        if (j == cols-1 || n + rows >= cmds->cnt)
@@ -126,21 +128,6 @@ static int is_executable(const char *name)
            !S_ISREG(st.st_mode))
                return 0;
 
-#ifdef __MINGW32__
-       /* cannot trust the executable bit, peek into the file instead */
-       char buf[3] = { 0 };
-       int n;
-       int fd = open(name, O_RDONLY);
-       st.st_mode &= ~S_IXUSR;
-       if (fd >= 0) {
-               n = read(fd, buf, 2);
-               if (n == 2)
-                       /* DOS executables start with "MZ" */
-                       if (!strcmp(buf, "#!") || !strcmp(buf, "MZ"))
-                               st.st_mode |= S_IXUSR;
-               close(fd);
-       }
-#endif
        return st.st_mode & S_IXUSR;
 }
 
@@ -223,7 +210,7 @@ void load_command_list(const char *prefix,
 void list_commands(const char *title, struct cmdnames *main_cmds,
                   struct cmdnames *other_cmds)
 {
-       int i, longest = 0;
+       unsigned int i, longest = 0;
 
        for (i = 0; i < main_cmds->cnt; i++)
                if (longest < main_cmds->names[i]->len)
@@ -254,7 +241,8 @@ void list_commands(const char *title, struct cmdnames *main_cmds,
 
 int is_in_cmdlist(struct cmdnames *c, const char *s)
 {
-       int i;
+       unsigned int i;
+
        for (i = 0; i < c->cnt; i++)
                if (!strcmp(s, c->names[i]->name))
                        return 1;
@@ -286,7 +274,8 @@ static int levenshtein_compare(const void *p1, const void *p2)
 
 static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
 {
-       int i;
+       unsigned int i;
+
        ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc);
 
        for (i = 0; i < old->cnt; i++)
@@ -298,7 +287,7 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
 
 const char *help_unknown_cmd(const char *cmd)
 {
-       int i, n = 0, best_similarity = 0;
+       unsigned int i, n = 0, best_similarity = 0;
        struct cmdnames main_cmds, other_cmds;
 
        memset(&main_cmds, 0, sizeof(main_cmds));
@@ -360,7 +349,7 @@ const char *help_unknown_cmd(const char *cmd)
        exit(1);
 }
 
-int cmd_version(int argc, const char **argv, const char *prefix)
+int cmd_version(int argc __used, const char **argv __used, const char *prefix __used)
 {
        printf("perf version %s\n", perf_version_string);
        return 0;
index 56bc15406ffc55115fa1c827e0d1d5a7e74c516d..7128783637b4a7be720c49a9e74ccb43cba2cac9 100644 (file)
@@ -2,8 +2,8 @@
 #define HELP_H
 
 struct cmdnames {
-       int alloc;
-       int cnt;
+       size_t alloc;
+       size_t cnt;
        struct cmdname {
                size_t len; /* also used for similarity index in help.c */
                char name[FLEX_ARRAY];
@@ -19,7 +19,7 @@ static inline void mput_char(char c, unsigned int num)
 void load_command_list(const char *prefix,
                struct cmdnames *main_cmds,
                struct cmdnames *other_cmds);
-void add_cmdname(struct cmdnames *cmds, const char *name, int len);
+void add_cmdname(struct cmdnames *cmds, const char *name, size_t len);
 /* Here we require that excludes is a sorted list. */
 void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes);
 int is_in_cmdlist(struct cmdnames *c, const char *s);
diff --git a/tools/perf/util/include/asm/system.h b/tools/perf/util/include/asm/system.h
new file mode 100644 (file)
index 0000000..710cecc
--- /dev/null
@@ -0,0 +1 @@
+/* Empty */
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h
new file mode 100644 (file)
index 0000000..a6b8739
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef PERF_LINUX_KERNEL_H_
+#define PERF_LINUX_KERNEL_H_
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#ifndef container_of
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:       the pointer to the member.
+ * @type:      the type of the container struct this is embedded in.
+ * @member:    the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({                     \
+       const typeof(((type *)0)->member) * __mptr = (ptr);     \
+       (type *)((char *)__mptr - offsetof(type, member)); })
+#endif
+
+#ifndef max
+#define max(x, y) ({                           \
+       typeof(x) _max1 = (x);                  \
+       typeof(y) _max2 = (y);                  \
+       (void) (&_max1 == &_max2);              \
+       _max1 > _max2 ? _max1 : _max2; })
+#endif
+
+#endif
diff --git a/tools/perf/util/include/linux/list.h b/tools/perf/util/include/linux/list.h
new file mode 100644 (file)
index 0000000..dbe4b81
--- /dev/null
@@ -0,0 +1,18 @@
+#include "../../../../include/linux/list.h"
+
+#ifndef PERF_LIST_H
+#define PERF_LIST_H
+/**
+ * list_del_range - deletes range of entries from list.
+ * @begin: first element in the range to delete from the list.
+ * @end: last element in the range to delete from the list.
+ * Note: list_empty on the range of entries does not return true after this,
+ * the entries is in an undefined state.
+ */
+static inline void list_del_range(struct list_head *begin,
+                                 struct list_head *end)
+{
+       begin->prev->next = end->next;
+       end->next->prev = begin->prev;
+}
+#endif
diff --git a/tools/perf/util/include/linux/module.h b/tools/perf/util/include/linux/module.h
new file mode 100644 (file)
index 0000000..b43e2dc
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef PERF_LINUX_MODULE_H
+#define PERF_LINUX_MODULE_H
+
+#define EXPORT_SYMBOL(name)
+
+#endif
diff --git a/tools/perf/util/include/linux/poison.h b/tools/perf/util/include/linux/poison.h
new file mode 100644 (file)
index 0000000..fef6dbc
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../../include/linux/poison.h"
diff --git a/tools/perf/util/include/linux/prefetch.h b/tools/perf/util/include/linux/prefetch.h
new file mode 100644 (file)
index 0000000..7841e48
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef PERF_LINUX_PREFETCH_H
+#define PERF_LINUX_PREFETCH_H
+
+static inline void prefetch(void *a __attribute__((unused))) { }
+
+#endif
diff --git a/tools/perf/util/include/linux/rbtree.h b/tools/perf/util/include/linux/rbtree.h
new file mode 100644 (file)
index 0000000..7a243a1
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../../include/linux/rbtree.h"
diff --git a/tools/perf/util/list.h b/tools/perf/util/list.h
deleted file mode 100644 (file)
index e2548e8..0000000
+++ /dev/null
@@ -1,603 +0,0 @@
-#ifndef _LINUX_LIST_H
-#define _LINUX_LIST_H
-/*
-  Copyright (C) Cast of dozens, comes from the Linux kernel
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms of version 2 of the GNU General Public License as
-  published by the Free Software Foundation.
-*/
-
-#include <stddef.h>
-
-/*
- * These are non-NULL pointers that will result in page faults
- * under normal circumstances, used to verify that nobody uses
- * non-initialized list entries.
- */
-#define LIST_POISON1 ((void *)0x00100100)
-#define LIST_POISON2 ((void *)0x00200200)
-
-/**
- * container_of - cast a member of a structure out to the containing structure
- * @ptr:       the pointer to the member.
- * @type:      the type of the container struct this is embedded in.
- * @member:    the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({                     \
-        const typeof( ((type *)0)->member ) *__mptr = (ptr);   \
-        (type *)( (char *)__mptr - offsetof(type,member) );})
-
-/*
- * Simple doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-struct list_head {
-       struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
-       struct list_head name = LIST_HEAD_INIT(name)
-
-static inline void INIT_LIST_HEAD(struct list_head *list)
-{
-       list->next = list;
-       list->prev = list;
-}
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_add(struct list_head *new,
-                             struct list_head *prev,
-                             struct list_head *next)
-{
-       next->prev = new;
-       new->next = next;
-       new->prev = prev;
-       prev->next = new;
-}
-
-/**
- * list_add - add a new entry
- * @new: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
-       __list_add(new, head, head->next);
-}
-
-/**
- * list_add_tail - add a new entry
- * @new: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
-       __list_add(new, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head * prev, struct list_head * next)
-{
-       next->prev = prev;
-       prev->next = next;
-}
-
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty on entry does not return true after this, the entry is
- * in an undefined state.
- */
-static inline void list_del(struct list_head *entry)
-{
-       __list_del(entry->prev, entry->next);
-       entry->next = LIST_POISON1;
-       entry->prev = LIST_POISON2;
-}
-
-/**
- * list_del_range - deletes range of entries from list.
- * @beging: first element in the range to delete from the list.
- * @beging: first element in the range to delete from the list.
- * Note: list_empty on the range of entries does not return true after this,
- * the entries is in an undefined state.
- */
-static inline void list_del_range(struct list_head *begin,
-                                 struct list_head *end)
-{
-       begin->prev->next = end->next;
-       end->next->prev = begin->prev;
-}
-
-/**
- * list_replace - replace old entry by new one
- * @old : the element to be replaced
- * @new : the new element to insert
- * Note: if 'old' was empty, it will be overwritten.
- */
-static inline void list_replace(struct list_head *old,
-                               struct list_head *new)
-{
-       new->next = old->next;
-       new->next->prev = new;
-       new->prev = old->prev;
-       new->prev->next = new;
-}
-
-static inline void list_replace_init(struct list_head *old,
-                                       struct list_head *new)
-{
-       list_replace(old, new);
-       INIT_LIST_HEAD(old);
-}
-
-/**
- * list_del_init - deletes entry from list and reinitialize it.
- * @entry: the element to delete from the list.
- */
-static inline void list_del_init(struct list_head *entry)
-{
-       __list_del(entry->prev, entry->next);
-       INIT_LIST_HEAD(entry);
-}
-
-/**
- * list_move - delete from one list and add as another's head
- * @list: the entry to move
- * @head: the head that will precede our entry
- */
-static inline void list_move(struct list_head *list, struct list_head *head)
-{
-        __list_del(list->prev, list->next);
-        list_add(list, head);
-}
-
-/**
- * list_move_tail - delete from one list and add as another's tail
- * @list: the entry to move
- * @head: the head that will follow our entry
- */
-static inline void list_move_tail(struct list_head *list,
-                                 struct list_head *head)
-{
-        __list_del(list->prev, list->next);
-        list_add_tail(list, head);
-}
-
-/**
- * list_is_last - tests whether @list is the last entry in list @head
- * @list: the entry to test
- * @head: the head of the list
- */
-static inline int list_is_last(const struct list_head *list,
-                               const struct list_head *head)
-{
-       return list->next == head;
-}
-
-/**
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-static inline int list_empty(const struct list_head *head)
-{
-       return head->next == head;
-}
-
-/**
- * list_empty_careful - tests whether a list is empty and not being modified
- * @head: the list to test
- *
- * Description:
- * tests whether a list is empty _and_ checks that no other CPU might be
- * in the process of modifying either member (next or prev)
- *
- * NOTE: using list_empty_careful() without synchronization
- * can only be safe if the only activity that can happen
- * to the list entry is list_del_init(). Eg. it cannot be used
- * if another CPU could re-list_add() it.
- */
-static inline int list_empty_careful(const struct list_head *head)
-{
-       struct list_head *next = head->next;
-       return (next == head) && (next == head->prev);
-}
-
-static inline void __list_splice(struct list_head *list,
-                                struct list_head *head)
-{
-       struct list_head *first = list->next;
-       struct list_head *last = list->prev;
-       struct list_head *at = head->next;
-
-       first->prev = head;
-       head->next = first;
-
-       last->next = at;
-       at->prev = last;
-}
-
-/**
- * list_splice - join two lists
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- */
-static inline void list_splice(struct list_head *list, struct list_head *head)
-{
-       if (!list_empty(list))
-               __list_splice(list, head);
-}
-
-/**
- * list_splice_init - join two lists and reinitialise the emptied list.
- * @list: the new list to add.
- * @head: the place to add it in the first list.
- *
- * The list at @list is reinitialised
- */
-static inline void list_splice_init(struct list_head *list,
-                                   struct list_head *head)
-{
-       if (!list_empty(list)) {
-               __list_splice(list, head);
-               INIT_LIST_HEAD(list);
-       }
-}
-
-/**
- * list_entry - get the struct for this entry
- * @ptr:       the &struct list_head pointer.
- * @type:      the type of the struct this is embedded in.
- * @member:    the name of the list_struct within the struct.
- */
-#define list_entry(ptr, type, member) \
-       container_of(ptr, type, member)
-
-/**
- * list_first_entry - get the first element from a list
- * @ptr:       the list head to take the element from.
- * @type:      the type of the struct this is embedded in.
- * @member:    the name of the list_struct within the struct.
- *
- * Note, that list is expected to be not empty.
- */
-#define list_first_entry(ptr, type, member) \
-       list_entry((ptr)->next, type, member)
-
-/**
- * list_for_each       -       iterate over a list
- * @pos:       the &struct list_head to use as a loop cursor.
- * @head:      the head for your list.
- */
-#define list_for_each(pos, head) \
-       for (pos = (head)->next; pos != (head); \
-               pos = pos->next)
-
-/**
- * __list_for_each     -       iterate over a list
- * @pos:       the &struct list_head to use as a loop cursor.
- * @head:      the head for your list.
- *
- * This variant differs from list_for_each() in that it's the
- * simplest possible list iteration code, no prefetching is done.
- * Use this for code that knows the list to be very short (empty
- * or 1 entry) most of the time.
- */
-#define __list_for_each(pos, head) \
-       for (pos = (head)->next; pos != (head); pos = pos->next)
-
-/**
- * list_for_each_prev  -       iterate over a list backwards
- * @pos:       the &struct list_head to use as a loop cursor.
- * @head:      the head for your list.
- */
-#define list_for_each_prev(pos, head) \
-       for (pos = (head)->prev; pos != (head); \
-               pos = pos->prev)
-
-/**
- * list_for_each_safe - iterate over a list safe against removal of list entry
- * @pos:       the &struct list_head to use as a loop cursor.
- * @n:         another &struct list_head to use as temporary storage
- * @head:      the head for your list.
- */
-#define list_for_each_safe(pos, n, head) \
-       for (pos = (head)->next, n = pos->next; pos != (head); \
-               pos = n, n = pos->next)
-
-/**
- * list_for_each_entry -       iterate over list of given type
- * @pos:       the type * to use as a loop cursor.
- * @head:      the head for your list.
- * @member:    the name of the list_struct within the struct.
- */
-#define list_for_each_entry(pos, head, member)                         \
-       for (pos = list_entry((head)->next, typeof(*pos), member);      \
-            &pos->member != (head);    \
-            pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_reverse - iterate backwards over list of given type.
- * @pos:       the type * to use as a loop cursor.
- * @head:      the head for your list.
- * @member:    the name of the list_struct within the struct.
- */
-#define list_for_each_entry_reverse(pos, head, member)                 \
-       for (pos = list_entry((head)->prev, typeof(*pos), member);      \
-            &pos->member != (head);    \
-            pos = list_entry(pos->member.prev, typeof(*pos), member))
-
-/**
- * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue
- * @pos:       the type * to use as a start point
- * @head:      the head of the list
- * @member:    the name of the list_struct within the struct.
- *
- * Prepares a pos entry for use as a start point in list_for_each_entry_continue.
- */
-#define list_prepare_entry(pos, head, member) \
-       ((pos) ? : list_entry(head, typeof(*pos), member))
-
-/**
- * list_for_each_entry_continue - continue iteration over list of given type
- * @pos:       the type * to use as a loop cursor.
- * @head:      the head for your list.
- * @member:    the name of the list_struct within the struct.
- *
- * Continue to iterate over list of given type, continuing after
- * the current position.
- */
-#define list_for_each_entry_continue(pos, head, member)                \
-       for (pos = list_entry(pos->member.next, typeof(*pos), member);  \
-            &pos->member != (head);    \
-            pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_from - iterate over list of given type from the current point
- * @pos:       the type * to use as a loop cursor.
- * @head:      the head for your list.
- * @member:    the name of the list_struct within the struct.
- *
- * Iterate over list of given type, continuing from current position.
- */
-#define list_for_each_entry_from(pos, head, member)                    \
-       for (; &pos->member != (head);  \
-            pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @pos:       the type * to use as a loop cursor.
- * @n:         another type * to use as temporary storage
- * @head:      the head for your list.
- * @member:    the name of the list_struct within the struct.
- */
-#define list_for_each_entry_safe(pos, n, head, member)                 \
-       for (pos = list_entry((head)->next, typeof(*pos), member),      \
-               n = list_entry(pos->member.next, typeof(*pos), member); \
-            &pos->member != (head);                                    \
-            pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_for_each_entry_safe_continue
- * @pos:       the type * to use as a loop cursor.
- * @n:         another type * to use as temporary storage
- * @head:      the head for your list.
- * @member:    the name of the list_struct within the struct.
- *
- * Iterate over list of given type, continuing after current point,
- * safe against removal of list entry.
- */
-#define list_for_each_entry_safe_continue(pos, n, head, member)                \
-       for (pos = list_entry(pos->member.next, typeof(*pos), member),          \
-               n = list_entry(pos->member.next, typeof(*pos), member);         \
-            &pos->member != (head);                                            \
-            pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_for_each_entry_safe_from
- * @pos:       the type * to use as a loop cursor.
- * @n:         another type * to use as temporary storage
- * @head:      the head for your list.
- * @member:    the name of the list_struct within the struct.
- *
- * Iterate over list of given type from current point, safe against
- * removal of list entry.
- */
-#define list_for_each_entry_safe_from(pos, n, head, member)                    \
-       for (n = list_entry(pos->member.next, typeof(*pos), member);            \
-            &pos->member != (head);                                            \
-            pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_for_each_entry_safe_reverse
- * @pos:       the type * to use as a loop cursor.
- * @n:         another type * to use as temporary storage
- * @head:      the head for your list.
- * @member:    the name of the list_struct within the struct.
- *
- * Iterate backwards over list of given type, safe against removal
- * of list entry.
- */
-#define list_for_each_entry_safe_reverse(pos, n, head, member)         \
-       for (pos = list_entry((head)->prev, typeof(*pos), member),      \
-               n = list_entry(pos->member.prev, typeof(*pos), member); \
-            &pos->member != (head);                                    \
-            pos = n, n = list_entry(n->member.prev, typeof(*n), member))
-
-/*
- * Double linked lists with a single pointer list head.
- * Mostly useful for hash tables where the two pointer list head is
- * too wasteful.
- * You lose the ability to access the tail in O(1).
- */
-
-struct hlist_head {
-       struct hlist_node *first;
-};
-
-struct hlist_node {
-       struct hlist_node *next, **pprev;
-};
-
-#define HLIST_HEAD_INIT { .first = NULL }
-#define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
-#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
-static inline void INIT_HLIST_NODE(struct hlist_node *h)
-{
-       h->next = NULL;
-       h->pprev = NULL;
-}
-
-static inline int hlist_unhashed(const struct hlist_node *h)
-{
-       return !h->pprev;
-}
-
-static inline int hlist_empty(const struct hlist_head *h)
-{
-       return !h->first;
-}
-
-static inline void __hlist_del(struct hlist_node *n)
-{
-       struct hlist_node *next = n->next;
-       struct hlist_node **pprev = n->pprev;
-       *pprev = next;
-       if (next)
-               next->pprev = pprev;
-}
-
-static inline void hlist_del(struct hlist_node *n)
-{
-       __hlist_del(n);
-       n->next = LIST_POISON1;
-       n->pprev = LIST_POISON2;
-}
-
-static inline void hlist_del_init(struct hlist_node *n)
-{
-       if (!hlist_unhashed(n)) {
-               __hlist_del(n);
-               INIT_HLIST_NODE(n);
-       }
-}
-
-static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
-{
-       struct hlist_node *first = h->first;
-       n->next = first;
-       if (first)
-               first->pprev = &n->next;
-       h->first = n;
-       n->pprev = &h->first;
-}
-
-/* next must be != NULL */
-static inline void hlist_add_before(struct hlist_node *n,
-                                       struct hlist_node *next)
-{
-       n->pprev = next->pprev;
-       n->next = next;
-       next->pprev = &n->next;
-       *(n->pprev) = n;
-}
-
-static inline void hlist_add_after(struct hlist_node *n,
-                                       struct hlist_node *next)
-{
-       next->next = n->next;
-       n->next = next;
-       next->pprev = &n->next;
-
-       if(next->next)
-               next->next->pprev  = &next->next;
-}
-
-#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
-
-#define hlist_for_each(pos, head) \
-       for (pos = (head)->first; pos; \
-            pos = pos->next)
-
-#define hlist_for_each_safe(pos, n, head) \
-       for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
-            pos = n)
-
-/**
- * hlist_for_each_entry        - iterate over list of given type
- * @tpos:      the type * to use as a loop cursor.
- * @pos:       the &struct hlist_node to use as a loop cursor.
- * @head:      the head for your list.
- * @member:    the name of the hlist_node within the struct.
- */
-#define hlist_for_each_entry(tpos, pos, head, member)                   \
-       for (pos = (head)->first;                                        \
-            pos &&                      \
-               ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
-            pos = pos->next)
-
-/**
- * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
- * @tpos:      the type * to use as a loop cursor.
- * @pos:       the &struct hlist_node to use as a loop cursor.
- * @member:    the name of the hlist_node within the struct.
- */
-#define hlist_for_each_entry_continue(tpos, pos, member)                \
-       for (pos = (pos)->next;                                          \
-            pos &&                      \
-               ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
-            pos = pos->next)
-
-/**
- * hlist_for_each_entry_from - iterate over a hlist continuing from current point
- * @tpos:      the type * to use as a loop cursor.
- * @pos:       the &struct hlist_node to use as a loop cursor.
- * @member:    the name of the hlist_node within the struct.
- */
-#define hlist_for_each_entry_from(tpos, pos, member)                    \
-       for (; pos &&                    \
-               ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
-            pos = pos->next)
-
-/**
- * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @tpos:      the type * to use as a loop cursor.
- * @pos:       the &struct hlist_node to use as a loop cursor.
- * @n:         another &struct hlist_node to use as temporary storage
- * @head:      the head for your list.
- * @member:    the name of the hlist_node within the struct.
- */
-#define hlist_for_each_entry_safe(tpos, pos, n, head, member)           \
-       for (pos = (head)->first;                                        \
-            pos && ({ n = pos->next; 1; }) &&                           \
-               ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
-            pos = n)
-
-#endif
diff --git a/tools/perf/util/module.c b/tools/perf/util/module.c
new file mode 100644 (file)
index 0000000..ddabe92
--- /dev/null
@@ -0,0 +1,509 @@
+#include "util.h"
+#include "../perf.h"
+#include "string.h"
+#include "module.h"
+
+#include <libelf.h>
+#include <gelf.h>
+#include <elf.h>
+#include <dirent.h>
+#include <sys/utsname.h>
+
+static unsigned int crc32(const char *p, unsigned int len)
+{
+       int i;
+       unsigned int crc = 0;
+
+       while (len--) {
+               crc ^= *p++;
+               for (i = 0; i < 8; i++)
+                       crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
+       }
+       return crc;
+}
+
+/* module section methods */
+
+struct sec_dso *sec_dso__new_dso(const char *name)
+{
+       struct sec_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
+
+       if (self != NULL) {
+               strcpy(self->name, name);
+               self->secs = RB_ROOT;
+               self->find_section = sec_dso__find_section;
+       }
+
+       return self;
+}
+
+static void sec_dso__delete_section(struct section *self)
+{
+       free(((void *)self));
+}
+
+void sec_dso__delete_sections(struct sec_dso *self)
+{
+       struct section *pos;
+       struct rb_node *next = rb_first(&self->secs);
+
+       while (next) {
+               pos = rb_entry(next, struct section, rb_node);
+               next = rb_next(&pos->rb_node);
+               rb_erase(&pos->rb_node, &self->secs);
+               sec_dso__delete_section(pos);
+       }
+}
+
+void sec_dso__delete_self(struct sec_dso *self)
+{
+       sec_dso__delete_sections(self);
+       free(self);
+}
+
+static void sec_dso__insert_section(struct sec_dso *self, struct section *sec)
+{
+       struct rb_node **p = &self->secs.rb_node;
+       struct rb_node *parent = NULL;
+       const u64 hash = sec->hash;
+       struct section *s;
+
+       while (*p != NULL) {
+               parent = *p;
+               s = rb_entry(parent, struct section, rb_node);
+               if (hash < s->hash)
+                       p = &(*p)->rb_left;
+               else
+                       p = &(*p)->rb_right;
+       }
+       rb_link_node(&sec->rb_node, parent, p);
+       rb_insert_color(&sec->rb_node, &self->secs);
+}
+
+struct section *sec_dso__find_section(struct sec_dso *self, const char *name)
+{
+       struct rb_node *n;
+       u64 hash;
+       int len;
+
+       if (self == NULL)
+               return NULL;
+
+       len = strlen(name);
+       hash = crc32(name, len);
+
+       n = self->secs.rb_node;
+
+       while (n) {
+               struct section *s = rb_entry(n, struct section, rb_node);
+
+               if (hash < s->hash)
+                       n = n->rb_left;
+               else if (hash > s->hash)
+                       n = n->rb_right;
+               else {
+                       if (!strcmp(name, s->name))
+                               return s;
+                       else
+                               n = rb_next(&s->rb_node);
+               }
+       }
+
+       return NULL;
+}
+
+static size_t sec_dso__fprintf_section(struct section *self, FILE *fp)
+{
+       return fprintf(fp, "name:%s vma:%llx path:%s\n",
+                      self->name, self->vma, self->path);
+}
+
+size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp)
+{
+       size_t ret = fprintf(fp, "dso: %s\n", self->name);
+
+       struct rb_node *nd;
+       for (nd = rb_first(&self->secs); nd; nd = rb_next(nd)) {
+               struct section *pos = rb_entry(nd, struct section, rb_node);
+               ret += sec_dso__fprintf_section(pos, fp);
+       }
+
+       return ret;
+}
+
+static struct section *section__new(const char *name, const char *path)
+{
+       struct section *self = calloc(1, sizeof(*self));
+
+       if (!self)
+               goto out_failure;
+
+       self->name = calloc(1, strlen(name) + 1);
+       if (!self->name)
+               goto out_failure;
+
+       self->path = calloc(1, strlen(path) + 1);
+       if (!self->path)
+               goto out_failure;
+
+       strcpy(self->name, name);
+       strcpy(self->path, path);
+       self->hash = crc32(self->name, strlen(name));
+
+       return self;
+
+out_failure:
+       if (self) {
+               if (self->name)
+                       free(self->name);
+               if (self->path)
+                       free(self->path);
+               free(self);
+       }
+
+       return NULL;
+}
+
+/* module methods */
+
+struct mod_dso *mod_dso__new_dso(const char *name)
+{
+       struct mod_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
+
+       if (self != NULL) {
+               strcpy(self->name, name);
+               self->mods = RB_ROOT;
+               self->find_module = mod_dso__find_module;
+       }
+
+       return self;
+}
+
+static void mod_dso__delete_module(struct module *self)
+{
+       free(((void *)self));
+}
+
+void mod_dso__delete_modules(struct mod_dso *self)
+{
+       struct module *pos;
+       struct rb_node *next = rb_first(&self->mods);
+
+       while (next) {
+               pos = rb_entry(next, struct module, rb_node);
+               next = rb_next(&pos->rb_node);
+               rb_erase(&pos->rb_node, &self->mods);
+               mod_dso__delete_module(pos);
+       }
+}
+
+void mod_dso__delete_self(struct mod_dso *self)
+{
+       mod_dso__delete_modules(self);
+       free(self);
+}
+
+static void mod_dso__insert_module(struct mod_dso *self, struct module *mod)
+{
+       struct rb_node **p = &self->mods.rb_node;
+       struct rb_node *parent = NULL;
+       const u64 hash = mod->hash;
+       struct module *m;
+
+       while (*p != NULL) {
+               parent = *p;
+               m = rb_entry(parent, struct module, rb_node);
+               if (hash < m->hash)
+                       p = &(*p)->rb_left;
+               else
+                       p = &(*p)->rb_right;
+       }
+       rb_link_node(&mod->rb_node, parent, p);
+       rb_insert_color(&mod->rb_node, &self->mods);
+}
+
+struct module *mod_dso__find_module(struct mod_dso *self, const char *name)
+{
+       struct rb_node *n;
+       u64 hash;
+       int len;
+
+       if (self == NULL)
+               return NULL;
+
+       len = strlen(name);
+       hash = crc32(name, len);
+
+       n = self->mods.rb_node;
+
+       while (n) {
+               struct module *m = rb_entry(n, struct module, rb_node);
+
+               if (hash < m->hash)
+                       n = n->rb_left;
+               else if (hash > m->hash)
+                       n = n->rb_right;
+               else {
+                       if (!strcmp(name, m->name))
+                               return m;
+                       else
+                               n = rb_next(&m->rb_node);
+               }
+       }
+
+       return NULL;
+}
+
+static size_t mod_dso__fprintf_module(struct module *self, FILE *fp)
+{
+       return fprintf(fp, "name:%s path:%s\n", self->name, self->path);
+}
+
+size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp)
+{
+       struct rb_node *nd;
+       size_t ret;
+
+       ret = fprintf(fp, "dso: %s\n", self->name);
+
+       for (nd = rb_first(&self->mods); nd; nd = rb_next(nd)) {
+               struct module *pos = rb_entry(nd, struct module, rb_node);
+
+               ret += mod_dso__fprintf_module(pos, fp);
+       }
+
+       return ret;
+}
+
+static struct module *module__new(const char *name, const char *path)
+{
+       struct module *self = calloc(1, sizeof(*self));
+
+       if (!self)
+               goto out_failure;
+
+       self->name = calloc(1, strlen(name) + 1);
+       if (!self->name)
+               goto out_failure;
+
+       self->path = calloc(1, strlen(path) + 1);
+       if (!self->path)
+               goto out_failure;
+
+       strcpy(self->name, name);
+       strcpy(self->path, path);
+       self->hash = crc32(self->name, strlen(name));
+
+       return self;
+
+out_failure:
+       if (self) {
+               if (self->name)
+                       free(self->name);
+               if (self->path)
+                       free(self->path);
+               free(self);
+       }
+
+       return NULL;
+}
+
+static int mod_dso__load_sections(struct module *mod)
+{
+       int count = 0, path_len;
+       struct dirent *entry;
+       char *line = NULL;
+       char *dir_path;
+       DIR *dir;
+       size_t n;
+
+       path_len = strlen("/sys/module/");
+       path_len += strlen(mod->name);
+       path_len += strlen("/sections/");
+
+       dir_path = calloc(1, path_len + 1);
+       if (dir_path == NULL)
+               goto out_failure;
+
+       strcat(dir_path, "/sys/module/");
+       strcat(dir_path, mod->name);
+       strcat(dir_path, "/sections/");
+
+       dir = opendir(dir_path);
+       if (dir == NULL)
+               goto out_free;
+
+       while ((entry = readdir(dir))) {
+               struct section *section;
+               char *path, *vma;
+               int line_len;
+               FILE *file;
+
+               if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name))
+                       continue;
+
+               path = calloc(1, path_len + strlen(entry->d_name) + 1);
+               if (path == NULL)
+                       break;
+               strcat(path, dir_path);
+               strcat(path, entry->d_name);
+
+               file = fopen(path, "r");
+               if (file == NULL) {
+                       free(path);
+                       break;
+               }
+
+               line_len = getline(&line, &n, file);
+               if (line_len < 0) {
+                       free(path);
+                       fclose(file);
+                       break;
+               }
+
+               if (!line) {
+                       free(path);
+                       fclose(file);
+                       break;
+               }
+
+               line[--line_len] = '\0'; /* \n */
+
+               vma = strstr(line, "0x");
+               if (!vma) {
+                       free(path);
+                       fclose(file);
+                       break;
+               }
+               vma += 2;
+
+               section = section__new(entry->d_name, path);
+               if (!section) {
+                       fprintf(stderr, "load_sections: allocation error\n");
+                       free(path);
+                       fclose(file);
+                       break;
+               }
+
+               hex2u64(vma, &section->vma);
+               sec_dso__insert_section(mod->sections, section);
+
+               free(path);
+               fclose(file);
+               count++;
+       }
+
+       closedir(dir);
+       free(line);
+       free(dir_path);
+
+       return count;
+
+out_free:
+       free(dir_path);
+
+out_failure:
+       return count;
+}
+
+static int mod_dso__load_module_paths(struct mod_dso *self)
+{
+       struct utsname uts;
+       int count = 0, len;
+       char *line = NULL;
+       FILE *file;
+       char *path;
+       size_t n;
+
+       if (uname(&uts) < 0)
+               goto out_failure;
+
+       len = strlen("/lib/modules/");
+       len += strlen(uts.release);
+       len += strlen("/modules.dep");
+
+       path = calloc(1, len);
+       if (path == NULL)
+               goto out_failure;
+
+       strcat(path, "/lib/modules/");
+       strcat(path, uts.release);
+       strcat(path, "/modules.dep");
+
+       file = fopen(path, "r");
+       free(path);
+       if (file == NULL)
+               goto out_failure;
+
+       while (!feof(file)) {
+               char *path, *name, *tmp;
+               struct module *module;
+               int line_len, len;
+
+               line_len = getline(&line, &n, file);
+               if (line_len < 0)
+                       break;
+
+               if (!line)
+                       goto out_failure;
+
+               line[--line_len] = '\0'; /* \n */
+
+               path = strtok(line, ":");
+               if (!path)
+                       goto out_failure;
+
+               name = strdup(path);
+               name = strtok(name, "/");
+
+               tmp = name;
+
+               while (tmp) {
+                       tmp = strtok(NULL, "/");
+                       if (tmp)
+                               name = tmp;
+               }
+               name = strsep(&name, ".");
+
+               /* Quirk: replace '-' with '_' in sound modules */
+               for (len = strlen(name); len; len--) {
+                       if (*(name+len) == '-')
+                               *(name+len) = '_';
+               }
+
+               module = module__new(name, path);
+               if (!module) {
+                       fprintf(stderr, "load_module_paths: allocation error\n");
+                       goto out_failure;
+               }
+               mod_dso__insert_module(self, module);
+
+               module->sections = sec_dso__new_dso("sections");
+               if (!module->sections) {
+                       fprintf(stderr, "load_module_paths: allocation error\n");
+                       goto out_failure;
+               }
+
+               module->active = mod_dso__load_sections(module);
+
+               if (module->active > 0)
+                       count++;
+       }
+
+       free(line);
+       fclose(file);
+
+       return count;
+
+out_failure:
+       return -1;
+}
+
+int mod_dso__load_modules(struct mod_dso *dso)
+{
+       int err;
+
+       err = mod_dso__load_module_paths(dso);
+
+       return err;
+}
diff --git a/tools/perf/util/module.h b/tools/perf/util/module.h
new file mode 100644 (file)
index 0000000..8a592ef
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef _PERF_MODULE_
+#define _PERF_MODULE_ 1
+
+#include <linux/types.h>
+#include "../types.h"
+#include <linux/list.h>
+#include <linux/rbtree.h>
+
+struct section {
+       struct rb_node  rb_node;
+       u64             hash;
+       u64             vma;
+       char            *name;
+       char            *path;
+};
+
+struct sec_dso {
+       struct list_head node;
+       struct rb_root   secs;
+       struct section    *(*find_section)(struct sec_dso *, const char *name);
+       char             name[0];
+};
+
+struct module {
+       struct rb_node  rb_node;
+       u64             hash;
+       char            *name;
+       char            *path;
+       struct sec_dso  *sections;
+       int             active;
+};
+
+struct mod_dso {
+       struct list_head node;
+       struct rb_root   mods;
+       struct module    *(*find_module)(struct mod_dso *, const char *name);
+       char             name[0];
+};
+
+struct sec_dso *sec_dso__new_dso(const char *name);
+void sec_dso__delete_sections(struct sec_dso *self);
+void sec_dso__delete_self(struct sec_dso *self);
+size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp);
+struct section *sec_dso__find_section(struct sec_dso *self, const char *name);
+
+struct mod_dso *mod_dso__new_dso(const char *name);
+void mod_dso__delete_modules(struct mod_dso *self);
+void mod_dso__delete_self(struct mod_dso *self);
+size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp);
+struct module *mod_dso__find_module(struct mod_dso *self, const char *name);
+int mod_dso__load_modules(struct mod_dso *dso);
+
+#endif /* _PERF_MODULE_ */
index a28bccae5458b3015fdbcfe0e458746d5b2db23b..1915de20dcacf28e3dd037ca5b5f462577b561b5 100644 (file)
@@ -9,7 +9,6 @@
 
 static int spawned_pager;
 
-#ifndef __MINGW32__
 static void pager_preexec(void)
 {
        /*
@@ -24,7 +23,6 @@ static void pager_preexec(void)
 
        setenv("LESS", "FRSX", 0);
 }
-#endif
 
 static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
 static struct child_process pager_process;
@@ -70,9 +68,8 @@ void setup_pager(void)
        pager_argv[2] = pager;
        pager_process.argv = pager_argv;
        pager_process.in = -1;
-#ifndef __MINGW32__
        pager_process.preexec_cb = pager_preexec;
-#endif
+
        if (start_command(&pager_process))
                return;
 
index 35d04da38d6a156de599a5ca157c73fb5fe203ca..044178408783004c66429f48f75e937d61e32e8a 100644 (file)
@@ -5,6 +5,7 @@
 #include "parse-events.h"
 #include "exec_cmd.h"
 #include "string.h"
+#include "cache.h"
 
 extern char *strcasestr(const char *haystack, const char *needle);
 
@@ -16,32 +17,30 @@ struct event_symbol {
        u8      type;
        u64     config;
        char    *symbol;
+       char    *alias;
 };
 
-#define C(x, y) .type = PERF_TYPE_##x, .config = PERF_COUNT_##y
-#define CR(x, y) .type = PERF_TYPE_##x, .config = y
+char debugfs_path[MAXPATHLEN];
+
+#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
+#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
 
 static struct event_symbol event_symbols[] = {
-  { C(HARDWARE, HW_CPU_CYCLES),                "cpu-cycles",           },
-  { C(HARDWARE, HW_CPU_CYCLES),                "cycles",               },
-  { C(HARDWARE, HW_INSTRUCTIONS),      "instructions",         },
-  { C(HARDWARE, HW_CACHE_REFERENCES),  "cache-references",     },
-  { C(HARDWARE, HW_CACHE_MISSES),      "cache-misses",         },
-  { C(HARDWARE, HW_BRANCH_INSTRUCTIONS),"branch-instructions", },
-  { C(HARDWARE, HW_BRANCH_INSTRUCTIONS),"branches",            },
-  { C(HARDWARE, HW_BRANCH_MISSES),     "branch-misses",        },
-  { C(HARDWARE, HW_BUS_CYCLES),                "bus-cycles",           },
-
-  { C(SOFTWARE, SW_CPU_CLOCK),         "cpu-clock",            },
-  { C(SOFTWARE, SW_TASK_CLOCK),                "task-clock",           },
-  { C(SOFTWARE, SW_PAGE_FAULTS),       "page-faults",          },
-  { C(SOFTWARE, SW_PAGE_FAULTS),       "faults",               },
-  { C(SOFTWARE, SW_PAGE_FAULTS_MIN),   "minor-faults",         },
-  { C(SOFTWARE, SW_PAGE_FAULTS_MAJ),   "major-faults",         },
-  { C(SOFTWARE, SW_CONTEXT_SWITCHES),  "context-switches",     },
-  { C(SOFTWARE, SW_CONTEXT_SWITCHES),  "cs",                   },
-  { C(SOFTWARE, SW_CPU_MIGRATIONS),    "cpu-migrations",       },
-  { C(SOFTWARE, SW_CPU_MIGRATIONS),    "migrations",           },
+  { CHW(CPU_CYCLES),           "cpu-cycles",           "cycles"        },
+  { CHW(INSTRUCTIONS),         "instructions",         ""              },
+  { CHW(CACHE_REFERENCES),     "cache-references",     ""              },
+  { CHW(CACHE_MISSES),         "cache-misses",         ""              },
+  { CHW(BRANCH_INSTRUCTIONS),  "branch-instructions",  "branches"      },
+  { CHW(BRANCH_MISSES),                "branch-misses",        ""              },
+  { CHW(BUS_CYCLES),           "bus-cycles",           ""              },
+
+  { CSW(CPU_CLOCK),            "cpu-clock",            ""              },
+  { CSW(TASK_CLOCK),           "task-clock",           ""              },
+  { CSW(PAGE_FAULTS),          "page-faults",          "faults"        },
+  { CSW(PAGE_FAULTS_MIN),      "minor-faults",         ""              },
+  { CSW(PAGE_FAULTS_MAJ),      "major-faults",         ""              },
+  { CSW(CONTEXT_SWITCHES),     "context-switches",     "cs"            },
+  { CSW(CPU_MIGRATIONS),       "cpu-migrations",       "migrations"    },
 };
 
 #define __PERF_COUNTER_FIELD(config, name) \
@@ -74,33 +73,181 @@ static char *sw_event_names[] = {
 
 #define MAX_ALIASES 8
 
-static char *hw_cache [][MAX_ALIASES] = {
      { "L1-data"             , "l1-d", "l1d"                                 },
      { "L1-instruction"      , "l1-i", "l1i"                                 },
      { "L2"                  , "l2"                                          },
      { "Data-TLB"            , "dtlb", "d-tlb"                               },
      { "Instruction-TLB"     , "itlb", "i-tlb"                               },
      { "Branch"              , "bpu" , "btb", "bpc"                          },
+static char *hw_cache[][MAX_ALIASES] = {
{ "L1-dcache",        "l1-d",         "l1d",          "L1-data",              },
{ "L1-icache",        "l1-i",         "l1i",          "L1-instruction",       },
{ "LLC",      "L2"                                                    },
{ "dTLB",     "d-tlb",        "Data-TLB",                             },
{ "iTLB",     "i-tlb",        "Instruction-TLB",                      },
{ "branch",   "branches",     "bpu",          "btb",          "bpc",  },
 };
 
-static char *hw_cache_op [][MAX_ALIASES] = {
      { "Load"                , "read"                                        },
      { "Store"               , "write"                                       },
      { "Prefetch"            , "speculative-read", "speculative-load"        },
+static char *hw_cache_op[][MAX_ALIASES] = {
{ "load",     "loads",        "read",                                 },
{ "store",    "stores",       "write",                                },
{ "prefetch", "prefetches",   "speculative-read", "speculative-load", },
 };
 
-static char *hw_cache_result [][MAX_ALIASES] = {
      { "Reference"           , "ops", "access"                               },
      { "Miss"                                                                },
+static char *hw_cache_result[][MAX_ALIASES] = {
{ "refs",     "Reference",    "ops",          "access",               },
{ "misses",   "miss",                                                 },
 };
 
+#define C(x)           PERF_COUNT_HW_CACHE_##x
+#define CACHE_READ     (1 << C(OP_READ))
+#define CACHE_WRITE    (1 << C(OP_WRITE))
+#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
+#define COP(x)         (1 << x)
+
+/*
+ * cache operartion stat
+ * L1I : Read and prefetch only
+ * ITLB and BPU : Read-only
+ */
+static unsigned long hw_cache_stat[C(MAX)] = {
+ [C(L1D)]      = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
+ [C(L1I)]      = (CACHE_READ | CACHE_PREFETCH),
+ [C(LL)]       = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
+ [C(DTLB)]     = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
+ [C(ITLB)]     = (CACHE_READ),
+ [C(BPU)]      = (CACHE_READ),
+};
+
+#define for_each_subsystem(sys_dir, sys_dirent, sys_next, file, st)           \
+       while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)        \
+       if (snprintf(file, MAXPATHLEN, "%s/%s", debugfs_path,                  \
+                       sys_dirent.d_name) &&                                  \
+          (!stat(file, &st)) && (S_ISDIR(st.st_mode)) &&                      \
+          (strcmp(sys_dirent.d_name, ".")) &&                                 \
+          (strcmp(sys_dirent.d_name, "..")))
+
+static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
+{
+       char evt_path[MAXPATHLEN];
+       int fd;
+
+       snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
+                       sys_dir->d_name, evt_dir->d_name);
+       fd = open(evt_path, O_RDONLY);
+       if (fd < 0)
+               return -EINVAL;
+       close(fd);
+
+       return 0;
+}
+
+#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st)    \
+       while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next)        \
+       if (snprintf(file, MAXPATHLEN, "%s/%s/%s", debugfs_path,               \
+                    sys_dirent.d_name, evt_dirent.d_name) &&                  \
+          (!stat(file, &st)) && (S_ISDIR(st.st_mode)) &&                      \
+          (strcmp(evt_dirent.d_name, ".")) &&                                 \
+          (strcmp(evt_dirent.d_name, "..")) &&                                \
+          (!tp_event_has_id(&sys_dirent, &evt_dirent)))
+
+#define MAX_EVENT_LENGTH 30
+
+int valid_debugfs_mount(const char *debugfs)
+{
+       struct statfs st_fs;
+
+       if (statfs(debugfs, &st_fs) < 0)
+               return -ENOENT;
+       else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
+               return -ENOENT;
+       return 0;
+}
+
+static char *tracepoint_id_to_name(u64 config)
+{
+       static char tracepoint_name[2 * MAX_EVENT_LENGTH];
+       DIR *sys_dir, *evt_dir;
+       struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
+       struct stat st;
+       char id_buf[4];
+       int fd;
+       u64 id;
+       char evt_path[MAXPATHLEN];
+
+       if (valid_debugfs_mount(debugfs_path))
+               return "unkown";
+
+       sys_dir = opendir(debugfs_path);
+       if (!sys_dir)
+               goto cleanup;
+
+       for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) {
+               evt_dir = opendir(evt_path);
+               if (!evt_dir)
+                       goto cleanup;
+               for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
+                                                               evt_path, st) {
+                       snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id",
+                                debugfs_path, sys_dirent.d_name,
+                                evt_dirent.d_name);
+                       fd = open(evt_path, O_RDONLY);
+                       if (fd < 0)
+                               continue;
+                       if (read(fd, id_buf, sizeof(id_buf)) < 0) {
+                               close(fd);
+                               continue;
+                       }
+                       close(fd);
+                       id = atoll(id_buf);
+                       if (id == config) {
+                               closedir(evt_dir);
+                               closedir(sys_dir);
+                               snprintf(tracepoint_name, 2 * MAX_EVENT_LENGTH,
+                                       "%s:%s", sys_dirent.d_name,
+                                       evt_dirent.d_name);
+                               return tracepoint_name;
+                       }
+               }
+               closedir(evt_dir);
+       }
+
+cleanup:
+       closedir(sys_dir);
+       return "unkown";
+}
+
+static int is_cache_op_valid(u8 cache_type, u8 cache_op)
+{
+       if (hw_cache_stat[cache_type] & COP(cache_op))
+               return 1;       /* valid */
+       else
+               return 0;       /* invalid */
+}
+
+static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
+{
+       static char name[50];
+
+       if (cache_result) {
+               sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
+                       hw_cache_op[cache_op][0],
+                       hw_cache_result[cache_result][0]);
+       } else {
+               sprintf(name, "%s-%s", hw_cache[cache_type][0],
+                       hw_cache_op[cache_op][1]);
+       }
+
+       return name;
+}
+
 char *event_name(int counter)
 {
        u64 config = attrs[counter].config;
        int type = attrs[counter].type;
+
+       return __event_name(type, config);
+}
+
+char *__event_name(int type, u64 config)
+{
        static char buf[32];
 
-       if (attrs[counter].type == PERF_TYPE_RAW) {
+       if (type == PERF_TYPE_RAW) {
                sprintf(buf, "raw 0x%llx", config);
                return buf;
        }
@@ -113,7 +260,6 @@ char *event_name(int counter)
 
        case PERF_TYPE_HW_CACHE: {
                u8 cache_type, cache_op, cache_result;
-               static char name[100];
 
                cache_type   = (config >>  0) & 0xff;
                if (cache_type > PERF_COUNT_HW_CACHE_MAX)
@@ -127,12 +273,10 @@ char *event_name(int counter)
                if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
                        return "unknown-ext-hardware-cache-result";
 
-               sprintf(name, "%s-Cache-%s-%ses",
-                       hw_cache[cache_type][0],
-                       hw_cache_op[cache_op][0],
-                       hw_cache_result[cache_result][0]);
+               if (!is_cache_op_valid(cache_type, cache_op))
+                       return "invalid-cache";
 
-               return name;
+               return event_cache_name(cache_type, cache_op, cache_result);
        }
 
        case PERF_TYPE_SOFTWARE:
@@ -140,6 +284,9 @@ char *event_name(int counter)
                        return sw_event_names[config];
                return "unknown-software";
 
+       case PERF_TYPE_TRACEPOINT:
+               return tracepoint_id_to_name(config);
+
        default:
                break;
        }
@@ -147,43 +294,74 @@ char *event_name(int counter)
        return "unknown";
 }
 
-static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size)
+static int parse_aliases(const char **str, char *names[][MAX_ALIASES], int size)
 {
        int i, j;
+       int n, longest = -1;
 
        for (i = 0; i < size; i++) {
-               for (j = 0; j < MAX_ALIASES; j++) {
-                       if (!names[i][j])
-                               break;
-                       if (strcasestr(str, names[i][j]))
-                               return i;
+               for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
+                       n = strlen(names[i][j]);
+                       if (n > longest && !strncasecmp(*str, names[i][j], n))
+                               longest = n;
+               }
+               if (longest > 0) {
+                       *str += longest;
+                       return i;
                }
        }
 
        return -1;
 }
 
-static int parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr)
+static int
+parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
 {
-       int cache_type = -1, cache_op = 0, cache_result = 0;
+       const char *s = *str;
+       int cache_type = -1, cache_op = -1, cache_result = -1;
 
-       cache_type = parse_aliases(str, hw_cache, PERF_COUNT_HW_CACHE_MAX);
+       cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX);
        /*
         * No fallback - if we cannot get a clear cache type
         * then bail out:
         */
        if (cache_type == -1)
-               return -EINVAL;
+               return 0;
+
+       while ((cache_op == -1 || cache_result == -1) && *s == '-') {
+               ++s;
+
+               if (cache_op == -1) {
+                       cache_op = parse_aliases(&s, hw_cache_op,
+                                               PERF_COUNT_HW_CACHE_OP_MAX);
+                       if (cache_op >= 0) {
+                               if (!is_cache_op_valid(cache_type, cache_op))
+                                       return 0;
+                               continue;
+                       }
+               }
+
+               if (cache_result == -1) {
+                       cache_result = parse_aliases(&s, hw_cache_result,
+                                               PERF_COUNT_HW_CACHE_RESULT_MAX);
+                       if (cache_result >= 0)
+                               continue;
+               }
+
+               /*
+                * Can't parse this as a cache op or result, so back up
+                * to the '-'.
+                */
+               --s;
+               break;
+       }
 
-       cache_op = parse_aliases(str, hw_cache_op, PERF_COUNT_HW_CACHE_OP_MAX);
        /*
         * Fall back to reads:
         */
        if (cache_op == -1)
                cache_op = PERF_COUNT_HW_CACHE_OP_READ;
 
-       cache_result = parse_aliases(str, hw_cache_result,
-                                       PERF_COUNT_HW_CACHE_RESULT_MAX);
        /*
         * Fall back to accesses:
         */
@@ -193,82 +371,212 @@ static int parse_generic_hw_symbols(const char *str, struct perf_counter_attr *a
        attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
        attr->type = PERF_TYPE_HW_CACHE;
 
-       return 0;
+       *str = s;
+       return 1;
 }
 
-/*
- * Each event can have multiple symbolic names.
- * Symbolic names are (almost) exactly matched.
- */
-static int parse_event_symbols(const char *str, struct perf_counter_attr *attr)
+static int parse_tracepoint_event(const char **strp,
+                                   struct perf_counter_attr *attr)
 {
-       u64 config, id;
-       int type;
-       unsigned int i;
-       const char *sep, *pstr;
+       const char *evt_name;
+       char *flags;
+       char sys_name[MAX_EVENT_LENGTH];
+       char id_buf[4];
+       int fd;
+       unsigned int sys_length, evt_length;
+       u64 id;
+       char evt_path[MAXPATHLEN];
+
+       if (valid_debugfs_mount(debugfs_path))
+               return 0;
 
-       if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) {
-               attr->type = PERF_TYPE_RAW;
-               attr->config = config;
+       evt_name = strchr(*strp, ':');
+       if (!evt_name)
+               return 0;
 
+       sys_length = evt_name - *strp;
+       if (sys_length >= MAX_EVENT_LENGTH)
                return 0;
+
+       strncpy(sys_name, *strp, sys_length);
+       sys_name[sys_length] = '\0';
+       evt_name = evt_name + 1;
+
+       flags = strchr(evt_name, ':');
+       if (flags) {
+               *flags = '\0';
+               flags++;
+               if (!strncmp(flags, "record", strlen(flags)))
+                       attr->sample_type |= PERF_SAMPLE_RAW;
        }
 
-       pstr = str;
-       sep = strchr(pstr, ':');
-       if (sep) {
-               type = atoi(pstr);
-               pstr = sep + 1;
-               id = atoi(pstr);
-               sep = strchr(pstr, ':');
-               if (sep) {
-                       pstr = sep + 1;
-                       if (strchr(pstr, 'k'))
-                               attr->exclude_user = 1;
-                       if (strchr(pstr, 'u'))
-                               attr->exclude_kernel = 1;
-               }
-               attr->type = type;
-               attr->config = id;
+       evt_length = strlen(evt_name);
+       if (evt_length >= MAX_EVENT_LENGTH)
+               return 0;
 
+       snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
+                sys_name, evt_name);
+       fd = open(evt_path, O_RDONLY);
+       if (fd < 0)
+               return 0;
+
+       if (read(fd, id_buf, sizeof(id_buf)) < 0) {
+               close(fd);
                return 0;
        }
+       close(fd);
+       id = atoll(id_buf);
+       attr->config = id;
+       attr->type = PERF_TYPE_TRACEPOINT;
+       *strp = evt_name + evt_length;
+       return 1;
+}
 
-       for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
-               if (!strncmp(str, event_symbols[i].symbol,
-                            strlen(event_symbols[i].symbol))) {
+static int check_events(const char *str, unsigned int i)
+{
+       int n;
+
+       n = strlen(event_symbols[i].symbol);
+       if (!strncmp(str, event_symbols[i].symbol, n))
+               return n;
+
+       n = strlen(event_symbols[i].alias);
+       if (n)
+               if (!strncmp(str, event_symbols[i].alias, n))
+                       return n;
+       return 0;
+}
+
+static int
+parse_symbolic_event(const char **strp, struct perf_counter_attr *attr)
+{
+       const char *str = *strp;
+       unsigned int i;
+       int n;
 
+       for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
+               n = check_events(str, i);
+               if (n > 0) {
                        attr->type = event_symbols[i].type;
                        attr->config = event_symbols[i].config;
+                       *strp = str + n;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static int parse_raw_event(const char **strp, struct perf_counter_attr *attr)
+{
+       const char *str = *strp;
+       u64 config;
+       int n;
+
+       if (*str != 'r')
+               return 0;
+       n = hex2u64(str + 1, &config);
+       if (n > 0) {
+               *strp = str + n + 1;
+               attr->type = PERF_TYPE_RAW;
+               attr->config = config;
+               return 1;
+       }
+       return 0;
+}
 
-                       return 0;
+static int
+parse_numeric_event(const char **strp, struct perf_counter_attr *attr)
+{
+       const char *str = *strp;
+       char *endp;
+       unsigned long type;
+       u64 config;
+
+       type = strtoul(str, &endp, 0);
+       if (endp > str && type < PERF_TYPE_MAX && *endp == ':') {
+               str = endp + 1;
+               config = strtoul(str, &endp, 0);
+               if (endp > str) {
+                       attr->type = type;
+                       attr->config = config;
+                       *strp = endp;
+                       return 1;
                }
        }
+       return 0;
+}
+
+static int
+parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
+{
+       const char *str = *strp;
+       int eu = 1, ek = 1, eh = 1;
+
+       if (*str++ != ':')
+               return 0;
+       while (*str) {
+               if (*str == 'u')
+                       eu = 0;
+               else if (*str == 'k')
+                       ek = 0;
+               else if (*str == 'h')
+                       eh = 0;
+               else
+                       break;
+               ++str;
+       }
+       if (str >= *strp + 2) {
+               *strp = str;
+               attr->exclude_user   = eu;
+               attr->exclude_kernel = ek;
+               attr->exclude_hv     = eh;
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * Each event can have multiple symbolic names.
+ * Symbolic names are (almost) exactly matched.
+ */
+static int parse_event_symbols(const char **str, struct perf_counter_attr *attr)
+{
+       if (!(parse_tracepoint_event(str, attr) ||
+             parse_raw_event(str, attr) ||
+             parse_numeric_event(str, attr) ||
+             parse_symbolic_event(str, attr) ||
+             parse_generic_hw_event(str, attr)))
+               return 0;
 
-       return parse_generic_hw_symbols(str, attr);
+       parse_event_modifier(str, attr);
+
+       return 1;
 }
 
-int parse_events(const struct option *opt, const char *str, int unset)
+int parse_events(const struct option *opt __used, const char *str, int unset __used)
 {
        struct perf_counter_attr attr;
-       int ret;
 
-       memset(&attr, 0, sizeof(attr));
-again:
-       if (nr_counters == MAX_COUNTERS)
-               return -1;
+       for (;;) {
+               if (nr_counters == MAX_COUNTERS)
+                       return -1;
+
+               memset(&attr, 0, sizeof(attr));
+               if (!parse_event_symbols(&str, &attr))
+                       return -1;
 
-       ret = parse_event_symbols(str, &attr);
-       if (ret < 0)
-               return ret;
+               if (!(*str == 0 || *str == ',' || isspace(*str)))
+                       return -1;
 
-       attrs[nr_counters] = attr;
-       nr_counters++;
+               attrs[nr_counters] = attr;
+               nr_counters++;
 
-       str = strstr(str, ",");
-       if (str) {
-               str++;
-               goto again;
+               if (*str == 0)
+                       break;
+               if (*str == ',')
+                       ++str;
+               while (isspace(*str))
+                       ++str;
        }
 
        return 0;
@@ -282,35 +590,93 @@ static const char * const event_type_descriptors[] = {
        "Hardware cache event",
 };
 
+/*
+ * Print the events from <debugfs_mount_point>/tracing/events
+ */
+
+static void print_tracepoint_events(void)
+{
+       DIR *sys_dir, *evt_dir;
+       struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
+       struct stat st;
+       char evt_path[MAXPATHLEN];
+
+       if (valid_debugfs_mount(debugfs_path))
+               return;
+
+       sys_dir = opendir(debugfs_path);
+       if (!sys_dir)
+               goto cleanup;
+
+       for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) {
+               evt_dir = opendir(evt_path);
+               if (!evt_dir)
+                       goto cleanup;
+               for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
+                                                               evt_path, st) {
+                       snprintf(evt_path, MAXPATHLEN, "%s:%s",
+                                sys_dirent.d_name, evt_dirent.d_name);
+                       fprintf(stderr, "  %-40s [%s]\n", evt_path,
+                               event_type_descriptors[PERF_TYPE_TRACEPOINT+1]);
+               }
+               closedir(evt_dir);
+       }
+
+cleanup:
+       closedir(sys_dir);
+}
+
 /*
  * Print the help text for the event symbols:
  */
 void print_events(void)
 {
        struct event_symbol *syms = event_symbols;
-       unsigned int i, type, prev_type = -1;
+       unsigned int i, type, op, prev_type = -1;
+       char name[40];
 
        fprintf(stderr, "\n");
        fprintf(stderr, "List of pre-defined events (to be used in -e):\n");
 
        for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
                type = syms->type + 1;
-               if (type > ARRAY_SIZE(event_type_descriptors))
+               if (type >= ARRAY_SIZE(event_type_descriptors))
                        type = 0;
 
                if (type != prev_type)
                        fprintf(stderr, "\n");
 
-               fprintf(stderr, "  %-30s [%s]\n", syms->symbol,
+               if (strlen(syms->alias))
+                       sprintf(name, "%s OR %s", syms->symbol, syms->alias);
+               else
+                       strcpy(name, syms->symbol);
+               fprintf(stderr, "  %-40s [%s]\n", name,
                        event_type_descriptors[type]);
 
                prev_type = type;
        }
 
        fprintf(stderr, "\n");
-       fprintf(stderr, "  %-30s [raw hardware event descriptor]\n",
+       for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
+               for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
+                       /* skip invalid cache type */
+                       if (!is_cache_op_valid(type, op))
+                               continue;
+
+                       for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
+                               fprintf(stderr, "  %-40s [%s]\n",
+                                       event_cache_name(type, op, i),
+                                       event_type_descriptors[4]);
+                       }
+               }
+       }
+
+       fprintf(stderr, "\n");
+       fprintf(stderr, "  %-40s [raw hardware event descriptor]\n",
                "rNNN");
        fprintf(stderr, "\n");
 
+       print_tracepoint_events();
+
        exit(129);
 }
index e3d552908e60015517316d2d91cba6324c8fbc2f..192a962e3a0fbe15b294dc6f1f5e9e787f68e32e 100644 (file)
@@ -3,11 +3,14 @@
  * Parse symbolic events/counts passed in as options:
  */
 
+struct option;
+
 extern int                     nr_counters;
 
 extern struct perf_counter_attr attrs[MAX_COUNTERS];
 
 extern char *event_name(int ctr);
+extern char *__event_name(int type, u64 config);
 
 extern int parse_events(const struct option *opt, const char *str, int unset);
 
@@ -15,3 +18,6 @@ extern int parse_events(const struct option *opt, const char *str, int unset);
 
 extern void print_events(void);
 
+extern char debugfs_path[];
+extern int valid_debugfs_mount(const char *debugfs);
+
index b3affb1658d2a1646aea5680a941c9701df27e1b..1bf67190c820041edb9e751c3aa56713394fcdce 100644 (file)
@@ -20,7 +20,8 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
        if (p->opt) {
                *arg = p->opt;
                p->opt = NULL;
-       } else if (p->argc == 1 && (opt->flags & PARSE_OPT_LASTARG_DEFAULT)) {
+       } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
+                   **(p->argv + 1) == '-')) {
                *arg = (const char *)opt->defval;
        } else if (p->argc > 1) {
                p->argc--;
@@ -485,7 +486,7 @@ int parse_options_usage(const char * const *usagestr,
 }
 
 
-int parse_opt_verbosity_cb(const struct option *opt, const char *arg,
+int parse_opt_verbosity_cb(const struct option *opt, const char *arg __used,
                           int unset)
 {
        int *target = opt->value;
index a1039a6ce0ebabdc561fc1b061e3e2ead566cc83..8aa3464c709054ba8b6275f39d3bead3873f5936 100644 (file)
@@ -90,21 +90,22 @@ struct option {
        intptr_t defval;
 };
 
-#define OPT_END()                   { OPTION_END }
-#define OPT_ARGUMENT(l, h)          { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) }
-#define OPT_GROUP(h)                { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
-#define OPT_BIT(s, l, v, h, b)      { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) }
-#define OPT_BOOLEAN(s, l, v, h)     { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) }
-#define OPT_SET_INT(s, l, v, h, i)  { OPTION_SET_INT, (s), (l), (v), NULL, (h), 0, NULL, (i) }
-#define OPT_SET_PTR(s, l, v, h, p)  { OPTION_SET_PTR, (s), (l), (v), NULL, (h), 0, NULL, (p) }
-#define OPT_INTEGER(s, l, v, h)     { OPTION_INTEGER, (s), (l), (v), NULL, (h) }
-#define OPT_LONG(s, l, v, h)        { OPTION_LONG, (s), (l), (v), NULL, (h) }
-#define OPT_STRING(s, l, v, a, h)   { OPTION_STRING,  (s), (l), (v), (a), (h) }
+#define OPT_END()                   { .type = OPTION_END }
+#define OPT_ARGUMENT(l, h)          { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) }
+#define OPT_GROUP(h)                { .type = OPTION_GROUP, .help = (h) }
+#define OPT_BIT(s, l, v, h, b)      { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (b) }
+#define OPT_BOOLEAN(s, l, v, h)     { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = (v), .help = (h) }
+#define OPT_SET_INT(s, l, v, h, i)  { .type = OPTION_SET_INT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (i) }
+#define OPT_SET_PTR(s, l, v, h, p)  { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) }
+#define OPT_INTEGER(s, l, v, h)     { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = (v), .help = (h) }
+#define OPT_LONG(s, l, v, h)        { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = (v), .help = (h) }
+#define OPT_STRING(s, l, v, a, h)   { .type = OPTION_STRING,  .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h) }
 #define OPT_DATE(s, l, v, h) \
-       { OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \
-         parse_opt_approxidate_cb }
+       { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
 #define OPT_CALLBACK(s, l, v, a, h, f) \
-       { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) }
+       { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) }
+#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \
+       { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT }
 
 /* parse_options() will filter out the processed options and leave the
  * non-option argments in argv[].
index f18c5212bc92b8a89437a65fbdd83c0928266110..2726fe40eb5dd2483d16ab3064caa91eea92c62e 100644 (file)
@@ -162,12 +162,16 @@ static inline int sq_must_quote(char c)
        return sq_lookup[(unsigned char)c] + quote_path_fully > 0;
 }
 
-/* returns the longest prefix not needing a quote up to maxlen if positive.
-   This stops at the first \0 because it's marked as a character needing an
-   escape */
-static size_t next_quote_pos(const char *s, ssize_t maxlen)
+/*
+ * Returns the longest prefix not needing a quote up to maxlen if
+ * positive.
+ * This stops at the first \0 because it's marked as a character
+ * needing an escape.
+ */
+static ssize_t next_quote_pos(const char *s, ssize_t maxlen)
 {
-       size_t len;
+       ssize_t len;
+
        if (maxlen < 0) {
                for (len = 0; !sq_must_quote(s[len]); len++);
        } else {
@@ -192,22 +196,22 @@ static size_t next_quote_pos(const char *s, ssize_t maxlen)
 static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
                                     struct strbuf *sb, FILE *fp, int no_dq)
 {
-#undef EMIT
-#define EMIT(c)                                 \
-       do {                                        \
-               if (sb) strbuf_addch(sb, (c));          \
-               if (fp) fputc((c), fp);                 \
-               count++;                                \
+#define EMIT(c)                                                        \
+       do {                                                    \
+               if (sb) strbuf_addch(sb, (c));                  \
+               if (fp) fputc((c), fp);                         \
+               count++;                                        \
        } while (0)
-#define EMITBUF(s, l)                           \
-       do {                                        \
-               int __ret;                              \
-               if (sb) strbuf_add(sb, (s), (l));       \
-               if (fp) __ret = fwrite((s), (l), 1, fp);        \
-               count += (l);                           \
+
+#define EMITBUF(s, l)                                          \
+       do {                                                    \
+               int __ret;                                      \
+               if (sb) strbuf_add(sb, (s), (l));               \
+               if (fp) __ret = fwrite((s), (l), 1, fp);        \
+               count += (l);                                   \
        } while (0)
 
-       size_t len, count = 0;
+       ssize_t len, count = 0;
        const char *p = name;
 
        for (;;) {
@@ -273,8 +277,8 @@ void write_name_quoted(const char *name, FILE *fp, int terminator)
        fputc(terminator, fp);
 }
 
-extern void write_name_quotedpfx(const char *pfx, size_t pfxlen,
-                                 const char *name, FILE *fp, int terminator)
+void write_name_quotedpfx(const char *pfx, ssize_t pfxlen,
+                         const char *name, FILE *fp, int terminator)
 {
        int needquote = 0;
 
@@ -306,7 +310,7 @@ char *quote_path_relative(const char *in, int len,
                len = strlen(in);
 
        /* "../" prefix itself does not need quoting, but "in" might. */
-       needquote = next_quote_pos(in, len) < len;
+       needquote = (next_quote_pos(in, len) < len);
        strbuf_setlen(out, 0);
        strbuf_grow(out, len);
 
@@ -314,7 +318,7 @@ char *quote_path_relative(const char *in, int len,
                strbuf_addch(out, '"');
        if (prefix) {
                int off = 0;
-               while (prefix[off] && off < len && prefix[off] == in[off])
+               while (off < len && prefix[off] && prefix[off] == in[off])
                        if (prefix[off] == '/') {
                                prefix += off + 1;
                                in += off + 1;
index 5dfad89816db124e9b18abc7d2964997a55a329b..a5454a1d1c137ba3640add2945f1be186727d36c 100644 (file)
@@ -53,7 +53,7 @@ extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq
 extern void quote_two_c_style(struct strbuf *, const char *, const char *, int);
 
 extern void write_name_quoted(const char *name, FILE *, int terminator);
-extern void write_name_quotedpfx(const char *pfx, size_t pfxlen,
+extern void write_name_quotedpfx(const char *pfx, ssize_t pfxlen,
                                  const char *name, FILE *, int terminator);
 
 /* quote path as relative to the given prefix */
diff --git a/tools/perf/util/rbtree.c b/tools/perf/util/rbtree.c
deleted file mode 100644 (file)
index b15ba9c..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
-  Red Black Trees
-  (C) 1999  Andrea Arcangeli <andrea@suse.de>
-  (C) 2002  David Woodhouse <dwmw2@infradead.org>
-  
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This 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
-
-  linux/lib/rbtree.c
-*/
-
-#include "rbtree.h"
-
-static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
-{
-       struct rb_node *right = node->rb_right;
-       struct rb_node *parent = rb_parent(node);
-
-       if ((node->rb_right = right->rb_left))
-               rb_set_parent(right->rb_left, node);
-       right->rb_left = node;
-
-       rb_set_parent(right, parent);
-
-       if (parent)
-       {
-               if (node == parent->rb_left)
-                       parent->rb_left = right;
-               else
-                       parent->rb_right = right;
-       }
-       else
-               root->rb_node = right;
-       rb_set_parent(node, right);
-}
-
-static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
-{
-       struct rb_node *left = node->rb_left;
-       struct rb_node *parent = rb_parent(node);
-
-       if ((node->rb_left = left->rb_right))
-               rb_set_parent(left->rb_right, node);
-       left->rb_right = node;
-
-       rb_set_parent(left, parent);
-
-       if (parent)
-       {
-               if (node == parent->rb_right)
-                       parent->rb_right = left;
-               else
-                       parent->rb_left = left;
-       }
-       else
-               root->rb_node = left;
-       rb_set_parent(node, left);
-}
-
-void rb_insert_color(struct rb_node *node, struct rb_root *root)
-{
-       struct rb_node *parent, *gparent;
-
-       while ((parent = rb_parent(node)) && rb_is_red(parent))
-       {
-               gparent = rb_parent(parent);
-
-               if (parent == gparent->rb_left)
-               {
-                       {
-                               register struct rb_node *uncle = gparent->rb_right;
-                               if (uncle && rb_is_red(uncle))
-                               {
-                                       rb_set_black(uncle);
-                                       rb_set_black(parent);
-                                       rb_set_red(gparent);
-                                       node = gparent;
-                                       continue;
-                               }
-                       }
-
-                       if (parent->rb_right == node)
-                       {
-                               register struct rb_node *tmp;
-                               __rb_rotate_left(parent, root);
-                               tmp = parent;
-                               parent = node;
-                               node = tmp;
-                       }
-
-                       rb_set_black(parent);
-                       rb_set_red(gparent);
-                       __rb_rotate_right(gparent, root);
-               } else {
-                       {
-                               register struct rb_node *uncle = gparent->rb_left;
-                               if (uncle && rb_is_red(uncle))
-                               {
-                                       rb_set_black(uncle);
-                                       rb_set_black(parent);
-                                       rb_set_red(gparent);
-                                       node = gparent;
-                                       continue;
-                               }
-                       }
-
-                       if (parent->rb_left == node)
-                       {
-                               register struct rb_node *tmp;
-                               __rb_rotate_right(parent, root);
-                               tmp = parent;
-                               parent = node;
-                               node = tmp;
-                       }
-
-                       rb_set_black(parent);
-                       rb_set_red(gparent);
-                       __rb_rotate_left(gparent, root);
-               }
-       }
-
-       rb_set_black(root->rb_node);
-}
-
-static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
-                            struct rb_root *root)
-{
-       struct rb_node *other;
-
-       while ((!node || rb_is_black(node)) && node != root->rb_node)
-       {
-               if (parent->rb_left == node)
-               {
-                       other = parent->rb_right;
-                       if (rb_is_red(other))
-                       {
-                               rb_set_black(other);
-                               rb_set_red(parent);
-                               __rb_rotate_left(parent, root);
-                               other = parent->rb_right;
-                       }
-                       if ((!other->rb_left || rb_is_black(other->rb_left)) &&
-                           (!other->rb_right || rb_is_black(other->rb_right)))
-                       {
-                               rb_set_red(other);
-                               node = parent;
-                               parent = rb_parent(node);
-                       }
-                       else
-                       {
-                               if (!other->rb_right || rb_is_black(other->rb_right))
-                               {
-                                       rb_set_black(other->rb_left);
-                                       rb_set_red(other);
-                                       __rb_rotate_right(other, root);
-                                       other = parent->rb_right;
-                               }
-                               rb_set_color(other, rb_color(parent));
-                               rb_set_black(parent);
-                               rb_set_black(other->rb_right);
-                               __rb_rotate_left(parent, root);
-                               node = root->rb_node;
-                               break;
-                       }
-               }
-               else
-               {
-                       other = parent->rb_left;
-                       if (rb_is_red(other))
-                       {
-                               rb_set_black(other);
-                               rb_set_red(parent);
-                               __rb_rotate_right(parent, root);
-                               other = parent->rb_left;
-                       }
-                       if ((!other->rb_left || rb_is_black(other->rb_left)) &&
-                           (!other->rb_right || rb_is_black(other->rb_right)))
-                       {
-                               rb_set_red(other);
-                               node = parent;
-                               parent = rb_parent(node);
-                       }
-                       else
-                       {
-                               if (!other->rb_left || rb_is_black(other->rb_left))
-                               {
-                                       rb_set_black(other->rb_right);
-                                       rb_set_red(other);
-                                       __rb_rotate_left(other, root);
-                                       other = parent->rb_left;
-                               }
-                               rb_set_color(other, rb_color(parent));
-                               rb_set_black(parent);
-                               rb_set_black(other->rb_left);
-                               __rb_rotate_right(parent, root);
-                               node = root->rb_node;
-                               break;
-                       }
-               }
-       }
-       if (node)
-               rb_set_black(node);
-}
-
-void rb_erase(struct rb_node *node, struct rb_root *root)
-{
-       struct rb_node *child, *parent;
-       int color;
-
-       if (!node->rb_left)
-               child = node->rb_right;
-       else if (!node->rb_right)
-               child = node->rb_left;
-       else
-       {
-               struct rb_node *old = node, *left;
-
-               node = node->rb_right;
-               while ((left = node->rb_left) != NULL)
-                       node = left;
-               child = node->rb_right;
-               parent = rb_parent(node);
-               color = rb_color(node);
-
-               if (child)
-                       rb_set_parent(child, parent);
-               if (parent == old) {
-                       parent->rb_right = child;
-                       parent = node;
-               } else
-                       parent->rb_left = child;
-
-               node->rb_parent_color = old->rb_parent_color;
-               node->rb_right = old->rb_right;
-               node->rb_left = old->rb_left;
-
-               if (rb_parent(old))
-               {
-                       if (rb_parent(old)->rb_left == old)
-                               rb_parent(old)->rb_left = node;
-                       else
-                               rb_parent(old)->rb_right = node;
-               } else
-                       root->rb_node = node;
-
-               rb_set_parent(old->rb_left, node);
-               if (old->rb_right)
-                       rb_set_parent(old->rb_right, node);
-               goto color;
-       }
-
-       parent = rb_parent(node);
-       color = rb_color(node);
-
-       if (child)
-               rb_set_parent(child, parent);
-       if (parent)
-       {
-               if (parent->rb_left == node)
-                       parent->rb_left = child;
-               else
-                       parent->rb_right = child;
-       }
-       else
-               root->rb_node = child;
-
- color:
-       if (color == RB_BLACK)
-               __rb_erase_color(child, parent, root);
-}
-
-/*
- * This function returns the first node (in sort order) of the tree.
- */
-struct rb_node *rb_first(const struct rb_root *root)
-{
-       struct rb_node  *n;
-
-       n = root->rb_node;
-       if (!n)
-               return NULL;
-       while (n->rb_left)
-               n = n->rb_left;
-       return n;
-}
-
-struct rb_node *rb_last(const struct rb_root *root)
-{
-       struct rb_node  *n;
-
-       n = root->rb_node;
-       if (!n)
-               return NULL;
-       while (n->rb_right)
-               n = n->rb_right;
-       return n;
-}
-
-struct rb_node *rb_next(const struct rb_node *node)
-{
-       struct rb_node *parent;
-
-       if (rb_parent(node) == node)
-               return NULL;
-
-       /* If we have a right-hand child, go down and then left as far
-          as we can. */
-       if (node->rb_right) {
-               node = node->rb_right; 
-               while (node->rb_left)
-                       node=node->rb_left;
-               return (struct rb_node *)node;
-       }
-
-       /* No right-hand children.  Everything down and left is
-          smaller than us, so any 'next' node must be in the general
-          direction of our parent. Go up the tree; any time the
-          ancestor is a right-hand child of its parent, keep going
-          up. First time it's a left-hand child of its parent, said
-          parent is our 'next' node. */
-       while ((parent = rb_parent(node)) && node == parent->rb_right)
-               node = parent;
-
-       return parent;
-}
-
-struct rb_node *rb_prev(const struct rb_node *node)
-{
-       struct rb_node *parent;
-
-       if (rb_parent(node) == node)
-               return NULL;
-
-       /* If we have a left-hand child, go down and then right as far
-          as we can. */
-       if (node->rb_left) {
-               node = node->rb_left; 
-               while (node->rb_right)
-                       node=node->rb_right;
-               return (struct rb_node *)node;
-       }
-
-       /* No left-hand children. Go up till we find an ancestor which
-          is a right-hand child of its parent */
-       while ((parent = rb_parent(node)) && node == parent->rb_left)
-               node = parent;
-
-       return parent;
-}
-
-void rb_replace_node(struct rb_node *victim, struct rb_node *new,
-                    struct rb_root *root)
-{
-       struct rb_node *parent = rb_parent(victim);
-
-       /* Set the surrounding nodes to point to the replacement */
-       if (parent) {
-               if (victim == parent->rb_left)
-                       parent->rb_left = new;
-               else
-                       parent->rb_right = new;
-       } else {
-               root->rb_node = new;
-       }
-       if (victim->rb_left)
-               rb_set_parent(victim->rb_left, new);
-       if (victim->rb_right)
-               rb_set_parent(victim->rb_right, new);
-
-       /* Copy the pointers/colour from the victim to the replacement */
-       *new = *victim;
-}
diff --git a/tools/perf/util/rbtree.h b/tools/perf/util/rbtree.h
deleted file mode 100644 (file)
index 6bdc488..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
-  Red Black Trees
-  (C) 1999  Andrea Arcangeli <andrea@suse.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 the Free Software
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-  linux/include/linux/rbtree.h
-
-  To use rbtrees you'll have to implement your own insert and search cores.
-  This will avoid us to use callbacks and to drop drammatically performances.
-  I know it's not the cleaner way,  but in C (not in C++) to get
-  performances and genericity...
-
-  Some example of insert and search follows here. The search is a plain
-  normal search over an ordered tree. The insert instead must be implemented
-  int two steps: as first thing the code must insert the element in
-  order as a red leaf in the tree, then the support library function
-  rb_insert_color() must be called. Such function will do the
-  not trivial work to rebalance the rbtree if necessary.
-
------------------------------------------------------------------------
-static inline struct page * rb_search_page_cache(struct inode * inode,
-                                                unsigned long offset)
-{
-       struct rb_node * n = inode->i_rb_page_cache.rb_node;
-       struct page * page;
-
-       while (n)
-       {
-               page = rb_entry(n, struct page, rb_page_cache);
-
-               if (offset < page->offset)
-                       n = n->rb_left;
-               else if (offset > page->offset)
-                       n = n->rb_right;
-               else
-                       return page;
-       }
-       return NULL;
-}
-
-static inline struct page * __rb_insert_page_cache(struct inode * inode,
-                                                  unsigned long offset,
-                                                  struct rb_node * node)
-{
-       struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
-       struct rb_node * parent = NULL;
-       struct page * page;
-
-       while (*p)
-       {
-               parent = *p;
-               page = rb_entry(parent, struct page, rb_page_cache);
-
-               if (offset < page->offset)
-                       p = &(*p)->rb_left;
-               else if (offset > page->offset)
-                       p = &(*p)->rb_right;
-               else
-                       return page;
-       }
-
-       rb_link_node(node, parent, p);
-
-       return NULL;
-}
-
-static inline struct page * rb_insert_page_cache(struct inode * inode,
-                                                unsigned long offset,
-                                                struct rb_node * node)
-{
-       struct page * ret;
-       if ((ret = __rb_insert_page_cache(inode, offset, node)))
-               goto out;
-       rb_insert_color(node, &inode->i_rb_page_cache);
- out:
-       return ret;
-}
------------------------------------------------------------------------
-*/
-
-#ifndef        _LINUX_RBTREE_H
-#define        _LINUX_RBTREE_H
-
-#include <stddef.h>
-
-/**
- * container_of - cast a member of a structure out to the containing structure
- * @ptr:       the pointer to the member.
- * @type:      the type of the container struct this is embedded in.
- * @member:    the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({                     \
-       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
-       (type *)( (char *)__mptr - offsetof(type,member) );})
-
-struct rb_node
-{
-       unsigned long  rb_parent_color;
-#define        RB_RED          0
-#define        RB_BLACK        1
-       struct rb_node *rb_right;
-       struct rb_node *rb_left;
-} __attribute__((aligned(sizeof(long))));
-    /* The alignment might seem pointless, but allegedly CRIS needs it */
-
-struct rb_root
-{
-       struct rb_node *rb_node;
-};
-
-
-#define rb_parent(r)   ((struct rb_node *)((r)->rb_parent_color & ~3))
-#define rb_color(r)   ((r)->rb_parent_color & 1)
-#define rb_is_red(r)   (!rb_color(r))
-#define rb_is_black(r) rb_color(r)
-#define rb_set_red(r)  do { (r)->rb_parent_color &= ~1; } while (0)
-#define rb_set_black(r)  do { (r)->rb_parent_color |= 1; } while (0)
-
-static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
-{
-       rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
-}
-static inline void rb_set_color(struct rb_node *rb, int color)
-{
-       rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
-}
-
-#define RB_ROOT        (struct rb_root) { NULL, }
-#define        rb_entry(ptr, type, member) container_of(ptr, type, member)
-
-#define RB_EMPTY_ROOT(root)    ((root)->rb_node == NULL)
-#define RB_EMPTY_NODE(node)    (rb_parent(node) == node)
-#define RB_CLEAR_NODE(node)    (rb_set_parent(node, node))
-
-extern void rb_insert_color(struct rb_node *, struct rb_root *);
-extern void rb_erase(struct rb_node *, struct rb_root *);
-
-/* Find logical next and previous nodes in a tree */
-extern struct rb_node *rb_next(const struct rb_node *);
-extern struct rb_node *rb_prev(const struct rb_node *);
-extern struct rb_node *rb_first(const struct rb_root *);
-extern struct rb_node *rb_last(const struct rb_root *);
-
-/* Fast replacement of a single node without remove/rebalance/add/rebalance */
-extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 
-                           struct rb_root *root);
-
-static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
-                               struct rb_node ** rb_link)
-{
-       node->rb_parent_color = (unsigned long )parent;
-       node->rb_left = node->rb_right = NULL;
-
-       *rb_link = node;
-}
-
-#endif /* _LINUX_RBTREE_H */
index b2f5e854f40adf807eab34876a2b475bff31cf19..a3935343091ab0a8cac2759b0765a916feaeae19 100644 (file)
@@ -65,7 +65,6 @@ int start_command(struct child_process *cmd)
                cmd->err = fderr[0];
        }
 
-#ifndef __MINGW32__
        fflush(NULL);
        cmd->pid = fork();
        if (!cmd->pid) {
@@ -118,71 +117,6 @@ int start_command(struct child_process *cmd)
                }
                exit(127);
        }
-#else
-       int s0 = -1, s1 = -1, s2 = -1;  /* backups of stdin, stdout, stderr */
-       const char **sargv = cmd->argv;
-       char **env = environ;
-
-       if (cmd->no_stdin) {
-               s0 = dup(0);
-               dup_devnull(0);
-       } else if (need_in) {
-               s0 = dup(0);
-               dup2(fdin[0], 0);
-       } else if (cmd->in) {
-               s0 = dup(0);
-               dup2(cmd->in, 0);
-       }
-
-       if (cmd->no_stderr) {
-               s2 = dup(2);
-               dup_devnull(2);
-       } else if (need_err) {
-               s2 = dup(2);
-               dup2(fderr[1], 2);
-       }
-
-       if (cmd->no_stdout) {
-               s1 = dup(1);
-               dup_devnull(1);
-       } else if (cmd->stdout_to_stderr) {
-               s1 = dup(1);
-               dup2(2, 1);
-       } else if (need_out) {
-               s1 = dup(1);
-               dup2(fdout[1], 1);
-       } else if (cmd->out > 1) {
-               s1 = dup(1);
-               dup2(cmd->out, 1);
-       }
-
-       if (cmd->dir)
-               die("chdir in start_command() not implemented");
-       if (cmd->env) {
-               env = copy_environ();
-               for (; *cmd->env; cmd->env++)
-                       env = env_setenv(env, *cmd->env);
-       }
-
-       if (cmd->perf_cmd) {
-               cmd->argv = prepare_perf_cmd(cmd->argv);
-       }
-
-       cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);
-
-       if (cmd->env)
-               free_environ(env);
-       if (cmd->perf_cmd)
-               free(cmd->argv);
-
-       cmd->argv = sargv;
-       if (s0 >= 0)
-               dup2(s0, 0), close(s0);
-       if (s1 >= 0)
-               dup2(s1, 1), close(s1);
-       if (s2 >= 0)
-               dup2(s2, 2), close(s2);
-#endif
 
        if (cmd->pid < 0) {
                int err = errno;
@@ -288,14 +222,6 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const
        return run_command(&cmd);
 }
 
-#ifdef __MINGW32__
-static __stdcall unsigned run_thread(void *data)
-{
-       struct async *async = data;
-       return async->proc(async->fd_for_proc, async->data);
-}
-#endif
-
 int start_async(struct async *async)
 {
        int pipe_out[2];
@@ -304,7 +230,6 @@ int start_async(struct async *async)
                return error("cannot create pipe: %s", strerror(errno));
        async->out = pipe_out[0];
 
-#ifndef __MINGW32__
        /* Flush stdio before fork() to avoid cloning buffers */
        fflush(NULL);
 
@@ -319,33 +244,17 @@ int start_async(struct async *async)
                exit(!!async->proc(pipe_out[1], async->data));
        }
        close(pipe_out[1]);
-#else
-       async->fd_for_proc = pipe_out[1];
-       async->tid = (HANDLE) _beginthreadex(NULL, 0, run_thread, async, 0, NULL);
-       if (!async->tid) {
-               error("cannot create thread: %s", strerror(errno));
-               close_pair(pipe_out);
-               return -1;
-       }
-#endif
+
        return 0;
 }
 
 int finish_async(struct async *async)
 {
-#ifndef __MINGW32__
        int ret = 0;
 
        if (wait_or_whine(async->pid))
                ret = error("waitpid (async) failed");
-#else
-       DWORD ret = 0;
-       if (WaitForSingleObject(async->tid, INFINITE) != WAIT_OBJECT_0)
-               ret = error("waiting for thread failed: %lu", GetLastError());
-       else if (!GetExitCodeThread(async->tid, &ret))
-               ret = error("cannot get thread exit code: %lu", GetLastError());
-       CloseHandle(async->tid);
-#endif
+
        return ret;
 }
 
index 328289f236695fc909375378090f2783965d5582..cc1837deba88af6371785e4721f632529d19face 100644 (file)
@@ -79,12 +79,7 @@ struct async {
        int (*proc)(int fd, void *data);
        void *data;
        int out;        /* caller reads from here and closes it */
-#ifndef __MINGW32__
        pid_t pid;
-#else
-       HANDLE tid;
-       int fd_for_proc;
-#endif
 };
 
 int start_async(struct async *async);
index eaba0930680233a6f682c2d7710a2eb7fa9daac8..5249d5a1b0c203176b08fce72003ea90ce114e74 100644 (file)
@@ -16,7 +16,7 @@ int prefixcmp(const char *str, const char *prefix)
  */
 char strbuf_slopbuf[1];
 
-void strbuf_init(struct strbuf *sb, size_t hint)
+void strbuf_init(struct strbuf *sb, ssize_t hint)
 {
        sb->alloc = sb->len = 0;
        sb->buf = strbuf_slopbuf;
@@ -92,7 +92,8 @@ void strbuf_ltrim(struct strbuf *sb)
 
 void strbuf_tolower(struct strbuf *sb)
 {
-       int i;
+       unsigned int i;
+
        for (i = 0; i < sb->len; i++)
                sb->buf[i] = tolower(sb->buf[i]);
 }
@@ -259,12 +260,12 @@ size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
        res = fread(sb->buf + sb->len, 1, size, f);
        if (res > 0)
                strbuf_setlen(sb, sb->len + res);
-       else if (res < 0 && oldalloc == 0)
+       else if (oldalloc == 0)
                strbuf_release(sb);
        return res;
 }
 
-ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
+ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
 {
        size_t oldlen = sb->len;
        size_t oldalloc = sb->alloc;
@@ -293,7 +294,7 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
 
 #define STRBUF_MAXLINK (2*PATH_MAX)
 
-int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
+int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint)
 {
        size_t oldalloc = sb->alloc;
 
@@ -301,7 +302,7 @@ int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
                hint = 32;
 
        while (hint < STRBUF_MAXLINK) {
-               int len;
+               ssize_t len;
 
                strbuf_grow(sb, hint);
                len = readlink(path, sb->buf, hint);
@@ -343,7 +344,7 @@ int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
        return 0;
 }
 
-int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
+int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint)
 {
        int fd, len;
 
index 9ee908a3ec5d4d5329385bc10cdd676f703c0c1f..d2aa86c014c1b9a3882cfd924affaa116a122e79 100644 (file)
@@ -50,7 +50,7 @@ struct strbuf {
 #define STRBUF_INIT  { 0, 0, strbuf_slopbuf }
 
 /*----- strbuf life cycle -----*/
-extern void strbuf_init(struct strbuf *, size_t);
+extern void strbuf_init(struct strbuf *buf, ssize_t hint);
 extern void strbuf_release(struct strbuf *);
 extern char *strbuf_detach(struct strbuf *, size_t *);
 extern void strbuf_attach(struct strbuf *, void *, size_t, size_t);
@@ -61,7 +61,7 @@ static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) {
 }
 
 /*----- strbuf size related -----*/
-static inline size_t strbuf_avail(const struct strbuf *sb) {
+static inline ssize_t strbuf_avail(const struct strbuf *sb) {
        return sb->alloc ? sb->alloc - sb->len - 1 : 0;
 }
 
@@ -122,9 +122,9 @@ extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
 
 extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
 /* XXX: if read fails, any partial read is undone */
-extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint);
-extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint);
-extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint);
+extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
+extern int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint);
+extern int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint);
 
 extern int strbuf_getline(struct strbuf *, FILE *, int);
 
index 37b03255b425f4ac0e055e4ca8532050b40564e5..bf39dfadfd24dd00fe845f1c321bf0994ad768b0 100644 (file)
@@ -1,8 +1,11 @@
 #ifndef _PERF_STRING_H_
 #define _PERF_STRING_H_
 
-#include "../types.h"
+#include "types.h"
 
 int hex2u64(const char *ptr, u64 *val);
 
+#define _STR(x) #x
+#define STR(x) _STR(x)
+
 #endif
diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c
new file mode 100644 (file)
index 0000000..7ad3817
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
+ *
+ * Licensed under the GPLv2.
+ */
+
+#include "strlist.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static struct str_node *str_node__new(const char *s, bool dupstr)
+{
+       struct str_node *self = malloc(sizeof(*self));
+
+       if (self != NULL) {
+               if (dupstr) {
+                       s = strdup(s);
+                       if (s == NULL)
+                               goto out_delete;
+               }
+               self->s = s;
+       }
+
+       return self;
+
+out_delete:
+       free(self);
+       return NULL;
+}
+
+static void str_node__delete(struct str_node *self, bool dupstr)
+{
+       if (dupstr)
+               free((void *)self->s);
+       free(self);
+}
+
+int strlist__add(struct strlist *self, const char *new_entry)
+{
+       struct rb_node **p = &self->entries.rb_node;
+       struct rb_node *parent = NULL;
+       struct str_node *sn;
+
+       while (*p != NULL) {
+               int rc;
+
+               parent = *p;
+               sn = rb_entry(parent, struct str_node, rb_node);
+               rc = strcmp(sn->s, new_entry);
+
+               if (rc > 0)
+                       p = &(*p)->rb_left;
+               else if (rc < 0)
+                       p = &(*p)->rb_right;
+               else
+                       return -EEXIST;
+       }
+
+       sn = str_node__new(new_entry, self->dupstr);
+       if (sn == NULL)
+               return -ENOMEM;
+
+       rb_link_node(&sn->rb_node, parent, p);
+       rb_insert_color(&sn->rb_node, &self->entries);
+       ++self->nr_entries;
+
+       return 0;
+}
+
+int strlist__load(struct strlist *self, const char *filename)
+{
+       char entry[1024];
+       int err;
+       FILE *fp = fopen(filename, "r");
+
+       if (fp == NULL)
+               return errno;
+
+       while (fgets(entry, sizeof(entry), fp) != NULL) {
+               const size_t len = strlen(entry);
+
+               if (len == 0)
+                       continue;
+               entry[len - 1] = '\0';
+
+               err = strlist__add(self, entry);
+               if (err != 0)
+                       goto out;
+       }
+
+       err = 0;
+out:
+       fclose(fp);
+       return err;
+}
+
+void strlist__remove(struct strlist *self, struct str_node *sn)
+{
+       rb_erase(&sn->rb_node, &self->entries);
+       str_node__delete(sn, self->dupstr);
+}
+
+bool strlist__has_entry(struct strlist *self, const char *entry)
+{
+       struct rb_node **p = &self->entries.rb_node;
+       struct rb_node *parent = NULL;
+
+       while (*p != NULL) {
+               struct str_node *sn;
+               int rc;
+
+               parent = *p;
+               sn = rb_entry(parent, struct str_node, rb_node);
+               rc = strcmp(sn->s, entry);
+
+               if (rc > 0)
+                       p = &(*p)->rb_left;
+               else if (rc < 0)
+                       p = &(*p)->rb_right;
+               else
+                       return true;
+       }
+
+       return false;
+}
+
+static int strlist__parse_list_entry(struct strlist *self, const char *s)
+{
+       if (strncmp(s, "file://", 7) == 0)
+               return strlist__load(self, s + 7);
+
+       return strlist__add(self, s);
+}
+
+int strlist__parse_list(struct strlist *self, const char *s)
+{
+       char *sep;
+       int err;
+
+       while ((sep = strchr(s, ',')) != NULL) {
+               *sep = '\0';
+               err = strlist__parse_list_entry(self, s);
+               *sep = ',';
+               if (err != 0)
+                       return err;
+               s = sep + 1;
+       }
+
+       return *s ? strlist__parse_list_entry(self, s) : 0;
+}
+
+struct strlist *strlist__new(bool dupstr, const char *slist)
+{
+       struct strlist *self = malloc(sizeof(*self));
+
+       if (self != NULL) {
+               self->entries    = RB_ROOT;
+               self->dupstr     = dupstr;
+               self->nr_entries = 0;
+               if (slist && strlist__parse_list(self, slist) != 0)
+                       goto out_error;
+       }
+
+       return self;
+out_error:
+       free(self);
+       return NULL;
+}
+
+void strlist__delete(struct strlist *self)
+{
+       if (self != NULL) {
+               struct str_node *pos;
+               struct rb_node *next = rb_first(&self->entries);
+
+               while (next) {
+                       pos = rb_entry(next, struct str_node, rb_node);
+                       next = rb_next(&pos->rb_node);
+                       strlist__remove(self, pos);
+               }
+               self->entries = RB_ROOT;
+               free(self);
+       }
+}
+
+struct str_node *strlist__entry(const struct strlist *self, unsigned int idx)
+{
+       struct rb_node *nd;
+
+       for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
+               struct str_node *pos = rb_entry(nd, struct str_node, rb_node);
+
+               if (!idx--)
+                       return pos;
+       }
+
+       return NULL;
+}
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h
new file mode 100644 (file)
index 0000000..921818e
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef STRLIST_H_
+#define STRLIST_H_
+
+#include <linux/rbtree.h>
+#include <stdbool.h>
+
+struct str_node {
+       struct rb_node rb_node;
+       const char     *s;
+};
+
+struct strlist {
+       struct rb_root entries;
+       unsigned int   nr_entries;
+       bool           dupstr;
+};
+
+struct strlist *strlist__new(bool dupstr, const char *slist);
+void strlist__delete(struct strlist *self);
+
+void strlist__remove(struct strlist *self, struct str_node *sn);
+int strlist__load(struct strlist *self, const char *filename);
+int strlist__add(struct strlist *self, const char *str);
+
+struct str_node *strlist__entry(const struct strlist *self, unsigned int idx);
+bool strlist__has_entry(struct strlist *self, const char *entry);
+
+static inline bool strlist__empty(const struct strlist *self)
+{
+       return self->nr_entries == 0;
+}
+
+static inline unsigned int strlist__nr_entries(const struct strlist *self)
+{
+       return self->nr_entries;
+}
+
+int strlist__parse_list(struct strlist *self, const char *s);
+#endif /* STRLIST_H_ */
index 86e14375e74e3a4990f536bc8baebb913b86e75b..5c0f42e6b33b90ee8960ccb91845ae74da6b725e 100644 (file)
@@ -9,6 +9,16 @@
 
 const char *sym_hist_filter;
 
+enum dso_origin {
+       DSO__ORIG_KERNEL = 0,
+       DSO__ORIG_JAVA_JIT,
+       DSO__ORIG_FEDORA,
+       DSO__ORIG_UBUNTU,
+       DSO__ORIG_BUILDID,
+       DSO__ORIG_DSO,
+       DSO__ORIG_NOT_FOUND,
+};
+
 static struct symbol *symbol__new(u64 start, u64 len,
                                  const char *name, unsigned int priv_size,
                                  u64 obj_start, int verbose)
@@ -35,7 +45,7 @@ static struct symbol *symbol__new(u64 start, u64 len,
                self = ((void *)self) + priv_size;
        }
        self->start = start;
-       self->end   = start + len - 1;
+       self->end   = len ? start + len - 1 : start;
        memcpy(self->name, name, namelen);
 
        return self;
@@ -48,8 +58,12 @@ static void symbol__delete(struct symbol *self, unsigned int priv_size)
 
 static size_t symbol__fprintf(struct symbol *self, FILE *fp)
 {
-       return fprintf(fp, " %llx-%llx %s\n",
+       if (!self->module)
+               return fprintf(fp, " %llx-%llx %s\n",
                       self->start, self->end, self->name);
+       else
+               return fprintf(fp, " %llx-%llx %s \t[%s]\n",
+                      self->start, self->end, self->name, self->module->name);
 }
 
 struct dso *dso__new(const char *name, unsigned int sym_priv_size)
@@ -61,6 +75,8 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
                self->syms = RB_ROOT;
                self->sym_priv_size = sym_priv_size;
                self->find_symbol = dso__find_symbol;
+               self->slen_calculated = 0;
+               self->origin = DSO__ORIG_NOT_FOUND;
        }
 
        return self;
@@ -146,6 +162,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
        char *line = NULL;
        size_t n;
        FILE *file = fopen("/proc/kallsyms", "r");
+       int count = 0;
 
        if (file == NULL)
                goto out_failure;
@@ -188,8 +205,10 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
 
                if (filter && filter(self, sym))
                        symbol__delete(sym, self->sym_priv_size);
-               else
+               else {
                        dso__insert_symbol(self, sym);
+                       count++;
+               }
        }
 
        /*
@@ -212,7 +231,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
        free(line);
        fclose(file);
 
-       return 0;
+       return count;
 
 out_delete_line:
        free(line);
@@ -307,6 +326,26 @@ static inline int elf_sym__is_function(const GElf_Sym *sym)
               sym->st_size != 0;
 }
 
+static inline int elf_sym__is_label(const GElf_Sym *sym)
+{
+       return elf_sym__type(sym) == STT_NOTYPE &&
+               sym->st_name != 0 &&
+               sym->st_shndx != SHN_UNDEF &&
+               sym->st_shndx != SHN_ABS;
+}
+
+static inline const char *elf_sec__name(const GElf_Shdr *shdr,
+                                       const Elf_Data *secstrs)
+{
+       return secstrs->d_buf + shdr->sh_name;
+}
+
+static inline int elf_sec__is_text(const GElf_Shdr *shdr,
+                                       const Elf_Data *secstrs)
+{
+       return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
+}
+
 static inline const char *elf_sym__name(const GElf_Sym *sym,
                                        const Elf_Data *symstrs)
 {
@@ -346,36 +385,61 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
             idx < nr_entries; \
             ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
 
-static int dso__synthesize_plt_symbols(struct  dso *self, Elf *elf,
-                                      GElf_Ehdr *ehdr, Elf_Scn *scn_dynsym,
-                                      GElf_Shdr *shdr_dynsym,
-                                      size_t dynsym_idx, int verbose)
+/*
+ * We need to check if we have a .dynsym, so that we can handle the
+ * .plt, synthesizing its symbols, that aren't on the symtabs (be it
+ * .dynsym or .symtab).
+ * And always look at the original dso, not at debuginfo packages, that
+ * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
+ */
+static int dso__synthesize_plt_symbols(struct  dso *self, int verbose)
 {
        uint32_t nr_rel_entries, idx;
        GElf_Sym sym;
        u64 plt_offset;
        GElf_Shdr shdr_plt;
        struct symbol *f;
-       GElf_Shdr shdr_rel_plt;
+       GElf_Shdr shdr_rel_plt, shdr_dynsym;
        Elf_Data *reldata, *syms, *symstrs;
-       Elf_Scn *scn_plt_rel, *scn_symstrs;
+       Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
+       size_t dynsym_idx;
+       GElf_Ehdr ehdr;
        char sympltname[1024];
-       int nr = 0, symidx;
+       Elf *elf;
+       int nr = 0, symidx, fd, err = 0;
 
-       scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt,
+       fd = open(self->name, O_RDONLY);
+       if (fd < 0)
+               goto out;
+
+       elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
+       if (elf == NULL)
+               goto out_close;
+
+       if (gelf_getehdr(elf, &ehdr) == NULL)
+               goto out_elf_end;
+
+       scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
+                                        ".dynsym", &dynsym_idx);
+       if (scn_dynsym == NULL)
+               goto out_elf_end;
+
+       scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
                                          ".rela.plt", NULL);
        if (scn_plt_rel == NULL) {
-               scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt,
+               scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
                                                  ".rel.plt", NULL);
                if (scn_plt_rel == NULL)
-                       return 0;
+                       goto out_elf_end;
        }
 
+       err = -1;
+
        if (shdr_rel_plt.sh_link != dynsym_idx)
-               return 0;
+               goto out_elf_end;
 
-       if (elf_section_by_name(elf, ehdr, &shdr_plt, ".plt", NULL) == NULL)
-               return 0;
+       if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
+               goto out_elf_end;
 
        /*
         * Fetch the relocation section to find the indexes to the GOT
@@ -383,19 +447,19 @@ static int dso__synthesize_plt_symbols(struct  dso *self, Elf *elf,
         */
        reldata = elf_getdata(scn_plt_rel, NULL);
        if (reldata == NULL)
-               return -1;
+               goto out_elf_end;
 
        syms = elf_getdata(scn_dynsym, NULL);
        if (syms == NULL)
-               return -1;
+               goto out_elf_end;
 
-       scn_symstrs = elf_getscn(elf, shdr_dynsym->sh_link);
+       scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
        if (scn_symstrs == NULL)
-               return -1;
+               goto out_elf_end;
 
        symstrs = elf_getdata(scn_symstrs, NULL);
        if (symstrs == NULL)
-               return -1;
+               goto out_elf_end;
 
        nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
        plt_offset = shdr_plt.sh_offset;
@@ -414,7 +478,7 @@ static int dso__synthesize_plt_symbols(struct  dso *self, Elf *elf,
                        f = symbol__new(plt_offset, shdr_plt.sh_entsize,
                                        sympltname, self->sym_priv_size, 0, verbose);
                        if (!f)
-                               return -1;
+                               goto out_elf_end;
 
                        dso__insert_symbol(self, f);
                        ++nr;
@@ -432,25 +496,31 @@ static int dso__synthesize_plt_symbols(struct  dso *self, Elf *elf,
                        f = symbol__new(plt_offset, shdr_plt.sh_entsize,
                                        sympltname, self->sym_priv_size, 0, verbose);
                        if (!f)
-                               return -1;
+                               goto out_elf_end;
 
                        dso__insert_symbol(self, f);
                        ++nr;
                }
-       } else {
-               /*
-                * TODO: There are still one more shdr_rel_plt.sh_type
-                * I have to investigate, but probably should be ignored.
-                */
        }
 
-       return nr;
+       err = 0;
+out_elf_end:
+       elf_end(elf);
+out_close:
+       close(fd);
+
+       if (err == 0)
+               return nr;
+out:
+       fprintf(stderr, "%s: problems reading %s PLT info.\n",
+               __func__, self->name);
+       return 0;
 }
 
 static int dso__load_sym(struct dso *self, int fd, const char *name,
-                        symbol_filter_t filter, int verbose)
+                        symbol_filter_t filter, int verbose, struct module *mod)
 {
-       Elf_Data *symstrs;
+       Elf_Data *symstrs, *secstrs;
        uint32_t nr_syms;
        int err = -1;
        uint32_t index;
@@ -458,10 +528,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
        GElf_Shdr shdr;
        Elf_Data *syms;
        GElf_Sym sym;
-       Elf_Scn *sec, *sec_dynsym;
+       Elf_Scn *sec, *sec_strndx;
        Elf *elf;
-       size_t dynsym_idx;
-       int nr = 0;
+       int nr = 0, kernel = !strcmp("[kernel]", self->name);
 
        elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
        if (elf == NULL) {
@@ -477,32 +546,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
                goto out_elf_end;
        }
 
-       /*
-        * We need to check if we have a .dynsym, so that we can handle the
-        * .plt, synthesizing its symbols, that aren't on the symtabs (be it
-        * .dynsym or .symtab)
-        */
-       sec_dynsym = elf_section_by_name(elf, &ehdr, &shdr,
-                                        ".dynsym", &dynsym_idx);
-       if (sec_dynsym != NULL) {
-               nr = dso__synthesize_plt_symbols(self, elf, &ehdr,
-                                                sec_dynsym, &shdr,
-                                                dynsym_idx, verbose);
-               if (nr < 0)
-                       goto out_elf_end;
-       }
-
-       /*
-        * But if we have a full .symtab (that is a superset of .dynsym) we
-        * should add the symbols not in the .dynsyn
-        */
        sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
        if (sec == NULL) {
-               if (sec_dynsym == NULL)
+               sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
+               if (sec == NULL)
                        goto out_elf_end;
-
-               sec = sec_dynsym;
-               gelf_getshdr(sec, &shdr);
        }
 
        syms = elf_getdata(sec, NULL);
@@ -517,15 +565,34 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
        if (symstrs == NULL)
                goto out_elf_end;
 
+       sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
+       if (sec_strndx == NULL)
+               goto out_elf_end;
+
+       secstrs = elf_getdata(sec_strndx, NULL);
+       if (secstrs == NULL)
+               goto out_elf_end;
+
        nr_syms = shdr.sh_size / shdr.sh_entsize;
 
        memset(&sym, 0, sizeof(sym));
+       if (!kernel) {
+               self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
+                               elf_section_by_name(elf, &ehdr, &shdr,
+                                                    ".gnu.prelink_undo",
+                                                    NULL) != NULL);
+       } else self->adjust_symbols = 0;
 
        elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
                struct symbol *f;
+               const char *name;
+               char *demangled;
                u64 obj_start;
+               struct section *section = NULL;
+               int is_label = elf_sym__is_label(&sym);
+               const char *section_name;
 
-               if (!elf_sym__is_function(&sym))
+               if (!is_label && !elf_sym__is_function(&sym))
                        continue;
 
                sec = elf_getscn(elf, sym.st_shndx);
@@ -533,19 +600,51 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
                        goto out_elf_end;
 
                gelf_getshdr(sec, &shdr);
+
+               if (is_label && !elf_sec__is_text(&shdr, secstrs))
+                       continue;
+
+               section_name = elf_sec__name(&shdr, secstrs);
                obj_start = sym.st_value;
 
-               sym.st_value -= shdr.sh_addr - shdr.sh_offset;
+               if (self->adjust_symbols) {
+                       if (verbose >= 2)
+                               printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
+                                       (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
+
+                       sym.st_value -= shdr.sh_addr - shdr.sh_offset;
+               }
+
+               if (mod) {
+                       section = mod->sections->find_section(mod->sections, section_name);
+                       if (section)
+                               sym.st_value += section->vma;
+                       else {
+                               fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
+                                       mod->name, section_name);
+                               goto out_elf_end;
+                       }
+               }
+               /*
+                * We need to figure out if the object was created from C++ sources
+                * DWARF DW_compile_unit has this, but we don't always have access
+                * to it...
+                */
+               name = elf_sym__name(&sym, symstrs);
+               demangled = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI);
+               if (demangled != NULL)
+                       name = demangled;
 
-               f = symbol__new(sym.st_value, sym.st_size,
-                               elf_sym__name(&sym, symstrs),
+               f = symbol__new(sym.st_value, sym.st_size, name,
                                self->sym_priv_size, obj_start, verbose);
+               free(demangled);
                if (!f)
                        goto out_elf_end;
 
                if (filter && filter(self, f))
                        symbol__delete(f, self->sym_priv_size);
                else {
+                       f->module = mod;
                        dso__insert_symbol(self, f);
                        nr++;
                }
@@ -558,42 +657,135 @@ out_close:
        return err;
 }
 
+#define BUILD_ID_SIZE 128
+
+static char *dso__read_build_id(struct dso *self, int verbose)
+{
+       int i;
+       GElf_Ehdr ehdr;
+       GElf_Shdr shdr;
+       Elf_Data *build_id_data;
+       Elf_Scn *sec;
+       char *build_id = NULL, *bid;
+       unsigned char *raw;
+       Elf *elf;
+       int fd = open(self->name, O_RDONLY);
+
+       if (fd < 0)
+               goto out;
+
+       elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
+       if (elf == NULL) {
+               if (verbose)
+                       fprintf(stderr, "%s: cannot read %s ELF file.\n",
+                               __func__, self->name);
+               goto out_close;
+       }
+
+       if (gelf_getehdr(elf, &ehdr) == NULL) {
+               if (verbose)
+                       fprintf(stderr, "%s: cannot get elf header.\n", __func__);
+               goto out_elf_end;
+       }
+
+       sec = elf_section_by_name(elf, &ehdr, &shdr, ".note.gnu.build-id", NULL);
+       if (sec == NULL)
+               goto out_elf_end;
+
+       build_id_data = elf_getdata(sec, NULL);
+       if (build_id_data == NULL)
+               goto out_elf_end;
+       build_id = malloc(BUILD_ID_SIZE);
+       if (build_id == NULL)
+               goto out_elf_end;
+       raw = build_id_data->d_buf + 16;
+       bid = build_id;
+
+       for (i = 0; i < 20; ++i) {
+               sprintf(bid, "%02x", *raw);
+               ++raw;
+               bid += 2;
+       }
+       if (verbose >= 2)
+               printf("%s(%s): %s\n", __func__, self->name, build_id);
+out_elf_end:
+       elf_end(elf);
+out_close:
+       close(fd);
+out:
+       return build_id;
+}
+
+char dso__symtab_origin(const struct dso *self)
+{
+       static const char origin[] = {
+               [DSO__ORIG_KERNEL] =   'k',
+               [DSO__ORIG_JAVA_JIT] = 'j',
+               [DSO__ORIG_FEDORA] =   'f',
+               [DSO__ORIG_UBUNTU] =   'u',
+               [DSO__ORIG_BUILDID] =  'b',
+               [DSO__ORIG_DSO] =      'd',
+       };
+
+       if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
+               return '!';
+       return origin[self->origin];
+}
+
 int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
 {
-       int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug");
-       char *name = malloc(size);
-       int variant = 0;
+       int size = PATH_MAX;
+       char *name = malloc(size), *build_id = NULL;
        int ret = -1;
        int fd;
 
        if (!name)
                return -1;
 
-       if (strncmp(self->name, "/tmp/perf-", 10) == 0)
-               return dso__load_perf_map(self, filter, verbose);
+       self->adjust_symbols = 0;
+
+       if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
+               ret = dso__load_perf_map(self, filter, verbose);
+               self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
+                                        DSO__ORIG_NOT_FOUND;
+               return ret;
+       }
+
+       self->origin = DSO__ORIG_FEDORA - 1;
 
 more:
        do {
-               switch (variant) {
-               case 0: /* Fedora */
+               self->origin++;
+               switch (self->origin) {
+               case DSO__ORIG_FEDORA:
                        snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
                        break;
-               case 1: /* Ubuntu */
+               case DSO__ORIG_UBUNTU:
                        snprintf(name, size, "/usr/lib/debug%s", self->name);
                        break;
-               case 2: /* Sane people */
+               case DSO__ORIG_BUILDID:
+                       build_id = dso__read_build_id(self, verbose);
+                       if (build_id != NULL) {
+                               snprintf(name, size,
+                                        "/usr/lib/debug/.build-id/%.2s/%s.debug",
+                                       build_id, build_id + 2);
+                               free(build_id);
+                               break;
+                       }
+                       self->origin++;
+                       /* Fall thru */
+               case DSO__ORIG_DSO:
                        snprintf(name, size, "%s", self->name);
                        break;
 
                default:
                        goto out;
                }
-               variant++;
 
                fd = open(name, O_RDONLY);
        } while (fd < 0);
 
-       ret = dso__load_sym(self, fd, name, filter, verbose);
+       ret = dso__load_sym(self, fd, name, filter, verbose, NULL);
        close(fd);
 
        /*
@@ -602,11 +794,98 @@ more:
        if (!ret)
                goto more;
 
+       if (ret > 0) {
+               int nr_plt = dso__synthesize_plt_symbols(self, verbose);
+               if (nr_plt > 0)
+                       ret += nr_plt;
+       }
 out:
        free(name);
+       if (ret < 0 && strstr(self->name, " (deleted)") != NULL)
+               return 0;
        return ret;
 }
 
+static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name,
+                            symbol_filter_t filter, int verbose)
+{
+       struct module *mod = mod_dso__find_module(mods, name);
+       int err = 0, fd;
+
+       if (mod == NULL || !mod->active)
+               return err;
+
+       fd = open(mod->path, O_RDONLY);
+
+       if (fd < 0)
+               return err;
+
+       err = dso__load_sym(self, fd, name, filter, verbose, mod);
+       close(fd);
+
+       return err;
+}
+
+int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose)
+{
+       struct mod_dso *mods = mod_dso__new_dso("modules");
+       struct module *pos;
+       struct rb_node *next;
+       int err;
+
+       err = mod_dso__load_modules(mods);
+
+       if (err <= 0)
+               return err;
+
+       /*
+        * Iterate over modules, and load active symbols.
+        */
+       next = rb_first(&mods->mods);
+       while (next) {
+               pos = rb_entry(next, struct module, rb_node);
+               err = dso__load_module(self, mods, pos->name, filter, verbose);
+
+               if (err < 0)
+                       break;
+
+               next = rb_next(&pos->rb_node);
+       }
+
+       if (err < 0) {
+               mod_dso__delete_modules(mods);
+               mod_dso__delete_self(mods);
+       }
+
+       return err;
+}
+
+static inline void dso__fill_symbol_holes(struct dso *self)
+{
+       struct symbol *prev = NULL;
+       struct rb_node *nd;
+
+       for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) {
+               struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
+
+               if (prev) {
+                       u64 hole = 0;
+                       int alias = pos->start == prev->start;
+
+                       if (!alias)
+                               hole = prev->start - pos->end - 1;
+
+                       if (hole || alias) {
+                               if (alias)
+                                       pos->end = prev->end;
+                               else if (hole)
+                                       pos->end = prev->start - 1;
+                       }
+               }
+               prev = pos;
+       }
+}
+
 static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
                             symbol_filter_t filter, int verbose)
 {
@@ -615,23 +894,33 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
        if (fd < 0)
                return -1;
 
-       err = dso__load_sym(self, fd, vmlinux, filter, verbose);
+       err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL);
+
+       if (err > 0)
+               dso__fill_symbol_holes(self);
+
        close(fd);
 
        return err;
 }
 
 int dso__load_kernel(struct dso *self, const char *vmlinux,
-                    symbol_filter_t filter, int verbose)
+                    symbol_filter_t filter, int verbose, int modules)
 {
        int err = -1;
 
-       if (vmlinux)
+       if (vmlinux) {
                err = dso__load_vmlinux(self, vmlinux, filter, verbose);
+               if (err > 0 && modules)
+                       err = dso__load_modules(self, filter, verbose);
+       }
 
-       if (err)
+       if (err <= 0)
                err = dso__load_kallsyms(self, filter, verbose);
 
+       if (err > 0)
+               self->origin = DSO__ORIG_KERNEL;
+
        return err;
 }
 
index ea332e56e4582d565a7975208328b9d9b60b8d22..b53bf0125c1bcaff4d88d2ddc9dd7c766f7dfb57 100644 (file)
@@ -2,9 +2,34 @@
 #define _PERF_SYMBOL_ 1
 
 #include <linux/types.h>
-#include "../types.h"
-#include "list.h"
-#include "rbtree.h"
+#include "types.h"
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include "module.h"
+
+#ifdef HAVE_CPLUS_DEMANGLE
+extern char *cplus_demangle(const char *, int);
+
+static inline char *bfd_demangle(void __used *v, const char *c, int i)
+{
+       return cplus_demangle(c, i);
+}
+#else
+#ifdef NO_DEMANGLE
+static inline char *bfd_demangle(void __used *v, const char __used *c,
+                                int __used i)
+{
+       return NULL;
+}
+#else
+#include <bfd.h>
+#endif
+#endif
+
+#ifndef DMGL_PARAMS
+#define DMGL_PARAMS      (1 << 0)       /* Include function args */
+#define DMGL_ANSI        (1 << 1)       /* Include const, volatile, etc */
+#endif
 
 struct symbol {
        struct rb_node  rb_node;
@@ -13,6 +38,7 @@ struct symbol {
        u64             obj_start;
        u64             hist_sum;
        u64             *hist;
+       struct module   *module;
        void            *priv;
        char            name[0];
 };
@@ -20,8 +46,11 @@ struct symbol {
 struct dso {
        struct list_head node;
        struct rb_root   syms;
-       unsigned int     sym_priv_size;
        struct symbol    *(*find_symbol)(struct dso *, u64 ip);
+       unsigned int     sym_priv_size;
+       unsigned char    adjust_symbols;
+       unsigned char    slen_calculated;
+       unsigned char    origin;
        char             name[0];
 };
 
@@ -40,10 +69,12 @@ static inline void *dso__sym_priv(struct dso *self, struct symbol *sym)
 struct symbol *dso__find_symbol(struct dso *self, u64 ip);
 
 int dso__load_kernel(struct dso *self, const char *vmlinux,
-                    symbol_filter_t filter, int verbose);
+                    symbol_filter_t filter, int verbose, int modules);
+int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose);
 int dso__load(struct dso *self, symbol_filter_t filter, int verbose);
 
 size_t dso__fprintf(struct dso *self, FILE *fp);
+char dso__symtab_origin(const struct dso *self);
 
 void symbol__init(void);
 #endif /* _PERF_SYMBOL_ */
similarity index 100%
rename from tools/perf/types.h
rename to tools/perf/util/types.h
index b8cfed776d81896ed882c6969d932581d07a385c..68fe157d72fb9ddae6991fdfa9b1c69ac7f51fa4 100644 (file)
@@ -50,6 +50,7 @@
 #include <unistd.h>
 #include <stdio.h>
 #include <sys/stat.h>
+#include <sys/statfs.h>
 #include <fcntl.h>
 #include <stddef.h>
 #include <stdlib.h>
@@ -67,7 +68,6 @@
 #include <assert.h>
 #include <regex.h>
 #include <utime.h>
-#ifndef __MINGW32__
 #include <sys/wait.h>
 #include <sys/poll.h>
 #include <sys/socket.h>
 #include <netdb.h>
 #include <pwd.h>
 #include <inttypes.h>
-#if defined(__CYGWIN__)
-#undef _XOPEN_SOURCE
-#include <grp.h>
-#define _XOPEN_SOURCE 600
-#include "compat/cygwin.h"
-#else
-#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
-#include <grp.h>
-#define _ALL_SOURCE 1
-#endif
-#else  /* __MINGW32__ */
-/* pull in Windows compatibility stuff */
-#include "compat/mingw.h"
-#endif /* __MINGW32__ */
+#include "../../../include/linux/magic.h"
 
 #ifndef NO_ICONV
 #include <iconv.h>
index 6350d65f6d9e5f8a2faca0dd40ff790bd4cda8b9..4574ac28396f6779fcecacfafe570dc0a5e01dc6 100644 (file)
@@ -7,7 +7,7 @@
  * There's no pack memory to release - but stay close to the Git
  * version so wrap this away:
  */
-static inline void release_pack_memory(size_t size, int flag)
+static inline void release_pack_memory(size_t size __used, int flag __used)
 {
 }
 
@@ -59,7 +59,8 @@ void *xmemdupz(const void *data, size_t len)
 char *xstrndup(const char *str, size_t len)
 {
        char *p = memchr(str, '\0', len);
-       return xmemdupz(str, p ? p - str : len);
+
+       return xmemdupz(str, p ? (size_t)(p - str) : len);
 }
 
 void *xrealloc(void *ptr, size_t size)
index 1eddae94bab331bee8eb01b5e71fd6df8e0d7604..1150c6d5c7b893fdaebb73e8eb8b53ed0b41be5d 100644 (file)
@@ -95,8 +95,6 @@ static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
                if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG)
                        pent->fields.remote_irr = 1;
        }
-       if (!pent->fields.trig_mode)
-               ioapic->irr &= ~(1 << idx);
 
        return injected;
 }
@@ -136,7 +134,8 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
                mask_after = ioapic->redirtbl[index].fields.mask;
                if (mask_before != mask_after)
                        kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after);
-               if (ioapic->irr & (1 << index))
+               if (ioapic->redirtbl[index].fields.trig_mode == IOAPIC_LEVEL_TRIG
+                   && ioapic->irr & (1 << index))
                        ioapic_service(ioapic, index);
                break;
        }
@@ -184,9 +183,10 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
                if (!level)
                        ioapic->irr &= ~mask;
                else {
+                       int edge = (entry.fields.trig_mode == IOAPIC_EDGE_TRIG);
                        ioapic->irr |= mask;
-                       if ((!entry.fields.trig_mode && old_irr != ioapic->irr)
-                           || !entry.fields.remote_irr)
+                       if ((edge && old_irr != ioapic->irr) ||
+                           (!edge && !entry.fields.remote_irr))
                                ret = ioapic_service(ioapic, irq);
                }
        }
index a8bd466d00ccf1af71ab09e229197c2366fcdef5..ddc17f0e2f353f86c9ff831354a26bb9f76a76f7 100644 (file)
@@ -160,7 +160,8 @@ void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
        unsigned gsi = pin;
 
        list_for_each_entry(e, &kvm->irq_routing, link)
-               if (e->irqchip.irqchip == irqchip &&
+               if (e->type == KVM_IRQ_ROUTING_IRQCHIP &&
+                   e->irqchip.irqchip == irqchip &&
                    e->irqchip.pin == pin) {
                        gsi = e->gsi;
                        break;
@@ -259,6 +260,7 @@ static int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e,
        int delta;
 
        e->gsi = ue->gsi;
+       e->type = ue->type;
        switch (ue->type) {
        case KVM_IRQ_ROUTING_IRQCHIP:
                delta = 0;
index 764554350ed86f41b26f45eb840ad02138a55081..2884baf1d5f919a8e72183be0d390e632da4a385 100644 (file)
@@ -746,6 +746,7 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req)
                cpumask_clear(cpus);
 
        me = get_cpu();
+       spin_lock(&kvm->requests_lock);
        for (i = 0; i < KVM_MAX_VCPUS; ++i) {
                vcpu = kvm->vcpus[i];
                if (!vcpu)
@@ -762,6 +763,7 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req)
                smp_call_function_many(cpus, ack_flush, NULL, 1);
        else
                called = false;
+       spin_unlock(&kvm->requests_lock);
        put_cpu();
        free_cpumask_var(cpus);
        return called;
@@ -982,6 +984,7 @@ static struct kvm *kvm_create_vm(void)
        kvm->mm = current->mm;
        atomic_inc(&kvm->mm->mm_count);
        spin_lock_init(&kvm->mmu_lock);
+       spin_lock_init(&kvm->requests_lock);
        kvm_io_bus_init(&kvm->pio_bus);
        mutex_init(&kvm->lock);
        kvm_io_bus_init(&kvm->mmio_bus);
@@ -1194,6 +1197,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
                if (!new.dirty_bitmap)
                        goto out_free;
                memset(new.dirty_bitmap, 0, dirty_bytes);
+               if (old.npages)
+                       kvm_arch_flush_shadow(kvm);
        }
 #endif /* not defined CONFIG_S390 */